diff options
author | Luca Boccassi <luca.boccassi@gmail.com> | 2018-08-14 18:52:30 +0100 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2018-08-14 18:53:17 +0100 |
commit | b63264c8342e6a1b6971c79550d2af2024b6a4de (patch) | |
tree | 83114aac64286fe616506c0b3dfaec2ab86ef835 /examples | |
parent | ca33590b6af032bff57d9cc70455660466a654b2 (diff) |
New upstream version 18.08upstream/18.08
Change-Id: I32fdf5e5016556d9c0a6d88ddaf1fc468961790a
Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
Diffstat (limited to 'examples')
243 files changed, 15911 insertions, 30826 deletions
diff --git a/examples/Makefile b/examples/Makefile index 17ecf7f6..481720cb 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,32 +1,5 @@ -# BSD LICENSE -# -# Copyright(c) 2016 6WIND S.A. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# * Neither the name of 6WIND S.A. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2016 6WIND S.A. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") @@ -93,6 +66,9 @@ DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += tep_termination endif DIRS-$(CONFIG_RTE_LIBRTE_TIMER) += timer DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost vhost_scsi +ifeq ($(CONFIG_RTE_LIBRTE_CRYPTODEV),y) +DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost_crypto +endif DIRS-y += vmdq DIRS-y += vmdq_dcb ifeq ($(CONFIG_RTE_LIBRTE_POWER), y) diff --git a/examples/bbdev_app/main.c b/examples/bbdev_app/main.c index 3c452569..045a190b 100644 --- a/examples/bbdev_app/main.c +++ b/examples/bbdev_app/main.c @@ -64,11 +64,7 @@ static const struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .header_split = 0, /**< Header Split disabled */ - .hw_ip_checksum = 0, /**< IP checksum offload disabled */ - .hw_vlan_filter = 0, /**< VLAN filtering disabled */ - .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ - .hw_strip_crc = 0, /**< CRC stripped by hardware */ + .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, @@ -1017,7 +1013,7 @@ int main(int argc, char **argv) { int ret; - unsigned int nb_bbdevs, nb_ports, flags, lcore_id; + unsigned int nb_bbdevs, flags, lcore_id; void *sigret; struct app_config_params app_params = def_app_config; struct rte_mempool *ethdev_mbuf_mempool, *bbdev_mbuf_mempool; @@ -1079,12 +1075,10 @@ main(int argc, char **argv) nb_bbdevs, app_params.bbdev_id); printf("Number of bbdevs detected: %d\n", nb_bbdevs); - /* Get the number of available ethdev devices */ - nb_ports = rte_eth_dev_count(); - if (nb_ports <= app_params.port_id) + if (!rte_eth_dev_is_valid_port(app_params.port_id)) rte_exit(EXIT_FAILURE, - "%u ports detected, cannot use port with ID %u!\n", - nb_ports, app_params.port_id); + "cannot use port with ID %u!\n", + app_params.port_id); /* create the mbuf mempool for ethdev pkts */ ethdev_mbuf_mempool = rte_pktmbuf_pool_create("ethdev_mbuf_pool", diff --git a/examples/bond/Makefile b/examples/bond/Makefile index 44d10d4f..d6e500aa 100644 --- a/examples/bond/Makefile +++ b/examples/bond/Makefile @@ -25,6 +25,8 @@ CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) +CFLAGS += -DALLOW_EXPERIMENTAL_API + build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) @@ -59,6 +61,7 @@ CFLAGS_main.o += -Wno-return-type endif CFLAGS += -O3 +CFLAGS += -DALLOW_EXPERIMENTAL_API ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) LDLIBS += -lrte_pmd_bond diff --git a/examples/bond/main.c b/examples/bond/main.c index 455f108e..23d0981a 100644 --- a/examples/bond/main.c +++ b/examples/bond/main.c @@ -122,7 +122,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .rx_adv_conf = { @@ -147,13 +146,25 @@ slave_port_init(uint16_t portid, struct rte_mempool *mbuf_pool) struct rte_eth_txconf txq_conf; struct rte_eth_conf local_port_conf = port_conf; - if (portid >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(portid)) rte_exit(EXIT_FAILURE, "Invalid port\n"); rte_eth_dev_info_get(portid, &dev_info); if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + retval = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); if (retval != 0) rte_exit(EXIT_FAILURE, "port %u: configuration failed (res=%d)\n", @@ -177,7 +188,6 @@ slave_port_init(uint16_t portid, struct rte_mempool *mbuf_pool) /* TX setup */ txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; retval = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), &txq_conf); @@ -246,7 +256,6 @@ bond_port_init(struct rte_mempool *mbuf_pool) /* TX setup */ txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; retval = rte_eth_tx_queue_setup(BOND_PORT, 0, nb_txd, rte_eth_dev_socket_id(BOND_PORT), &txq_conf); @@ -738,17 +747,17 @@ int main(int argc, char *argv[]) { int ret; - uint8_t nb_ports, i; + uint16_t nb_ports, i; /* init EAL */ ret = rte_eal_init(argc, argv); - rte_eal_devargs_dump(stdout); + rte_devargs_dump(stdout); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "Give at least one port\n"); else if (nb_ports > MAX_PORTS) @@ -761,7 +770,7 @@ main(int argc, char *argv[]) /* initialize all ports */ slaves_count = nb_ports; - for (i = 0; i < nb_ports; i++) { + RTE_ETH_FOREACH_DEV(i) { slave_port_init(i, mbuf_pool); slaves[i] = i; } diff --git a/examples/bond/meson.build b/examples/bond/meson.build index 8f65e4a8..82e355a4 100644 --- a/examples/bond/meson.build +++ b/examples/bond/meson.build @@ -7,6 +7,7 @@ # DPDK instance, use 'make' deps += 'pmd_bond' +allow_experimental_apis = true sources = files( 'main.c' ) diff --git a/examples/distributor/main.c b/examples/distributor/main.c index c49d680b..03a05e3d 100644 --- a/examples/distributor/main.c +++ b/examples/distributor/main.c @@ -80,7 +80,6 @@ static const struct rte_eth_conf port_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, @@ -116,7 +115,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) struct rte_eth_dev_info dev_info; struct rte_eth_txconf txconf; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; rte_eth_dev_info_get(port, &dev_info); @@ -124,6 +123,17 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf_default.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + port_conf_default.rx_adv_conf.rss_conf.rss_hf, + port_conf.rx_adv_conf.rss_conf.rss_hf); + } + retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf); if (retval != 0) return retval; @@ -141,7 +151,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; for (q = 0; q < txRings; q++) { retval = rte_eth_tx_queue_setup(port, q, nb_txd, @@ -193,12 +202,12 @@ struct lcore_params { static int lcore_rx(struct lcore_params *p) { - const uint16_t nb_ports = rte_eth_dev_count(); + const uint16_t nb_ports = rte_eth_dev_count_avail(); const int socket_id = rte_socket_id(); uint16_t port; struct rte_mbuf *bufs[BURST_SIZE*2]; - for (port = 0; port < nb_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << port)) == 0) continue; @@ -295,11 +304,11 @@ flush_one_port(struct output_buffer *outbuf, uint8_t outp) } static inline void -flush_all_ports(struct output_buffer *tx_buffers, uint16_t nb_ports) +flush_all_ports(struct output_buffer *tx_buffers) { uint16_t outp; - for (outp = 0; outp < nb_ports; outp++) { + RTE_ETH_FOREACH_DEV(outp) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << outp)) == 0) continue; @@ -367,11 +376,10 @@ static int lcore_tx(struct rte_ring *in_r) { static struct output_buffer tx_buffers[RTE_MAX_ETHPORTS]; - const uint16_t nb_ports = rte_eth_dev_count(); const int socket_id = rte_socket_id(); uint16_t port; - for (port = 0; port < nb_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << port)) == 0) continue; @@ -386,7 +394,7 @@ lcore_tx(struct rte_ring *in_r) printf("\nCore %u doing packet TX.\n", rte_lcore_id()); while (!quit_signal) { - for (port = 0; port < nb_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << port)) == 0) continue; @@ -398,7 +406,7 @@ lcore_tx(struct rte_ring *in_r) /* if we get no traffic, flush anything we have */ if (unlikely(nb_rx == 0)) { - flush_all_ports(tx_buffers, nb_ports); + flush_all_ports(tx_buffers); continue; } @@ -446,14 +454,14 @@ print_stats(void) unsigned int i, j; const unsigned int num_workers = rte_lcore_count() - 4; - for (i = 0; i < rte_eth_dev_count(); i++) { + RTE_ETH_FOREACH_DEV(i) { rte_eth_stats_get(i, ð_stats); app_stats.port_rx_pkts[i] = eth_stats.ipackets; app_stats.port_tx_pkts[i] = eth_stats.opackets; } printf("\n\nRX Thread:\n"); - for (i = 0; i < rte_eth_dev_count(); i++) { + RTE_ETH_FOREACH_DEV(i) { printf("Port %u Pktsin : %5.2f\n", i, (app_stats.port_rx_pkts[i] - prev_app_stats.port_rx_pkts[i])/1000000.0); @@ -492,7 +500,7 @@ print_stats(void) printf(" - Dequeued: %5.2f\n", (app_stats.tx.dequeue_pkts - prev_app_stats.tx.dequeue_pkts)/1000000.0); - for (i = 0; i < rte_eth_dev_count(); i++) { + RTE_ETH_FOREACH_DEV(i) { printf("Port %u Pktsout: %5.2f\n", i, (app_stats.port_tx_pkts[i] - prev_app_stats.port_tx_pkts[i])/1000000.0); @@ -543,7 +551,7 @@ lcore_worker(struct lcore_params *p) * for single port, xor_val will be zero so we won't modify the output * port, otherwise we send traffic from 0 to 1, 2 to 3, and vice versa */ - const unsigned xor_val = (rte_eth_dev_count() > 1); + const unsigned xor_val = (rte_eth_dev_count_avail() > 1); struct rte_mbuf *buf[8] __rte_cache_aligned; for (i = 0; i < 8; i++) @@ -679,7 +687,7 @@ main(int argc, char *argv[]) "1 lcore for packet TX\n" "and at least 1 lcore for worker threads\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n"); if (nb_ports != 1 && (nb_ports & 1)) @@ -694,7 +702,7 @@ main(int argc, char *argv[]) nb_ports_available = nb_ports; /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); diff --git a/examples/ethtool/Makefile b/examples/ethtool/Makefile index 2b40b4b6..3d9d4f06 100644 --- a/examples/ethtool/Makefile +++ b/examples/ethtool/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +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) else diff --git a/examples/ethtool/ethtool-app/ethapp.c b/examples/ethtool/ethtool-app/ethapp.c index 0c3f1f6e..a4e64b35 100644 --- a/examples/ethtool/ethtool-app/ethapp.c +++ b/examples/ethtool/ethtool-app/ethapp.c @@ -75,6 +75,9 @@ cmdline_parse_token_num_t pcmd_int_token_port = /* Commands taking port id and string */ cmdline_parse_token_string_t pcmd_eeprom_token_cmd = TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom"); +cmdline_parse_token_string_t pcmd_module_eeprom_token_cmd = + TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, + "module-eeprom"); cmdline_parse_token_string_t pcmd_mtu_token_cmd = TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu"); cmdline_parse_token_string_t pcmd_regs_token_cmd = @@ -145,9 +148,9 @@ pcmd_drvinfo_callback(__rte_unused void *ptr_params, __rte_unused void *ptr_data) { struct ethtool_drvinfo info; - int id_port; + uint16_t id_port; - for (id_port = 0; id_port < rte_eth_dev_count(); id_port++) { + RTE_ETH_FOREACH_DEV(id_port) { memset(&info, 0, sizeof(info)); if (rte_ethtool_get_drvinfo(id_port, &info)) { printf("Error getting info for port %i\n", id_port); @@ -167,10 +170,10 @@ pcmd_link_callback(__rte_unused void *ptr_params, __rte_unused struct cmdline *ctx, __rte_unused void *ptr_data) { - int num_ports = rte_eth_dev_count(); - int id_port, stat_port; + uint16_t id_port; + int stat_port; - for (id_port = 0; id_port < num_ports; id_port++) { + RTE_ETH_FOREACH_DEV(id_port) { if (!rte_eth_dev_is_valid_port(id_port)) continue; stat_port = rte_ethtool_get_link(id_port); @@ -298,6 +301,54 @@ pcmd_eeprom_callback(void *ptr_params, static void +pcmd_module_eeprom_callback(void *ptr_params, + __rte_unused struct cmdline *ctx, + __rte_unused void *ptr_data) +{ + struct pcmd_intstr_params *params = ptr_params; + struct ethtool_eeprom info_eeprom; + uint32_t module_info[2]; + int stat; + unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE]; + FILE *fp_eeprom; + + if (!rte_eth_dev_is_valid_port(params->port)) { + printf("Error: Invalid port number %i\n", params->port); + return; + } + + stat = rte_ethtool_get_module_info(params->port, module_info); + if (stat != 0) { + printf("Module EEPROM information read error %i\n", stat); + return; + } + + info_eeprom.len = module_info[1]; + info_eeprom.offset = 0; + + stat = rte_ethtool_get_module_eeprom(params->port, + &info_eeprom, bytes_eeprom); + if (stat != 0) { + printf("Module EEPROM read error %i\n", stat); + return; + } + + fp_eeprom = fopen(params->opt, "wb"); + if (fp_eeprom == NULL) { + printf("Error opening '%s' for writing\n", params->opt); + return; + } + printf("Total plugin module EEPROM length: %i bytes\n", + info_eeprom.len); + if (fwrite(bytes_eeprom, 1, info_eeprom.len, + fp_eeprom) != info_eeprom.len) { + printf("Error writing '%s'\n", params->opt); + } + fclose(fp_eeprom); +} + + +static void pcmd_pause_callback(void *ptr_params, __rte_unused struct cmdline *ctx, void *ptr_data) @@ -664,6 +715,18 @@ cmdline_parse_inst_t pcmd_eeprom = { NULL }, }; +cmdline_parse_inst_t pcmd_module_eeprom = { + .f = pcmd_module_eeprom_callback, + .data = NULL, + .help_str = "module-eeprom <port_id> <filename>\n" + " Dump plugin module EEPROM to file", + .tokens = { + (void *)&pcmd_module_eeprom_token_cmd, + (void *)&pcmd_intstr_token_port, + (void *)&pcmd_intstr_token_opt, + NULL + }, +}; cmdline_parse_inst_t pcmd_pause_noopt = { .f = pcmd_pause_callback, .data = (void *)0x01, @@ -816,6 +879,7 @@ cmdline_parse_inst_t pcmd_vlan = { cmdline_parse_ctx_t list_prompt_commands[] = { (cmdline_parse_inst_t *)&pcmd_drvinfo, (cmdline_parse_inst_t *)&pcmd_eeprom, + (cmdline_parse_inst_t *)&pcmd_module_eeprom, (cmdline_parse_inst_t *)&pcmd_link, (cmdline_parse_inst_t *)&pcmd_macaddr_get, (cmdline_parse_inst_t *)&pcmd_macaddr, diff --git a/examples/ethtool/ethtool-app/main.c b/examples/ethtool/ethtool-app/main.c index 702feabe..dc93adfe 100644 --- a/examples/ethtool/ethtool-app/main.c +++ b/examples/ethtool/ethtool-app/main.c @@ -99,7 +99,6 @@ static void setup_ports(struct app_config *app_cfg, int cnt_ports) memset(&cfg_port, 0, sizeof(cfg_port)); cfg_port.txmode.mq_mode = ETH_MQ_TX_NONE; - cfg_port.rxmode.ignore_offload_bitfield = 1; for (idx_port = 0; idx_port < cnt_ports; idx_port++) { struct app_port *ptr_port = &app_cfg->ports[idx_port]; @@ -142,7 +141,6 @@ static void setup_ports(struct app_config *app_cfg, int cnt_ports) "rte_eth_rx_queue_setup failed" ); txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; if (rte_eth_tx_queue_setup( idx_port, 0, nb_txd, rte_eth_dev_socket_id(idx_port), &txconf) < 0) @@ -251,7 +249,7 @@ int main(int argc, char **argv) if (cnt_args_parsed < 0) rte_exit(EXIT_FAILURE, "rte_eal_init(): Failed"); - cnt_ports = rte_eth_dev_count(); + cnt_ports = rte_eth_dev_count_avail(); printf("Number of NICs: %i\n", cnt_ports); if (cnt_ports == 0) rte_exit(EXIT_FAILURE, "No available NIC ports!\n"); diff --git a/examples/ethtool/lib/Makefile b/examples/ethtool/lib/Makefile index fbafa6d3..6eaa640b 100644 --- a/examples/ethtool/lib/Makefile +++ b/examples/ethtool/lib/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif @@ -25,6 +25,7 @@ SRCS-y := rte_ethtool.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) +CFLAGS += -DALLOW_EXPERIMENTAL_API ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) ifeq ($(CONFIG_RTE_LIBRTE_IXGBE_PMD),y) diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c index 90dfbb73..e6a2e88c 100644 --- a/examples/ethtool/lib/rte_ethtool.c +++ b/examples/ethtool/lib/rte_ethtool.c @@ -22,6 +22,8 @@ rte_ethtool_get_drvinfo(uint16_t port_id, struct ethtool_drvinfo *drvinfo) { struct rte_eth_dev_info dev_info; struct rte_dev_reg_info reg_info; + const struct rte_pci_device *pci_dev; + const struct rte_bus *bus = NULL; int n; int ret; @@ -46,15 +48,17 @@ rte_ethtool_get_drvinfo(uint16_t port_id, struct ethtool_drvinfo *drvinfo) snprintf(drvinfo->version, sizeof(drvinfo->version), "%s", rte_version()); /* TODO: replace bus_info by rte_devargs.name */ - if (dev_info.pci_dev) + if (dev_info.device) + bus = rte_bus_find_by_device(dev_info.device); + if (bus && !strcmp(bus->name, "pci")) { + pci_dev = RTE_DEV_TO_PCI(dev_info.device); snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info), "%04x:%02x:%02x.%x", - dev_info.pci_dev->addr.domain, - dev_info.pci_dev->addr.bus, - dev_info.pci_dev->addr.devid, - dev_info.pci_dev->addr.function); - else + pci_dev->addr.domain, pci_dev->addr.bus, + pci_dev->addr.devid, pci_dev->addr.function); + } else { snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info), "N/A"); + } memset(®_info, 0, sizeof(reg_info)); rte_eth_dev_get_reg_info(port_id, ®_info); @@ -174,6 +178,36 @@ rte_ethtool_set_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom, } int +rte_ethtool_get_module_info(uint16_t port_id, uint32_t *modinfo) +{ + struct rte_eth_dev_module_info *info; + + info = (struct rte_eth_dev_module_info *)modinfo; + return rte_eth_dev_get_module_info(port_id, info); +} + +int +rte_ethtool_get_module_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom, + void *words) +{ + struct rte_dev_eeprom_info eeprom_info; + int status; + + if (eeprom == NULL || words == NULL) + return -EINVAL; + + eeprom_info.offset = eeprom->offset; + eeprom_info.length = eeprom->len; + eeprom_info.data = words; + + status = rte_eth_dev_get_module_eeprom(port_id, &eeprom_info); + if (status) + return status; + + return 0; +} + +int rte_ethtool_get_pauseparam(uint16_t port_id, struct ethtool_pauseparam *pause_param) { diff --git a/examples/ethtool/lib/rte_ethtool.h b/examples/ethtool/lib/rte_ethtool.h index c9623962..43adc97a 100644 --- a/examples/ethtool/lib/rte_ethtool.h +++ b/examples/ethtool/lib/rte_ethtool.h @@ -154,6 +154,40 @@ int rte_ethtool_set_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom, void *words); /** + * Retrieve the type and size of plugin module EEPROM + * + * @param port_id + * The port identifier of the Ethernet device. + * @param modinfo + * The pointer that provides the type and size of plugin module EEPROM. + * @return + * - (0) if successful. + * - (-ENOTSUP) if hardware doesn't support. + * - (-ENODEV) if *port_id* invalid. + * - others depends on the specific operations implementation. + */ +int rte_ethtool_get_module_info(uint16_t port_id, uint32_t *modinfo); + +/** + * Retrieve the data of plugin module EEPROM + * + * @param port_id + * The port identifier of the Ethernet device. + * @param eeprom + * The pointer of ethtool_eeprom that provides plugin module eeprom + * offset and length + * @param words + * A buffer that holds data read from plugin module eeprom + * @return + * - (0) if successful. + * - (-ENOTSUP) if hardware doesn't support. + * - (-ENODEV) if *port_id* invalid. + * - others depends on the specific operations implementation. + */ +int rte_ethtool_get_module_eeprom(uint16_t port_id, + struct ethtool_eeprom *eeprom, void *words); + +/** * Retrieve the Ethernet device pause frame configuration according to * parameter attributes desribed by ethtool data structure, * ethtool_pauseparam. diff --git a/examples/ethtool/meson.build b/examples/ethtool/meson.build new file mode 100644 index 00000000..c370d747 --- /dev/null +++ b/examples/ethtool/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +# Example app currently unsupported by meson build +build = false diff --git a/examples/eventdev_pipeline/main.c b/examples/eventdev_pipeline/main.c index 2422c184..700bc696 100644 --- a/examples/eventdev_pipeline/main.c +++ b/examples/eventdev_pipeline/main.c @@ -267,7 +267,6 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, .rx_adv_conf = { .rss_conf = { @@ -285,7 +284,7 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) struct rte_eth_dev_info dev_info; struct rte_eth_txconf txconf; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; rte_eth_dev_info_get(port, &dev_info); @@ -293,6 +292,17 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf_default.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + port_conf_default.rx_adv_conf.rss_conf.rss_hf, + port_conf.rx_adv_conf.rss_conf.rss_hf); + } + /* Configure the Ethernet device. */ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) @@ -307,7 +317,6 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf_default.txmode.offloads; /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { @@ -339,10 +348,9 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) } static int -init_ports(unsigned int num_ports) +init_ports(uint16_t num_ports) { - uint8_t portid; - unsigned int i; + uint16_t portid, i; if (!cdata.num_mbuf) cdata.num_mbuf = 16384 * num_ports; @@ -354,12 +362,12 @@ init_ports(unsigned int num_ports) /* data_room_size */ RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); - for (portid = 0; portid < num_ports; portid++) + RTE_ETH_FOREACH_DEV(portid) if (port_init(portid, mp) != 0) - rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", + rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu16 "\n", portid); - for (i = 0; i < num_ports; i++) { + RTE_ETH_FOREACH_DEV(i) { void *userdata = (void *)(uintptr_t) i; fdata->tx_buf[i] = rte_malloc(NULL, RTE_ETH_TX_BUFFER_SIZE(32), 0); @@ -375,13 +383,13 @@ init_ports(unsigned int num_ports) } static void -do_capability_setup(uint16_t nb_ethdev, uint8_t eventdev_id) +do_capability_setup(uint8_t eventdev_id) { - int i; + uint16_t i; uint8_t mt_unsafe = 0; uint8_t burst = 0; - for (i = 0; i < nb_ethdev; i++) { + RTE_ETH_FOREACH_DEV(i) { struct rte_eth_dev_info dev_info; memset(&dev_info, 0, sizeof(struct rte_eth_dev_info)); @@ -430,7 +438,7 @@ int main(int argc, char **argv) { struct worker_data *worker_data; - unsigned int num_ports; + uint16_t num_ports; int lcore_id; int err; @@ -452,7 +460,7 @@ main(int argc, char **argv) /* Parse cli options*/ parse_app_args(argc, argv); - num_ports = rte_eth_dev_count(); + num_ports = rte_eth_dev_count_avail(); if (num_ports == 0) rte_panic("No ethernet ports found\n"); @@ -483,7 +491,7 @@ main(int argc, char **argv) fprintf(stderr, "Warning: More than one eventdev, using idx 0"); - do_capability_setup(num_ports, 0); + do_capability_setup(0); fdata->cap.check_opt(); worker_data = rte_calloc(0, cdata.num_workers, diff --git a/examples/eventdev_pipeline/pipeline_worker_generic.c b/examples/eventdev_pipeline/pipeline_worker_generic.c index c673160f..2215e9eb 100644 --- a/examples/eventdev_pipeline/pipeline_worker_generic.c +++ b/examples/eventdev_pipeline/pipeline_worker_generic.c @@ -138,7 +138,7 @@ consumer(void) &packet, 1, 0); if (n == 0) { - for (i = 0; i < rte_eth_dev_count(); i++) + RTE_ETH_FOREACH_DEV(i) rte_eth_tx_buffer_flush(i, 0, fdata->tx_buf[i]); return 0; } @@ -196,14 +196,13 @@ consumer_burst(void) unsigned int i, j; uint8_t dev_id = cons_data.dev_id; uint8_t port_id = cons_data.port_id; - uint16_t nb_ports = rte_eth_dev_count(); do { uint16_t n = rte_event_dequeue_burst(dev_id, port_id, packets, RTE_DIM(packets), 0); if (n == 0) { - for (j = 0; j < nb_ports; j++) + RTE_ETH_FOREACH_DEV(j) rte_eth_tx_buffer_flush(j, 0, fdata->tx_buf[j]); return 0; } @@ -521,7 +520,7 @@ generic_opt_check(void) rte_exit(EXIT_FAILURE, "Event dev doesn't support all type queues\n"); - for (i = 0; i < rte_eth_dev_count(); i++) { + RTE_ETH_FOREACH_DEV(i) { ret = rte_event_eth_rx_adapter_caps_get(0, i, &cap); if (ret) rte_exit(EXIT_FAILURE, diff --git a/examples/eventdev_pipeline/pipeline_worker_tx.c b/examples/eventdev_pipeline/pipeline_worker_tx.c index b254b03f..3dbde92d 100644 --- a/examples/eventdev_pipeline/pipeline_worker_tx.c +++ b/examples/eventdev_pipeline/pipeline_worker_tx.c @@ -422,7 +422,7 @@ setup_eventdev_worker_tx(struct cons_data *cons_data, const uint8_t dev_id = 0; const uint8_t nb_ports = cdata.num_workers; uint8_t nb_slots = 0; - uint8_t nb_queues = rte_eth_dev_count(); + uint8_t nb_queues = rte_eth_dev_count_avail(); /* * In case where all type queues are not enabled, use queues equal to @@ -431,7 +431,7 @@ setup_eventdev_worker_tx(struct cons_data *cons_data, */ if (!atq) { nb_queues *= cdata.num_stages; - nb_queues += rte_eth_dev_count(); + nb_queues += rte_eth_dev_count_avail(); } struct rte_event_dev_config config = { @@ -735,7 +735,7 @@ worker_tx_opt_check(void) rte_exit(EXIT_FAILURE, "Event dev doesn't support all type queues\n"); - for (i = 0; i < rte_eth_dev_count(); i++) { + RTE_ETH_FOREACH_DEV(i) { ret = rte_event_eth_rx_adapter_caps_get(0, i, &cap); if (ret) rte_exit(EXIT_FAILURE, diff --git a/examples/exception_path/main.c b/examples/exception_path/main.c index 3e5b1e71..440422bc 100644 --- a/examples/exception_path/main.c +++ b/examples/exception_path/main.c @@ -41,13 +41,21 @@ #include <rte_string_fns.h> #include <rte_cycles.h> +#ifndef APP_MAX_LCORE +#if (RTE_MAX_LCORE > 64) +#define APP_MAX_LCORE 64 +#else +#define APP_MAX_LCORE RTE_MAX_LCORE +#endif +#endif + /* Macros for printing using RTE_LOG */ #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 #define FATAL_ERROR(fmt, args...) rte_exit(EXIT_FAILURE, fmt "\n", ##args) #define PRINT_INFO(fmt, args...) RTE_LOG(INFO, APP, fmt "\n", ##args) /* Max ports than can be used (each port is associated with two lcores) */ -#define MAX_PORTS (RTE_MAX_LCORE / 2) +#define MAX_PORTS (APP_MAX_LCORE / 2) /* Max size of a single packet */ #define MAX_PACKET_SZ (2048) @@ -80,7 +88,6 @@ /* Options for configuring ethernet port */ static struct rte_eth_conf port_conf = { .rxmode = { - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -101,7 +108,7 @@ static uint64_t input_cores_mask = 0; static uint64_t output_cores_mask = 0; /* Array storing port_id that is associated with each lcore */ -static uint16_t port_ids[RTE_MAX_LCORE]; +static uint16_t port_ids[APP_MAX_LCORE]; /* Structure type for recording lcore-specific stats */ struct stats { @@ -111,7 +118,7 @@ struct stats { } __rte_cache_aligned; /* Array of lcore-specific stats */ -static struct stats lcore_stats[RTE_MAX_LCORE]; +static struct stats lcore_stats[APP_MAX_LCORE]; /* Print out statistics on packets handled */ static void @@ -124,6 +131,9 @@ print_stats(void) " Lcore Port RX TX Dropped on TX\n" "------- ------ ------------ ------------ ---------------\n"); RTE_LCORE_FOREACH(i) { + /* limit ourselves to application supported cores only */ + if (i >= APP_MAX_LCORE) + break; printf("%6u %7u %13"PRIu64" %13"PRIu64" %16"PRIu64"\n", i, (unsigned)port_ids[i], lcore_stats[i].rx, lcore_stats[i].tx, @@ -330,7 +340,9 @@ setup_port_lcore_affinities(void) uint16_t rx_port = 0; /* Setup port_ids[] array, and check masks were ok */ - RTE_LCORE_FOREACH(i) { + for (i = 0; i < APP_MAX_LCORE; i++) { + if (!rte_lcore_is_enabled(i)) + continue; if (input_cores_mask & (1ULL << i)) { /* Skip ports that are not enabled */ while ((ports_mask & (1 << rx_port)) == 0) { @@ -447,7 +459,6 @@ init_port(uint16_t port) port, ret); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port, 0, nb_txd, rte_eth_dev_socket_id(port), @@ -465,7 +476,7 @@ init_port(uint16_t port) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -477,7 +488,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -549,7 +560,7 @@ main(int argc, char** argv) } /* Get number of ports found in scan */ - nb_sys_ports = rte_eth_dev_count(); + nb_sys_ports = rte_eth_dev_count_avail(); if (nb_sys_ports == 0) FATAL_ERROR("No supported Ethernet device found"); /* Find highest port set in portmask */ @@ -561,14 +572,14 @@ main(int argc, char** argv) FATAL_ERROR("Port mask requires more ports than available"); /* Initialise each port */ - for (port = 0; port < nb_sys_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { /* Skip ports that are not enabled */ if ((ports_mask & (1 << port)) == 0) { continue; } init_port(port); } - check_all_ports_link_status(nb_sys_ports, ports_mask); + check_all_ports_link_status(ports_mask); /* Launch per-lcore function on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); diff --git a/examples/flow_classify/flow_classify.c b/examples/flow_classify/flow_classify.c index 32d9b1d3..19961292 100644 --- a/examples/flow_classify/flow_classify.c +++ b/examples/flow_classify/flow_classify.c @@ -62,7 +62,6 @@ const char cb_port_delim[] = ":"; static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; @@ -200,7 +199,7 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) struct rte_eth_dev_info dev_info; struct rte_eth_txconf txconf; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; rte_eth_dev_info_get(port, &dev_info); @@ -222,7 +221,6 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { @@ -259,8 +257,7 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) static __attribute__((noreturn)) void lcore_main(struct flow_classifier *cls_app) { - const uint8_t nb_ports = rte_eth_dev_count(); - uint8_t port; + uint16_t port; int ret; int i = 0; @@ -275,7 +272,7 @@ lcore_main(struct flow_classifier *cls_app) * Check that the port is on the same NUMA node as the polling thread * for best performance. */ - for (port = 0; port < nb_ports; port++) + RTE_ETH_FOREACH_DEV(port) if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != (int)rte_socket_id()) { printf("\n\n"); @@ -294,7 +291,7 @@ lcore_main(struct flow_classifier *cls_app) * on the paired port. * The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc. */ - for (port = 0; port < nb_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { /* Get burst of RX packets, from first port of pair. */ struct rte_mbuf *bufs[BURST_SIZE]; const uint16_t nb_rx = rte_eth_rx_burst(port, 0, @@ -753,8 +750,8 @@ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool; - uint8_t nb_ports; - uint8_t portid; + uint16_t nb_ports; + uint16_t portid; int ret; int socket_id; struct rte_table_acl_params table_acl_params; @@ -777,7 +774,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Invalid flow_classify parameters\n"); /* Check that there is an even number of ports to send/receive on. */ - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports < 2 || (nb_ports & 1)) rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); @@ -789,7 +786,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* Initialize all ports. */ - for (portid = 0; portid < nb_ports; portid++) + RTE_ETH_FOREACH_DEV(portid) if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", portid); diff --git a/examples/flow_filtering/Makefile b/examples/flow_filtering/Makefile index 01bb4cd8..8f86b7b2 100644 --- a/examples/flow_filtering/Makefile +++ b/examples/flow_filtering/Makefile @@ -1,34 +1,5 @@ -# -# BSD LICENSE -# -# Copyright 2017 Mellanox. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Mellanox nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2017 Mellanox Technologies, Ltd APP = flow diff --git a/examples/flow_filtering/flow_blocks.c b/examples/flow_filtering/flow_blocks.c index 61b045af..4da45928 100644 --- a/examples/flow_filtering/flow_blocks.c +++ b/examples/flow_filtering/flow_blocks.c @@ -1,33 +1,5 @@ -/*- - * BSD LICENSE - * - * Copyright 2017 Mellanox. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Mellanox nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2017 Mellanox Technologies, Ltd */ #define MAX_PATTERN_NUM 4 diff --git a/examples/flow_filtering/main.c b/examples/flow_filtering/main.c index 0bb81a8d..ce91e8a6 100644 --- a/examples/flow_filtering/main.c +++ b/examples/flow_filtering/main.c @@ -1,33 +1,5 @@ -/*- - * BSD LICENSE - * - * Copyright 2017 Mellanox. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Mellanox. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2017 Mellanox Technologies, Ltd */ #include <stdio.h> @@ -149,7 +121,6 @@ init_port(void) struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -161,6 +132,22 @@ init_port(void) DEV_TX_OFFLOAD_SCTP_CKSUM | DEV_TX_OFFLOAD_TCP_TSO, }, + /* + * Initialize fdir_conf of rte_eth_conf. + * Fdir is used in flow filtering for I40e, + * so rte_flow rules involve some fdir + * configurations. In long term it's better + * that drivers don't require any fdir + * configuration for rte_flow, but we need to + * get this workaround so that sample app can + * run on I40e. + */ + .fdir_conf = { + .mode = RTE_FDIR_MODE_PERFECT, + .pballoc = RTE_FDIR_PBALLOC_64K, + .status = RTE_FDIR_REPORT_STATUS, + .drop_queue = 127, + }, }; struct rte_eth_txconf txq_conf; struct rte_eth_rxconf rxq_conf; @@ -232,7 +219,7 @@ int main(int argc, char **argv) { int ret; - uint8_t nr_ports; + uint16_t nr_ports; struct rte_flow_error error; ret = rte_eal_init(argc, argv); @@ -243,7 +230,7 @@ main(int argc, char **argv) signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); - nr_ports = rte_eth_dev_count(); + nr_ports = rte_eth_dev_count_avail(); if (nr_ports == 0) rte_exit(EXIT_FAILURE, ":: no Ethernet ports found\n"); port_id = 0; diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c index d3b1da6c..5306d767 100644 --- a/examples/ip_fragmentation/main.c +++ b/examples/ip_fragmentation/main.c @@ -140,7 +140,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_JUMBO_FRAME | DEV_RX_OFFLOAD_CRC_STRIP), @@ -571,7 +570,7 @@ print_ethaddr(const char *name, struct ether_addr *eth_addr) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -583,7 +582,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -843,7 +842,7 @@ main(int argc, char **argv) struct rte_eth_txconf *txconf; struct rx_queue *rxq; int socket, ret; - unsigned nb_ports; + uint16_t nb_ports; uint16_t queueid = 0; unsigned lcore_id = 0, rx_lcore_id = 0; uint32_t n_tx_queue, nb_lcores; @@ -861,7 +860,7 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid arguments"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No ports found!\n"); @@ -876,7 +875,7 @@ main(int argc, char **argv) rte_exit(EXIT_FAILURE, "Non-existent ports in portmask!\n"); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_conf local_port_conf = port_conf; struct rte_eth_rxconf rxq_conf; @@ -973,7 +972,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socket, txconf); @@ -994,7 +992,7 @@ main(int argc, char **argv) printf("\n"); /* start ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } @@ -1016,7 +1014,7 @@ main(int argc, char **argv) if (init_routing_table() < 0) rte_exit(EXIT_FAILURE, "Cannot init routing table\n"); - check_all_ports_link_status(nb_ports, enabled_port_mask); + check_all_ports_link_status(enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); 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 <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <rte_string_fns.h> + +#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 <sys/queue.h> + +#include <rte_port_in_action.h> +#include <rte_table_action.h> + +#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 <stdint.h> -#include <string.h> - -#include <rte_common.h> -#include <rte_mempool.h> -#include <rte_ring.h> -#include <rte_sched.h> -#include <cmdline_parse.h> - -#include <rte_ethdev.h> -#ifdef RTE_LIBRTE_KNI -#include <rte_kni.h> -#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 <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_cycles.h> +#include <rte_ethdev.h> + +#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 <mempool_name>\n" +" buffer <buffer_size>\n" +" pool <pool_size>\n" +" cache <cache_size>\n" +" cpu <cpu_id>\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 <link_name>\n" +" dev <device_name> | port <port_id>\n" +" rxq <n_queues> <queue_size> <mempool_name>\n" +" txq <n_queues> <queue_size>\n" +" promiscuous on | off\n" +" [rss <qid_0> ... <qid_n>]\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 [<link_name>] + */ +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 <swq_name>\n" +" size <size>\n" +" cpu <cpu_id>\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" +" <tb_rate> <tb_size>\n" +" <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>\n" +" <tc_period>\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" +" <tb_rate> <tb_size>\n" +" <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>\n" +" <tc_period>\n" +" <tc_ov_weight>\n" +" <wrr_weight0..15>\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 <tmgr_name>\n" +" rate <rate>\n" +" spp <n_subports_per_port>\n" +" pps <n_pipes_per_subport>\n" +" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2> <qsize_tc3>\n" +" fo <frame_overhead>\n" +" mtu <mtu>\n" +" cpu <cpu_id>\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 <tmgr_name> subport <subport_id>\n" +" profile <subport_profile_id>\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 <tmgr_name> subport <subport_id> pipe\n" +" from <pipe_id_first> to <pipe_id_last>\n" +" profile <pipe_profile_id>\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 <tap_name>\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 <kni_name>\n" +" link <link_name>\n" +" mempool <mempool_name>\n" +" [thread <thread_id>]\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 <profile_name>\n" +" [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]\n" +" [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]\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 <profile_name>\n" +" ipv4 | ipv6\n" +" offset <ip_offset>\n" +" fwd\n" +" [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]\n" +" [meter srtcm | trtcm\n" +" tc <n_tc>\n" +" stats none | pkts | bytes | both]\n" +" [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]\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 <pipeline_name>\n" +" period <timer_period_ms>\n" +" offset_port_id <offset_port_id>\n" +" cpu <cpu_id>\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 <pipeline_name> port in\n" +" bsz <burst_size>\n" +" link <link_name> rxq <queue_id>\n" +" | swq <swq_name>\n" +" | tmgr <tmgr_name>\n" +" | tap <tap_name> mempool <mempool_name> mtu <mtu>\n" +" | kni <kni_name>\n" +" | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>\n" +" [action <port_in_action_profile_name>]\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 <pipeline_name> port out\n" +" bsz <burst_size>\n" +" link <link_name> txq <txq_id>\n" +" | swq <swq_name>\n" +" | tmgr <tmgr_name>\n" +" | tap <tap_name>\n" +" | kni <kni_name>\n" +" | sink [file <file_name> pkts <max_n_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 <pipeline_name> table\n" +" match\n" +" acl\n" +" ipv4 | ipv6\n" +" offset <ip_header_offset>\n" +" size <n_rules>\n" +" | array\n" +" offset <key_offset>\n" +" size <n_keys>\n" +" | hash\n" +" ext | lru\n" +" key <key_size>\n" +" mask <key_mask>\n" +" offset <key_offset>\n" +" buckets <n_buckets>\n" +" size <n_keys>\n" +" | lpm\n" +" ipv4 | ipv6\n" +" offset <ip_header_offset>\n" +" size <n_rules>\n" +" | stub\n" +" [action <table_action_profile_name>]\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 <pipeline_name> port in <port_id> table <table_id>\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 <pipeline_name> port in <port_id> 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 <pipeline_name> port in <port_id> 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 <pipeline_name> port in <port_id> 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 <pipeline_name> port out <port_id> 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 <pipeline_name> table <table_id> 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> ::= + * + * match + * acl + * priority <priority> + * ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth> + * <sp0> <sp1> <dp0> <dp1> <proto> + * | array <pos> + * | hash + * raw <key> + * | ipv4_5tuple <sa> <da> <sp> <dp> <proto> + * | ipv6_5tuple <sa> <da> <sp> <dp> <proto> + * | ipv4_addr <addr> + * | ipv6_addr <addr> + * | qinq <svlan> <cvlan> + * | lpm + * ipv4 | ipv6 <addr> <depth> + */ +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 <port_id> + * | meta + * | table <table_id> + * [balance <out0> ... <out7>] + * [meter + * tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa> + * [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa> + * tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa> + * tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]] + * [tm subport <subport_id> pipe <pipe_id>] + * [encap + * ether <da> <sa> + * | vlan <da> <sa> <pcp> <dei> <vid> + * | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> + * | mpls unicast | multicast + * <da> <sa> + * label0 <label> <tc> <ttl> + * [label1 <label> <tc> <ttl> + * [label2 <label> <tc> <ttl> + * [label3 <label> <tc> <ttl>]]] + * | pppoe <da> <sa> <session_id>] + * [nat ipv4 | ipv6 <addr> <port>] + * [ttl dec | keep] + * [stats] + * [time] + * + * where: + * <pa> ::= g | y | r | drop + */ +static uint32_t +parse_table_action_fwd(char **tokens, + uint32_t n_tokens, + struct table_rule_action *a) +{ + if ((n_tokens == 0) || (strcmp(tokens[0], "fwd") != 0)) + return 0; + + tokens++; + n_tokens--; + + if (n_tokens && (strcmp(tokens[0], "drop") == 0)) { + a->fwd.action = RTE_PIPELINE_ACTION_DROP; + a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; + return 1 + 1; + } + + if (n_tokens && (strcmp(tokens[0], "port") == 0)) { + uint32_t id; + + if ((n_tokens < 2) || + parser_read_uint32(&id, tokens[1])) + return 0; + + a->fwd.action = RTE_PIPELINE_ACTION_PORT; + a->fwd.id = id; + a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; + return 1 + 2; + } + + if (n_tokens && (strcmp(tokens[0], "meta") == 0)) { + a->fwd.action = RTE_PIPELINE_ACTION_PORT_META; + a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; + return 1 + 1; + } + + if (n_tokens && (strcmp(tokens[0], "table") == 0)) { + uint32_t id; + + if ((n_tokens < 2) || + parser_read_uint32(&id, tokens[1])) + return 0; + + a->fwd.action = RTE_PIPELINE_ACTION_TABLE; + a->fwd.id = id; + a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; + return 1 + 2; + } + + return 0; +} + +static uint32_t +parse_table_action_balance(char **tokens, + uint32_t n_tokens, + struct table_rule_action *a) +{ + uint32_t i; + + if ((n_tokens == 0) || (strcmp(tokens[0], "balance") != 0)) + return 0; + + tokens++; + n_tokens--; + + if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE) + return 0; + + for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++) + if (parser_read_uint32(&a->lb.out[i], tokens[i]) != 0) + return 0; + + a->action_mask |= 1 << RTE_TABLE_ACTION_LB; + return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE; + +} + +static int +parse_policer_action(char *token, enum rte_table_action_policer *a) +{ + if (strcmp(token, "g") == 0) { + *a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN; + return 0; + } + + if (strcmp(token, "y") == 0) { + *a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW; + return 0; + } + + if (strcmp(token, "r") == 0) { + *a = RTE_TABLE_ACTION_POLICER_COLOR_RED; + return 0; + } + + if (strcmp(token, "drop") == 0) { + *a = RTE_TABLE_ACTION_POLICER_DROP; + return 0; + } + + return -1; +} + +static uint32_t +parse_table_action_meter_tc(char **tokens, + uint32_t n_tokens, + struct rte_table_action_mtr_tc_params *mtr) +{ + if ((n_tokens < 9) || + strcmp(tokens[0], "meter") || + parser_read_uint32(&mtr->meter_profile_id, tokens[1]) || + strcmp(tokens[2], "policer") || + strcmp(tokens[3], "g") || + parse_policer_action(tokens[4], &mtr->policer[e_RTE_METER_GREEN]) || + strcmp(tokens[5], "y") || + parse_policer_action(tokens[6], &mtr->policer[e_RTE_METER_YELLOW]) || + strcmp(tokens[7], "r") || + parse_policer_action(tokens[8], &mtr->policer[e_RTE_METER_RED])) + return 0; + + return 9; +} + +static uint32_t +parse_table_action_meter(char **tokens, + uint32_t n_tokens, + struct table_rule_action *a) +{ + if ((n_tokens == 0) || strcmp(tokens[0], "meter")) + return 0; + + tokens++; + n_tokens--; + + if ((n_tokens < 10) || + strcmp(tokens[0], "tc0") || + (parse_table_action_meter_tc(tokens + 1, + n_tokens - 1, + &a->mtr.mtr[0]) == 0)) + return 0; + + tokens += 10; + n_tokens -= 10; + + if ((n_tokens == 0) || strcmp(tokens[0], "tc1")) { + a->mtr.tc_mask = 1; + a->action_mask |= 1 << RTE_TABLE_ACTION_MTR; + return 1 + 10; + } + + if ((n_tokens < 30) || + (parse_table_action_meter_tc(tokens + 1, + n_tokens - 1, &a->mtr.mtr[1]) == 0) || + strcmp(tokens[10], "tc2") || + (parse_table_action_meter_tc(tokens + 11, + n_tokens - 11, &a->mtr.mtr[2]) == 0) || + strcmp(tokens[20], "tc3") || + (parse_table_action_meter_tc(tokens + 21, + n_tokens - 21, &a->mtr.mtr[3]) == 0)) + return 0; + + a->mtr.tc_mask = 0xF; + a->action_mask |= 1 << RTE_TABLE_ACTION_MTR; + return 1 + 10 + 3 * 10; +} + +static uint32_t +parse_table_action_tm(char **tokens, + uint32_t n_tokens, + struct table_rule_action *a) +{ + uint32_t subport_id, pipe_id; + + if ((n_tokens < 5) || + strcmp(tokens[0], "tm") || + strcmp(tokens[1], "subport") || + parser_read_uint32(&subport_id, tokens[2]) || + strcmp(tokens[3], "pipe") || + parser_read_uint32(&pipe_id, tokens[4])) + return 0; + + a->tm.subport_id = subport_id; + a->tm.pipe_id = pipe_id; + a->action_mask |= 1 << RTE_TABLE_ACTION_TM; + return 5; +} + +static uint32_t +parse_table_action_encap(char **tokens, + uint32_t n_tokens, + struct table_rule_action *a) +{ + if ((n_tokens == 0) || strcmp(tokens[0], "encap")) + return 0; + + tokens++; + n_tokens--; + + /* ether */ + if (n_tokens && (strcmp(tokens[0], "ether") == 0)) { + if ((n_tokens < 3) || + parse_mac_addr(tokens[1], &a->encap.ether.ether.da) || + parse_mac_addr(tokens[2], &a->encap.ether.ether.sa)) + return 0; + + a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER; + a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; + return 1 + 3; + } + + /* vlan */ + if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) { + uint32_t pcp, dei, vid; + + if ((n_tokens < 6) || + parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) || + parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) || + parser_read_uint32(&pcp, tokens[3]) || + (pcp > 0x7) || + parser_read_uint32(&dei, tokens[4]) || + (dei > 0x1) || + parser_read_uint32(&vid, tokens[5]) || + (vid > 0xFFF)) + return 0; + + a->encap.vlan.vlan.pcp = pcp & 0x7; + a->encap.vlan.vlan.dei = dei & 0x1; + a->encap.vlan.vlan.vid = vid & 0xFFF; + a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN; + a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; + return 1 + 6; + } + + /* qinq */ + if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) { + uint32_t svlan_pcp, svlan_dei, svlan_vid; + uint32_t cvlan_pcp, cvlan_dei, cvlan_vid; + + if ((n_tokens < 9) || + parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) || + parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) || + parser_read_uint32(&svlan_pcp, tokens[3]) || + (svlan_pcp > 0x7) || + parser_read_uint32(&svlan_dei, tokens[4]) || + (svlan_dei > 0x1) || + parser_read_uint32(&svlan_vid, tokens[5]) || + (svlan_vid > 0xFFF) || + parser_read_uint32(&cvlan_pcp, tokens[6]) || + (cvlan_pcp > 0x7) || + parser_read_uint32(&cvlan_dei, tokens[7]) || + (cvlan_dei > 0x1) || + parser_read_uint32(&cvlan_vid, tokens[8]) || + (cvlan_vid > 0xFFF)) + return 0; + + a->encap.qinq.svlan.pcp = svlan_pcp & 0x7; + a->encap.qinq.svlan.dei = svlan_dei & 0x1; + a->encap.qinq.svlan.vid = svlan_vid & 0xFFF; + a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7; + a->encap.qinq.cvlan.dei = cvlan_dei & 0x1; + a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF; + a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ; + a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; + return 1 + 9; + } + + /* mpls */ + if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) { + uint32_t label, tc, ttl; + + if (n_tokens < 8) + return 0; + + if (strcmp(tokens[1], "unicast") == 0) + a->encap.mpls.unicast = 1; + else if (strcmp(tokens[1], "multicast") == 0) + a->encap.mpls.unicast = 0; + else + return 0; + + if (parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) || + parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) || + strcmp(tokens[4], "label0") || + parser_read_uint32(&label, tokens[5]) || + (label > 0xFFFFF) || + parser_read_uint32(&tc, tokens[6]) || + (tc > 0x7) || + parser_read_uint32(&ttl, tokens[7]) || + (ttl > 0x3F)) + return 0; + + a->encap.mpls.mpls[0].label = label; + a->encap.mpls.mpls[0].tc = tc; + a->encap.mpls.mpls[0].ttl = ttl; + + tokens += 8; + n_tokens -= 8; + + if ((n_tokens == 0) || strcmp(tokens[0], "label1")) { + a->encap.mpls.mpls_count = 1; + a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; + a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; + return 1 + 8; + } + + if ((n_tokens < 4) || + parser_read_uint32(&label, tokens[1]) || + (label > 0xFFFFF) || + parser_read_uint32(&tc, tokens[2]) || + (tc > 0x7) || + parser_read_uint32(&ttl, tokens[3]) || + (ttl > 0x3F)) + return 0; + + a->encap.mpls.mpls[1].label = label; + a->encap.mpls.mpls[1].tc = tc; + a->encap.mpls.mpls[1].ttl = ttl; + + tokens += 4; + n_tokens -= 4; + + if ((n_tokens == 0) || strcmp(tokens[0], "label2")) { + a->encap.mpls.mpls_count = 2; + a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; + a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; + return 1 + 8 + 4; + } + + if ((n_tokens < 4) || + parser_read_uint32(&label, tokens[1]) || + (label > 0xFFFFF) || + parser_read_uint32(&tc, tokens[2]) || + (tc > 0x7) || + parser_read_uint32(&ttl, tokens[3]) || + (ttl > 0x3F)) + return 0; + + a->encap.mpls.mpls[2].label = label; + a->encap.mpls.mpls[2].tc = tc; + a->encap.mpls.mpls[2].ttl = ttl; + + tokens += 4; + n_tokens -= 4; + + if ((n_tokens == 0) || strcmp(tokens[0], "label3")) { + a->encap.mpls.mpls_count = 3; + a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; + a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; + return 1 + 8 + 4 + 4; + } + + if ((n_tokens < 4) || + parser_read_uint32(&label, tokens[1]) || + (label > 0xFFFFF) || + parser_read_uint32(&tc, tokens[2]) || + (tc > 0x7) || + parser_read_uint32(&ttl, tokens[3]) || + (ttl > 0x3F)) + return 0; + + a->encap.mpls.mpls[3].label = label; + a->encap.mpls.mpls[3].tc = tc; + a->encap.mpls.mpls[3].ttl = ttl; + + a->encap.mpls.mpls_count = 4; + a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; + a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; + return 1 + 8 + 4 + 4 + 4; + } + + /* pppoe */ + if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) { + if ((n_tokens < 4) || + parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) || + parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) || + parser_read_uint16(&a->encap.pppoe.pppoe.session_id, + tokens[3])) + return 0; + + a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE; + a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; + return 1 + 4; + } + + return 0; +} + +static uint32_t +parse_table_action_nat(char **tokens, + uint32_t n_tokens, + struct table_rule_action *a) +{ + if ((n_tokens < 4) || + strcmp(tokens[0], "nat")) + return 0; + + if (strcmp(tokens[1], "ipv4") == 0) { + struct in_addr addr; + uint16_t port; + + if (parse_ipv4_addr(tokens[2], &addr) || + parser_read_uint16(&port, tokens[3])) + return 0; + + a->nat.ip_version = 1; + a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr); + a->nat.port = port; + a->action_mask |= 1 << RTE_TABLE_ACTION_NAT; + return 4; + } + + if (strcmp(tokens[1], "ipv6") == 0) { + struct in6_addr addr; + uint16_t port; + + if (parse_ipv6_addr(tokens[2], &addr) || + parser_read_uint16(&port, tokens[3])) + return 0; + + a->nat.ip_version = 0; + memcpy(a->nat.addr.ipv6, addr.s6_addr, 16); + a->nat.port = port; + a->action_mask |= 1 << RTE_TABLE_ACTION_NAT; + return 4; + } + + return 0; +} + +static uint32_t +parse_table_action_ttl(char **tokens, + uint32_t n_tokens, + struct table_rule_action *a) +{ + if ((n_tokens < 2) || + strcmp(tokens[0], "ttl")) + return 0; + + if (strcmp(tokens[1], "dec") == 0) + a->ttl.decrement = 1; + else if (strcmp(tokens[1], "keep") == 0) + a->ttl.decrement = 0; + else + return 0; + + a->action_mask |= 1 << RTE_TABLE_ACTION_TTL; + return 2; +} + +static uint32_t +parse_table_action_stats(char **tokens, + uint32_t n_tokens, + struct table_rule_action *a) +{ + if ((n_tokens < 1) || + strcmp(tokens[0], "stats")) + return 0; + + a->stats.n_packets = 0; + a->stats.n_bytes = 0; + a->action_mask |= 1 << RTE_TABLE_ACTION_STATS; + return 1; +} + +static uint32_t +parse_table_action_time(char **tokens, + uint32_t n_tokens, + struct table_rule_action *a) +{ + if ((n_tokens < 1) || + strcmp(tokens[0], "time")) + return 0; + + a->time.time = rte_rdtsc(); + a->action_mask |= 1 << RTE_TABLE_ACTION_TIME; + return 1; +} + +static uint32_t +parse_table_action(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + struct table_rule_action *a) +{ + uint32_t n_tokens0 = n_tokens; + + memset(a, 0, sizeof(*a)); + + if ((n_tokens < 2) || + strcmp(tokens[0], "action")) + return 0; + + tokens++; + n_tokens--; + + if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) { + uint32_t n; + + n = parse_table_action_fwd(tokens, n_tokens, a); + if (n == 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "action fwd"); + return 0; + } + + tokens += n; + n_tokens -= n; + } + + if (n_tokens && (strcmp(tokens[0], "balance") == 0)) { + uint32_t n; + + n = parse_table_action_balance(tokens, n_tokens, a); + if (n == 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "action balance"); + return 0; + } + + tokens += n; + n_tokens -= n; + } + + if (n_tokens && (strcmp(tokens[0], "meter") == 0)) { + uint32_t n; + + n = parse_table_action_meter(tokens, n_tokens, a); + if (n == 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "action meter"); + return 0; + } + + tokens += n; + n_tokens -= n; + } + + if (n_tokens && (strcmp(tokens[0], "tm") == 0)) { + uint32_t n; + + n = parse_table_action_tm(tokens, n_tokens, a); + if (n == 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "action tm"); + return 0; + } + + tokens += n; + n_tokens -= n; + } + + if (n_tokens && (strcmp(tokens[0], "encap") == 0)) { + uint32_t n; + + n = parse_table_action_encap(tokens, n_tokens, a); + if (n == 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "action encap"); + return 0; + } + + tokens += n; + n_tokens -= n; + } + + if (n_tokens && (strcmp(tokens[0], "nat") == 0)) { + uint32_t n; + + n = parse_table_action_nat(tokens, n_tokens, a); + if (n == 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "action nat"); + return 0; + } + + tokens += n; + n_tokens -= n; + } + + if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) { + uint32_t n; + + n = parse_table_action_ttl(tokens, n_tokens, a); + if (n == 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "action ttl"); + return 0; + } + + tokens += n; + n_tokens -= n; + } + + if (n_tokens && (strcmp(tokens[0], "stats") == 0)) { + uint32_t n; + + n = parse_table_action_stats(tokens, n_tokens, a); + if (n == 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "action stats"); + return 0; + } + + tokens += n; + n_tokens -= n; + } + + if (n_tokens && (strcmp(tokens[0], "time") == 0)) { + uint32_t n; + + n = parse_table_action_time(tokens, n_tokens, a); + if (n == 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "action time"); + return 0; + } + + tokens += n; + n_tokens -= n; + } + + if (n_tokens0 - n_tokens == 1) { + snprintf(out, out_size, MSG_ARG_INVALID, "action"); + return 0; + } + + return n_tokens0 - n_tokens; +} + + +static const char cmd_pipeline_table_rule_add_help[] = +"pipeline <pipeline_name> table <table_id> rule add\n" +" match <match>\n" +" action <table_action>\n"; + +static void +cmd_pipeline_table_rule_add(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct table_rule_match m; + struct table_rule_action a; + char *pipeline_name; + void *data; + uint32_t table_id, t0, n_tokens_parsed; + int status; + + if (n_tokens < 8) { + 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 (parser_read_uint32(&table_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); + return; + } + + if (strcmp(tokens[4], "rule") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); + return; + } + + if (strcmp(tokens[5], "add") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); + return; + } + + t0 = 6; + + /* match */ + n_tokens_parsed = parse_match(tokens + t0, + n_tokens - t0, + out, + out_size, + &m); + if (n_tokens_parsed == 0) + return; + t0 += n_tokens_parsed; + + /* action */ + n_tokens_parsed = parse_table_action(tokens + t0, + n_tokens - t0, + out, + out_size, + &a); + if (n_tokens_parsed == 0) + return; + t0 += n_tokens_parsed; + + if (t0 != n_tokens) { + snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); + return; + } + + status = pipeline_table_rule_add(pipeline_name, table_id, + &m, &a, &data); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_table_rule_add_default_help[] = +"pipeline <pipeline_name> table <table_id> rule add\n" +" match\n" +" default\n" +" action\n" +" fwd\n" +" drop\n" +" | port <port_id>\n" +" | meta\n" +" | table <table_id>\n"; + +static void +cmd_pipeline_table_rule_add_default(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct table_rule_action action; + void *data; + char *pipeline_name; + uint32_t table_id; + int status; + + if ((n_tokens != 11) && (n_tokens != 12)) { + 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 (parser_read_uint32(&table_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); + return; + } + + if (strcmp(tokens[4], "rule") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); + return; + } + + if (strcmp(tokens[5], "add") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); + return; + } + + if (strcmp(tokens[6], "match") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "match"); + return; + } + + if (strcmp(tokens[7], "default") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "default"); + return; + } + + if (strcmp(tokens[8], "action") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "action"); + return; + } + + if (strcmp(tokens[9], "fwd") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "fwd"); + return; + } + + action.action_mask = 1 << RTE_TABLE_ACTION_FWD; + + if (strcmp(tokens[10], "drop") == 0) { + if (n_tokens != 11) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + action.fwd.action = RTE_PIPELINE_ACTION_DROP; + } else if (strcmp(tokens[10], "port") == 0) { + uint32_t id; + + if (n_tokens != 12) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (parser_read_uint32(&id, tokens[11]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + action.fwd.action = RTE_PIPELINE_ACTION_PORT; + action.fwd.id = id; + } else if (strcmp(tokens[10], "meta") == 0) { + if (n_tokens != 11) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + action.fwd.action = RTE_PIPELINE_ACTION_PORT_META; + } else if (strcmp(tokens[10], "table") == 0) { + uint32_t id; + + if (n_tokens != 12) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (parser_read_uint32(&id, tokens[11]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); + return; + } + + action.fwd.action = RTE_PIPELINE_ACTION_TABLE; + action.fwd.id = id; + } else { + snprintf(out, out_size, MSG_ARG_INVALID, + "drop or port or meta or table"); + return; + } + + status = pipeline_table_rule_add_default(pipeline_name, + table_id, + &action, + &data); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_table_rule_add_bulk_help[] = +"pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>\n" +"\n" +" File <file_name>:\n" +" - line format: match <match> action <action>\n"; + +static int +cli_rule_file_process(const char *file_name, + size_t line_len_max, + struct table_rule_match *m, + struct table_rule_action *a, + uint32_t *n_rules, + uint32_t *line_number, + char *out, + size_t out_size); + +static void +cmd_pipeline_table_rule_add_bulk(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct table_rule_match *match; + struct table_rule_action *action; + void **data; + char *pipeline_name, *file_name; + uint32_t table_id, n_rules, n_rules_parsed, line_number; + int status; + + if (n_tokens != 9) { + 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 (parser_read_uint32(&table_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); + return; + } + + if (strcmp(tokens[4], "rule") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); + return; + } + + if (strcmp(tokens[5], "add") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); + return; + } + + if (strcmp(tokens[6], "bulk") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "bulk"); + return; + } + + file_name = tokens[7]; + + if ((parser_read_uint32(&n_rules, tokens[8]) != 0) || + (n_rules == 0)) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); + return; + } + + /* Memory allocation. */ + match = calloc(n_rules, sizeof(struct table_rule_match)); + action = calloc(n_rules, sizeof(struct table_rule_action)); + data = calloc(n_rules, sizeof(void *)); + if ((match == NULL) || (action == NULL) || (data == NULL)) { + snprintf(out, out_size, MSG_OUT_OF_MEMORY); + free(data); + free(action); + free(match); + return; + } + + /* Load rule file */ + n_rules_parsed = n_rules; + status = cli_rule_file_process(file_name, + 1024, + match, + action, + &n_rules_parsed, + &line_number, + out, + out_size); + if (status) { + snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); + free(data); + free(action); + free(match); + return; + } + if (n_rules_parsed != n_rules) { + snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name); + free(data); + free(action); + free(match); + return; + } + + /* Rule bulk add */ + status = pipeline_table_rule_add_bulk(pipeline_name, + table_id, + match, + action, + data, + &n_rules); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + free(data); + free(action); + free(match); + return; + } + + /* Memory free */ + free(data); + free(action); + free(match); +} + + +static const char cmd_pipeline_table_rule_delete_help[] = +"pipeline <pipeline_name> table <table_id> rule delete\n" +" match <match>\n"; + +static void +cmd_pipeline_table_rule_delete(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct table_rule_match m; + char *pipeline_name; + uint32_t table_id, n_tokens_parsed, t0; + int status; + + if (n_tokens < 8) { + 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 (parser_read_uint32(&table_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); + return; + } + + if (strcmp(tokens[4], "rule") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); + return; + } + + if (strcmp(tokens[5], "delete") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); + return; + } + + t0 = 6; + + /* match */ + n_tokens_parsed = parse_match(tokens + t0, + n_tokens - t0, + out, + out_size, + &m); + if (n_tokens_parsed == 0) + return; + t0 += n_tokens_parsed; + + if (n_tokens != t0) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + status = pipeline_table_rule_delete(pipeline_name, + table_id, + &m); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_table_rule_delete_default_help[] = +"pipeline <pipeline_name> table <table_id> rule delete\n" +" match\n" +" default\n"; + +static void +cmd_pipeline_table_rule_delete_default(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t table_id; + int status; + + if (n_tokens != 8) { + 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 (parser_read_uint32(&table_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); + return; + } + + if (strcmp(tokens[4], "rule") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); + return; + } + + if (strcmp(tokens[5], "delete") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); + return; + } + + if (strcmp(tokens[6], "match") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "match"); + return; + } + + if (strcmp(tokens[7], "default") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "default"); + return; + } + + status = pipeline_table_rule_delete_default(pipeline_name, + table_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_table_rule_stats_read_help[] = +"pipeline <pipeline_name> table <table_id> rule read stats [clear]\n"; + +static void +cmd_pipeline_table_rule_stats_read(char **tokens, + uint32_t n_tokens __rte_unused, + char *out, + size_t out_size) +{ + snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); +} + + +static const char cmd_pipeline_table_meter_profile_add_help[] = +"pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>\n" +" add srtcm cir <cir> cbs <cbs> ebs <ebs>\n" +" | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n"; + +static void +cmd_pipeline_table_meter_profile_add(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct rte_table_action_meter_profile p; + char *pipeline_name; + uint32_t table_id, meter_profile_id; + int status; + + if (n_tokens < 9) { + 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], "meter") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); + return; + } + + if (strcmp(tokens[5], "profile") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); + return; + } + + if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); + return; + } + + if (strcmp(tokens[7], "add") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); + return; + } + + if (strcmp(tokens[8], "srtcm") == 0) { + if (n_tokens != 15) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return; + } + + p.alg = RTE_TABLE_ACTION_METER_SRTCM; + + if (strcmp(tokens[9], "cir") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); + return; + } + + if (parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cir"); + return; + } + + if (strcmp(tokens[11], "cbs") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); + return; + } + + if (parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); + return; + } + + if (strcmp(tokens[13], "ebs") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs"); + return; + } + + if (parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "ebs"); + return; + } + } else if (strcmp(tokens[8], "trtcm") == 0) { + if (n_tokens != 17) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + p.alg = RTE_TABLE_ACTION_METER_TRTCM; + + if (strcmp(tokens[9], "cir") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); + return; + } + + if (parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cir"); + return; + } + + if (strcmp(tokens[11], "pir") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir"); + return; + } + + if (parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "pir"); + return; + } + if (strcmp(tokens[13], "cbs") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); + return; + } + + if (parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); + return; + } + + if (strcmp(tokens[15], "pbs") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs"); + return; + } + + if (parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "pbs"); + return; + } + } else { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + status = pipeline_table_mtr_profile_add(pipeline_name, + table_id, + meter_profile_id, + &p); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_table_meter_profile_delete_help[] = +"pipeline <pipeline_name> table <table_id>\n" +" meter profile <meter_profile_id> delete\n"; + +static void +cmd_pipeline_table_meter_profile_delete(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t table_id, meter_profile_id; + int status; + + if (n_tokens != 8) { + 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], "meter") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); + return; + } + + if (strcmp(tokens[5], "profile") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); + return; + } + + if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); + return; + } + + if (strcmp(tokens[7], "delete") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); + return; + } + + status = pipeline_table_mtr_profile_delete(pipeline_name, + table_id, + meter_profile_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_table_rule_meter_read_help[] = +"pipeline <pipeline_name> table <table_id> rule read meter [clear]\n"; + +static void +cmd_pipeline_table_rule_meter_read(char **tokens, + uint32_t n_tokens __rte_unused, + char *out, + size_t out_size) +{ + snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); +} + + +static const char cmd_pipeline_table_dscp_help[] = +"pipeline <pipeline_name> table <table_id> dscp <file_name>\n" +"\n" +" File <file_name>:\n" +" - exactly 64 lines\n" +" - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r\n"; + +static int +load_dscp_table(struct rte_table_action_dscp_table *dscp_table, + const char *file_name, + uint32_t *line_number) +{ + FILE *f = NULL; + uint32_t dscp, l; + + /* Check input arguments */ + if ((dscp_table == NULL) || + (file_name == NULL) || + (line_number == NULL)) { + if (line_number) + *line_number = 0; + return -EINVAL; + } + + /* Open input file */ + f = fopen(file_name, "r"); + if (f == NULL) { + *line_number = 0; + return -EINVAL; + } + + /* Read file */ + for (dscp = 0, l = 1; ; l++) { + char line[64]; + char *tokens[3]; + enum rte_meter_color color; + uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens); + + if (fgets(line, sizeof(line), f) == NULL) + break; + + if (is_comment(line)) + continue; + + if (parse_tokenize_string(line, tokens, &n_tokens)) { + *line_number = l; + fclose(f); + return -EINVAL; + } + + if (n_tokens == 0) + continue; + + if ((dscp >= RTE_DIM(dscp_table->entry)) || + (n_tokens != RTE_DIM(tokens)) || + parser_read_uint32(&tc_id, tokens[0]) || + (tc_id >= RTE_TABLE_ACTION_TC_MAX) || + parser_read_uint32(&tc_queue_id, tokens[1]) || + (tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX) || + (strlen(tokens[2]) != 1)) { + *line_number = l; + fclose(f); + return -EINVAL; + } + + switch (tokens[2][0]) { + case 'g': + case 'G': + color = e_RTE_METER_GREEN; + break; + + case 'y': + case 'Y': + color = e_RTE_METER_YELLOW; + break; + + case 'r': + case 'R': + color = e_RTE_METER_RED; + break; + + default: + *line_number = l; + fclose(f); + return -EINVAL; + } + + dscp_table->entry[dscp].tc_id = tc_id; + dscp_table->entry[dscp].tc_queue_id = tc_queue_id; + dscp_table->entry[dscp].color = color; + dscp++; + } + + /* Close file */ + fclose(f); + return 0; +} + +static void +cmd_pipeline_table_dscp(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct rte_table_action_dscp_table dscp_table; + char *pipeline_name, *file_name; + uint32_t table_id, line_number; + int status; + + if (n_tokens != 6) { + 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], "dscp") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp"); + return; + } + + file_name = tokens[5]; + + status = load_dscp_table(&dscp_table, file_name, &line_number); + if (status) { + snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); + return; + } + + status = pipeline_table_dscp_table_update(pipeline_name, + table_id, + UINT64_MAX, + &dscp_table); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_table_rule_ttl_read_help[] = +"pipeline <pipeline_name> table <table_id> rule read ttl [clear]\n"; + +static void +cmd_pipeline_table_rule_ttl_read(char **tokens, + uint32_t n_tokens __rte_unused, + char *out, + size_t out_size) +{ + snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); +} + + +static const char cmd_thread_pipeline_enable_help[] = +"thread <thread_id> pipeline <pipeline_name> enable\n"; + +static void +cmd_thread_pipeline_enable(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t thread_id; + int status; + + if (n_tokens != 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (parser_read_uint32(&thread_id, tokens[1]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); + return; + } + + if (strcmp(tokens[2], "pipeline") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); + return; + } + + pipeline_name = tokens[3]; + + if (strcmp(tokens[4], "enable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); + return; + } + + status = thread_pipeline_enable(thread_id, pipeline_name); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); + return; + } +} + + +static const char cmd_thread_pipeline_disable_help[] = +"thread <thread_id> pipeline <pipeline_name> disable\n"; + +static void +cmd_thread_pipeline_disable(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t thread_id; + int status; + + if (n_tokens != 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (parser_read_uint32(&thread_id, tokens[1]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); + return; + } + + if (strcmp(tokens[2], "pipeline") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); + return; + } + + pipeline_name = tokens[3]; + + if (strcmp(tokens[4], "disable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); + return; + } + + status = thread_pipeline_disable(thread_id, pipeline_name); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, + "thread pipeline disable"); + return; + } +} + +static void +cmd_help(char **tokens, uint32_t n_tokens, char *out, size_t out_size) +{ + tokens++; + n_tokens--; + + if (n_tokens == 0) { + snprintf(out, out_size, + "Type 'help <command>' for details on each command.\n\n" + "List of commands:\n" + "\tmempool\n" + "\tlink\n" + "\tswq\n" + "\ttmgr subport profile\n" + "\ttmgr pipe profile\n" + "\ttmgr\n" + "\ttmgr subport\n" + "\ttmgr subport pipe\n" + "\ttap\n" + "\tkni\n" + "\tport in action profile\n" + "\ttable action profile\n" + "\tpipeline\n" + "\tpipeline port in\n" + "\tpipeline port out\n" + "\tpipeline table\n" + "\tpipeline port in table\n" + "\tpipeline port in stats\n" + "\tpipeline port in enable\n" + "\tpipeline port in disable\n" + "\tpipeline port out stats\n" + "\tpipeline table stats\n" + "\tpipeline table rule add\n" + "\tpipeline table rule add default\n" + "\tpipeline table rule add bulk\n" + "\tpipeline table rule delete\n" + "\tpipeline table rule delete default\n" + "\tpipeline table rule stats read\n" + "\tpipeline table meter profile add\n" + "\tpipeline table meter profile delete\n" + "\tpipeline table rule meter read\n" + "\tpipeline table dscp\n" + "\tpipeline table rule ttl read\n" + "\tthread pipeline enable\n" + "\tthread pipeline disable\n\n"); + return; + } + + if (strcmp(tokens[0], "mempool") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_mempool_help); + return; + } + + if (strcmp(tokens[0], "link") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_link_help); + return; + } + + if (strcmp(tokens[0], "swq") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_swq_help); + return; + } + + if (strcmp(tokens[0], "tmgr") == 0) { + if (n_tokens == 1) { + snprintf(out, out_size, "\n%s\n", cmd_tmgr_help); + return; + } + + if ((n_tokens == 2) && + (strcmp(tokens[1], "subport")) == 0) { + snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_help); + return; + } + + if ((n_tokens == 3) && + (strcmp(tokens[1], "subport") == 0) && + (strcmp(tokens[2], "profile") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_tmgr_subport_profile_help); + return; + } + + if ((n_tokens == 3) && + (strcmp(tokens[1], "subport") == 0) && + (strcmp(tokens[2], "pipe") == 0)) { + snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_pipe_help); + return; + } + + if ((n_tokens == 3) && + (strcmp(tokens[1], "pipe") == 0) && + (strcmp(tokens[2], "profile") == 0)) { + snprintf(out, out_size, "\n%s\n", cmd_tmgr_pipe_profile_help); + return; + } + } + + if (strcmp(tokens[0], "tap") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_tap_help); + return; + } + + if (strcmp(tokens[0], "kni") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_kni_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[0], "port") == 0) && + (strcmp(tokens[1], "in") == 0) && + (strcmp(tokens[2], "action") == 0) && + (strcmp(tokens[3], "profile") == 0)) { + snprintf(out, out_size, "\n%s\n", cmd_port_in_action_profile_help); + return; + } + + if ((n_tokens == 3) && + (strcmp(tokens[0], "table") == 0) && + (strcmp(tokens[1], "action") == 0) && + (strcmp(tokens[2], "profile") == 0)) { + snprintf(out, out_size, "\n%s\n", cmd_table_action_profile_help); + return; + } + + if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 1)) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_help); + return; + } + + if ((strcmp(tokens[0], "pipeline") == 0) && + (strcmp(tokens[1], "port") == 0)) { + if ((n_tokens == 3) && (strcmp(tokens[2], "in")) == 0) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_in_help); + return; + } + + if ((n_tokens == 3) && (strcmp(tokens[2], "out")) == 0) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_out_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "in") == 0) && + (strcmp(tokens[3], "table") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_in_table_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "in") == 0) && + (strcmp(tokens[3], "stats") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_in_stats_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "in") == 0) && + (strcmp(tokens[3], "enable") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_in_enable_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "in") == 0) && + (strcmp(tokens[3], "disable") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_in_disable_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "out") == 0) && + (strcmp(tokens[3], "stats") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_out_stats_help); + return; + } + } + + if ((strcmp(tokens[0], "pipeline") == 0) && + (strcmp(tokens[1], "table") == 0)) { + if (n_tokens == 2) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_table_help); + return; + } + + if ((n_tokens == 3) && strcmp(tokens[2], "stats") == 0) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_stats_help); + return; + } + + if ((n_tokens == 3) && strcmp(tokens[2], "dscp") == 0) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_dscp_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "add") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_add_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "add") == 0) && + (strcmp(tokens[4], "default") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_add_default_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "add") == 0) && + (strcmp(tokens[4], "bulk") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_add_bulk_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "delete") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_delete_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "delete") == 0) && + (strcmp(tokens[4], "default") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_delete_default_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "stats") == 0) && + (strcmp(tokens[4], "read") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_stats_read_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "meter") == 0) && + (strcmp(tokens[3], "profile") == 0) && + (strcmp(tokens[4], "add") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_meter_profile_add_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "meter") == 0) && + (strcmp(tokens[3], "profile") == 0) && + (strcmp(tokens[4], "delete") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_meter_profile_delete_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "meter") == 0) && + (strcmp(tokens[4], "read") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_meter_read_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "ttl") == 0) && + (strcmp(tokens[4], "read") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_ttl_read_help); + return; + } + } + + if ((n_tokens == 3) && + (strcmp(tokens[0], "thread") == 0) && + (strcmp(tokens[1], "pipeline") == 0)) { + if (strcmp(tokens[2], "enable") == 0) { + snprintf(out, out_size, "\n%s\n", + cmd_thread_pipeline_enable_help); + return; + } + + if (strcmp(tokens[2], "disable") == 0) { + snprintf(out, out_size, "\n%s\n", + cmd_thread_pipeline_disable_help); + return; + } + } + + snprintf(out, out_size, "Invalid command\n"); +} + +void +cli_process(char *in, char *out, size_t out_size) +{ + char *tokens[CMD_MAX_TOKENS]; + uint32_t n_tokens = RTE_DIM(tokens); + int status; + + if (is_comment(in)) + return; + + status = parse_tokenize_string(in, tokens, &n_tokens); + if (status) { + snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); + return; + } + + if (n_tokens == 0) + return; + + if (strcmp(tokens[0], "help") == 0) { + cmd_help(tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "mempool") == 0) { + cmd_mempool(tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "link") == 0) { + if (strcmp(tokens[1], "show") == 0) { + cmd_link_show(tokens, n_tokens, out, out_size); + return; + } + + cmd_link(tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "swq") == 0) { + cmd_swq(tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "tmgr") == 0) { + if ((n_tokens >= 3) && + (strcmp(tokens[1], "subport") == 0) && + (strcmp(tokens[2], "profile") == 0)) { + cmd_tmgr_subport_profile(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 3) && + (strcmp(tokens[1], "pipe") == 0) && + (strcmp(tokens[2], "profile") == 0)) { + cmd_tmgr_pipe_profile(tokens, n_tokens, out, out_size); + return; + } + + if ((n_tokens >= 5) && + (strcmp(tokens[2], "subport") == 0) && + (strcmp(tokens[4], "profile") == 0)) { + cmd_tmgr_subport(tokens, n_tokens, out, out_size); + return; + } + + if ((n_tokens >= 5) && + (strcmp(tokens[2], "subport") == 0) && + (strcmp(tokens[4], "pipe") == 0)) { + cmd_tmgr_subport_pipe(tokens, n_tokens, out, out_size); + return; + } + + cmd_tmgr(tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "tap") == 0) { + cmd_tap(tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "kni") == 0) { + cmd_kni(tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "port") == 0) { + cmd_port_in_action_profile(tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "table") == 0) { + cmd_table_action_profile(tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "pipeline") == 0) { + if ((n_tokens >= 3) && + (strcmp(tokens[2], "period") == 0)) { + cmd_pipeline(tokens, n_tokens, out, out_size); + return; + } + + if ((n_tokens >= 5) && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "in") == 0) && + (strcmp(tokens[4], "bsz") == 0)) { + cmd_pipeline_port_in(tokens, n_tokens, out, out_size); + return; + } + + if ((n_tokens >= 5) && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "out") == 0) && + (strcmp(tokens[4], "bsz") == 0)) { + cmd_pipeline_port_out(tokens, n_tokens, out, out_size); + return; + } + + if ((n_tokens >= 4) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[3], "match") == 0)) { + cmd_pipeline_table(tokens, n_tokens, out, out_size); + return; + } + + if ((n_tokens >= 6) && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "in") == 0) && + (strcmp(tokens[5], "table") == 0)) { + cmd_pipeline_port_in_table(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 6) && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "in") == 0) && + (strcmp(tokens[5], "stats") == 0)) { + cmd_pipeline_port_in_stats(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 6) && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "in") == 0) && + (strcmp(tokens[5], "enable") == 0)) { + cmd_pipeline_port_in_enable(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 6) && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "in") == 0) && + (strcmp(tokens[5], "disable") == 0)) { + cmd_pipeline_port_in_disable(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 6) && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "out") == 0) && + (strcmp(tokens[5], "stats") == 0)) { + cmd_pipeline_port_out_stats(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 5) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "stats") == 0)) { + cmd_pipeline_table_stats(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 7) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "rule") == 0) && + (strcmp(tokens[5], "add") == 0) && + (strcmp(tokens[6], "match") == 0)) { + if ((n_tokens >= 8) && + (strcmp(tokens[7], "default") == 0)) { + cmd_pipeline_table_rule_add_default(tokens, + n_tokens, out, out_size); + return; + } + + cmd_pipeline_table_rule_add(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 7) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "rule") == 0) && + (strcmp(tokens[5], "add") == 0) && + (strcmp(tokens[6], "bulk") == 0)) { + cmd_pipeline_table_rule_add_bulk(tokens, + n_tokens, out, out_size); + return; + } + + if ((n_tokens >= 7) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "rule") == 0) && + (strcmp(tokens[5], "delete") == 0) && + (strcmp(tokens[6], "match") == 0)) { + if ((n_tokens >= 8) && + (strcmp(tokens[7], "default") == 0)) { + cmd_pipeline_table_rule_delete_default(tokens, + n_tokens, out, out_size); + return; + } + + cmd_pipeline_table_rule_delete(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 7) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "rule") == 0) && + (strcmp(tokens[5], "read") == 0) && + (strcmp(tokens[6], "stats") == 0)) { + cmd_pipeline_table_rule_stats_read(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 8) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "meter") == 0) && + (strcmp(tokens[5], "profile") == 0) && + (strcmp(tokens[7], "add") == 0)) { + cmd_pipeline_table_meter_profile_add(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 8) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "meter") == 0) && + (strcmp(tokens[5], "profile") == 0) && + (strcmp(tokens[7], "delete") == 0)) { + cmd_pipeline_table_meter_profile_delete(tokens, + n_tokens, out, out_size); + return; + } + + if ((n_tokens >= 7) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "rule") == 0) && + (strcmp(tokens[5], "read") == 0) && + (strcmp(tokens[6], "meter") == 0)) { + cmd_pipeline_table_rule_meter_read(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 5) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "dscp") == 0)) { + cmd_pipeline_table_dscp(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 7) && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[4], "rule") == 0) && + (strcmp(tokens[5], "read") == 0) && + (strcmp(tokens[6], "ttl") == 0)) { + cmd_pipeline_table_rule_ttl_read(tokens, n_tokens, + out, out_size); + return; + } + } + + if (strcmp(tokens[0], "thread") == 0) { + if ((n_tokens >= 5) && + (strcmp(tokens[4], "enable") == 0)) { + cmd_thread_pipeline_enable(tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 5) && + (strcmp(tokens[4], "disable") == 0)) { + cmd_thread_pipeline_disable(tokens, n_tokens, + out, out_size); + return; + } + } + + snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); +} + +int +cli_script_process(const char *file_name, + size_t msg_in_len_max, + size_t msg_out_len_max) +{ + char *msg_in = NULL, *msg_out = NULL; + FILE *f = NULL; + + /* Check input arguments */ + if ((file_name == NULL) || + (strlen(file_name) == 0) || + (msg_in_len_max == 0) || + (msg_out_len_max == 0)) + return -EINVAL; + + msg_in = malloc(msg_in_len_max + 1); + msg_out = malloc(msg_out_len_max + 1); + if ((msg_in == NULL) || + (msg_out == NULL)) { + free(msg_out); + free(msg_in); + return -ENOMEM; + } + + /* Open input file */ + f = fopen(file_name, "r"); + if (f == NULL) { + free(msg_out); + free(msg_in); + return -EIO; + } + + /* Read file */ + for ( ; ; ) { + if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) + break; + + printf("%s", msg_in); + msg_out[0] = 0; + + cli_process(msg_in, + msg_out, + msg_out_len_max); + + if (strlen(msg_out)) + printf("%s", msg_out); + } + + /* Close file */ + fclose(f); + free(msg_out); + free(msg_in); + return 0; +} + +static int +cli_rule_file_process(const char *file_name, + size_t line_len_max, + struct table_rule_match *m, + struct table_rule_action *a, + uint32_t *n_rules, + uint32_t *line_number, + char *out, + size_t out_size) +{ + FILE *f = NULL; + char *line = NULL; + uint32_t rule_id, line_id; + int status = 0; + + /* Check input arguments */ + if ((file_name == NULL) || + (strlen(file_name) == 0) || + (line_len_max == 0)) { + *line_number = 0; + return -EINVAL; + } + + /* Memory allocation */ + line = malloc(line_len_max + 1); + if (line == NULL) { + *line_number = 0; + return -ENOMEM; + } + + /* Open file */ + f = fopen(file_name, "r"); + if (f == NULL) { + *line_number = 0; + free(line); + return -EIO; + } + + /* Read file */ + for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) { + char *tokens[CMD_MAX_TOKENS]; + uint32_t n_tokens, n_tokens_parsed, t0; + + /* Read next line from file. */ + if (fgets(line, line_len_max + 1, f) == NULL) + break; + + /* Comment. */ + if (is_comment(line)) + continue; + + /* Parse line. */ + n_tokens = RTE_DIM(tokens); + status = parse_tokenize_string(line, tokens, &n_tokens); + if (status) { + status = -EINVAL; + break; + } + + /* Empty line. */ + if (n_tokens == 0) + continue; + t0 = 0; + + /* Rule match. */ + n_tokens_parsed = parse_match(tokens + t0, + n_tokens - t0, + out, + out_size, + &m[rule_id]); + if (n_tokens_parsed == 0) { + status = -EINVAL; + break; + } + t0 += n_tokens_parsed; + + /* Rule action. */ + n_tokens_parsed = parse_table_action(tokens + t0, + n_tokens - t0, + out, + out_size, + &a[rule_id]); + if (n_tokens_parsed == 0) { + status = -EINVAL; + break; + } + t0 += n_tokens_parsed; + + /* Line completed. */ + if (t0 < n_tokens) { + status = -EINVAL; + break; + } + + /* Increment rule count */ + rule_id++; + } + + /* Close file */ + fclose(f); + + /* Memory free */ + free(line); + + *n_rules = rule_id; + *line_number = line_id; + return status; +} diff --git a/examples/ip_pipeline/cli.h b/examples/ip_pipeline/cli.h new file mode 100644 index 00000000..992e4c3a --- /dev/null +++ b/examples/ip_pipeline/cli.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef __INCLUDE_CLI_H__ +#define __INCLUDE_CLI_H__ + +#include <stddef.h> + +void +cli_process(char *in, char *out, size_t out_size); + +int +cli_script_process(const char *file_name, + size_t msg_in_len_max, + size_t msg_out_len_max); + +#endif diff --git a/examples/ip_pipeline/common.h b/examples/ip_pipeline/common.h new file mode 100644 index 00000000..0886dfbe --- /dev/null +++ b/examples/ip_pipeline/common.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _INCLUDE_COMMON_H_ +#define _INCLUDE_COMMON_H_ + +#ifndef NAME_SIZE +#define NAME_SIZE 64 +#endif + +#endif /* _INCLUDE_COMMON_H_ */ diff --git a/examples/ip_pipeline/config/action.cfg b/examples/ip_pipeline/config/action.cfg deleted file mode 100644 index 994ae94a..00000000 --- a/examples/ip_pipeline/config/action.cfg +++ /dev/null @@ -1,68 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -; ________________ -; RXQ0.0 --->| |---> TXQ0.0 -; | | -; RXQ1.0 --->| |---> TXQ1.0 -; | Flow | -; RXQ2.0 --->| Actions |---> TXQ2.0 -; | | -; RXQ3.0 --->| |---> TXQ3.0 -; |________________| -; -; -; Input packet: Ethernet/IPv4 -; -; Packet buffer layout: -; # Field Name Offset (Bytes) Size (Bytes) -; 0 Mbuf 0 128 -; 1 Headroom 128 128 -; 2 Ethernet header 256 14 -; 3 IPv4 header 270 20 - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = FLOW_ACTIONS -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 -pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 -n_flows = 65536 -n_meters_per_flow = 4 -flow_id_offset = 286; ipdaddr -ip_hdr_offset = 270 -color_offset = 128 diff --git a/examples/ip_pipeline/config/action.sh b/examples/ip_pipeline/config/action.sh deleted file mode 100644 index 2986ae60..00000000 --- a/examples/ip_pipeline/config/action.sh +++ /dev/null @@ -1,119 +0,0 @@ -# -# run ./config/action.sh -# - -p 1 action flow 0 meter 0 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 0 policer 0 g G y Y r R -p 1 action flow 0 meter 1 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 0 policer 1 g G y Y r R -p 1 action flow 0 meter 2 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 0 policer 2 g G y Y r R -p 1 action flow 0 meter 3 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 0 policer 3 g G y Y r R -p 1 action flow 0 port 0 - -p 1 action flow 1 meter 0 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 1 policer 0 g G y Y r R -p 1 action flow 1 meter 1 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 1 policer 1 g G y Y r R -p 1 action flow 1 meter 2 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 1 policer 2 g G y Y r R -p 1 action flow 1 meter 3 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 1 policer 3 g G y Y r R -p 1 action flow 1 port 1 - -p 1 action flow 2 meter 0 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 2 policer 0 g G y Y r R -p 1 action flow 2 meter 1 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 2 policer 1 g G y Y r R -p 1 action flow 2 meter 2 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 2 policer 2 g G y Y r R -p 1 action flow 2 meter 3 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 2 policer 3 g G y Y r R -p 1 action flow 2 port 2 - -p 1 action flow 3 meter 0 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 3 policer 0 g G y Y r R -p 1 action flow 3 meter 1 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 3 policer 1 g G y Y r R -p 1 action flow 3 meter 2 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 3 policer 2 g G y Y r R -p 1 action flow 3 meter 3 trtcm 1250000000 1250000000 1000000 1000000 -p 1 action flow 3 policer 3 g G y Y r R -p 1 action flow 3 port 3 - -#p 1 action flow bulk ./config/action.txt - -#p 1 action flow ls - -p 1 action flow 0 stats -p 1 action flow 1 stats -p 1 action flow 2 stats -p 1 action flow 3 stats - -p 1 action dscp 0 class 0 color G -p 1 action dscp 1 class 1 color G -p 1 action dscp 2 class 2 color G -p 1 action dscp 3 class 3 color G -p 1 action dscp 4 class 0 color G -p 1 action dscp 5 class 1 color G -p 1 action dscp 6 class 2 color G -p 1 action dscp 7 class 3 color G -p 1 action dscp 8 class 0 color G -p 1 action dscp 9 class 1 color G -p 1 action dscp 10 class 2 color G -p 1 action dscp 11 class 3 color G -p 1 action dscp 12 class 0 color G -p 1 action dscp 13 class 1 color G -p 1 action dscp 14 class 2 color G -p 1 action dscp 15 class 3 color G -p 1 action dscp 16 class 0 color G -p 1 action dscp 17 class 1 color G -p 1 action dscp 18 class 2 color G -p 1 action dscp 19 class 3 color G -p 1 action dscp 20 class 0 color G -p 1 action dscp 21 class 1 color G -p 1 action dscp 22 class 2 color G -p 1 action dscp 23 class 3 color G -p 1 action dscp 24 class 0 color G -p 1 action dscp 25 class 1 color G -p 1 action dscp 26 class 2 color G -p 1 action dscp 27 class 3 color G -p 1 action dscp 27 class 0 color G -p 1 action dscp 29 class 1 color G -p 1 action dscp 30 class 2 color G -p 1 action dscp 31 class 3 color G -p 1 action dscp 32 class 0 color G -p 1 action dscp 33 class 1 color G -p 1 action dscp 34 class 2 color G -p 1 action dscp 35 class 3 color G -p 1 action dscp 36 class 0 color G -p 1 action dscp 37 class 1 color G -p 1 action dscp 38 class 2 color G -p 1 action dscp 39 class 3 color G -p 1 action dscp 40 class 0 color G -p 1 action dscp 41 class 1 color G -p 1 action dscp 42 class 2 color G -p 1 action dscp 43 class 3 color G -p 1 action dscp 44 class 0 color G -p 1 action dscp 45 class 1 color G -p 1 action dscp 46 class 2 color G -p 1 action dscp 47 class 3 color G -p 1 action dscp 48 class 0 color G -p 1 action dscp 49 class 1 color G -p 1 action dscp 50 class 2 color G -p 1 action dscp 51 class 3 color G -p 1 action dscp 52 class 0 color G -p 1 action dscp 53 class 1 color G -p 1 action dscp 54 class 2 color G -p 1 action dscp 55 class 3 color G -p 1 action dscp 56 class 0 color G -p 1 action dscp 57 class 1 color G -p 1 action dscp 58 class 2 color G -p 1 action dscp 59 class 3 color G -p 1 action dscp 60 class 0 color G -p 1 action dscp 61 class 1 color G -p 1 action dscp 62 class 2 color G -p 1 action dscp 63 class 3 color G - -p 1 action dscp ls diff --git a/examples/ip_pipeline/config/action.txt b/examples/ip_pipeline/config/action.txt deleted file mode 100644 index f14207b9..00000000 --- a/examples/ip_pipeline/config/action.txt +++ /dev/null @@ -1,8 +0,0 @@ -# -# p <pipelineid> action flow bulk ./config/action.txt -# - -flow 0 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 0 -flow 1 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 1 -flow 2 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 2 -flow 3 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 3 diff --git a/examples/ip_pipeline/config/diagram-generator.py b/examples/ip_pipeline/config/diagram-generator.py deleted file mode 100755 index d9efc75e..00000000 --- a/examples/ip_pipeline/config/diagram-generator.py +++ /dev/null @@ -1,317 +0,0 @@ -#!/usr/bin/env python -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2016 Intel Corporation - -# -# This script creates a visual representation for a configuration file used by -# the DPDK ip_pipeline application. -# -# The input configuration file is translated to an output file in DOT syntax, -# which is then used to create the image file using graphviz -# (www.graphviz.org). -# - -from __future__ import print_function -import argparse -import re -import os - -# -# Command to generate the image file -# -DOT_COMMAND = 'dot -Gsize=20,30 -Tpng %s > %s' - -# -# Layout of generated DOT file -# -DOT_INTRO = \ - '#\n# Command to generate image file:\n# \t%s\n#\n\n' -DOT_GRAPH_BEGIN = \ - 'digraph g {\n graph [ splines = true rankdir = "LR" ]\n' -DOT_NODE_LINK_RX = \ - ' "%s RX" [ shape = box style = filled fillcolor = yellowgreen ]\n' -DOT_NODE_LINK_TX = \ - ' "%s TX" [ shape = box style = filled fillcolor = yellowgreen ]\n' -DOT_NODE_KNI_RX = \ - ' "%s RX" [ shape = box style = filled fillcolor = orange ]\n' -DOT_NODE_KNI_TX = \ - ' "%s TX" [ shape = box style = filled fillcolor = orange ]\n' -DOT_NODE_TAP_RX = \ - ' "%s RX" [ shape = box style = filled fillcolor = gold ]\n' -DOT_NODE_TAP_TX = \ - ' "%s TX" [ shape = box style = filled fillcolor = gold ]\n' -DOT_NODE_SOURCE = \ - ' "%s" [ shape = box style = filled fillcolor = darkgreen ]\n' -DOT_NODE_SINK = \ - ' "%s" [ shape = box style = filled fillcolor = peachpuff ]\n' -DOT_NODE_PIPELINE = \ - ' "%s" [ shape = box style = filled fillcolor = royalblue ]\n' -DOT_EDGE_PKTQ = \ - ' "%s" -> "%s" [ label = "%s" color = gray ]\n' -DOT_GRAPH_END = \ - '}\n' - -# Relationships between the graph nodes and the graph edges: -# -# Edge ID | Edge Label | Writer Node | Reader Node | Dependencies -# --------+------------+-------------+---------------+-------------- -# RXQx.y | RXQx.y | LINKx | PIPELINEz | LINKx -# TXQx.y | TXQx.y | PIPELINEz | LINKx | LINKx -# SWQx | SWQx | PIPELINEy | PIPELINEz | - -# TMx | TMx | PIPELINEy | PIPELINEz | LINKx -# KNIx RX | KNIx | KNIx RX | PIPELINEy | KNIx, LINKx -# KNIx TX | KNIx | PIPELINEy | KNIx TX | KNIx, LINKx -# TAPx RX | TAPx | TAPx RX | PIPELINEy | TAPx -# TAPx TX | TAPx | PIPELINEy | TAPx TX | TAPx -# SOURCEx | SOURCEx | SOURCEx | PIPELINEy | SOURCEx -# SINKx | SINKx | PIPELINEy | SINKx | SINKx - - -# -# Parse the input configuration file to detect the graph nodes and edges -# -def process_config_file(cfgfile): - edges = {} - links = set() - knis = set() - taps = set() - sources = set() - sinks = set() - pipelines = set() - pipeline = '' - - dotfile = cfgfile + '.txt' - imgfile = cfgfile + '.png' - - # - # Read configuration file - # - lines = open(cfgfile, 'r') - for line in lines: - # Remove any leading and trailing white space characters - line = line.strip() - - # Remove any comment at end of line - line, sep, tail = line.partition(';') - - # Look for next "PIPELINE" section - match = re.search(r'\[(PIPELINE\d+)\]', line) - if match: - pipeline = match.group(1) - continue - - # Look for next "pktq_in" section entry - match = re.search(r'pktq_in\s*=\s*(.+)', line) - if match: - pipelines.add(pipeline) - for q in re.findall('\S+', match.group(1)): - match_rxq = re.search(r'^RXQ(\d+)\.\d+$', q) - match_swq = re.search(r'^SWQ\d+$', q) - match_tm = re.search(r'^TM(\d+)$', q) - match_kni = re.search(r'^KNI(\d+)$', q) - match_tap = re.search(r'^TAP\d+$', q) - match_source = re.search(r'^SOURCE\d+$', q) - - # Set ID for the current packet queue (graph edge) - q_id = '' - if match_rxq or match_swq or match_tm or match_source: - q_id = q - elif match_kni or match_tap: - q_id = q + ' RX' - else: - print('Error: Unrecognized pktq_in element "%s"' % q) - return - - # Add current packet queue to the set of graph edges - if q_id not in edges: - edges[q_id] = {} - if 'label' not in edges[q_id]: - edges[q_id]['label'] = q - if 'readers' not in edges[q_id]: - edges[q_id]['readers'] = [] - if 'writers' not in edges[q_id]: - edges[q_id]['writers'] = [] - - # Add reader for the new edge - edges[q_id]['readers'].append(pipeline) - - # Check for RXQ - if match_rxq: - link = 'LINK' + str(match_rxq.group(1)) - edges[q_id]['writers'].append(link + ' RX') - links.add(link) - continue - - # Check for SWQ - if match_swq: - continue - - # Check for TM - if match_tm: - link = 'LINK' + str(match_tm.group(1)) - links.add(link) - continue - - # Check for KNI - if match_kni: - link = 'LINK' + str(match_kni.group(1)) - edges[q_id]['writers'].append(q_id) - knis.add(q) - links.add(link) - continue - - # Check for TAP - if match_tap: - edges[q_id]['writers'].append(q_id) - taps.add(q) - continue - - # Check for SOURCE - if match_source: - edges[q_id]['writers'].append(q) - sources.add(q) - continue - - continue - - # Look for next "pktq_out" section entry - match = re.search(r'pktq_out\s*=\s*(.+)', line) - if match: - for q in re.findall('\S+', match.group(1)): - match_txq = re.search(r'^TXQ(\d+)\.\d+$', q) - match_swq = re.search(r'^SWQ\d+$', q) - match_tm = re.search(r'^TM(\d+)$', q) - match_kni = re.search(r'^KNI(\d+)$', q) - match_tap = re.search(r'^TAP(\d+)$', q) - match_sink = re.search(r'^SINK(\d+)$', q) - - # Set ID for the current packet queue (graph edge) - q_id = '' - if match_txq or match_swq or match_tm or match_sink: - q_id = q - elif match_kni or match_tap: - q_id = q + ' TX' - else: - print('Error: Unrecognized pktq_out element "%s"' % q) - return - - # Add current packet queue to the set of graph edges - if q_id not in edges: - edges[q_id] = {} - if 'label' not in edges[q_id]: - edges[q_id]['label'] = q - if 'readers' not in edges[q_id]: - edges[q_id]['readers'] = [] - if 'writers' not in edges[q_id]: - edges[q_id]['writers'] = [] - - # Add writer for the new edge - edges[q_id]['writers'].append(pipeline) - - # Check for TXQ - if match_txq: - link = 'LINK' + str(match_txq.group(1)) - edges[q_id]['readers'].append(link + ' TX') - links.add(link) - continue - - # Check for SWQ - if match_swq: - continue - - # Check for TM - if match_tm: - link = 'LINK' + str(match_tm.group(1)) - links.add(link) - continue - - # Check for KNI - if match_kni: - link = 'LINK' + str(match_kni.group(1)) - edges[q_id]['readers'].append(q_id) - knis.add(q) - links.add(link) - continue - - # Check for TAP - if match_tap: - edges[q_id]['readers'].append(q_id) - taps.add(q) - continue - - # Check for SINK - if match_sink: - edges[q_id]['readers'].append(q) - sinks.add(q) - continue - - continue - - # - # Write DOT file - # - print('Creating DOT file "%s" ...' % dotfile) - dot_cmd = DOT_COMMAND % (dotfile, imgfile) - file = open(dotfile, 'w') - file.write(DOT_INTRO % dot_cmd) - file.write(DOT_GRAPH_BEGIN) - - # Write the graph nodes to the DOT file - for l in sorted(links): - file.write(DOT_NODE_LINK_RX % l) - file.write(DOT_NODE_LINK_TX % l) - for k in sorted(knis): - file.write(DOT_NODE_KNI_RX % k) - file.write(DOT_NODE_KNI_TX % k) - for t in sorted(taps): - file.write(DOT_NODE_TAP_RX % t) - file.write(DOT_NODE_TAP_TX % t) - for s in sorted(sources): - file.write(DOT_NODE_SOURCE % s) - for s in sorted(sinks): - file.write(DOT_NODE_SINK % s) - for p in sorted(pipelines): - file.write(DOT_NODE_PIPELINE % p) - - # Write the graph edges to the DOT file - for q in sorted(edges.keys()): - rw = edges[q] - if 'writers' not in rw: - print('Error: "%s" has no writer' % q) - return - if 'readers' not in rw: - print('Error: "%s" has no reader' % q) - return - for w in rw['writers']: - for r in rw['readers']: - file.write(DOT_EDGE_PKTQ % (w, r, rw['label'])) - - file.write(DOT_GRAPH_END) - file.close() - - # - # Execute the DOT command to create the image file - # - print('Creating image file "%s" ...' % imgfile) - if os.system('which dot > /dev/null'): - print('Error: Unable to locate "dot" executable.' - 'Please install the "graphviz" package (www.graphviz.org).') - return - - os.system(dot_cmd) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Create diagram for IP ' - 'pipeline configuration ' - 'file.') - - parser.add_argument( - '-f', - '--file', - help='input configuration file (e.g. "ip_pipeline.cfg")', - required=True) - - args = parser.parse_args() - - process_config_file(args.file) diff --git a/examples/ip_pipeline/config/edge_router_downstream.cfg b/examples/ip_pipeline/config/edge_router_downstream.cfg deleted file mode 100644 index c6b4e1f2..00000000 --- a/examples/ip_pipeline/config/edge_router_downstream.cfg +++ /dev/null @@ -1,97 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -; An edge router typically sits between two networks such as the provider -; core network and the provider access network. A typical packet processing -; pipeline for the downstream traffic (i.e. traffic from core to access -; network) contains the following functional blocks: Packet RX & Routing, -; Traffic management and Packet TX. The input packets are assumed to be -; IPv4, while the output packets are Q-in-Q IPv4. -; -; A simple implementation for this functional pipeline is presented below. -; -; Packet Rx & Traffic Management Packet Tx -; Routing (Pass-Through) (Pass-Through) -; _____________________ SWQ0 ______________________ SWQ4 _____________________ -; RXQ0.0 --->| |----->| |----->| |---> TXQ0.0 -; | | SWQ1 | | SWQ5 | | -; RXQ1.0 --->| |----->| |----->| |---> TXQ1.0 -; | (P1) | SWQ2 | (P2) | SWQ6 | (P3) | -; RXQ2.0 --->| |----->| |----->| |---> TXQ2.0 -; | | SWQ3 | | SWQ7 | | -; RXQ3.0 --->| |----->| |----->| |---> TXQ3.0 -; |_____________________| |______________________| |_____________________| -; | | ^ | ^ | ^ | ^ -; | |__| |__| |__| |__| -; +--> SINK0 TM0 TM1 TM2 TM3 -; (Default) -; -; Input packet: Ethernet/IPv4 -; Output packet: Ethernet/QinQ/IPv4 -; -; Packet buffer layout: -; # Field Name Offset (Bytes) Size (Bytes) -; 0 Mbuf 0 128 -; 1 Headroom 128 128 -; 2 Ethernet header 256 14 -; 3 IPv4 header 270 20 - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = ROUTING -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 -pktq_out = SWQ0 SWQ1 SWQ2 SWQ3 SINK0 -encap = ethernet_qinq -qinq_sched = test -ip_hdr_offset = 270 - -[PIPELINE2] -type = PASS-THROUGH -core = 2 -pktq_in = SWQ0 SWQ1 SWQ2 SWQ3 TM0 TM1 TM2 TM3 -pktq_out = TM0 TM1 TM2 TM3 SWQ4 SWQ5 SWQ6 SWQ7 - -[PIPELINE3] -type = PASS-THROUGH -core = 3 -pktq_in = SWQ4 SWQ5 SWQ6 SWQ7 -pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 - -[MEMPOOL0] -pool_size = 2M diff --git a/examples/ip_pipeline/config/edge_router_downstream.sh b/examples/ip_pipeline/config/edge_router_downstream.sh deleted file mode 100644 index 67c3a0d1..00000000 --- a/examples/ip_pipeline/config/edge_router_downstream.sh +++ /dev/null @@ -1,13 +0,0 @@ -# -# run ./config/edge_router_downstream.sh -# - -################################################################################ -# Routing: Ether QinQ, ARP off -################################################################################ -p 1 route add default 4 #SINK0 -p 1 route add 0.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 qinq 256 257 -p 1 route add 0.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 qinq 258 259 -p 1 route add 0.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 qinq 260 261 -p 1 route add 0.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 qinq 262 263 -#p 1 route ls diff --git a/examples/ip_pipeline/config/edge_router_upstream.cfg b/examples/ip_pipeline/config/edge_router_upstream.cfg deleted file mode 100644 index dea42b95..00000000 --- a/examples/ip_pipeline/config/edge_router_upstream.cfg +++ /dev/null @@ -1,124 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -; An edge router typically sits between two networks such as the provider -; core network and the provider access network. A typical packet processing -; pipeline for the upstream traffic (i.e. traffic from access to core -; network) contains the following functional blocks: Packet RX & Firewall, -; Flow classification, Metering, Routing and Packet TX. The input packets -; are assumed to be Q-in-Q IPv4, while the output packets are MPLS IPv4 -; (with variable number of labels per route). -; -; A simple implementation for this functional pipeline is presented below. -; -; Packet RX & Pass-Through Flow Classification Flow Actions Routing -: Firewall -; __________ SWQ0 __________ SWQ4 __________ SWQ8 __________ SWQ12 __________ -; RXQ0.0 --->| |------>| |------>| |------>| |------>| |------> TXQ0.0 -; | | SWQ1 | | SWQ5 | | SWQ9 | | SWQ13 | | -; RXQ1.0 --->| |------>| |------>| |------>| |------>| |------> TXQ1.0 -; | (P1) | SWQ2 | (P2) | SWQ6 | (P3) | SWQ10 | (P4) | SWQ14 | (P5) | -; RXQ2.0 --->| |------>| |------>| |------>| |------>| |------> TXQ2.0 -; | | SWQ3 | | SWQ7 | | SWQ11 | | SWQ15 | | -; RXQ3.0 --->| |------>| |------>| |------>| |------>| |------> TXQ3.0 -; |__________| |__________| |__________| |__________| |__________| -; | | | -; +--> SINK0 (Default) +--> SINK1 (Default) +--> SINK2 (Default) -; -; Input packet: Ethernet/QinQ/IPv4 -; Output packet: Ethernet/MPLS/IPv4 -; -; Packet buffer layout: -; # Field Name Offset (Bytes) Size (Bytes) -; 0 Mbuf 0 128 -; 1 Headroom 128 128 -; 2 Ethernet header 256 14 -; 3 QinQ header 270 8 -; 4 IPv4 header 278 20 - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = FIREWALL -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 -pktq_out = SWQ0 SWQ1 SWQ2 SWQ3 SINK0 -n_rules = 4096 -pkt_type = qinq_ipv4 - -[PIPELINE2] -type = PASS-THROUGH -core = 2 -pktq_in = SWQ0 SWQ1 SWQ2 SWQ3 -pktq_out = SWQ4 SWQ5 SWQ6 SWQ7 -dma_size = 8 -dma_dst_offset = 128 -dma_src_offset = 268; 1st Ethertype offset -dma_src_mask = 00000FFF00000FFF; qinq -dma_hash_offset = 136; dma_dst_offset + dma_size - -[PIPELINE3] -type = FLOW_CLASSIFICATION -core = 2 -pktq_in = SWQ4 SWQ5 SWQ6 SWQ7 -pktq_out = SWQ8 SWQ9 SWQ10 SWQ11 SINK1 -n_flows = 65536 -key_size = 8; dma_size -key_offset = 128; dma_dst_offset -hash_offset = 136; dma_hash_offset -flowid_offset = 192 - -[PIPELINE4] -type = FLOW_ACTIONS -core = 3 -pktq_in = SWQ8 SWQ9 SWQ10 SWQ11 -pktq_out = SWQ12 SWQ13 SWQ14 SWQ15 -n_flows = 65536 -n_meters_per_flow = 1 -flow_id_offset = 192; flowid_offset -ip_hdr_offset = 278 -color_offset = 196; flowid_offset + sizeof(flow_id) - -[PIPELINE5] -type = ROUTING -core = 4 -pktq_in = SWQ12 SWQ13 SWQ14 SWQ15 -pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK2 -encap = ethernet_mpls -mpls_color_mark = yes -ip_hdr_offset = 278 -color_offset = 196; flowid_offset + sizeof(flow_id) diff --git a/examples/ip_pipeline/config/edge_router_upstream.sh b/examples/ip_pipeline/config/edge_router_upstream.sh deleted file mode 100644 index 5d574c1a..00000000 --- a/examples/ip_pipeline/config/edge_router_upstream.sh +++ /dev/null @@ -1,33 +0,0 @@ -# -# run ./config/edge_router_upstream.sh -# - -################################################################################ -# Firewall -################################################################################ -p 1 firewall add default 4 #SINK0 -p 1 firewall add bulk ./config/edge_router_upstream_firewall.txt -#p 1 firewall ls - -################################################################################ -# Flow Classification -################################################################################ -p 3 flow add default 4 #SINK1 -p 3 flow add qinq bulk ./config/edge_router_upstream_flow.txt -#p 3 flow ls - -################################################################################ -# Flow Actions - Metering and Policing -################################################################################ -p 4 action flow bulk ./config/edge_router_upstream_action.txt -#p 4 action flow ls - -################################################################################ -# Routing: Ether MPLS, ARP off -################################################################################ -p 5 route add default 4 #SINK2 -p 5 route add 0.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 mpls 0:1 -p 5 route add 0.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 mpls 10:11 -p 5 route add 0.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 mpls 20:21 -p 5 route add 0.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 mpls 30:31 -#p 5 route ls diff --git a/examples/ip_pipeline/config/firewall.cfg b/examples/ip_pipeline/config/firewall.cfg deleted file mode 100644 index 2f5dd9f6..00000000 --- a/examples/ip_pipeline/config/firewall.cfg +++ /dev/null @@ -1,68 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -; _______________ -; RXQ0.0 --->| |---> TXQ0.0 -; | | -; RXQ1.0 --->| |---> TXQ1.0 -; | Firewall | -; RXQ2.0 --->| |---> TXQ2.0 -; | | -; RXQ3.0 --->| |---> TXQ3.0 -; |_______________| -; | -; +-----------> SINK0 (default rule) -; -; Input packet: Ethernet/IPv4 -; -; Packet buffer layout: -; # Field Name Offset (Bytes) Size (Bytes) -; 0 Mbuf 0 128 -; 1 Headroom 128 128 -; 2 Ethernet header 256 14 -; 3 IPv4 header 270 20 - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = FIREWALL -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 -pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0 -n_rules = 4096 -pkt_type = ipv4 -;pkt_type = vlan_ipv4 -;pkt_type = qinq_ipv4 diff --git a/examples/ip_pipeline/config/firewall.sh b/examples/ip_pipeline/config/firewall.sh deleted file mode 100644 index c83857ee..00000000 --- a/examples/ip_pipeline/config/firewall.sh +++ /dev/null @@ -1,13 +0,0 @@ -# -# run ./config/firewall.sh -# - -p 1 firewall add default 4 #SINK0 -p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.0.0.0 10 0 65535 0 65535 6 0xF port 0 -p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.64.0.0 10 0 65535 0 65535 6 0xF port 1 -p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.128.0.0 10 0 65535 0 65535 6 0xF port 2 -p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.192.0.0 10 0 65535 0 65535 6 0xF port 3 - -#p 1 firewall add bulk ./config/firewall.txt - -p 1 firewall ls diff --git a/examples/ip_pipeline/config/firewall.txt b/examples/ip_pipeline/config/firewall.txt deleted file mode 100644 index 54cfffda..00000000 --- a/examples/ip_pipeline/config/firewall.txt +++ /dev/null @@ -1,9 +0,0 @@ -# -# p <pipelineid> firewall add bulk ./config/firewall.txt -# p <pipelineid> firewall del bulk ./config/firewall.txt -# - -priority 1 ipv4 0.0.0.0 0 100.0.0.0 10 0 65535 0 65535 6 0xF port 0 -priority 1 ipv4 0.0.0.0 0 100.64.0.0 10 0 65535 0 65535 6 0xF port 1 -priority 1 ipv4 0.0.0.0 0 100.128.0.0 10 0 65535 0 65535 6 0xF port 2 -priority 1 ipv4 0.0.0.0 0 100.192.0.0 10 0 65535 0 65535 6 0xF port 3 diff --git a/examples/ip_pipeline/config/flow.cfg b/examples/ip_pipeline/config/flow.cfg deleted file mode 100644 index cec990ab..00000000 --- a/examples/ip_pipeline/config/flow.cfg +++ /dev/null @@ -1,72 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -; ________________ -; RXQ0.0 --->| |---> TXQ0.0 -; | | -; RXQ1.0 --->| |---> TXQ1.0 -; | Flow | -; RXQ2.0 --->| Classification |---> TXQ2.0 -; | | -; RXQ3.0 --->| |---> TXQ3.0 -; |________________| -; | -; +-----------> SINK0 (flow lookup miss) -; -; Input packet: Ethernet/IPv4 -; -; Packet buffer layout: -; # Field Name Offset (Bytes) Size (Bytes) -; 0 Mbuf 0 128 -; 1 Headroom 128 128 -; 2 Ethernet header 256 14 -; 3 QinQ/IPv4/IPv6 header 270 8/20/40 - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = FLOW_CLASSIFICATION -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 -pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0 -n_flows = 65536 -;key_size = 8 ; QinQ key size -;key_offset = 268 ; QinQ key offset -;key_mask = 00000FFF00000FFF ; QinQ key mask -key_size = 16 ; IPv4 5-tuple key size -key_offset = 278 ; IPv4 5-tuple key offset -key_mask = 00FF0000FFFFFFFFFFFFFFFFFFFFFFFF ; IPv4 5-tuple key mask -flowid_offset = 128 diff --git a/examples/ip_pipeline/config/flow.sh b/examples/ip_pipeline/config/flow.sh deleted file mode 100644 index 489c7079..00000000 --- a/examples/ip_pipeline/config/flow.sh +++ /dev/null @@ -1,25 +0,0 @@ -# -# run ./config/flow.sh -# - -################################################################################ -# Flow classification (QinQ) -################################################################################ -#p 1 flow add default 4 #SINK0 -#p 1 flow add qinq 100 200 port 0 id 0 -#p 1 flow add qinq 101 201 port 1 id 1 -#p 1 flow add qinq 102 202 port 2 id 2 -#p 1 flow add qinq 103 203 port 3 id 3 - -#p 1 flow add qinq bulk ./config/flow.txt - -################################################################################ -# Flow classification (IPv4 5-tuple) -################################################################################ -p 1 flow add default 4 #SINK0 -p 1 flow add ipv4 100.0.0.10 200.0.0.10 100 200 6 port 0 id 0 -p 1 flow add ipv4 100.0.0.11 200.0.0.11 101 201 6 port 1 id 1 -p 1 flow add ipv4 100.0.0.12 200.0.0.12 102 202 6 port 2 id 2 -p 1 flow add ipv4 100.0.0.13 200.0.0.13 103 203 6 port 3 id 3 - -#p 1 flow add ipv4 bulk ./config/flow.txt diff --git a/examples/ip_pipeline/config/flow.txt b/examples/ip_pipeline/config/flow.txt deleted file mode 100644 index c1a141dd..00000000 --- a/examples/ip_pipeline/config/flow.txt +++ /dev/null @@ -1,17 +0,0 @@ -# -# p <pipelineid> flow add qinq bulk ./config/flow.txt -# - -#qinq 100 200 port 0 id 0 -#qinq 101 201 port 1 id 1 -#qinq 102 202 port 2 id 2 -#qinq 103 203 port 3 id 3 - -# -# p <pipelineid> flow add ipv4 bulk ./config/flow.txt -# - -ipv4 100.0.0.10 200.0.0.10 100 200 6 port 0 id 0 -ipv4 100.0.0.11 200.0.0.11 101 201 6 port 1 id 1 -ipv4 100.0.0.12 200.0.0.12 102 202 6 port 2 id 2 -ipv4 100.0.0.13 200.0.0.13 103 203 6 port 3 id 3 diff --git a/examples/ip_pipeline/config/ip_pipeline.cfg b/examples/ip_pipeline/config/ip_pipeline.cfg deleted file mode 100644 index 095ed25e..00000000 --- a/examples/ip_pipeline/config/ip_pipeline.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = PASS-THROUGH -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 -pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 diff --git a/examples/ip_pipeline/config/ip_pipeline.sh b/examples/ip_pipeline/config/ip_pipeline.sh deleted file mode 100644 index 4fca2597..00000000 --- a/examples/ip_pipeline/config/ip_pipeline.sh +++ /dev/null @@ -1,5 +0,0 @@ -# -#run config/ip_pipeline.sh -# - -p 1 ping diff --git a/examples/ip_pipeline/config/kni.cfg b/examples/ip_pipeline/config/kni.cfg deleted file mode 100644 index cea208b4..00000000 --- a/examples/ip_pipeline/config/kni.cfg +++ /dev/null @@ -1,67 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2016 Intel Corporation. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -; -; ______________ ______________________ -; | | KNI0 | | -; RXQ0.0 --->| |------->|--+ | -; | | KNI1 | | br0 | -; TXQ1.0 <---| |<-------|<-+ | -; | Pass-through | | Linux Kernel | -; | (P1) | | Network Stack | -; | | KNI1 | | -; RXQ1.0 --->| |------->|--+ | -; | | KNI0 | | br0 | -; TXQ0.0 <---| |<-------|<-+ | -; |______________| |______________________| -; -; Insert Linux kernel KNI module: -; [Linux]$ insmod rte_kni.ko -; -; Configure Linux kernel bridge between KNI0 and KNI1 interfaces: -; [Linux]$ ifconfig KNI0 up -; [Linux]$ ifconfig KNI1 up -; [Linux]$ brctl addbr "br0" -; [Linux]$ brctl addif br0 KNI0 -; [Linux]$ brctl addif br0 KNI1 -; [Linux]$ ifconfig br0 up - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = PASS-THROUGH -core = 1 -pktq_in = RXQ0.0 KNI1 RXQ1.0 KNI0 -pktq_out = KNI0 TXQ1.0 KNI1 TXQ0.0 diff --git a/examples/ip_pipeline/config/l2fwd.cfg b/examples/ip_pipeline/config/l2fwd.cfg deleted file mode 100644 index a1df9e6a..00000000 --- a/examples/ip_pipeline/config/l2fwd.cfg +++ /dev/null @@ -1,58 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -; -; The pass-through pipeline below connects the input ports to the output ports -; as follows: RXQ0.0 -> TXQ1.0, RXQ1.0 -> TXQ0.0, RXQ2.0 -> TXQ3.0 and -; RXQ3.0 -> TXQ2.0. -; ________________ -; RXQ0.0 --->|................|---> TXQ1.0 -; | | -; RXQ1.0 --->|................|---> TXQ0.0 -; | Pass-through | -; RXQ2.0 --->|................|---> TXQ3.0 -; | | -; RXQ3.0 --->|................|---> TXQ2.0 -; |________________| -; - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = PASS-THROUGH -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 -pktq_out = TXQ1.0 TXQ0.0 TXQ3.0 TXQ2.0 diff --git a/examples/ip_pipeline/config/l3fwd.cfg b/examples/ip_pipeline/config/l3fwd.cfg deleted file mode 100644 index 02c8f36f..00000000 --- a/examples/ip_pipeline/config/l3fwd.cfg +++ /dev/null @@ -1,68 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -; _______________ -; RXQ0.0 --->| |---> TXQ0.0 -; | | -; RXQ1.0 --->| |---> TXQ1.0 -; | Routing | -; RXQ2.0 --->| |---> TXQ2.0 -; | | -; RXQ3.0 --->| |---> TXQ3.0 -; |_______________| -; | -; +-----------> SINK0 (route miss) -; -; Input packet: Ethernet/IPv4 -; -; Packet buffer layout: -; # Field Name Offset (Bytes) Size (Bytes) -; 0 Mbuf 0 128 -; 1 Headroom 128 128 -; 2 Ethernet header 256 14 -; 3 IPv4 header 270 20 - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = ROUTING -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 -pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0 -encap = ethernet -;encap = ethernet_qinq -;encap = ethernet_mpls -ip_hdr_offset = 270 diff --git a/examples/ip_pipeline/config/l3fwd.sh b/examples/ip_pipeline/config/l3fwd.sh deleted file mode 100644 index 47406aa4..00000000 --- a/examples/ip_pipeline/config/l3fwd.sh +++ /dev/null @@ -1,33 +0,0 @@ -# -# run ./config/l3fwd.sh -# - -################################################################################ -# Routing: encap = ethernet, arp = off -################################################################################ -p 1 route add default 4 #SINK0 -p 1 route add 100.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 -p 1 route add 100.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 -p 1 route add 100.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 -p 1 route add 100.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 -p 1 route ls - -################################################################################ -# Routing: encap = ethernet_qinq, arp = off -################################################################################ -#p 1 route add default 4 #SINK0 -#p 1 route add 100.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 qinq 1000 2000 -#p 1 route add 100.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 qinq 1001 2001 -#p 1 route add 100.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 qinq 1002 2002 -#p 1 route add 100.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 qinq 1003 2003 -#p 1 route ls - -################################################################################ -# Routing: encap = ethernet_mpls, arp = off -################################################################################ -#p 1 route add default 4 #SINK0 -#p 1 route add 100.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 mpls 1000:2000 -#p 1 route add 100.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 mpls 1001:2001 -#p 1 route add 100.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 mpls 1002:2002 -#p 1 route add 100.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 mpls 1003:2003 -#p 1 route ls diff --git a/examples/ip_pipeline/config/l3fwd_arp.cfg b/examples/ip_pipeline/config/l3fwd_arp.cfg deleted file mode 100644 index 2c63c8fd..00000000 --- a/examples/ip_pipeline/config/l3fwd_arp.cfg +++ /dev/null @@ -1,70 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -; _______________ -; RXQ0.0 --->| |---> TXQ0.0 -; | | -; RXQ1.0 --->| |---> TXQ1.0 -; | Routing | -; RXQ2.0 --->| |---> TXQ2.0 -; | | -; RXQ3.0 --->| |---> TXQ3.0 -; |_______________| -; | -; +-----------> SINK0 (route miss) -; -; Input packet: Ethernet/IPv4 -; -; Packet buffer layout: -; # Field Name Offset (Bytes) Size (Bytes) -; 0 Mbuf 0 128 -; 1 Headroom 128 128 -; 2 Ethernet header 256 14 -; 3 IPv4 header 270 20 - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = ROUTING -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 -pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0 -encap = ethernet -;encap = ethernet_qinq -;encap = ethernet_mpls -n_arp_entries = 1024 -ip_hdr_offset = 270 -arp_key_offset = 128 diff --git a/examples/ip_pipeline/config/l3fwd_arp.sh b/examples/ip_pipeline/config/l3fwd_arp.sh deleted file mode 100644 index 20bea582..00000000 --- a/examples/ip_pipeline/config/l3fwd_arp.sh +++ /dev/null @@ -1,43 +0,0 @@ -# -# run ./config/l3fwd_arp.sh -# - -################################################################################ -# ARP -################################################################################ -p 1 arp add default 4 #SINK0 -p 1 arp add 0 10.0.0.1 a0:b0:c0:d0:e0:f0 -p 1 arp add 1 11.0.0.1 a1:b1:c1:d1:e1:f1 -p 1 arp add 2 12.0.0.1 a2:b2:c2:d2:e2:f2 -p 1 arp add 3 13.0.0.1 a3:b3:c3:d3:e3:f3 -p 1 arp ls - -################################################################################ -# Routing: encap = ethernet, arp = on -################################################################################ -p 1 route add default 4 #SINK0 -p 1 route add 100.0.0.0 10 port 0 ether 10.0.0.1 -p 1 route add 100.64.0.0 10 port 1 ether 11.0.0.1 -p 1 route add 100.128.0.0 10 port 2 ether 12.0.0.1 -p 1 route add 100.192.0.0 10 port 3 ether 13.0.0.1 -p 1 route ls - -################################################################################ -# Routing: encap = ethernet_qinq, arp = on -################################################################################ -#p 1 route add default 4 #SINK0 -#p 1 route add 100.0.0.0 10 port 0 ether 10.0.0.1 qinq 1000 2000 -#p 1 route add 100.64.0.0 10 port 1 ether 11.0.0.1 qinq 1001 2001 -#p 1 route add 100.128.0.0 10 port 2 ether 12.0.0.1 qinq 1002 2002 -#p 1 route add 100.192.0.0 10 port 3 ether 13.0.0.1 qinq 1003 2003 -#p 1 route ls - -################################################################################ -# Routing: encap = ethernet_mpls, arp = on -################################################################################ -#p 1 route add default 4 #SINK0 -#p 1 route add 100.0.0.0 10 port 0 ether 10.0.0.1 mpls 1000:2000 -#p 1 route add 100.64.0.0 10 port 1 ether 11.0.0.1 mpls 1001:2001 -#p 1 route add 100.128.0.0 10 port 2 ether 12.0.0.1 mpls 1002:2002 -#p 1 route add 100.192.0.0 10 port 3 ether 13.0.0.1 mpls 1003:2003 -#p 1 route ls diff --git a/examples/ip_pipeline/config/network_layers.cfg b/examples/ip_pipeline/config/network_layers.cfg deleted file mode 100644 index 397b5d77..00000000 --- a/examples/ip_pipeline/config/network_layers.cfg +++ /dev/null @@ -1,227 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -; The diagram below shows how additional protocol components can be plugged into -; the IP layer implemented by the ip_pipeline application. Pick your favorite -; open source components for dynamic ARP, ICMP, UDP or TCP termination, etc and -; connect them through SWQs to the IP infrastructure. -; -; The input packets with local destination are sent to the UDP/TCP applications -; while the input packets with remote destination are routed back to the -; network. Additional features can easily be added to this setup: -; * IP Reassembly: add SWQs with IP reassembly enabled (typically required for -; the input traffic with local destination); -; * IP Fragmentation: add SWQs with IP fragmentation enabled (typically -; required to enforce the MTU for the routed output traffic); -; * Traffic Metering: add Flow Action pipeline instances (e.g. for metering the -; TCP connections or ICMP input traffic); -; * Traffic Management: add TMs for the required output LINKs; -; * Protocol encapsulations (QinQ, MPLS) for the output packets: part of the -; routing pipeline configuration. -; -; _________ _________ -; | | | | -; | UDP | | TCP | -; | App | | App | -; |_________| |_________| -; ^ | ^ | -; __|___V__ __|___V__ -; | | SWQ0 (UDP TX) | | SWQ1 (TCP TX) -; | UDP |-------+ | TCP |------------+ -; | | | | | | -; |_________| | |_________| | -; ^ | ^ | -; | SWQ2 | | SWQ3 | -; | (UDP RX) | | (TCP RX) | -; ____|____ | ____|____ | -; | | | | | | -; RXQ<0..3>.1 ------>|Firewall +--->| | +------>| Flow +--->| | -; (UDP local dest) | (P2) | SINK0 | | | (P3) | SINK1 | -; |_________| (Deny)| | |_________| (RST) | -; RXQ<0..3>.2 -------------------------|-----+ | -; (TCP local dest) | | -; | +------------------------------+ -; | | -; _V_____V_ -; | | -; | Routing | TXQ<0..3>.0 -; RXQ<0..3>.0 ---------------------->| & ARP +-----------------------------> -; (IP remote dest) | (P1) | -; |_________| -; | ^ | -; SWQ4 +-------------+ | | SWQ5 (ARP miss) -; (Route miss) | | +------------+ -; | +-------------+ | -; ___V__|__ SWQ6 ____V____ -; | | (ICMP TX) | | TXQ<0..3>.1 -; RXQ<0..3>.3 ------>| ICMP | +------>| Dyn ARP +-------------> -; (IP local dest) | | | | | -; |_________| | |_________| -; RXQ<0..3>.4 -------------------------------+ -; (ARP) -; -; This configuration file implements the diagram presented below, where the -; dynamic ARP, ICMP, UDP and TCP components have been stubbed out and replaced -; with loop-back and packet drop devices. -; -; _________ _________ -; | | SWQ0 (UDP TX) | | SWQ1 (TCP TX) -; |Loobpack |-------+ |Loopback |------------+ -; | (P4) | | | (P5) | | -; |_________| | |_________| | -; ^ | ^ | -; | SWQ2 | | SWQ3 | -; | (UDP RX) | | (TCP RX) | -; ____|____ | ____|____ | -; | | | | | | -; RXQ<0..3>.1 ------>|Firewall +--->| | +------>| Flow +--->| | -; (UDP local dest) | (P2) | SINK0 | | | (P3) | SINK1 | -; |_________| (Deny)| | |_________| (RST) | -; RXQ<0..3>.2 -------------------------|-----+ | -; (TCP local dest) | | -; | +------------------------------+ -; | | -; _V_____V_ -; | | -; | Routing | TXQ<0..3>.0 -; RXQ<0..3>.0 ---------------------->| & ARP +-----------------------------> -; (IP remote dest) | (P1) | -; |_________| -; | | -; SINK2 |<---+ +--->| SINK3 -; (Route miss) (ARP miss) -; -; _________ _________ -; | | | | -; RXQ<0..3>.3 ------>| Drop +--->| SINK<4..7> +------>| Drop +--->| SINK<8..11> -; (IP local dest) | (P6) | (IP local dest) | | (P7) | (ARP) -; |_________| | |_________| -; RXQ<0..3>.4 ------------------------------------+ -; (ARP) -; -; -; Input packet: Ethernet/IPv4 or Ethernet/ARP -; Output packet: Ethernet/IPv4 or Ethernet/ARP -; -; Packet buffer layout (for input IPv4 packets): -; # Field Name Offset (Bytes) Size (Bytes) -; 0 Mbuf 0 128 -; 1 Headroom 128 128 -; 2 Ethernet header 256 14 -; 3 IPv4 header 270 20 -; 4 ICMP/UDP/TCP header 290 8/8/20 - -[EAL] -log_level = 0 - -[LINK0] -udp_local_q = 1 -tcp_local_q = 2 -ip_local_q = 3 -arp_q = 4 - -[LINK1] -udp_local_q = 1 -tcp_local_q = 2 -ip_local_q = 3 -arp_q = 4 - -[LINK2] -udp_local_q = 1 -tcp_local_q = 2 -ip_local_q = 3 -arp_q = 4 - -[LINK3] -udp_local_q = 1 -tcp_local_q = 2 -ip_local_q = 3 -arp_q = 4 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = ROUTING -core = 1 -pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 SWQ0 SWQ1 -pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK2 SINK3 -port_local_dest = 4 ; SINK2 (Drop) -n_arp_entries = 1000 -ip_hdr_offset = 270 -arp_key_offset = 128 - -[PIPELINE2] -type = FIREWALL -core = 1 -pktq_in = RXQ0.1 RXQ1.1 RXQ2.1 RXQ3.1 -pktq_out = SWQ2 SINK0 -n_rules = 4096 - -[PIPELINE3] -type = FLOW_CLASSIFICATION -core = 1 -pktq_in = RXQ0.2 RXQ1.2 RXQ2.2 RXQ3.2 -pktq_out = SWQ3 SINK1 -n_flows = 65536 -key_size = 16 ; IPv4 5-tuple key size -key_offset = 278 ; IPv4 5-tuple key offset -key_mask = 00FF0000FFFFFFFFFFFFFFFFFFFFFFFF ; IPv4 5-tuple key mask -flowid_offset = 128 ; Flow ID effectively acts as TCP socket ID - -[PIPELINE4] -type = PASS-THROUGH ; Loop-back (UDP place-holder) -core = 1 -pktq_in = SWQ2 -pktq_out = SWQ0 -swap = 282 286 ; IPSRC <-> IPDST -swap = 290 292 ; PORTSRC <-> PORTDST - -[PIPELINE5] -type = PASS-THROUGH ; Loop-back (TCP place-holder) -core = 1 -pktq_in = SWQ3 -pktq_out = SWQ1 -swap = 282 286 ; IPSRC <-> IPDST -swap = 290 292 ; PORTSRC <-> PORTDST - -[PIPELINE6] -type = PASS-THROUGH ; Drop (ICMP place-holder) -core = 1 -pktq_in = RXQ0.3 RXQ1.3 RXQ2.3 RXQ3.3 -pktq_out = SINK4 SINK5 SINK6 SINK7 - -[PIPELINE7] -type = PASS-THROUGH ; Drop (Dynamic ARP place-holder) -core = 1 -pktq_in = RXQ0.4 RXQ1.4 RXQ2.4 RXQ3.4 -pktq_out = SINK8 SINK9 SINK10 SINK11 diff --git a/examples/ip_pipeline/config/network_layers.sh b/examples/ip_pipeline/config/network_layers.sh deleted file mode 100644 index 449b0069..00000000 --- a/examples/ip_pipeline/config/network_layers.sh +++ /dev/null @@ -1,79 +0,0 @@ -# -# run ./config/network_layers.sh -# - -################################################################################ -# Link configuration -################################################################################ -# Routes added implicitly when links are brought UP: -# IP Prefix = 10.0.0.1/16 => (Port 0, Local) -# IP Prefix = 10.0.0.1/32 => (Port 4, Local) -# IP Prefix = 10.1.0.1/16 => (Port 1, Local) -# IP Prefix = 10.1.0.1/32 => (Port 4, Local) -# IP Prefix = 10.2.0.1/16 => (Port 2, Local) -# IP Prefix = 10.2.0.1/32 => (Port 4, Local) -# IP Prefix = 10.3.0.1/16 => (Port 3, Local) -# IP Prefix = 10.3.0.1/32 => (Port 4, Local) -link 0 down -link 1 down -link 2 down -link 3 down -link 0 config 10.0.0.1 16 -link 1 config 10.1.0.1 16 -link 2 config 10.2.0.1 16 -link 3 config 10.3.0.1 16 -link 0 up -link 1 up -link 2 up -link 3 up -#link ls - -################################################################################ -# Static ARP -################################################################################ -p 1 arp add default 5 #SINK3 -p 1 arp add 0 10.0.0.2 a0:b0:c0:d0:e0:f0 -p 1 arp add 1 10.1.0.2 a1:b1:c1:d1:e1:f1 -p 1 arp add 2 10.2.0.2 a2:b2:c2:d2:e2:f2 -p 1 arp add 3 10.3.0.2 a3:b3:c3:d3:e3:f3 -#p 1 arp ls - -################################################################################ -# Routes -################################################################################ -p 1 route add default 4 #SINK2 -p 1 route add 100.0.0.0 16 port 0 ether 10.0.0.2 -p 1 route add 100.1.0.0 16 port 1 ether 10.1.0.2 -p 1 route add 100.2.0.0 16 port 2 ether 10.2.0.2 -p 1 route add 100.3.0.0 16 port 3 ether 10.3.0.2 -#p 1 route ls - -################################################################################ -# Local destination UDP traffic -################################################################################ -# Prio = Lowest: [SA = ANY, DA = ANY, SP = ANY, DP = ANY, PROTO = ANY] => Drop -# Prio = 1 (High): [SA = ANY, DA = 10.0.0.1, SP = ANY, DP = 1000, PROTO = UDP] => Allow -# Prio = 1 (High): [SA = ANY, DA = 10.1.0.1, SP = ANY, DP = 1001, PROTO = UDP] => Allow -# Prio = 1 (High): [SA = ANY, DA = 10.2.0.1, SP = ANY, DP = 1002, PROTO = UDP] => Allow -# Prio = 1 (High): [SA = ANY, DA = 10.3.0.1, SP = ANY, DP = 1003, PROTO = UDP] => Allow -p 2 firewall add default 1 #SINK0 -p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.0.0.1 32 0 65535 1000 1000 17 0xF port 0 -p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.1.0.1 32 0 65535 1001 1001 17 0xF port 0 -p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.2.0.1 32 0 65535 1002 1002 17 0xF port 0 -p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.3.0.1 32 0 65535 1003 1003 17 0xF port 0 -#p 2 firewall ls - -################################################################################ -# Local destination TCP traffic -################################################################################ -# Unknown connection => Drop -# TCP [SA = 100.0.0.10, DA = 10.0.0.1, SP = 1000, DP = 80] => socket ID = 0 -# TCP [SA = 100.1.0.10, DA = 10.1.0.1, SP = 1001, DP = 80] => socket ID = 1 -# TCP [SA = 100.2.0.10, DA = 10.2.0.1, SP = 1002, DP = 80] => socket ID = 2 -# TCP [SA = 100.3.0.10, DA = 10.3.0.1, SP = 1003, DP = 80] => socket ID = 3 -p 3 flow add default 1 #SINK1 -p 3 flow add ipv4 100.0.0.10 10.0.0.1 1000 80 6 port 0 id 0 -p 3 flow add ipv4 100.1.0.10 10.1.0.1 1001 80 6 port 0 id 1 -p 3 flow add ipv4 100.2.0.10 10.2.0.1 1002 80 6 port 0 id 2 -p 3 flow add ipv4 100.3.0.10 10.3.0.1 1003 80 6 port 0 id 3 -#p 3 flow ls diff --git a/examples/ip_pipeline/config/pipeline-to-core-mapping.py b/examples/ip_pipeline/config/pipeline-to-core-mapping.py deleted file mode 100755 index fc52b2b3..00000000 --- a/examples/ip_pipeline/config/pipeline-to-core-mapping.py +++ /dev/null @@ -1,906 +0,0 @@ -#!/usr/bin/env python -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2016 Intel Corporation - -# -# This script maps the set of pipelines identified (MASTER pipelines are -# ignored) from the input configuration file to the set of cores -# provided as input argument and creates configuration files for each of -# the mapping combinations. -# - -from __future__ import print_function -from collections import namedtuple -import argparse -import array -import errno -import itertools -import os -import re -import sys - -# default values -enable_stage0_traceout = 1 -enable_stage1_traceout = 1 -enable_stage2_traceout = 1 - -enable_stage1_fileout = 1 -enable_stage2_fileout = 1 - -Constants = namedtuple('Constants', ['MAX_CORES', 'MAX_PIPELINES']) -constants = Constants(16, 64) - -# pattern for physical core -pattern_phycore = '^(s|S)\d(c|C)[1-9][0-9]*$' -reg_phycore = re.compile(pattern_phycore) - - -def popcount(mask): - return bin(mask).count("1") - - -def len2mask(length): - if (length == 0): - return 0 - - if (length > 64): - sys.exit('error: len2mask - length %i > 64. exiting' % length) - - return int('1' * length, 2) - - -def bitstring_write(n, n_bits): - tmpstr = "" - if (n_bits > 64): - return - - i = n_bits - 1 - while (i >= 0): - cond = (n & (1 << i)) - if (cond): - print('1', end='') - tmpstr += '1' - else: - print('0', end='') - tmpstr += '0' - i -= 1 - return tmpstr - - -class Cores0: - - def __init__(self): - self.n_pipelines = 0 - - -class Cores1: - - def __init__(self): - self.pipelines = 0 - self.n_pipelines = 0 - - -class Cores2: - - def __init__(self): - self.pipelines = 0 - self.n_pipelines = 0 - self.counter = 0 - self.counter_max = 0 - self.bitpos = array.array( - "L", itertools.repeat(0, constants.MAX_PIPELINES)) - - -class Context0: - - def __init__(self): - self.cores = [Cores0() for i in range(0, constants.MAX_CORES)] - self.n_cores = 0 - self.n_pipelines = 0 - self.n_pipelines0 = 0 - self.pos = 0 - self.file_comment = "" - self.ctx1 = None - self.ctx2 = None - - def stage0_print(self): - print('printing Context0 obj') - print('c0.cores(n_pipelines) = [ ', end='') - for cores_count in range(0, constants.MAX_CORES): - print(self.cores[cores_count].n_pipelines, end=' ') - print(']') - print('c0.n_cores = %d' % self.n_cores) - print('c0.n_pipelines = %d' % self.n_pipelines) - print('c0.n_pipelines0 = %d' % self.n_pipelines0) - print('c0.pos = %d' % self.pos) - print('c0.file_comment = %s' % self.file_comment) - if (self.ctx1 is not None): - print('c0.ctx1 = ', end='') - print(repr(self.ctx1)) - else: - print('c0.ctx1 = None') - - if (self.ctx2 is not None): - print('c0.ctx2 = ', end='') - print(repr(self.ctx2)) - else: - print('c0.ctx2 = None') - - def stage0_init(self, num_cores, num_pipelines, ctx1, ctx2): - self.n_cores = num_cores - self.n_pipelines = num_pipelines - self.ctx1 = ctx1 - self.ctx2 = ctx2 - - def stage0_process(self): - # stage0 init - self.cores[0].n_pipelines = self.n_pipelines - self.n_pipelines0 = 0 - self.pos = 1 - - while True: - # go forward - while True: - if ((self.pos < self.n_cores) and (self.n_pipelines0 > 0)): - self.cores[self.pos].n_pipelines = min( - self.cores[self.pos - 1].n_pipelines, - self.n_pipelines0) - self.n_pipelines0 -= self.cores[self.pos].n_pipelines - self.pos += 1 - else: - break - - # check solution - if (self.n_pipelines0 == 0): - self.stage0_log() - self.ctx1.stage1_init(self, self.ctx2) # self is object c0 - self.ctx1.stage1_process() - - # go backward - while True: - if (self.pos == 0): - return - - self.pos -= 1 - if ((self.cores[self.pos].n_pipelines > 1) and - (self.pos != (self.n_cores - 1))): - break - - self.n_pipelines0 += self.cores[self.pos].n_pipelines - self.cores[self.pos].n_pipelines = 0 - - # rearm - self.cores[self.pos].n_pipelines -= 1 - self.n_pipelines0 += 1 - self.pos += 1 - - def stage0_log(self): - tmp_file_comment = "" - if(enable_stage0_traceout != 1): - return - - print('STAGE0: ', end='') - tmp_file_comment += 'STAGE0: ' - for cores_count in range(0, self.n_cores): - print('C%d = %d\t' - % (cores_count, - self.cores[cores_count].n_pipelines), end='') - tmp_file_comment += "C{} = {}\t".format( - cores_count, self.cores[cores_count].n_pipelines) - # end for - print('') - self.ctx1.stage0_file_comment = tmp_file_comment - self.ctx2.stage0_file_comment = tmp_file_comment - - -class Context1: - _fileTrace = None - - def __init__(self): - self.cores = [Cores1() for i in range(constants.MAX_CORES)] - self.n_cores = 0 - self.n_pipelines = 0 - self.pos = 0 - self.stage0_file_comment = "" - self.stage1_file_comment = "" - - self.ctx2 = None - self.arr_pipelines2cores = [] - - def stage1_reset(self): - for i in range(constants.MAX_CORES): - self.cores[i].pipelines = 0 - self.cores[i].n_pipelines = 0 - - self.n_cores = 0 - self.n_pipelines = 0 - self.pos = 0 - self.ctx2 = None - # clear list - del self.arr_pipelines2cores[:] - - def stage1_print(self): - print('printing Context1 obj') - print('ctx1.cores(pipelines,n_pipelines) = [ ', end='') - for cores_count in range(0, constants.MAX_CORES): - print('(%d,%d)' % (self.cores[cores_count].pipelines, - self.cores[cores_count].n_pipelines), end=' ') - print(']') - print('ctx1.n_cores = %d' % self.n_cores) - print('ctx1.n_pipelines = %d' % self.n_pipelines) - print('ctx1.pos = %d' % self.pos) - print('ctx1.stage0_file_comment = %s' % self.stage0_file_comment) - print('ctx1.stage1_file_comment = %s' % self.stage1_file_comment) - if (self.ctx2 is not None): - print('ctx1.ctx2 = ', end='') - print(self.ctx2) - else: - print('ctx1.ctx2 = None') - - def stage1_init(self, c0, ctx2): - self.stage1_reset() - self.n_cores = 0 - while (c0.cores[self.n_cores].n_pipelines > 0): - self.n_cores += 1 - - self.n_pipelines = c0.n_pipelines - self.ctx2 = ctx2 - - self.arr_pipelines2cores = [0] * self.n_pipelines - - i = 0 - while (i < self.n_cores): - self.cores[i].n_pipelines = c0.cores[i].n_pipelines - i += 1 - - def stage1_process(self): - pipelines_max = len2mask(self.n_pipelines) - while True: - pos = 0 - overlap = 0 - - if (self.cores[self.pos].pipelines == pipelines_max): - if (self.pos == 0): - return - - self.cores[self.pos].pipelines = 0 - self.pos -= 1 - continue - - self.cores[self.pos].pipelines += 1 - if (popcount(self.cores[self.pos].pipelines) != - self.cores[self.pos].n_pipelines): - continue - - overlap = 0 - pos = 0 - while (pos < self.pos): - if ((self.cores[self.pos].pipelines) & - (self.cores[pos].pipelines)): - overlap = 1 - break - pos += 1 - - if (overlap): - continue - - if ((self.pos > 0) and - ((self.cores[self.pos].n_pipelines) == - (self.cores[self.pos - 1].n_pipelines)) and - ((self.cores[self.pos].pipelines) < - (self.cores[self.pos - 1].pipelines))): - continue - - if (self.pos == self.n_cores - 1): - self.stage1_log() - self.ctx2.stage2_init(self) - self.ctx2.stage2_process() - - if (self.pos == 0): - return - - self.cores[self.pos].pipelines = 0 - self.pos -= 1 - continue - - self.pos += 1 - - def stage1_log(self): - tmp_file_comment = "" - if(enable_stage1_traceout == 1): - print('STAGE1: ', end='') - tmp_file_comment += 'STAGE1: ' - i = 0 - while (i < self.n_cores): - print('C%d = [' % i, end='') - tmp_file_comment += "C{} = [".format(i) - - j = self.n_pipelines - 1 - while (j >= 0): - cond = ((self.cores[i].pipelines) & (1 << j)) - if (cond): - print('1', end='') - tmp_file_comment += '1' - else: - print('0', end='') - tmp_file_comment += '0' - j -= 1 - - print(']\t', end='') - tmp_file_comment += ']\t' - i += 1 - - print('\n', end='') - self.stage1_file_comment = tmp_file_comment - self.ctx2.stage1_file_comment = tmp_file_comment - - # check if file traceing is enabled - if(enable_stage1_fileout != 1): - return - - # spit out the combination to file - self.stage1_process_file() - - def stage1_updateCoresInBuf(self, nPipeline, sCore): - rePipeline = self._fileTrace.arr_pipelines[nPipeline] - rePipeline = rePipeline.replace("[", "\[").replace("]", "\]") - reCore = 'core\s*=\s*((\d*)|(((s|S)\d)?(c|C)[1-9][0-9]*)).*\n' - sSubs = 'core = ' + sCore + '\n' - - reg_pipeline = re.compile(rePipeline) - search_match = reg_pipeline.search(self._fileTrace.in_buf) - - if(search_match): - pos = search_match.start() - substr1 = self._fileTrace.in_buf[:pos] - substr2 = self._fileTrace.in_buf[pos:] - substr2 = re.sub(reCore, sSubs, substr2, 1) - self._fileTrace.in_buf = substr1 + substr2 - - def stage1_process_file(self): - outFileName = os.path.join(self._fileTrace.out_path, - self._fileTrace.prefix_outfile) - outFileName += "_{}CoReS".format(self.n_cores) - - i = 0 # represents core number - while (i < self.n_cores): - j = self.n_pipelines - 1 - pipeline_idx = 0 - while(j >= 0): - cond = ((self.cores[i].pipelines) & (1 << j)) - if (cond): - # update the pipelines array to match the core - # only in case of cond match - self.arr_pipelines2cores[ - pipeline_idx] = fileTrace.in_physical_cores[i] - - j -= 1 - pipeline_idx += 1 - - i += 1 - - # update the in_buf as per the arr_pipelines2cores - for pipeline_idx in range(len(self.arr_pipelines2cores)): - outFileName += "_{}".format(self.arr_pipelines2cores[pipeline_idx]) - self.stage1_updateCoresInBuf( - pipeline_idx, self.arr_pipelines2cores[pipeline_idx]) - - # by now the in_buf is all set to be written to file - outFileName += self._fileTrace.suffix_outfile - outputFile = open(outFileName, "w") - - # write out the comments - strTruncated = ("", "(Truncated)")[self._fileTrace.ncores_truncated] - outputFile.write( - "; =============== Pipeline-to-Core Mapping ================\n" - "; Generated from file {}\n" - "; Input pipelines = {}\n" - "; Input cores = {}\n" - "; N_PIPELINES = {} N_CORES = {} {} hyper_thread = {}\n" - .format( - self._fileTrace.in_file_namepath, - fileTrace.arr_pipelines, - fileTrace.in_physical_cores, - self._fileTrace.n_pipelines, - self._fileTrace.n_cores, - strTruncated, - self._fileTrace.hyper_thread)) - - outputFile.write( - "; {stg0cmt}\n" - "; {stg1cmt}\n" - "; ========================================================\n" - "; \n" - .format( - stg0cmt=self.stage0_file_comment, - stg1cmt=self.stage1_file_comment)) - - # write buffer contents - outputFile.write(self._fileTrace.in_buf) - outputFile.flush() - outputFile.close() - - -class Context2: - _fileTrace = None - - def __init__(self): - self.cores = [Cores2() for i in range(constants.MAX_CORES)] - self.n_cores = 0 - self.n_pipelines = 0 - self.pos = 0 - self.stage0_file_comment = "" - self.stage1_file_comment = "" - self.stage2_file_comment = "" - - # each array entry is a pipeline mapped to core stored as string - # pipeline ranging from 1 to n, however stored in zero based array - self.arr2_pipelines2cores = [] - - def stage2_print(self): - print('printing Context2 obj') - print('ctx2.cores(pipelines, n_pipelines, counter, counter_max) =') - for cores_count in range(0, constants.MAX_CORES): - print('core[%d] = (%d,%d,%d,%d)' % ( - cores_count, - self.cores[cores_count].pipelines, - self.cores[cores_count].n_pipelines, - self.cores[cores_count].counter, - self.cores[cores_count].counter_max)) - - print('ctx2.n_cores = %d' % self.n_cores, end='') - print('ctx2.n_pipelines = %d' % self.n_pipelines, end='') - print('ctx2.pos = %d' % self.pos) - print('ctx2.stage0_file_comment = %s' % - self.self.stage0_file_comment) - print('ctx2.stage1_file_comment = %s' % - self.self.stage1_file_comment) - print('ctx2.stage2_file_comment = %s' % - self.self.stage2_file_comment) - - def stage2_reset(self): - for i in range(0, constants.MAX_CORES): - self.cores[i].pipelines = 0 - self.cores[i].n_pipelines = 0 - self.cores[i].counter = 0 - self.cores[i].counter_max = 0 - - for idx in range(0, constants.MAX_PIPELINES): - self.cores[i].bitpos[idx] = 0 - - self.n_cores = 0 - self.n_pipelines = 0 - self.pos = 0 - # clear list - del self.arr2_pipelines2cores[:] - - def bitpos_load(self, coreidx): - i = j = 0 - while (i < self.n_pipelines): - if ((self.cores[coreidx].pipelines) & - (1 << i)): - self.cores[coreidx].bitpos[j] = i - j += 1 - i += 1 - self.cores[coreidx].n_pipelines = j - - def bitpos_apply(self, in_buf, pos, n_pos): - out = 0 - for i in range(0, n_pos): - out |= (in_buf & (1 << i)) << (pos[i] - i) - - return out - - def stage2_init(self, ctx1): - self.stage2_reset() - self.n_cores = ctx1.n_cores - self.n_pipelines = ctx1.n_pipelines - - self.arr2_pipelines2cores = [''] * self.n_pipelines - - core_idx = 0 - while (core_idx < self.n_cores): - self.cores[core_idx].pipelines = ctx1.cores[core_idx].pipelines - - self.bitpos_load(core_idx) - core_idx += 1 - - def stage2_log(self): - tmp_file_comment = "" - if(enable_stage2_traceout == 1): - print('STAGE2: ', end='') - tmp_file_comment += 'STAGE2: ' - - for i in range(0, self.n_cores): - mask = len2mask(self.cores[i].n_pipelines) - pipelines_ht0 = self.bitpos_apply( - (~self.cores[i].counter) & mask, - self.cores[i].bitpos, - self.cores[i].n_pipelines) - - pipelines_ht1 = self.bitpos_apply( - self.cores[i].counter, - self.cores[i].bitpos, - self.cores[i].n_pipelines) - - print('C%dHT0 = [' % i, end='') - tmp_file_comment += "C{}HT0 = [".format(i) - tmp_file_comment += bitstring_write( - pipelines_ht0, self.n_pipelines) - - print(']\tC%dHT1 = [' % i, end='') - tmp_file_comment += "]\tC{}HT1 = [".format(i) - tmp_file_comment += bitstring_write( - pipelines_ht1, self.n_pipelines) - print(']\t', end='') - tmp_file_comment += ']\t' - - print('') - self.stage2_file_comment = tmp_file_comment - - # check if file traceing is enabled - if(enable_stage2_fileout != 1): - return - # spit out the combination to file - self.stage2_process_file() - - def stage2_updateCoresInBuf(self, nPipeline, sCore): - rePipeline = self._fileTrace.arr_pipelines[nPipeline] - rePipeline = rePipeline.replace("[", "\[").replace("]", "\]") - reCore = 'core\s*=\s*((\d*)|(((s|S)\d)?(c|C)[1-9][0-9]*)).*\n' - sSubs = 'core = ' + sCore + '\n' - - reg_pipeline = re.compile(rePipeline) - search_match = reg_pipeline.search(self._fileTrace.in_buf) - - if(search_match): - pos = search_match.start() - substr1 = self._fileTrace.in_buf[:pos] - substr2 = self._fileTrace.in_buf[pos:] - substr2 = re.sub(reCore, sSubs, substr2, 1) - self._fileTrace.in_buf = substr1 + substr2 - - def pipelines2cores(self, n, n_bits, nCore, bHT): - if (n_bits > 64): - return - - i = n_bits - 1 - pipeline_idx = 0 - while (i >= 0): - cond = (n & (1 << i)) - if (cond): - # update the pipelines array to match the core - # only in case of cond match - # PIPELINE0 and core 0 are reserved - if(bHT): - tmpCore = fileTrace.in_physical_cores[nCore] + 'h' - self.arr2_pipelines2cores[pipeline_idx] = tmpCore - else: - self.arr2_pipelines2cores[pipeline_idx] = \ - fileTrace.in_physical_cores[nCore] - - i -= 1 - pipeline_idx += 1 - - def stage2_process_file(self): - outFileName = os.path.join(self._fileTrace.out_path, - self._fileTrace.prefix_outfile) - outFileName += "_{}CoReS".format(self.n_cores) - - for i in range(0, self.n_cores): - mask = len2mask(self.cores[i].n_pipelines) - pipelines_ht0 = self.bitpos_apply((~self.cores[i].counter) & mask, - self.cores[i].bitpos, - self.cores[i].n_pipelines) - - pipelines_ht1 = self.bitpos_apply(self.cores[i].counter, - self.cores[i].bitpos, - self.cores[i].n_pipelines) - - # update pipelines to core mapping - self.pipelines2cores(pipelines_ht0, self.n_pipelines, i, False) - self.pipelines2cores(pipelines_ht1, self.n_pipelines, i, True) - - # update the in_buf as per the arr_pipelines2cores - for pipeline_idx in range(len(self.arr2_pipelines2cores)): - outFileName += "_{}".format( - self.arr2_pipelines2cores[pipeline_idx]) - self.stage2_updateCoresInBuf( - pipeline_idx, self.arr2_pipelines2cores[pipeline_idx]) - - # by now the in_buf is all set to be written to file - outFileName += self._fileTrace.suffix_outfile - outputFile = open(outFileName, "w") - - # write the file comments - strTruncated = ("", "(Truncated)")[self._fileTrace.ncores_truncated] - outputFile.write( - "; =============== Pipeline-to-Core Mapping ================\n" - "; Generated from file {}\n" - "; Input pipelines = {}\n" - "; Input cores = {}\n" - "; N_PIPELINES = {} N_CORES = {} {} hyper_thread = {} \n" - .format( - self._fileTrace.in_file_namepath, - fileTrace.arr_pipelines, - fileTrace.in_physical_cores, - self._fileTrace.n_pipelines, - self._fileTrace.n_cores, - strTruncated, - self._fileTrace.hyper_thread)) - - outputFile.write( - "; {stg0cmt}\n" - "; {stg1cmt}\n" - "; {stg2cmt}\n" - "; ========================================================\n" - "; \n" - .format( - stg0cmt=self.stage0_file_comment, - stg1cmt=self.stage1_file_comment, - stg2cmt=self.stage2_file_comment)) - - # write the buffer contents - outputFile.write(self._fileTrace.in_buf) - outputFile.flush() - outputFile.close() - - def stage2_process(self): - i = 0 - while(i < self.n_cores): - self.cores[i].counter_max = len2mask( - self.cores[i].n_pipelines - 1) - i += 1 - - self.pos = self.n_cores - 1 - while True: - if (self.pos == self.n_cores - 1): - self.stage2_log() - - if (self.cores[self.pos].counter == - self.cores[self.pos].counter_max): - if (self.pos == 0): - return - - self.cores[self.pos].counter = 0 - self.pos -= 1 - continue - - self.cores[self.pos].counter += 1 - if(self.pos < self.n_cores - 1): - self.pos += 1 - - -class FileTrace: - - def __init__(self, filenamepath): - self.in_file_namepath = os.path.abspath(filenamepath) - self.in_filename = os.path.basename(self.in_file_namepath) - self.in_path = os.path.dirname(self.in_file_namepath) - - filenamesplit = self.in_filename.split('.') - self.prefix_outfile = filenamesplit[0] - self.suffix_outfile = ".cfg" - - # output folder: in the same folder as input file - # create new folder in the name of input file - self.out_path = os.path.join( - os.path.abspath(os.path.dirname(__file__)), - self.prefix_outfile) - - try: - os.makedirs(self.out_path) - except OSError as excep: - if excep.errno == errno.EEXIST and os.path.isdir(self.out_path): - pass - else: - raise - - self.in_buf = None - self.arr_pipelines = [] # holds the positions of search - - self.max_cores = 15 - self.max_pipelines = 15 - - self.in_physical_cores = None - self.hyper_thread = None - - # save the num of pipelines determined from input file - self.n_pipelines = 0 - # save the num of cores input (or the truncated value) - self.n_cores = 0 - self.ncores_truncated = False - - def print_TraceFile(self): - print("self.in_file_namepath = ", self.in_file_namepath) - print("self.in_filename = ", self.in_filename) - print("self.in_path = ", self.in_path) - print("self.out_path = ", self.out_path) - print("self.prefix_outfile = ", self.prefix_outfile) - print("self.suffix_outfile = ", self.suffix_outfile) - print("self.in_buf = ", self.in_buf) - print("self.arr_pipelines =", self.arr_pipelines) - print("self.in_physical_cores", self.in_physical_cores) - print("self.hyper_thread", self.hyper_thread) - - -def process(n_cores, n_pipelines, fileTrace): - '''process and map pipelines, cores.''' - if (n_cores == 0): - sys.exit('N_CORES is 0, exiting') - - if (n_pipelines == 0): - sys.exit('N_PIPELINES is 0, exiting') - - if (n_cores > n_pipelines): - print('\nToo many cores, truncating N_CORES to N_PIPELINES') - n_cores = n_pipelines - fileTrace.ncores_truncated = True - - fileTrace.n_pipelines = n_pipelines - fileTrace.n_cores = n_cores - - strTruncated = ("", "(Truncated)")[fileTrace.ncores_truncated] - print("N_PIPELINES = {}, N_CORES = {} {}" - .format(n_pipelines, n_cores, strTruncated)) - print("---------------------------------------------------------------") - - ctx0_inst = Context0() - ctx1_inst = Context1() - ctx2_inst = Context2() - - # initialize the class variables - ctx1_inst._fileTrace = fileTrace - ctx2_inst._fileTrace = fileTrace - - ctx0_inst.stage0_init(n_cores, n_pipelines, ctx1_inst, ctx2_inst) - ctx0_inst.stage0_process() - - -def validate_core(core): - match = reg_phycore.match(core) - if(match): - return True - else: - return False - - -def validate_phycores(phy_cores): - '''validate physical cores, check if unique.''' - # eat up whitespaces - phy_cores = phy_cores.strip().split(',') - - # check if the core list is unique - if(len(phy_cores) != len(set(phy_cores))): - print('list of physical cores has duplicates') - return None - - for core in phy_cores: - if not validate_core(core): - print('invalid physical core specified.') - return None - return phy_cores - - -def scanconfigfile(fileTrace): - '''scan input file for pipelines, validate then process.''' - # open file - filetoscan = open(fileTrace.in_file_namepath, 'r') - fileTrace.in_buf = filetoscan.read() - - # reset iterator on open file - filetoscan.seek(0) - - # scan input file for pipelines - # master pipelines to be ignored - pattern_pipeline = r'\[PIPELINE\d*\]' - pattern_mastertype = r'type\s*=\s*MASTER' - - pending_pipeline = False - for line in filetoscan: - match_pipeline = re.search(pattern_pipeline, line) - match_type = re.search('type\s*=', line) - match_mastertype = re.search(pattern_mastertype, line) - - if(match_pipeline): - sPipeline = line[match_pipeline.start():match_pipeline.end()] - pending_pipeline = True - elif(match_type): - # found a type definition... - if(match_mastertype is None): - # and this is not a master pipeline... - if(pending_pipeline): - # add it to the list of pipelines to be mapped - fileTrace.arr_pipelines.append(sPipeline) - pending_pipeline = False - else: - # and this is a master pipeline... - # ignore the current and move on to next - sPipeline = "" - pending_pipeline = False - filetoscan.close() - - # validate if pipelines are unique - if(len(fileTrace.arr_pipelines) != len(set(fileTrace.arr_pipelines))): - sys.exit('Error: duplicate pipelines in input file') - - num_pipelines = len(fileTrace.arr_pipelines) - num_cores = len(fileTrace.in_physical_cores) - - print("-------------------Pipeline-to-core mapping--------------------") - print("Input pipelines = {}\nInput cores = {}" - .format(fileTrace.arr_pipelines, fileTrace.in_physical_cores)) - - # input configuration file validations goes here - if (num_cores > fileTrace.max_cores): - sys.exit('Error: number of cores specified > max_cores (%d)' % - fileTrace.max_cores) - - if (num_pipelines > fileTrace.max_pipelines): - sys.exit('Error: number of pipelines in input \ - cfg file > max_pipelines (%d)' % fileTrace.max_pipelines) - - # call process to generate pipeline-to-core mapping, trace and log - process(num_cores, num_pipelines, fileTrace) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='mappipelines') - - reqNamedGrp = parser.add_argument_group('required named args') - reqNamedGrp.add_argument( - '-i', - '--input-file', - type=argparse.FileType('r'), - help='Input config file', - required=True) - - reqNamedGrp.add_argument( - '-pc', - '--physical-cores', - type=validate_phycores, - help='''Enter available CPU cores in - format:\"<core>,<core>,...\" - where each core format: \"s<SOCKETID>c<COREID>\" - where SOCKETID={0..9}, COREID={1-99}''', - required=True) - - # add optional arguments - parser.add_argument( - '-ht', - '--hyper-thread', - help='enable/disable hyper threading. default is ON', - default='ON', - choices=['ON', 'OFF']) - - parser.add_argument( - '-nO', - '--no-output-file', - help='''disable output config file generation. - Output file generation is enabled by default''', - action="store_true") - - args = parser.parse_args() - - if(args.physical_cores is None): - parser.error("invalid physical_cores specified") - - # create object of FileTrace and initialise - fileTrace = FileTrace(args.input_file.name) - fileTrace.in_physical_cores = args.physical_cores - fileTrace.hyper_thread = args.hyper_thread - - if(fileTrace.hyper_thread == 'OFF'): - print("!!!!disabling stage2 HT!!!!") - enable_stage2_traceout = 0 - enable_stage2_fileout = 0 - elif(fileTrace.hyper_thread == 'ON'): - print("!!!!HT enabled. disabling stage1 file generation.!!!!") - enable_stage1_fileout = 0 - - if(args.no_output_file is True): - print("!!!!disabling stage1 and stage2 fileout!!!!") - enable_stage1_fileout = 0 - enable_stage2_fileout = 0 - - scanconfigfile(fileTrace) diff --git a/examples/ip_pipeline/config/tap.cfg b/examples/ip_pipeline/config/tap.cfg deleted file mode 100644 index 10d35ebb..00000000 --- a/examples/ip_pipeline/config/tap.cfg +++ /dev/null @@ -1,64 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2016 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -; ______________ ______________________ -; | | TAP0 | | -; RXQ0.0 --->| |------->|--+ | -; | | TAP1 | | br0 | -; TXQ1.0 <---| |<-------|<-+ | -; | Pass-through | | Linux Kernel | -; | (P1) | | Network Stack | -; | | TAP1 | | -; RXQ1.0 --->| |------->|--+ | -; | | TAP0 | | br0 | -; TXQ0.0 <---| |<-------|<-+ | -; |______________| |______________________| -; -; Configure Linux kernel bridge between TAP0 and TAP1 interfaces: -; [Linux]$ ifconfig TAP0 up -; [Linux]$ ifconfig TAP1 up -; [Linux]$ brctl addbr "br0" -; [Linux]$ brctl addif br0 TAP0 -; [Linux]$ brctl addif br0 TAP1 -; [Linux]$ ifconfig br0 up - -[EAL] -log_level = 0 - -[PIPELINE0] -type = MASTER -core = 0 - -[PIPELINE1] -type = PASS-THROUGH -core = 1 -pktq_in = RXQ0.0 TAP1 RXQ1.0 TAP0 -pktq_out = TAP0 TXQ1.0 TAP1 TXQ0.0 diff --git a/examples/ip_pipeline/config/tm_profile.cfg b/examples/ip_pipeline/config/tm_profile.cfg deleted file mode 100644 index 2dfb215e..00000000 --- a/examples/ip_pipeline/config/tm_profile.cfg +++ /dev/null @@ -1,105 +0,0 @@ -; BSD LICENSE -; -; Copyright(c) 2010-2014 Intel Corporation. All rights reserved. -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -; This file enables the following hierarchical scheduler configuration for each -; 10GbE output port: -; * Single subport (subport 0): -; - Subport rate set to 100% of port rate -; - Each of the 4 traffic classes has rate set to 100% of port rate -; * 4K pipes per subport 0 (pipes 0 .. 4095) with identical configuration: -; - Pipe rate set to 1/4K of port rate -; - Each of the 4 traffic classes has rate set to 100% of pipe rate -; - Within each traffic class, the byte-level WRR weights for the 4 queues -; are set to 1:1:1:1 -; -; For more details, please refer to chapter "Quality of Service (QoS) Framework" -; of Data Plane Development Kit (DPDK) Programmer's Guide. - -; Port configuration -[port] -frame overhead = 24 ; frame overhead = Preamble (7) + SFD (1) + FCS (4) + IFG (12) -mtu = 1522; mtu = Q-in-Q MTU (FCS not included) -number of subports per port = 1 -number of pipes per subport = 4096 -queue sizes = 64 64 64 64 - -; Subport configuration -[subport 0] -tb rate = 1250000000 ; Bytes per second -tb size = 1000000 ; Bytes - -tc 0 rate = 1250000000 ; Bytes per second -tc 1 rate = 1250000000 ; Bytes per second -tc 2 rate = 1250000000 ; Bytes per second -tc 3 rate = 1250000000 ; Bytes per second -tc period = 10 ; Milliseconds - -pipe 0-4095 = 0 ; These pipes are configured with pipe profile 0 - -; Pipe configuration -[pipe profile 0] -tb rate = 305175 ; Bytes per second -tb size = 1000000 ; Bytes - -tc 0 rate = 305175 ; Bytes per second -tc 1 rate = 305175 ; Bytes per second -tc 2 rate = 305175 ; Bytes per second -tc 3 rate = 305175 ; Bytes per second -tc period = 40 ; Milliseconds - -tc 3 oversubscription weight = 1 - -tc 0 wrr weights = 1 1 1 1 -tc 1 wrr weights = 1 1 1 1 -tc 2 wrr weights = 1 1 1 1 -tc 3 wrr weights = 1 1 1 1 - -; RED params per traffic class and color (Green / Yellow / Red) -[red] -tc 0 wred min = 48 40 32 -tc 0 wred max = 64 64 64 -tc 0 wred inv prob = 10 10 10 -tc 0 wred weight = 9 9 9 - -tc 1 wred min = 48 40 32 -tc 1 wred max = 64 64 64 -tc 1 wred inv prob = 10 10 10 -tc 1 wred weight = 9 9 9 - -tc 2 wred min = 48 40 32 -tc 2 wred max = 64 64 64 -tc 2 wred inv prob = 10 10 10 -tc 2 wred weight = 9 9 9 - -tc 3 wred min = 48 40 32 -tc 3 wred max = 64 64 64 -tc 3 wred inv prob = 10 10 10 -tc 3 wred weight = 9 9 9 diff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c deleted file mode 100644 index 86d1191a..00000000 --- a/examples/ip_pipeline/config_check.c +++ /dev/null @@ -1,488 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <stdio.h> - -#include <rte_ip.h> - -#include "app.h" - -static void -check_mempools(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_mempools; i++) { - struct app_mempool_params *p = &app->mempool_params[i]; - - APP_CHECK((p->pool_size > 0), - "Mempool %s size is 0\n", p->name); - - APP_CHECK((p->cache_size > 0), - "Mempool %s cache size is 0\n", p->name); - - APP_CHECK(rte_is_power_of_2(p->cache_size), - "Mempool %s cache size not a power of 2\n", p->name); - } -} - -static inline uint32_t -link_rxq_used(struct app_link_params *link, uint32_t q_id) -{ - uint32_t i; - - if ((link->arp_q == q_id) || - (link->tcp_syn_q == q_id) || - (link->ip_local_q == q_id) || - (link->tcp_local_q == q_id) || - (link->udp_local_q == q_id) || - (link->sctp_local_q == q_id)) - return 1; - - for (i = 0; i < link->n_rss_qs; i++) - if (link->rss_qs[i] == q_id) - return 1; - - return 0; -} - -static void -check_links(struct app_params *app) -{ - uint32_t i; - - /* Check that number of links matches the port mask */ - if (app->port_mask) { - uint32_t n_links_port_mask = - __builtin_popcountll(app->port_mask); - - APP_CHECK((app->n_links == n_links_port_mask), - "Not enough links provided in the PORT_MASK\n"); - } - - for (i = 0; i < app->n_links; i++) { - struct app_link_params *link = &app->link_params[i]; - uint32_t rxq_max, n_rxq, n_txq, link_id, i; - - APP_PARAM_GET_ID(link, "LINK", link_id); - - /* Check that link RXQs are contiguous */ - rxq_max = 0; - if (link->arp_q > rxq_max) - rxq_max = link->arp_q; - if (link->tcp_syn_q > rxq_max) - rxq_max = link->tcp_syn_q; - if (link->ip_local_q > rxq_max) - rxq_max = link->ip_local_q; - if (link->tcp_local_q > rxq_max) - rxq_max = link->tcp_local_q; - if (link->udp_local_q > rxq_max) - rxq_max = link->udp_local_q; - if (link->sctp_local_q > rxq_max) - rxq_max = link->sctp_local_q; - for (i = 0; i < link->n_rss_qs; i++) - if (link->rss_qs[i] > rxq_max) - rxq_max = link->rss_qs[i]; - - for (i = 1; i <= rxq_max; i++) - APP_CHECK((link_rxq_used(link, i)), - "%s RXQs are not contiguous (A)\n", link->name); - - n_rxq = app_link_get_n_rxq(app, link); - - APP_CHECK((n_rxq), "%s does not have any RXQ\n", link->name); - - APP_CHECK((n_rxq == rxq_max + 1), - "%s RXQs are not contiguous (B)\n", link->name); - - for (i = 0; i < n_rxq; i++) { - char name[APP_PARAM_NAME_SIZE]; - int pos; - - sprintf(name, "RXQ%" PRIu32 ".%" PRIu32, - link_id, i); - pos = APP_PARAM_FIND(app->hwq_in_params, name); - APP_CHECK((pos >= 0), - "%s RXQs are not contiguous (C)\n", link->name); - } - - /* Check that link TXQs are contiguous */ - n_txq = app_link_get_n_txq(app, link); - - APP_CHECK((n_txq), "%s does not have any TXQ\n", link->name); - - for (i = 0; i < n_txq; i++) { - char name[APP_PARAM_NAME_SIZE]; - int pos; - - sprintf(name, "TXQ%" PRIu32 ".%" PRIu32, - link_id, i); - pos = APP_PARAM_FIND(app->hwq_out_params, name); - APP_CHECK((pos >= 0), - "%s TXQs are not contiguous\n", link->name); - } - } -} - -static void -check_rxqs(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_hwq_in; i++) { - struct app_pktq_hwq_in_params *p = &app->hwq_in_params[i]; - uint32_t n_readers = app_rxq_get_readers(app, p); - - APP_CHECK((p->size > 0), - "%s size is 0\n", p->name); - - APP_CHECK((rte_is_power_of_2(p->size)), - "%s size is not a power of 2\n", p->name); - - APP_CHECK((p->burst > 0), - "%s burst size is 0\n", p->name); - - APP_CHECK((p->burst <= p->size), - "%s burst size is bigger than its size\n", p->name); - - APP_CHECK((n_readers != 0), - "%s has no reader\n", p->name); - - APP_CHECK((n_readers == 1), - "%s has more than one reader\n", p->name); - } -} - -static void -check_txqs(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_hwq_out; i++) { - struct app_pktq_hwq_out_params *p = &app->hwq_out_params[i]; - uint32_t n_writers = app_txq_get_writers(app, p); - - APP_CHECK((p->size > 0), - "%s size is 0\n", p->name); - - APP_CHECK((rte_is_power_of_2(p->size)), - "%s size is not a power of 2\n", p->name); - - APP_CHECK((p->burst > 0), - "%s burst size is 0\n", p->name); - - APP_CHECK((p->burst <= p->size), - "%s burst size is bigger than its size\n", p->name); - - APP_CHECK((n_writers != 0), - "%s has no writer\n", p->name); - - APP_CHECK((n_writers == 1), - "%s has more than one writer\n", p->name); - } -} - -static void -check_swqs(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_swq; i++) { - struct app_pktq_swq_params *p = &app->swq_params[i]; - uint32_t n_readers = app_swq_get_readers(app, p); - uint32_t n_writers = app_swq_get_writers(app, p); - uint32_t n_flags; - - APP_CHECK((p->size > 0), - "%s size is 0\n", p->name); - - APP_CHECK((rte_is_power_of_2(p->size)), - "%s size is not a power of 2\n", p->name); - - APP_CHECK((p->burst_read > 0), - "%s read burst size is 0\n", p->name); - - APP_CHECK((p->burst_read <= p->size), - "%s read burst size is bigger than its size\n", - p->name); - - APP_CHECK((p->burst_write > 0), - "%s write burst size is 0\n", p->name); - - APP_CHECK((p->burst_write <= p->size), - "%s write burst size is bigger than its size\n", - p->name); - - APP_CHECK((n_readers != 0), - "%s has no reader\n", p->name); - - if (n_readers > 1) - APP_LOG(app, LOW, "%s has more than one reader", p->name); - - APP_CHECK((n_writers != 0), - "%s has no writer\n", p->name); - - if (n_writers > 1) - APP_LOG(app, LOW, "%s has more than one writer", p->name); - - n_flags = p->ipv4_frag + p->ipv6_frag + p->ipv4_ras + p->ipv6_ras; - - APP_CHECK((n_flags < 2), - "%s has more than one fragmentation or reassembly mode enabled\n", - p->name); - - APP_CHECK((!((n_readers > 1) && (n_flags == 1))), - "%s has more than one reader when fragmentation or reassembly" - " mode enabled\n", - p->name); - - APP_CHECK((!((n_writers > 1) && (n_flags == 1))), - "%s has more than one writer when fragmentation or reassembly" - " mode enabled\n", - p->name); - - n_flags = p->ipv4_ras + p->ipv6_ras; - - APP_CHECK((!((p->dropless == 1) && (n_flags == 1))), - "%s has dropless when reassembly mode enabled\n", p->name); - - n_flags = p->ipv4_frag + p->ipv6_frag; - - if (n_flags == 1) { - uint16_t ip_hdr_size = (p->ipv4_frag) ? sizeof(struct ipv4_hdr) : - sizeof(struct ipv6_hdr); - - APP_CHECK((p->mtu > ip_hdr_size), - "%s mtu size is smaller than ip header\n", p->name); - - APP_CHECK((!((p->mtu - ip_hdr_size) % 8)), - "%s mtu size is incorrect\n", p->name); - } - } -} - -static void -check_tms(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_tm; i++) { - struct app_pktq_tm_params *p = &app->tm_params[i]; - uint32_t n_readers = app_tm_get_readers(app, p); - uint32_t n_writers = app_tm_get_writers(app, p); - - APP_CHECK((n_readers != 0), - "%s has no reader\n", p->name); - - APP_CHECK((n_readers == 1), - "%s has more than one reader\n", p->name); - - APP_CHECK((n_writers != 0), - "%s has no writer\n", p->name); - - APP_CHECK((n_writers == 1), - "%s has more than one writer\n", p->name); - } -} - -static void -check_taps(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_tap; i++) { - struct app_pktq_tap_params *p = &app->tap_params[i]; - uint32_t n_readers = app_tap_get_readers(app, p); - uint32_t n_writers = app_tap_get_writers(app, p); - - APP_CHECK((n_readers != 0), - "%s has no reader\n", p->name); - - APP_CHECK((n_readers == 1), - "%s has more than one reader\n", p->name); - - APP_CHECK((n_writers != 0), - "%s has no writer\n", p->name); - - APP_CHECK((n_writers == 1), - "%s has more than one writer\n", p->name); - - APP_CHECK((p->burst_read > 0), - "%s read burst size is 0\n", p->name); - - APP_CHECK((p->burst_write > 0), - "%s write burst size is 0\n", p->name); - } -} - -static void -check_knis(struct app_params *app) { - uint32_t i; - - for (i = 0; i < app->n_pktq_kni; i++) { - struct app_pktq_kni_params *p = &app->kni_params[i]; - uint32_t n_readers = app_kni_get_readers(app, p); - uint32_t n_writers = app_kni_get_writers(app, p); - - APP_CHECK((n_readers != 0), - "%s has no reader\n", p->name); - - APP_CHECK((n_readers == 1), - "%s has more than one reader\n", p->name); - - APP_CHECK((n_writers != 0), - "%s has no writer\n", p->name); - - APP_CHECK((n_writers == 1), - "%s has more than one writer\n", p->name); - } -} - -static void -check_sources(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_source; i++) { - struct app_pktq_source_params *p = &app->source_params[i]; - uint32_t n_readers = app_source_get_readers(app, p); - - APP_CHECK((n_readers != 0), - "%s has no reader\n", p->name); - - APP_CHECK((n_readers == 1), - "%s has more than one reader\n", p->name); - } -} - -static void -check_sinks(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_sink; i++) { - struct app_pktq_sink_params *p = &app->sink_params[i]; - uint32_t n_writers = app_sink_get_writers(app, p); - - APP_CHECK((n_writers != 0), - "%s has no writer\n", p->name); - - APP_CHECK((n_writers == 1), - "%s has more than one writer\n", p->name); - } -} - -static void -check_msgqs(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_msgq; i++) { - struct app_msgq_params *p = &app->msgq_params[i]; - uint32_t n_readers = app_msgq_get_readers(app, p); - uint32_t n_writers = app_msgq_get_writers(app, p); - uint32_t msgq_req_pipeline, msgq_rsp_pipeline; - uint32_t msgq_req_core, msgq_rsp_core; - - APP_CHECK((p->size > 0), - "%s size is 0\n", p->name); - - APP_CHECK((rte_is_power_of_2(p->size)), - "%s size is not a power of 2\n", p->name); - - msgq_req_pipeline = (strncmp(p->name, "MSGQ-REQ-PIPELINE", - strlen("MSGQ-REQ-PIPELINE")) == 0); - - msgq_rsp_pipeline = (strncmp(p->name, "MSGQ-RSP-PIPELINE", - strlen("MSGQ-RSP-PIPELINE")) == 0); - - msgq_req_core = (strncmp(p->name, "MSGQ-REQ-CORE", - strlen("MSGQ-REQ-CORE")) == 0); - - msgq_rsp_core = (strncmp(p->name, "MSGQ-RSP-CORE", - strlen("MSGQ-RSP-CORE")) == 0); - - if ((msgq_req_pipeline == 0) && - (msgq_rsp_pipeline == 0) && - (msgq_req_core == 0) && - (msgq_rsp_core == 0)) { - APP_CHECK((n_readers != 0), - "%s has no reader\n", p->name); - - APP_CHECK((n_readers == 1), - "%s has more than one reader\n", p->name); - - APP_CHECK((n_writers != 0), - "%s has no writer\n", p->name); - - APP_CHECK((n_writers == 1), - "%s has more than one writer\n", p->name); - } - - if (msgq_req_pipeline) { - struct app_pipeline_params *pipeline; - uint32_t pipeline_id; - - APP_PARAM_GET_ID(p, "MSGQ-REQ-PIPELINE", pipeline_id); - - APP_PARAM_FIND_BY_ID(app->pipeline_params, - "PIPELINE", - pipeline_id, - pipeline); - - APP_CHECK((pipeline != NULL), - "%s is not associated with a valid pipeline\n", - p->name); - } - - if (msgq_rsp_pipeline) { - struct app_pipeline_params *pipeline; - uint32_t pipeline_id; - - APP_PARAM_GET_ID(p, "MSGQ-RSP-PIPELINE", pipeline_id); - - APP_PARAM_FIND_BY_ID(app->pipeline_params, - "PIPELINE", - pipeline_id, - pipeline); - - APP_CHECK((pipeline != NULL), - "%s is not associated with a valid pipeline\n", - p->name); - } - } -} - -static void -check_pipelines(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - - APP_CHECK((p->n_msgq_in == p->n_msgq_out), - "%s number of input MSGQs does not match " - "the number of output MSGQs\n", p->name); - } -} - -int -app_config_check(struct app_params *app) -{ - check_mempools(app); - check_links(app); - check_rxqs(app); - check_txqs(app); - check_swqs(app); - check_tms(app); - check_taps(app); - check_knis(app); - check_sources(app); - check_sinks(app); - check_msgqs(app); - check_pipelines(app); - - return 0; -} diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c deleted file mode 100644 index e90499e7..00000000 --- a/examples/ip_pipeline/config_parse.c +++ /dev/null @@ -1,3395 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <getopt.h> -#include <errno.h> -#include <stdarg.h> -#include <string.h> -#include <libgen.h> -#include <unistd.h> -#include <sys/wait.h> - -#include <rte_errno.h> -#include <rte_cfgfile.h> -#include <rte_string_fns.h> - -#include "app.h" -#include "parser.h" - -/** - * Default config values - **/ - -static struct app_params app_params_default = { - .config_file = "./config/ip_pipeline.cfg", - .log_level = APP_LOG_LEVEL_HIGH, - .port_mask = 0, - - .eal_params = { - .channels = 4, - }, -}; - -static const struct app_mempool_params mempool_params_default = { - .parsed = 0, - .buffer_size = 2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM, - .pool_size = 32 * 1024, - .cache_size = 256, - .cpu_socket_id = 0, -}; - -static const struct app_link_params link_params_default = { - .parsed = 0, - .pmd_id = 0, - .arp_q = 0, - .tcp_syn_q = 0, - .ip_local_q = 0, - .tcp_local_q = 0, - .udp_local_q = 0, - .sctp_local_q = 0, - .rss_qs = {0}, - .n_rss_qs = 0, - .rss_proto_ipv4 = ETH_RSS_IPV4, - .rss_proto_ipv6 = ETH_RSS_IPV6, - .rss_proto_l2 = 0, - .state = 0, - .ip = 0, - .depth = 0, - .mac_addr = 0, - .pci_bdf = {0}, - - .conf = { - .link_speeds = 0, - .rxmode = { - .mq_mode = ETH_MQ_RX_NONE, - - .ignore_offload_bitfield = 1, - .offloads = DEV_RX_OFFLOAD_CRC_STRIP, - - .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */ - .split_hdr_size = 0, /* Header split buffer size */ - }, - .rx_adv_conf = { - .rss_conf = { - .rss_key = NULL, - .rss_key_len = 40, - .rss_hf = 0, - }, - }, - .txmode = { - .mq_mode = ETH_MQ_TX_NONE, - }, - .lpbk_mode = 0, - }, - - .promisc = 1, -}; - -static const struct app_pktq_hwq_in_params default_hwq_in_params = { - .parsed = 0, - .mempool_id = 0, - .size = 128, - .burst = 32, - - .conf = { - .rx_thresh = { - .pthresh = 8, - .hthresh = 8, - .wthresh = 4, - }, - .rx_free_thresh = 64, - .rx_drop_en = 0, - .rx_deferred_start = 0, - } -}; - -static const struct app_pktq_hwq_out_params default_hwq_out_params = { - .parsed = 0, - .size = 512, - .burst = 32, - .dropless = 0, - .n_retries = 0, - - .conf = { - .tx_thresh = { - .pthresh = 36, - .hthresh = 0, - .wthresh = 0, - }, - .tx_rs_thresh = 0, - .tx_free_thresh = 0, - .txq_flags = ETH_TXQ_FLAGS_IGNORE, - .tx_deferred_start = 0, - } -}; - -static const struct app_pktq_swq_params default_swq_params = { - .parsed = 0, - .size = 256, - .burst_read = 32, - .burst_write = 32, - .dropless = 0, - .n_retries = 0, - .cpu_socket_id = 0, - .ipv4_frag = 0, - .ipv6_frag = 0, - .ipv4_ras = 0, - .ipv6_ras = 0, - .mtu = 0, - .metadata_size = 0, - .mempool_direct_id = 0, - .mempool_indirect_id = 0, -}; - -struct app_pktq_tm_params default_tm_params = { - .parsed = 0, - .file_name = "./config/tm_profile.cfg", - .burst_read = 24, - .burst_write = 32, -}; - -struct app_pktq_tap_params default_tap_params = { - .parsed = 0, - .burst_read = 32, - .burst_write = 32, - .dropless = 0, - .n_retries = 0, - .mempool_id = 0, -}; - -struct app_pktq_kni_params default_kni_params = { - .parsed = 0, - .socket_id = 0, - .core_id = 0, - .hyper_th_id = 0, - .force_bind = 0, - - .mempool_id = 0, - .burst_read = 32, - .burst_write = 32, - .dropless = 0, - .n_retries = 0, -}; - -struct app_pktq_source_params default_source_params = { - .parsed = 0, - .mempool_id = 0, - .burst = 32, - .file_name = "./config/packets.pcap", - .n_bytes_per_pkt = 0, -}; - -struct app_pktq_sink_params default_sink_params = { - .parsed = 0, - .file_name = NULL, - .n_pkts_to_dump = 0, -}; - -struct app_msgq_params default_msgq_params = { - .parsed = 0, - .size = 64, - .cpu_socket_id = 0, -}; - -struct app_pipeline_params default_pipeline_params = { - .parsed = 0, - .socket_id = 0, - .core_id = 0, - .hyper_th_id = 0, - .n_pktq_in = 0, - .n_pktq_out = 0, - .n_msgq_in = 0, - .n_msgq_out = 0, - .timer_period = 1, - .n_args = 0, -}; - -static const char app_usage[] = - "Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] [-p PORT_MASK] " - "[-l LOG_LEVEL] [--preproc PREPROCESSOR] [--preproc-args ARGS]\n" - "\n" - "Arguments:\n" - "\t-f CONFIG_FILE: Default config file is %s\n" - "\t-p PORT_MASK: Mask of NIC port IDs in hex format (generated from " - "config file when not provided)\n" - "\t-s SCRIPT_FILE: No CLI script file is run when not specified\n" - "\t-l LOG_LEVEL: 0 = NONE, 1 = HIGH PRIO (default), 2 = LOW PRIO\n" - "\t--preproc PREPROCESSOR: Configuration file pre-processor\n" - "\t--preproc-args ARGS: Arguments to be passed to pre-processor\n" - "\n"; - -static void -app_print_usage(char *prgname) -{ - rte_exit(0, app_usage, prgname, app_params_default.config_file); -} - -#define APP_PARAM_ADD(set, key) \ -({ \ - ssize_t pos = APP_PARAM_FIND(set, key); \ - ssize_t size = RTE_DIM(set); \ - \ - if (pos < 0) { \ - for (pos = 0; pos < size; pos++) { \ - if (!APP_PARAM_VALID(&((set)[pos]))) \ - break; \ - } \ - \ - APP_CHECK((pos < size), \ - "Parse error: size of %s is limited to %u elements",\ - #set, (uint32_t) size); \ - \ - (set)[pos].name = strdup(key); \ - APP_CHECK(((set)[pos].name), \ - "Parse error: no free memory"); \ - } \ - pos; \ -}) - -#define APP_PARAM_ADD_LINK_FOR_RXQ(app, rxq_name) \ -({ \ - char link_name[APP_PARAM_NAME_SIZE]; \ - ssize_t link_param_pos; \ - uint32_t link_id, queue_id; \ - \ - sscanf((rxq_name), "RXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\ - sprintf(link_name, "LINK%" PRIu32, link_id); \ - link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ - link_param_pos; \ -}) - -#define APP_PARAM_ADD_LINK_FOR_TXQ(app, txq_name) \ -({ \ - char link_name[APP_PARAM_NAME_SIZE]; \ - ssize_t link_param_pos; \ - uint32_t link_id, queue_id; \ - \ - sscanf((txq_name), "TXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\ - sprintf(link_name, "LINK%" PRIu32, link_id); \ - link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ - link_param_pos; \ -}) - -#define APP_PARAM_ADD_LINK_FOR_TM(app, tm_name) \ -({ \ - char link_name[APP_PARAM_NAME_SIZE]; \ - ssize_t link_param_pos; \ - uint32_t link_id; \ - \ - sscanf((tm_name), "TM%" SCNu32, &link_id); \ - sprintf(link_name, "LINK%" PRIu32, link_id); \ - link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ - link_param_pos; \ -}) - -#define APP_PARAM_ADD_LINK_FOR_KNI(app, kni_name) \ -({ \ - char link_name[APP_PARAM_NAME_SIZE]; \ - ssize_t link_param_pos; \ - uint32_t link_id; \ - \ - sscanf((kni_name), "KNI%" SCNu32, &link_id); \ - sprintf(link_name, "LINK%" PRIu32, link_id); \ - link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ - link_param_pos; \ -}) - -#define PARSE_CHECK_DUPLICATE_SECTION(obj) \ -do { \ - APP_CHECK(((obj)->parsed == 0), \ - "Parse error: duplicate \"%s\" section", (obj)->name); \ - (obj)->parsed++; \ -} while (0) - -#define PARSE_CHECK_DUPLICATE_SECTION_EAL(obj) \ -do { \ - APP_CHECK(((obj)->parsed == 0), \ - "Parse error: duplicate \"%s\" section", "EAL"); \ - (obj)->parsed++; \ -} while (0) - -#define PARSE_ERROR(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"", section, entry) - -#define PARSE_ERROR_MESSAGE(exp, section, entry, message) \ -APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": %s", \ - section, entry, message) - -#define PARSE_ERROR_NO_ELEMENTS(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \ - "no elements detected", \ - section, entry) - -#define PARSE_ERROR_TOO_MANY_ELEMENTS(exp, section, entry, max) \ -APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \ - "maximum number of elements allowed is %u", \ - section, entry, max) - -#define PARSE_ERROR_INVALID_ELEMENT(exp, section, entry, value) \ -APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \ - "Invalid element value \"%s\"", \ - section, entry, value) - -#define PARSE_ERROR_MALLOC(exp) \ -APP_CHECK(exp, "Parse error: no free memory") - -#define PARSE_ERROR_SECTION(exp, section) \ -APP_CHECK(exp, "Parse error in section \"%s\"", section) - -#define PARSE_ERROR_SECTION_NO_ENTRIES(exp, section) \ -APP_CHECK(exp, "Parse error in section \"%s\": no entries", section) - -#define PARSE_WARNING_IGNORED(exp, section, entry) \ -do \ -if (!(exp)) \ - fprintf(stderr, "Parse warning in section \"%s\": " \ - "entry \"%s\" is ignored", section, entry); \ -while (0) - -#define PARSE_ERROR_INVALID(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"",\ - section, entry) - -#define PARSE_ERROR_DUPLICATE(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"", \ - section, entry) - -static int -validate_name(const char *name, const char *prefix, int num) -{ - size_t i, j; - - for (i = 0; (name[i] != '\0') && (prefix[i] != '\0'); i++) { - if (name[i] != prefix[i]) - return -1; - } - - if (prefix[i] != '\0') - return -1; - - if (!num) { - if (name[i] != '\0') - return -1; - else - return 0; - } - - if (num == 2) { - j = skip_digits(&name[i]); - i += j; - if ((j == 0) || (name[i] != '.')) - return -1; - i++; - } - - if (num == 1) { - j = skip_digits(&name[i]); - i += j; - if ((j == 0) || (name[i] != '\0')) - return -1; - } - - return 0; -} - -static void -parse_eal(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_eal_params *p = &app->eal_params; - struct rte_cfgfile_entry *entries; - int n_entries, i; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - PARSE_CHECK_DUPLICATE_SECTION_EAL(p); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *entry = &entries[i]; - - /* coremask */ - if (strcmp(entry->name, "c") == 0) { - PARSE_WARNING_IGNORED(0, section_name, entry->name); - continue; - } - - /* corelist */ - if (strcmp(entry->name, "l") == 0) { - PARSE_WARNING_IGNORED(0, section_name, entry->name); - continue; - } - - /* coremap */ - if (strcmp(entry->name, "lcores") == 0) { - PARSE_ERROR_DUPLICATE((p->coremap == NULL), - section_name, - entry->name); - p->coremap = strdup(entry->value); - continue; - } - - /* master_lcore */ - if (strcmp(entry->name, "master_lcore") == 0) { - int status; - - PARSE_ERROR_DUPLICATE((p->master_lcore_present == 0), - section_name, - entry->name); - p->master_lcore_present = 1; - - status = parser_read_uint32(&p->master_lcore, - entry->value); - PARSE_ERROR((status == 0), section_name, entry->name); - continue; - } - - /* channels */ - if (strcmp(entry->name, "n") == 0) { - int status; - - PARSE_ERROR_DUPLICATE((p->channels_present == 0), - section_name, - entry->name); - p->channels_present = 1; - - status = parser_read_uint32(&p->channels, entry->value); - PARSE_ERROR((status == 0), section_name, entry->name); - continue; - } - - /* memory */ - if (strcmp(entry->name, "m") == 0) { - int status; - - PARSE_ERROR_DUPLICATE((p->memory_present == 0), - section_name, - entry->name); - p->memory_present = 1; - - status = parser_read_uint32(&p->memory, entry->value); - PARSE_ERROR((status == 0), section_name, entry->name); - continue; - } - - /* ranks */ - if (strcmp(entry->name, "r") == 0) { - int status; - - PARSE_ERROR_DUPLICATE((p->ranks_present == 0), - section_name, - entry->name); - p->ranks_present = 1; - - status = parser_read_uint32(&p->ranks, entry->value); - PARSE_ERROR((status == 0), section_name, entry->name); - continue; - } - - /* pci_blacklist */ - if ((strcmp(entry->name, "pci_blacklist") == 0) || - (strcmp(entry->name, "b") == 0)) { - uint32_t i; - - for (i = 0; i < APP_MAX_LINKS; i++) { - if (p->pci_blacklist[i]) - continue; - - p->pci_blacklist[i] = - strdup(entry->value); - PARSE_ERROR_MALLOC(p->pci_blacklist[i]); - - break; - } - - PARSE_ERROR_MESSAGE((i < APP_MAX_LINKS), - section_name, entry->name, - "too many elements"); - continue; - } - - /* pci_whitelist */ - if ((strcmp(entry->name, "pci_whitelist") == 0) || - (strcmp(entry->name, "w") == 0)) { - uint32_t i; - - PARSE_ERROR_MESSAGE((app->port_mask != 0), - section_name, entry->name, "entry to be " - "generated by the application (port_mask " - "not provided)"); - - for (i = 0; i < APP_MAX_LINKS; i++) { - if (p->pci_whitelist[i]) - continue; - - p->pci_whitelist[i] = strdup(entry->value); - PARSE_ERROR_MALLOC(p->pci_whitelist[i]); - - break; - } - - PARSE_ERROR_MESSAGE((i < APP_MAX_LINKS), - section_name, entry->name, - "too many elements"); - continue; - } - - /* vdev */ - if (strcmp(entry->name, "vdev") == 0) { - uint32_t i; - - for (i = 0; i < APP_MAX_LINKS; i++) { - if (p->vdev[i]) - continue; - - p->vdev[i] = strdup(entry->value); - PARSE_ERROR_MALLOC(p->vdev[i]); - - break; - } - - PARSE_ERROR_MESSAGE((i < APP_MAX_LINKS), - section_name, entry->name, - "too many elements"); - continue; - } - - /* vmware_tsc_map */ - if (strcmp(entry->name, "vmware_tsc_map") == 0) { - int val; - - PARSE_ERROR_DUPLICATE((p->vmware_tsc_map_present == 0), - section_name, - entry->name); - p->vmware_tsc_map_present = 1; - - val = parser_read_arg_bool(entry->value); - PARSE_ERROR((val >= 0), section_name, entry->name); - p->vmware_tsc_map = val; - continue; - } - - /* proc_type */ - if (strcmp(entry->name, "proc_type") == 0) { - PARSE_ERROR_DUPLICATE((p->proc_type == NULL), - section_name, - entry->name); - p->proc_type = strdup(entry->value); - continue; - } - - /* syslog */ - if (strcmp(entry->name, "syslog") == 0) { - PARSE_ERROR_DUPLICATE((p->syslog == NULL), - section_name, - entry->name); - p->syslog = strdup(entry->value); - continue; - } - - /* log_level */ - if (strcmp(entry->name, "log_level") == 0) { - int status; - - PARSE_ERROR_DUPLICATE((p->log_level_present == 0), - section_name, - entry->name); - p->log_level_present = 1; - - status = parser_read_uint32(&p->log_level, - entry->value); - PARSE_ERROR((status == 0), section_name, entry->name); - continue; - } - - /* version */ - if (strcmp(entry->name, "v") == 0) { - int val; - - PARSE_ERROR_DUPLICATE((p->version_present == 0), - section_name, - entry->name); - p->version_present = 1; - - val = parser_read_arg_bool(entry->value); - PARSE_ERROR((val >= 0), section_name, entry->name); - p->version = val; - continue; - } - - /* help */ - if ((strcmp(entry->name, "help") == 0) || - (strcmp(entry->name, "h") == 0)) { - int val; - - PARSE_ERROR_DUPLICATE((p->help_present == 0), - section_name, - entry->name); - p->help_present = 1; - - val = parser_read_arg_bool(entry->value); - PARSE_ERROR((val >= 0), section_name, entry->name); - p->help = val; - continue; - } - - /* no_huge */ - if (strcmp(entry->name, "no_huge") == 0) { - int val; - - PARSE_ERROR_DUPLICATE((p->no_huge_present == 0), - section_name, - entry->name); - p->no_huge_present = 1; - - val = parser_read_arg_bool(entry->value); - PARSE_ERROR((val >= 0), section_name, entry->name); - p->no_huge = val; - continue; - } - - /* no_pci */ - if (strcmp(entry->name, "no_pci") == 0) { - int val; - - PARSE_ERROR_DUPLICATE((p->no_pci_present == 0), - section_name, - entry->name); - p->no_pci_present = 1; - - val = parser_read_arg_bool(entry->value); - PARSE_ERROR((val >= 0), section_name, entry->name); - p->no_pci = val; - continue; - } - - /* no_hpet */ - if (strcmp(entry->name, "no_hpet") == 0) { - int val; - - PARSE_ERROR_DUPLICATE((p->no_hpet_present == 0), - section_name, - entry->name); - p->no_hpet_present = 1; - - val = parser_read_arg_bool(entry->value); - PARSE_ERROR((val >= 0), section_name, entry->name); - p->no_hpet = val; - continue; - } - - /* no_shconf */ - if (strcmp(entry->name, "no_shconf") == 0) { - int val; - - PARSE_ERROR_DUPLICATE((p->no_shconf_present == 0), - section_name, - entry->name); - p->no_shconf_present = 1; - - val = parser_read_arg_bool(entry->value); - PARSE_ERROR((val >= 0), section_name, entry->name); - p->no_shconf = val; - continue; - } - - /* add_driver */ - if (strcmp(entry->name, "d") == 0) { - PARSE_ERROR_DUPLICATE((p->add_driver == NULL), - section_name, - entry->name); - p->add_driver = strdup(entry->value); - continue; - } - - /* socket_mem */ - if (strcmp(entry->name, "socket_mem") == 0) { - PARSE_ERROR_DUPLICATE((p->socket_mem == NULL), - section_name, - entry->name); - p->socket_mem = strdup(entry->value); - continue; - } - - /* huge_dir */ - if (strcmp(entry->name, "huge_dir") == 0) { - PARSE_ERROR_DUPLICATE((p->huge_dir == NULL), - section_name, - entry->name); - p->huge_dir = strdup(entry->value); - continue; - } - - /* file_prefix */ - if (strcmp(entry->name, "file_prefix") == 0) { - PARSE_ERROR_DUPLICATE((p->file_prefix == NULL), - section_name, - entry->name); - p->file_prefix = strdup(entry->value); - continue; - } - - /* base_virtaddr */ - if (strcmp(entry->name, "base_virtaddr") == 0) { - PARSE_ERROR_DUPLICATE((p->base_virtaddr == NULL), - section_name, - entry->name); - p->base_virtaddr = strdup(entry->value); - continue; - } - - /* create_uio_dev */ - if (strcmp(entry->name, "create_uio_dev") == 0) { - int val; - - PARSE_ERROR_DUPLICATE((p->create_uio_dev_present == 0), - section_name, - entry->name); - p->create_uio_dev_present = 1; - - val = parser_read_arg_bool(entry->value); - PARSE_ERROR((val >= 0), section_name, entry->name); - p->create_uio_dev = val; - continue; - } - - /* vfio_intr */ - if (strcmp(entry->name, "vfio_intr") == 0) { - PARSE_ERROR_DUPLICATE((p->vfio_intr == NULL), - section_name, - entry->name); - p->vfio_intr = strdup(entry->value); - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, entry->name); - } - - free(entries); -} - -static void -parse_pipeline_pktq_in(struct app_params *app, - struct app_pipeline_params *p, - char *value) -{ - p->n_pktq_in = 0; - - while (1) { - enum app_pktq_in_type type; - int id; - char *name = strtok_r(value, PARSE_DELIMITER, &value); - - if (name == NULL) - break; - - PARSE_ERROR_TOO_MANY_ELEMENTS( - (p->n_pktq_in < RTE_DIM(p->pktq_in)), - p->name, "pktq_in", (uint32_t)RTE_DIM(p->pktq_in)); - - if (validate_name(name, "RXQ", 2) == 0) { - type = APP_PKTQ_IN_HWQ; - id = APP_PARAM_ADD(app->hwq_in_params, name); - APP_PARAM_ADD_LINK_FOR_RXQ(app, name); - } else if (validate_name(name, "SWQ", 1) == 0) { - type = APP_PKTQ_IN_SWQ; - id = APP_PARAM_ADD(app->swq_params, name); - } else if (validate_name(name, "TM", 1) == 0) { - type = APP_PKTQ_IN_TM; - id = APP_PARAM_ADD(app->tm_params, name); - APP_PARAM_ADD_LINK_FOR_TM(app, name); - } else if (validate_name(name, "TAP", 1) == 0) { - type = APP_PKTQ_IN_TAP; - id = APP_PARAM_ADD(app->tap_params, name); - } else if (validate_name(name, "KNI", 1) == 0) { - type = APP_PKTQ_IN_KNI; - id = APP_PARAM_ADD(app->kni_params, name); - APP_PARAM_ADD_LINK_FOR_KNI(app, name); - } else if (validate_name(name, "SOURCE", 1) == 0) { - type = APP_PKTQ_IN_SOURCE; - id = APP_PARAM_ADD(app->source_params, name); - } else - PARSE_ERROR_INVALID_ELEMENT(0, - p->name, "pktq_in", name); - - p->pktq_in[p->n_pktq_in].type = type; - p->pktq_in[p->n_pktq_in].id = (uint32_t) id; - p->n_pktq_in++; - } - - PARSE_ERROR_NO_ELEMENTS((p->n_pktq_in > 0), p->name, "pktq_in"); -} - -static void -parse_pipeline_pktq_out(struct app_params *app, - struct app_pipeline_params *p, - char *value) -{ - p->n_pktq_out = 0; - - while (1) { - enum app_pktq_out_type type; - int id; - char *name = strtok_r(value, PARSE_DELIMITER, &value); - - if (name == NULL) - break; - - PARSE_ERROR_TOO_MANY_ELEMENTS( - (p->n_pktq_out < RTE_DIM(p->pktq_out)), - p->name, "pktq_out", (uint32_t)RTE_DIM(p->pktq_out)); - - if (validate_name(name, "TXQ", 2) == 0) { - type = APP_PKTQ_OUT_HWQ; - id = APP_PARAM_ADD(app->hwq_out_params, name); - APP_PARAM_ADD_LINK_FOR_TXQ(app, name); - } else if (validate_name(name, "SWQ", 1) == 0) { - type = APP_PKTQ_OUT_SWQ; - id = APP_PARAM_ADD(app->swq_params, name); - } else if (validate_name(name, "TM", 1) == 0) { - type = APP_PKTQ_OUT_TM; - id = APP_PARAM_ADD(app->tm_params, name); - APP_PARAM_ADD_LINK_FOR_TM(app, name); - } else if (validate_name(name, "TAP", 1) == 0) { - type = APP_PKTQ_OUT_TAP; - id = APP_PARAM_ADD(app->tap_params, name); - } else if (validate_name(name, "KNI", 1) == 0) { - type = APP_PKTQ_OUT_KNI; - id = APP_PARAM_ADD(app->kni_params, name); - APP_PARAM_ADD_LINK_FOR_KNI(app, name); - } else if (validate_name(name, "SINK", 1) == 0) { - type = APP_PKTQ_OUT_SINK; - id = APP_PARAM_ADD(app->sink_params, name); - } else - PARSE_ERROR_INVALID_ELEMENT(0, - p->name, "pktq_out", name); - - p->pktq_out[p->n_pktq_out].type = type; - p->pktq_out[p->n_pktq_out].id = id; - p->n_pktq_out++; - } - - PARSE_ERROR_NO_ELEMENTS((p->n_pktq_out > 0), p->name, "pktq_out"); -} - -static void -parse_pipeline_msgq_in(struct app_params *app, - struct app_pipeline_params *p, - char *value) -{ - p->n_msgq_in = 0; - - while (1) { - int idx; - char *name = strtok_r(value, PARSE_DELIMITER, &value); - - if (name == NULL) - break; - - PARSE_ERROR_TOO_MANY_ELEMENTS( - (p->n_msgq_in < RTE_DIM(p->msgq_in)), - p->name, "msgq_in", (uint32_t)(RTE_DIM(p->msgq_in))); - - PARSE_ERROR_INVALID_ELEMENT( - (validate_name(name, "MSGQ", 1) == 0), - p->name, "msgq_in", name); - - idx = APP_PARAM_ADD(app->msgq_params, name); - p->msgq_in[p->n_msgq_in] = idx; - p->n_msgq_in++; - } - - PARSE_ERROR_NO_ELEMENTS((p->n_msgq_in > 0), p->name, "msgq_in"); -} - -static void -parse_pipeline_msgq_out(struct app_params *app, - struct app_pipeline_params *p, - char *value) -{ - p->n_msgq_out = 0; - - while (1) { - int idx; - char *name = strtok_r(value, PARSE_DELIMITER, &value); - - if (name == NULL) - break; - - PARSE_ERROR_TOO_MANY_ELEMENTS( - (p->n_msgq_out < RTE_DIM(p->msgq_out)), - p->name, "msgq_out", (uint32_t)RTE_DIM(p->msgq_out)); - - PARSE_ERROR_INVALID_ELEMENT( - (validate_name(name, "MSGQ", 1) == 0), - p->name, "msgq_out", name); - - idx = APP_PARAM_ADD(app->msgq_params, name); - p->msgq_out[p->n_msgq_out] = idx; - p->n_msgq_out++; - } - - PARSE_ERROR_NO_ELEMENTS((p->n_msgq_out > 0), p->name, "msgq_out"); -} - -static void -parse_pipeline(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - char name[CFG_NAME_LEN]; - struct app_pipeline_params *param; - struct rte_cfgfile_entry *entries; - ssize_t param_idx; - int n_entries, i; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->pipeline_params, section_name); - param = &app->pipeline_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "type") == 0) { - int w_size = snprintf(param->type, RTE_DIM(param->type), - "%s", ent->value); - - PARSE_ERROR(((w_size > 0) && - (w_size < (int)RTE_DIM(param->type))), - section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "core") == 0) { - int status = parse_pipeline_core( - ¶m->socket_id, ¶m->core_id, - ¶m->hyper_th_id, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "pktq_in") == 0) { - parse_pipeline_pktq_in(app, param, ent->value); - - continue; - } - - if (strcmp(ent->name, "pktq_out") == 0) { - parse_pipeline_pktq_out(app, param, ent->value); - - continue; - } - - if (strcmp(ent->name, "msgq_in") == 0) { - parse_pipeline_msgq_in(app, param, ent->value); - - continue; - } - - if (strcmp(ent->name, "msgq_out") == 0) { - parse_pipeline_msgq_out(app, param, ent->value); - - continue; - } - - if (strcmp(ent->name, "timer_period") == 0) { - int status = parser_read_uint32( - ¶m->timer_period, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - /* pipeline type specific items */ - APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS), - "Parse error in section \"%s\": too many " - "pipeline specified parameters", section_name); - - param->args_name[param->n_args] = strdup(ent->name); - param->args_value[param->n_args] = strdup(ent->value); - - APP_CHECK((param->args_name[param->n_args] != NULL) && - (param->args_value[param->n_args] != NULL), - "Parse error: no free memory"); - - param->n_args++; - } - - snprintf(name, sizeof(name), "MSGQ-REQ-%s", section_name); - param_idx = APP_PARAM_ADD(app->msgq_params, name); - app->msgq_params[param_idx].cpu_socket_id = param->socket_id; - param->msgq_in[param->n_msgq_in++] = param_idx; - - snprintf(name, sizeof(name), "MSGQ-RSP-%s", section_name); - param_idx = APP_PARAM_ADD(app->msgq_params, name); - app->msgq_params[param_idx].cpu_socket_id = param->socket_id; - param->msgq_out[param->n_msgq_out++] = param_idx; - - snprintf(name, sizeof(name), "MSGQ-REQ-CORE-s%" PRIu32 "c%" PRIu32 "%s", - param->socket_id, - param->core_id, - (param->hyper_th_id) ? "h" : ""); - param_idx = APP_PARAM_ADD(app->msgq_params, name); - app->msgq_params[param_idx].cpu_socket_id = param->socket_id; - - snprintf(name, sizeof(name), "MSGQ-RSP-CORE-s%" PRIu32 "c%" PRIu32 "%s", - param->socket_id, - param->core_id, - (param->hyper_th_id) ? "h" : ""); - param_idx = APP_PARAM_ADD(app->msgq_params, name); - app->msgq_params[param_idx].cpu_socket_id = param->socket_id; - - free(entries); -} - -static void -parse_mempool(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_mempool_params *param; - struct rte_cfgfile_entry *entries; - ssize_t param_idx; - int n_entries, i; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->mempool_params, section_name); - param = &app->mempool_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "buffer_size") == 0) { - int status = parser_read_uint32( - ¶m->buffer_size, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "pool_size") == 0) { - int status = parser_read_uint32( - ¶m->pool_size, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "cache_size") == 0) { - int status = parser_read_uint32( - ¶m->cache_size, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "cpu") == 0) { - int status = parser_read_uint32( - ¶m->cpu_socket_id, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static int -parse_link_rss_qs(struct app_link_params *p, - char *value) -{ - p->n_rss_qs = 0; - - while (1) { - char *token = strtok_r(value, PARSE_DELIMITER, &value); - - if (token == NULL) - break; - - if (p->n_rss_qs == RTE_DIM(p->rss_qs)) - return -ENOMEM; - - if (parser_read_uint32(&p->rss_qs[p->n_rss_qs++], token)) - return -EINVAL; - } - - return 0; -} - -static int -parse_link_rss_proto_ipv4(struct app_link_params *p, - char *value) -{ - uint64_t mask = 0; - - while (1) { - char *token = strtok_r(value, PARSE_DELIMITER, &value); - - if (token == NULL) - break; - - if (strcmp(token, "IP") == 0) { - mask |= ETH_RSS_IPV4; - continue; - } - if (strcmp(token, "FRAG") == 0) { - mask |= ETH_RSS_FRAG_IPV4; - continue; - } - if (strcmp(token, "TCP") == 0) { - mask |= ETH_RSS_NONFRAG_IPV4_TCP; - continue; - } - if (strcmp(token, "UDP") == 0) { - mask |= ETH_RSS_NONFRAG_IPV4_UDP; - continue; - } - if (strcmp(token, "SCTP") == 0) { - mask |= ETH_RSS_NONFRAG_IPV4_SCTP; - continue; - } - if (strcmp(token, "OTHER") == 0) { - mask |= ETH_RSS_NONFRAG_IPV4_OTHER; - continue; - } - return -EINVAL; - } - - p->rss_proto_ipv4 = mask; - return 0; -} - -static int -parse_link_rss_proto_ipv6(struct app_link_params *p, - char *value) -{ - uint64_t mask = 0; - - while (1) { - char *token = strtok_r(value, PARSE_DELIMITER, &value); - - if (token == NULL) - break; - - if (strcmp(token, "IP") == 0) { - mask |= ETH_RSS_IPV6; - continue; - } - if (strcmp(token, "FRAG") == 0) { - mask |= ETH_RSS_FRAG_IPV6; - continue; - } - if (strcmp(token, "TCP") == 0) { - mask |= ETH_RSS_NONFRAG_IPV6_TCP; - continue; - } - if (strcmp(token, "UDP") == 0) { - mask |= ETH_RSS_NONFRAG_IPV6_UDP; - continue; - } - if (strcmp(token, "SCTP") == 0) { - mask |= ETH_RSS_NONFRAG_IPV6_SCTP; - continue; - } - if (strcmp(token, "OTHER") == 0) { - mask |= ETH_RSS_NONFRAG_IPV6_OTHER; - continue; - } - if (strcmp(token, "IP_EX") == 0) { - mask |= ETH_RSS_IPV6_EX; - continue; - } - if (strcmp(token, "TCP_EX") == 0) { - mask |= ETH_RSS_IPV6_TCP_EX; - continue; - } - if (strcmp(token, "UDP_EX") == 0) { - mask |= ETH_RSS_IPV6_UDP_EX; - continue; - } - return -EINVAL; - } - - p->rss_proto_ipv6 = mask; - return 0; -} - -static int -parse_link_rss_proto_l2(struct app_link_params *p, - char *value) -{ - uint64_t mask = 0; - - while (1) { - char *token = strtok_r(value, PARSE_DELIMITER, &value); - - if (token == NULL) - break; - - if (strcmp(token, "L2") == 0) { - mask |= ETH_RSS_L2_PAYLOAD; - continue; - } - return -EINVAL; - } - - p->rss_proto_l2 = mask; - return 0; -} - -static void -parse_link(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_link_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - int rss_qs_present = 0; - int rss_proto_ipv4_present = 0; - int rss_proto_ipv6_present = 0; - int rss_proto_l2_present = 0; - int pci_bdf_present = 0; - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->link_params, section_name); - param = &app->link_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "promisc") == 0) { - int status = parser_read_arg_bool(ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - param->promisc = status; - continue; - } - - if (strcmp(ent->name, "arp_q") == 0) { - int status = parser_read_uint32(¶m->arp_q, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "tcp_syn_q") == 0) { - int status = parser_read_uint32( - ¶m->tcp_syn_q, ent->value); - - PARSE_ERROR((status == 0), section_name, ent->name); - continue; - } - - if (strcmp(ent->name, "ip_local_q") == 0) { - int status = parser_read_uint32( - ¶m->ip_local_q, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "tcp_local_q") == 0) { - int status = parser_read_uint32( - ¶m->tcp_local_q, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "udp_local_q") == 0) { - int status = parser_read_uint32( - ¶m->udp_local_q, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "sctp_local_q") == 0) { - int status = parser_read_uint32( - ¶m->sctp_local_q, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "rss_qs") == 0) { - int status = parse_link_rss_qs(param, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - rss_qs_present = 1; - continue; - } - - if (strcmp(ent->name, "rss_proto_ipv4") == 0) { - int status = - parse_link_rss_proto_ipv4(param, ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - rss_proto_ipv4_present = 1; - continue; - } - - if (strcmp(ent->name, "rss_proto_ipv6") == 0) { - int status = - parse_link_rss_proto_ipv6(param, ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - rss_proto_ipv6_present = 1; - continue; - } - - if (strcmp(ent->name, "rss_proto_l2") == 0) { - int status = parse_link_rss_proto_l2(param, ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - rss_proto_l2_present = 1; - continue; - } - - if (strcmp(ent->name, "pci_bdf") == 0) { - PARSE_ERROR_DUPLICATE((pci_bdf_present == 0), - section_name, ent->name); - - snprintf(param->pci_bdf, APP_LINK_PCI_BDF_SIZE, - "%s", ent->value); - pci_bdf_present = 1; - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - /* Check for mandatory fields */ - if (app->port_mask) - PARSE_ERROR_MESSAGE((pci_bdf_present == 0), - section_name, "pci_bdf", - "entry not allowed (port_mask is provided)"); - else - PARSE_ERROR_MESSAGE((pci_bdf_present), - section_name, "pci_bdf", - "this entry is mandatory (port_mask is not " - "provided)"); - - if (rss_proto_ipv4_present) - PARSE_ERROR_MESSAGE((rss_qs_present), - section_name, "rss_proto_ipv4", - "entry not allowed (rss_qs entry is not provided)"); - if (rss_proto_ipv6_present) - PARSE_ERROR_MESSAGE((rss_qs_present), - section_name, "rss_proto_ipv6", - "entry not allowed (rss_qs entry is not provided)"); - if (rss_proto_l2_present) - PARSE_ERROR_MESSAGE((rss_qs_present), - section_name, "rss_proto_l2", - "entry not allowed (rss_qs entry is not provided)"); - if (rss_proto_ipv4_present | - rss_proto_ipv6_present | - rss_proto_l2_present){ - if (rss_proto_ipv4_present == 0) - param->rss_proto_ipv4 = 0; - if (rss_proto_ipv6_present == 0) - param->rss_proto_ipv6 = 0; - if (rss_proto_l2_present == 0) - param->rss_proto_l2 = 0; - } - - free(entries); -} - -static void -parse_rxq(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_pktq_hwq_in_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->hwq_in_params, section_name); - param = &app->hwq_in_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - APP_PARAM_ADD_LINK_FOR_RXQ(app, section_name); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "mempool") == 0) { - int status = validate_name(ent->value, - "MEMPOOL", 1); - ssize_t idx; - - PARSE_ERROR((status == 0), section_name, - ent->name); - - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - param->mempool_id = idx; - continue; - } - - if (strcmp(ent->name, "size") == 0) { - int status = parser_read_uint32(¶m->size, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "burst") == 0) { - int status = parser_read_uint32(¶m->burst, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static void -parse_txq(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_pktq_hwq_out_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->hwq_out_params, section_name); - param = &app->hwq_out_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - APP_PARAM_ADD_LINK_FOR_TXQ(app, section_name); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "size") == 0) { - int status = parser_read_uint32(¶m->size, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "burst") == 0) { - int status = parser_read_uint32(¶m->burst, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "dropless") == 0) { - int status = parser_read_arg_bool(ent->value); - - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - param->dropless = status; - continue; - } - - if (strcmp(ent->name, "n_retries") == 0) { - int status = parser_read_uint64(¶m->n_retries, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static void -parse_swq(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_pktq_swq_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - uint32_t mtu_present = 0; - uint32_t metadata_size_present = 0; - uint32_t mempool_direct_present = 0; - uint32_t mempool_indirect_present = 0; - - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->swq_params, section_name); - param = &app->swq_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "size") == 0) { - int status = parser_read_uint32(¶m->size, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "burst_read") == 0) { - int status = parser_read_uint32(& - param->burst_read, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "burst_write") == 0) { - int status = parser_read_uint32( - ¶m->burst_write, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "dropless") == 0) { - int status = parser_read_arg_bool(ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - param->dropless = status; - continue; - } - - if (strcmp(ent->name, "n_retries") == 0) { - int status = parser_read_uint64(¶m->n_retries, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "cpu") == 0) { - int status = parser_read_uint32( - ¶m->cpu_socket_id, ent->value); - - PARSE_ERROR((status == 0), section_name, ent->name); - continue; - } - - if (strcmp(ent->name, "ipv4_frag") == 0) { - int status = parser_read_arg_bool(ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - - param->ipv4_frag = status; - if (param->mtu == 0) - param->mtu = 1500; - - continue; - } - - if (strcmp(ent->name, "ipv6_frag") == 0) { - int status = parser_read_arg_bool(ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - param->ipv6_frag = status; - if (param->mtu == 0) - param->mtu = 1320; - continue; - } - - if (strcmp(ent->name, "ipv4_ras") == 0) { - int status = parser_read_arg_bool(ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - param->ipv4_ras = status; - continue; - } - - if (strcmp(ent->name, "ipv6_ras") == 0) { - int status = parser_read_arg_bool(ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - param->ipv6_ras = status; - continue; - } - - if (strcmp(ent->name, "mtu") == 0) { - int status = parser_read_uint32(¶m->mtu, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - mtu_present = 1; - continue; - } - - if (strcmp(ent->name, "metadata_size") == 0) { - int status = parser_read_uint32( - ¶m->metadata_size, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - metadata_size_present = 1; - continue; - } - - if (strcmp(ent->name, "mempool_direct") == 0) { - int status = validate_name(ent->value, - "MEMPOOL", 1); - ssize_t idx; - - PARSE_ERROR((status == 0), section_name, - ent->name); - - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - param->mempool_direct_id = idx; - - mempool_direct_present = 1; - continue; - } - - if (strcmp(ent->name, "mempool_indirect") == 0) { - int status = validate_name(ent->value, - "MEMPOOL", 1); - ssize_t idx; - - PARSE_ERROR((status == 0), section_name, - ent->name); - - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - param->mempool_indirect_id = idx; - - mempool_indirect_present = 1; - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - APP_CHECK(((mtu_present == 0) || - ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), - "Parse error in section \"%s\": IPv4/IPv6 fragmentation " - "is off, therefore entry \"mtu\" is not allowed", - section_name); - - APP_CHECK(((metadata_size_present == 0) || - ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), - "Parse error in section \"%s\": IPv4/IPv6 fragmentation " - "is off, therefore entry \"metadata_size\" is " - "not allowed", section_name); - - APP_CHECK(((mempool_direct_present == 0) || - ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), - "Parse error in section \"%s\": IPv4/IPv6 fragmentation " - "is off, therefore entry \"mempool_direct\" is " - "not allowed", section_name); - - APP_CHECK(((mempool_indirect_present == 0) || - ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), - "Parse error in section \"%s\": IPv4/IPv6 fragmentation " - "is off, therefore entry \"mempool_indirect\" is " - "not allowed", section_name); - - free(entries); -} - -static void -parse_tm(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_pktq_tm_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->tm_params, section_name); - param = &app->tm_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - APP_PARAM_ADD_LINK_FOR_TM(app, section_name); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "cfg") == 0) { - param->file_name = strdup(ent->value); - PARSE_ERROR_MALLOC(param->file_name != NULL); - continue; - } - - if (strcmp(ent->name, "burst_read") == 0) { - int status = parser_read_uint32( - ¶m->burst_read, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "burst_write") == 0) { - int status = parser_read_uint32( - ¶m->burst_write, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static void -parse_tap(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_pktq_tap_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->tap_params, section_name); - param = &app->tap_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "burst_read") == 0) { - int status = parser_read_uint32( - ¶m->burst_read, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "burst_write") == 0) { - int status = parser_read_uint32( - ¶m->burst_write, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "dropless") == 0) { - int status = parser_read_arg_bool(ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - param->dropless = status; - continue; - } - - if (strcmp(ent->name, "n_retries") == 0) { - int status = parser_read_uint64(¶m->n_retries, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "mempool") == 0) { - int status = validate_name(ent->value, - "MEMPOOL", 1); - ssize_t idx; - - PARSE_ERROR((status == 0), section_name, - ent->name); - - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - param->mempool_id = idx; - - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static void -parse_kni(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_pktq_kni_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->kni_params, section_name); - param = &app->kni_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - APP_PARAM_ADD_LINK_FOR_KNI(app, section_name); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "core") == 0) { - int status = parse_pipeline_core( - ¶m->socket_id, - ¶m->core_id, - ¶m->hyper_th_id, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - param->force_bind = 1; - continue; - } - - if (strcmp(ent->name, "mempool") == 0) { - int status = validate_name(ent->value, - "MEMPOOL", 1); - ssize_t idx; - - PARSE_ERROR((status == 0), section_name, - ent->name); - - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - param->mempool_id = idx; - continue; - } - - if (strcmp(ent->name, "burst_read") == 0) { - int status = parser_read_uint32(¶m->burst_read, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "burst_write") == 0) { - int status = parser_read_uint32(¶m->burst_write, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "dropless") == 0) { - int status = parser_read_arg_bool(ent->value); - - PARSE_ERROR((status != -EINVAL), section_name, - ent->name); - param->dropless = status; - continue; - } - - if (strcmp(ent->name, "n_retries") == 0) { - int status = parser_read_uint64(¶m->n_retries, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static void -parse_source(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_pktq_source_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - uint32_t pcap_file_present = 0; - uint32_t pcap_size_present = 0; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->source_params, section_name); - param = &app->source_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "mempool") == 0) { - int status = validate_name(ent->value, - "MEMPOOL", 1); - ssize_t idx; - - PARSE_ERROR((status == 0), section_name, - ent->name); - - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - param->mempool_id = idx; - continue; - } - - if (strcmp(ent->name, "burst") == 0) { - int status = parser_read_uint32(¶m->burst, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "pcap_file_rd") == 0) { - PARSE_ERROR_DUPLICATE((pcap_file_present == 0), - section_name, ent->name); - - param->file_name = strdup(ent->value); - - PARSE_ERROR_MALLOC(param->file_name != NULL); - pcap_file_present = 1; - - continue; - } - - if (strcmp(ent->name, "pcap_bytes_rd_per_pkt") == 0) { - int status; - - PARSE_ERROR_DUPLICATE((pcap_size_present == 0), - section_name, ent->name); - - status = parser_read_uint32( - ¶m->n_bytes_per_pkt, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - pcap_size_present = 1; - - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static void -parse_sink(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_pktq_sink_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - uint32_t pcap_file_present = 0; - uint32_t pcap_n_pkt_present = 0; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->sink_params, section_name); - param = &app->sink_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "pcap_file_wr") == 0) { - PARSE_ERROR_DUPLICATE((pcap_file_present == 0), - section_name, ent->name); - - param->file_name = strdup(ent->value); - - PARSE_ERROR_MALLOC((param->file_name != NULL)); - - continue; - } - - if (strcmp(ent->name, "pcap_n_pkt_wr") == 0) { - int status; - - PARSE_ERROR_DUPLICATE((pcap_n_pkt_present == 0), - section_name, ent->name); - - status = parser_read_uint32( - ¶m->n_pkts_to_dump, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static void -parse_msgq_req_pipeline(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_msgq_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->msgq_params, section_name); - param = &app->msgq_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "size") == 0) { - int status = parser_read_uint32(¶m->size, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static void -parse_msgq_rsp_pipeline(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_msgq_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->msgq_params, section_name); - param = &app->msgq_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "size") == 0) { - int status = parser_read_uint32(¶m->size, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -static void -parse_msgq(struct app_params *app, - const char *section_name, - struct rte_cfgfile *cfg) -{ - struct app_msgq_params *param; - struct rte_cfgfile_entry *entries; - int n_entries, i; - ssize_t param_idx; - - n_entries = rte_cfgfile_section_num_entries(cfg, section_name); - PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); - - entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); - PARSE_ERROR_MALLOC(entries != NULL); - - rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - - param_idx = APP_PARAM_ADD(app->msgq_params, section_name); - param = &app->msgq_params[param_idx]; - PARSE_CHECK_DUPLICATE_SECTION(param); - - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; - - if (strcmp(ent->name, "size") == 0) { - int status = parser_read_uint32(¶m->size, - ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "cpu") == 0) { - int status = parser_read_uint32( - ¶m->cpu_socket_id, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); - } - - free(entries); -} - -typedef void (*config_section_load)(struct app_params *p, - const char *section_name, - struct rte_cfgfile *cfg); - -struct config_section { - const char prefix[CFG_NAME_LEN]; - int numbers; - config_section_load load; -}; - -static const struct config_section cfg_file_scheme[] = { - {"EAL", 0, parse_eal}, - {"PIPELINE", 1, parse_pipeline}, - {"MEMPOOL", 1, parse_mempool}, - {"LINK", 1, parse_link}, - {"RXQ", 2, parse_rxq}, - {"TXQ", 2, parse_txq}, - {"SWQ", 1, parse_swq}, - {"TM", 1, parse_tm}, - {"TAP", 1, parse_tap}, - {"KNI", 1, parse_kni}, - {"SOURCE", 1, parse_source}, - {"SINK", 1, parse_sink}, - {"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline}, - {"MSGQ-RSP-PIPELINE", 1, parse_msgq_rsp_pipeline}, - {"MSGQ", 1, parse_msgq}, -}; - -static void -create_implicit_mempools(struct app_params *app) -{ - APP_PARAM_ADD(app->mempool_params, "MEMPOOL0"); -} - -static void -create_implicit_links_from_port_mask(struct app_params *app, - uint64_t port_mask) -{ - uint32_t pmd_id, link_id; - - link_id = 0; - for (pmd_id = 0; pmd_id < RTE_MAX_ETHPORTS; pmd_id++) { - char name[APP_PARAM_NAME_SIZE]; - ssize_t idx; - - if ((port_mask & (1LLU << pmd_id)) == 0) - continue; - - snprintf(name, sizeof(name), "LINK%" PRIu32, link_id); - idx = APP_PARAM_ADD(app->link_params, name); - - app->link_params[idx].pmd_id = pmd_id; - link_id++; - } -} - -static void -assign_link_pmd_id_from_pci_bdf(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_links; i++) { - struct app_link_params *link = &app->link_params[i]; - - APP_CHECK((strlen(link->pci_bdf)), - "Parse error: %s pci_bdf is not configured " - "(port_mask is not provided)", - link->name); - - link->pmd_id = i; - } -} - -int -app_config_parse(struct app_params *app, const char *file_name) -{ - struct rte_cfgfile *cfg; - char **section_names; - int i, j, sect_count; - - /* Implicit mempools */ - create_implicit_mempools(app); - - /* Port mask */ - if (app->port_mask) - create_implicit_links_from_port_mask(app, app->port_mask); - - /* Load application configuration file */ - cfg = rte_cfgfile_load(file_name, 0); - APP_CHECK((cfg != NULL), "Parse error: Unable to load config " - "file %s", file_name); - - sect_count = rte_cfgfile_num_sections(cfg, NULL, 0); - APP_CHECK((sect_count > 0), "Parse error: number of sections " - "in file \"%s\" return %d", file_name, - sect_count); - - section_names = malloc(sect_count * sizeof(char *)); - PARSE_ERROR_MALLOC(section_names != NULL); - - for (i = 0; i < sect_count; i++) - section_names[i] = malloc(CFG_NAME_LEN); - - rte_cfgfile_sections(cfg, section_names, sect_count); - - for (i = 0; i < sect_count; i++) { - const struct config_section *sch_s; - int len, cfg_name_len; - - cfg_name_len = strlen(section_names[i]); - - /* Find section type */ - for (j = 0; j < (int)RTE_DIM(cfg_file_scheme); j++) { - sch_s = &cfg_file_scheme[j]; - len = strlen(sch_s->prefix); - - if (cfg_name_len < len) - continue; - - /* After section name we expect only '\0' or digit or - * digit dot digit, so protect against false matching, - * for example: "ABC" should match section name - * "ABC0.0", but it should not match section_name - * "ABCDEF". - */ - if ((section_names[i][len] != '\0') && - !isdigit(section_names[i][len])) - continue; - - if (strncmp(sch_s->prefix, section_names[i], len) == 0) - break; - } - - APP_CHECK(j < (int)RTE_DIM(cfg_file_scheme), - "Parse error: unknown section %s", - section_names[i]); - - APP_CHECK(validate_name(section_names[i], - sch_s->prefix, - sch_s->numbers) == 0, - "Parse error: invalid section name \"%s\"", - section_names[i]); - - sch_s->load(app, section_names[i], cfg); - } - - for (i = 0; i < sect_count; i++) - free(section_names[i]); - - free(section_names); - - rte_cfgfile_close(cfg); - - APP_PARAM_COUNT(app->mempool_params, app->n_mempools); - APP_PARAM_COUNT(app->link_params, app->n_links); - APP_PARAM_COUNT(app->hwq_in_params, app->n_pktq_hwq_in); - APP_PARAM_COUNT(app->hwq_out_params, app->n_pktq_hwq_out); - APP_PARAM_COUNT(app->swq_params, app->n_pktq_swq); - APP_PARAM_COUNT(app->tm_params, app->n_pktq_tm); - APP_PARAM_COUNT(app->tap_params, app->n_pktq_tap); - APP_PARAM_COUNT(app->kni_params, app->n_pktq_kni); - APP_PARAM_COUNT(app->source_params, app->n_pktq_source); - APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink); - APP_PARAM_COUNT(app->msgq_params, app->n_msgq); - APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines); - - if (app->port_mask == 0) - assign_link_pmd_id_from_pci_bdf(app); - - /* Save configuration to output file */ - app_config_save(app, app->output_file); - - /* Load TM configuration files */ - app_config_parse_tm(app); - - return 0; -} - -static void -save_eal_params(struct app_params *app, FILE *f) -{ - struct app_eal_params *p = &app->eal_params; - uint32_t i; - - fprintf(f, "[EAL]\n"); - - if (p->coremap) - fprintf(f, "%s = %s\n", "lcores", p->coremap); - - if (p->master_lcore_present) - fprintf(f, "%s = %" PRIu32 "\n", - "master_lcore", p->master_lcore); - - fprintf(f, "%s = %" PRIu32 "\n", "n", p->channels); - - if (p->memory_present) - fprintf(f, "%s = %" PRIu32 "\n", "m", p->memory); - - if (p->ranks_present) - fprintf(f, "%s = %" PRIu32 "\n", "r", p->ranks); - - for (i = 0; i < APP_MAX_LINKS; i++) { - if (p->pci_blacklist[i] == NULL) - break; - - fprintf(f, "%s = %s\n", "pci_blacklist", - p->pci_blacklist[i]); - } - - for (i = 0; i < APP_MAX_LINKS; i++) { - if (p->pci_whitelist[i] == NULL) - break; - - fprintf(f, "%s = %s\n", "pci_whitelist", - p->pci_whitelist[i]); - } - - for (i = 0; i < APP_MAX_LINKS; i++) { - if (p->vdev[i] == NULL) - break; - - fprintf(f, "%s = %s\n", "vdev", - p->vdev[i]); - } - - if (p->vmware_tsc_map_present) - fprintf(f, "%s = %s\n", "vmware_tsc_map", - (p->vmware_tsc_map) ? "yes" : "no"); - - if (p->proc_type) - fprintf(f, "%s = %s\n", "proc_type", p->proc_type); - - if (p->syslog) - fprintf(f, "%s = %s\n", "syslog", p->syslog); - - if (p->log_level_present) - fprintf(f, "%s = %" PRIu32 "\n", "log_level", p->log_level); - - if (p->version_present) - fprintf(f, "%s = %s\n", "v", (p->version) ? "yes" : "no"); - - if (p->help_present) - fprintf(f, "%s = %s\n", "help", (p->help) ? "yes" : "no"); - - if (p->no_huge_present) - fprintf(f, "%s = %s\n", "no_huge", (p->no_huge) ? "yes" : "no"); - - if (p->no_pci_present) - fprintf(f, "%s = %s\n", "no_pci", (p->no_pci) ? "yes" : "no"); - - if (p->no_hpet_present) - fprintf(f, "%s = %s\n", "no_hpet", (p->no_hpet) ? "yes" : "no"); - - if (p->no_shconf_present) - fprintf(f, "%s = %s\n", "no_shconf", - (p->no_shconf) ? "yes" : "no"); - - if (p->add_driver) - fprintf(f, "%s = %s\n", "d", p->add_driver); - - if (p->socket_mem) - fprintf(f, "%s = %s\n", "socket_mem", p->socket_mem); - - if (p->huge_dir) - fprintf(f, "%s = %s\n", "huge_dir", p->huge_dir); - - if (p->file_prefix) - fprintf(f, "%s = %s\n", "file_prefix", p->file_prefix); - - if (p->base_virtaddr) - fprintf(f, "%s = %s\n", "base_virtaddr", p->base_virtaddr); - - if (p->create_uio_dev_present) - fprintf(f, "%s = %s\n", "create_uio_dev", - (p->create_uio_dev) ? "yes" : "no"); - - if (p->vfio_intr) - fprintf(f, "%s = %s\n", "vfio_intr", p->vfio_intr); - - fputc('\n', f); -} - -static void -save_mempool_params(struct app_params *app, FILE *f) -{ - struct app_mempool_params *p; - size_t i, count; - - count = RTE_DIM(app->mempool_params); - for (i = 0; i < count; i++) { - p = &app->mempool_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "%s = %" PRIu32 "\n", "buffer_size", p->buffer_size); - fprintf(f, "%s = %" PRIu32 "\n", "pool_size", p->pool_size); - fprintf(f, "%s = %" PRIu32 "\n", "cache_size", p->cache_size); - fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id); - - fputc('\n', f); - } -} - -static void -save_links_params(struct app_params *app, FILE *f) -{ - struct app_link_params *p; - size_t i, count; - - count = RTE_DIM(app->link_params); - for (i = 0; i < count; i++) { - p = &app->link_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "; %s = %" PRIu32 "\n", "pmd_id", p->pmd_id); - fprintf(f, "%s = %s\n", "promisc", p->promisc ? "yes" : "no"); - fprintf(f, "%s = %" PRIu32 "\n", "arp_q", p->arp_q); - fprintf(f, "%s = %" PRIu32 "\n", "tcp_syn_q", - p->tcp_syn_q); - fprintf(f, "%s = %" PRIu32 "\n", "ip_local_q", p->ip_local_q); - fprintf(f, "%s = %" PRIu32 "\n", "tcp_local_q", p->tcp_local_q); - fprintf(f, "%s = %" PRIu32 "\n", "udp_local_q", p->udp_local_q); - fprintf(f, "%s = %" PRIu32 "\n", "sctp_local_q", - p->sctp_local_q); - - if (p->n_rss_qs) { - uint32_t j; - - /* rss_qs */ - fprintf(f, "rss_qs = "); - for (j = 0; j < p->n_rss_qs; j++) - fprintf(f, "%" PRIu32 " ", p->rss_qs[j]); - fputc('\n', f); - - /* rss_proto_ipv4 */ - if (p->rss_proto_ipv4) { - fprintf(f, "rss_proto_ipv4 = "); - if (p->rss_proto_ipv4 & ETH_RSS_IPV4) - fprintf(f, "IP "); - if (p->rss_proto_ipv4 & ETH_RSS_FRAG_IPV4) - fprintf(f, "FRAG "); - if (p->rss_proto_ipv4 & - ETH_RSS_NONFRAG_IPV4_TCP) - fprintf(f, "TCP "); - if (p->rss_proto_ipv4 & - ETH_RSS_NONFRAG_IPV4_UDP) - fprintf(f, "UDP "); - if (p->rss_proto_ipv4 & - ETH_RSS_NONFRAG_IPV4_SCTP) - fprintf(f, "SCTP "); - if (p->rss_proto_ipv4 & - ETH_RSS_NONFRAG_IPV4_OTHER) - fprintf(f, "OTHER "); - fprintf(f, "\n"); - } else - fprintf(f, "; rss_proto_ipv4 = <NONE>\n"); - - /* rss_proto_ipv6 */ - if (p->rss_proto_ipv6) { - fprintf(f, "rss_proto_ipv6 = "); - if (p->rss_proto_ipv6 & ETH_RSS_IPV6) - fprintf(f, "IP "); - if (p->rss_proto_ipv6 & ETH_RSS_FRAG_IPV6) - fprintf(f, "FRAG "); - if (p->rss_proto_ipv6 & - ETH_RSS_NONFRAG_IPV6_TCP) - fprintf(f, "TCP "); - if (p->rss_proto_ipv6 & - ETH_RSS_NONFRAG_IPV6_UDP) - fprintf(f, "UDP "); - if (p->rss_proto_ipv6 & - ETH_RSS_NONFRAG_IPV6_SCTP) - fprintf(f, "SCTP "); - if (p->rss_proto_ipv6 & - ETH_RSS_NONFRAG_IPV6_OTHER) - fprintf(f, "OTHER "); - if (p->rss_proto_ipv6 & ETH_RSS_IPV6_EX) - fprintf(f, "IP_EX "); - if (p->rss_proto_ipv6 & - ETH_RSS_IPV6_TCP_EX) - fprintf(f, "TCP_EX "); - if (p->rss_proto_ipv6 & - ETH_RSS_IPV6_UDP_EX) - fprintf(f, "UDP_EX "); - fprintf(f, "\n"); - } else - fprintf(f, "; rss_proto_ipv6 = <NONE>\n"); - - /* rss_proto_l2 */ - if (p->rss_proto_l2) { - fprintf(f, "rss_proto_l2 = "); - if (p->rss_proto_l2 & ETH_RSS_L2_PAYLOAD) - fprintf(f, "L2 "); - fprintf(f, "\n"); - } else - fprintf(f, "; rss_proto_l2 = <NONE>\n"); - } else { - fprintf(f, "; rss_qs = <NONE>\n"); - fprintf(f, "; rss_proto_ipv4 = <NONE>\n"); - fprintf(f, "; rss_proto_ipv6 = <NONE>\n"); - fprintf(f, "; rss_proto_l2 = <NONE>\n"); - } - - if (strlen(p->pci_bdf)) - fprintf(f, "%s = %s\n", "pci_bdf", p->pci_bdf); - - fputc('\n', f); - } -} - -static void -save_rxq_params(struct app_params *app, FILE *f) -{ - struct app_pktq_hwq_in_params *p; - size_t i, count; - - count = RTE_DIM(app->hwq_in_params); - for (i = 0; i < count; i++) { - p = &app->hwq_in_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "%s = %s\n", - "mempool", - app->mempool_params[p->mempool_id].name); - fprintf(f, "%s = %" PRIu32 "\n", "size", p->size); - fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst); - - fputc('\n', f); - } -} - -static void -save_txq_params(struct app_params *app, FILE *f) -{ - struct app_pktq_hwq_out_params *p; - size_t i, count; - - count = RTE_DIM(app->hwq_out_params); - for (i = 0; i < count; i++) { - p = &app->hwq_out_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "%s = %" PRIu32 "\n", "size", p->size); - fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst); - fprintf(f, "%s = %s\n", - "dropless", - p->dropless ? "yes" : "no"); - fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); - - fputc('\n', f); - } -} - -static void -save_swq_params(struct app_params *app, FILE *f) -{ - struct app_pktq_swq_params *p; - size_t i, count; - - count = RTE_DIM(app->swq_params); - for (i = 0; i < count; i++) { - p = &app->swq_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "%s = %" PRIu32 "\n", "size", p->size); - fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read); - fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write); - fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no"); - fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); - fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id); - fprintf(f, "%s = %s\n", "ipv4_frag", p->ipv4_frag ? "yes" : "no"); - fprintf(f, "%s = %s\n", "ipv6_frag", p->ipv6_frag ? "yes" : "no"); - fprintf(f, "%s = %s\n", "ipv4_ras", p->ipv4_ras ? "yes" : "no"); - fprintf(f, "%s = %s\n", "ipv6_ras", p->ipv6_ras ? "yes" : "no"); - if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1)) { - fprintf(f, "%s = %" PRIu32 "\n", "mtu", p->mtu); - fprintf(f, "%s = %" PRIu32 "\n", "metadata_size", p->metadata_size); - fprintf(f, "%s = %s\n", - "mempool_direct", - app->mempool_params[p->mempool_direct_id].name); - fprintf(f, "%s = %s\n", - "mempool_indirect", - app->mempool_params[p->mempool_indirect_id].name); - } - - fputc('\n', f); - } -} - -static void -save_tm_params(struct app_params *app, FILE *f) -{ - struct app_pktq_tm_params *p; - size_t i, count; - - count = RTE_DIM(app->tm_params); - for (i = 0; i < count; i++) { - p = &app->tm_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "%s = %s\n", "cfg", p->file_name); - fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read); - fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write); - - fputc('\n', f); - } -} - -static void -save_tap_params(struct app_params *app, FILE *f) -{ - struct app_pktq_tap_params *p; - size_t i, count; - - count = RTE_DIM(app->tap_params); - for (i = 0; i < count; i++) { - p = &app->tap_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read); - fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write); - fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no"); - fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); - fprintf(f, "%s = %s\n", "mempool", - app->mempool_params[p->mempool_id].name); - - fputc('\n', f); - } -} - -static void -save_kni_params(struct app_params *app, FILE *f) -{ - struct app_pktq_kni_params *p; - size_t i, count; - - count = RTE_DIM(app->kni_params); - for (i = 0; i < count; i++) { - p = &app->kni_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - /* section name */ - fprintf(f, "[%s]\n", p->name); - - /* core */ - if (p->force_bind) { - fprintf(f, "; force_bind = 1\n"); - fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n", - p->socket_id, - p->core_id, - (p->hyper_th_id) ? "h" : ""); - } else - fprintf(f, "; force_bind = 0\n"); - - /* mempool */ - fprintf(f, "%s = %s\n", "mempool", - app->mempool_params[p->mempool_id].name); - - /* burst_read */ - fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read); - - /* burst_write */ - fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write); - - /* dropless */ - fprintf(f, "%s = %s\n", - "dropless", - p->dropless ? "yes" : "no"); - - /* n_retries */ - fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); - - fputc('\n', f); - } -} - -static void -save_source_params(struct app_params *app, FILE *f) -{ - struct app_pktq_source_params *p; - size_t i, count; - - count = RTE_DIM(app->source_params); - for (i = 0; i < count; i++) { - p = &app->source_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "%s = %s\n", - "mempool", - app->mempool_params[p->mempool_id].name); - fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst); - fprintf(f, "%s = %s\n", "pcap_file_rd", p->file_name); - fprintf(f, "%s = %" PRIu32 "\n", "pcap_bytes_rd_per_pkt", - p->n_bytes_per_pkt); - fputc('\n', f); - } -} - -static void -save_sink_params(struct app_params *app, FILE *f) -{ - struct app_pktq_sink_params *p; - size_t i, count; - - count = RTE_DIM(app->sink_params); - for (i = 0; i < count; i++) { - p = &app->sink_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "%s = %s\n", "pcap_file_wr", p->file_name); - fprintf(f, "%s = %" PRIu32 "\n", - "pcap_n_pkt_wr", p->n_pkts_to_dump); - fputc('\n', f); - } -} - -static void -save_msgq_params(struct app_params *app, FILE *f) -{ - struct app_msgq_params *p; - size_t i, count; - - count = RTE_DIM(app->msgq_params); - for (i = 0; i < count; i++) { - p = &app->msgq_params[i]; - if (!APP_PARAM_VALID(p)) - continue; - - fprintf(f, "[%s]\n", p->name); - fprintf(f, "%s = %" PRIu32 "\n", "size", p->size); - fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id); - - fputc('\n', f); - } -} - -static void -save_pipeline_params(struct app_params *app, FILE *f) -{ - size_t i, count; - - count = RTE_DIM(app->pipeline_params); - for (i = 0; i < count; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - - if (!APP_PARAM_VALID(p)) - continue; - - /* section name */ - fprintf(f, "[%s]\n", p->name); - - /* type */ - fprintf(f, "type = %s\n", p->type); - - /* core */ - fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n", - p->socket_id, - p->core_id, - (p->hyper_th_id) ? "h" : ""); - - /* pktq_in */ - if (p->n_pktq_in) { - uint32_t j; - - fprintf(f, "pktq_in ="); - for (j = 0; j < p->n_pktq_in; j++) { - struct app_pktq_in_params *pp = &p->pktq_in[j]; - char *name; - - switch (pp->type) { - case APP_PKTQ_IN_HWQ: - name = app->hwq_in_params[pp->id].name; - break; - case APP_PKTQ_IN_SWQ: - name = app->swq_params[pp->id].name; - break; - case APP_PKTQ_IN_TM: - name = app->tm_params[pp->id].name; - break; - case APP_PKTQ_IN_TAP: - name = app->tap_params[pp->id].name; - break; - case APP_PKTQ_IN_KNI: - name = app->kni_params[pp->id].name; - break; - case APP_PKTQ_IN_SOURCE: - name = app->source_params[pp->id].name; - break; - default: - APP_CHECK(0, "System error " - "occurred while saving " - "parameter to file"); - } - - fprintf(f, " %s", name); - } - fprintf(f, "\n"); - } - - /* pktq_in */ - if (p->n_pktq_out) { - uint32_t j; - - fprintf(f, "pktq_out ="); - for (j = 0; j < p->n_pktq_out; j++) { - struct app_pktq_out_params *pp = - &p->pktq_out[j]; - char *name; - - switch (pp->type) { - case APP_PKTQ_OUT_HWQ: - name = app->hwq_out_params[pp->id].name; - break; - case APP_PKTQ_OUT_SWQ: - name = app->swq_params[pp->id].name; - break; - case APP_PKTQ_OUT_TM: - name = app->tm_params[pp->id].name; - break; - case APP_PKTQ_OUT_TAP: - name = app->tap_params[pp->id].name; - break; - case APP_PKTQ_OUT_KNI: - name = app->kni_params[pp->id].name; - break; - case APP_PKTQ_OUT_SINK: - name = app->sink_params[pp->id].name; - break; - default: - APP_CHECK(0, "System error " - "occurred while saving " - "parameter to file"); - } - - fprintf(f, " %s", name); - } - fprintf(f, "\n"); - } - - /* msgq_in */ - if (p->n_msgq_in) { - uint32_t j; - - fprintf(f, "msgq_in ="); - for (j = 0; j < p->n_msgq_in; j++) { - uint32_t id = p->msgq_in[j]; - char *name = app->msgq_params[id].name; - - fprintf(f, " %s", name); - } - fprintf(f, "\n"); - } - - /* msgq_out */ - if (p->n_msgq_out) { - uint32_t j; - - fprintf(f, "msgq_out ="); - for (j = 0; j < p->n_msgq_out; j++) { - uint32_t id = p->msgq_out[j]; - char *name = app->msgq_params[id].name; - - fprintf(f, " %s", name); - } - fprintf(f, "\n"); - } - - /* timer_period */ - fprintf(f, "timer_period = %" PRIu32 "\n", p->timer_period); - - /* args */ - if (p->n_args) { - uint32_t j; - - for (j = 0; j < p->n_args; j++) - fprintf(f, "%s = %s\n", p->args_name[j], - p->args_value[j]); - } - - fprintf(f, "\n"); - } -} - -void -app_config_save(struct app_params *app, const char *file_name) -{ - FILE *file; - char *name, *dir_name; - int status; - - name = strdup(file_name); - dir_name = dirname(name); - status = access(dir_name, W_OK); - APP_CHECK((status == 0), - "Error: need write access privilege to directory " - "\"%s\" to save configuration\n", dir_name); - - file = fopen(file_name, "w"); - APP_CHECK((file != NULL), - "Error: failed to save configuration to file \"%s\"", - file_name); - - save_eal_params(app, file); - save_pipeline_params(app, file); - save_mempool_params(app, file); - save_links_params(app, file); - save_rxq_params(app, file); - save_txq_params(app, file); - save_swq_params(app, file); - save_tm_params(app, file); - save_tap_params(app, file); - save_kni_params(app, file); - save_source_params(app, file); - save_sink_params(app, file); - save_msgq_params(app, file); - - fclose(file); - free(name); -} - -int -app_config_init(struct app_params *app) -{ - size_t i; - - memcpy(app, &app_params_default, sizeof(struct app_params)); - - for (i = 0; i < RTE_DIM(app->mempool_params); i++) - memcpy(&app->mempool_params[i], - &mempool_params_default, - sizeof(struct app_mempool_params)); - - for (i = 0; i < RTE_DIM(app->link_params); i++) - memcpy(&app->link_params[i], - &link_params_default, - sizeof(struct app_link_params)); - - for (i = 0; i < RTE_DIM(app->hwq_in_params); i++) - memcpy(&app->hwq_in_params[i], - &default_hwq_in_params, - sizeof(default_hwq_in_params)); - - for (i = 0; i < RTE_DIM(app->hwq_out_params); i++) - memcpy(&app->hwq_out_params[i], - &default_hwq_out_params, - sizeof(default_hwq_out_params)); - - for (i = 0; i < RTE_DIM(app->swq_params); i++) - memcpy(&app->swq_params[i], - &default_swq_params, - sizeof(default_swq_params)); - - for (i = 0; i < RTE_DIM(app->tm_params); i++) - memcpy(&app->tm_params[i], - &default_tm_params, - sizeof(default_tm_params)); - - for (i = 0; i < RTE_DIM(app->tap_params); i++) - memcpy(&app->tap_params[i], - &default_tap_params, - sizeof(default_tap_params)); - - for (i = 0; i < RTE_DIM(app->kni_params); i++) - memcpy(&app->kni_params[i], - &default_kni_params, - sizeof(default_kni_params)); - - for (i = 0; i < RTE_DIM(app->source_params); i++) - memcpy(&app->source_params[i], - &default_source_params, - sizeof(default_source_params)); - - for (i = 0; i < RTE_DIM(app->sink_params); i++) - memcpy(&app->sink_params[i], - &default_sink_params, - sizeof(default_sink_params)); - - for (i = 0; i < RTE_DIM(app->msgq_params); i++) - memcpy(&app->msgq_params[i], - &default_msgq_params, - sizeof(default_msgq_params)); - - for (i = 0; i < RTE_DIM(app->pipeline_params); i++) - memcpy(&app->pipeline_params[i], - &default_pipeline_params, - sizeof(default_pipeline_params)); - - return 0; -} - -static char * -filenamedup(const char *filename, const char *suffix) -{ - char *s = malloc(strlen(filename) + strlen(suffix) + 1); - - if (!s) - return NULL; - - sprintf(s, "%s%s", filename, suffix); - return s; -} - -int -app_config_args(struct app_params *app, int argc, char **argv) -{ - const char *optname; - int opt, option_index; - int f_present, s_present, p_present, l_present; - int preproc_present, preproc_params_present; - int scaned = 0; - - static struct option lgopts[] = { - { "preproc", 1, 0, 0 }, - { "preproc-args", 1, 0, 0 }, - { NULL, 0, 0, 0 } - }; - - /* Copy application name */ - strncpy(app->app_name, argv[0], APP_APPNAME_SIZE - 1); - - f_present = 0; - s_present = 0; - p_present = 0; - l_present = 0; - preproc_present = 0; - preproc_params_present = 0; - - while ((opt = getopt_long(argc, argv, "f:s:p:l:", lgopts, - &option_index)) != EOF) - switch (opt) { - case 'f': - if (f_present) - rte_panic("Error: Config file is provided " - "more than once\n"); - f_present = 1; - - if (!strlen(optarg)) - rte_panic("Error: Config file name is null\n"); - - app->config_file = strdup(optarg); - if (app->config_file == NULL) - rte_panic("Error: Memory allocation failure\n"); - - break; - - case 's': - if (s_present) - rte_panic("Error: Script file is provided " - "more than once\n"); - s_present = 1; - - if (!strlen(optarg)) - rte_panic("Error: Script file name is null\n"); - - app->script_file = strdup(optarg); - if (app->script_file == NULL) - rte_panic("Error: Memory allocation failure\n"); - - break; - - case 'p': - if (p_present) - rte_panic("Error: PORT_MASK is provided " - "more than once\n"); - p_present = 1; - - if ((sscanf(optarg, "%" SCNx64 "%n", &app->port_mask, - &scaned) != 1) || - ((size_t) scaned != strlen(optarg))) - rte_panic("Error: PORT_MASK is not " - "a hexadecimal integer\n"); - - if (app->port_mask == 0) - rte_panic("Error: PORT_MASK is null\n"); - - break; - - case 'l': - if (l_present) - rte_panic("Error: LOG_LEVEL is provided " - "more than once\n"); - l_present = 1; - - if ((sscanf(optarg, "%" SCNu32 "%n", &app->log_level, - &scaned) != 1) || - ((size_t) scaned != strlen(optarg)) || - (app->log_level >= APP_LOG_LEVELS)) - rte_panic("Error: LOG_LEVEL invalid value\n"); - - break; - - case 0: - optname = lgopts[option_index].name; - - if (strcmp(optname, "preproc") == 0) { - if (preproc_present) - rte_panic("Error: Preprocessor argument " - "is provided more than once\n"); - preproc_present = 1; - - app->preproc = strdup(optarg); - break; - } - - if (strcmp(optname, "preproc-args") == 0) { - if (preproc_params_present) - rte_panic("Error: Preprocessor args " - "are provided more than once\n"); - preproc_params_present = 1; - - app->preproc_args = strdup(optarg); - break; - } - - app_print_usage(argv[0]); - break; - - default: - app_print_usage(argv[0]); - } - - optind = 1; /* reset getopt lib */ - - /* Check dependencies between args */ - if (preproc_params_present && (preproc_present == 0)) - rte_panic("Error: Preprocessor args specified while " - "preprocessor is not defined\n"); - - app->parser_file = preproc_present ? - filenamedup(app->config_file, ".preproc") : - strdup(app->config_file); - app->output_file = filenamedup(app->config_file, ".out"); - - return 0; -} - -int -app_config_preproc(struct app_params *app) -{ - char buffer[256]; - int status; - - if (app->preproc == NULL) - return 0; - - status = access(app->config_file, F_OK | R_OK); - APP_CHECK((status == 0), "Error: Unable to open file %s", - app->config_file); - - snprintf(buffer, sizeof(buffer), "%s %s %s > %s", - app->preproc, - app->preproc_args ? app->preproc_args : "", - app->config_file, - app->parser_file); - - status = system(buffer); - APP_CHECK((WIFEXITED(status) && (WEXITSTATUS(status) == 0)), - "Error occurred while pre-processing file \"%s\"\n", - app->config_file); - - return status; -} diff --git a/examples/ip_pipeline/config_parse_tm.c b/examples/ip_pipeline/config_parse_tm.c deleted file mode 100644 index 6edd2ca9..00000000 --- a/examples/ip_pipeline/config_parse_tm.c +++ /dev/null @@ -1,419 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <getopt.h> -#include <errno.h> -#include <stdarg.h> -#include <string.h> -#include <libgen.h> -#include <unistd.h> - -#include <rte_errno.h> -#include <rte_cfgfile.h> -#include <rte_string_fns.h> - -#include "app.h" - -static int -tm_cfgfile_load_sched_port( - struct rte_cfgfile *file, - struct rte_sched_port_params *port_params) -{ - const char *entry; - int j; - - entry = rte_cfgfile_get_entry(file, "port", "frame overhead"); - if (entry) - port_params->frame_overhead = (uint32_t)atoi(entry); - - entry = rte_cfgfile_get_entry(file, "port", "mtu"); - if (entry) - port_params->mtu = (uint32_t)atoi(entry); - - entry = rte_cfgfile_get_entry(file, - "port", - "number of subports per port"); - if (entry) - port_params->n_subports_per_port = (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, - "port", - "number of pipes per subport"); - if (entry) - port_params->n_pipes_per_subport = (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, "port", "queue sizes"); - if (entry) { - char *next; - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - port_params->qsize[j] = (uint16_t) - strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - -#ifdef RTE_SCHED_RED - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - char str[32]; - - /* Parse WRED min thresholds */ - snprintf(str, sizeof(str), "tc %" PRId32 " wred min", j); - entry = rte_cfgfile_get_entry(file, "red", str); - if (entry) { - char *next; - int k; - - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < e_RTE_METER_COLORS; k++) { - port_params->red_params[j][k].min_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED max thresholds */ - snprintf(str, sizeof(str), "tc %" PRId32 " wred max", j); - entry = rte_cfgfile_get_entry(file, "red", str); - if (entry) { - char *next; - int k; - - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < e_RTE_METER_COLORS; k++) { - port_params->red_params[j][k].max_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED inverse mark probabilities */ - snprintf(str, sizeof(str), "tc %" PRId32 " wred inv prob", j); - entry = rte_cfgfile_get_entry(file, "red", str); - if (entry) { - char *next; - int k; - - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < e_RTE_METER_COLORS; k++) { - port_params->red_params[j][k].maxp_inv - = (uint8_t)strtol(entry, &next, 10); - - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED EWMA filter weights */ - snprintf(str, sizeof(str), "tc %" PRId32 " wred weight", j); - entry = rte_cfgfile_get_entry(file, "red", str); - if (entry) { - char *next; - int k; - - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < e_RTE_METER_COLORS; k++) { - port_params->red_params[j][k].wq_log2 - = (uint8_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - } -#endif /* RTE_SCHED_RED */ - - return 0; -} - -static int -tm_cfgfile_load_sched_pipe( - struct rte_cfgfile *file, - struct rte_sched_port_params *port_params, - struct rte_sched_pipe_params *pipe_params) -{ - int i, j; - char *next; - const char *entry; - int profiles; - - profiles = rte_cfgfile_num_sections(file, - "pipe profile", sizeof("pipe profile") - 1); - port_params->n_pipe_profiles = profiles; - - for (j = 0; j < profiles; j++) { - char pipe_name[32]; - - snprintf(pipe_name, sizeof(pipe_name), - "pipe profile %" PRId32, j); - - entry = rte_cfgfile_get_entry(file, pipe_name, "tb rate"); - if (entry) - pipe_params[j].tb_rate = (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, pipe_name, "tb size"); - if (entry) - pipe_params[j].tb_size = (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, pipe_name, "tc period"); - if (entry) - pipe_params[j].tc_period = (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, pipe_name, "tc 0 rate"); - if (entry) - pipe_params[j].tc_rate[0] = (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, pipe_name, "tc 1 rate"); - if (entry) - pipe_params[j].tc_rate[1] = (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, pipe_name, "tc 2 rate"); - if (entry) - pipe_params[j].tc_rate[2] = (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, pipe_name, "tc 3 rate"); - if (entry) - pipe_params[j].tc_rate[3] = (uint32_t) atoi(entry); - -#ifdef RTE_SCHED_SUBPORT_TC_OV - entry = rte_cfgfile_get_entry(file, pipe_name, - "tc 3 oversubscription weight"); - if (entry) - pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry); -#endif - - entry = rte_cfgfile_get_entry(file, - pipe_name, - "tc 0 wrr weights"); - if (entry) - for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { - pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*0 + i] = - (uint8_t) strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - entry = rte_cfgfile_get_entry(file, pipe_name, "tc 1 wrr weights"); - if (entry) - for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { - pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*1 + i] = - (uint8_t) strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - entry = rte_cfgfile_get_entry(file, pipe_name, "tc 2 wrr weights"); - if (entry) - for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { - pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*2 + i] = - (uint8_t) strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - entry = rte_cfgfile_get_entry(file, pipe_name, "tc 3 wrr weights"); - if (entry) - for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { - pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*3 + i] = - (uint8_t) strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - return 0; -} - -static int -tm_cfgfile_load_sched_subport( - struct rte_cfgfile *file, - struct rte_sched_subport_params *subport_params, - int *pipe_to_profile) -{ - const char *entry; - int i, j, k; - - for (i = 0; i < APP_MAX_SCHED_SUBPORTS; i++) { - char sec_name[CFG_NAME_LEN]; - - snprintf(sec_name, sizeof(sec_name), - "subport %" PRId32, i); - - if (rte_cfgfile_has_section(file, sec_name)) { - entry = rte_cfgfile_get_entry(file, - sec_name, - "tb rate"); - if (entry) - subport_params[i].tb_rate = - (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, - sec_name, - "tb size"); - if (entry) - subport_params[i].tb_size = - (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, - sec_name, - "tc period"); - if (entry) - subport_params[i].tc_period = - (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, - sec_name, - "tc 0 rate"); - if (entry) - subport_params[i].tc_rate[0] = - (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, - sec_name, - "tc 1 rate"); - if (entry) - subport_params[i].tc_rate[1] = - (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, - sec_name, - "tc 2 rate"); - if (entry) - subport_params[i].tc_rate[2] = - (uint32_t) atoi(entry); - - entry = rte_cfgfile_get_entry(file, - sec_name, - "tc 3 rate"); - if (entry) - subport_params[i].tc_rate[3] = - (uint32_t) atoi(entry); - - int n_entries = rte_cfgfile_section_num_entries(file, - sec_name); - struct rte_cfgfile_entry entries[n_entries]; - - rte_cfgfile_section_entries(file, - sec_name, - entries, - n_entries); - - for (j = 0; j < n_entries; j++) - if (strncmp("pipe", - entries[j].name, - sizeof("pipe") - 1) == 0) { - int profile; - char *tokens[2] = {NULL, NULL}; - int n_tokens; - int begin, end; - char name[CFG_NAME_LEN + 1]; - - profile = atoi(entries[j].value); - strncpy(name, - entries[j].name, - sizeof(name)); - n_tokens = rte_strsplit( - &name[sizeof("pipe")], - strnlen(name, CFG_NAME_LEN), - tokens, 2, '-'); - - begin = atoi(tokens[0]); - if (n_tokens == 2) - end = atoi(tokens[1]); - else - end = begin; - - if ((end >= APP_MAX_SCHED_PIPES) || - (begin > end)) - return -1; - - for (k = begin; k <= end; k++) { - char profile_name[CFG_NAME_LEN]; - - snprintf(profile_name, - sizeof(profile_name), - "pipe profile %" PRId32, - profile); - if (rte_cfgfile_has_section(file, profile_name)) - pipe_to_profile[i * APP_MAX_SCHED_PIPES + k] = profile; - else - rte_exit(EXIT_FAILURE, - "Wrong pipe profile %s\n", - entries[j].value); - } - } - } - } - - return 0; -} - -static int -tm_cfgfile_load(struct app_pktq_tm_params *tm) -{ - struct rte_cfgfile *file; - uint32_t i; - - memset(tm->sched_subport_params, 0, sizeof(tm->sched_subport_params)); - memset(tm->sched_pipe_profiles, 0, sizeof(tm->sched_pipe_profiles)); - memset(&tm->sched_port_params, 0, sizeof(tm->sched_port_params)); - for (i = 0; i < APP_MAX_SCHED_SUBPORTS * APP_MAX_SCHED_PIPES; i++) - tm->sched_pipe_to_profile[i] = -1; - - tm->sched_port_params.pipe_profiles = &tm->sched_pipe_profiles[0]; - - if (tm->file_name[0] == '\0') - return -1; - - file = rte_cfgfile_load(tm->file_name, 0); - if (file == NULL) - return -1; - - tm_cfgfile_load_sched_port(file, - &tm->sched_port_params); - tm_cfgfile_load_sched_subport(file, - tm->sched_subport_params, - tm->sched_pipe_to_profile); - tm_cfgfile_load_sched_pipe(file, - &tm->sched_port_params, - tm->sched_pipe_profiles); - - rte_cfgfile_close(file); - return 0; -} - -int -app_config_parse_tm(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < RTE_DIM(app->tm_params); i++) { - struct app_pktq_tm_params *p = &app->tm_params[i]; - int status; - - if (!APP_PARAM_VALID(p)) - break; - - status = tm_cfgfile_load(p); - APP_CHECK(status == 0, - "Parse error for %s configuration file \"%s\"\n", - p->name, - p->file_name); - } - - return 0; -} diff --git a/examples/ip_pipeline/conn.c b/examples/ip_pipeline/conn.c new file mode 100644 index 00000000..6b08e9e8 --- /dev/null +++ b/examples/ip_pipeline/conn.c @@ -0,0 +1,329 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> + +#define __USE_GNU +#include <sys/socket.h> + +#include <sys/epoll.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> + +#include "conn.h" + +#define MSG_CMD_TOO_LONG "Command too long." + +struct conn { + char *welcome; + char *prompt; + char *buf; + char *msg_in; + char *msg_out; + size_t buf_size; + size_t msg_in_len_max; + size_t msg_out_len_max; + size_t msg_in_len; + int fd_server; + int fd_client_group; + conn_msg_handle_t msg_handle; +}; + +struct conn * +conn_init(struct conn_params *p) +{ + struct sockaddr_in server_address; + struct conn *conn; + int fd_server, fd_client_group, status; + + memset(&server_address, 0, sizeof(server_address)); + + /* Check input arguments */ + if ((p == NULL) || + (p->welcome == NULL) || + (p->prompt == NULL) || + (p->addr == NULL) || + (p->buf_size == 0) || + (p->msg_in_len_max == 0) || + (p->msg_out_len_max == 0) || + (p->msg_handle == NULL)) + return NULL; + + status = inet_aton(p->addr, &server_address.sin_addr); + if (status == 0) + return NULL; + + /* Memory allocation */ + conn = calloc(1, sizeof(struct conn)); + if (conn == NULL) + return NULL; + + conn->welcome = calloc(1, CONN_WELCOME_LEN_MAX + 1); + conn->prompt = calloc(1, CONN_PROMPT_LEN_MAX + 1); + conn->buf = calloc(1, p->buf_size); + conn->msg_in = calloc(1, p->msg_in_len_max + 1); + conn->msg_out = calloc(1, p->msg_out_len_max + 1); + + if ((conn->welcome == NULL) || + (conn->prompt == NULL) || + (conn->buf == NULL) || + (conn->msg_in == NULL) || + (conn->msg_out == NULL)) { + conn_free(conn); + return NULL; + } + + /* Server socket */ + server_address.sin_family = AF_INET; + server_address.sin_port = htons(p->port); + + fd_server = socket(AF_INET, + SOCK_STREAM | SOCK_NONBLOCK, + 0); + if (fd_server == -1) { + conn_free(conn); + return NULL; + } + + status = bind(fd_server, + (struct sockaddr *) &server_address, + sizeof(server_address)); + if (status == -1) { + conn_free(conn); + close(fd_server); + return NULL; + } + + status = listen(fd_server, 16); + if (status == -1) { + conn_free(conn); + close(fd_server); + return NULL; + } + + /* Client group */ + fd_client_group = epoll_create(1); + if (fd_client_group == -1) { + conn_free(conn); + close(fd_server); + return NULL; + } + + /* Fill in */ + strncpy(conn->welcome, p->welcome, CONN_WELCOME_LEN_MAX); + strncpy(conn->prompt, p->prompt, CONN_PROMPT_LEN_MAX); + conn->buf_size = p->buf_size; + conn->msg_in_len_max = p->msg_in_len_max; + conn->msg_out_len_max = p->msg_out_len_max; + conn->msg_in_len = 0; + conn->fd_server = fd_server; + conn->fd_client_group = fd_client_group; + conn->msg_handle = p->msg_handle; + + return conn; +} + +void +conn_free(struct conn *conn) +{ + if (conn == NULL) + return; + + if (conn->fd_client_group) + close(conn->fd_client_group); + + if (conn->fd_server) + close(conn->fd_server); + + free(conn->msg_out); + free(conn->msg_in); + free(conn->prompt); + free(conn->welcome); + free(conn); +} + +int +conn_poll_for_conn(struct conn *conn) +{ + struct sockaddr_in client_address; + struct epoll_event event; + socklen_t client_address_length; + int fd_client, status; + + /* Check input arguments */ + if (conn == NULL) + return -1; + + /* Server socket */ + client_address_length = sizeof(client_address); + fd_client = accept4(conn->fd_server, + (struct sockaddr *) &client_address, + &client_address_length, + SOCK_NONBLOCK); + if (fd_client == -1) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + return 0; + + return -1; + } + + /* Client group */ + event.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP; + event.data.fd = fd_client; + + status = epoll_ctl(conn->fd_client_group, + EPOLL_CTL_ADD, + fd_client, + &event); + if (status == -1) { + close(fd_client); + return -1; + } + + /* Client */ + status = write(fd_client, + conn->welcome, + strlen(conn->welcome)); + if (status == -1) { + close(fd_client); + return -1; + } + + status = write(fd_client, + conn->prompt, + strlen(conn->prompt)); + if (status == -1) { + close(fd_client); + return -1; + } + + return 0; +} + +static int +data_event_handle(struct conn *conn, + int fd_client) +{ + ssize_t len, i, status; + + /* Read input message */ + + len = read(fd_client, + conn->buf, + conn->buf_size); + if (len == -1) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + return 0; + + return -1; + } + if (len == 0) + return 0; + + /* Handle input messages */ + for (i = 0; i < len; i++) { + if (conn->buf[i] == '\n') { + size_t n; + + conn->msg_in[conn->msg_in_len] = 0; + conn->msg_out[0] = 0; + + conn->msg_handle(conn->msg_in, + conn->msg_out, + conn->msg_out_len_max); + + n = strlen(conn->msg_out); + if (n) { + status = write(fd_client, + conn->msg_out, + n); + if (status == -1) + return status; + } + + conn->msg_in_len = 0; + } else if (conn->msg_in_len < conn->msg_in_len_max) { + conn->msg_in[conn->msg_in_len] = conn->buf[i]; + conn->msg_in_len++; + } else { + status = write(fd_client, + MSG_CMD_TOO_LONG, + strlen(MSG_CMD_TOO_LONG)); + if (status == -1) + return status; + + conn->msg_in_len = 0; + } + } + + /* Write prompt */ + status = write(fd_client, + conn->prompt, + strlen(conn->prompt)); + if (status == -1) + return status; + + return 0; +} + +static int +control_event_handle(struct conn *conn, + int fd_client) +{ + int status; + + status = epoll_ctl(conn->fd_client_group, + EPOLL_CTL_DEL, + fd_client, + NULL); + if (status == -1) + return -1; + + status = close(fd_client); + if (status == -1) + return -1; + + return 0; +} + +int +conn_poll_for_msg(struct conn *conn) +{ + struct epoll_event event; + int fd_client, status, status_data = 0, status_control = 0; + + /* Check input arguments */ + if (conn == NULL) + return -1; + + /* Client group */ + status = epoll_wait(conn->fd_client_group, + &event, + 1, + 0); + if (status == -1) + return -1; + if (status == 0) + return 0; + + fd_client = event.data.fd; + + /* Data available */ + if (event.events & EPOLLIN) + status_data = data_event_handle(conn, fd_client); + + /* Control events */ + if (event.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP)) + status_control = control_event_handle(conn, fd_client); + + if (status_data || status_control) + return -1; + + return 0; +} diff --git a/examples/ip_pipeline/conn.h b/examples/ip_pipeline/conn.h new file mode 100644 index 00000000..46f9f95e --- /dev/null +++ b/examples/ip_pipeline/conn.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef __INCLUDE_CONN_H__ +#define __INCLUDE_CONN_H__ + +#include <stdint.h> + +struct conn; + +#ifndef CONN_WELCOME_LEN_MAX +#define CONN_WELCOME_LEN_MAX 1024 +#endif + +#ifndef CONN_PROMPT_LEN_MAX +#define CONN_PROMPT_LEN_MAX 16 +#endif + +typedef void (*conn_msg_handle_t)(char *msg_in, + char *msg_out, + size_t msg_out_len_max); + +struct conn_params { + const char *welcome; + const char *prompt; + const char *addr; + uint16_t port; + size_t buf_size; + size_t msg_in_len_max; + size_t msg_out_len_max; + conn_msg_handle_t msg_handle; +}; + +struct conn * +conn_init(struct conn_params *p); + +void +conn_free(struct conn *conn); + +int +conn_poll_for_conn(struct conn *conn); + +int +conn_poll_for_msg(struct conn *conn); + +#endif diff --git a/examples/ip_pipeline/cpu_core_map.c b/examples/ip_pipeline/cpu_core_map.c deleted file mode 100644 index 231f38ef..00000000 --- a/examples/ip_pipeline/cpu_core_map.c +++ /dev/null @@ -1,471 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#include <inttypes.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include <rte_lcore.h> - -#include "cpu_core_map.h" - -struct cpu_core_map { - uint32_t n_max_sockets; - uint32_t n_max_cores_per_socket; - uint32_t n_max_ht_per_core; - uint32_t n_sockets; - uint32_t n_cores_per_socket; - uint32_t n_ht_per_core; - int map[0]; -}; - -static inline uint32_t -cpu_core_map_pos(struct cpu_core_map *map, - uint32_t socket_id, - uint32_t core_id, - uint32_t ht_id) -{ - return (socket_id * map->n_max_cores_per_socket + core_id) * - map->n_max_ht_per_core + ht_id; -} - -static int -cpu_core_map_compute_eal(struct cpu_core_map *map); - -static int -cpu_core_map_compute_linux(struct cpu_core_map *map); - -static int -cpu_core_map_compute_and_check(struct cpu_core_map *map); - -struct cpu_core_map * -cpu_core_map_init(uint32_t n_max_sockets, - uint32_t n_max_cores_per_socket, - uint32_t n_max_ht_per_core, - uint32_t eal_initialized) -{ - uint32_t map_size, map_mem_size, i; - struct cpu_core_map *map; - int status; - - /* Check input arguments */ - if ((n_max_sockets == 0) || - (n_max_cores_per_socket == 0) || - (n_max_ht_per_core == 0)) - return NULL; - - /* Memory allocation */ - map_size = n_max_sockets * n_max_cores_per_socket * n_max_ht_per_core; - map_mem_size = sizeof(struct cpu_core_map) + map_size * sizeof(int); - map = (struct cpu_core_map *) malloc(map_mem_size); - if (map == NULL) - return NULL; - - /* Initialization */ - map->n_max_sockets = n_max_sockets; - map->n_max_cores_per_socket = n_max_cores_per_socket; - map->n_max_ht_per_core = n_max_ht_per_core; - map->n_sockets = 0; - map->n_cores_per_socket = 0; - map->n_ht_per_core = 0; - - for (i = 0; i < map_size; i++) - map->map[i] = -1; - - status = (eal_initialized) ? - cpu_core_map_compute_eal(map) : - cpu_core_map_compute_linux(map); - - if (status) { - free(map); - return NULL; - } - - status = cpu_core_map_compute_and_check(map); - if (status) { - free(map); - return NULL; - } - - return map; -} - -int -cpu_core_map_compute_eal(struct cpu_core_map *map) -{ - uint32_t socket_id, core_id, ht_id; - - /* Compute map */ - for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) { - uint32_t n_detected, core_id_contig; - int lcore_id; - - n_detected = 0; - for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { - struct lcore_config *p = &lcore_config[lcore_id]; - - if ((p->detected) && (p->socket_id == socket_id)) - n_detected++; - } - - core_id_contig = 0; - - for (core_id = 0; n_detected ; core_id++) { - ht_id = 0; - - for (lcore_id = 0; - lcore_id < RTE_MAX_LCORE; - lcore_id++) { - struct lcore_config *p = - &lcore_config[lcore_id]; - - if ((p->detected) && - (p->socket_id == socket_id) && - (p->core_id == core_id)) { - uint32_t pos = cpu_core_map_pos(map, - socket_id, - core_id_contig, - ht_id); - - map->map[pos] = lcore_id; - ht_id++; - n_detected--; - } - } - - if (ht_id) { - core_id_contig++; - if (core_id_contig == - map->n_max_cores_per_socket) - return -1; - } - } - } - - return 0; -} - -int -cpu_core_map_compute_and_check(struct cpu_core_map *map) -{ - uint32_t socket_id, core_id, ht_id; - - /* Compute n_ht_per_core, n_cores_per_socket, n_sockets */ - for (ht_id = 0; ht_id < map->n_max_ht_per_core; ht_id++) { - if (map->map[ht_id] == -1) - break; - - map->n_ht_per_core++; - } - - if (map->n_ht_per_core == 0) - return -1; - - for (core_id = 0; core_id < map->n_max_cores_per_socket; core_id++) { - uint32_t pos = core_id * map->n_max_ht_per_core; - - if (map->map[pos] == -1) - break; - - map->n_cores_per_socket++; - } - - if (map->n_cores_per_socket == 0) - return -1; - - for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) { - uint32_t pos = socket_id * map->n_max_cores_per_socket * - map->n_max_ht_per_core; - - if (map->map[pos] == -1) - break; - - map->n_sockets++; - } - - if (map->n_sockets == 0) - return -1; - - /* Check that each socket has exactly the same number of cores - and that each core has exactly the same number of hyper-threads */ - for (socket_id = 0; socket_id < map->n_sockets; socket_id++) { - for (core_id = 0; core_id < map->n_cores_per_socket; core_id++) - for (ht_id = 0; - ht_id < map->n_max_ht_per_core; - ht_id++) { - uint32_t pos = (socket_id * - map->n_max_cores_per_socket + core_id) * - map->n_max_ht_per_core + ht_id; - - if (((ht_id < map->n_ht_per_core) && - (map->map[pos] == -1)) || - ((ht_id >= map->n_ht_per_core) && - (map->map[pos] != -1))) - return -1; - } - - for ( ; core_id < map->n_max_cores_per_socket; core_id++) - for (ht_id = 0; - ht_id < map->n_max_ht_per_core; - ht_id++) { - uint32_t pos = cpu_core_map_pos(map, - socket_id, - core_id, - ht_id); - - if (map->map[pos] != -1) - return -1; - } - } - - return 0; -} - -#define FILE_LINUX_CPU_N_LCORES \ - "/sys/devices/system/cpu/present" - -static int -cpu_core_map_get_n_lcores_linux(void) -{ - char buffer[64], *string; - FILE *fd; - - fd = fopen(FILE_LINUX_CPU_N_LCORES, "r"); - if (fd == NULL) - return -1; - - if (fgets(buffer, sizeof(buffer), fd) == NULL) { - fclose(fd); - return -1; - } - - fclose(fd); - - string = index(buffer, '-'); - if (string == NULL) - return -1; - - return atoi(++string) + 1; -} - -#define FILE_LINUX_CPU_CORE_ID \ - "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/core_id" - -static int -cpu_core_map_get_core_id_linux(int lcore_id) -{ - char buffer[64]; - FILE *fd; - int core_id; - - snprintf(buffer, sizeof(buffer), FILE_LINUX_CPU_CORE_ID, lcore_id); - fd = fopen(buffer, "r"); - if (fd == NULL) - return -1; - - if (fgets(buffer, sizeof(buffer), fd) == NULL) { - fclose(fd); - return -1; - } - - fclose(fd); - - core_id = atoi(buffer); - return core_id; -} - -#define FILE_LINUX_CPU_SOCKET_ID \ - "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/physical_package_id" - -static int -cpu_core_map_get_socket_id_linux(int lcore_id) -{ - char buffer[64]; - FILE *fd; - int socket_id; - - snprintf(buffer, sizeof(buffer), FILE_LINUX_CPU_SOCKET_ID, lcore_id); - fd = fopen(buffer, "r"); - if (fd == NULL) - return -1; - - if (fgets(buffer, sizeof(buffer), fd) == NULL) { - fclose(fd); - return -1; - } - - fclose(fd); - - socket_id = atoi(buffer); - return socket_id; -} - -int -cpu_core_map_compute_linux(struct cpu_core_map *map) -{ - uint32_t socket_id, core_id, ht_id; - int n_lcores; - - n_lcores = cpu_core_map_get_n_lcores_linux(); - if (n_lcores <= 0) - return -1; - - /* Compute map */ - for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) { - uint32_t n_detected, core_id_contig; - int lcore_id; - - n_detected = 0; - for (lcore_id = 0; lcore_id < n_lcores; lcore_id++) { - int lcore_socket_id = - cpu_core_map_get_socket_id_linux(lcore_id); - -#if !defined(RTE_ARCH_PPC_64) - if (lcore_socket_id < 0) - return -1; -#endif - - if (((uint32_t) lcore_socket_id) == socket_id) - n_detected++; - } - - core_id_contig = 0; - - for (core_id = 0; n_detected ; core_id++) { - ht_id = 0; - - for (lcore_id = 0; lcore_id < n_lcores; lcore_id++) { - int lcore_socket_id = - cpu_core_map_get_socket_id_linux( - lcore_id); - -#if !defined(RTE_ARCH_PPC_64) - if (lcore_socket_id < 0) - return -1; - - int lcore_core_id = - cpu_core_map_get_core_id_linux( - lcore_id); - - if (lcore_core_id < 0) - return -1; -#endif - -#if !defined(RTE_ARCH_PPC_64) - if (((uint32_t) lcore_socket_id == socket_id) && - ((uint32_t) lcore_core_id == core_id)) { -#else - if (((uint32_t) lcore_socket_id == socket_id)) { -#endif - uint32_t pos = cpu_core_map_pos(map, - socket_id, - core_id_contig, - ht_id); - - map->map[pos] = lcore_id; - ht_id++; - n_detected--; - } - } - - if (ht_id) { - core_id_contig++; - if (core_id_contig == - map->n_max_cores_per_socket) - return -1; - } - } - } - - return 0; -} - -void -cpu_core_map_print(struct cpu_core_map *map) -{ - uint32_t socket_id, core_id, ht_id; - - if (map == NULL) - return; - - for (socket_id = 0; socket_id < map->n_sockets; socket_id++) { - printf("Socket %" PRIu32 ":\n", socket_id); - - for (core_id = 0; - core_id < map->n_cores_per_socket; - core_id++) { - printf("[%" PRIu32 "] = [", core_id); - - for (ht_id = 0; ht_id < map->n_ht_per_core; ht_id++) { - int lcore_id = cpu_core_map_get_lcore_id(map, - socket_id, - core_id, - ht_id); - - uint32_t core_id_noncontig = - cpu_core_map_get_core_id_linux( - lcore_id); - - printf(" %" PRId32 " (%" PRIu32 ") ", - lcore_id, - core_id_noncontig); - } - - printf("]\n"); - } - } -} - -uint32_t -cpu_core_map_get_n_sockets(struct cpu_core_map *map) -{ - if (map == NULL) - return 0; - - return map->n_sockets; -} - -uint32_t -cpu_core_map_get_n_cores_per_socket(struct cpu_core_map *map) -{ - if (map == NULL) - return 0; - - return map->n_cores_per_socket; -} - -uint32_t -cpu_core_map_get_n_ht_per_core(struct cpu_core_map *map) -{ - if (map == NULL) - return 0; - - return map->n_ht_per_core; -} - -int -cpu_core_map_get_lcore_id(struct cpu_core_map *map, - uint32_t socket_id, - uint32_t core_id, - uint32_t ht_id) -{ - uint32_t pos; - - if ((map == NULL) || - (socket_id >= map->n_sockets) || - (core_id >= map->n_cores_per_socket) || - (ht_id >= map->n_ht_per_core)) - return -1; - - pos = cpu_core_map_pos(map, socket_id, core_id, ht_id); - - return map->map[pos]; -} - -void -cpu_core_map_free(struct cpu_core_map *map) -{ - free(map); -} diff --git a/examples/ip_pipeline/cpu_core_map.h b/examples/ip_pipeline/cpu_core_map.h deleted file mode 100644 index 5e50f6e5..00000000 --- a/examples/ip_pipeline/cpu_core_map.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_CPU_CORE_MAP_H__ -#define __INCLUDE_CPU_CORE_MAP_H__ - -#include <stdio.h> - -#include <rte_lcore.h> - -struct cpu_core_map; - -struct cpu_core_map * -cpu_core_map_init(uint32_t n_max_sockets, - uint32_t n_max_cores_per_socket, - uint32_t n_max_ht_per_core, - uint32_t eal_initialized); - -uint32_t -cpu_core_map_get_n_sockets(struct cpu_core_map *map); - -uint32_t -cpu_core_map_get_n_cores_per_socket(struct cpu_core_map *map); - -uint32_t -cpu_core_map_get_n_ht_per_core(struct cpu_core_map *map); - -int -cpu_core_map_get_lcore_id(struct cpu_core_map *map, - uint32_t socket_id, - uint32_t core_id, - uint32_t ht_id); - -void cpu_core_map_print(struct cpu_core_map *map); - -void -cpu_core_map_free(struct cpu_core_map *map); - -#endif diff --git a/examples/ip_pipeline/examples/firewall.cli b/examples/ip_pipeline/examples/firewall.cli new file mode 100644 index 00000000..269256c1 --- /dev/null +++ b/examples/ip_pipeline/examples/firewall.cli @@ -0,0 +1,59 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2010-2018 Intel Corporation + +; _______________ +; LINK0 RXQ0 --->| |---> LINK0 TXQ0 +; | | +; LINK1 RXQ0 --->| |---> LINK1 TXQ0 +; | Firewall | +; LINK2 RXQ0 --->| |---> LINK2 TXQ0 +; | | +; LINK3 RXQ0 --->| |---> LINK3 TXQ0 +; |_______________| +; | +; -+- +; +; Input packet: Ethernet/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 IPv4 header 270 20 + +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 + +link LINK0 dev 0000:02:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK1 dev 0000:02:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK2 dev 0000:06:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK3 dev 0000:06:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on + +table action profile AP0 ipv4 offset 270 fwd + +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 + +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK2 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK3 rxq 0 + +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK1 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK2 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK3 txq 0 + +pipeline PIPELINE0 table match acl ipv4 offset 270 size 4K action AP0 + +pipeline PIPELINE0 port in 0 table 0 +pipeline PIPELINE0 port in 1 table 0 +pipeline PIPELINE0 port in 2 table 0 +pipeline PIPELINE0 port in 3 table 0 + +thread 1 pipeline PIPELINE0 enable + +pipeline PIPELINE0 table 0 rule add match default action fwd drop +pipeline PIPELINE0 table 0 rule add match acl priority 0 ipv4 0.0.0.0 0 100.0.0.0 10 0 65535 0 65535 6 action fwd port 0 +pipeline PIPELINE0 table 0 rule add match acl priority 0 ipv4 0.0.0.0 0 100.64.0.0 10 0 65535 0 65535 6 action fwd port 1 +pipeline PIPELINE0 table 0 rule add match acl priority 0 ipv4 0.0.0.0 0 100.128.0.0 10 0 65535 0 65535 6 action fwd port 2 +pipeline PIPELINE0 table 0 rule add match acl priority 0 ipv4 0.0.0.0 0 100.192.0.0 10 0 65535 0 65535 6 action fwd port 3 diff --git a/examples/ip_pipeline/examples/flow.cli b/examples/ip_pipeline/examples/flow.cli new file mode 100644 index 00000000..426ff902 --- /dev/null +++ b/examples/ip_pipeline/examples/flow.cli @@ -0,0 +1,60 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2010-2018 Intel Corporation + +; ________________ +; LINK0 RXQ0 --->| |---> LINK0 TXQ0 +; | | +; LINK1 RXQ0 --->| |---> LINK1 TXQ0 +; | Flow | +; LINK2 RXQ0 --->| Classification |---> LINK2 TXQ0 +; | | +; LINK3 RXQ0 --->| |---> LINK3 TXQ0 +; |________________| +; | +; +-----------> SINK0 (flow lookup miss) +; +; Input packet: Ethernet/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 IPv4 header 270 20 + +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 + +link LINK0 dev 0000:02:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK1 dev 0000:02:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK2 dev 0000:06:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK3 dev 0000:06:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on + +table action profile AP0 ipv4 offset 270 fwd + +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 + +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK2 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK3 rxq 0 + +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK1 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK2 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK3 txq 0 +pipeline PIPELINE0 port out bsz 32 sink + +pipeline PIPELINE0 table match hash ext key 16 mask 00FF0000FFFFFFFFFFFFFFFFFFFFFFFF offset 278 buckets 16K size 65K action AP0 + +pipeline PIPELINE0 port in 0 table 0 +pipeline PIPELINE0 port in 1 table 0 +pipeline PIPELINE0 port in 2 table 0 +pipeline PIPELINE0 port in 3 table 0 + +thread 1 pipeline PIPELINE0 enable + +pipeline PIPELINE0 table 0 rule add match default action fwd port 4 +pipeline PIPELINE0 table 0 rule add match hash ipv4_5tuple 100.0.0.10 200.0.0.10 100 200 6 action fwd port 0 +pipeline PIPELINE0 table 0 rule add match hash ipv4_5tuple 100.0.0.11 200.0.0.11 101 201 6 action fwd port 1 +pipeline PIPELINE0 table 0 rule add match hash ipv4_5tuple 100.0.0.12 200.0.0.12 102 202 6 action fwd port 2 +pipeline PIPELINE0 table 0 rule add match hash ipv4_5tuple 100.0.0.13 200.0.0.13 103 203 6 action fwd port 3 diff --git a/examples/ip_pipeline/examples/kni.cli b/examples/ip_pipeline/examples/kni.cli new file mode 100644 index 00000000..14383409 --- /dev/null +++ b/examples/ip_pipeline/examples/kni.cli @@ -0,0 +1,69 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2010-2018 Intel Corporation + +; _______________ ______________________ +; | | KNI0 | | +; LINK0 RXQ0 --->|...............|------->|--+ | +; | | KNI1 | | br0 | +; LINK1 TXQ0 <---|...............|<-------|<-+ | +; | | | Linux Kernel | +; | PIPELINE0 | | Network Stack | +; | | KNI1 | | +; LINK1 RXQ0 --->|...............|------->|--+ | +; | | KNI0 | | br0 | +; LINK0 TXQ0 <---|...............|<-------|<-+ | +; |_______________| |______________________| +; +; Insert Linux kernel KNI module: +; [Linux]$ insmod rte_kni.ko +; +; Configure Linux kernel bridge between KNI0 and KNI1 interfaces: +; [Linux]$ brctl addbr br0 +; [Linux]$ brctl addif br0 KNI0 +; [Linux]$ brctl addif br0 KNI1 +; [Linux]$ ifconfig br0 up +; [Linux]$ ifconfig KNI0 up +; [Linux]$ ifconfig KNI1 up +; +; Monitor packet forwarding performed by Linux kernel between KNI0 and KNI1: +; [Linux]$ tcpdump -i KNI0 +; [Linux]$ tcpdump -i KNI1 + +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 + +link LINK0 dev 0000:02:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK1 dev 0000:02:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on + +kni KNI0 link LINK0 mempool MEMPOOL0 +kni KNI1 link LINK1 mempool MEMPOOL0 + +table action profile AP0 ipv4 offset 270 fwd + +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 + +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 +pipeline PIPELINE0 port in bsz 32 kni KNI1 +pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 +pipeline PIPELINE0 port in bsz 32 kni KNI0 + +pipeline PIPELINE0 port out bsz 32 kni KNI0 +pipeline PIPELINE0 port out bsz 32 link LINK1 txq 0 +pipeline PIPELINE0 port out bsz 32 kni KNI1 +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 + +pipeline PIPELINE0 table match stub action AP0 +pipeline PIPELINE0 table match stub action AP0 +pipeline PIPELINE0 table match stub action AP0 +pipeline PIPELINE0 table match stub action AP0 + +pipeline PIPELINE0 port in 0 table 0 +pipeline PIPELINE0 port in 1 table 1 +pipeline PIPELINE0 port in 2 table 2 +pipeline PIPELINE0 port in 3 table 3 + +thread 1 pipeline PIPELINE0 enable + +pipeline PIPELINE0 table 0 rule add match default action fwd port 0 +pipeline PIPELINE0 table 1 rule add match default action fwd port 1 +pipeline PIPELINE0 table 2 rule add match default action fwd port 2 +pipeline PIPELINE0 table 3 rule add match default action fwd port 3 diff --git a/examples/ip_pipeline/examples/l2fwd.cli b/examples/ip_pipeline/examples/l2fwd.cli new file mode 100644 index 00000000..35e77cc9 --- /dev/null +++ b/examples/ip_pipeline/examples/l2fwd.cli @@ -0,0 +1,51 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2010-2018 Intel Corporation + +; The pipeline below implements a simple pass-through connection between the +; input ports to the output ports, as in this diagram: +; ________________ +; LINK0 RXQ0 --->|................|---> LINK1 TXQ0 +; | | +; LINK1 RXQ0 --->|................|---> LINK0 TXQ0 +; | PIPELINE0 | +; LINK2 RXQ0 --->|................|---> LINK3 TXQ0 +; | | +; LINK3 RXQ0 --->|................|---> LINK2 TXQ0 +; |________________| +; + +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 + +link LINK0 dev 0000:02:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK1 dev 0000:02:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK2 dev 0000:06:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK3 dev 0000:06:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on + +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 + +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK2 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK3 rxq 0 + +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK1 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK2 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK3 txq 0 + +pipeline PIPELINE0 table match stub +pipeline PIPELINE0 table match stub +pipeline PIPELINE0 table match stub +pipeline PIPELINE0 table match stub + +pipeline PIPELINE0 port in 0 table 0 +pipeline PIPELINE0 port in 1 table 1 +pipeline PIPELINE0 port in 2 table 2 +pipeline PIPELINE0 port in 3 table 3 + +thread 1 pipeline PIPELINE0 enable + +pipeline PIPELINE0 table 0 rule add match default action fwd port 1 +pipeline PIPELINE0 table 1 rule add match default action fwd port 0 +pipeline PIPELINE0 table 2 rule add match default action fwd port 3 +pipeline PIPELINE0 table 3 rule add match default action fwd port 2 diff --git a/examples/ip_pipeline/examples/route.cli b/examples/ip_pipeline/examples/route.cli new file mode 100644 index 00000000..579b36a6 --- /dev/null +++ b/examples/ip_pipeline/examples/route.cli @@ -0,0 +1,60 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2010-2018 Intel Corporation + +; _______________ +; LINK0 RXQ0 --->| |---> LINK0 TXQ0 +; | | +; LINK1 RXQ0 --->| |---> LINK1 TXQ0 +; | Routing | +; LINK2 RXQ0 --->| |---> LINK2 TXQ0 +; | | +; LINK3 RXQ0 --->| |---> LINK3 TXQ0 +; |_______________| +; | +; +-----------> SINK0 (route miss) +; +; Input packet: Ethernet/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 IPv4 header 270 20 + +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 + +link LINK0 dev 0000:02:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK1 dev 0000:02:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK2 dev 0000:06:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK3 dev 0000:06:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on + +table action profile AP0 ipv4 offset 270 fwd encap ether + +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 + +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK2 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK3 rxq 0 + +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK1 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK2 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK3 txq 0 +pipeline PIPELINE0 port out bsz 32 sink + +pipeline PIPELINE0 table match lpm ipv4 offset 286 size 4K action AP0 + +pipeline PIPELINE0 port in 0 table 0 +pipeline PIPELINE0 port in 1 table 0 +pipeline PIPELINE0 port in 2 table 0 +pipeline PIPELINE0 port in 3 table 0 + +thread 1 pipeline PIPELINE0 enable + +pipeline PIPELINE0 table 0 rule add match default action fwd port 4 +pipeline PIPELINE0 table 0 rule add match lpm ipv4 100.0.0.0 10 action fwd port 0 encap ether a0:a1:a2:a3:a4:a5 00:01:02:03:04:05 +pipeline PIPELINE0 table 0 rule add match lpm ipv4 100.64.0.0 10 action fwd port 1 encap ether b0:b1:b2:b3:b4:b5 10:11:12:13:14:15 +pipeline PIPELINE0 table 0 rule add match lpm ipv4 100.128.0.0 10 action fwd port 2 encap ether c0:c1:c2:c3:c4:c5 20:21:22:23:24:25 +pipeline PIPELINE0 table 0 rule add match lpm ipv4 100.192.0.0 10 action fwd port 3 encap ether d0:d1:d2:d3:d4:d5 30:31:32:33:34:35 diff --git a/examples/ip_pipeline/examples/route_ecmp.cli b/examples/ip_pipeline/examples/route_ecmp.cli new file mode 100644 index 00000000..06434a25 --- /dev/null +++ b/examples/ip_pipeline/examples/route_ecmp.cli @@ -0,0 +1,57 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2010-2018 Intel Corporation + +; Equal Cost Multi-Path (ECMP) Routing +; +; Input packet: Ethernet/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 IPv4 header 270 20 + +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 + +link LINK0 dev 0000:02:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK1 dev 0000:02:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK2 dev 0000:06:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK3 dev 0000:06:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on + +table action profile APRT ipv4 offset 270 fwd balance offset 278 mask 00FF0000FFFFFFFFFFFFFFFFFFFFFFFF outoffset 256 +table action profile APNH ipv4 offset 270 fwd encap ether + +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 + +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK2 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK3 rxq 0 + +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK1 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK2 txq 0 +pipeline PIPELINE0 port out bsz 32 link LINK3 txq 0 +pipeline PIPELINE0 port out bsz 32 sink + +pipeline PIPELINE0 table match lpm ipv4 offset 286 size 4K action APRT +pipeline PIPELINE0 table match array offset 256 size 64K action APNH + +pipeline PIPELINE0 port in 0 table 0 +pipeline PIPELINE0 port in 1 table 0 +pipeline PIPELINE0 port in 2 table 0 +pipeline PIPELINE0 port in 3 table 0 + +thread 1 pipeline PIPELINE0 enable + +pipeline PIPELINE0 table 0 rule add match default action fwd port 4 +pipeline PIPELINE0 table 0 rule add match lpm ipv4 100.0.0.0 10 action fwd table 1 balance 0 0 0 0 1 1 2 2 +pipeline PIPELINE0 table 0 rule add match lpm ipv4 100.64.0.0 10 action fwd table 1 balance 1 1 1 1 2 2 3 3 +pipeline PIPELINE0 table 0 rule add match lpm ipv4 100.128.0.0 10 action fwd table 1 balance 2 2 2 2 3 3 0 0 +pipeline PIPELINE0 table 0 rule add match lpm ipv4 100.192.0.0 10 action fwd table 1 balance 3 3 3 3 0 0 1 1 + +pipeline PIPELINE0 table 1 rule add match array 0 action fwd port 0 encap ether a0:a1:a2:a3:a4:a5 00:01:02:03:04:05 +pipeline PIPELINE0 table 1 rule add match array 1 action fwd port 1 encap ether b0:b1:b2:b3:b4:b5 10:11:12:13:14:15 +pipeline PIPELINE0 table 1 rule add match array 2 action fwd port 2 encap ether c0:c1:c2:c3:c4:c5 20:21:22:23:24:25 +pipeline PIPELINE0 table 1 rule add match array 3 action fwd port 3 encap ether d0:d1:d2:d3:d4:d5 30:31:32:33:34:35 diff --git a/examples/ip_pipeline/examples/rss.cli b/examples/ip_pipeline/examples/rss.cli new file mode 100644 index 00000000..29c0a913 --- /dev/null +++ b/examples/ip_pipeline/examples/rss.cli @@ -0,0 +1,112 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2010-2018 Intel Corporation + +; This setup demonstrates the usage of NIC Receive Side Scaling (RSS) feature. +; Each NIC splits the input traffic into 4 RX queues, with each of its RX queues +; being handled by a different pipeline: +; +; +-----------+ +----------+ +; +--------------------------->| | | | +; | +------------------->| PIPELINE0 +--->| LINK 0 |---> +; | | +------------->| (CORE A) | | TX | +; | | | +------->| | | | +; | | | | +-----------+ +----------+ +; +----------+ | | | | +; | |-------+ | | | +;--->| LINK 0 |-----------+ | | | +; | RX |---------+ | | | | +; | |-------+ | | | | | +; +----------+ | | | | | | +-----------+ +----------+ +; | | +---|-----|-----|------->| | | | +; +----------+ | | | +---|-----|------->| PIPELINE1 +--->| LINK 1 |---> +; | |-------|-|-----+ | | +---|------->| (CORE B) | | TX | +;--->| LINK 1 |-------|-|-------+ | | | +----->| | | | +; | RX |-------|-|-------+ | | | | +-----------+ +----------+ +; | |-------|-|-----+ | | | | | +; +----------+ | | | | | | | | +; | | | | | | | | +; +----------+ | | | | | | | | +; | |-------|-|-----|-|---+ | | | +;--->| LINK 2 |-------|-|-----|-|-----+ | | +-----------+ +----------+ +; | RX |-----+ | +-----|-|---------|-|----->| | | | +; | |---+ | | | +---------|-|----->| PIPELINE2 +--->| LINK 2 |---> +; +----------+ | +-|-------|-----------|-|----->| (CORE C) | | TX | +; | | | | | +--->| | | | +; +----------+ | | | | | | +-----------+ +----------+ +; | |---|---|-------|-----------+ | | +;--->| LINK 3 |---|---|-------|-------------+ | +; | RX |---|---|-------|---------------+ +; | |---|---|-------|-----------+ +; +----------+ | | | | +; | | | | +-----------+ +----------+ +; | +-------|-----------|------->| | | | +; | +-----------|------->| PIPELINE3 +--->| LINK 3 |---> +; +-----------------------|------->| (CORE D) | | TX | +; +------->| | | | +; +-----------+ +----------+ +; +; + +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 + +link LINK0 dev 0000:02:00.0 rxq 4 128 MEMPOOL0 txq 1 512 promiscuous on rss 0 1 2 3 +link LINK1 dev 0000:02:00.1 rxq 4 128 MEMPOOL0 txq 1 512 promiscuous on rss 0 1 2 3 +link LINK2 dev 0000:06:00.0 rxq 4 128 MEMPOOL0 txq 1 512 promiscuous on rss 0 1 2 3 +link LINK3 dev 0000:06:00.1 rxq 4 128 MEMPOOL0 txq 1 512 promiscuous on rss 0 1 2 3 + +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK2 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK3 rxq 0 +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 +pipeline PIPELINE0 table match stub +pipeline PIPELINE0 port in 0 table 0 +pipeline PIPELINE0 port in 1 table 0 +pipeline PIPELINE0 port in 2 table 0 +pipeline PIPELINE0 port in 3 table 0 +pipeline PIPELINE0 table 0 rule add match default action fwd port 0 + +pipeline PIPELINE1 period 10 offset_port_id 0 cpu 0 +pipeline PIPELINE1 port in bsz 32 link LINK0 rxq 1 +pipeline PIPELINE1 port in bsz 32 link LINK1 rxq 1 +pipeline PIPELINE1 port in bsz 32 link LINK2 rxq 1 +pipeline PIPELINE1 port in bsz 32 link LINK3 rxq 1 +pipeline PIPELINE1 port out bsz 32 link LINK1 txq 0 +pipeline PIPELINE1 table match stub +pipeline PIPELINE1 port in 0 table 0 +pipeline PIPELINE1 port in 1 table 0 +pipeline PIPELINE1 port in 2 table 0 +pipeline PIPELINE1 port in 3 table 0 +pipeline PIPELINE1 table 0 rule add match default action fwd port 0 + +pipeline PIPELINE2 period 10 offset_port_id 0 cpu 0 +pipeline PIPELINE2 port in bsz 32 link LINK0 rxq 2 +pipeline PIPELINE2 port in bsz 32 link LINK1 rxq 2 +pipeline PIPELINE2 port in bsz 32 link LINK2 rxq 2 +pipeline PIPELINE2 port in bsz 32 link LINK3 rxq 2 +pipeline PIPELINE2 port out bsz 32 link LINK2 txq 0 +pipeline PIPELINE2 table match stub +pipeline PIPELINE2 port in 0 table 0 +pipeline PIPELINE2 port in 1 table 0 +pipeline PIPELINE2 port in 2 table 0 +pipeline PIPELINE2 port in 3 table 0 +pipeline PIPELINE2 table 0 rule add match default action fwd port 0 + +pipeline PIPELINE3 period 10 offset_port_id 0 cpu 0 +pipeline PIPELINE3 port in bsz 32 link LINK0 rxq 3 +pipeline PIPELINE3 port in bsz 32 link LINK1 rxq 3 +pipeline PIPELINE3 port in bsz 32 link LINK2 rxq 3 +pipeline PIPELINE3 port in bsz 32 link LINK3 rxq 3 +pipeline PIPELINE3 port out bsz 32 link LINK3 txq 0 +pipeline PIPELINE3 table match stub +pipeline PIPELINE3 port in 0 table 0 +pipeline PIPELINE3 port in 1 table 0 +pipeline PIPELINE3 port in 2 table 0 +pipeline PIPELINE3 port in 3 table 0 +pipeline PIPELINE3 table 0 rule add match default action fwd port 0 + +thread 1 pipeline PIPELINE0 enable +thread 2 pipeline PIPELINE1 enable +thread 3 pipeline PIPELINE2 enable +thread 4 pipeline PIPELINE3 enable diff --git a/examples/ip_pipeline/examples/tap.cli b/examples/ip_pipeline/examples/tap.cli new file mode 100644 index 00000000..600cea26 --- /dev/null +++ b/examples/ip_pipeline/examples/tap.cli @@ -0,0 +1,66 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2010-2018 Intel Corporation + +; _______________ ______________________ +; | | TAP0 | | +; LINK0 RXQ0 --->|...............|------->|--+ | +; | | TAP1 | | br0 | +; LINK1 TXQ0 <---|...............|<-------|<-+ | +; | | | Linux Kernel | +; | PIPELINE0 | | Network Stack | +; | | TAP1 | | +; LINK1 RXQ0 --->|...............|------->|--+ | +; | | TAP0 | | br0 | +; LINK0 TXQ0 <---|...............|<-------|<-+ | +; |_______________| |______________________| +; +; Configure Linux kernel bridge between TAP0 and TAP1 interfaces: +; [Linux]$ brctl addbr br0 +; [Linux]$ brctl addif br0 TAP0 +; [Linux]$ brctl addif br0 TAP1 +; [Linux]$ ifconfig TAP0 up +; [Linux]$ ifconfig TAP1 up +; [Linux]$ ifconfig br0 up +; +; Monitor packet forwarding performed by Linux kernel between TAP0 and TAP1: +; [Linux]$ tcpdump -i TAP0 +; [Linux]$ tcpdump -i TAP1 + +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 + +link LINK0 dev 0000:02:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +link LINK1 dev 0000:02:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on + +tap TAP0 +tap TAP1 + +table action profile AP0 ipv4 offset 270 fwd + +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 + +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 +pipeline PIPELINE0 port in bsz 32 tap TAP1 mempool MEMPOOL0 mtu 1500 +pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 +pipeline PIPELINE0 port in bsz 32 tap TAP0 mempool MEMPOOL0 mtu 1500 + +pipeline PIPELINE0 port out bsz 32 tap TAP0 +pipeline PIPELINE0 port out bsz 32 link LINK1 txq 0 +pipeline PIPELINE0 port out bsz 32 tap TAP1 +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 + +pipeline PIPELINE0 table match stub action AP0 +pipeline PIPELINE0 table match stub action AP0 +pipeline PIPELINE0 table match stub action AP0 +pipeline PIPELINE0 table match stub action AP0 + +pipeline PIPELINE0 port in 0 table 0 +pipeline PIPELINE0 port in 1 table 1 +pipeline PIPELINE0 port in 2 table 2 +pipeline PIPELINE0 port in 3 table 3 + +thread 1 pipeline PIPELINE0 enable + +pipeline PIPELINE0 table 0 rule add match default action fwd port 0 +pipeline PIPELINE0 table 1 rule add match default action fwd port 1 +pipeline PIPELINE0 table 2 rule add match default action fwd port 2 +pipeline PIPELINE0 table 3 rule add match default action fwd port 3 diff --git a/examples/ip_pipeline/pipeline/hash_func.h b/examples/ip_pipeline/hash_func.h index 806ac227..f1b9d944 100644 --- a/examples/ip_pipeline/pipeline/hash_func.h +++ b/examples/ip_pipeline/hash_func.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation + * Copyright(c) 2010-2018 Intel Corporation */ + #ifndef __INCLUDE_HASH_FUNC_H__ #define __INCLUDE_HASH_FUNC_H__ diff --git a/examples/ip_pipeline/pipeline/hash_func_arm64.h b/examples/ip_pipeline/hash_func_arm64.h index ae6c0f41..50df8167 100644 --- a/examples/ip_pipeline/pipeline/hash_func_arm64.h +++ b/examples/ip_pipeline/hash_func_arm64.h @@ -1,34 +1,5 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2017 Linaro Limited. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Linaro Limited. */ #ifndef __HASH_FUNC_ARM64_H__ #define __HASH_FUNC_ARM64_H__ diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c deleted file mode 100644 index bb07efa1..00000000 --- a/examples/ip_pipeline/init.c +++ /dev/null @@ -1,1927 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <inttypes.h> -#include <stdio.h> -#include <string.h> -#include <netinet/in.h> -#ifdef RTE_EXEC_ENV_LINUXAPP -#include <linux/if.h> -#include <linux/if_tun.h> -#endif -#include <fcntl.h> -#include <sys/ioctl.h> -#include <unistd.h> - -#include <rte_cycles.h> -#include <rte_ethdev.h> -#include <rte_ether.h> -#include <rte_ip.h> -#include <rte_eal.h> -#include <rte_malloc.h> -#include <rte_bus_pci.h> - -#include "app.h" -#include "pipeline.h" -#include "pipeline_common_fe.h" -#include "pipeline_master.h" -#include "pipeline_passthrough.h" -#include "pipeline_firewall.h" -#include "pipeline_flow_classification.h" -#include "pipeline_flow_actions.h" -#include "pipeline_routing.h" -#include "thread_fe.h" - -#define APP_NAME_SIZE 32 - -#define APP_RETA_SIZE_MAX (ETH_RSS_RETA_SIZE_512 / RTE_RETA_GROUP_SIZE) - -static void -app_init_core_map(struct app_params *app) -{ - APP_LOG(app, HIGH, "Initializing CPU core map ..."); - app->core_map = cpu_core_map_init(RTE_MAX_NUMA_NODES, RTE_MAX_LCORE, - 4, 0); - - if (app->core_map == NULL) - rte_panic("Cannot create CPU core map\n"); - - if (app->log_level >= APP_LOG_LEVEL_LOW) - cpu_core_map_print(app->core_map); -} - -/* Core Mask String in Hex Representation */ -#define APP_CORE_MASK_STRING_SIZE ((64 * APP_CORE_MASK_SIZE) / 8 * 2 + 1) - -static void -app_init_core_mask(struct app_params *app) -{ - uint32_t i; - char core_mask_str[APP_CORE_MASK_STRING_SIZE]; - - for (i = 0; i < app->n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - int lcore_id; - - lcore_id = cpu_core_map_get_lcore_id(app->core_map, - p->socket_id, - p->core_id, - p->hyper_th_id); - - if (lcore_id < 0) - rte_panic("Cannot create CPU core mask\n"); - - app_core_enable_in_core_mask(app, lcore_id); - } - - app_core_build_core_mask_string(app, core_mask_str); - APP_LOG(app, HIGH, "CPU core mask = 0x%s", core_mask_str); -} - -static void -app_init_eal(struct app_params *app) -{ - char buffer[256]; - char core_mask_str[APP_CORE_MASK_STRING_SIZE]; - struct app_eal_params *p = &app->eal_params; - uint32_t n_args = 0; - uint32_t i; - int status; - - app->eal_argv[n_args++] = strdup(app->app_name); - - app_core_build_core_mask_string(app, core_mask_str); - snprintf(buffer, sizeof(buffer), "-c%s", core_mask_str); - app->eal_argv[n_args++] = strdup(buffer); - - if (p->coremap) { - snprintf(buffer, sizeof(buffer), "--lcores=%s", p->coremap); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->master_lcore_present) { - snprintf(buffer, - sizeof(buffer), - "--master-lcore=%" PRIu32, - p->master_lcore); - app->eal_argv[n_args++] = strdup(buffer); - } - - snprintf(buffer, sizeof(buffer), "-n%" PRIu32, p->channels); - app->eal_argv[n_args++] = strdup(buffer); - - if (p->memory_present) { - snprintf(buffer, sizeof(buffer), "-m%" PRIu32, p->memory); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->ranks_present) { - snprintf(buffer, sizeof(buffer), "-r%" PRIu32, p->ranks); - app->eal_argv[n_args++] = strdup(buffer); - } - - for (i = 0; i < APP_MAX_LINKS; i++) { - if (p->pci_blacklist[i] == NULL) - break; - - snprintf(buffer, - sizeof(buffer), - "--pci-blacklist=%s", - p->pci_blacklist[i]); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (app->port_mask != 0) - for (i = 0; i < APP_MAX_LINKS; i++) { - if (p->pci_whitelist[i] == NULL) - break; - - snprintf(buffer, - sizeof(buffer), - "--pci-whitelist=%s", - p->pci_whitelist[i]); - app->eal_argv[n_args++] = strdup(buffer); - } - else - for (i = 0; i < app->n_links; i++) { - char *pci_bdf = app->link_params[i].pci_bdf; - - snprintf(buffer, - sizeof(buffer), - "--pci-whitelist=%s", - pci_bdf); - app->eal_argv[n_args++] = strdup(buffer); - } - - for (i = 0; i < APP_MAX_LINKS; i++) { - if (p->vdev[i] == NULL) - break; - - snprintf(buffer, - sizeof(buffer), - "--vdev=%s", - p->vdev[i]); - app->eal_argv[n_args++] = strdup(buffer); - } - - if ((p->vmware_tsc_map_present) && p->vmware_tsc_map) { - snprintf(buffer, sizeof(buffer), "--vmware-tsc-map"); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->proc_type) { - snprintf(buffer, - sizeof(buffer), - "--proc-type=%s", - p->proc_type); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->syslog) { - snprintf(buffer, sizeof(buffer), "--syslog=%s", p->syslog); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->log_level_present) { - snprintf(buffer, - sizeof(buffer), - "--log-level=%" PRIu32, - p->log_level); - app->eal_argv[n_args++] = strdup(buffer); - } - - if ((p->version_present) && p->version) { - snprintf(buffer, sizeof(buffer), "-v"); - app->eal_argv[n_args++] = strdup(buffer); - } - - if ((p->help_present) && p->help) { - snprintf(buffer, sizeof(buffer), "--help"); - app->eal_argv[n_args++] = strdup(buffer); - } - - if ((p->no_huge_present) && p->no_huge) { - snprintf(buffer, sizeof(buffer), "--no-huge"); - app->eal_argv[n_args++] = strdup(buffer); - } - - if ((p->no_pci_present) && p->no_pci) { - snprintf(buffer, sizeof(buffer), "--no-pci"); - app->eal_argv[n_args++] = strdup(buffer); - } - - if ((p->no_hpet_present) && p->no_hpet) { - snprintf(buffer, sizeof(buffer), "--no-hpet"); - app->eal_argv[n_args++] = strdup(buffer); - } - - if ((p->no_shconf_present) && p->no_shconf) { - snprintf(buffer, sizeof(buffer), "--no-shconf"); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->add_driver) { - snprintf(buffer, sizeof(buffer), "-d%s", p->add_driver); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->socket_mem) { - snprintf(buffer, - sizeof(buffer), - "--socket-mem=%s", - p->socket_mem); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->huge_dir) { - snprintf(buffer, sizeof(buffer), "--huge-dir=%s", p->huge_dir); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->file_prefix) { - snprintf(buffer, - sizeof(buffer), - "--file-prefix=%s", - p->file_prefix); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->base_virtaddr) { - snprintf(buffer, - sizeof(buffer), - "--base-virtaddr=%s", - p->base_virtaddr); - app->eal_argv[n_args++] = strdup(buffer); - } - - if ((p->create_uio_dev_present) && p->create_uio_dev) { - snprintf(buffer, sizeof(buffer), "--create-uio-dev"); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->vfio_intr) { - snprintf(buffer, - sizeof(buffer), - "--vfio-intr=%s", - p->vfio_intr); - app->eal_argv[n_args++] = strdup(buffer); - } - - snprintf(buffer, sizeof(buffer), "--"); - app->eal_argv[n_args++] = strdup(buffer); - - app->eal_argc = n_args; - - APP_LOG(app, HIGH, "Initializing EAL ..."); - if (app->log_level >= APP_LOG_LEVEL_LOW) { - int i; - - fprintf(stdout, "[APP] EAL arguments: \""); - for (i = 1; i < app->eal_argc; i++) - fprintf(stdout, "%s ", app->eal_argv[i]); - fprintf(stdout, "\"\n"); - } - - status = rte_eal_init(app->eal_argc, app->eal_argv); - if (status < 0) - rte_panic("EAL init error\n"); -} - -static void -app_init_mempool(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_mempools; i++) { - struct app_mempool_params *p = &app->mempool_params[i]; - - APP_LOG(app, HIGH, "Initializing %s ...", p->name); - app->mempool[i] = rte_pktmbuf_pool_create( - p->name, - p->pool_size, - p->cache_size, - 0, /* priv_size */ - p->buffer_size - - sizeof(struct rte_mbuf), /* mbuf data size */ - p->cpu_socket_id); - - if (app->mempool[i] == NULL) - rte_panic("%s init error\n", p->name); - } -} - -static inline int -app_link_filter_arp_add(struct app_link_params *link) -{ - struct rte_eth_ethertype_filter filter = { - .ether_type = ETHER_TYPE_ARP, - .flags = 0, - .queue = link->arp_q, - }; - - return rte_eth_dev_filter_ctrl(link->pmd_id, - RTE_ETH_FILTER_ETHERTYPE, - RTE_ETH_FILTER_ADD, - &filter); -} - -static inline int -app_link_filter_tcp_syn_add(struct app_link_params *link) -{ - struct rte_eth_syn_filter filter = { - .hig_pri = 1, - .queue = link->tcp_syn_q, - }; - - return rte_eth_dev_filter_ctrl(link->pmd_id, - RTE_ETH_FILTER_SYN, - RTE_ETH_FILTER_ADD, - &filter); -} - -static inline int -app_link_filter_ip_add(struct app_link_params *l1, struct app_link_params *l2) -{ - struct rte_eth_ntuple_filter filter = { - .flags = RTE_5TUPLE_FLAGS, - .dst_ip = rte_bswap32(l2->ip), - .dst_ip_mask = UINT32_MAX, /* Enable */ - .src_ip = 0, - .src_ip_mask = 0, /* Disable */ - .dst_port = 0, - .dst_port_mask = 0, /* Disable */ - .src_port = 0, - .src_port_mask = 0, /* Disable */ - .proto = 0, - .proto_mask = 0, /* Disable */ - .tcp_flags = 0, - .priority = 1, /* Lowest */ - .queue = l1->ip_local_q, - }; - - return rte_eth_dev_filter_ctrl(l1->pmd_id, - RTE_ETH_FILTER_NTUPLE, - RTE_ETH_FILTER_ADD, - &filter); -} - -static inline int -app_link_filter_ip_del(struct app_link_params *l1, struct app_link_params *l2) -{ - struct rte_eth_ntuple_filter filter = { - .flags = RTE_5TUPLE_FLAGS, - .dst_ip = rte_bswap32(l2->ip), - .dst_ip_mask = UINT32_MAX, /* Enable */ - .src_ip = 0, - .src_ip_mask = 0, /* Disable */ - .dst_port = 0, - .dst_port_mask = 0, /* Disable */ - .src_port = 0, - .src_port_mask = 0, /* Disable */ - .proto = 0, - .proto_mask = 0, /* Disable */ - .tcp_flags = 0, - .priority = 1, /* Lowest */ - .queue = l1->ip_local_q, - }; - - return rte_eth_dev_filter_ctrl(l1->pmd_id, - RTE_ETH_FILTER_NTUPLE, - RTE_ETH_FILTER_DELETE, - &filter); -} - -static inline int -app_link_filter_tcp_add(struct app_link_params *l1, struct app_link_params *l2) -{ - struct rte_eth_ntuple_filter filter = { - .flags = RTE_5TUPLE_FLAGS, - .dst_ip = rte_bswap32(l2->ip), - .dst_ip_mask = UINT32_MAX, /* Enable */ - .src_ip = 0, - .src_ip_mask = 0, /* Disable */ - .dst_port = 0, - .dst_port_mask = 0, /* Disable */ - .src_port = 0, - .src_port_mask = 0, /* Disable */ - .proto = IPPROTO_TCP, - .proto_mask = UINT8_MAX, /* Enable */ - .tcp_flags = 0, - .priority = 2, /* Higher priority than IP */ - .queue = l1->tcp_local_q, - }; - - return rte_eth_dev_filter_ctrl(l1->pmd_id, - RTE_ETH_FILTER_NTUPLE, - RTE_ETH_FILTER_ADD, - &filter); -} - -static inline int -app_link_filter_tcp_del(struct app_link_params *l1, struct app_link_params *l2) -{ - struct rte_eth_ntuple_filter filter = { - .flags = RTE_5TUPLE_FLAGS, - .dst_ip = rte_bswap32(l2->ip), - .dst_ip_mask = UINT32_MAX, /* Enable */ - .src_ip = 0, - .src_ip_mask = 0, /* Disable */ - .dst_port = 0, - .dst_port_mask = 0, /* Disable */ - .src_port = 0, - .src_port_mask = 0, /* Disable */ - .proto = IPPROTO_TCP, - .proto_mask = UINT8_MAX, /* Enable */ - .tcp_flags = 0, - .priority = 2, /* Higher priority than IP */ - .queue = l1->tcp_local_q, - }; - - return rte_eth_dev_filter_ctrl(l1->pmd_id, - RTE_ETH_FILTER_NTUPLE, - RTE_ETH_FILTER_DELETE, - &filter); -} - -static inline int -app_link_filter_udp_add(struct app_link_params *l1, struct app_link_params *l2) -{ - struct rte_eth_ntuple_filter filter = { - .flags = RTE_5TUPLE_FLAGS, - .dst_ip = rte_bswap32(l2->ip), - .dst_ip_mask = UINT32_MAX, /* Enable */ - .src_ip = 0, - .src_ip_mask = 0, /* Disable */ - .dst_port = 0, - .dst_port_mask = 0, /* Disable */ - .src_port = 0, - .src_port_mask = 0, /* Disable */ - .proto = IPPROTO_UDP, - .proto_mask = UINT8_MAX, /* Enable */ - .tcp_flags = 0, - .priority = 2, /* Higher priority than IP */ - .queue = l1->udp_local_q, - }; - - return rte_eth_dev_filter_ctrl(l1->pmd_id, - RTE_ETH_FILTER_NTUPLE, - RTE_ETH_FILTER_ADD, - &filter); -} - -static inline int -app_link_filter_udp_del(struct app_link_params *l1, struct app_link_params *l2) -{ - struct rte_eth_ntuple_filter filter = { - .flags = RTE_5TUPLE_FLAGS, - .dst_ip = rte_bswap32(l2->ip), - .dst_ip_mask = UINT32_MAX, /* Enable */ - .src_ip = 0, - .src_ip_mask = 0, /* Disable */ - .dst_port = 0, - .dst_port_mask = 0, /* Disable */ - .src_port = 0, - .src_port_mask = 0, /* Disable */ - .proto = IPPROTO_UDP, - .proto_mask = UINT8_MAX, /* Enable */ - .tcp_flags = 0, - .priority = 2, /* Higher priority than IP */ - .queue = l1->udp_local_q, - }; - - return rte_eth_dev_filter_ctrl(l1->pmd_id, - RTE_ETH_FILTER_NTUPLE, - RTE_ETH_FILTER_DELETE, - &filter); -} - -static inline int -app_link_filter_sctp_add(struct app_link_params *l1, struct app_link_params *l2) -{ - struct rte_eth_ntuple_filter filter = { - .flags = RTE_5TUPLE_FLAGS, - .dst_ip = rte_bswap32(l2->ip), - .dst_ip_mask = UINT32_MAX, /* Enable */ - .src_ip = 0, - .src_ip_mask = 0, /* Disable */ - .dst_port = 0, - .dst_port_mask = 0, /* Disable */ - .src_port = 0, - .src_port_mask = 0, /* Disable */ - .proto = IPPROTO_SCTP, - .proto_mask = UINT8_MAX, /* Enable */ - .tcp_flags = 0, - .priority = 2, /* Higher priority than IP */ - .queue = l1->sctp_local_q, - }; - - return rte_eth_dev_filter_ctrl(l1->pmd_id, - RTE_ETH_FILTER_NTUPLE, - RTE_ETH_FILTER_ADD, - &filter); -} - -static inline int -app_link_filter_sctp_del(struct app_link_params *l1, struct app_link_params *l2) -{ - struct rte_eth_ntuple_filter filter = { - .flags = RTE_5TUPLE_FLAGS, - .dst_ip = rte_bswap32(l2->ip), - .dst_ip_mask = UINT32_MAX, /* Enable */ - .src_ip = 0, - .src_ip_mask = 0, /* Disable */ - .dst_port = 0, - .dst_port_mask = 0, /* Disable */ - .src_port = 0, - .src_port_mask = 0, /* Disable */ - .proto = IPPROTO_SCTP, - .proto_mask = UINT8_MAX, /* Enable */ - .tcp_flags = 0, - .priority = 2, /* Higher priority than IP */ - .queue = l1->sctp_local_q, - }; - - return rte_eth_dev_filter_ctrl(l1->pmd_id, - RTE_ETH_FILTER_NTUPLE, - RTE_ETH_FILTER_DELETE, - &filter); -} - -static void -app_link_set_arp_filter(struct app_params *app, struct app_link_params *cp) -{ - if (cp->arp_q != 0) { - int status = app_link_filter_arp_add(cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 "): " - "Adding ARP filter (queue = %" PRIu32 ")", - cp->name, cp->pmd_id, cp->arp_q); - - if (status) - rte_panic("%s (%" PRIu32 "): " - "Error adding ARP filter " - "(queue = %" PRIu32 ") (%" PRId32 ")\n", - cp->name, cp->pmd_id, cp->arp_q, status); - } -} - -static void -app_link_set_tcp_syn_filter(struct app_params *app, struct app_link_params *cp) -{ - if (cp->tcp_syn_q != 0) { - int status = app_link_filter_tcp_syn_add(cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 "): " - "Adding TCP SYN filter (queue = %" PRIu32 ")", - cp->name, cp->pmd_id, cp->tcp_syn_q); - - if (status) - rte_panic("%s (%" PRIu32 "): " - "Error adding TCP SYN filter " - "(queue = %" PRIu32 ") (%" PRId32 ")\n", - cp->name, cp->pmd_id, cp->tcp_syn_q, - status); - } -} - -void -app_link_up_internal(struct app_params *app, struct app_link_params *cp) -{ - uint32_t i; - int status; - - /* For each link, add filters for IP of current link */ - if (cp->ip != 0) { - for (i = 0; i < app->n_links; i++) { - struct app_link_params *p = &app->link_params[i]; - - /* IP */ - if (p->ip_local_q != 0) { - int status = app_link_filter_ip_add(p, cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 "): " - "Adding IP filter (queue= %" PRIu32 - ", IP = 0x%08" PRIx32 ")", - p->name, p->pmd_id, p->ip_local_q, - cp->ip); - - if (status) - rte_panic("%s (%" PRIu32 "): " - "Error adding IP " - "filter (queue= %" PRIu32 ", " - "IP = 0x%08" PRIx32 - ") (%" PRId32 ")\n", - p->name, p->pmd_id, - p->ip_local_q, cp->ip, status); - } - - /* TCP */ - if (p->tcp_local_q != 0) { - int status = app_link_filter_tcp_add(p, cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 "): " - "Adding TCP filter " - "(queue = %" PRIu32 - ", IP = 0x%08" PRIx32 ")", - p->name, p->pmd_id, p->tcp_local_q, - cp->ip); - - if (status) - rte_panic("%s (%" PRIu32 "): " - "Error adding TCP " - "filter (queue = %" PRIu32 ", " - "IP = 0x%08" PRIx32 - ") (%" PRId32 ")\n", - p->name, p->pmd_id, - p->tcp_local_q, cp->ip, status); - } - - /* UDP */ - if (p->udp_local_q != 0) { - int status = app_link_filter_udp_add(p, cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 "): " - "Adding UDP filter " - "(queue = %" PRIu32 - ", IP = 0x%08" PRIx32 ")", - p->name, p->pmd_id, p->udp_local_q, - cp->ip); - - if (status) - rte_panic("%s (%" PRIu32 "): " - "Error adding UDP " - "filter (queue = %" PRIu32 ", " - "IP = 0x%08" PRIx32 - ") (%" PRId32 ")\n", - p->name, p->pmd_id, - p->udp_local_q, cp->ip, status); - } - - /* SCTP */ - if (p->sctp_local_q != 0) { - int status = app_link_filter_sctp_add(p, cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 - "): Adding SCTP filter " - "(queue = %" PRIu32 - ", IP = 0x%08" PRIx32 ")", - p->name, p->pmd_id, p->sctp_local_q, - cp->ip); - - if (status) - rte_panic("%s (%" PRIu32 "): " - "Error adding SCTP " - "filter (queue = %" PRIu32 ", " - "IP = 0x%08" PRIx32 - ") (%" PRId32 ")\n", - p->name, p->pmd_id, - p->sctp_local_q, cp->ip, - status); - } - } - } - - /* PMD link up */ - status = rte_eth_dev_set_link_up(cp->pmd_id); - /* Do not panic if PMD does not provide link up functionality */ - if (status < 0 && status != -ENOTSUP) - rte_panic("%s (%" PRIu32 "): PMD set link up error %" - PRId32 "\n", cp->name, cp->pmd_id, status); - - /* Mark link as UP */ - cp->state = 1; -} - -void -app_link_down_internal(struct app_params *app, struct app_link_params *cp) -{ - uint32_t i; - int status; - - /* PMD link down */ - status = rte_eth_dev_set_link_down(cp->pmd_id); - /* Do not panic if PMD does not provide link down functionality */ - if (status < 0 && status != -ENOTSUP) - rte_panic("%s (%" PRIu32 "): PMD set link down error %" - PRId32 "\n", cp->name, cp->pmd_id, status); - - /* Mark link as DOWN */ - cp->state = 0; - - /* Return if current link IP is not valid */ - if (cp->ip == 0) - return; - - /* For each link, remove filters for IP of current link */ - for (i = 0; i < app->n_links; i++) { - struct app_link_params *p = &app->link_params[i]; - - /* IP */ - if (p->ip_local_q != 0) { - int status = app_link_filter_ip_del(p, cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 - "): Deleting IP filter " - "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")", - p->name, p->pmd_id, p->ip_local_q, cp->ip); - - if (status) - rte_panic("%s (%" PRIu32 - "): Error deleting IP filter " - "(queue = %" PRIu32 - ", IP = 0x%" PRIx32 - ") (%" PRId32 ")\n", - p->name, p->pmd_id, p->ip_local_q, - cp->ip, status); - } - - /* TCP */ - if (p->tcp_local_q != 0) { - int status = app_link_filter_tcp_del(p, cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 - "): Deleting TCP filter " - "(queue = %" PRIu32 - ", IP = 0x%" PRIx32 ")", - p->name, p->pmd_id, p->tcp_local_q, cp->ip); - - if (status) - rte_panic("%s (%" PRIu32 - "): Error deleting TCP filter " - "(queue = %" PRIu32 - ", IP = 0x%" PRIx32 - ") (%" PRId32 ")\n", - p->name, p->pmd_id, p->tcp_local_q, - cp->ip, status); - } - - /* UDP */ - if (p->udp_local_q != 0) { - int status = app_link_filter_udp_del(p, cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 - "): Deleting UDP filter " - "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")", - p->name, p->pmd_id, p->udp_local_q, cp->ip); - - if (status) - rte_panic("%s (%" PRIu32 - "): Error deleting UDP filter " - "(queue = %" PRIu32 - ", IP = 0x%" PRIx32 - ") (%" PRId32 ")\n", - p->name, p->pmd_id, p->udp_local_q, - cp->ip, status); - } - - /* SCTP */ - if (p->sctp_local_q != 0) { - int status = app_link_filter_sctp_del(p, cp); - - APP_LOG(app, LOW, "%s (%" PRIu32 - "): Deleting SCTP filter " - "(queue = %" PRIu32 - ", IP = 0x%" PRIx32 ")", - p->name, p->pmd_id, p->sctp_local_q, cp->ip); - - if (status) - rte_panic("%s (%" PRIu32 - "): Error deleting SCTP filter " - "(queue = %" PRIu32 - ", IP = 0x%" PRIx32 - ") (%" PRId32 ")\n", - p->name, p->pmd_id, p->sctp_local_q, - cp->ip, status); - } - } -} - -static void -app_check_link(struct app_params *app) -{ - uint32_t all_links_up, i; - - all_links_up = 1; - - for (i = 0; i < app->n_links; i++) { - struct app_link_params *p = &app->link_params[i]; - struct rte_eth_link link_params; - - memset(&link_params, 0, sizeof(link_params)); - rte_eth_link_get(p->pmd_id, &link_params); - - APP_LOG(app, HIGH, "%s (%" PRIu32 ") (%" PRIu32 " Gbps) %s", - p->name, - p->pmd_id, - link_params.link_speed / 1000, - link_params.link_status ? "UP" : "DOWN"); - - if (link_params.link_status == ETH_LINK_DOWN) - all_links_up = 0; - } - - if (all_links_up == 0) - rte_panic("Some links are DOWN\n"); -} - -static uint32_t -is_any_swq_frag_or_ras(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_swq; i++) { - struct app_pktq_swq_params *p = &app->swq_params[i]; - - if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1) || - (p->ipv4_ras == 1) || (p->ipv6_ras == 1)) - return 1; - } - - return 0; -} - -static void -app_init_link_frag_ras(struct app_params *app) -{ - uint32_t i; - - if (is_any_swq_frag_or_ras(app)) { - for (i = 0; i < app->n_links; i++) { - struct app_link_params *p_link = &app->link_params[i]; - p_link->conf.txmode.offloads |= - DEV_TX_OFFLOAD_MULTI_SEGS; - } - } -} - -static inline int -app_get_cpu_socket_id(uint32_t pmd_id) -{ - int status = rte_eth_dev_socket_id(pmd_id); - - return (status != SOCKET_ID_ANY) ? status : 0; -} - -static inline int -app_link_rss_enabled(struct app_link_params *cp) -{ - return (cp->n_rss_qs) ? 1 : 0; -} - -static void -app_link_rss_setup(struct app_link_params *cp) -{ - struct rte_eth_dev_info dev_info; - struct rte_eth_rss_reta_entry64 reta_conf[APP_RETA_SIZE_MAX]; - uint32_t i; - int status; - - /* Get RETA size */ - memset(&dev_info, 0, sizeof(dev_info)); - rte_eth_dev_info_get(cp->pmd_id, &dev_info); - - if (dev_info.reta_size == 0) - rte_panic("%s (%u): RSS setup error (null RETA size)\n", - cp->name, cp->pmd_id); - - if (dev_info.reta_size > ETH_RSS_RETA_SIZE_512) - rte_panic("%s (%u): RSS setup error (RETA size too big)\n", - cp->name, cp->pmd_id); - - /* Setup RETA contents */ - memset(reta_conf, 0, sizeof(reta_conf)); - - for (i = 0; i < dev_info.reta_size; i++) - reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX; - - for (i = 0; i < dev_info.reta_size; i++) { - uint32_t reta_id = i / RTE_RETA_GROUP_SIZE; - uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE; - uint32_t rss_qs_pos = i % cp->n_rss_qs; - - reta_conf[reta_id].reta[reta_pos] = - (uint16_t) cp->rss_qs[rss_qs_pos]; - } - - /* RETA update */ - status = rte_eth_dev_rss_reta_update(cp->pmd_id, - reta_conf, - dev_info.reta_size); - if (status != 0) - rte_panic("%s (%u): RSS setup error (RETA update failed)\n", - cp->name, cp->pmd_id); -} - -static void -app_init_link_set_config(struct app_link_params *p) -{ - if (p->n_rss_qs) { - p->conf.rxmode.mq_mode = ETH_MQ_RX_RSS; - p->conf.rx_adv_conf.rss_conf.rss_hf = p->rss_proto_ipv4 | - p->rss_proto_ipv6 | - p->rss_proto_l2; - } -} - -static void -app_init_link(struct app_params *app) -{ - uint32_t i; - - app_init_link_frag_ras(app); - - for (i = 0; i < app->n_links; i++) { - struct app_link_params *p_link = &app->link_params[i]; - struct rte_eth_dev_info dev_info; - uint32_t link_id, n_hwq_in, n_hwq_out, j; - int status; - - sscanf(p_link->name, "LINK%" PRIu32, &link_id); - n_hwq_in = app_link_get_n_rxq(app, p_link); - n_hwq_out = app_link_get_n_txq(app, p_link); - app_init_link_set_config(p_link); - - APP_LOG(app, HIGH, "Initializing %s (%" PRIu32") " - "(%" PRIu32 " RXQ, %" PRIu32 " TXQ) ...", - p_link->name, - p_link->pmd_id, - n_hwq_in, - n_hwq_out); - - /* LINK */ - rte_eth_dev_info_get(p_link->pmd_id, &dev_info); - if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) - p_link->conf.txmode.offloads |= - DEV_TX_OFFLOAD_MBUF_FAST_FREE; - status = rte_eth_dev_configure( - p_link->pmd_id, - n_hwq_in, - n_hwq_out, - &p_link->conf); - if (status < 0) - rte_panic("%s (%" PRId32 "): " - "init error (%" PRId32 ")\n", - p_link->name, p_link->pmd_id, status); - - rte_eth_macaddr_get(p_link->pmd_id, - (struct ether_addr *) &p_link->mac_addr); - - if (p_link->promisc) - rte_eth_promiscuous_enable(p_link->pmd_id); - - /* RXQ */ - for (j = 0; j < app->n_pktq_hwq_in; j++) { - struct app_pktq_hwq_in_params *p_rxq = - &app->hwq_in_params[j]; - uint32_t rxq_link_id, rxq_queue_id; - uint16_t nb_rxd = p_rxq->size; - - sscanf(p_rxq->name, "RXQ%" PRIu32 ".%" PRIu32, - &rxq_link_id, &rxq_queue_id); - if (rxq_link_id != link_id) - continue; - - status = rte_eth_dev_adjust_nb_rx_tx_desc( - p_link->pmd_id, - &nb_rxd, - NULL); - if (status < 0) - rte_panic("%s (%" PRIu32 "): " - "%s adjust number of Rx descriptors " - "error (%" PRId32 ")\n", - p_link->name, - p_link->pmd_id, - p_rxq->name, - status); - - p_rxq->conf.offloads = p_link->conf.rxmode.offloads; - status = rte_eth_rx_queue_setup( - p_link->pmd_id, - rxq_queue_id, - nb_rxd, - app_get_cpu_socket_id(p_link->pmd_id), - &p_rxq->conf, - app->mempool[p_rxq->mempool_id]); - if (status < 0) - rte_panic("%s (%" PRIu32 "): " - "%s init error (%" PRId32 ")\n", - p_link->name, - p_link->pmd_id, - p_rxq->name, - status); - } - - /* TXQ */ - for (j = 0; j < app->n_pktq_hwq_out; j++) { - struct app_pktq_hwq_out_params *p_txq = - &app->hwq_out_params[j]; - uint32_t txq_link_id, txq_queue_id; - uint16_t nb_txd = p_txq->size; - - sscanf(p_txq->name, "TXQ%" PRIu32 ".%" PRIu32, - &txq_link_id, &txq_queue_id); - if (txq_link_id != link_id) - continue; - - status = rte_eth_dev_adjust_nb_rx_tx_desc( - p_link->pmd_id, - NULL, - &nb_txd); - if (status < 0) - rte_panic("%s (%" PRIu32 "): " - "%s adjust number of Tx descriptors " - "error (%" PRId32 ")\n", - p_link->name, - p_link->pmd_id, - p_txq->name, - status); - - p_txq->conf.offloads = p_link->conf.txmode.offloads; - status = rte_eth_tx_queue_setup( - p_link->pmd_id, - txq_queue_id, - nb_txd, - app_get_cpu_socket_id(p_link->pmd_id), - &p_txq->conf); - if (status < 0) - rte_panic("%s (%" PRIu32 "): " - "%s init error (%" PRId32 ")\n", - p_link->name, - p_link->pmd_id, - p_txq->name, - status); - } - - /* LINK START */ - status = rte_eth_dev_start(p_link->pmd_id); - if (status < 0) - rte_panic("Cannot start %s (error %" PRId32 ")\n", - p_link->name, status); - - /* LINK FILTERS */ - app_link_set_arp_filter(app, p_link); - app_link_set_tcp_syn_filter(app, p_link); - if (app_link_rss_enabled(p_link)) - app_link_rss_setup(p_link); - - /* LINK UP */ - app_link_up_internal(app, p_link); - } - - app_check_link(app); -} - -static void -app_init_swq(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_swq; i++) { - struct app_pktq_swq_params *p = &app->swq_params[i]; - unsigned flags = 0; - - if (app_swq_get_readers(app, p) == 1) - flags |= RING_F_SC_DEQ; - if (app_swq_get_writers(app, p) == 1) - flags |= RING_F_SP_ENQ; - - APP_LOG(app, HIGH, "Initializing %s...", p->name); - app->swq[i] = rte_ring_create( - p->name, - p->size, - p->cpu_socket_id, - flags); - - if (app->swq[i] == NULL) - rte_panic("%s init error\n", p->name); - } -} - -static void -app_init_tm(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_tm; i++) { - struct app_pktq_tm_params *p_tm = &app->tm_params[i]; - struct app_link_params *p_link; - struct rte_eth_link link_eth_params; - struct rte_sched_port *sched; - uint32_t n_subports, subport_id; - int status; - - p_link = app_get_link_for_tm(app, p_tm); - /* LINK */ - rte_eth_link_get(p_link->pmd_id, &link_eth_params); - - /* TM */ - p_tm->sched_port_params.name = p_tm->name; - p_tm->sched_port_params.socket = - app_get_cpu_socket_id(p_link->pmd_id); - p_tm->sched_port_params.rate = - (uint64_t) link_eth_params.link_speed * 1000 * 1000 / 8; - - APP_LOG(app, HIGH, "Initializing %s ...", p_tm->name); - sched = rte_sched_port_config(&p_tm->sched_port_params); - if (sched == NULL) - rte_panic("%s init error\n", p_tm->name); - app->tm[i] = sched; - - /* Subport */ - n_subports = p_tm->sched_port_params.n_subports_per_port; - for (subport_id = 0; subport_id < n_subports; subport_id++) { - uint32_t n_pipes_per_subport, pipe_id; - - status = rte_sched_subport_config(sched, - subport_id, - &p_tm->sched_subport_params[subport_id]); - if (status) - rte_panic("%s subport %" PRIu32 - " init error (%" PRId32 ")\n", - p_tm->name, subport_id, status); - - /* Pipe */ - n_pipes_per_subport = - p_tm->sched_port_params.n_pipes_per_subport; - for (pipe_id = 0; - pipe_id < n_pipes_per_subport; - pipe_id++) { - int profile_id = p_tm->sched_pipe_to_profile[ - subport_id * APP_MAX_SCHED_PIPES + - pipe_id]; - - if (profile_id == -1) - continue; - - status = rte_sched_pipe_config(sched, - subport_id, - pipe_id, - profile_id); - if (status) - rte_panic("%s subport %" PRIu32 - " pipe %" PRIu32 - " (profile %" PRId32 ") " - "init error (% " PRId32 ")\n", - p_tm->name, subport_id, pipe_id, - profile_id, status); - } - } - } -} - -#ifndef RTE_EXEC_ENV_LINUXAPP -static void -app_init_tap(struct app_params *app) { - if (app->n_pktq_tap == 0) - return; - - rte_panic("TAP device not supported.\n"); -} -#else -static void -app_init_tap(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_pktq_tap; i++) { - struct app_pktq_tap_params *p_tap = &app->tap_params[i]; - struct ifreq ifr; - int fd, status; - - APP_LOG(app, HIGH, "Initializing %s ...", p_tap->name); - - fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK); - if (fd < 0) - rte_panic("Cannot open file /dev/net/tun\n"); - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */ - snprintf(ifr.ifr_name, IFNAMSIZ, "%s", p_tap->name); - - status = ioctl(fd, TUNSETIFF, (void *) &ifr); - if (status < 0) - rte_panic("TAP setup error\n"); - - app->tap[i] = fd; - } -} -#endif - -#ifdef RTE_LIBRTE_KNI -static int -kni_config_network_interface(uint16_t port_id, uint8_t if_up) { - int ret = 0; - - if (port_id >= rte_eth_dev_count()) - return -EINVAL; - - ret = (if_up) ? - rte_eth_dev_set_link_up(port_id) : - rte_eth_dev_set_link_down(port_id); - - return ret; -} - -static int -kni_change_mtu(uint16_t port_id, unsigned int new_mtu) { - int ret; - - if (port_id >= rte_eth_dev_count()) - return -EINVAL; - - if (new_mtu > ETHER_MAX_LEN) - return -EINVAL; - - /* Set new MTU */ - ret = rte_eth_dev_set_mtu(port_id, new_mtu); - if (ret < 0) - return ret; - - return 0; -} -#endif /* RTE_LIBRTE_KNI */ - -#ifndef RTE_LIBRTE_KNI -static void -app_init_kni(struct app_params *app) { - if (app->n_pktq_kni == 0) - return; - - rte_panic("Can not init KNI without librte_kni support.\n"); -} -#else -static void -app_init_kni(struct app_params *app) { - uint32_t i; - - if (app->n_pktq_kni == 0) - return; - - rte_kni_init(app->n_pktq_kni); - - for (i = 0; i < app->n_pktq_kni; i++) { - struct app_pktq_kni_params *p_kni = &app->kni_params[i]; - struct app_link_params *p_link; - struct rte_eth_dev_info dev_info; - struct app_mempool_params *mempool_params; - struct rte_mempool *mempool; - struct rte_kni_conf conf; - struct rte_kni_ops ops; - - /* LINK */ - p_link = app_get_link_for_kni(app, p_kni); - memset(&dev_info, 0, sizeof(dev_info)); - rte_eth_dev_info_get(p_link->pmd_id, &dev_info); - - /* MEMPOOL */ - mempool_params = &app->mempool_params[p_kni->mempool_id]; - mempool = app->mempool[p_kni->mempool_id]; - - /* KNI */ - memset(&conf, 0, sizeof(conf)); - snprintf(conf.name, RTE_KNI_NAMESIZE, "%s", p_kni->name); - conf.force_bind = p_kni->force_bind; - if (conf.force_bind) { - int lcore_id; - - lcore_id = cpu_core_map_get_lcore_id(app->core_map, - p_kni->socket_id, - p_kni->core_id, - p_kni->hyper_th_id); - - if (lcore_id < 0) - rte_panic("%s invalid CPU core\n", p_kni->name); - - conf.core_id = (uint32_t) lcore_id; - } - conf.group_id = p_link->pmd_id; - conf.mbuf_size = mempool_params->buffer_size; - conf.addr = dev_info.pci_dev->addr; - conf.id = dev_info.pci_dev->id; - - memset(&ops, 0, sizeof(ops)); - ops.port_id = (uint8_t) p_link->pmd_id; - ops.change_mtu = kni_change_mtu; - ops.config_network_if = kni_config_network_interface; - - APP_LOG(app, HIGH, "Initializing %s ...", p_kni->name); - app->kni[i] = rte_kni_alloc(mempool, &conf, &ops); - if (!app->kni[i]) - rte_panic("%s init error\n", p_kni->name); - } -} -#endif /* RTE_LIBRTE_KNI */ - -static void -app_init_msgq(struct app_params *app) -{ - uint32_t i; - - for (i = 0; i < app->n_msgq; i++) { - struct app_msgq_params *p = &app->msgq_params[i]; - - APP_LOG(app, HIGH, "Initializing %s ...", p->name); - app->msgq[i] = rte_ring_create( - p->name, - p->size, - p->cpu_socket_id, - RING_F_SP_ENQ | RING_F_SC_DEQ); - - if (app->msgq[i] == NULL) - rte_panic("%s init error\n", p->name); - } -} - -void app_pipeline_params_get(struct app_params *app, - struct app_pipeline_params *p_in, - struct pipeline_params *p_out) -{ - uint32_t i; - - snprintf(p_out->name, PIPELINE_NAME_SIZE, "%s", p_in->name); - - snprintf(p_out->type, PIPELINE_TYPE_SIZE, "%s", p_in->type); - - p_out->socket_id = (int) p_in->socket_id; - - p_out->log_level = app->log_level; - - /* pktq_in */ - p_out->n_ports_in = p_in->n_pktq_in; - for (i = 0; i < p_in->n_pktq_in; i++) { - struct app_pktq_in_params *in = &p_in->pktq_in[i]; - struct pipeline_port_in_params *out = &p_out->port_in[i]; - - switch (in->type) { - case APP_PKTQ_IN_HWQ: - { - struct app_pktq_hwq_in_params *p_hwq_in = - &app->hwq_in_params[in->id]; - struct app_link_params *p_link = - app_get_link_for_rxq(app, p_hwq_in); - uint32_t rxq_link_id, rxq_queue_id; - - sscanf(p_hwq_in->name, "RXQ%" SCNu32 ".%" SCNu32, - &rxq_link_id, - &rxq_queue_id); - - out->type = PIPELINE_PORT_IN_ETHDEV_READER; - out->params.ethdev.port_id = p_link->pmd_id; - out->params.ethdev.queue_id = rxq_queue_id; - out->burst_size = p_hwq_in->burst; - break; - } - case APP_PKTQ_IN_SWQ: - { - struct app_pktq_swq_params *swq_params = &app->swq_params[in->id]; - - if ((swq_params->ipv4_frag == 0) && (swq_params->ipv6_frag == 0)) { - if (app_swq_get_readers(app, swq_params) == 1) { - out->type = PIPELINE_PORT_IN_RING_READER; - out->params.ring.ring = app->swq[in->id]; - out->burst_size = app->swq_params[in->id].burst_read; - } else { - out->type = PIPELINE_PORT_IN_RING_MULTI_READER; - out->params.ring_multi.ring = app->swq[in->id]; - out->burst_size = swq_params->burst_read; - } - } else { - if (swq_params->ipv4_frag == 1) { - struct rte_port_ring_reader_ipv4_frag_params *params = - &out->params.ring_ipv4_frag; - - out->type = PIPELINE_PORT_IN_RING_READER_IPV4_FRAG; - params->ring = app->swq[in->id]; - params->mtu = swq_params->mtu; - params->metadata_size = swq_params->metadata_size; - params->pool_direct = - app->mempool[swq_params->mempool_direct_id]; - params->pool_indirect = - app->mempool[swq_params->mempool_indirect_id]; - out->burst_size = swq_params->burst_read; - } else { - struct rte_port_ring_reader_ipv6_frag_params *params = - &out->params.ring_ipv6_frag; - - out->type = PIPELINE_PORT_IN_RING_READER_IPV6_FRAG; - params->ring = app->swq[in->id]; - params->mtu = swq_params->mtu; - params->metadata_size = swq_params->metadata_size; - params->pool_direct = - app->mempool[swq_params->mempool_direct_id]; - params->pool_indirect = - app->mempool[swq_params->mempool_indirect_id]; - out->burst_size = swq_params->burst_read; - } - } - break; - } - case APP_PKTQ_IN_TM: - { - out->type = PIPELINE_PORT_IN_SCHED_READER; - out->params.sched.sched = app->tm[in->id]; - out->burst_size = app->tm_params[in->id].burst_read; - break; - } -#ifdef RTE_EXEC_ENV_LINUXAPP - case APP_PKTQ_IN_TAP: - { - struct app_pktq_tap_params *tap_params = - &app->tap_params[in->id]; - struct app_mempool_params *mempool_params = - &app->mempool_params[tap_params->mempool_id]; - struct rte_mempool *mempool = - app->mempool[tap_params->mempool_id]; - - out->type = PIPELINE_PORT_IN_FD_READER; - out->params.fd.fd = app->tap[in->id]; - out->params.fd.mtu = mempool_params->buffer_size; - out->params.fd.mempool = mempool; - out->burst_size = app->tap_params[in->id].burst_read; - break; - } -#endif -#ifdef RTE_LIBRTE_KNI - case APP_PKTQ_IN_KNI: - { - out->type = PIPELINE_PORT_IN_KNI_READER; - out->params.kni.kni = app->kni[in->id]; - out->burst_size = app->kni_params[in->id].burst_read; - break; - } -#endif /* RTE_LIBRTE_KNI */ - case APP_PKTQ_IN_SOURCE: - { - uint32_t mempool_id = - app->source_params[in->id].mempool_id; - - out->type = PIPELINE_PORT_IN_SOURCE; - out->params.source.mempool = app->mempool[mempool_id]; - out->burst_size = app->source_params[in->id].burst; - out->params.source.file_name = - app->source_params[in->id].file_name; - out->params.source.n_bytes_per_pkt = - app->source_params[in->id].n_bytes_per_pkt; - break; - } - default: - break; - } - } - - /* pktq_out */ - p_out->n_ports_out = p_in->n_pktq_out; - for (i = 0; i < p_in->n_pktq_out; i++) { - struct app_pktq_out_params *in = &p_in->pktq_out[i]; - struct pipeline_port_out_params *out = &p_out->port_out[i]; - - switch (in->type) { - case APP_PKTQ_OUT_HWQ: - { - struct app_pktq_hwq_out_params *p_hwq_out = - &app->hwq_out_params[in->id]; - struct app_link_params *p_link = - app_get_link_for_txq(app, p_hwq_out); - uint32_t txq_link_id, txq_queue_id; - - sscanf(p_hwq_out->name, - "TXQ%" SCNu32 ".%" SCNu32, - &txq_link_id, - &txq_queue_id); - - if (p_hwq_out->dropless == 0) { - struct rte_port_ethdev_writer_params *params = - &out->params.ethdev; - - out->type = PIPELINE_PORT_OUT_ETHDEV_WRITER; - params->port_id = p_link->pmd_id; - params->queue_id = txq_queue_id; - params->tx_burst_sz = - app->hwq_out_params[in->id].burst; - } else { - struct rte_port_ethdev_writer_nodrop_params - *params = &out->params.ethdev_nodrop; - - out->type = - PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP; - params->port_id = p_link->pmd_id; - params->queue_id = txq_queue_id; - params->tx_burst_sz = p_hwq_out->burst; - params->n_retries = p_hwq_out->n_retries; - } - break; - } - case APP_PKTQ_OUT_SWQ: - { - struct app_pktq_swq_params *swq_params = &app->swq_params[in->id]; - - if ((swq_params->ipv4_ras == 0) && (swq_params->ipv6_ras == 0)) { - if (app_swq_get_writers(app, swq_params) == 1) { - if (app->swq_params[in->id].dropless == 0) { - struct rte_port_ring_writer_params *params = - &out->params.ring; - - out->type = PIPELINE_PORT_OUT_RING_WRITER; - params->ring = app->swq[in->id]; - params->tx_burst_sz = - app->swq_params[in->id].burst_write; - } else { - struct rte_port_ring_writer_nodrop_params - *params = &out->params.ring_nodrop; - - out->type = - PIPELINE_PORT_OUT_RING_WRITER_NODROP; - params->ring = app->swq[in->id]; - params->tx_burst_sz = - app->swq_params[in->id].burst_write; - params->n_retries = - app->swq_params[in->id].n_retries; - } - } else { - if (swq_params->dropless == 0) { - struct rte_port_ring_multi_writer_params *params = - &out->params.ring_multi; - - out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER; - params->ring = app->swq[in->id]; - params->tx_burst_sz = swq_params->burst_write; - } else { - struct rte_port_ring_multi_writer_nodrop_params - *params = &out->params.ring_multi_nodrop; - - out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP; - params->ring = app->swq[in->id]; - params->tx_burst_sz = swq_params->burst_write; - params->n_retries = swq_params->n_retries; - } - } - } else { - if (swq_params->ipv4_ras == 1) { - struct rte_port_ring_writer_ipv4_ras_params *params = - &out->params.ring_ipv4_ras; - - out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS; - params->ring = app->swq[in->id]; - params->tx_burst_sz = swq_params->burst_write; - } else { - struct rte_port_ring_writer_ipv6_ras_params *params = - &out->params.ring_ipv6_ras; - - out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS; - params->ring = app->swq[in->id]; - params->tx_burst_sz = swq_params->burst_write; - } - } - break; - } - case APP_PKTQ_OUT_TM: - { - struct rte_port_sched_writer_params *params = - &out->params.sched; - - out->type = PIPELINE_PORT_OUT_SCHED_WRITER; - params->sched = app->tm[in->id]; - params->tx_burst_sz = - app->tm_params[in->id].burst_write; - break; - } -#ifdef RTE_EXEC_ENV_LINUXAPP - case APP_PKTQ_OUT_TAP: - { - struct rte_port_fd_writer_params *params = - &out->params.fd; - - out->type = PIPELINE_PORT_OUT_FD_WRITER; - params->fd = app->tap[in->id]; - params->tx_burst_sz = - app->tap_params[in->id].burst_write; - break; - } -#endif -#ifdef RTE_LIBRTE_KNI - case APP_PKTQ_OUT_KNI: - { - struct app_pktq_kni_params *p_kni = - &app->kni_params[in->id]; - - if (p_kni->dropless == 0) { - struct rte_port_kni_writer_params *params = - &out->params.kni; - - out->type = PIPELINE_PORT_OUT_KNI_WRITER; - params->kni = app->kni[in->id]; - params->tx_burst_sz = - app->kni_params[in->id].burst_write; - } else { - struct rte_port_kni_writer_nodrop_params - *params = &out->params.kni_nodrop; - - out->type = PIPELINE_PORT_OUT_KNI_WRITER_NODROP; - params->kni = app->kni[in->id]; - params->tx_burst_sz = - app->kni_params[in->id].burst_write; - params->n_retries = - app->kni_params[in->id].n_retries; - } - break; - } -#endif /* RTE_LIBRTE_KNI */ - case APP_PKTQ_OUT_SINK: - { - out->type = PIPELINE_PORT_OUT_SINK; - out->params.sink.file_name = - app->sink_params[in->id].file_name; - out->params.sink.max_n_pkts = - app->sink_params[in->id]. - n_pkts_to_dump; - - break; - } - default: - break; - } - } - - /* msgq */ - p_out->n_msgq = p_in->n_msgq_in; - - for (i = 0; i < p_in->n_msgq_in; i++) - p_out->msgq_in[i] = app->msgq[p_in->msgq_in[i]]; - - for (i = 0; i < p_in->n_msgq_out; i++) - p_out->msgq_out[i] = app->msgq[p_in->msgq_out[i]]; - - /* args */ - p_out->n_args = p_in->n_args; - for (i = 0; i < p_in->n_args; i++) { - p_out->args_name[i] = p_in->args_name[i]; - p_out->args_value[i] = p_in->args_value[i]; - } -} - -static void -app_init_pipelines(struct app_params *app) -{ - uint32_t p_id; - - for (p_id = 0; p_id < app->n_pipelines; p_id++) { - struct app_pipeline_params *params = - &app->pipeline_params[p_id]; - struct app_pipeline_data *data = &app->pipeline_data[p_id]; - struct pipeline_type *ptype; - struct pipeline_params pp; - - APP_LOG(app, HIGH, "Initializing %s ...", params->name); - - ptype = app_pipeline_type_find(app, params->type); - if (ptype == NULL) - rte_panic("Init error: Unknown pipeline type \"%s\"\n", - params->type); - - app_pipeline_params_get(app, params, &pp); - - /* Back-end */ - data->be = NULL; - if (ptype->be_ops->f_init) { - data->be = ptype->be_ops->f_init(&pp, (void *) app); - - if (data->be == NULL) - rte_panic("Pipeline instance \"%s\" back-end " - "init error\n", params->name); - } - - /* Front-end */ - data->fe = NULL; - if (ptype->fe_ops->f_init) { - data->fe = ptype->fe_ops->f_init(&pp, (void *) app); - - if (data->fe == NULL) - rte_panic("Pipeline instance \"%s\" front-end " - "init error\n", params->name); - } - - data->ptype = ptype; - - data->timer_period = (rte_get_tsc_hz() * - params->timer_period) / 1000; - } -} - -static void -app_post_init_pipelines(struct app_params *app) -{ - uint32_t p_id; - - for (p_id = 0; p_id < app->n_pipelines; p_id++) { - struct app_pipeline_params *params = - &app->pipeline_params[p_id]; - struct app_pipeline_data *data = &app->pipeline_data[p_id]; - int status; - - if (data->ptype->fe_ops->f_post_init == NULL) - continue; - - status = data->ptype->fe_ops->f_post_init(data->fe); - if (status) - rte_panic("Pipeline instance \"%s\" front-end " - "post-init error\n", params->name); - } -} - -static void -app_init_threads(struct app_params *app) -{ - uint64_t time = rte_get_tsc_cycles(); - uint32_t p_id; - - for (p_id = 0; p_id < app->n_pipelines; p_id++) { - struct app_pipeline_params *params = - &app->pipeline_params[p_id]; - struct app_pipeline_data *data = &app->pipeline_data[p_id]; - struct pipeline_type *ptype; - struct app_thread_data *t; - struct app_thread_pipeline_data *p; - int lcore_id; - - lcore_id = cpu_core_map_get_lcore_id(app->core_map, - params->socket_id, - params->core_id, - params->hyper_th_id); - - if (lcore_id < 0) - rte_panic("Invalid core s%" PRIu32 "c%" PRIu32 "%s\n", - params->socket_id, - params->core_id, - (params->hyper_th_id) ? "h" : ""); - - t = &app->thread_data[lcore_id]; - - t->timer_period = (rte_get_tsc_hz() * APP_THREAD_TIMER_PERIOD) / 1000; - t->thread_req_deadline = time + t->timer_period; - - t->headroom_cycles = 0; - t->headroom_time = rte_get_tsc_cycles(); - t->headroom_ratio = 0.0; - - t->msgq_in = app_thread_msgq_in_get(app, - params->socket_id, - params->core_id, - params->hyper_th_id); - if (t->msgq_in == NULL) - rte_panic("Init error: Cannot find MSGQ_IN for thread %" PRId32, - lcore_id); - - t->msgq_out = app_thread_msgq_out_get(app, - params->socket_id, - params->core_id, - params->hyper_th_id); - if (t->msgq_out == NULL) - rte_panic("Init error: Cannot find MSGQ_OUT for thread %" PRId32, - lcore_id); - - ptype = app_pipeline_type_find(app, params->type); - if (ptype == NULL) - rte_panic("Init error: Unknown pipeline " - "type \"%s\"\n", params->type); - - p = (ptype->be_ops->f_run == NULL) ? - &t->regular[t->n_regular] : - &t->custom[t->n_custom]; - - p->pipeline_id = p_id; - p->be = data->be; - p->f_run = ptype->be_ops->f_run; - p->f_timer = ptype->be_ops->f_timer; - p->timer_period = data->timer_period; - p->deadline = time + data->timer_period; - - data->enabled = 1; - - if (ptype->be_ops->f_run == NULL) - t->n_regular++; - else - t->n_custom++; - } -} - -int app_init(struct app_params *app) -{ - app_init_core_map(app); - app_init_core_mask(app); - - app_init_eal(app); - app_init_mempool(app); - app_init_link(app); - app_init_swq(app); - app_init_tm(app); - app_init_tap(app); - app_init_kni(app); - app_init_msgq(app); - - app_pipeline_common_cmd_push(app); - app_pipeline_thread_cmd_push(app); - app_pipeline_type_register(app, &pipeline_master); - app_pipeline_type_register(app, &pipeline_passthrough); - app_pipeline_type_register(app, &pipeline_flow_classification); - app_pipeline_type_register(app, &pipeline_flow_actions); - app_pipeline_type_register(app, &pipeline_firewall); - app_pipeline_type_register(app, &pipeline_routing); - - app_init_pipelines(app); - app_init_threads(app); - - return 0; -} - -int app_post_init(struct app_params *app) -{ - app_post_init_pipelines(app); - - return 0; -} - -static int -app_pipeline_type_cmd_push(struct app_params *app, - struct pipeline_type *ptype) -{ - cmdline_parse_ctx_t *cmds; - uint32_t n_cmds, i; - - /* Check input arguments */ - if ((app == NULL) || - (ptype == NULL)) - return -EINVAL; - - n_cmds = pipeline_type_cmds_count(ptype); - if (n_cmds == 0) - return 0; - - cmds = ptype->fe_ops->cmds; - - /* Check for available slots in the application commands array */ - if (n_cmds > APP_MAX_CMDS - app->n_cmds) - return -ENOMEM; - - /* Push pipeline commands into the application */ - memcpy(&app->cmds[app->n_cmds], - cmds, - n_cmds * sizeof(cmdline_parse_ctx_t)); - - for (i = 0; i < n_cmds; i++) - app->cmds[app->n_cmds + i]->data = app; - - app->n_cmds += n_cmds; - app->cmds[app->n_cmds] = NULL; - - return 0; -} - -int -app_pipeline_type_register(struct app_params *app, struct pipeline_type *ptype) -{ - uint32_t n_cmds, i; - - /* Check input arguments */ - if ((app == NULL) || - (ptype == NULL) || - (ptype->name == NULL) || - (strlen(ptype->name) == 0) || - (ptype->be_ops->f_init == NULL) || - (ptype->be_ops->f_timer == NULL)) - return -EINVAL; - - /* Check for duplicate entry */ - for (i = 0; i < app->n_pipeline_types; i++) - if (strcmp(app->pipeline_type[i].name, ptype->name) == 0) - return -EEXIST; - - /* Check for resource availability */ - n_cmds = pipeline_type_cmds_count(ptype); - if ((app->n_pipeline_types == APP_MAX_PIPELINE_TYPES) || - (n_cmds > APP_MAX_CMDS - app->n_cmds)) - return -ENOMEM; - - /* Copy pipeline type */ - memcpy(&app->pipeline_type[app->n_pipeline_types++], - ptype, - sizeof(struct pipeline_type)); - - /* Copy CLI commands */ - if (n_cmds) - app_pipeline_type_cmd_push(app, ptype); - - return 0; -} - -struct -pipeline_type *app_pipeline_type_find(struct app_params *app, char *name) -{ - uint32_t i; - - for (i = 0; i < app->n_pipeline_types; i++) - if (strcmp(app->pipeline_type[i].name, name) == 0) - return &app->pipeline_type[i]; - - return NULL; -} diff --git a/examples/ip_pipeline/kni.c b/examples/ip_pipeline/kni.c new file mode 100644 index 00000000..7e5ff054 --- /dev/null +++ b/examples/ip_pipeline/kni.c @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <stdlib.h> +#include <string.h> + +#include <rte_ethdev.h> +#include <rte_bus_pci.h> +#include <rte_string_fns.h> + +#include "kni.h" +#include "mempool.h" +#include "link.h" + +static struct kni_list kni_list; + +#ifndef KNI_MAX +#define KNI_MAX 16 +#endif + +int +kni_init(void) +{ + TAILQ_INIT(&kni_list); + +#ifdef RTE_LIBRTE_KNI + rte_kni_init(KNI_MAX); +#endif + + return 0; +} + +struct kni * +kni_find(const char *name) +{ + struct kni *kni; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(kni, &kni_list, node) + if (strcmp(kni->name, name) == 0) + return kni; + + return NULL; +} + +#ifndef RTE_LIBRTE_KNI + +struct kni * +kni_create(const char *name __rte_unused, + struct kni_params *params __rte_unused) +{ + return NULL; +} + +void +kni_handle_request(void) +{ + return; +} + +#else + +static int +kni_config_network_interface(uint16_t port_id, uint8_t if_up) +{ + int ret = 0; + + if (!rte_eth_dev_is_valid_port(port_id)) + return -EINVAL; + + ret = (if_up) ? + rte_eth_dev_set_link_up(port_id) : + rte_eth_dev_set_link_down(port_id); + + return ret; +} + +static int +kni_change_mtu(uint16_t port_id, unsigned int new_mtu) +{ + int ret; + + if (!rte_eth_dev_is_valid_port(port_id)) + return -EINVAL; + + if (new_mtu > ETHER_MAX_LEN) + return -EINVAL; + + /* Set new MTU */ + ret = rte_eth_dev_set_mtu(port_id, new_mtu); + if (ret < 0) + return ret; + + return 0; +} + +struct kni * +kni_create(const char *name, struct kni_params *params) +{ + struct rte_eth_dev_info dev_info; + struct rte_kni_conf kni_conf; + struct rte_kni_ops kni_ops; + struct kni *kni; + struct mempool *mempool; + struct link *link; + struct rte_kni *k; + const struct rte_pci_device *pci_dev; + const struct rte_bus *bus = NULL; + + /* Check input params */ + if ((name == NULL) || + kni_find(name) || + (params == NULL)) + return NULL; + + mempool = mempool_find(params->mempool_name); + link = link_find(params->link_name); + if ((mempool == NULL) || + (link == NULL)) + return NULL; + + /* Resource create */ + rte_eth_dev_info_get(link->port_id, &dev_info); + + memset(&kni_conf, 0, sizeof(kni_conf)); + snprintf(kni_conf.name, RTE_KNI_NAMESIZE, "%s", name); + kni_conf.force_bind = params->force_bind; + kni_conf.core_id = params->thread_id; + kni_conf.group_id = link->port_id; + kni_conf.mbuf_size = mempool->buffer_size; + if (dev_info.device) + bus = rte_bus_find_by_device(dev_info.device); + if (bus && !strcmp(bus->name, "pci")) { + pci_dev = RTE_DEV_TO_PCI(dev_info.device); + kni_conf.addr = pci_dev->addr; + kni_conf.id = pci_dev->id; + } + + memset(&kni_ops, 0, sizeof(kni_ops)); + kni_ops.port_id = link->port_id; + kni_ops.config_network_if = kni_config_network_interface; + kni_ops.change_mtu = kni_change_mtu; + + k = rte_kni_alloc(mempool->m, &kni_conf, &kni_ops); + if (k == NULL) + return NULL; + + /* Node allocation */ + kni = calloc(1, sizeof(struct kni)); + if (kni == NULL) + return NULL; + + /* Node fill in */ + strlcpy(kni->name, name, sizeof(kni->name)); + kni->k = k; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&kni_list, kni, node); + + return kni; +} + +void +kni_handle_request(void) +{ + struct kni *kni; + + TAILQ_FOREACH(kni, &kni_list, node) + rte_kni_handle_request(kni->k); +} + +#endif diff --git a/examples/ip_pipeline/kni.h b/examples/ip_pipeline/kni.h new file mode 100644 index 00000000..c3856456 --- /dev/null +++ b/examples/ip_pipeline/kni.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _INCLUDE_KNI_H_ +#define _INCLUDE_KNI_H_ + +#include <stdint.h> +#include <sys/queue.h> + +#ifdef RTE_LIBRTE_KNI +#include <rte_kni.h> +#endif + +#include "common.h" + +struct kni { + TAILQ_ENTRY(kni) node; + char name[NAME_SIZE]; +#ifdef RTE_LIBRTE_KNI + struct rte_kni *k; +#endif +}; + +TAILQ_HEAD(kni_list, kni); + +int +kni_init(void); + +struct kni * +kni_find(const char *name); + +struct kni_params { + const char *link_name; + const char *mempool_name; + int force_bind; + uint32_t thread_id; +}; + +struct kni * +kni_create(const char *name, struct kni_params *params); + +void +kni_handle_request(void); + +#endif /* _INCLUDE_KNI_H_ */ diff --git a/examples/ip_pipeline/link.c b/examples/ip_pipeline/link.c new file mode 100644 index 00000000..392a890f --- /dev/null +++ b/examples/ip_pipeline/link.c @@ -0,0 +1,267 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <stdlib.h> +#include <string.h> + +#include <rte_ethdev.h> +#include <rte_string_fns.h> + +#include "link.h" +#include "mempool.h" + +static struct link_list link_list; + +int +link_init(void) +{ + TAILQ_INIT(&link_list); + + return 0; +} + +struct link * +link_find(const char *name) +{ + struct link *link; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(link, &link_list, node) + if (strcmp(link->name, name) == 0) + return link; + + return NULL; +} + +struct link * +link_next(struct link *link) +{ + return (link == NULL) ? TAILQ_FIRST(&link_list) : TAILQ_NEXT(link, node); +} + +static struct rte_eth_conf port_conf_default = { + .link_speeds = 0, + .rxmode = { + .mq_mode = ETH_MQ_RX_NONE, + .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */ + .split_hdr_size = 0, /* Header split buffer size */ + .offloads = DEV_RX_OFFLOAD_CRC_STRIP, + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_key_len = 40, + .rss_hf = 0, + }, + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + }, + .lpbk_mode = 0, +}; + +#define RETA_CONF_SIZE (ETH_RSS_RETA_SIZE_512 / RTE_RETA_GROUP_SIZE) + +static int +rss_setup(uint16_t port_id, + uint16_t reta_size, + struct link_params_rss *rss) +{ + struct rte_eth_rss_reta_entry64 reta_conf[RETA_CONF_SIZE]; + uint32_t i; + int status; + + /* RETA setting */ + memset(reta_conf, 0, sizeof(reta_conf)); + + for (i = 0; i < reta_size; i++) + reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX; + + for (i = 0; i < reta_size; i++) { + uint32_t reta_id = i / RTE_RETA_GROUP_SIZE; + uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE; + uint32_t rss_qs_pos = i % rss->n_queues; + + reta_conf[reta_id].reta[reta_pos] = + (uint16_t) rss->queue_id[rss_qs_pos]; + } + + /* RETA update */ + status = rte_eth_dev_rss_reta_update(port_id, + reta_conf, + reta_size); + + return status; +} + +struct link * +link_create(const char *name, struct link_params *params) +{ + struct rte_eth_dev_info port_info; + struct rte_eth_conf port_conf; + struct link *link; + struct link_params_rss *rss; + struct mempool *mempool; + uint32_t cpu_id, i; + int status; + uint16_t port_id; + + /* Check input params */ + if ((name == NULL) || + link_find(name) || + (params == NULL) || + (params->rx.n_queues == 0) || + (params->rx.queue_size == 0) || + (params->tx.n_queues == 0) || + (params->tx.queue_size == 0)) + return NULL; + + port_id = params->port_id; + if (params->dev_name) { + status = rte_eth_dev_get_port_by_name(params->dev_name, + &port_id); + + if (status) + return NULL; + } else + if (!rte_eth_dev_is_valid_port(port_id)) + return NULL; + + rte_eth_dev_info_get(port_id, &port_info); + + mempool = mempool_find(params->rx.mempool_name); + if (mempool == NULL) + return NULL; + + rss = params->rx.rss; + if (rss) { + if ((port_info.reta_size == 0) || + (port_info.reta_size > ETH_RSS_RETA_SIZE_512)) + return NULL; + + if ((rss->n_queues == 0) || + (rss->n_queues >= LINK_RXQ_RSS_MAX)) + return NULL; + + for (i = 0; i < rss->n_queues; i++) + if (rss->queue_id[i] >= port_info.max_rx_queues) + return NULL; + } + + /** + * Resource create + */ + /* Port */ + memcpy(&port_conf, &port_conf_default, sizeof(port_conf)); + if (rss) { + port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS; + port_conf.rx_adv_conf.rss_conf.rss_hf = + (ETH_RSS_IP | ETH_RSS_TCP | ETH_RSS_UDP) & + port_info.flow_type_rss_offloads; + } + + cpu_id = (uint32_t) rte_eth_dev_socket_id(port_id); + if (cpu_id == (uint32_t) SOCKET_ID_ANY) + cpu_id = 0; + + status = rte_eth_dev_configure( + port_id, + params->rx.n_queues, + params->tx.n_queues, + &port_conf); + + if (status < 0) + return NULL; + + if (params->promiscuous) + rte_eth_promiscuous_enable(port_id); + + /* Port RX */ + for (i = 0; i < params->rx.n_queues; i++) { + status = rte_eth_rx_queue_setup( + port_id, + i, + params->rx.queue_size, + cpu_id, + NULL, + mempool->m); + + if (status < 0) + return NULL; + } + + /* Port TX */ + for (i = 0; i < params->tx.n_queues; i++) { + status = rte_eth_tx_queue_setup( + port_id, + i, + params->tx.queue_size, + cpu_id, + NULL); + + if (status < 0) + return NULL; + } + + /* Port start */ + status = rte_eth_dev_start(port_id); + if (status < 0) + return NULL; + + if (rss) { + status = rss_setup(port_id, port_info.reta_size, rss); + + if (status) { + rte_eth_dev_stop(port_id); + return NULL; + } + } + + /* Port link up */ + status = rte_eth_dev_set_link_up(port_id); + if ((status < 0) && (status != -ENOTSUP)) { + rte_eth_dev_stop(port_id); + return NULL; + } + + /* Node allocation */ + link = calloc(1, sizeof(struct link)); + if (link == NULL) { + rte_eth_dev_stop(port_id); + return NULL; + } + + /* Node fill in */ + strlcpy(link->name, name, sizeof(link->name)); + link->port_id = port_id; + link->n_rxq = params->rx.n_queues; + link->n_txq = params->tx.n_queues; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&link_list, link, node); + + return link; +} + +int +link_is_up(const char *name) +{ + struct rte_eth_link link_params; + struct link *link; + + /* Check input params */ + if (name == NULL) + return 0; + + link = link_find(name); + if (link == NULL) + return 0; + + /* Resource */ + rte_eth_link_get(link->port_id, &link_params); + + return (link_params.link_status == ETH_LINK_DOWN) ? 0 : 1; +} diff --git a/examples/ip_pipeline/link.h b/examples/ip_pipeline/link.h new file mode 100644 index 00000000..34ff1149 --- /dev/null +++ b/examples/ip_pipeline/link.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _INCLUDE_LINK_H_ +#define _INCLUDE_LINK_H_ + +#include <stdint.h> +#include <sys/queue.h> + +#include "common.h" + +#ifndef LINK_RXQ_RSS_MAX +#define LINK_RXQ_RSS_MAX 16 +#endif + +struct link { + TAILQ_ENTRY(link) node; + char name[NAME_SIZE]; + uint16_t port_id; + uint32_t n_rxq; + uint32_t n_txq; +}; + +TAILQ_HEAD(link_list, link); + +int +link_init(void); + +struct link * +link_find(const char *name); + +struct link * +link_next(struct link *link); + +struct link_params_rss { + uint32_t queue_id[LINK_RXQ_RSS_MAX]; + uint32_t n_queues; +}; + +struct link_params { + const char *dev_name; + uint16_t port_id; /**< Valid only when *dev_name* is NULL. */ + + struct { + uint32_t n_queues; + uint32_t queue_size; + const char *mempool_name; + struct link_params_rss *rss; + } rx; + + struct { + uint32_t n_queues; + uint32_t queue_size; + } tx; + + int promiscuous; +}; + +struct link * +link_create(const char *name, struct link_params *params); + +int +link_is_up(const char *name); + +#endif /* _INCLUDE_LINK_H_ */ diff --git a/examples/ip_pipeline/main.c b/examples/ip_pipeline/main.c index a44cf9a3..a69facee 100644 --- a/examples/ip_pipeline/main.c +++ b/examples/ip_pipeline/main.c @@ -1,35 +1,260 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation + * Copyright(c) 2010-2018 Intel Corporation */ -#include "app.h" +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <getopt.h> -static struct app_params app; +#include <rte_launch.h> +#include <rte_eal.h> + +#include "cli.h" +#include "conn.h" +#include "kni.h" +#include "link.h" +#include "mempool.h" +#include "pipeline.h" +#include "swq.h" +#include "tap.h" +#include "thread.h" +#include "tmgr.h" + +static const char usage[] = + "%s EAL_ARGS -- [-h HOST] [-p PORT] [-s SCRIPT]\n"; + +static const char welcome[] = + "\n" + "Welcome to IP Pipeline!\n" + "\n"; + +static const char prompt[] = "pipeline> "; + +static struct app_params { + struct conn_params conn; + char *script_name; +} app = { + .conn = { + .welcome = welcome, + .prompt = prompt, + .addr = "0.0.0.0", + .port = 8086, + .buf_size = 1024 * 1024, + .msg_in_len_max = 1024, + .msg_out_len_max = 1024 * 1024, + .msg_handle = cli_process, + }, + .script_name = NULL, +}; + +static int +parse_args(int argc, char **argv) +{ + char *app_name = argv[0]; + struct option lgopts[] = { + { NULL, 0, 0, 0 } + }; + int opt, option_index; + int h_present, p_present, s_present, n_args, i; + + /* Skip EAL input args */ + n_args = argc; + for (i = 0; i < n_args; i++) + if (strcmp(argv[i], "--") == 0) { + argc -= i; + argv += i; + break; + } + + if (i == n_args) + return 0; + + /* Parse args */ + h_present = 0; + p_present = 0; + s_present = 0; + + while ((opt = getopt_long(argc, argv, "h:p:s:", lgopts, &option_index)) + != EOF) + switch (opt) { + case 'h': + if (h_present) { + printf("Error: Multiple -h arguments\n"); + return -1; + } + h_present = 1; + + if (!strlen(optarg)) { + printf("Error: Argument for -h not provided\n"); + return -1; + } + + app.conn.addr = strdup(optarg); + if (app.conn.addr == NULL) { + printf("Error: Not enough memory\n"); + return -1; + } + break; + + case 'p': + if (p_present) { + printf("Error: Multiple -p arguments\n"); + return -1; + } + p_present = 1; + + if (!strlen(optarg)) { + printf("Error: Argument for -p not provided\n"); + return -1; + } + + app.conn.port = (uint16_t) atoi(optarg); + break; + + case 's': + if (s_present) { + printf("Error: Multiple -s arguments\n"); + return -1; + } + s_present = 1; + + if (!strlen(optarg)) { + printf("Error: Argument for -s not provided\n"); + return -1; + } + + app.script_name = strdup(optarg); + if (app.script_name == NULL) { + printf("Error: Not enough memory\n"); + return -1; + } + break; + + default: + printf(usage, app_name); + return -1; + } + + optind = 1; /* reset getopt lib */ + + return 0; +} int main(int argc, char **argv) { - rte_openlog_stream(stderr); + struct conn *conn; + int status; + + /* Parse application arguments */ + status = parse_args(argc, argv); + if (status < 0) + return status; + + /* EAL */ + status = rte_eal_init(argc, argv); + if (status < 0) { + printf("Error: EAL initialization failed (%d)\n", status); + return status; + }; + + /* Connectivity */ + conn = conn_init(&app.conn); + if (conn == NULL) { + printf("Error: Connectivity initialization failed (%d)\n", + status); + return status; + }; - /* Config */ - app_config_init(&app); + /* Mempool */ + status = mempool_init(); + if (status) { + printf("Error: Mempool initialization failed (%d)\n", status); + return status; + } - app_config_args(&app, argc, argv); + /* Link */ + status = link_init(); + if (status) { + printf("Error: Link initialization failed (%d)\n", status); + return status; + } - app_config_preproc(&app); + /* SWQ */ + status = swq_init(); + if (status) { + printf("Error: SWQ initialization failed (%d)\n", status); + return status; + } - app_config_parse(&app, app.parser_file); + /* Traffic Manager */ + status = tmgr_init(); + if (status) { + printf("Error: TMGR initialization failed (%d)\n", status); + return status; + } - app_config_check(&app); + /* TAP */ + status = tap_init(); + if (status) { + printf("Error: TAP initialization failed (%d)\n", status); + return status; + } - /* Init */ - app_init(&app); + /* KNI */ + status = kni_init(); + if (status) { + printf("Error: KNI initialization failed (%d)\n", status); + return status; + } + + /* Action */ + status = port_in_action_profile_init(); + if (status) { + printf("Error: Input port action profile initialization failed (%d)\n", status); + return status; + } + + status = table_action_profile_init(); + if (status) { + printf("Error: Action profile initialization failed (%d)\n", + status); + return status; + } + + /* Pipeline */ + status = pipeline_init(); + if (status) { + printf("Error: Pipeline initialization failed (%d)\n", status); + return status; + } + + /* Thread */ + status = thread_init(); + if (status) { + printf("Error: Thread initialization failed (%d)\n", status); + return status; + } - /* Run-time */ rte_eal_mp_remote_launch( - app_thread, - (void *) &app, - CALL_MASTER); + thread_main, + NULL, + SKIP_MASTER); - return 0; + /* Script */ + if (app.script_name) + cli_script_process(app.script_name, + app.conn.msg_in_len_max, + app.conn.msg_out_len_max); + + /* Dispatch loop */ + for ( ; ; ) { + conn_poll_for_conn(conn); + + conn_poll_for_msg(conn); + + kni_handle_request(); + } } diff --git a/examples/ip_pipeline/mempool.c b/examples/ip_pipeline/mempool.c new file mode 100644 index 00000000..f5d2a7d1 --- /dev/null +++ b/examples/ip_pipeline/mempool.c @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <stdlib.h> +#include <string.h> + +#include <rte_mbuf.h> +#include <rte_string_fns.h> + +#include "mempool.h" + +#define BUFFER_SIZE_MIN (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) + +static struct mempool_list mempool_list; + +int +mempool_init(void) +{ + TAILQ_INIT(&mempool_list); + + return 0; +} + +struct mempool * +mempool_find(const char *name) +{ + struct mempool *mempool; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(mempool, &mempool_list, node) + if (strcmp(mempool->name, name) == 0) + return mempool; + + return NULL; +} + +struct mempool * +mempool_create(const char *name, struct mempool_params *params) +{ + struct mempool *mempool; + struct rte_mempool *m; + + /* Check input params */ + if ((name == NULL) || + mempool_find(name) || + (params == NULL) || + (params->buffer_size < BUFFER_SIZE_MIN) || + (params->pool_size == 0)) + return NULL; + + /* Resource create */ + m = rte_pktmbuf_pool_create( + name, + params->pool_size, + params->cache_size, + 0, + params->buffer_size - sizeof(struct rte_mbuf), + params->cpu_id); + + if (m == NULL) + return NULL; + + /* Node allocation */ + mempool = calloc(1, sizeof(struct mempool)); + if (mempool == NULL) { + rte_mempool_free(m); + return NULL; + } + + /* Node fill in */ + strlcpy(mempool->name, name, sizeof(mempool->name)); + mempool->m = m; + mempool->buffer_size = params->buffer_size; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&mempool_list, mempool, node); + + return mempool; +} diff --git a/examples/ip_pipeline/mempool.h b/examples/ip_pipeline/mempool.h new file mode 100644 index 00000000..bd46a11c --- /dev/null +++ b/examples/ip_pipeline/mempool.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _INCLUDE_MEMPOOL_H_ +#define _INCLUDE_MEMPOOL_H_ + +#include <stdint.h> +#include <sys/queue.h> + +#include <rte_mempool.h> + +#include "common.h" + +struct mempool { + TAILQ_ENTRY(mempool) node; + char name[NAME_SIZE]; + struct rte_mempool *m; + uint32_t buffer_size; +}; + +TAILQ_HEAD(mempool_list, mempool); + +int +mempool_init(void); + +struct mempool * +mempool_find(const char *name); + +struct mempool_params { + uint32_t buffer_size; + uint32_t pool_size; + uint32_t cache_size; + uint32_t cpu_id; +}; + +struct mempool * +mempool_create(const char *name, struct mempool_params *params); + +#endif /* _INCLUDE_MEMPOOL_H_ */ diff --git a/examples/ip_pipeline/meson.build b/examples/ip_pipeline/meson.build index 748c9ae0..a9f2ea44 100644 --- a/examples/ip_pipeline/meson.build +++ b/examples/ip_pipeline/meson.build @@ -1,35 +1,25 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2017 Intel Corporation +# Copyright(c) 2017-2018 Intel Corporation # meson file, for building this example as part of a main DPDK build. # # To build this example as a standalone application with an already-installed # DPDK instance, use 'make' -deps += ['cfgfile', 'pipeline', 'bus_pci'] -includes += include_directories('pipeline') +deps += ['pipeline', 'bus_pci'] +allow_experimental_apis = true sources = files( - 'config_check.c', - 'config_parse.c', - 'config_parse_tm.c', - 'cpu_core_map.c', - 'init.c', + 'action.c', + 'cli.c', + 'conn.c', + 'kni.c', + 'link.c', 'main.c', + 'mempool.c', 'parser.c', + 'pipeline.c', + 'swq.c', + 'tap.c', 'thread.c', - 'thread_fe.c', - 'pipeline/pipeline_common_be.c', - 'pipeline/pipeline_common_fe.c', - 'pipeline/pipeline_firewall_be.c', - 'pipeline/pipeline_firewall.c', - 'pipeline/pipeline_flow_actions_be.c', - 'pipeline/pipeline_flow_actions.c', - 'pipeline/pipeline_flow_classification_be.c', - 'pipeline/pipeline_flow_classification.c', - 'pipeline/pipeline_master_be.c', - 'pipeline/pipeline_master.c', - 'pipeline/pipeline_passthrough_be.c', - 'pipeline/pipeline_passthrough.c', - 'pipeline/pipeline_routing_be.c', - 'pipeline/pipeline_routing.c', + 'tmgr.c' ) diff --git a/examples/ip_pipeline/parser.c b/examples/ip_pipeline/parser.c index 0901e9c6..ffcdeb3a 100644 --- a/examples/ip_pipeline/parser.c +++ b/examples/ip_pipeline/parser.c @@ -36,10 +36,8 @@ #include <sys/wait.h> #include <rte_errno.h> -#include <rte_cfgfile.h> #include <rte_string_fns.h> -#include "app.h" #include "parser.h" static uint32_t @@ -596,10 +594,8 @@ parse_mac_addr(const char *token, struct ether_addr *addr) } int -parse_pipeline_core(uint32_t *socket, - uint32_t *core, - uint32_t *ht, - const char *entry) +parse_cpu_core(const char *entry, + struct cpu_core_params *p) { size_t num_len; char num[8]; @@ -609,6 +605,9 @@ parse_pipeline_core(uint32_t *socket, const char *next = skip_white_spaces(entry); char type; + if (p == NULL) + return -EINVAL; + /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */ while (*next != '\0') { /* If everything parsed nothing should left */ @@ -682,8 +681,8 @@ parse_pipeline_core(uint32_t *socket, } } - *socket = s; - *core = c; - *ht = h; + p->socket_id = s; + p->core_id = c; + p->thread_id = h; return 0; } diff --git a/examples/ip_pipeline/parser.h b/examples/ip_pipeline/parser.h index 5c421d27..261a8c85 100644 --- a/examples/ip_pipeline/parser.h +++ b/examples/ip_pipeline/parser.h @@ -50,6 +50,14 @@ int parse_ipv6_addr(const char *token, struct in6_addr *ipv6); int parse_mac_addr(const char *token, struct ether_addr *addr); int parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels); +struct cpu_core_params { + uint32_t socket_id; + uint32_t core_id; + uint32_t thread_id; +}; + +int parse_cpu_core(const char *entry, struct cpu_core_params *p); + int parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens); #endif diff --git a/examples/ip_pipeline/pipeline.c b/examples/ip_pipeline/pipeline.c new file mode 100644 index 00000000..43fe8677 --- /dev/null +++ b/examples/ip_pipeline/pipeline.c @@ -0,0 +1,988 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <stdlib.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_ip.h> +#include <rte_tcp.h> + +#include <rte_string_fns.h> +#include <rte_port_ethdev.h> +#ifdef RTE_LIBRTE_KNI +#include <rte_port_kni.h> +#endif +#include <rte_port_ring.h> +#include <rte_port_source_sink.h> +#include <rte_port_fd.h> +#include <rte_port_sched.h> + +#include <rte_table_acl.h> +#include <rte_table_array.h> +#include <rte_table_hash.h> +#include <rte_table_lpm.h> +#include <rte_table_lpm_ipv6.h> +#include <rte_table_stub.h> + +#ifdef RTE_LIBRTE_KNI +#include "kni.h" +#endif +#include "link.h" +#include "mempool.h" +#include "pipeline.h" +#include "tap.h" +#include "tmgr.h" +#include "swq.h" + +#include "hash_func.h" + +#ifndef PIPELINE_MSGQ_SIZE +#define PIPELINE_MSGQ_SIZE 64 +#endif + +#ifndef TABLE_LPM_NUMBER_TBL8 +#define TABLE_LPM_NUMBER_TBL8 256 +#endif + +static struct pipeline_list pipeline_list; + +int +pipeline_init(void) +{ + TAILQ_INIT(&pipeline_list); + + return 0; +} + +struct pipeline * +pipeline_find(const char *name) +{ + struct pipeline *pipeline; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(pipeline, &pipeline_list, node) + if (strcmp(name, pipeline->name) == 0) + return pipeline; + + return NULL; +} + +struct pipeline * +pipeline_create(const char *name, struct pipeline_params *params) +{ + char msgq_name[NAME_MAX]; + struct rte_pipeline_params pp; + struct pipeline *pipeline; + struct rte_pipeline *p; + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + + /* Check input params */ + if ((name == NULL) || + pipeline_find(name) || + (params == NULL) || + (params->timer_period_ms == 0)) + return NULL; + + /* Resource create */ + snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-REQ", name); + + msgq_req = rte_ring_create(msgq_name, + PIPELINE_MSGQ_SIZE, + params->cpu_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (msgq_req == NULL) + return NULL; + + snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-RSP", name); + + msgq_rsp = rte_ring_create(msgq_name, + PIPELINE_MSGQ_SIZE, + params->cpu_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (msgq_rsp == NULL) { + rte_ring_free(msgq_req); + return NULL; + } + + pp.name = name; + pp.socket_id = (int) params->cpu_id; + pp.offset_port_id = params->offset_port_id; + + p = rte_pipeline_create(&pp); + if (p == NULL) { + rte_ring_free(msgq_rsp); + rte_ring_free(msgq_req); + return NULL; + } + + /* Node allocation */ + pipeline = calloc(1, sizeof(struct pipeline)); + if (pipeline == NULL) { + rte_pipeline_free(p); + rte_ring_free(msgq_rsp); + rte_ring_free(msgq_req); + return NULL; + } + + /* Node fill in */ + strlcpy(pipeline->name, name, sizeof(pipeline->name)); + pipeline->p = p; + pipeline->n_ports_in = 0; + pipeline->n_ports_out = 0; + pipeline->n_tables = 0; + pipeline->msgq_req = msgq_req; + pipeline->msgq_rsp = msgq_rsp; + pipeline->timer_period_ms = params->timer_period_ms; + pipeline->enabled = 0; + pipeline->cpu_id = params->cpu_id; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&pipeline_list, pipeline, node); + + return pipeline; +} + +int +pipeline_port_in_create(const char *pipeline_name, + struct port_in_params *params, + int enabled) +{ + struct rte_pipeline_port_in_params p; + + union { + struct rte_port_ethdev_reader_params ethdev; + struct rte_port_ring_reader_params ring; + struct rte_port_sched_reader_params sched; + struct rte_port_fd_reader_params fd; +#ifdef RTE_LIBRTE_KNI + struct rte_port_kni_reader_params kni; +#endif + struct rte_port_source_params source; + } pp; + + struct pipeline *pipeline; + struct port_in *port_in; + struct port_in_action_profile *ap; + struct rte_port_in_action *action; + uint32_t port_id; + int status; + + memset(&p, 0, sizeof(p)); + memset(&pp, 0, sizeof(pp)); + + /* Check input params */ + if ((pipeline_name == NULL) || + (params == NULL) || + (params->burst_size == 0) || + (params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX)) + return -1; + + pipeline = pipeline_find(pipeline_name); + if (pipeline == NULL) + return -1; + + ap = NULL; + if (params->action_profile_name) { + ap = port_in_action_profile_find(params->action_profile_name); + if (ap == NULL) + return -1; + } + + switch (params->type) { + case PORT_IN_RXQ: + { + struct link *link; + + link = link_find(params->dev_name); + if (link == NULL) + return -1; + + if (params->rxq.queue_id >= link->n_rxq) + return -1; + + pp.ethdev.port_id = link->port_id; + pp.ethdev.queue_id = params->rxq.queue_id; + + p.ops = &rte_port_ethdev_reader_ops; + p.arg_create = &pp.ethdev; + break; + } + + case PORT_IN_SWQ: + { + struct swq *swq; + + swq = swq_find(params->dev_name); + if (swq == NULL) + return -1; + + pp.ring.ring = swq->r; + + p.ops = &rte_port_ring_reader_ops; + p.arg_create = &pp.ring; + break; + } + + case PORT_IN_TMGR: + { + struct tmgr_port *tmgr_port; + + tmgr_port = tmgr_port_find(params->dev_name); + if (tmgr_port == NULL) + return -1; + + pp.sched.sched = tmgr_port->s; + + p.ops = &rte_port_sched_reader_ops; + p.arg_create = &pp.sched; + break; + } + + case PORT_IN_TAP: + { + struct tap *tap; + struct mempool *mempool; + + tap = tap_find(params->dev_name); + mempool = mempool_find(params->tap.mempool_name); + if ((tap == NULL) || (mempool == NULL)) + return -1; + + pp.fd.fd = tap->fd; + pp.fd.mempool = mempool->m; + pp.fd.mtu = params->tap.mtu; + + p.ops = &rte_port_fd_reader_ops; + p.arg_create = &pp.fd; + break; + } + +#ifdef RTE_LIBRTE_KNI + case PORT_IN_KNI: + { + struct kni *kni; + + kni = kni_find(params->dev_name); + if (kni == NULL) + return -1; + + pp.kni.kni = kni->k; + + p.ops = &rte_port_kni_reader_ops; + p.arg_create = &pp.kni; + break; + } +#endif + + case PORT_IN_SOURCE: + { + struct mempool *mempool; + + mempool = mempool_find(params->source.mempool_name); + if (mempool == NULL) + return -1; + + pp.source.mempool = mempool->m; + pp.source.file_name = params->source.file_name; + pp.source.n_bytes_per_pkt = params->source.n_bytes_per_pkt; + + p.ops = &rte_port_source_ops; + p.arg_create = &pp.source; + break; + } + + default: + return -1; + } + + p.burst_size = params->burst_size; + + /* Resource create */ + action = NULL; + p.f_action = NULL; + p.arg_ah = NULL; + + if (ap) { + action = rte_port_in_action_create(ap->ap, + pipeline->cpu_id); + if (action == NULL) + return -1; + + status = rte_port_in_action_params_get( + action, + &p); + if (status) { + rte_port_in_action_free(action); + return -1; + } + } + + status = rte_pipeline_port_in_create(pipeline->p, + &p, + &port_id); + if (status) { + rte_port_in_action_free(action); + return -1; + } + + if (enabled) + rte_pipeline_port_in_enable(pipeline->p, port_id); + + /* Pipeline */ + port_in = &pipeline->port_in[pipeline->n_ports_in]; + memcpy(&port_in->params, params, sizeof(*params)); + port_in->ap = ap; + port_in->a = action; + pipeline->n_ports_in++; + + return 0; +} + +int +pipeline_port_in_connect_to_table(const char *pipeline_name, + uint32_t port_id, + uint32_t table_id) +{ + struct pipeline *pipeline; + int status; + + /* Check input params */ + if (pipeline_name == NULL) + return -1; + + pipeline = pipeline_find(pipeline_name); + if ((pipeline == NULL) || + (port_id >= pipeline->n_ports_in) || + (table_id >= pipeline->n_tables)) + return -1; + + /* Resource */ + status = rte_pipeline_port_in_connect_to_table(pipeline->p, + port_id, + table_id); + + return status; + +} + +int +pipeline_port_out_create(const char *pipeline_name, + struct port_out_params *params) +{ + struct rte_pipeline_port_out_params p; + + union { + struct rte_port_ethdev_writer_params ethdev; + struct rte_port_ring_writer_params ring; + struct rte_port_sched_writer_params sched; + struct rte_port_fd_writer_params fd; +#ifdef RTE_LIBRTE_KNI + struct rte_port_kni_writer_params kni; +#endif + struct rte_port_sink_params sink; + } pp; + + union { + struct rte_port_ethdev_writer_nodrop_params ethdev; + struct rte_port_ring_writer_nodrop_params ring; + struct rte_port_fd_writer_nodrop_params fd; +#ifdef RTE_LIBRTE_KNI + struct rte_port_kni_writer_nodrop_params kni; +#endif + } pp_nodrop; + + struct pipeline *pipeline; + uint32_t port_id; + int status; + + memset(&p, 0, sizeof(p)); + memset(&pp, 0, sizeof(pp)); + memset(&pp_nodrop, 0, sizeof(pp_nodrop)); + + /* Check input params */ + if ((pipeline_name == NULL) || + (params == NULL) || + (params->burst_size == 0) || + (params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX)) + return -1; + + pipeline = pipeline_find(pipeline_name); + if (pipeline == NULL) + return -1; + + switch (params->type) { + case PORT_OUT_TXQ: + { + struct link *link; + + link = link_find(params->dev_name); + if (link == NULL) + return -1; + + if (params->txq.queue_id >= link->n_txq) + return -1; + + pp.ethdev.port_id = link->port_id; + pp.ethdev.queue_id = params->txq.queue_id; + pp.ethdev.tx_burst_sz = params->burst_size; + + pp_nodrop.ethdev.port_id = link->port_id; + pp_nodrop.ethdev.queue_id = params->txq.queue_id; + pp_nodrop.ethdev.tx_burst_sz = params->burst_size; + pp_nodrop.ethdev.n_retries = params->n_retries; + + if (params->retry == 0) { + p.ops = &rte_port_ethdev_writer_ops; + p.arg_create = &pp.ethdev; + } else { + p.ops = &rte_port_ethdev_writer_nodrop_ops; + p.arg_create = &pp_nodrop.ethdev; + } + break; + } + + case PORT_OUT_SWQ: + { + struct swq *swq; + + swq = swq_find(params->dev_name); + if (swq == NULL) + return -1; + + pp.ring.ring = swq->r; + pp.ring.tx_burst_sz = params->burst_size; + + pp_nodrop.ring.ring = swq->r; + pp_nodrop.ring.tx_burst_sz = params->burst_size; + pp_nodrop.ring.n_retries = params->n_retries; + + if (params->retry == 0) { + p.ops = &rte_port_ring_writer_ops; + p.arg_create = &pp.ring; + } else { + p.ops = &rte_port_ring_writer_nodrop_ops; + p.arg_create = &pp_nodrop.ring; + } + break; + } + + case PORT_OUT_TMGR: + { + struct tmgr_port *tmgr_port; + + tmgr_port = tmgr_port_find(params->dev_name); + if (tmgr_port == NULL) + return -1; + + pp.sched.sched = tmgr_port->s; + pp.sched.tx_burst_sz = params->burst_size; + + p.ops = &rte_port_sched_writer_ops; + p.arg_create = &pp.sched; + break; + } + + case PORT_OUT_TAP: + { + struct tap *tap; + + tap = tap_find(params->dev_name); + if (tap == NULL) + return -1; + + pp.fd.fd = tap->fd; + pp.fd.tx_burst_sz = params->burst_size; + + pp_nodrop.fd.fd = tap->fd; + pp_nodrop.fd.tx_burst_sz = params->burst_size; + pp_nodrop.fd.n_retries = params->n_retries; + + if (params->retry == 0) { + p.ops = &rte_port_fd_writer_ops; + p.arg_create = &pp.fd; + } else { + p.ops = &rte_port_fd_writer_nodrop_ops; + p.arg_create = &pp_nodrop.fd; + } + break; + } + +#ifdef RTE_LIBRTE_KNI + case PORT_OUT_KNI: + { + struct kni *kni; + + kni = kni_find(params->dev_name); + if (kni == NULL) + return -1; + + pp.kni.kni = kni->k; + pp.kni.tx_burst_sz = params->burst_size; + + pp_nodrop.kni.kni = kni->k; + pp_nodrop.kni.tx_burst_sz = params->burst_size; + pp_nodrop.kni.n_retries = params->n_retries; + + if (params->retry == 0) { + p.ops = &rte_port_kni_writer_ops; + p.arg_create = &pp.kni; + } else { + p.ops = &rte_port_kni_writer_nodrop_ops; + p.arg_create = &pp_nodrop.kni; + } + break; + } +#endif + + case PORT_OUT_SINK: + { + pp.sink.file_name = params->sink.file_name; + pp.sink.max_n_pkts = params->sink.max_n_pkts; + + p.ops = &rte_port_sink_ops; + p.arg_create = &pp.sink; + break; + } + + default: + return -1; + } + + p.f_action = NULL; + p.arg_ah = NULL; + + /* Resource create */ + status = rte_pipeline_port_out_create(pipeline->p, + &p, + &port_id); + + if (status) + return -1; + + /* Pipeline */ + pipeline->n_ports_out++; + + return 0; +} + +static const struct rte_acl_field_def table_acl_field_format_ipv4[] = { + /* Protocol */ + [0] = { + .type = RTE_ACL_FIELD_TYPE_BITMASK, + .size = sizeof(uint8_t), + .field_index = 0, + .input_index = 0, + .offset = offsetof(struct ipv4_hdr, next_proto_id), + }, + + /* Source IP address (IPv4) */ + [1] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 1, + .input_index = 1, + .offset = offsetof(struct ipv4_hdr, src_addr), + }, + + /* Destination IP address (IPv4) */ + [2] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 2, + .input_index = 2, + .offset = offsetof(struct ipv4_hdr, dst_addr), + }, + + /* Source Port */ + [3] = { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = 3, + .input_index = 3, + .offset = sizeof(struct ipv4_hdr) + + offsetof(struct tcp_hdr, src_port), + }, + + /* Destination Port */ + [4] = { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = 4, + .input_index = 3, + .offset = sizeof(struct ipv4_hdr) + + offsetof(struct tcp_hdr, dst_port), + }, +}; + +static const struct rte_acl_field_def table_acl_field_format_ipv6[] = { + /* Protocol */ + [0] = { + .type = RTE_ACL_FIELD_TYPE_BITMASK, + .size = sizeof(uint8_t), + .field_index = 0, + .input_index = 0, + .offset = offsetof(struct ipv6_hdr, proto), + }, + + /* Source IP address (IPv6) */ + [1] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 1, + .input_index = 1, + .offset = offsetof(struct ipv6_hdr, src_addr[0]), + }, + + [2] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 2, + .input_index = 2, + .offset = offsetof(struct ipv6_hdr, src_addr[4]), + }, + + [3] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 3, + .input_index = 3, + .offset = offsetof(struct ipv6_hdr, src_addr[8]), + }, + + [4] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 4, + .input_index = 4, + .offset = offsetof(struct ipv6_hdr, src_addr[12]), + }, + + /* Destination IP address (IPv6) */ + [5] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 5, + .input_index = 5, + .offset = offsetof(struct ipv6_hdr, dst_addr[0]), + }, + + [6] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 6, + .input_index = 6, + .offset = offsetof(struct ipv6_hdr, dst_addr[4]), + }, + + [7] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 7, + .input_index = 7, + .offset = offsetof(struct ipv6_hdr, dst_addr[8]), + }, + + [8] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 8, + .input_index = 8, + .offset = offsetof(struct ipv6_hdr, dst_addr[12]), + }, + + /* Source Port */ + [9] = { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = 9, + .input_index = 9, + .offset = sizeof(struct ipv6_hdr) + + offsetof(struct tcp_hdr, src_port), + }, + + /* Destination Port */ + [10] = { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = 10, + .input_index = 9, + .offset = sizeof(struct ipv6_hdr) + + offsetof(struct tcp_hdr, dst_port), + }, +}; + +int +pipeline_table_create(const char *pipeline_name, + struct table_params *params) +{ + char name[NAME_MAX]; + struct rte_pipeline_table_params p; + + union { + struct rte_table_acl_params acl; + struct rte_table_array_params array; + struct rte_table_hash_params hash; + struct rte_table_lpm_params lpm; + struct rte_table_lpm_ipv6_params lpm_ipv6; + } pp; + + struct pipeline *pipeline; + struct table *table; + struct table_action_profile *ap; + struct rte_table_action *action; + uint32_t table_id; + int status; + + memset(&p, 0, sizeof(p)); + memset(&pp, 0, sizeof(pp)); + + /* Check input params */ + if ((pipeline_name == NULL) || + (params == NULL)) + return -1; + + pipeline = pipeline_find(pipeline_name); + if ((pipeline == NULL) || + (pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX)) + return -1; + + ap = NULL; + if (params->action_profile_name) { + ap = table_action_profile_find(params->action_profile_name); + if (ap == NULL) + return -1; + } + + snprintf(name, NAME_MAX, "%s_table%u", + pipeline_name, pipeline->n_tables); + + switch (params->match_type) { + case TABLE_ACL: + { + uint32_t ip_header_offset = params->match.acl.ip_header_offset - + (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM); + uint32_t i; + + if (params->match.acl.n_rules == 0) + return -1; + + pp.acl.name = name; + pp.acl.n_rules = params->match.acl.n_rules; + if (params->match.acl.ip_version) { + memcpy(&pp.acl.field_format, + &table_acl_field_format_ipv4, + sizeof(table_acl_field_format_ipv4)); + pp.acl.n_rule_fields = + RTE_DIM(table_acl_field_format_ipv4); + } else { + memcpy(&pp.acl.field_format, + &table_acl_field_format_ipv6, + sizeof(table_acl_field_format_ipv6)); + pp.acl.n_rule_fields = + RTE_DIM(table_acl_field_format_ipv6); + } + + for (i = 0; i < pp.acl.n_rule_fields; i++) + pp.acl.field_format[i].offset += ip_header_offset; + + p.ops = &rte_table_acl_ops; + p.arg_create = &pp.acl; + break; + } + + case TABLE_ARRAY: + { + if (params->match.array.n_keys == 0) + return -1; + + pp.array.n_entries = params->match.array.n_keys; + pp.array.offset = params->match.array.key_offset; + + p.ops = &rte_table_array_ops; + p.arg_create = &pp.array; + break; + } + + case TABLE_HASH: + { + struct rte_table_ops *ops; + rte_table_hash_op_hash f_hash; + + if (params->match.hash.n_keys == 0) + return -1; + + switch (params->match.hash.key_size) { + case 8: + f_hash = hash_default_key8; + break; + case 16: + f_hash = hash_default_key16; + break; + case 24: + f_hash = hash_default_key24; + break; + case 32: + f_hash = hash_default_key32; + break; + case 40: + f_hash = hash_default_key40; + break; + case 48: + f_hash = hash_default_key48; + break; + case 56: + f_hash = hash_default_key56; + break; + case 64: + f_hash = hash_default_key64; + break; + default: + return -1; + } + + pp.hash.name = name; + pp.hash.key_size = params->match.hash.key_size; + pp.hash.key_offset = params->match.hash.key_offset; + pp.hash.key_mask = params->match.hash.key_mask; + pp.hash.n_keys = params->match.hash.n_keys; + pp.hash.n_buckets = params->match.hash.n_buckets; + pp.hash.f_hash = f_hash; + pp.hash.seed = 0; + + if (params->match.hash.extendable_bucket) + switch (params->match.hash.key_size) { + case 8: + ops = &rte_table_hash_key8_ext_ops; + break; + case 16: + ops = &rte_table_hash_key16_ext_ops; + break; + default: + ops = &rte_table_hash_ext_ops; + } + else + switch (params->match.hash.key_size) { + case 8: + ops = &rte_table_hash_key8_lru_ops; + break; + case 16: + ops = &rte_table_hash_key16_lru_ops; + break; + default: + ops = &rte_table_hash_lru_ops; + } + + p.ops = ops; + p.arg_create = &pp.hash; + break; + } + + case TABLE_LPM: + { + if (params->match.lpm.n_rules == 0) + return -1; + + switch (params->match.lpm.key_size) { + case 4: + { + pp.lpm.name = name; + pp.lpm.n_rules = params->match.lpm.n_rules; + pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8; + pp.lpm.flags = 0; + pp.lpm.entry_unique_size = p.action_data_size + + sizeof(struct rte_pipeline_table_entry); + pp.lpm.offset = params->match.lpm.key_offset; + + p.ops = &rte_table_lpm_ops; + p.arg_create = &pp.lpm; + break; + } + + case 16: + { + pp.lpm_ipv6.name = name; + pp.lpm_ipv6.n_rules = params->match.lpm.n_rules; + pp.lpm_ipv6.number_tbl8s = TABLE_LPM_NUMBER_TBL8; + pp.lpm_ipv6.entry_unique_size = p.action_data_size + + sizeof(struct rte_pipeline_table_entry); + pp.lpm_ipv6.offset = params->match.lpm.key_offset; + + p.ops = &rte_table_lpm_ipv6_ops; + p.arg_create = &pp.lpm_ipv6; + break; + } + + default: + return -1; + } + + break; + } + + case TABLE_STUB: + { + p.ops = &rte_table_stub_ops; + p.arg_create = NULL; + break; + } + + default: + return -1; + } + + /* Resource create */ + action = NULL; + p.f_action_hit = NULL; + p.f_action_miss = NULL; + p.arg_ah = NULL; + + if (ap) { + action = rte_table_action_create(ap->ap, + pipeline->cpu_id); + if (action == NULL) + return -1; + + status = rte_table_action_table_params_get( + action, + &p); + if (status || + ((p.action_data_size + + sizeof(struct rte_pipeline_table_entry)) > + TABLE_RULE_ACTION_SIZE_MAX)) { + rte_table_action_free(action); + return -1; + } + } + + if (params->match_type == TABLE_LPM) { + if (params->match.lpm.key_size == 4) + pp.lpm.entry_unique_size = p.action_data_size + + sizeof(struct rte_pipeline_table_entry); + + if (params->match.lpm.key_size == 16) + pp.lpm_ipv6.entry_unique_size = p.action_data_size + + sizeof(struct rte_pipeline_table_entry); + } + + status = rte_pipeline_table_create(pipeline->p, + &p, + &table_id); + if (status) { + rte_table_action_free(action); + return -1; + } + + /* Pipeline */ + table = &pipeline->table[pipeline->n_tables]; + memcpy(&table->params, params, sizeof(*params)); + table->ap = ap; + table->a = action; + pipeline->n_tables++; + + return 0; +} diff --git a/examples/ip_pipeline/pipeline.h b/examples/ip_pipeline/pipeline.h index 7ca9cad6..a953a29f 100644 --- a/examples/ip_pipeline/pipeline.h +++ b/examples/ip_pipeline/pipeline.h @@ -1,73 +1,368 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation + * Copyright(c) 2010-2018 Intel Corporation */ -#ifndef __INCLUDE_PIPELINE_H__ -#define __INCLUDE_PIPELINE_H__ +#ifndef _INCLUDE_PIPELINE_H_ +#define _INCLUDE_PIPELINE_H_ -#include <cmdline_parse.h> +#include <stdint.h> +#include <sys/queue.h> -#include "pipeline_be.h" +#include <rte_pipeline.h> +#include <rte_table_action.h> -/* - * Pipeline type front-end operations - */ +#include "common.h" +#include "action.h" + +struct pipeline_params { + uint32_t timer_period_ms; + uint32_t offset_port_id; + uint32_t cpu_id; +}; -typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params, - void *arg); +enum port_in_type { + PORT_IN_RXQ, + PORT_IN_SWQ, + PORT_IN_TMGR, + PORT_IN_TAP, + PORT_IN_KNI, + PORT_IN_SOURCE, +}; -typedef int (*pipeline_fe_op_post_init)(void *pipeline); +struct port_in_params { + /* Read */ + enum port_in_type type; + const char *dev_name; + union { + struct { + uint16_t queue_id; + } rxq; -typedef int (*pipeline_fe_op_free)(void *pipeline); + struct { + const char *mempool_name; + uint32_t mtu; + } tap; -typedef int (*pipeline_fe_op_track)(struct pipeline_params *params, - uint32_t port_in, - uint32_t *port_out); + struct { + const char *mempool_name; + const char *file_name; + uint32_t n_bytes_per_pkt; + } source; + }; + uint32_t burst_size; -struct pipeline_fe_ops { - pipeline_fe_op_init f_init; - pipeline_fe_op_post_init f_post_init; - pipeline_fe_op_free f_free; - pipeline_fe_op_track f_track; - cmdline_parse_ctx_t *cmds; + /* Action */ + const char *action_profile_name; }; -/* - * Pipeline type - */ +enum port_out_type { + PORT_OUT_TXQ, + PORT_OUT_SWQ, + PORT_OUT_TMGR, + PORT_OUT_TAP, + PORT_OUT_KNI, + PORT_OUT_SINK, +}; + +struct port_out_params { + enum port_out_type type; + const char *dev_name; + union { + struct { + uint16_t queue_id; + } txq; + + struct { + const char *file_name; + uint32_t max_n_pkts; + } sink; + }; + uint32_t burst_size; + int retry; + uint32_t n_retries; +}; + +enum table_type { + TABLE_ACL, + TABLE_ARRAY, + TABLE_HASH, + TABLE_LPM, + TABLE_STUB, +}; -struct pipeline_type { - const char *name; +struct table_acl_params { + uint32_t n_rules; + uint32_t ip_header_offset; + int ip_version; +}; - /* pipeline back-end */ - struct pipeline_be_ops *be_ops; +struct table_array_params { + uint32_t n_keys; + uint32_t key_offset; +}; - /* pipeline front-end */ - struct pipeline_fe_ops *fe_ops; +struct table_hash_params { + uint32_t n_keys; + uint32_t key_offset; + uint32_t key_size; + uint8_t *key_mask; + uint32_t n_buckets; + int extendable_bucket; }; -static inline uint32_t -pipeline_type_cmds_count(struct pipeline_type *ptype) -{ - cmdline_parse_ctx_t *cmds; - uint32_t n_cmds; +struct table_lpm_params { + uint32_t n_rules; + uint32_t key_offset; + uint32_t key_size; +}; - if (ptype->fe_ops == NULL) - return 0; +struct table_params { + /* Match */ + enum table_type match_type; + union { + struct table_acl_params acl; + struct table_array_params array; + struct table_hash_params hash; + struct table_lpm_params lpm; + } match; - cmds = ptype->fe_ops->cmds; - if (cmds == NULL) - return 0; + /* Action */ + const char *action_profile_name; +}; - for (n_cmds = 0; cmds[n_cmds]; n_cmds++); +struct port_in { + struct port_in_params params; + struct port_in_action_profile *ap; + struct rte_port_in_action *a; +}; - return n_cmds; -} +struct table { + struct table_params params; + struct table_action_profile *ap; + struct rte_table_action *a; +}; + +struct pipeline { + TAILQ_ENTRY(pipeline) node; + char name[NAME_SIZE]; + + struct rte_pipeline *p; + struct port_in port_in[RTE_PIPELINE_PORT_IN_MAX]; + struct table table[RTE_PIPELINE_TABLE_MAX]; + uint32_t n_ports_in; + uint32_t n_ports_out; + uint32_t n_tables; + + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + uint32_t timer_period_ms; + + int enabled; + uint32_t thread_id; + uint32_t cpu_id; +}; + +TAILQ_HEAD(pipeline_list, pipeline); + +int +pipeline_init(void); + +struct pipeline * +pipeline_find(const char *name); + +struct pipeline * +pipeline_create(const char *name, struct pipeline_params *params); + +int +pipeline_port_in_create(const char *pipeline_name, + struct port_in_params *params, + int enabled); + +int +pipeline_port_in_connect_to_table(const char *pipeline_name, + uint32_t port_id, + uint32_t table_id); + +int +pipeline_port_out_create(const char *pipeline_name, + struct port_out_params *params); int -parse_pipeline_core(uint32_t *socket, - uint32_t *core, - uint32_t *ht, - const char *entry); +pipeline_table_create(const char *pipeline_name, + struct table_params *params); +struct table_rule_match_acl { + int ip_version; + + RTE_STD_C11 + union { + struct { + uint32_t sa; + uint32_t da; + } ipv4; + + struct { + uint8_t sa[16]; + uint8_t da[16]; + } ipv6; + }; + + uint32_t sa_depth; + uint32_t da_depth; + uint16_t sp0; + uint16_t sp1; + uint16_t dp0; + uint16_t dp1; + uint8_t proto; + uint8_t proto_mask; + uint32_t priority; +}; + +struct table_rule_match_array { + uint32_t pos; +}; + +#ifndef TABLE_RULE_MATCH_SIZE_MAX +#define TABLE_RULE_MATCH_SIZE_MAX 256 #endif + +#ifndef TABLE_RULE_ACTION_SIZE_MAX +#define TABLE_RULE_ACTION_SIZE_MAX 2048 +#endif + +struct table_rule_match_hash { + uint8_t key[TABLE_RULE_MATCH_SIZE_MAX]; +}; + +struct table_rule_match_lpm { + int ip_version; + + RTE_STD_C11 + union { + uint32_t ipv4; + uint8_t ipv6[16]; + }; + + uint8_t depth; +}; + +struct table_rule_match { + enum table_type match_type; + + union { + struct table_rule_match_acl acl; + struct table_rule_match_array array; + struct table_rule_match_hash hash; + struct table_rule_match_lpm lpm; + } match; +}; + +struct table_rule_action { + uint64_t action_mask; + struct rte_table_action_fwd_params fwd; + struct rte_table_action_lb_params lb; + struct rte_table_action_mtr_params mtr; + struct rte_table_action_tm_params tm; + struct rte_table_action_encap_params encap; + struct rte_table_action_nat_params nat; + struct rte_table_action_ttl_params ttl; + struct rte_table_action_stats_params stats; + struct rte_table_action_time_params time; +}; + +int +pipeline_port_in_stats_read(const char *pipeline_name, + uint32_t port_id, + struct rte_pipeline_port_in_stats *stats, + int clear); + +int +pipeline_port_in_enable(const char *pipeline_name, + uint32_t port_id); + +int +pipeline_port_in_disable(const char *pipeline_name, + uint32_t port_id); + +int +pipeline_port_out_stats_read(const char *pipeline_name, + uint32_t port_id, + struct rte_pipeline_port_out_stats *stats, + int clear); + +int +pipeline_table_stats_read(const char *pipeline_name, + uint32_t table_id, + struct rte_pipeline_table_stats *stats, + int clear); + +int +pipeline_table_rule_add(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match, + struct table_rule_action *action, + void **data); + +int +pipeline_table_rule_add_bulk(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match, + struct table_rule_action *action, + void **data, + uint32_t *n_rules); + +int +pipeline_table_rule_add_default(const char *pipeline_name, + uint32_t table_id, + struct table_rule_action *action, + void **data); + +int +pipeline_table_rule_delete(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match); + +int +pipeline_table_rule_delete_default(const char *pipeline_name, + uint32_t table_id); + +int +pipeline_table_rule_stats_read(const char *pipeline_name, + uint32_t table_id, + void *data, + struct rte_table_action_stats_counters *stats, + int clear); + +int +pipeline_table_mtr_profile_add(const char *pipeline_name, + uint32_t table_id, + uint32_t meter_profile_id, + struct rte_table_action_meter_profile *profile); + +int +pipeline_table_mtr_profile_delete(const char *pipeline_name, + uint32_t table_id, + uint32_t meter_profile_id); + +int +pipeline_table_rule_mtr_read(const char *pipeline_name, + uint32_t table_id, + void *data, + uint32_t tc_mask, + struct rte_table_action_mtr_counters *stats, + int clear); + +int +pipeline_table_dscp_table_update(const char *pipeline_name, + uint32_t table_id, + uint64_t dscp_mask, + struct rte_table_action_dscp_table *dscp_table); + +int +pipeline_table_rule_ttl_read(const char *pipeline_name, + uint32_t table_id, + void *data, + struct rte_table_action_ttl_counters *stats, + int clear); + +#endif /* _INCLUDE_PIPELINE_H_ */ diff --git a/examples/ip_pipeline/pipeline/pipeline_actions_common.h b/examples/ip_pipeline/pipeline/pipeline_actions_common.h deleted file mode 100644 index 23f88367..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_actions_common.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ -#ifndef __INCLUDE_PIPELINE_ACTIONS_COMMON_H__ -#define __INCLUDE_PIPELINE_ACTIONS_COMMON_H__ - -#include <stdint.h> - -#include <rte_common.h> -#include <rte_cycles.h> -#include <rte_mbuf.h> -#include <rte_pipeline.h> - -#define PIPELINE_PORT_IN_AH(f_ah, f_pkt_work, f_pkt4_work) \ -static int \ -f_ah( \ - __rte_unused struct rte_pipeline *p, \ - struct rte_mbuf **pkts, \ - uint32_t n_pkts, \ - void *arg) \ -{ \ - uint32_t i; \ - \ - for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) \ - f_pkt4_work(&pkts[i], arg); \ - \ - for ( ; i < n_pkts; i++) \ - f_pkt_work(pkts[i], arg); \ - \ - return 0; \ -} - -#define PIPELINE_PORT_IN_AH_HIJACK_ALL(f_ah, f_pkt_work, f_pkt4_work) \ -static int \ -f_ah( \ - struct rte_pipeline *p, \ - struct rte_mbuf **pkts, \ - uint32_t n_pkts, \ - void *arg) \ -{ \ - uint64_t pkt_mask = RTE_LEN2MASK(n_pkts, uint64_t); \ - uint32_t i; \ - \ - rte_pipeline_ah_packet_hijack(p, pkt_mask); \ - \ - for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) \ - f_pkt4_work(&pkts[i], arg); \ - \ - for ( ; i < n_pkts; i++) \ - f_pkt_work(pkts[i], arg); \ - \ - return 0; \ -} - -#define PIPELINE_TABLE_AH_HIT(f_ah, f_pkt_work, f_pkt4_work) \ -static int \ -f_ah( \ - __rte_unused struct rte_pipeline *p, \ - struct rte_mbuf **pkts, \ - uint64_t pkts_in_mask, \ - struct rte_pipeline_table_entry **entries, \ - void *arg) \ -{ \ - if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \ - uint64_t n_pkts = __builtin_popcountll(pkts_in_mask); \ - uint32_t i; \ - \ - for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) \ - f_pkt4_work(&pkts[i], &entries[i], arg); \ - \ - for ( ; i < n_pkts; i++) \ - f_pkt_work(pkts[i], entries[i], arg); \ - } else \ - for ( ; pkts_in_mask; ) { \ - uint32_t pos = __builtin_ctzll(pkts_in_mask); \ - uint64_t pkt_mask = 1LLU << pos; \ - \ - pkts_in_mask &= ~pkt_mask; \ - f_pkt_work(pkts[pos], entries[pos], arg); \ - } \ - \ - return 0; \ -} - -#define PIPELINE_TABLE_AH_MISS(f_ah, f_pkt_work, f_pkt4_work) \ -static int \ -f_ah( \ - __rte_unused struct rte_pipeline *p, \ - struct rte_mbuf **pkts, \ - uint64_t pkts_in_mask, \ - struct rte_pipeline_table_entry *entry, \ - void *arg) \ -{ \ - if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \ - uint64_t n_pkts = __builtin_popcountll(pkts_in_mask); \ - uint32_t i; \ - \ - for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) \ - f_pkt4_work(&pkts[i], entry, arg); \ - \ - for ( ; i < n_pkts; i++) \ - f_pkt_work(pkts[i], entry, arg); \ - } else \ - for ( ; pkts_in_mask; ) { \ - uint32_t pos = __builtin_ctzll(pkts_in_mask); \ - uint64_t pkt_mask = 1LLU << pos; \ - \ - pkts_in_mask &= ~pkt_mask; \ - f_pkt_work(pkts[pos], entry, arg); \ - } \ - \ - return 0; \ -} - -#define PIPELINE_TABLE_AH_HIT_DROP_TIME(f_ah, f_pkt_work, f_pkt4_work) \ -static int \ -f_ah( \ - struct rte_pipeline *p, \ - struct rte_mbuf **pkts, \ - uint64_t pkts_mask, \ - struct rte_pipeline_table_entry **entries, \ - void *arg) \ -{ \ - uint64_t pkts_in_mask = pkts_mask; \ - uint64_t pkts_out_mask = pkts_mask; \ - uint64_t time = rte_rdtsc(); \ - \ - if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \ - uint64_t n_pkts = __builtin_popcountll(pkts_in_mask); \ - uint32_t i; \ - \ - for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) { \ - uint64_t mask = f_pkt4_work(&pkts[i], \ - &entries[i], arg, time); \ - pkts_out_mask ^= mask << i; \ - } \ - \ - for ( ; i < n_pkts; i++) { \ - uint64_t mask = f_pkt_work(pkts[i], \ - entries[i], arg, time); \ - pkts_out_mask ^= mask << i; \ - } \ - } else \ - for ( ; pkts_in_mask; ) { \ - uint32_t pos = __builtin_ctzll(pkts_in_mask); \ - uint64_t pkt_mask = 1LLU << pos; \ - uint64_t mask = f_pkt_work(pkts[pos], \ - entries[pos], arg, time); \ - \ - pkts_in_mask &= ~pkt_mask; \ - pkts_out_mask ^= mask << pos; \ - } \ - \ - rte_pipeline_ah_packet_drop(p, pkts_out_mask ^ pkts_mask); \ - \ - return 0; \ -} - -#define PIPELINE_TABLE_AH_MISS_DROP_TIME(f_ah, f_pkt_work, f_pkt4_work) \ -static int \ -f_ah( \ - struct rte_pipeline *p, \ - struct rte_mbuf **pkts, \ - uint64_t pkts_mask, \ - struct rte_pipeline_table_entry *entry, \ - void *arg) \ -{ \ - uint64_t pkts_in_mask = pkts_mask; \ - uint64_t pkts_out_mask = pkts_mask; \ - uint64_t time = rte_rdtsc(); \ - \ - if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \ - uint64_t n_pkts = __builtin_popcountll(pkts_in_mask); \ - uint32_t i; \ - \ - for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) { \ - uint64_t mask = f_pkt4_work(&pkts[i], \ - entry, arg, time); \ - pkts_out_mask ^= mask << i; \ - } \ - \ - for ( ; i < n_pkts; i++) { \ - uint64_t mask = f_pkt_work(pkts[i], entry, arg, time);\ - pkts_out_mask ^= mask << i; \ - } \ - } else \ - for ( ; pkts_in_mask; ) { \ - uint32_t pos = __builtin_ctzll(pkts_in_mask); \ - uint64_t pkt_mask = 1LLU << pos; \ - uint64_t mask = f_pkt_work(pkts[pos], \ - entry, arg, time); \ - \ - pkts_in_mask &= ~pkt_mask; \ - pkts_out_mask ^= mask << pos; \ - } \ - \ - rte_pipeline_ah_packet_drop(p, pkts_out_mask ^ pkts_mask); \ - \ - return 0; \ -} - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_common_be.c b/examples/ip_pipeline/pipeline/pipeline_common_be.c deleted file mode 100644 index 5d84989a..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_common_be.c +++ /dev/null @@ -1,176 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#include <rte_common.h> -#include <rte_malloc.h> - -#include "pipeline_common_be.h" - -void * -pipeline_msg_req_ping_handler(__rte_unused struct pipeline *p, - void *msg) -{ - struct pipeline_msg_rsp *rsp = msg; - - rsp->status = 0; /* OK */ - - return rsp; -} - -void * -pipeline_msg_req_stats_port_in_handler(struct pipeline *p, - void *msg) -{ - struct pipeline_stats_msg_req *req = msg; - struct pipeline_stats_port_in_msg_rsp *rsp = msg; - uint32_t port_id; - - /* Check request */ - if (req->id >= p->n_ports_in) { - rsp->status = -1; - return rsp; - } - port_id = p->port_in_id[req->id]; - - /* Process request */ - rsp->status = rte_pipeline_port_in_stats_read(p->p, - port_id, - &rsp->stats, - 1); - - return rsp; -} - -void * -pipeline_msg_req_stats_port_out_handler(struct pipeline *p, - void *msg) -{ - struct pipeline_stats_msg_req *req = msg; - struct pipeline_stats_port_out_msg_rsp *rsp = msg; - uint32_t port_id; - - /* Check request */ - if (req->id >= p->n_ports_out) { - rsp->status = -1; - return rsp; - } - port_id = p->port_out_id[req->id]; - - /* Process request */ - rsp->status = rte_pipeline_port_out_stats_read(p->p, - port_id, - &rsp->stats, - 1); - - return rsp; -} - -void * -pipeline_msg_req_stats_table_handler(struct pipeline *p, - void *msg) -{ - struct pipeline_stats_msg_req *req = msg; - struct pipeline_stats_table_msg_rsp *rsp = msg; - uint32_t table_id; - - /* Check request */ - if (req->id >= p->n_tables) { - rsp->status = -1; - return rsp; - } - table_id = p->table_id[req->id]; - - /* Process request */ - rsp->status = rte_pipeline_table_stats_read(p->p, - table_id, - &rsp->stats, - 1); - - return rsp; -} - -void * -pipeline_msg_req_port_in_enable_handler(struct pipeline *p, - void *msg) -{ - struct pipeline_port_in_msg_req *req = msg; - struct pipeline_msg_rsp *rsp = msg; - uint32_t port_id; - - /* Check request */ - if (req->port_id >= p->n_ports_in) { - rsp->status = -1; - return rsp; - } - port_id = p->port_in_id[req->port_id]; - - /* Process request */ - rsp->status = rte_pipeline_port_in_enable(p->p, - port_id); - - return rsp; -} - -void * -pipeline_msg_req_port_in_disable_handler(struct pipeline *p, - void *msg) -{ - struct pipeline_port_in_msg_req *req = msg; - struct pipeline_msg_rsp *rsp = msg; - uint32_t port_id; - - /* Check request */ - if (req->port_id >= p->n_ports_in) { - rsp->status = -1; - return rsp; - } - port_id = p->port_in_id[req->port_id]; - - /* Process request */ - rsp->status = rte_pipeline_port_in_disable(p->p, - port_id); - - return rsp; -} - -void * -pipeline_msg_req_invalid_handler(__rte_unused struct pipeline *p, - void *msg) -{ - struct pipeline_msg_rsp *rsp = msg; - - rsp->status = -1; /* Error */ - - return rsp; -} - -int -pipeline_msg_req_handle(struct pipeline *p) -{ - uint32_t msgq_id; - - for (msgq_id = 0; msgq_id < p->n_msgq; msgq_id++) { - for ( ; ; ) { - struct pipeline_msg_req *req; - pipeline_msg_req_handler f_handle; - - req = pipeline_msg_recv(p, msgq_id); - if (req == NULL) - break; - - f_handle = (req->type < PIPELINE_MSG_REQS) ? - p->handlers[req->type] : - pipeline_msg_req_invalid_handler; - - if (f_handle == NULL) - f_handle = pipeline_msg_req_invalid_handler; - - pipeline_msg_send(p, - msgq_id, - f_handle(p, (void *) req)); - } - } - - return 0; -} diff --git a/examples/ip_pipeline/pipeline/pipeline_common_be.h b/examples/ip_pipeline/pipeline/pipeline_common_be.h deleted file mode 100644 index 83bd04e6..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_common_be.h +++ /dev/null @@ -1,134 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_COMMON_BE_H__ -#define __INCLUDE_PIPELINE_COMMON_BE_H__ - -#include <rte_common.h> -#include <rte_ring.h> -#include <rte_pipeline.h> - -#include "pipeline_be.h" - -struct pipeline; - -enum pipeline_msg_req_type { - PIPELINE_MSG_REQ_PING = 0, - PIPELINE_MSG_REQ_STATS_PORT_IN, - PIPELINE_MSG_REQ_STATS_PORT_OUT, - PIPELINE_MSG_REQ_STATS_TABLE, - PIPELINE_MSG_REQ_PORT_IN_ENABLE, - PIPELINE_MSG_REQ_PORT_IN_DISABLE, - PIPELINE_MSG_REQ_CUSTOM, - PIPELINE_MSG_REQS -}; - -typedef void *(*pipeline_msg_req_handler)(struct pipeline *p, void *msg); - -struct pipeline { - struct rte_pipeline *p; - uint32_t port_in_id[PIPELINE_MAX_PORT_IN]; - uint32_t port_out_id[PIPELINE_MAX_PORT_OUT]; - uint32_t table_id[PIPELINE_MAX_TABLES]; - struct rte_ring *msgq_in[PIPELINE_MAX_MSGQ_IN]; - struct rte_ring *msgq_out[PIPELINE_MAX_MSGQ_OUT]; - - uint32_t n_ports_in; - uint32_t n_ports_out; - uint32_t n_tables; - uint32_t n_msgq; - - pipeline_msg_req_handler handlers[PIPELINE_MSG_REQS]; - char name[PIPELINE_NAME_SIZE]; - uint32_t log_level; -}; - -enum pipeline_log_level { - PIPELINE_LOG_LEVEL_HIGH = 1, - PIPELINE_LOG_LEVEL_LOW, - PIPELINE_LOG_LEVELS -}; - -#define PLOG(p, level, fmt, ...) \ -do { \ - if (p->log_level >= PIPELINE_LOG_LEVEL_ ## level) \ - fprintf(stdout, "[%s] " fmt "\n", p->name, ## __VA_ARGS__);\ -} while (0) - -static inline void * -pipeline_msg_recv(struct pipeline *p, - uint32_t msgq_id) -{ - struct rte_ring *r = p->msgq_in[msgq_id]; - void *msg; - int status = rte_ring_sc_dequeue(r, &msg); - - if (status != 0) - return NULL; - - return msg; -} - -static inline void -pipeline_msg_send(struct pipeline *p, - uint32_t msgq_id, - void *msg) -{ - struct rte_ring *r = p->msgq_out[msgq_id]; - int status; - - do { - status = rte_ring_sp_enqueue(r, msg); - } while (status == -ENOBUFS); -} - -struct pipeline_msg_req { - enum pipeline_msg_req_type type; -}; - -struct pipeline_stats_msg_req { - enum pipeline_msg_req_type type; - uint32_t id; -}; - -struct pipeline_port_in_msg_req { - enum pipeline_msg_req_type type; - uint32_t port_id; -}; - -struct pipeline_custom_msg_req { - enum pipeline_msg_req_type type; - uint32_t subtype; -}; - -struct pipeline_msg_rsp { - int status; -}; - -struct pipeline_stats_port_in_msg_rsp { - int status; - struct rte_pipeline_port_in_stats stats; -}; - -struct pipeline_stats_port_out_msg_rsp { - int status; - struct rte_pipeline_port_out_stats stats; -}; - -struct pipeline_stats_table_msg_rsp { - int status; - struct rte_pipeline_table_stats stats; -}; - -void *pipeline_msg_req_ping_handler(struct pipeline *p, void *msg); -void *pipeline_msg_req_stats_port_in_handler(struct pipeline *p, void *msg); -void *pipeline_msg_req_stats_port_out_handler(struct pipeline *p, void *msg); -void *pipeline_msg_req_stats_table_handler(struct pipeline *p, void *msg); -void *pipeline_msg_req_port_in_enable_handler(struct pipeline *p, void *msg); -void *pipeline_msg_req_port_in_disable_handler(struct pipeline *p, void *msg); -void *pipeline_msg_req_invalid_handler(struct pipeline *p, void *msg); - -int pipeline_msg_req_handle(struct pipeline *p); - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c deleted file mode 100644 index cc5214c7..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c +++ /dev/null @@ -1,1455 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> - -#include <rte_common.h> -#include <rte_malloc.h> -#include <cmdline_rdline.h> -#include <cmdline_parse.h> -#include <cmdline_parse_num.h> -#include <cmdline_parse_string.h> -#include <cmdline.h> - -#include "pipeline_common_fe.h" -#include "parser.h" - -struct app_link_params * -app_pipeline_track_pktq_out_to_link(struct app_params *app, - uint32_t pipeline_id, - uint32_t pktq_out_id) -{ - struct app_pipeline_params *p; - - /* Check input arguments */ - if (app == NULL) - return NULL; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); - if (p == NULL) - return NULL; - - for ( ; ; ) { - struct app_pktq_out_params *pktq_out = - &p->pktq_out[pktq_out_id]; - - switch (pktq_out->type) { - case APP_PKTQ_OUT_HWQ: - { - struct app_pktq_hwq_out_params *hwq_out; - - hwq_out = &app->hwq_out_params[pktq_out->id]; - - return app_get_link_for_txq(app, hwq_out); - } - - case APP_PKTQ_OUT_SWQ: - { - struct pipeline_params pp; - struct pipeline_type *ptype; - struct app_pktq_swq_params *swq; - uint32_t pktq_in_id; - int status; - - swq = &app->swq_params[pktq_out->id]; - p = app_swq_get_reader(app, swq, &pktq_in_id); - if (p == NULL) - return NULL; - - ptype = app_pipeline_type_find(app, p->type); - if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL)) - return NULL; - - app_pipeline_params_get(app, p, &pp); - status = ptype->fe_ops->f_track(&pp, - pktq_in_id, - &pktq_out_id); - if (status) - return NULL; - - break; - } - - case APP_PKTQ_OUT_TM: - { - struct pipeline_params pp; - struct pipeline_type *ptype; - struct app_pktq_tm_params *tm; - uint32_t pktq_in_id; - int status; - - tm = &app->tm_params[pktq_out->id]; - p = app_tm_get_reader(app, tm, &pktq_in_id); - if (p == NULL) - return NULL; - - ptype = app_pipeline_type_find(app, p->type); - if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL)) - return NULL; - - app_pipeline_params_get(app, p, &pp); - status = ptype->fe_ops->f_track(&pp, - pktq_in_id, - &pktq_out_id); - if (status) - return NULL; - - break; - } - - case APP_PKTQ_OUT_KNI: - { - struct pipeline_params pp; - struct pipeline_type *ptype; - struct app_pktq_kni_params *kni; - uint32_t pktq_in_id; - int status; - - kni = &app->kni_params[pktq_out->id]; - p = app_kni_get_reader(app, kni, &pktq_in_id); - if (p == NULL) - return NULL; - - ptype = app_pipeline_type_find(app, p->type); - if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL)) - return NULL; - - app_pipeline_params_get(app, p, &pp); - status = ptype->fe_ops->f_track(&pp, - pktq_in_id, - &pktq_out_id); - if (status) - return NULL; - - break; - } - - case APP_PKTQ_OUT_TAP: - case APP_PKTQ_OUT_SINK: - default: - return NULL; - } - } -} - -int -app_pipeline_track_default(struct pipeline_params *p, - uint32_t port_in, - uint32_t *port_out) -{ - /* Check input arguments */ - if ((p == NULL) || - (port_in >= p->n_ports_in) || - (port_out == NULL)) - return -1; - - if (p->n_ports_out == 1) { - *port_out = 0; - return 0; - } - - return -1; -} - -int -app_pipeline_ping(struct app_params *app, - uint32_t pipeline_id) -{ - struct app_pipeline_params *p; - struct pipeline_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status = 0; - - /* Check input arguments */ - if (app == NULL) - return -1; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); - if (p == NULL) - return -1; - - /* Message buffer allocation */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - /* Fill in request */ - req->type = PIPELINE_MSG_REQ_PING; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Check response */ - status = rsp->status; - - /* Message buffer free */ - app_msg_free(app, rsp); - - return status; -} - -int -app_pipeline_stats_port_in(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id, - struct rte_pipeline_port_in_stats *stats) -{ - struct app_pipeline_params *p; - struct pipeline_stats_msg_req *req; - struct pipeline_stats_port_in_msg_rsp *rsp; - int status = 0; - - /* Check input arguments */ - if ((app == NULL) || - (stats == NULL)) - return -1; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); - if ((p == NULL) || - (port_id >= p->n_pktq_in)) - return -1; - - /* Message buffer allocation */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - /* Fill in request */ - req->type = PIPELINE_MSG_REQ_STATS_PORT_IN; - req->id = port_id; - - /* Send request and wait for response */ - rsp = (struct pipeline_stats_port_in_msg_rsp *) - app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Check response */ - status = rsp->status; - if (status == 0) - memcpy(stats, &rsp->stats, sizeof(rsp->stats)); - - /* Message buffer free */ - app_msg_free(app, rsp); - - return status; -} - -int -app_pipeline_stats_port_out(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id, - struct rte_pipeline_port_out_stats *stats) -{ - struct app_pipeline_params *p; - struct pipeline_stats_msg_req *req; - struct pipeline_stats_port_out_msg_rsp *rsp; - int status = 0; - - /* Check input arguments */ - if ((app == NULL) || - (pipeline_id >= app->n_pipelines) || - (stats == NULL)) - return -1; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); - if ((p == NULL) || - (port_id >= p->n_pktq_out)) - return -1; - - /* Message buffer allocation */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - /* Fill in request */ - req->type = PIPELINE_MSG_REQ_STATS_PORT_OUT; - req->id = port_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Check response */ - status = rsp->status; - if (status == 0) - memcpy(stats, &rsp->stats, sizeof(rsp->stats)); - - /* Message buffer free */ - app_msg_free(app, rsp); - - return status; -} - -int -app_pipeline_stats_table(struct app_params *app, - uint32_t pipeline_id, - uint32_t table_id, - struct rte_pipeline_table_stats *stats) -{ - struct app_pipeline_params *p; - struct pipeline_stats_msg_req *req; - struct pipeline_stats_table_msg_rsp *rsp; - int status = 0; - - /* Check input arguments */ - if ((app == NULL) || - (stats == NULL)) - return -1; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); - if (p == NULL) - return -1; - - /* Message buffer allocation */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - /* Fill in request */ - req->type = PIPELINE_MSG_REQ_STATS_TABLE; - req->id = table_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Check response */ - status = rsp->status; - if (status == 0) - memcpy(stats, &rsp->stats, sizeof(rsp->stats)); - - /* Message buffer free */ - app_msg_free(app, rsp); - - return status; -} - -int -app_pipeline_port_in_enable(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id) -{ - struct app_pipeline_params *p; - struct pipeline_port_in_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status = 0; - - /* Check input arguments */ - if (app == NULL) - return -1; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); - if ((p == NULL) || - (port_id >= p->n_pktq_in)) - return -1; - - /* Message buffer allocation */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - /* Fill in request */ - req->type = PIPELINE_MSG_REQ_PORT_IN_ENABLE; - req->port_id = port_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Check response */ - status = rsp->status; - - /* Message buffer free */ - app_msg_free(app, rsp); - - return status; -} - -int -app_pipeline_port_in_disable(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id) -{ - struct app_pipeline_params *p; - struct pipeline_port_in_msg_req *req; - struct pipeline_msg_rsp *rsp; - int status = 0; - - /* Check input arguments */ - if (app == NULL) - return -1; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); - if ((p == NULL) || - (port_id >= p->n_pktq_in)) - return -1; - - /* Message buffer allocation */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - /* Fill in request */ - req->type = PIPELINE_MSG_REQ_PORT_IN_DISABLE; - req->port_id = port_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Check response */ - status = rsp->status; - - /* Message buffer free */ - app_msg_free(app, rsp); - - return status; -} - -int -app_link_set_op(struct app_params *app, - uint32_t link_id, - uint32_t pipeline_id, - app_link_op op, - void *arg) -{ - struct app_pipeline_params *pp; - struct app_link_params *lp; - struct app_link_data *ld; - uint32_t ppos, lpos; - - /* Check input arguments */ - if ((app == NULL) || - (op == NULL)) - return -1; - - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, lp); - if (lp == NULL) - return -1; - lpos = lp - app->link_params; - ld = &app->link_data[lpos]; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, pp); - if (pp == NULL) - return -1; - ppos = pp - app->pipeline_params; - - ld->f_link[ppos] = op; - ld->arg[ppos] = arg; - - return 0; -} - -int -app_link_config(struct app_params *app, - uint32_t link_id, - uint32_t ip, - uint32_t depth) -{ - struct app_link_params *p; - uint32_t i, netmask, host, bcast; - - /* Check input arguments */ - if (app == NULL) - return -1; - - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); - if (p == NULL) { - APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link", - link_id); - return -1; - } - - if (p->state) { - APP_LOG(app, HIGH, "%s is UP, please bring it DOWN first", - p->name); - return -1; - } - - netmask = (~0U) << (32 - depth); - host = ip & netmask; - bcast = host | (~netmask); - - if ((ip == 0) || - (ip == UINT32_MAX) || - (ip == host) || - (ip == bcast)) { - APP_LOG(app, HIGH, "Illegal IP address"); - return -1; - } - - for (i = 0; i < app->n_links; i++) { - struct app_link_params *link = &app->link_params[i]; - - if (strcmp(p->name, link->name) == 0) - continue; - - if (link->ip == ip) { - APP_LOG(app, HIGH, - "%s is already assigned this IP address", - link->name); - return -1; - } - } - - if ((depth == 0) || (depth > 32)) { - APP_LOG(app, HIGH, "Illegal value for depth parameter " - "(%" PRIu32 ")", - depth); - return -1; - } - - /* Save link parameters */ - p->ip = ip; - p->depth = depth; - - return 0; -} - -int -app_link_up(struct app_params *app, - uint32_t link_id) -{ - struct app_link_params *p; - struct app_link_data *d; - int i; - - /* Check input arguments */ - if (app == NULL) - return -1; - - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); - if (p == NULL) { - APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link", - link_id); - return -1; - } - - d = &app->link_data[p - app->link_params]; - - /* Check link state */ - if (p->state) { - APP_LOG(app, HIGH, "%s is already UP", p->name); - return 0; - } - - /* Check that IP address is valid */ - if (p->ip == 0) { - APP_LOG(app, HIGH, "%s IP address is not set", p->name); - return 0; - } - - app_link_up_internal(app, p); - - /* Callbacks */ - for (i = 0; i < APP_MAX_PIPELINES; i++) - if (d->f_link[i]) - d->f_link[i](app, link_id, 1, d->arg[i]); - - return 0; -} - -int -app_link_down(struct app_params *app, - uint32_t link_id) -{ - struct app_link_params *p; - struct app_link_data *d; - uint32_t i; - - /* Check input arguments */ - if (app == NULL) - return -1; - - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); - if (p == NULL) { - APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link", - link_id); - return -1; - } - - d = &app->link_data[p - app->link_params]; - - /* Check link state */ - if (p->state == 0) { - APP_LOG(app, HIGH, "%s is already DOWN", p->name); - return 0; - } - - app_link_down_internal(app, p); - - /* Callbacks */ - for (i = 0; i < APP_MAX_PIPELINES; i++) - if (d->f_link[i]) - d->f_link[i](app, link_id, 0, d->arg[i]); - - return 0; -} - -/* - * ping - */ - -struct cmd_ping_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t ping_string; -}; - -static void -cmd_ping_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_ping_result *params = parsed_result; - struct app_params *app = data; - int status; - - status = app_pipeline_ping(app, params->pipeline_id); - if (status != 0) - printf("Command failed\n"); -} - -static cmdline_parse_token_string_t cmd_ping_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_ping_result, p_string, "p"); - -static cmdline_parse_token_num_t cmd_ping_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_ping_result, pipeline_id, UINT32); - -static cmdline_parse_token_string_t cmd_ping_ping_string = - TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping_string, "ping"); - -static cmdline_parse_inst_t cmd_ping = { - .f = cmd_ping_parsed, - .data = NULL, - .help_str = "Pipeline ping", - .tokens = { - (void *) &cmd_ping_p_string, - (void *) &cmd_ping_pipeline_id, - (void *) &cmd_ping_ping_string, - NULL, - }, -}; - -/* - * stats port in - */ - -struct cmd_stats_port_in_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t stats_string; - cmdline_fixed_string_t port_string; - cmdline_fixed_string_t in_string; - uint32_t port_in_id; - -}; - -static void -cmd_stats_port_in_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_stats_port_in_result *params = parsed_result; - struct app_params *app = data; - struct rte_pipeline_port_in_stats stats; - int status; - - status = app_pipeline_stats_port_in(app, - params->pipeline_id, - params->port_in_id, - &stats); - - if (status != 0) { - printf("Command failed\n"); - return; - } - - /* Display stats */ - printf("Pipeline %" PRIu32 " - stats for input port %" PRIu32 ":\n" - "\tPkts in: %" PRIu64 "\n" - "\tPkts dropped by AH: %" PRIu64 "\n" - "\tPkts dropped by other: %" PRIu64 "\n", - params->pipeline_id, - params->port_in_id, - stats.stats.n_pkts_in, - stats.n_pkts_dropped_by_ah, - stats.stats.n_pkts_drop); -} - -static cmdline_parse_token_string_t cmd_stats_port_in_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_stats_port_in_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, pipeline_id, - UINT32); - -static cmdline_parse_token_string_t cmd_stats_port_in_stats_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, stats_string, - "stats"); - -static cmdline_parse_token_string_t cmd_stats_port_in_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, port_string, - "port"); - -static cmdline_parse_token_string_t cmd_stats_port_in_in_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, in_string, - "in"); - - cmdline_parse_token_num_t cmd_stats_port_in_port_in_id = - TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, port_in_id, - UINT32); - -static cmdline_parse_inst_t cmd_stats_port_in = { - .f = cmd_stats_port_in_parsed, - .data = NULL, - .help_str = "Pipeline input port stats", - .tokens = { - (void *) &cmd_stats_port_in_p_string, - (void *) &cmd_stats_port_in_pipeline_id, - (void *) &cmd_stats_port_in_stats_string, - (void *) &cmd_stats_port_in_port_string, - (void *) &cmd_stats_port_in_in_string, - (void *) &cmd_stats_port_in_port_in_id, - NULL, - }, -}; - -/* - * stats port out - */ - -struct cmd_stats_port_out_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t stats_string; - cmdline_fixed_string_t port_string; - cmdline_fixed_string_t out_string; - uint32_t port_out_id; -}; - -static void -cmd_stats_port_out_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - - struct cmd_stats_port_out_result *params = parsed_result; - struct app_params *app = data; - struct rte_pipeline_port_out_stats stats; - int status; - - status = app_pipeline_stats_port_out(app, - params->pipeline_id, - params->port_out_id, - &stats); - - if (status != 0) { - printf("Command failed\n"); - return; - } - - /* Display stats */ - printf("Pipeline %" PRIu32 " - stats for output port %" PRIu32 ":\n" - "\tPkts in: %" PRIu64 "\n" - "\tPkts dropped by AH: %" PRIu64 "\n" - "\tPkts dropped by other: %" PRIu64 "\n", - params->pipeline_id, - params->port_out_id, - stats.stats.n_pkts_in, - stats.n_pkts_dropped_by_ah, - stats.stats.n_pkts_drop); -} - -static cmdline_parse_token_string_t cmd_stats_port_out_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_stats_port_out_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, pipeline_id, - UINT32); - -static cmdline_parse_token_string_t cmd_stats_port_out_stats_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, stats_string, - "stats"); - -static cmdline_parse_token_string_t cmd_stats_port_out_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, port_string, - "port"); - -static cmdline_parse_token_string_t cmd_stats_port_out_out_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, out_string, - "out"); - -static cmdline_parse_token_num_t cmd_stats_port_out_port_out_id = - TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, port_out_id, - UINT32); - -static cmdline_parse_inst_t cmd_stats_port_out = { - .f = cmd_stats_port_out_parsed, - .data = NULL, - .help_str = "Pipeline output port stats", - .tokens = { - (void *) &cmd_stats_port_out_p_string, - (void *) &cmd_stats_port_out_pipeline_id, - (void *) &cmd_stats_port_out_stats_string, - (void *) &cmd_stats_port_out_port_string, - (void *) &cmd_stats_port_out_out_string, - (void *) &cmd_stats_port_out_port_out_id, - NULL, - }, -}; - -/* - * stats table - */ - -struct cmd_stats_table_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t stats_string; - cmdline_fixed_string_t table_string; - uint32_t table_id; -}; - -static void -cmd_stats_table_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_stats_table_result *params = parsed_result; - struct app_params *app = data; - struct rte_pipeline_table_stats stats; - int status; - - status = app_pipeline_stats_table(app, - params->pipeline_id, - params->table_id, - &stats); - - if (status != 0) { - printf("Command failed\n"); - return; - } - - /* Display stats */ - printf("Pipeline %" PRIu32 " - stats for table %" PRIu32 ":\n" - "\tPkts in: %" PRIu64 "\n" - "\tPkts in with lookup miss: %" PRIu64 "\n" - "\tPkts in with lookup hit dropped by AH: %" PRIu64 "\n" - "\tPkts in with lookup hit dropped by others: %" PRIu64 "\n" - "\tPkts in with lookup miss dropped by AH: %" PRIu64 "\n" - "\tPkts in with lookup miss dropped by others: %" PRIu64 "\n", - params->pipeline_id, - params->table_id, - 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); -} - -static cmdline_parse_token_string_t cmd_stats_table_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_stats_table_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, pipeline_id, - UINT32); - -static cmdline_parse_token_string_t cmd_stats_table_stats_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, stats_string, - "stats"); - -static cmdline_parse_token_string_t cmd_stats_table_table_string = - TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, table_string, - "table"); - -static cmdline_parse_token_num_t cmd_stats_table_table_id = - TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, table_id, UINT32); - -static cmdline_parse_inst_t cmd_stats_table = { - .f = cmd_stats_table_parsed, - .data = NULL, - .help_str = "Pipeline table stats", - .tokens = { - (void *) &cmd_stats_table_p_string, - (void *) &cmd_stats_table_pipeline_id, - (void *) &cmd_stats_table_stats_string, - (void *) &cmd_stats_table_table_string, - (void *) &cmd_stats_table_table_id, - NULL, - }, -}; - -/* - * port in enable - */ - -struct cmd_port_in_enable_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t port_string; - cmdline_fixed_string_t in_string; - uint32_t port_in_id; - cmdline_fixed_string_t enable_string; -}; - -static void -cmd_port_in_enable_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_port_in_enable_result *params = parsed_result; - struct app_params *app = data; - int status; - - status = app_pipeline_port_in_enable(app, - params->pipeline_id, - params->port_in_id); - - if (status != 0) - printf("Command failed\n"); -} - -static cmdline_parse_token_string_t cmd_port_in_enable_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_port_in_enable_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, pipeline_id, - UINT32); - -static cmdline_parse_token_string_t cmd_port_in_enable_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, port_string, - "port"); - -static cmdline_parse_token_string_t cmd_port_in_enable_in_string = - TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, in_string, - "in"); - -static cmdline_parse_token_num_t cmd_port_in_enable_port_in_id = - TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, port_in_id, - UINT32); - -static cmdline_parse_token_string_t cmd_port_in_enable_enable_string = - TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, - enable_string, "enable"); - -static cmdline_parse_inst_t cmd_port_in_enable = { - .f = cmd_port_in_enable_parsed, - .data = NULL, - .help_str = "Pipeline input port enable", - .tokens = { - (void *) &cmd_port_in_enable_p_string, - (void *) &cmd_port_in_enable_pipeline_id, - (void *) &cmd_port_in_enable_port_string, - (void *) &cmd_port_in_enable_in_string, - (void *) &cmd_port_in_enable_port_in_id, - (void *) &cmd_port_in_enable_enable_string, - NULL, - }, -}; - -/* - * port in disable - */ - -struct cmd_port_in_disable_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t port_string; - cmdline_fixed_string_t in_string; - uint32_t port_in_id; - cmdline_fixed_string_t disable_string; -}; - -static void -cmd_port_in_disable_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_port_in_disable_result *params = parsed_result; - struct app_params *app = data; - int status; - - status = app_pipeline_port_in_disable(app, - params->pipeline_id, - params->port_in_id); - - if (status != 0) - printf("Command failed\n"); -} - -static cmdline_parse_token_string_t cmd_port_in_disable_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_port_in_disable_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, pipeline_id, - UINT32); - -static cmdline_parse_token_string_t cmd_port_in_disable_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, port_string, - "port"); - -static cmdline_parse_token_string_t cmd_port_in_disable_in_string = - TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, in_string, - "in"); - -static cmdline_parse_token_num_t cmd_port_in_disable_port_in_id = - TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, port_in_id, - UINT32); - -static cmdline_parse_token_string_t cmd_port_in_disable_disable_string = - TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, - disable_string, "disable"); - -static cmdline_parse_inst_t cmd_port_in_disable = { - .f = cmd_port_in_disable_parsed, - .data = NULL, - .help_str = "Pipeline input port disable", - .tokens = { - (void *) &cmd_port_in_disable_p_string, - (void *) &cmd_port_in_disable_pipeline_id, - (void *) &cmd_port_in_disable_port_string, - (void *) &cmd_port_in_disable_in_string, - (void *) &cmd_port_in_disable_port_in_id, - (void *) &cmd_port_in_disable_disable_string, - NULL, - }, -}; - -/* - * link config - */ - -static void -print_link_info(struct app_link_params *p) -{ - struct rte_eth_stats stats; - struct ether_addr *mac_addr; - uint32_t netmask = (~0U) << (32 - p->depth); - uint32_t host = p->ip & netmask; - uint32_t bcast = host | (~netmask); - - memset(&stats, 0, sizeof(stats)); - rte_eth_stats_get(p->pmd_id, &stats); - - mac_addr = (struct ether_addr *) &p->mac_addr; - - if (strlen(p->pci_bdf)) - printf("%s(%s): flags=<%s>\n", - p->name, - p->pci_bdf, - (p->state) ? "UP" : "DOWN"); - else - printf("%s: flags=<%s>\n", - p->name, - (p->state) ? "UP" : "DOWN"); - - if (p->ip) - printf("\tinet %" PRIu32 ".%" PRIu32 - ".%" PRIu32 ".%" PRIu32 - " netmask %" PRIu32 ".%" PRIu32 - ".%" PRIu32 ".%" PRIu32 " " - "broadcast %" PRIu32 ".%" PRIu32 - ".%" PRIu32 ".%" PRIu32 "\n", - (p->ip >> 24) & 0xFF, - (p->ip >> 16) & 0xFF, - (p->ip >> 8) & 0xFF, - p->ip & 0xFF, - (netmask >> 24) & 0xFF, - (netmask >> 16) & 0xFF, - (netmask >> 8) & 0xFF, - netmask & 0xFF, - (bcast >> 24) & 0xFF, - (bcast >> 16) & 0xFF, - (bcast >> 8) & 0xFF, - bcast & 0xFF); - - printf("\tether %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 - ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n", - 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]); - - printf("\tRX packets %" PRIu64 - " bytes %" PRIu64 - "\n", - stats.ipackets, - stats.ibytes); - - printf("\tRX errors %" PRIu64 - " missed %" PRIu64 - " no-mbuf %" PRIu64 - "\n", - stats.ierrors, - stats.imissed, - stats.rx_nombuf); - - printf("\tTX packets %" PRIu64 - " bytes %" PRIu64 "\n", - stats.opackets, - stats.obytes); - - printf("\tTX errors %" PRIu64 - "\n", - stats.oerrors); - - printf("\n"); -} - -/* - * link - * - * link config: - * link <linkid> config <ipaddr> <depth> - * - * link up: - * link <linkid> up - * - * link down: - * link <linkid> down - * - * link ls: - * link ls - */ - -struct cmd_link_result { - cmdline_fixed_string_t link_string; - cmdline_multi_string_t multi_string; -}; - -static void -cmd_link_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_link_result *params = parsed_result; - struct app_params *app = data; - - char *tokens[16]; - uint32_t n_tokens = RTE_DIM(tokens); - int status; - - uint32_t link_id; - - status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); - if (status != 0) { - printf(CMD_MSG_TOO_MANY_ARGS, "link"); - return; - } - - /* link ls */ - if ((n_tokens == 1) && (strcmp(tokens[0], "ls") == 0)) { - for (link_id = 0; link_id < app->n_links; link_id++) { - struct app_link_params *p; - - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); - print_link_info(p); - } - return; - } /* link ls */ - - if (n_tokens < 2) { - printf(CMD_MSG_MISMATCH_ARGS, "link"); - return; - } - - if (parser_read_uint32(&link_id, tokens[0])) { - printf(CMD_MSG_INVALID_ARG, "linkid"); - return; - } - - /* link config */ - if (strcmp(tokens[1], "config") == 0) { - struct in_addr ipaddr_ipv4; - uint32_t depth; - - if (n_tokens != 4) { - printf(CMD_MSG_MISMATCH_ARGS, "link config"); - return; - } - - if (parse_ipv4_addr(tokens[2], &ipaddr_ipv4)) { - printf(CMD_MSG_INVALID_ARG, "ipaddr"); - return; - } - - if (parser_read_uint32(&depth, tokens[3])) { - printf(CMD_MSG_INVALID_ARG, "depth"); - return; - } - - status = app_link_config(app, - link_id, - rte_be_to_cpu_32(ipaddr_ipv4.s_addr), - depth); - if (status) - printf(CMD_MSG_FAIL, "link config"); - - return; - } /* link config */ - - /* link up */ - if (strcmp(tokens[1], "up") == 0) { - if (n_tokens != 2) { - printf(CMD_MSG_MISMATCH_ARGS, "link up"); - return; - } - - status = app_link_up(app, link_id); - if (status) - printf(CMD_MSG_FAIL, "link up"); - - return; - } /* link up */ - - /* link down */ - if (strcmp(tokens[1], "down") == 0) { - if (n_tokens != 2) { - printf(CMD_MSG_MISMATCH_ARGS, "link down"); - return; - } - - status = app_link_down(app, link_id); - if (status) - printf(CMD_MSG_FAIL, "link down"); - - return; - } /* link down */ - - printf(CMD_MSG_MISMATCH_ARGS, "link"); -} - -static cmdline_parse_token_string_t cmd_link_link_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_result, link_string, "link"); - -static cmdline_parse_token_string_t cmd_link_multi_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_result, multi_string, - TOKEN_STRING_MULTI); - -static cmdline_parse_inst_t cmd_link = { - .f = cmd_link_parsed, - .data = NULL, - .help_str = "link config / up / down / ls", - .tokens = { - (void *) &cmd_link_link_string, - (void *) &cmd_link_multi_string, - NULL, - }, -}; - -/* - * quit - */ - -struct cmd_quit_result { - cmdline_fixed_string_t quit; -}; - -static void -cmd_quit_parsed( - __rte_unused void *parsed_result, - struct cmdline *cl, - __rte_unused void *data) -{ - cmdline_quit(cl); -} - -static cmdline_parse_token_string_t cmd_quit_quit = - TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); - -static cmdline_parse_inst_t cmd_quit = { - .f = cmd_quit_parsed, - .data = NULL, - .help_str = "Quit", - .tokens = { - (void *) &cmd_quit_quit, - NULL, - }, -}; - -/* - * run - * - * run <file> - * run <file> [<count> [<interval>]] - <count> default is 1 - * <interval> is measured in milliseconds, default is 1 second - */ - -static void -app_run_file( - cmdline_parse_ctx_t *ctx, - const char *file_name) -{ - struct cmdline *file_cl; - int fd; - - fd = open(file_name, O_RDONLY); - if (fd < 0) { - printf("Cannot open file \"%s\"\n", file_name); - return; - } - - file_cl = cmdline_new(ctx, "", fd, 1); - cmdline_interact(file_cl); - close(fd); -} - -struct cmd_run_result { - cmdline_fixed_string_t run_string; - cmdline_multi_string_t multi_string; -}; - -static void -cmd_run_parsed( - void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - struct cmd_run_result *params = parsed_result; - - char *tokens[16]; - uint32_t n_tokens = RTE_DIM(tokens); - int status; - - char *file_name; - uint32_t count, interval, i; - - status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); - if (status) { - printf(CMD_MSG_TOO_MANY_ARGS, "run"); - return; - } - - switch (n_tokens) { - case 0: - printf(CMD_MSG_NOT_ENOUGH_ARGS, "run"); - return; - - case 1: - file_name = tokens[0]; - count = 1; - interval = 1000; - break; - - case 2: - file_name = tokens[0]; - - if (parser_read_uint32(&count, tokens[1]) || - (count == 0)) { - printf(CMD_MSG_INVALID_ARG, "count"); - return; - } - - interval = 1000; - break; - - case 3: - file_name = tokens[0]; - - if (parser_read_uint32(&count, tokens[1]) || - (count == 0)) { - printf(CMD_MSG_INVALID_ARG, "count"); - return; - } - - if (parser_read_uint32(&interval, tokens[2]) || - (interval == 0)) { - printf(CMD_MSG_INVALID_ARG, "interval"); - return; - } - break; - - default: - printf(CMD_MSG_MISMATCH_ARGS, "run"); - return; - } - - for (i = 0; i < count; i++) { - app_run_file(cl->ctx, file_name); - if (interval) - usleep(interval * 1000); - } -} - -static cmdline_parse_token_string_t cmd_run_run_string = - TOKEN_STRING_INITIALIZER(struct cmd_run_result, run_string, "run"); - -static cmdline_parse_token_string_t cmd_run_multi_string = - TOKEN_STRING_INITIALIZER(struct cmd_run_result, multi_string, - TOKEN_STRING_MULTI); - - -static cmdline_parse_inst_t cmd_run = { - .f = cmd_run_parsed, - .data = NULL, - .help_str = "Run CLI script file", - .tokens = { - (void *) &cmd_run_run_string, - (void *) &cmd_run_multi_string, - NULL, - }, -}; - -static cmdline_parse_ctx_t pipeline_common_cmds[] = { - (cmdline_parse_inst_t *) &cmd_quit, - (cmdline_parse_inst_t *) &cmd_run, - (cmdline_parse_inst_t *) &cmd_link, - (cmdline_parse_inst_t *) &cmd_ping, - (cmdline_parse_inst_t *) &cmd_stats_port_in, - (cmdline_parse_inst_t *) &cmd_stats_port_out, - (cmdline_parse_inst_t *) &cmd_stats_table, - (cmdline_parse_inst_t *) &cmd_port_in_enable, - (cmdline_parse_inst_t *) &cmd_port_in_disable, - NULL, -}; - -int -app_pipeline_common_cmd_push(struct app_params *app) -{ - uint32_t n_cmds, i; - - /* Check for available slots in the application commands array */ - n_cmds = RTE_DIM(pipeline_common_cmds) - 1; - if (n_cmds > APP_MAX_CMDS - app->n_cmds) - return -ENOMEM; - - /* Push pipeline commands into the application */ - memcpy(&app->cmds[app->n_cmds], - pipeline_common_cmds, - n_cmds * sizeof(cmdline_parse_ctx_t)); - - for (i = 0; i < n_cmds; i++) - app->cmds[app->n_cmds + i]->data = app; - - app->n_cmds += n_cmds; - app->cmds[app->n_cmds] = NULL; - - return 0; -} diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.h b/examples/ip_pipeline/pipeline/pipeline_common_fe.h deleted file mode 100644 index 7227544f..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_common_fe.h +++ /dev/null @@ -1,231 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_COMMON_FE_H__ -#define __INCLUDE_PIPELINE_COMMON_FE_H__ - -#include <rte_common.h> -#include <rte_cycles.h> -#include <rte_malloc.h> -#include <cmdline_parse.h> - -#include "pipeline_common_be.h" -#include "pipeline.h" -#include "app.h" - -#ifndef MSG_TIMEOUT_DEFAULT -#define MSG_TIMEOUT_DEFAULT 1000 -#endif - -static inline struct app_pipeline_data * -app_pipeline_data(struct app_params *app, uint32_t id) -{ - struct app_pipeline_params *params; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", id, params); - if (params == NULL) - return NULL; - - return &app->pipeline_data[params - app->pipeline_params]; -} - -static inline void * -app_pipeline_data_fe(struct app_params *app, uint32_t id, struct pipeline_type *ptype) -{ - struct app_pipeline_data *pipeline_data; - - pipeline_data = app_pipeline_data(app, id); - if (pipeline_data == NULL) - return NULL; - - if (strcmp(pipeline_data->ptype->name, ptype->name) != 0) - return NULL; - - if (pipeline_data->enabled == 0) - return NULL; - - return pipeline_data->fe; -} - -static inline struct rte_ring * -app_pipeline_msgq_in_get(struct app_params *app, - uint32_t pipeline_id) -{ - struct app_msgq_params *p; - - APP_PARAM_FIND_BY_ID(app->msgq_params, - "MSGQ-REQ-PIPELINE", - pipeline_id, - p); - if (p == NULL) - return NULL; - - return app->msgq[p - app->msgq_params]; -} - -static inline struct rte_ring * -app_pipeline_msgq_out_get(struct app_params *app, - uint32_t pipeline_id) -{ - struct app_msgq_params *p; - - APP_PARAM_FIND_BY_ID(app->msgq_params, - "MSGQ-RSP-PIPELINE", - pipeline_id, - p); - if (p == NULL) - return NULL; - - return app->msgq[p - app->msgq_params]; -} - -static inline void * -app_msg_alloc(__rte_unused struct app_params *app) -{ - return rte_malloc(NULL, 2048, RTE_CACHE_LINE_SIZE); -} - -static inline void -app_msg_free(__rte_unused struct app_params *app, - void *msg) -{ - rte_free(msg); -} - -static inline void -app_msg_send(struct app_params *app, - uint32_t pipeline_id, - void *msg) -{ - struct rte_ring *r = app_pipeline_msgq_in_get(app, pipeline_id); - int status; - - do { - status = rte_ring_sp_enqueue(r, msg); - } while (status == -ENOBUFS); -} - -static inline void * -app_msg_recv(struct app_params *app, - uint32_t pipeline_id) -{ - struct rte_ring *r = app_pipeline_msgq_out_get(app, pipeline_id); - void *msg; - int status = rte_ring_sc_dequeue(r, &msg); - - if (status != 0) - return NULL; - - return msg; -} - -static inline void * -app_msg_send_recv(struct app_params *app, - uint32_t pipeline_id, - void *msg, - uint32_t timeout_ms) -{ - struct rte_ring *r_req = app_pipeline_msgq_in_get(app, pipeline_id); - struct rte_ring *r_rsp = app_pipeline_msgq_out_get(app, pipeline_id); - uint64_t hz = rte_get_tsc_hz(); - void *msg_recv; - uint64_t deadline; - int status; - - /* send */ - do { - status = rte_ring_sp_enqueue(r_req, (void *) msg); - } while (status == -ENOBUFS); - - /* recv */ - deadline = (timeout_ms) ? - (rte_rdtsc() + ((hz * timeout_ms) / 1000)) : - UINT64_MAX; - - do { - if (rte_rdtsc() > deadline) - return NULL; - - status = rte_ring_sc_dequeue(r_rsp, &msg_recv); - } while (status != 0); - - return msg_recv; -} - -struct app_link_params * -app_pipeline_track_pktq_out_to_link(struct app_params *app, - uint32_t pipeline_id, - uint32_t pktq_out_id); - -int -app_pipeline_track_default(struct pipeline_params *params, - uint32_t port_in, - uint32_t *port_out); - -int -app_pipeline_ping(struct app_params *app, - uint32_t pipeline_id); - -int -app_pipeline_stats_port_in(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id, - struct rte_pipeline_port_in_stats *stats); - -int -app_pipeline_stats_port_out(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id, - struct rte_pipeline_port_out_stats *stats); - -int -app_pipeline_stats_table(struct app_params *app, - uint32_t pipeline_id, - uint32_t table_id, - struct rte_pipeline_table_stats *stats); - -int -app_pipeline_port_in_enable(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id); - -int -app_pipeline_port_in_disable(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id); - -int -app_link_set_op(struct app_params *app, - uint32_t link_id, - uint32_t pipeline_id, - app_link_op op, - void *arg); - -int -app_link_config(struct app_params *app, - uint32_t link_id, - uint32_t ip, - uint32_t depth); - -int -app_link_up(struct app_params *app, - uint32_t link_id); - -int -app_link_down(struct app_params *app, - uint32_t link_id); - -int -app_pipeline_common_cmd_push(struct app_params *app); - -#define CMD_MSG_OUT_OF_MEMORY "Not enough memory\n" -#define CMD_MSG_NOT_ENOUGH_ARGS "Not enough arguments for command \"%s\"\n" -#define CMD_MSG_TOO_MANY_ARGS "Too many arguments for command \"%s\"\n" -#define CMD_MSG_MISMATCH_ARGS "Incorrect set of arguments for command \"%s\"\n" -#define CMD_MSG_INVALID_ARG "Invalid value for argument \"%s\"\n" -#define CMD_MSG_ARG_NOT_FOUND "Syntax error: \"%s\" not found\n" -#define CMD_MSG_FILE_ERR "Error in file \"%s\" at line %u\n" -#define CMD_MSG_FAIL "Command \"%s\" failed\n" - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c deleted file mode 100644 index 0cae9d74..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_firewall.c +++ /dev/null @@ -1,1421 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/queue.h> -#include <netinet/in.h> - -#include <rte_common.h> -#include <rte_hexdump.h> -#include <rte_malloc.h> -#include <cmdline_rdline.h> -#include <cmdline_parse.h> -#include <cmdline_parse_num.h> -#include <cmdline_parse_string.h> - -#include "app.h" -#include "pipeline_common_fe.h" -#include "pipeline_firewall.h" -#include "parser.h" - -struct app_pipeline_firewall_rule { - struct pipeline_firewall_key key; - int32_t priority; - uint32_t port_id; - void *entry_ptr; - - TAILQ_ENTRY(app_pipeline_firewall_rule) node; -}; - -struct app_pipeline_firewall { - /* parameters */ - uint32_t n_ports_in; - uint32_t n_ports_out; - - /* rules */ - TAILQ_HEAD(, app_pipeline_firewall_rule) rules; - uint32_t n_rules; - uint32_t default_rule_present; - uint32_t default_rule_port_id; - void *default_rule_entry_ptr; -}; - -static void -print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule) -{ - printf("Prio = %" PRId32 " (SA = %" PRIu32 ".%" PRIu32 - ".%" PRIu32 ".%" PRIu32 "/%" PRIu32 ", " - "DA = %" PRIu32 ".%" PRIu32 - ".%"PRIu32 ".%" PRIu32 "/%" PRIu32 ", " - "SP = %" PRIu32 "-%" PRIu32 ", " - "DP = %" PRIu32 "-%" PRIu32 ", " - "Proto = %" PRIu32 " / 0x%" PRIx32 ") => " - "Port = %" PRIu32 " (entry ptr = %p)\n", - - rule->priority, - - (rule->key.key.ipv4_5tuple.src_ip >> 24) & 0xFF, - (rule->key.key.ipv4_5tuple.src_ip >> 16) & 0xFF, - (rule->key.key.ipv4_5tuple.src_ip >> 8) & 0xFF, - rule->key.key.ipv4_5tuple.src_ip & 0xFF, - rule->key.key.ipv4_5tuple.src_ip_mask, - - (rule->key.key.ipv4_5tuple.dst_ip >> 24) & 0xFF, - (rule->key.key.ipv4_5tuple.dst_ip >> 16) & 0xFF, - (rule->key.key.ipv4_5tuple.dst_ip >> 8) & 0xFF, - rule->key.key.ipv4_5tuple.dst_ip & 0xFF, - rule->key.key.ipv4_5tuple.dst_ip_mask, - - rule->key.key.ipv4_5tuple.src_port_from, - rule->key.key.ipv4_5tuple.src_port_to, - - rule->key.key.ipv4_5tuple.dst_port_from, - rule->key.key.ipv4_5tuple.dst_port_to, - - rule->key.key.ipv4_5tuple.proto, - rule->key.key.ipv4_5tuple.proto_mask, - - rule->port_id, - rule->entry_ptr); -} - -static struct app_pipeline_firewall_rule * -app_pipeline_firewall_rule_find(struct app_pipeline_firewall *p, - struct pipeline_firewall_key *key) -{ - struct app_pipeline_firewall_rule *r; - - TAILQ_FOREACH(r, &p->rules, node) - if (memcmp(key, - &r->key, - sizeof(struct pipeline_firewall_key)) == 0) - return r; - - return NULL; -} - -static int -app_pipeline_firewall_ls( - struct app_params *app, - uint32_t pipeline_id) -{ - struct app_pipeline_firewall *p; - struct app_pipeline_firewall_rule *rule; - uint32_t n_rules; - int priority; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall); - if (p == NULL) - return -1; - - n_rules = p->n_rules; - for (priority = 0; n_rules; priority++) - TAILQ_FOREACH(rule, &p->rules, node) - if (rule->priority == priority) { - print_firewall_ipv4_rule(rule); - n_rules--; - } - - if (p->default_rule_present) - printf("Default rule: port %" PRIu32 " (entry ptr = %p)\n", - p->default_rule_port_id, - p->default_rule_entry_ptr); - else - printf("Default rule: DROP\n"); - - printf("\n"); - - return 0; -} - -static void* -app_pipeline_firewall_init(struct pipeline_params *params, - __rte_unused void *arg) -{ - struct app_pipeline_firewall *p; - uint32_t size; - - /* Check input arguments */ - if ((params == NULL) || - (params->n_ports_in == 0) || - (params->n_ports_out == 0)) - return NULL; - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_firewall)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - if (p == NULL) - return NULL; - - /* Initialization */ - p->n_ports_in = params->n_ports_in; - p->n_ports_out = params->n_ports_out; - - TAILQ_INIT(&p->rules); - p->n_rules = 0; - p->default_rule_present = 0; - p->default_rule_port_id = 0; - p->default_rule_entry_ptr = NULL; - - return (void *) p; -} - -static int -app_pipeline_firewall_free(void *pipeline) -{ - struct app_pipeline_firewall *p = pipeline; - - /* Check input arguments */ - if (p == NULL) - return -1; - - /* Free resources */ - while (!TAILQ_EMPTY(&p->rules)) { - struct app_pipeline_firewall_rule *rule; - - rule = TAILQ_FIRST(&p->rules); - TAILQ_REMOVE(&p->rules, rule, node); - rte_free(rule); - } - - rte_free(p); - return 0; -} - -static int -app_pipeline_firewall_key_check_and_normalize(struct pipeline_firewall_key *key) -{ - switch (key->type) { - case PIPELINE_FIREWALL_IPV4_5TUPLE: - { - uint32_t src_ip_depth = key->key.ipv4_5tuple.src_ip_mask; - uint32_t dst_ip_depth = key->key.ipv4_5tuple.dst_ip_mask; - uint16_t src_port_from = key->key.ipv4_5tuple.src_port_from; - uint16_t src_port_to = key->key.ipv4_5tuple.src_port_to; - uint16_t dst_port_from = key->key.ipv4_5tuple.dst_port_from; - uint16_t dst_port_to = key->key.ipv4_5tuple.dst_port_to; - - uint32_t src_ip_netmask = 0; - uint32_t dst_ip_netmask = 0; - - if ((src_ip_depth > 32) || - (dst_ip_depth > 32) || - (src_port_from > src_port_to) || - (dst_port_from > dst_port_to)) - return -1; - - if (src_ip_depth) - src_ip_netmask = (~0U) << (32 - src_ip_depth); - - if (dst_ip_depth) - dst_ip_netmask = ((~0U) << (32 - dst_ip_depth)); - - key->key.ipv4_5tuple.src_ip &= src_ip_netmask; - key->key.ipv4_5tuple.dst_ip &= dst_ip_netmask; - - return 0; - } - - default: - return -1; - } -} - -int -app_pipeline_firewall_load_file(char *filename, - struct pipeline_firewall_key *keys, - uint32_t *priorities, - uint32_t *port_ids, - uint32_t *n_keys, - uint32_t *line) -{ - FILE *f = NULL; - char file_buf[1024]; - uint32_t i, l; - - /* Check input arguments */ - if ((filename == NULL) || - (keys == NULL) || - (priorities == NULL) || - (port_ids == NULL) || - (n_keys == NULL) || - (*n_keys == 0) || - (line == NULL)) { - if (line) - *line = 0; - return -1; - } - - /* Open input file */ - f = fopen(filename, "r"); - if (f == NULL) { - *line = 0; - return -1; - } - - /* Read file */ - for (i = 0, l = 1; i < *n_keys; l++) { - char *tokens[32]; - uint32_t n_tokens = RTE_DIM(tokens); - - uint32_t priority = 0; - struct in_addr sipaddr; - uint32_t sipdepth = 0; - struct in_addr dipaddr; - uint32_t dipdepth = 0; - uint16_t sport0 = 0; - uint16_t sport1 = 0; - uint16_t dport0 = 0; - uint16_t dport1 = 0; - uint8_t proto = 0; - uint8_t protomask = 0; - uint32_t port_id = 0; - - int status; - - if (fgets(file_buf, sizeof(file_buf), f) == NULL) - break; - - status = parse_tokenize_string(file_buf, tokens, &n_tokens); - if (status) - goto error1; - - if ((n_tokens == 0) || (tokens[0][0] == '#')) - continue; - - if ((n_tokens != 15) || - strcmp(tokens[0], "priority") || - parser_read_uint32(&priority, tokens[1]) || - strcmp(tokens[2], "ipv4") || - parse_ipv4_addr(tokens[3], &sipaddr) || - parser_read_uint32(&sipdepth, tokens[4]) || - parse_ipv4_addr(tokens[5], &dipaddr) || - parser_read_uint32(&dipdepth, tokens[6]) || - parser_read_uint16(&sport0, tokens[7]) || - parser_read_uint16(&sport1, tokens[8]) || - parser_read_uint16(&dport0, tokens[9]) || - parser_read_uint16(&dport1, tokens[10]) || - parser_read_uint8(&proto, tokens[11]) || - parser_read_uint8_hex(&protomask, tokens[12]) || - strcmp(tokens[13], "port") || - parser_read_uint32(&port_id, tokens[14])) - goto error1; - - keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE; - keys[i].key.ipv4_5tuple.src_ip = - rte_be_to_cpu_32(sipaddr.s_addr); - keys[i].key.ipv4_5tuple.src_ip_mask = sipdepth; - keys[i].key.ipv4_5tuple.dst_ip = - rte_be_to_cpu_32(dipaddr.s_addr); - keys[i].key.ipv4_5tuple.dst_ip_mask = dipdepth; - keys[i].key.ipv4_5tuple.src_port_from = sport0; - keys[i].key.ipv4_5tuple.src_port_to = sport1; - keys[i].key.ipv4_5tuple.dst_port_from = dport0; - keys[i].key.ipv4_5tuple.dst_port_to = dport1; - keys[i].key.ipv4_5tuple.proto = proto; - keys[i].key.ipv4_5tuple.proto_mask = protomask; - - port_ids[i] = port_id; - priorities[i] = priority; - - if (app_pipeline_firewall_key_check_and_normalize(&keys[i])) - goto error1; - - i++; - } - - /* Close file */ - *n_keys = i; - fclose(f); - return 0; - -error1: - *line = l; - fclose(f); - return -1; -} - -int -app_pipeline_firewall_add_rule(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_firewall_key *key, - uint32_t priority, - uint32_t port_id) -{ - struct app_pipeline_firewall *p; - struct app_pipeline_firewall_rule *rule; - struct pipeline_firewall_add_msg_req *req; - struct pipeline_firewall_add_msg_rsp *rsp; - int new_rule; - - /* Check input arguments */ - if ((app == NULL) || - (key == NULL) || - (key->type != PIPELINE_FIREWALL_IPV4_5TUPLE)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall); - if (p == NULL) - return -1; - - if (port_id >= p->n_ports_out) - return -1; - - if (app_pipeline_firewall_key_check_and_normalize(key) != 0) - return -1; - - /* Find existing rule or allocate new rule */ - rule = app_pipeline_firewall_rule_find(p, key); - new_rule = (rule == NULL); - if (rule == NULL) { - rule = rte_malloc(NULL, sizeof(*rule), RTE_CACHE_LINE_SIZE); - - if (rule == NULL) - return -1; - } - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) { - if (new_rule) - rte_free(rule); - return -1; - } - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD; - memcpy(&req->key, key, sizeof(*key)); - req->priority = priority; - req->port_id = port_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) { - if (new_rule) - rte_free(rule); - return -1; - } - - /* Read response and write rule */ - if (rsp->status || - (rsp->entry_ptr == NULL) || - ((new_rule == 0) && (rsp->key_found == 0)) || - ((new_rule == 1) && (rsp->key_found == 1))) { - app_msg_free(app, rsp); - if (new_rule) - rte_free(rule); - return -1; - } - - memcpy(&rule->key, key, sizeof(*key)); - rule->priority = priority; - rule->port_id = port_id; - rule->entry_ptr = rsp->entry_ptr; - - /* Commit rule */ - if (new_rule) { - TAILQ_INSERT_TAIL(&p->rules, rule, node); - p->n_rules++; - } - - print_firewall_ipv4_rule(rule); - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_firewall_delete_rule(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_firewall_key *key) -{ - struct app_pipeline_firewall *p; - struct app_pipeline_firewall_rule *rule; - struct pipeline_firewall_del_msg_req *req; - struct pipeline_firewall_del_msg_rsp *rsp; - - /* Check input arguments */ - if ((app == NULL) || - (key == NULL) || - (key->type != PIPELINE_FIREWALL_IPV4_5TUPLE)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall); - if (p == NULL) - return -1; - - if (app_pipeline_firewall_key_check_and_normalize(key) != 0) - return -1; - - /* Find rule */ - rule = app_pipeline_firewall_rule_find(p, key); - if (rule == NULL) - return 0; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL; - memcpy(&req->key, key, sizeof(*key)); - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response */ - if (rsp->status || !rsp->key_found) { - app_msg_free(app, rsp); - return -1; - } - - /* Remove rule */ - TAILQ_REMOVE(&p->rules, rule, node); - p->n_rules--; - rte_free(rule); - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_firewall_add_bulk(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_firewall_key *keys, - uint32_t n_keys, - uint32_t *priorities, - uint32_t *port_ids) -{ - struct app_pipeline_firewall *p; - struct pipeline_firewall_add_bulk_msg_req *req; - struct pipeline_firewall_add_bulk_msg_rsp *rsp; - - struct app_pipeline_firewall_rule **rules; - int *new_rules; - - int *keys_found; - void **entries_ptr; - - uint32_t i; - int status = 0; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall); - if (p == NULL) - return -1; - - rules = rte_malloc(NULL, - n_keys * sizeof(struct app_pipeline_firewall_rule *), - RTE_CACHE_LINE_SIZE); - if (rules == NULL) - return -1; - - new_rules = rte_malloc(NULL, - n_keys * sizeof(int), - RTE_CACHE_LINE_SIZE); - if (new_rules == NULL) { - rte_free(rules); - return -1; - } - - /* check data integrity and add to rule list */ - for (i = 0; i < n_keys; i++) { - if (port_ids[i] >= p->n_ports_out) { - rte_free(rules); - rte_free(new_rules); - return -1; - } - - if (app_pipeline_firewall_key_check_and_normalize(&keys[i]) != 0) { - rte_free(rules); - rte_free(new_rules); - return -1; - } - - rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]); - new_rules[i] = (rules[i] == NULL); - if (rules[i] == NULL) { - rules[i] = rte_malloc(NULL, - sizeof(*rules[i]), - RTE_CACHE_LINE_SIZE); - - if (rules[i] == NULL) { - uint32_t j; - - for (j = 0; j <= i; j++) - if (new_rules[j]) - rte_free(rules[j]); - - rte_free(rules); - rte_free(new_rules); - return -1; - } - } - } - - keys_found = rte_malloc(NULL, - n_keys * sizeof(int), - RTE_CACHE_LINE_SIZE); - if (keys_found == NULL) { - uint32_t j; - - for (j = 0; j < n_keys; j++) - if (new_rules[j]) - rte_free(rules[j]); - - rte_free(rules); - rte_free(new_rules); - return -1; - } - - entries_ptr = rte_malloc(NULL, - n_keys * sizeof(struct rte_pipeline_table_entry *), - RTE_CACHE_LINE_SIZE); - if (entries_ptr == NULL) { - uint32_t j; - - for (j = 0; j < n_keys; j++) - if (new_rules[j]) - rte_free(rules[j]); - - rte_free(rules); - rte_free(new_rules); - rte_free(keys_found); - return -1; - } - for (i = 0; i < n_keys; i++) { - entries_ptr[i] = rte_malloc(NULL, - sizeof(struct rte_pipeline_table_entry), - RTE_CACHE_LINE_SIZE); - - if (entries_ptr[i] == NULL) { - uint32_t j; - - for (j = 0; j < n_keys; j++) - if (new_rules[j]) - rte_free(rules[j]); - - for (j = 0; j <= i; j++) - rte_free(entries_ptr[j]); - - rte_free(rules); - rte_free(new_rules); - rte_free(keys_found); - rte_free(entries_ptr); - return -1; - } - } - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) { - uint32_t j; - - for (j = 0; j < n_keys; j++) - if (new_rules[j]) - rte_free(rules[j]); - - for (j = 0; j < n_keys; j++) - rte_free(entries_ptr[j]); - - rte_free(rules); - rte_free(new_rules); - rte_free(keys_found); - rte_free(entries_ptr); - return -1; - } - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD_BULK; - - req->keys = keys; - req->n_keys = n_keys; - req->port_ids = port_ids; - req->priorities = priorities; - req->keys_found = keys_found; - req->entries_ptr = entries_ptr; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) { - uint32_t j; - - for (j = 0; j < n_keys; j++) - if (new_rules[j]) - rte_free(rules[j]); - - for (j = 0; j < n_keys; j++) - rte_free(entries_ptr[j]); - - rte_free(rules); - rte_free(new_rules); - rte_free(keys_found); - rte_free(entries_ptr); - return -1; - } - - if (rsp->status) { - for (i = 0; i < n_keys; i++) - if (new_rules[i]) - rte_free(rules[i]); - - for (i = 0; i < n_keys; i++) - rte_free(entries_ptr[i]); - - status = -1; - goto cleanup; - } - - for (i = 0; i < n_keys; i++) { - if (entries_ptr[i] == NULL || - ((new_rules[i] == 0) && (keys_found[i] == 0)) || - ((new_rules[i] == 1) && (keys_found[i] == 1))) { - for (i = 0; i < n_keys; i++) - if (new_rules[i]) - rte_free(rules[i]); - - for (i = 0; i < n_keys; i++) - rte_free(entries_ptr[i]); - - status = -1; - goto cleanup; - } - } - - for (i = 0; i < n_keys; i++) { - memcpy(&rules[i]->key, &keys[i], sizeof(keys[i])); - rules[i]->priority = priorities[i]; - rules[i]->port_id = port_ids[i]; - rules[i]->entry_ptr = entries_ptr[i]; - - /* Commit rule */ - if (new_rules[i]) { - TAILQ_INSERT_TAIL(&p->rules, rules[i], node); - p->n_rules++; - } - - print_firewall_ipv4_rule(rules[i]); - } - -cleanup: - app_msg_free(app, rsp); - rte_free(rules); - rte_free(new_rules); - rte_free(keys_found); - rte_free(entries_ptr); - - return status; -} - -int -app_pipeline_firewall_delete_bulk(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_firewall_key *keys, - uint32_t n_keys) -{ - struct app_pipeline_firewall *p; - struct pipeline_firewall_del_bulk_msg_req *req; - struct pipeline_firewall_del_bulk_msg_rsp *rsp; - - struct app_pipeline_firewall_rule **rules; - int *keys_found; - - uint32_t i; - int status = 0; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall); - if (p == NULL) - return -1; - - rules = rte_malloc(NULL, - n_keys * sizeof(struct app_pipeline_firewall_rule *), - RTE_CACHE_LINE_SIZE); - if (rules == NULL) - return -1; - - for (i = 0; i < n_keys; i++) { - if (app_pipeline_firewall_key_check_and_normalize(&keys[i]) != 0) { - return -1; - } - - rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]); - } - - keys_found = rte_malloc(NULL, - n_keys * sizeof(int), - RTE_CACHE_LINE_SIZE); - if (keys_found == NULL) { - rte_free(rules); - return -1; - } - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) { - rte_free(rules); - rte_free(keys_found); - return -1; - } - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL_BULK; - - req->keys = keys; - req->n_keys = n_keys; - req->keys_found = keys_found; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) { - rte_free(rules); - rte_free(keys_found); - return -1; - } - - if (rsp->status) { - status = -1; - goto cleanup; - } - - for (i = 0; i < n_keys; i++) { - if (keys_found[i] == 0) { - status = -1; - goto cleanup; - } - } - - for (i = 0; i < n_keys; i++) { - TAILQ_REMOVE(&p->rules, rules[i], node); - p->n_rules--; - rte_free(rules[i]); - } - -cleanup: - app_msg_free(app, rsp); - rte_free(rules); - rte_free(keys_found); - - return status; -} - -int -app_pipeline_firewall_add_default_rule(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id) -{ - struct app_pipeline_firewall *p; - struct pipeline_firewall_add_default_msg_req *req; - struct pipeline_firewall_add_default_msg_rsp *rsp; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall); - if (p == NULL) - return -1; - - if (port_id >= p->n_ports_out) - return -1; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT; - req->port_id = port_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response and write rule */ - if (rsp->status || (rsp->entry_ptr == NULL)) { - app_msg_free(app, rsp); - return -1; - } - - p->default_rule_port_id = port_id; - p->default_rule_entry_ptr = rsp->entry_ptr; - - /* Commit rule */ - p->default_rule_present = 1; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_firewall_delete_default_rule(struct app_params *app, - uint32_t pipeline_id) -{ - struct app_pipeline_firewall *p; - struct pipeline_firewall_del_default_msg_req *req; - struct pipeline_firewall_del_default_msg_rsp *rsp; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall); - if (p == NULL) - return -1; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response and write rule */ - if (rsp->status) { - app_msg_free(app, rsp); - return -1; - } - - /* Commit rule */ - p->default_rule_present = 0; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -/* - * firewall - * - * firewall add: - * p <pipelineid> firewall add priority <priority> - * ipv4 <sipaddr> <sipdepth> <dipaddr> <dipdepth> - * <sport0> <sport1> <dport0> <dport1> <proto> <protomask> - * port <portid> - * Note: <protomask> is a hex value - * - * p <pipelineid> firewall add bulk <file> - * - * firewall add default: - * p <pipelineid> firewall add default <port ID> - * - * firewall del: - * p <pipelineid> firewall del - * ipv4 <sipaddr> <sipdepth> <dipaddr> <dipdepth> - * <sport0> <sport1> <dport0> <dport1> <proto> <protomask> - * - * p <pipelineid> firewall del bulk <file> - * - * firewall del default: - * p <pipelineid> firewall del default - * - * firewall ls: - * p <pipelineid> firewall ls - */ - -struct cmd_firewall_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t firewall_string; - cmdline_multi_string_t multi_string; -}; - -static void cmd_firewall_parsed(void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_firewall_result *params = parsed_result; - struct app_params *app = data; - int status; - - char *tokens[17]; - uint32_t n_tokens = RTE_DIM(tokens); - - status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); - if (status) { - printf(CMD_MSG_TOO_MANY_ARGS, "firewall"); - return; - } - - /* firewall add */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "priority") == 0)) { - struct pipeline_firewall_key key; - uint32_t priority; - struct in_addr sipaddr; - uint32_t sipdepth; - struct in_addr dipaddr; - uint32_t dipdepth; - uint16_t sport0; - uint16_t sport1; - uint16_t dport0; - uint16_t dport1; - uint8_t proto; - uint8_t protomask; - uint32_t port_id; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 16) { - printf(CMD_MSG_MISMATCH_ARGS, "firewall add"); - return; - } - - if (parser_read_uint32(&priority, tokens[2])) { - printf(CMD_MSG_INVALID_ARG, "priority"); - return; - } - - if (strcmp(tokens[3], "ipv4")) { - printf(CMD_MSG_ARG_NOT_FOUND, "ipv4"); - return; - } - - if (parse_ipv4_addr(tokens[4], &sipaddr)) { - printf(CMD_MSG_INVALID_ARG, "sipaddr"); - return; - } - - if (parser_read_uint32(&sipdepth, tokens[5])) { - printf(CMD_MSG_INVALID_ARG, "sipdepth"); - return; - } - - if (parse_ipv4_addr(tokens[6], &dipaddr)) { - printf(CMD_MSG_INVALID_ARG, "dipaddr"); - return; - } - - if (parser_read_uint32(&dipdepth, tokens[7])) { - printf(CMD_MSG_INVALID_ARG, "dipdepth"); - return; - } - - if (parser_read_uint16(&sport0, tokens[8])) { - printf(CMD_MSG_INVALID_ARG, "sport0"); - return; - } - - if (parser_read_uint16(&sport1, tokens[9])) { - printf(CMD_MSG_INVALID_ARG, "sport1"); - return; - } - - if (parser_read_uint16(&dport0, tokens[10])) { - printf(CMD_MSG_INVALID_ARG, "dport0"); - return; - } - - if (parser_read_uint16(&dport1, tokens[11])) { - printf(CMD_MSG_INVALID_ARG, "dport1"); - return; - } - - if (parser_read_uint8(&proto, tokens[12])) { - printf(CMD_MSG_INVALID_ARG, "proto"); - return; - } - - if (parser_read_uint8_hex(&protomask, tokens[13])) { - printf(CMD_MSG_INVALID_ARG, "protomask"); - return; - } - - if (strcmp(tokens[14], "port")) { - printf(CMD_MSG_ARG_NOT_FOUND, "port"); - return; - } - - if (parser_read_uint32(&port_id, tokens[15])) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; - key.key.ipv4_5tuple.src_ip = rte_be_to_cpu_32(sipaddr.s_addr); - key.key.ipv4_5tuple.src_ip_mask = sipdepth; - key.key.ipv4_5tuple.dst_ip = rte_be_to_cpu_32(dipaddr.s_addr); - key.key.ipv4_5tuple.dst_ip_mask = dipdepth; - key.key.ipv4_5tuple.src_port_from = sport0; - key.key.ipv4_5tuple.src_port_to = sport1; - key.key.ipv4_5tuple.dst_port_from = dport0; - key.key.ipv4_5tuple.dst_port_to = dport1; - key.key.ipv4_5tuple.proto = proto; - key.key.ipv4_5tuple.proto_mask = protomask; - - status = app_pipeline_firewall_add_rule(app, - params->pipeline_id, - &key, - priority, - port_id); - if (status) - printf(CMD_MSG_FAIL, "firewall add"); - - return; - } /* firewall add */ - - /* firewall add bulk */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "bulk") == 0)) { - struct pipeline_firewall_key *keys; - uint32_t *priorities, *port_ids, n_keys, line; - char *filename; - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "firewall add bulk"); - return; - } - - filename = tokens[2]; - - n_keys = APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE; - keys = malloc(n_keys * sizeof(struct pipeline_firewall_key)); - if (keys == NULL) { - printf(CMD_MSG_OUT_OF_MEMORY); - return; - } - memset(keys, 0, n_keys * sizeof(struct pipeline_firewall_key)); - - priorities = malloc(n_keys * sizeof(uint32_t)); - if (priorities == NULL) { - printf(CMD_MSG_OUT_OF_MEMORY); - free(keys); - return; - } - - port_ids = malloc(n_keys * sizeof(uint32_t)); - if (port_ids == NULL) { - printf(CMD_MSG_OUT_OF_MEMORY); - free(priorities); - free(keys); - return; - } - - status = app_pipeline_firewall_load_file(filename, - keys, - priorities, - port_ids, - &n_keys, - &line); - if (status != 0) { - printf(CMD_MSG_FILE_ERR, filename, line); - free(port_ids); - free(priorities); - free(keys); - return; - } - - status = app_pipeline_firewall_add_bulk(app, - params->pipeline_id, - keys, - n_keys, - priorities, - port_ids); - if (status) - printf(CMD_MSG_FAIL, "firewall add bulk"); - - free(keys); - free(priorities); - free(port_ids); - return; - } /* firewall add bulk */ - - /* firewall add default */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "default") == 0)) { - uint32_t port_id; - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "firewall add default"); - return; - } - - if (parser_read_uint32(&port_id, tokens[2])) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - status = app_pipeline_firewall_add_default_rule(app, - params->pipeline_id, - port_id); - if (status) - printf(CMD_MSG_FAIL, "firewall add default"); - - return; - } /* firewall add default */ - - /* firewall del */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - (strcmp(tokens[1], "ipv4") == 0)) { - struct pipeline_firewall_key key; - struct in_addr sipaddr; - uint32_t sipdepth; - struct in_addr dipaddr; - uint32_t dipdepth; - uint16_t sport0; - uint16_t sport1; - uint16_t dport0; - uint16_t dport1; - uint8_t proto; - uint8_t protomask; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 12) { - printf(CMD_MSG_MISMATCH_ARGS, "firewall del"); - return; - } - - if (parse_ipv4_addr(tokens[2], &sipaddr)) { - printf(CMD_MSG_INVALID_ARG, "sipaddr"); - return; - } - - if (parser_read_uint32(&sipdepth, tokens[3])) { - printf(CMD_MSG_INVALID_ARG, "sipdepth"); - return; - } - - if (parse_ipv4_addr(tokens[4], &dipaddr)) { - printf(CMD_MSG_INVALID_ARG, "dipaddr"); - return; - } - - if (parser_read_uint32(&dipdepth, tokens[5])) { - printf(CMD_MSG_INVALID_ARG, "dipdepth"); - return; - } - - if (parser_read_uint16(&sport0, tokens[6])) { - printf(CMD_MSG_INVALID_ARG, "sport0"); - return; - } - - if (parser_read_uint16(&sport1, tokens[7])) { - printf(CMD_MSG_INVALID_ARG, "sport1"); - return; - } - - if (parser_read_uint16(&dport0, tokens[8])) { - printf(CMD_MSG_INVALID_ARG, "dport0"); - return; - } - - if (parser_read_uint16(&dport1, tokens[9])) { - printf(CMD_MSG_INVALID_ARG, "dport1"); - return; - } - - if (parser_read_uint8(&proto, tokens[10])) { - printf(CMD_MSG_INVALID_ARG, "proto"); - return; - } - - if (parser_read_uint8_hex(&protomask, tokens[11])) { - printf(CMD_MSG_INVALID_ARG, "protomask"); - return; - } - - key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; - key.key.ipv4_5tuple.src_ip = rte_be_to_cpu_32(sipaddr.s_addr); - key.key.ipv4_5tuple.src_ip_mask = sipdepth; - key.key.ipv4_5tuple.dst_ip = rte_be_to_cpu_32(dipaddr.s_addr); - key.key.ipv4_5tuple.dst_ip_mask = dipdepth; - key.key.ipv4_5tuple.src_port_from = sport0; - key.key.ipv4_5tuple.src_port_to = sport1; - key.key.ipv4_5tuple.dst_port_from = dport0; - key.key.ipv4_5tuple.dst_port_to = dport1; - key.key.ipv4_5tuple.proto = proto; - key.key.ipv4_5tuple.proto_mask = protomask; - - status = app_pipeline_firewall_delete_rule(app, - params->pipeline_id, - &key); - if (status) - printf(CMD_MSG_FAIL, "firewall del"); - - return; - } /* firewall del */ - - /* firewall del bulk */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - (strcmp(tokens[1], "bulk") == 0)) { - struct pipeline_firewall_key *keys; - uint32_t *priorities, *port_ids, n_keys, line; - char *filename; - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "firewall del bulk"); - return; - } - - filename = tokens[2]; - - n_keys = APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE; - keys = malloc(n_keys * sizeof(struct pipeline_firewall_key)); - if (keys == NULL) { - printf(CMD_MSG_OUT_OF_MEMORY); - return; - } - memset(keys, 0, n_keys * sizeof(struct pipeline_firewall_key)); - - priorities = malloc(n_keys * sizeof(uint32_t)); - if (priorities == NULL) { - printf(CMD_MSG_OUT_OF_MEMORY); - free(keys); - return; - } - - port_ids = malloc(n_keys * sizeof(uint32_t)); - if (port_ids == NULL) { - printf(CMD_MSG_OUT_OF_MEMORY); - free(priorities); - free(keys); - return; - } - - status = app_pipeline_firewall_load_file(filename, - keys, - priorities, - port_ids, - &n_keys, - &line); - if (status != 0) { - printf(CMD_MSG_FILE_ERR, filename, line); - free(port_ids); - free(priorities); - free(keys); - return; - } - - status = app_pipeline_firewall_delete_bulk(app, - params->pipeline_id, - keys, - n_keys); - if (status) - printf(CMD_MSG_FAIL, "firewall del bulk"); - - free(port_ids); - free(priorities); - free(keys); - return; - } /* firewall del bulk */ - - /* firewall del default */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - (strcmp(tokens[1], "default") == 0)) { - if (n_tokens != 2) { - printf(CMD_MSG_MISMATCH_ARGS, "firewall del default"); - return; - } - - status = app_pipeline_firewall_delete_default_rule(app, - params->pipeline_id); - if (status) - printf(CMD_MSG_FAIL, "firewall del default"); - - return; - - } /* firewall del default */ - - /* firewall ls */ - if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) { - if (n_tokens != 1) { - printf(CMD_MSG_MISMATCH_ARGS, "firewall ls"); - return; - } - - status = app_pipeline_firewall_ls(app, params->pipeline_id); - if (status) - printf(CMD_MSG_FAIL, "firewall ls"); - - return; - } /* firewall ls */ - - printf(CMD_MSG_MISMATCH_ARGS, "firewall"); -} - -static cmdline_parse_token_string_t cmd_firewall_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, p_string, "p"); - -static cmdline_parse_token_num_t cmd_firewall_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_result, pipeline_id, UINT32); - -static cmdline_parse_token_string_t cmd_firewall_firewall_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, firewall_string, - "firewall"); - -static cmdline_parse_token_string_t cmd_firewall_multi_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, multi_string, - TOKEN_STRING_MULTI); - -static cmdline_parse_inst_t cmd_firewall = { - .f = cmd_firewall_parsed, - .data = NULL, - .help_str = "firewall add / add bulk / add default / del / del bulk" - " / del default / ls", - .tokens = { - (void *) &cmd_firewall_p_string, - (void *) &cmd_firewall_pipeline_id, - (void *) &cmd_firewall_firewall_string, - (void *) &cmd_firewall_multi_string, - NULL, - }, -}; - -static cmdline_parse_ctx_t pipeline_cmds[] = { - (cmdline_parse_inst_t *) &cmd_firewall, - NULL, -}; - -static struct pipeline_fe_ops pipeline_firewall_fe_ops = { - .f_init = app_pipeline_firewall_init, - .f_post_init = NULL, - .f_free = app_pipeline_firewall_free, - .f_track = app_pipeline_track_default, - .cmds = pipeline_cmds, -}; - -struct pipeline_type pipeline_firewall = { - .name = "FIREWALL", - .be_ops = &pipeline_firewall_be_ops, - .fe_ops = &pipeline_firewall_fe_ops, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.h b/examples/ip_pipeline/pipeline/pipeline_firewall.h deleted file mode 100644 index 27304b00..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_firewall.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_FIREWALL_H__ -#define __INCLUDE_PIPELINE_FIREWALL_H__ - -#include "pipeline.h" -#include "pipeline_firewall_be.h" - -int -app_pipeline_firewall_add_rule(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_firewall_key *key, - uint32_t priority, - uint32_t port_id); - -int -app_pipeline_firewall_delete_rule(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_firewall_key *key); - -int -app_pipeline_firewall_add_bulk(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_firewall_key *keys, - uint32_t n_keys, - uint32_t *priorities, - uint32_t *port_ids); - -int -app_pipeline_firewall_delete_bulk(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_firewall_key *keys, - uint32_t n_keys); - -int -app_pipeline_firewall_add_default_rule(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id); - -int -app_pipeline_firewall_delete_default_rule(struct app_params *app, - uint32_t pipeline_id); - -#ifndef APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE -#define APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE 65536 -#endif - -int -app_pipeline_firewall_load_file(char *filename, - struct pipeline_firewall_key *keys, - uint32_t *priorities, - uint32_t *port_ids, - uint32_t *n_keys, - uint32_t *line); - -extern struct pipeline_type pipeline_firewall; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c deleted file mode 100644 index bd5e1b2b..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c +++ /dev/null @@ -1,856 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <string.h> - -#include <rte_common.h> -#include <rte_malloc.h> -#include <rte_ether.h> -#include <rte_ip.h> -#include <rte_tcp.h> -#include <rte_byteorder.h> -#include <rte_table_acl.h> - -#include "pipeline_firewall_be.h" -#include "parser.h" - -struct pipeline_firewall { - struct pipeline p; - pipeline_msg_req_handler custom_handlers[PIPELINE_FIREWALL_MSG_REQS]; - - uint32_t n_rules; - uint32_t n_rule_fields; - struct rte_acl_field_def *field_format; - uint32_t field_format_size; -} __rte_cache_aligned; - -static void * -pipeline_firewall_msg_req_custom_handler(struct pipeline *p, void *msg); - -static pipeline_msg_req_handler handlers[] = { - [PIPELINE_MSG_REQ_PING] = - pipeline_msg_req_ping_handler, - [PIPELINE_MSG_REQ_STATS_PORT_IN] = - pipeline_msg_req_stats_port_in_handler, - [PIPELINE_MSG_REQ_STATS_PORT_OUT] = - pipeline_msg_req_stats_port_out_handler, - [PIPELINE_MSG_REQ_STATS_TABLE] = - pipeline_msg_req_stats_table_handler, - [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = - pipeline_msg_req_port_in_enable_handler, - [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = - pipeline_msg_req_port_in_disable_handler, - [PIPELINE_MSG_REQ_CUSTOM] = - pipeline_firewall_msg_req_custom_handler, -}; - -static void * -pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg); - -static void * -pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg); - -static void * -pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg); - -static void * -pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg); - -static void * -pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg); - -static void * -pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg); - -static pipeline_msg_req_handler custom_handlers[] = { - [PIPELINE_FIREWALL_MSG_REQ_ADD] = - pipeline_firewall_msg_req_add_handler, - [PIPELINE_FIREWALL_MSG_REQ_DEL] = - pipeline_firewall_msg_req_del_handler, - [PIPELINE_FIREWALL_MSG_REQ_ADD_BULK] = - pipeline_firewall_msg_req_add_bulk_handler, - [PIPELINE_FIREWALL_MSG_REQ_DEL_BULK] = - pipeline_firewall_msg_req_del_bulk_handler, - [PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT] = - pipeline_firewall_msg_req_add_default_handler, - [PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT] = - pipeline_firewall_msg_req_del_default_handler, -}; - -/* - * Firewall table - */ -struct firewall_table_entry { - struct rte_pipeline_table_entry head; -}; - -static struct rte_acl_field_def field_format_ipv4[] = { - /* Protocol */ - [0] = { - .type = RTE_ACL_FIELD_TYPE_BITMASK, - .size = sizeof(uint8_t), - .field_index = 0, - .input_index = 0, - .offset = sizeof(struct ether_hdr) + - offsetof(struct ipv4_hdr, next_proto_id), - }, - - /* Source IP address (IPv4) */ - [1] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 1, - .input_index = 1, - .offset = sizeof(struct ether_hdr) + - offsetof(struct ipv4_hdr, src_addr), - }, - - /* Destination IP address (IPv4) */ - [2] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 2, - .input_index = 2, - .offset = sizeof(struct ether_hdr) + - offsetof(struct ipv4_hdr, dst_addr), - }, - - /* Source Port */ - [3] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 3, - .input_index = 3, - .offset = sizeof(struct ether_hdr) + - sizeof(struct ipv4_hdr) + - offsetof(struct tcp_hdr, src_port), - }, - - /* Destination Port */ - [4] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 4, - .input_index = 3, - .offset = sizeof(struct ether_hdr) + - sizeof(struct ipv4_hdr) + - offsetof(struct tcp_hdr, dst_port), - }, -}; - -#define SIZEOF_VLAN_HDR 4 - -static struct rte_acl_field_def field_format_vlan_ipv4[] = { - /* Protocol */ - [0] = { - .type = RTE_ACL_FIELD_TYPE_BITMASK, - .size = sizeof(uint8_t), - .field_index = 0, - .input_index = 0, - .offset = sizeof(struct ether_hdr) + - SIZEOF_VLAN_HDR + - offsetof(struct ipv4_hdr, next_proto_id), - }, - - /* Source IP address (IPv4) */ - [1] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 1, - .input_index = 1, - .offset = sizeof(struct ether_hdr) + - SIZEOF_VLAN_HDR + - offsetof(struct ipv4_hdr, src_addr), - }, - - /* Destination IP address (IPv4) */ - [2] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 2, - .input_index = 2, - .offset = sizeof(struct ether_hdr) + - SIZEOF_VLAN_HDR + - offsetof(struct ipv4_hdr, dst_addr), - }, - - /* Source Port */ - [3] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 3, - .input_index = 3, - .offset = sizeof(struct ether_hdr) + - SIZEOF_VLAN_HDR + - sizeof(struct ipv4_hdr) + - offsetof(struct tcp_hdr, src_port), - }, - - /* Destination Port */ - [4] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 4, - .input_index = 3, - .offset = sizeof(struct ether_hdr) + - SIZEOF_VLAN_HDR + - sizeof(struct ipv4_hdr) + - offsetof(struct tcp_hdr, dst_port), - }, -}; - -#define SIZEOF_QINQ_HEADER 8 - -static struct rte_acl_field_def field_format_qinq_ipv4[] = { - /* Protocol */ - [0] = { - .type = RTE_ACL_FIELD_TYPE_BITMASK, - .size = sizeof(uint8_t), - .field_index = 0, - .input_index = 0, - .offset = sizeof(struct ether_hdr) + - SIZEOF_QINQ_HEADER + - offsetof(struct ipv4_hdr, next_proto_id), - }, - - /* Source IP address (IPv4) */ - [1] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 1, - .input_index = 1, - .offset = sizeof(struct ether_hdr) + - SIZEOF_QINQ_HEADER + - offsetof(struct ipv4_hdr, src_addr), - }, - - /* Destination IP address (IPv4) */ - [2] = { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = 2, - .input_index = 2, - .offset = sizeof(struct ether_hdr) + - SIZEOF_QINQ_HEADER + - offsetof(struct ipv4_hdr, dst_addr), - }, - - /* Source Port */ - [3] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 3, - .input_index = 3, - .offset = sizeof(struct ether_hdr) + - SIZEOF_QINQ_HEADER + - sizeof(struct ipv4_hdr) + - offsetof(struct tcp_hdr, src_port), - }, - - /* Destination Port */ - [4] = { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = 4, - .input_index = 3, - .offset = sizeof(struct ether_hdr) + - SIZEOF_QINQ_HEADER + - sizeof(struct ipv4_hdr) + - offsetof(struct tcp_hdr, dst_port), - }, -}; - -static int -pipeline_firewall_parse_args(struct pipeline_firewall *p, - struct pipeline_params *params) -{ - uint32_t n_rules_present = 0; - uint32_t pkt_type_present = 0; - uint32_t i; - - /* defaults */ - p->n_rules = 4 * 1024; - p->n_rule_fields = RTE_DIM(field_format_ipv4); - p->field_format = field_format_ipv4; - p->field_format_size = sizeof(field_format_ipv4); - - for (i = 0; i < params->n_args; i++) { - char *arg_name = params->args_name[i]; - char *arg_value = params->args_value[i]; - - if (strcmp(arg_name, "n_rules") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - n_rules_present == 0, params->name, - arg_name); - n_rules_present = 1; - - status = parser_read_uint32(&p->n_rules, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - continue; - } - - if (strcmp(arg_name, "pkt_type") == 0) { - PIPELINE_PARSE_ERR_DUPLICATE( - pkt_type_present == 0, params->name, - arg_name); - pkt_type_present = 1; - - /* ipv4 */ - if (strcmp(arg_value, "ipv4") == 0) { - p->n_rule_fields = RTE_DIM(field_format_ipv4); - p->field_format = field_format_ipv4; - p->field_format_size = - sizeof(field_format_ipv4); - continue; - } - - /* vlan_ipv4 */ - if (strcmp(arg_value, "vlan_ipv4") == 0) { - p->n_rule_fields = - RTE_DIM(field_format_vlan_ipv4); - p->field_format = field_format_vlan_ipv4; - p->field_format_size = - sizeof(field_format_vlan_ipv4); - continue; - } - - /* qinq_ipv4 */ - if (strcmp(arg_value, "qinq_ipv4") == 0) { - p->n_rule_fields = - RTE_DIM(field_format_qinq_ipv4); - p->field_format = field_format_qinq_ipv4; - p->field_format_size = - sizeof(field_format_qinq_ipv4); - continue; - } - - /* other */ - PIPELINE_PARSE_ERR_INV_VAL(0, params->name, - arg_name, arg_value); - } - - /* other */ - PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); - } - - return 0; -} - -static void * -pipeline_firewall_init(struct pipeline_params *params, - __rte_unused void *arg) -{ - struct pipeline *p; - struct pipeline_firewall *p_fw; - uint32_t size, i; - - /* Check input arguments */ - if ((params == NULL) || - (params->n_ports_in == 0) || - (params->n_ports_out == 0)) - return NULL; - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_firewall)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - p_fw = (struct pipeline_firewall *) p; - if (p == NULL) - return NULL; - - strcpy(p->name, params->name); - p->log_level = params->log_level; - - PLOG(p, HIGH, "Firewall"); - - /* Parse arguments */ - if (pipeline_firewall_parse_args(p_fw, params)) - return NULL; - - /* Pipeline */ - { - struct rte_pipeline_params pipeline_params = { - .name = params->name, - .socket_id = params->socket_id, - .offset_port_id = 0, - }; - - p->p = rte_pipeline_create(&pipeline_params); - if (p->p == NULL) { - rte_free(p); - return NULL; - } - } - - /* Input ports */ - p->n_ports_in = params->n_ports_in; - for (i = 0; i < p->n_ports_in; i++) { - struct rte_pipeline_port_in_params port_params = { - .ops = pipeline_port_in_params_get_ops( - ¶ms->port_in[i]), - .arg_create = pipeline_port_in_params_convert( - ¶ms->port_in[i]), - .f_action = NULL, - .arg_ah = NULL, - .burst_size = params->port_in[i].burst_size, - }; - - int status = rte_pipeline_port_in_create(p->p, - &port_params, - &p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Output ports */ - p->n_ports_out = params->n_ports_out; - for (i = 0; i < p->n_ports_out; i++) { - struct rte_pipeline_port_out_params port_params = { - .ops = pipeline_port_out_params_get_ops( - ¶ms->port_out[i]), - .arg_create = pipeline_port_out_params_convert( - ¶ms->port_out[i]), - .f_action = NULL, - .arg_ah = NULL, - }; - - int status = rte_pipeline_port_out_create(p->p, - &port_params, - &p->port_out_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Tables */ - p->n_tables = 1; - { - struct rte_table_acl_params table_acl_params = { - .name = params->name, - .n_rules = p_fw->n_rules, - .n_rule_fields = p_fw->n_rule_fields, - }; - - struct rte_pipeline_table_params table_params = { - .ops = &rte_table_acl_ops, - .arg_create = &table_acl_params, - .f_action_hit = NULL, - .f_action_miss = NULL, - .arg_ah = NULL, - .action_data_size = - sizeof(struct firewall_table_entry) - - sizeof(struct rte_pipeline_table_entry), - }; - - int status; - - memcpy(table_acl_params.field_format, - p_fw->field_format, - p_fw->field_format_size); - - status = rte_pipeline_table_create(p->p, - &table_params, - &p->table_id[0]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Connecting input ports to tables */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_connect_to_table(p->p, - p->port_in_id[i], - p->table_id[0]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Enable input ports */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_enable(p->p, - p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Check pipeline consistency */ - if (rte_pipeline_check(p->p) < 0) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - - /* Message queues */ - p->n_msgq = params->n_msgq; - for (i = 0; i < p->n_msgq; i++) - p->msgq_in[i] = params->msgq_in[i]; - for (i = 0; i < p->n_msgq; i++) - p->msgq_out[i] = params->msgq_out[i]; - - /* Message handlers */ - memcpy(p->handlers, handlers, sizeof(p->handlers)); - memcpy(p_fw->custom_handlers, - custom_handlers, - sizeof(p_fw->custom_handlers)); - - return p; -} - -static int -pipeline_firewall_free(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if (p == NULL) - return -1; - - /* Free resources */ - rte_pipeline_free(p->p); - rte_free(p); - return 0; -} - -static int -pipeline_firewall_timer(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - pipeline_msg_req_handle(p); - rte_pipeline_flush(p->p); - - return 0; -} - -void * -pipeline_firewall_msg_req_custom_handler(struct pipeline *p, - void *msg) -{ - struct pipeline_firewall *p_fw = (struct pipeline_firewall *) p; - struct pipeline_custom_msg_req *req = msg; - pipeline_msg_req_handler f_handle; - - f_handle = (req->subtype < PIPELINE_FIREWALL_MSG_REQS) ? - p_fw->custom_handlers[req->subtype] : - pipeline_msg_req_invalid_handler; - - if (f_handle == NULL) - f_handle = pipeline_msg_req_invalid_handler; - - return f_handle(p, req); -} - -void * -pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg) -{ - struct pipeline_firewall_add_msg_req *req = msg; - struct pipeline_firewall_add_msg_rsp *rsp = msg; - - struct rte_table_acl_rule_add_params params; - struct firewall_table_entry entry = { - .head = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[req->port_id]}, - }, - }; - - memset(¶ms, 0, sizeof(params)); - - switch (req->key.type) { - case PIPELINE_FIREWALL_IPV4_5TUPLE: - params.priority = req->priority; - params.field_value[0].value.u8 = - req->key.key.ipv4_5tuple.proto; - params.field_value[0].mask_range.u8 = - req->key.key.ipv4_5tuple.proto_mask; - params.field_value[1].value.u32 = - req->key.key.ipv4_5tuple.src_ip; - params.field_value[1].mask_range.u32 = - req->key.key.ipv4_5tuple.src_ip_mask; - params.field_value[2].value.u32 = - req->key.key.ipv4_5tuple.dst_ip; - params.field_value[2].mask_range.u32 = - req->key.key.ipv4_5tuple.dst_ip_mask; - params.field_value[3].value.u16 = - req->key.key.ipv4_5tuple.src_port_from; - params.field_value[3].mask_range.u16 = - req->key.key.ipv4_5tuple.src_port_to; - params.field_value[4].value.u16 = - req->key.key.ipv4_5tuple.dst_port_from; - params.field_value[4].mask_range.u16 = - req->key.key.ipv4_5tuple.dst_port_to; - break; - - default: - rsp->status = -1; /* Error */ - return rsp; - } - - rsp->status = rte_pipeline_table_entry_add(p->p, - p->table_id[0], - ¶ms, - (struct rte_pipeline_table_entry *) &entry, - &rsp->key_found, - (struct rte_pipeline_table_entry **) &rsp->entry_ptr); - - return rsp; -} - -void * -pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg) -{ - struct pipeline_firewall_del_msg_req *req = msg; - struct pipeline_firewall_del_msg_rsp *rsp = msg; - - struct rte_table_acl_rule_delete_params params; - - memset(¶ms, 0, sizeof(params)); - - switch (req->key.type) { - case PIPELINE_FIREWALL_IPV4_5TUPLE: - params.field_value[0].value.u8 = - req->key.key.ipv4_5tuple.proto; - params.field_value[0].mask_range.u8 = - req->key.key.ipv4_5tuple.proto_mask; - params.field_value[1].value.u32 = - req->key.key.ipv4_5tuple.src_ip; - params.field_value[1].mask_range.u32 = - req->key.key.ipv4_5tuple.src_ip_mask; - params.field_value[2].value.u32 = - req->key.key.ipv4_5tuple.dst_ip; - params.field_value[2].mask_range.u32 = - req->key.key.ipv4_5tuple.dst_ip_mask; - params.field_value[3].value.u16 = - req->key.key.ipv4_5tuple.src_port_from; - params.field_value[3].mask_range.u16 = - req->key.key.ipv4_5tuple.src_port_to; - params.field_value[4].value.u16 = - req->key.key.ipv4_5tuple.dst_port_from; - params.field_value[4].mask_range.u16 = - req->key.key.ipv4_5tuple.dst_port_to; - break; - - default: - rsp->status = -1; /* Error */ - return rsp; - } - - rsp->status = rte_pipeline_table_entry_delete(p->p, - p->table_id[0], - ¶ms, - &rsp->key_found, - NULL); - - return rsp; -} - -static void * -pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg) -{ - struct pipeline_firewall_add_bulk_msg_req *req = msg; - struct pipeline_firewall_add_bulk_msg_rsp *rsp = msg; - - struct rte_table_acl_rule_add_params *params[req->n_keys]; - struct firewall_table_entry *entries[req->n_keys]; - - uint32_t i, n_keys; - - n_keys = req->n_keys; - - for (i = 0; i < n_keys; i++) { - entries[i] = rte_zmalloc(NULL, - sizeof(struct firewall_table_entry), - RTE_CACHE_LINE_SIZE); - if (entries[i] == NULL) { - rsp->status = -1; - return rsp; - } - - params[i] = rte_zmalloc(NULL, - sizeof(struct rte_table_acl_rule_add_params), - RTE_CACHE_LINE_SIZE); - if (params[i] == NULL) { - rsp->status = -1; - return rsp; - } - - entries[i]->head.action = RTE_PIPELINE_ACTION_PORT; - entries[i]->head.port_id = p->port_out_id[req->port_ids[i]]; - - switch (req->keys[i].type) { - case PIPELINE_FIREWALL_IPV4_5TUPLE: - params[i]->priority = req->priorities[i]; - params[i]->field_value[0].value.u8 = - req->keys[i].key.ipv4_5tuple.proto; - params[i]->field_value[0].mask_range.u8 = - req->keys[i].key.ipv4_5tuple.proto_mask; - params[i]->field_value[1].value.u32 = - req->keys[i].key.ipv4_5tuple.src_ip; - params[i]->field_value[1].mask_range.u32 = - req->keys[i].key.ipv4_5tuple.src_ip_mask; - params[i]->field_value[2].value.u32 = - req->keys[i].key.ipv4_5tuple.dst_ip; - params[i]->field_value[2].mask_range.u32 = - req->keys[i].key.ipv4_5tuple.dst_ip_mask; - params[i]->field_value[3].value.u16 = - req->keys[i].key.ipv4_5tuple.src_port_from; - params[i]->field_value[3].mask_range.u16 = - req->keys[i].key.ipv4_5tuple.src_port_to; - params[i]->field_value[4].value.u16 = - req->keys[i].key.ipv4_5tuple.dst_port_from; - params[i]->field_value[4].mask_range.u16 = - req->keys[i].key.ipv4_5tuple.dst_port_to; - break; - - default: - rsp->status = -1; /* Error */ - - for (i = 0; i < n_keys; i++) { - rte_free(entries[i]); - rte_free(params[i]); - } - - return rsp; - } - } - - rsp->status = rte_pipeline_table_entry_add_bulk(p->p, p->table_id[0], - (void *)params, (struct rte_pipeline_table_entry **)entries, - n_keys, req->keys_found, - (struct rte_pipeline_table_entry **)req->entries_ptr); - - for (i = 0; i < n_keys; i++) { - rte_free(entries[i]); - rte_free(params[i]); - } - - return rsp; -} - -static void * -pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg) -{ - struct pipeline_firewall_del_bulk_msg_req *req = msg; - struct pipeline_firewall_del_bulk_msg_rsp *rsp = msg; - - struct rte_table_acl_rule_delete_params *params[req->n_keys]; - - uint32_t i, n_keys; - - n_keys = req->n_keys; - - for (i = 0; i < n_keys; i++) { - params[i] = rte_zmalloc(NULL, - sizeof(struct rte_table_acl_rule_delete_params), - RTE_CACHE_LINE_SIZE); - if (params[i] == NULL) { - rsp->status = -1; - return rsp; - } - - switch (req->keys[i].type) { - case PIPELINE_FIREWALL_IPV4_5TUPLE: - params[i]->field_value[0].value.u8 = - req->keys[i].key.ipv4_5tuple.proto; - params[i]->field_value[0].mask_range.u8 = - req->keys[i].key.ipv4_5tuple.proto_mask; - params[i]->field_value[1].value.u32 = - req->keys[i].key.ipv4_5tuple.src_ip; - params[i]->field_value[1].mask_range.u32 = - req->keys[i].key.ipv4_5tuple.src_ip_mask; - params[i]->field_value[2].value.u32 = - req->keys[i].key.ipv4_5tuple.dst_ip; - params[i]->field_value[2].mask_range.u32 = - req->keys[i].key.ipv4_5tuple.dst_ip_mask; - params[i]->field_value[3].value.u16 = - req->keys[i].key.ipv4_5tuple.src_port_from; - params[i]->field_value[3].mask_range.u16 = - req->keys[i].key.ipv4_5tuple.src_port_to; - params[i]->field_value[4].value.u16 = - req->keys[i].key.ipv4_5tuple.dst_port_from; - params[i]->field_value[4].mask_range.u16 = - req->keys[i].key.ipv4_5tuple.dst_port_to; - break; - - default: - rsp->status = -1; /* Error */ - - for (i = 0; i < n_keys; i++) - rte_free(params[i]); - - return rsp; - } - } - - rsp->status = rte_pipeline_table_entry_delete_bulk(p->p, p->table_id[0], - (void **)¶ms, n_keys, req->keys_found, NULL); - - for (i = 0; i < n_keys; i++) - rte_free(params[i]); - - return rsp; -} - -void * -pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg) -{ - struct pipeline_firewall_add_default_msg_req *req = msg; - struct pipeline_firewall_add_default_msg_rsp *rsp = msg; - - struct firewall_table_entry default_entry = { - .head = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[req->port_id]}, - }, - }; - - rsp->status = rte_pipeline_table_default_entry_add(p->p, - p->table_id[0], - (struct rte_pipeline_table_entry *) &default_entry, - (struct rte_pipeline_table_entry **) &rsp->entry_ptr); - - return rsp; -} - -void * -pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg) -{ - struct pipeline_firewall_del_default_msg_rsp *rsp = msg; - - rsp->status = rte_pipeline_table_default_entry_delete(p->p, - p->table_id[0], - NULL); - - return rsp; -} - -struct pipeline_be_ops pipeline_firewall_be_ops = { - .f_init = pipeline_firewall_init, - .f_free = pipeline_firewall_free, - .f_run = NULL, - .f_timer = pipeline_firewall_timer, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.h b/examples/ip_pipeline/pipeline/pipeline_firewall_be.h deleted file mode 100644 index 246f0a6d..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.h +++ /dev/null @@ -1,147 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_FIREWALL_BE_H__ -#define __INCLUDE_PIPELINE_FIREWALL_BE_H__ - -#include "pipeline_common_be.h" - -enum pipeline_firewall_key_type { - PIPELINE_FIREWALL_IPV4_5TUPLE, -}; - -struct pipeline_firewall_key_ipv4_5tuple { - uint32_t src_ip; - uint32_t src_ip_mask; - uint32_t dst_ip; - uint32_t dst_ip_mask; - uint16_t src_port_from; - uint16_t src_port_to; - uint16_t dst_port_from; - uint16_t dst_port_to; - uint8_t proto; - uint8_t proto_mask; -}; - -struct pipeline_firewall_key { - enum pipeline_firewall_key_type type; - union { - struct pipeline_firewall_key_ipv4_5tuple ipv4_5tuple; - } key; -}; - -enum pipeline_firewall_msg_req_type { - PIPELINE_FIREWALL_MSG_REQ_ADD = 0, - PIPELINE_FIREWALL_MSG_REQ_DEL, - PIPELINE_FIREWALL_MSG_REQ_ADD_BULK, - PIPELINE_FIREWALL_MSG_REQ_DEL_BULK, - PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT, - PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT, - PIPELINE_FIREWALL_MSG_REQS -}; - -/* - * MSG ADD - */ -struct pipeline_firewall_add_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_firewall_msg_req_type subtype; - - /* key */ - struct pipeline_firewall_key key; - - /* data */ - int32_t priority; - uint32_t port_id; -}; - -struct pipeline_firewall_add_msg_rsp { - int status; - int key_found; - void *entry_ptr; -}; - -/* - * MSG DEL - */ -struct pipeline_firewall_del_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_firewall_msg_req_type subtype; - - /* key */ - struct pipeline_firewall_key key; -}; - -struct pipeline_firewall_del_msg_rsp { - int status; - int key_found; -}; - -/* - * MSG ADD BULK - */ -struct pipeline_firewall_add_bulk_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_firewall_msg_req_type subtype; - - struct pipeline_firewall_key *keys; - uint32_t n_keys; - - uint32_t *priorities; - uint32_t *port_ids; - int *keys_found; - void **entries_ptr; -}; -struct pipeline_firewall_add_bulk_msg_rsp { - int status; -}; - -/* - * MSG DEL BULK - */ -struct pipeline_firewall_del_bulk_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_firewall_msg_req_type subtype; - - /* key */ - struct pipeline_firewall_key *keys; - uint32_t n_keys; - int *keys_found; -}; - -struct pipeline_firewall_del_bulk_msg_rsp { - int status; -}; - -/* - * MSG ADD DEFAULT - */ -struct pipeline_firewall_add_default_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_firewall_msg_req_type subtype; - - /* data */ - uint32_t port_id; -}; - -struct pipeline_firewall_add_default_msg_rsp { - int status; - void *entry_ptr; -}; - -/* - * MSG DEL DEFAULT - */ -struct pipeline_firewall_del_default_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_firewall_msg_req_type subtype; -}; - -struct pipeline_firewall_del_default_msg_rsp { - int status; -}; - -extern struct pipeline_be_ops pipeline_firewall_be_ops; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c deleted file mode 100644 index 021aee18..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c +++ /dev/null @@ -1,1286 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#include <stdio.h> -#include <string.h> -#include <sys/queue.h> -#include <netinet/in.h> -#include <unistd.h> - -#include <rte_common.h> -#include <rte_hexdump.h> -#include <rte_malloc.h> -#include <cmdline_rdline.h> -#include <cmdline_parse.h> -#include <cmdline_parse_num.h> -#include <cmdline_parse_string.h> - -#include "app.h" -#include "pipeline_common_fe.h" -#include "pipeline_flow_actions.h" -#include "hash_func.h" -#include "parser.h" - -/* - * Flow actions pipeline - */ -#ifndef N_FLOWS_BULK -#define N_FLOWS_BULK 4096 -#endif - -struct app_pipeline_fa_flow { - struct pipeline_fa_flow_params params; - void *entry_ptr; -}; - -struct app_pipeline_fa_dscp { - uint32_t traffic_class; - enum rte_meter_color color; -}; - -struct app_pipeline_fa { - /* Parameters */ - uint32_t n_ports_in; - uint32_t n_ports_out; - struct pipeline_fa_params params; - - /* Flows */ - struct app_pipeline_fa_dscp dscp[PIPELINE_FA_N_DSCP]; - struct app_pipeline_fa_flow *flows; -} __rte_cache_aligned; - -static void* -app_pipeline_fa_init(struct pipeline_params *params, - __rte_unused void *arg) -{ - struct app_pipeline_fa *p; - uint32_t size, i; - - /* Check input arguments */ - if ((params == NULL) || - (params->n_ports_in == 0) || - (params->n_ports_out == 0)) - return NULL; - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fa)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - if (p == NULL) - return NULL; - - /* Initialization */ - p->n_ports_in = params->n_ports_in; - p->n_ports_out = params->n_ports_out; - if (pipeline_fa_parse_args(&p->params, params)) { - rte_free(p); - return NULL; - } - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP( - p->params.n_flows * sizeof(struct app_pipeline_fa_flow)); - p->flows = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - if (p->flows == NULL) { - rte_free(p); - return NULL; - } - - /* Initialization of flow table */ - for (i = 0; i < p->params.n_flows; i++) - pipeline_fa_flow_params_set_default(&p->flows[i].params); - - /* Initialization of DSCP table */ - for (i = 0; i < RTE_DIM(p->dscp); i++) { - p->dscp[i].traffic_class = 0; - p->dscp[i].color = e_RTE_METER_GREEN; - } - - return (void *) p; -} - -static int -app_pipeline_fa_free(void *pipeline) -{ - struct app_pipeline_fa *p = pipeline; - - /* Check input arguments */ - if (p == NULL) - return -1; - - /* Free resources */ - rte_free(p->flows); - rte_free(p); - - return 0; -} - -static int -flow_params_check(struct app_pipeline_fa *p, - __rte_unused uint32_t meter_update_mask, - uint32_t policer_update_mask, - uint32_t port_update, - struct pipeline_fa_flow_params *params) -{ - uint32_t mask, i; - - /* Meter */ - - /* Policer */ - for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) { - struct pipeline_fa_policer_params *p = ¶ms->p[i]; - uint32_t j; - - if ((mask & policer_update_mask) == 0) - continue; - - for (j = 0; j < e_RTE_METER_COLORS; j++) { - struct pipeline_fa_policer_action *action = - &p->action[j]; - - if ((action->drop == 0) && - (action->color >= e_RTE_METER_COLORS)) - return -1; - } - } - - /* Port */ - if (port_update && (params->port_id >= p->n_ports_out)) - return -1; - - return 0; -} - -int -app_pipeline_fa_flow_config(struct app_params *app, - uint32_t pipeline_id, - uint32_t flow_id, - uint32_t meter_update_mask, - uint32_t policer_update_mask, - uint32_t port_update, - struct pipeline_fa_flow_params *params) -{ - struct app_pipeline_fa *p; - struct app_pipeline_fa_flow *flow; - - struct pipeline_fa_flow_config_msg_req *req; - struct pipeline_fa_flow_config_msg_rsp *rsp; - - uint32_t i, mask; - - /* Check input arguments */ - if ((app == NULL) || - ((meter_update_mask == 0) && - (policer_update_mask == 0) && - (port_update == 0)) || - (meter_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) || - (policer_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) || - (params == NULL)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, - &pipeline_flow_actions); - if (p == NULL) - return -1; - - if (flow_params_check(p, - meter_update_mask, - policer_update_mask, - port_update, - params) != 0) - return -1; - - flow_id %= p->params.n_flows; - flow = &p->flows[flow_id]; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FA_MSG_REQ_FLOW_CONFIG; - req->entry_ptr = flow->entry_ptr; - req->flow_id = flow_id; - req->meter_update_mask = meter_update_mask; - req->policer_update_mask = policer_update_mask; - req->port_update = port_update; - memcpy(&req->params, params, sizeof(*params)); - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response */ - if (rsp->status || - (rsp->entry_ptr == NULL)) { - app_msg_free(app, rsp); - return -1; - } - - /* Commit flow */ - for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) { - if ((mask & meter_update_mask) == 0) - continue; - - memcpy(&flow->params.m[i], ¶ms->m[i], sizeof(params->m[i])); - } - - for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) { - if ((mask & policer_update_mask) == 0) - continue; - - memcpy(&flow->params.p[i], ¶ms->p[i], sizeof(params->p[i])); - } - - if (port_update) - flow->params.port_id = params->port_id; - - flow->entry_ptr = rsp->entry_ptr; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_fa_flow_config_bulk(struct app_params *app, - uint32_t pipeline_id, - uint32_t *flow_id, - uint32_t n_flows, - uint32_t meter_update_mask, - uint32_t policer_update_mask, - uint32_t port_update, - struct pipeline_fa_flow_params *params) -{ - struct app_pipeline_fa *p; - struct pipeline_fa_flow_config_bulk_msg_req *req; - struct pipeline_fa_flow_config_bulk_msg_rsp *rsp; - void **req_entry_ptr; - uint32_t *req_flow_id; - uint32_t i; - int status; - - /* Check input arguments */ - if ((app == NULL) || - (flow_id == NULL) || - (n_flows == 0) || - ((meter_update_mask == 0) && - (policer_update_mask == 0) && - (port_update == 0)) || - (meter_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) || - (policer_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) || - (params == NULL)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, - &pipeline_flow_actions); - if (p == NULL) - return -1; - - for (i = 0; i < n_flows; i++) { - struct pipeline_fa_flow_params *flow_params = ¶ms[i]; - - if (flow_params_check(p, - meter_update_mask, - policer_update_mask, - port_update, - flow_params) != 0) - return -1; - } - - /* Allocate and write request */ - req_entry_ptr = (void **) rte_malloc(NULL, - n_flows * sizeof(void *), - RTE_CACHE_LINE_SIZE); - if (req_entry_ptr == NULL) - return -1; - - req_flow_id = (uint32_t *) rte_malloc(NULL, - n_flows * sizeof(uint32_t), - RTE_CACHE_LINE_SIZE); - if (req_flow_id == NULL) { - rte_free(req_entry_ptr); - return -1; - } - - for (i = 0; i < n_flows; i++) { - uint32_t fid = flow_id[i] % p->params.n_flows; - struct app_pipeline_fa_flow *flow = &p->flows[fid]; - - req_flow_id[i] = fid; - req_entry_ptr[i] = flow->entry_ptr; - } - - req = app_msg_alloc(app); - if (req == NULL) { - rte_free(req_flow_id); - rte_free(req_entry_ptr); - return -1; - } - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FA_MSG_REQ_FLOW_CONFIG_BULK; - req->entry_ptr = req_entry_ptr; - req->flow_id = req_flow_id; - req->n_flows = n_flows; - req->meter_update_mask = meter_update_mask; - req->policer_update_mask = policer_update_mask; - req->port_update = port_update; - req->params = params; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) { - rte_free(req_flow_id); - rte_free(req_entry_ptr); - return -1; - } - - /* Read response */ - status = (rsp->n_flows == n_flows) ? 0 : -1; - - /* Commit flows */ - for (i = 0; i < rsp->n_flows; i++) { - uint32_t fid = flow_id[i] % p->params.n_flows; - struct app_pipeline_fa_flow *flow = &p->flows[fid]; - struct pipeline_fa_flow_params *flow_params = ¶ms[i]; - void *entry_ptr = req_entry_ptr[i]; - uint32_t j, mask; - - for (j = 0, mask = 1; j < PIPELINE_FA_N_TC_MAX; - j++, mask <<= 1) { - if ((mask & meter_update_mask) == 0) - continue; - - memcpy(&flow->params.m[j], - &flow_params->m[j], - sizeof(flow_params->m[j])); - } - - for (j = 0, mask = 1; j < PIPELINE_FA_N_TC_MAX; - j++, mask <<= 1) { - if ((mask & policer_update_mask) == 0) - continue; - - memcpy(&flow->params.p[j], - &flow_params->p[j], - sizeof(flow_params->p[j])); - } - - if (port_update) - flow->params.port_id = flow_params->port_id; - - flow->entry_ptr = entry_ptr; - } - - /* Free response */ - app_msg_free(app, rsp); - rte_free(req_flow_id); - rte_free(req_entry_ptr); - - return status; -} - -int -app_pipeline_fa_dscp_config(struct app_params *app, - uint32_t pipeline_id, - uint32_t dscp, - uint32_t traffic_class, - enum rte_meter_color color) -{ - struct app_pipeline_fa *p; - - struct pipeline_fa_dscp_config_msg_req *req; - struct pipeline_fa_dscp_config_msg_rsp *rsp; - - /* Check input arguments */ - if ((app == NULL) || - (dscp >= PIPELINE_FA_N_DSCP) || - (traffic_class >= PIPELINE_FA_N_TC_MAX) || - (color >= e_RTE_METER_COLORS)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, - &pipeline_flow_actions); - if (p == NULL) - return -1; - - if (p->params.dscp_enabled == 0) - return -1; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FA_MSG_REQ_DSCP_CONFIG; - req->dscp = dscp; - req->traffic_class = traffic_class; - req->color = color; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response */ - if (rsp->status) { - app_msg_free(app, rsp); - return -1; - } - - /* Commit DSCP */ - p->dscp[dscp].traffic_class = traffic_class; - p->dscp[dscp].color = color; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_fa_flow_policer_stats_read(struct app_params *app, - uint32_t pipeline_id, - uint32_t flow_id, - uint32_t policer_id, - int clear, - struct pipeline_fa_policer_stats *stats) -{ - struct app_pipeline_fa *p; - struct app_pipeline_fa_flow *flow; - - struct pipeline_fa_policer_stats_msg_req *req; - struct pipeline_fa_policer_stats_msg_rsp *rsp; - - /* Check input arguments */ - if ((app == NULL) || (stats == NULL)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, - &pipeline_flow_actions); - if (p == NULL) - return -1; - - flow_id %= p->params.n_flows; - flow = &p->flows[flow_id]; - - if ((policer_id >= p->params.n_meters_per_flow) || - (flow->entry_ptr == NULL)) - return -1; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FA_MSG_REQ_POLICER_STATS_READ; - req->entry_ptr = flow->entry_ptr; - req->policer_id = policer_id; - req->clear = clear; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response */ - if (rsp->status) { - app_msg_free(app, rsp); - return -1; - } - - memcpy(stats, &rsp->stats, sizeof(*stats)); - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -static const char * -color_to_string(enum rte_meter_color color) -{ - switch (color) { - case e_RTE_METER_GREEN: return "G"; - case e_RTE_METER_YELLOW: return "Y"; - case e_RTE_METER_RED: return "R"; - default: return "?"; - } -} - -static int -string_to_color(char *s, enum rte_meter_color *c) -{ - if (strcmp(s, "G") == 0) { - *c = e_RTE_METER_GREEN; - return 0; - } - - if (strcmp(s, "Y") == 0) { - *c = e_RTE_METER_YELLOW; - return 0; - } - - if (strcmp(s, "R") == 0) { - *c = e_RTE_METER_RED; - return 0; - } - - return -1; -} - -static const char * -policer_action_to_string(struct pipeline_fa_policer_action *a) -{ - if (a->drop) - return "D"; - - return color_to_string(a->color); -} - -static int -string_to_policer_action(char *s, struct pipeline_fa_policer_action *a) -{ - if (strcmp(s, "G") == 0) { - a->drop = 0; - a->color = e_RTE_METER_GREEN; - return 0; - } - - if (strcmp(s, "Y") == 0) { - a->drop = 0; - a->color = e_RTE_METER_YELLOW; - return 0; - } - - if (strcmp(s, "R") == 0) { - a->drop = 0; - a->color = e_RTE_METER_RED; - return 0; - } - - if (strcmp(s, "D") == 0) { - a->drop = 1; - a->color = e_RTE_METER_GREEN; - return 0; - } - - return -1; -} - -static void -print_flow(struct app_pipeline_fa *p, - uint32_t flow_id, - struct app_pipeline_fa_flow *flow) -{ - uint32_t i; - - printf("Flow ID = %" PRIu32 "\n", flow_id); - - for (i = 0; i < p->params.n_meters_per_flow; i++) { - struct rte_meter_trtcm_params *meter = &flow->params.m[i]; - struct pipeline_fa_policer_params *policer = &flow->params.p[i]; - - printf("\ttrTCM [CIR = %" PRIu64 - ", CBS = %" PRIu64 ", PIR = %" PRIu64 - ", PBS = %" PRIu64 "] Policer [G : %s, Y : %s, R : %s]\n", - meter->cir, - meter->cbs, - meter->pir, - meter->pbs, - policer_action_to_string(&policer->action[e_RTE_METER_GREEN]), - policer_action_to_string(&policer->action[e_RTE_METER_YELLOW]), - policer_action_to_string(&policer->action[e_RTE_METER_RED])); - } - - printf("\tPort %u (entry_ptr = %p)\n", - flow->params.port_id, - flow->entry_ptr); -} - - -static int -app_pipeline_fa_flow_ls(struct app_params *app, - uint32_t pipeline_id) -{ - struct app_pipeline_fa *p; - uint32_t i; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, - &pipeline_flow_actions); - if (p == NULL) - return -1; - - for (i = 0; i < p->params.n_flows; i++) { - struct app_pipeline_fa_flow *flow = &p->flows[i]; - - print_flow(p, i, flow); - } - - return 0; -} - -static int -app_pipeline_fa_dscp_ls(struct app_params *app, - uint32_t pipeline_id) -{ - struct app_pipeline_fa *p; - uint32_t i; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, - &pipeline_flow_actions); - if (p == NULL) - return -1; - - if (p->params.dscp_enabled == 0) - return -1; - - for (i = 0; i < RTE_DIM(p->dscp); i++) { - struct app_pipeline_fa_dscp *dscp = &p->dscp[i]; - - printf("DSCP = %2" PRIu32 ": Traffic class = %" PRIu32 - ", Color = %s\n", - i, - dscp->traffic_class, - color_to_string(dscp->color)); - } - - return 0; -} - -int -app_pipeline_fa_load_file(char *filename, - uint32_t *flow_ids, - struct pipeline_fa_flow_params *p, - uint32_t *n_flows, - uint32_t *line) -{ - FILE *f = NULL; - char file_buf[1024]; - uint32_t i, l; - - /* Check input arguments */ - if ((filename == NULL) || - (flow_ids == NULL) || - (p == NULL) || - (n_flows == NULL) || - (*n_flows == 0) || - (line == NULL)) { - if (line) - *line = 0; - return -1; - } - - /* Open input file */ - f = fopen(filename, "r"); - if (f == NULL) { - *line = 0; - return -1; - } - - /* Read file */ - for (i = 0, l = 1; i < *n_flows; l++) { - char *tokens[64]; - uint32_t n_tokens = RTE_DIM(tokens); - - int status; - - if (fgets(file_buf, sizeof(file_buf), f) == NULL) - break; - - status = parse_tokenize_string(file_buf, tokens, &n_tokens); - if (status) - goto error1; - - if ((n_tokens == 0) || (tokens[0][0] == '#')) - continue; - - - if ((n_tokens != 64) || - /* flow */ - strcmp(tokens[0], "flow") || - parser_read_uint32(&flow_ids[i], tokens[1]) || - - /* meter & policer 0 */ - strcmp(tokens[2], "meter") || - strcmp(tokens[3], "0") || - strcmp(tokens[4], "trtcm") || - parser_read_uint64(&p[i].m[0].cir, tokens[5]) || - parser_read_uint64(&p[i].m[0].pir, tokens[6]) || - parser_read_uint64(&p[i].m[0].cbs, tokens[7]) || - parser_read_uint64(&p[i].m[0].pbs, tokens[8]) || - strcmp(tokens[9], "policer") || - strcmp(tokens[10], "0") || - strcmp(tokens[11], "g") || - string_to_policer_action(tokens[12], - &p[i].p[0].action[e_RTE_METER_GREEN]) || - strcmp(tokens[13], "y") || - string_to_policer_action(tokens[14], - &p[i].p[0].action[e_RTE_METER_YELLOW]) || - strcmp(tokens[15], "r") || - string_to_policer_action(tokens[16], - &p[i].p[0].action[e_RTE_METER_RED]) || - - /* meter & policer 1 */ - strcmp(tokens[17], "meter") || - strcmp(tokens[18], "1") || - strcmp(tokens[19], "trtcm") || - parser_read_uint64(&p[i].m[1].cir, tokens[20]) || - parser_read_uint64(&p[i].m[1].pir, tokens[21]) || - parser_read_uint64(&p[i].m[1].cbs, tokens[22]) || - parser_read_uint64(&p[i].m[1].pbs, tokens[23]) || - strcmp(tokens[24], "policer") || - strcmp(tokens[25], "1") || - strcmp(tokens[26], "g") || - string_to_policer_action(tokens[27], - &p[i].p[1].action[e_RTE_METER_GREEN]) || - strcmp(tokens[28], "y") || - string_to_policer_action(tokens[29], - &p[i].p[1].action[e_RTE_METER_YELLOW]) || - strcmp(tokens[30], "r") || - string_to_policer_action(tokens[31], - &p[i].p[1].action[e_RTE_METER_RED]) || - - /* meter & policer 2 */ - strcmp(tokens[32], "meter") || - strcmp(tokens[33], "2") || - strcmp(tokens[34], "trtcm") || - parser_read_uint64(&p[i].m[2].cir, tokens[35]) || - parser_read_uint64(&p[i].m[2].pir, tokens[36]) || - parser_read_uint64(&p[i].m[2].cbs, tokens[37]) || - parser_read_uint64(&p[i].m[2].pbs, tokens[38]) || - strcmp(tokens[39], "policer") || - strcmp(tokens[40], "2") || - strcmp(tokens[41], "g") || - string_to_policer_action(tokens[42], - &p[i].p[2].action[e_RTE_METER_GREEN]) || - strcmp(tokens[43], "y") || - string_to_policer_action(tokens[44], - &p[i].p[2].action[e_RTE_METER_YELLOW]) || - strcmp(tokens[45], "r") || - string_to_policer_action(tokens[46], - &p[i].p[2].action[e_RTE_METER_RED]) || - - /* meter & policer 3 */ - strcmp(tokens[47], "meter") || - strcmp(tokens[48], "3") || - strcmp(tokens[49], "trtcm") || - parser_read_uint64(&p[i].m[3].cir, tokens[50]) || - parser_read_uint64(&p[i].m[3].pir, tokens[51]) || - parser_read_uint64(&p[i].m[3].cbs, tokens[52]) || - parser_read_uint64(&p[i].m[3].pbs, tokens[53]) || - strcmp(tokens[54], "policer") || - strcmp(tokens[55], "3") || - strcmp(tokens[56], "g") || - string_to_policer_action(tokens[57], - &p[i].p[3].action[e_RTE_METER_GREEN]) || - strcmp(tokens[58], "y") || - string_to_policer_action(tokens[59], - &p[i].p[3].action[e_RTE_METER_YELLOW]) || - strcmp(tokens[60], "r") || - string_to_policer_action(tokens[61], - &p[i].p[3].action[e_RTE_METER_RED]) || - - /* port */ - strcmp(tokens[62], "port") || - parser_read_uint32(&p[i].port_id, tokens[63])) - goto error1; - - i++; - } - - /* Close file */ - *n_flows = i; - fclose(f); - return 0; - -error1: - *line = l; - fclose(f); - return -1; -} - -/* - * action - * - * flow meter, policer and output port configuration: - * p <pipelineid> action flow <flowid> meter <meterid> trtcm <cir> <pir> <cbs> <pbs> - * - * p <pipelineid> action flow <flowid> policer <policerid> g <gaction> y <yaction> r <raction> - * <action> is one of the following: - * G = recolor to green - * Y = recolor as yellow - * R = recolor as red - * D = drop - * - * p <pipelineid> action flow <flowid> port <port ID> - * - * p <pipelineid> action flow bulk <file> - * - * flow policer stats read: - * p <pipelineid> action flow <flowid> stats - * - * flow ls: - * p <pipelineid> action flow ls - * - * dscp table configuration: - * p <pipelineid> action dscp <dscpid> class <class ID> color <color> - * - * dscp table ls: - * p <pipelineid> action dscp ls -**/ - -struct cmd_action_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t action_string; - cmdline_multi_string_t multi_string; -}; - -static void -cmd_action_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_action_result *params = parsed_result; - struct app_params *app = data; - - char *tokens[16]; - uint32_t n_tokens = RTE_DIM(tokens); - int status; - - status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); - if (status != 0) { - printf(CMD_MSG_TOO_MANY_ARGS, "action"); - return; - } - - /* action flow meter */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "flow") == 0) && - strcmp(tokens[1], "bulk") && - strcmp(tokens[1], "ls") && - (strcmp(tokens[2], "meter") == 0)) { - struct pipeline_fa_flow_params flow_params; - uint32_t flow_id, meter_id; - - if (n_tokens != 9) { - printf(CMD_MSG_MISMATCH_ARGS, "action flow meter"); - return; - } - - memset(&flow_params, 0, sizeof(flow_params)); - - if (parser_read_uint32(&flow_id, tokens[1])) { - printf(CMD_MSG_INVALID_ARG, "flowid"); - return; - } - - if (parser_read_uint32(&meter_id, tokens[3]) || - (meter_id >= PIPELINE_FA_N_TC_MAX)) { - printf(CMD_MSG_INVALID_ARG, "meterid"); - return; - } - - if (strcmp(tokens[4], "trtcm")) { - printf(CMD_MSG_ARG_NOT_FOUND, "trtcm"); - return; - } - - if (parser_read_uint64(&flow_params.m[meter_id].cir, tokens[5])) { - printf(CMD_MSG_INVALID_ARG, "cir"); - return; - } - - if (parser_read_uint64(&flow_params.m[meter_id].pir, tokens[6])) { - printf(CMD_MSG_INVALID_ARG, "pir"); - return; - } - - if (parser_read_uint64(&flow_params.m[meter_id].cbs, tokens[7])) { - printf(CMD_MSG_INVALID_ARG, "cbs"); - return; - } - - if (parser_read_uint64(&flow_params.m[meter_id].pbs, tokens[8])) { - printf(CMD_MSG_INVALID_ARG, "pbs"); - return; - } - - status = app_pipeline_fa_flow_config(app, - params->pipeline_id, - flow_id, - 1 << meter_id, - 0, - 0, - &flow_params); - if (status) - printf(CMD_MSG_FAIL, "action flow meter"); - - return; - } /* action flow meter */ - - /* action flow policer */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "flow") == 0) && - strcmp(tokens[1], "bulk") && - strcmp(tokens[1], "ls") && - (strcmp(tokens[2], "policer") == 0)) { - struct pipeline_fa_flow_params flow_params; - uint32_t flow_id, policer_id; - - if (n_tokens != 10) { - printf(CMD_MSG_MISMATCH_ARGS, "action flow policer"); - return; - } - - memset(&flow_params, 0, sizeof(flow_params)); - - if (parser_read_uint32(&flow_id, tokens[1])) { - printf(CMD_MSG_INVALID_ARG, "flowid"); - return; - } - - if (parser_read_uint32(&policer_id, tokens[3]) || - (policer_id >= PIPELINE_FA_N_TC_MAX)) { - printf(CMD_MSG_INVALID_ARG, "policerid"); - return; - } - - if (strcmp(tokens[4], "g")) { - printf(CMD_MSG_ARG_NOT_FOUND, "g"); - return; - } - - if (string_to_policer_action(tokens[5], - &flow_params.p[policer_id].action[e_RTE_METER_GREEN])) { - printf(CMD_MSG_INVALID_ARG, "gaction"); - return; - } - - if (strcmp(tokens[6], "y")) { - printf(CMD_MSG_ARG_NOT_FOUND, "y"); - return; - } - - if (string_to_policer_action(tokens[7], - &flow_params.p[policer_id].action[e_RTE_METER_YELLOW])) { - printf(CMD_MSG_INVALID_ARG, "yaction"); - return; - } - - if (strcmp(tokens[8], "r")) { - printf(CMD_MSG_ARG_NOT_FOUND, "r"); - return; - } - - if (string_to_policer_action(tokens[9], - &flow_params.p[policer_id].action[e_RTE_METER_RED])) { - printf(CMD_MSG_INVALID_ARG, "raction"); - return; - } - - status = app_pipeline_fa_flow_config(app, - params->pipeline_id, - flow_id, - 0, - 1 << policer_id, - 0, - &flow_params); - if (status != 0) - printf(CMD_MSG_FAIL, "action flow policer"); - - return; - } /* action flow policer */ - - /* action flow port */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "flow") == 0) && - strcmp(tokens[1], "bulk") && - strcmp(tokens[1], "ls") && - (strcmp(tokens[2], "port") == 0)) { - struct pipeline_fa_flow_params flow_params; - uint32_t flow_id, port_id; - - if (n_tokens != 4) { - printf(CMD_MSG_MISMATCH_ARGS, "action flow port"); - return; - } - - memset(&flow_params, 0, sizeof(flow_params)); - - if (parser_read_uint32(&flow_id, tokens[1])) { - printf(CMD_MSG_INVALID_ARG, "flowid"); - return; - } - - if (parser_read_uint32(&port_id, tokens[3])) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - flow_params.port_id = port_id; - - status = app_pipeline_fa_flow_config(app, - params->pipeline_id, - flow_id, - 0, - 0, - 1, - &flow_params); - if (status) - printf(CMD_MSG_FAIL, "action flow port"); - - return; - } /* action flow port */ - - /* action flow stats */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "flow") == 0) && - strcmp(tokens[1], "bulk") && - strcmp(tokens[1], "ls") && - (strcmp(tokens[2], "stats") == 0)) { - struct pipeline_fa_policer_stats stats; - uint32_t flow_id, policer_id; - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "action flow stats"); - return; - } - - if (parser_read_uint32(&flow_id, tokens[1])) { - printf(CMD_MSG_INVALID_ARG, "flowid"); - return; - } - - for (policer_id = 0; - policer_id < PIPELINE_FA_N_TC_MAX; - policer_id++) { - status = app_pipeline_fa_flow_policer_stats_read(app, - params->pipeline_id, - flow_id, - policer_id, - 1, - &stats); - if (status != 0) { - printf(CMD_MSG_FAIL, "action flow stats"); - return; - } - - /* Display stats */ - printf("\tPolicer: %" PRIu32 - "\tPkts G: %" PRIu64 - "\tPkts Y: %" PRIu64 - "\tPkts R: %" PRIu64 - "\tPkts D: %" PRIu64 "\n", - policer_id, - stats.n_pkts[e_RTE_METER_GREEN], - stats.n_pkts[e_RTE_METER_YELLOW], - stats.n_pkts[e_RTE_METER_RED], - stats.n_pkts_drop); - } - - return; - } /* action flow stats */ - - /* action flow bulk */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "flow") == 0) && - (strcmp(tokens[1], "bulk") == 0)) { - struct pipeline_fa_flow_params *flow_params; - uint32_t *flow_ids, n_flows, line; - char *filename; - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "action flow bulk"); - return; - } - - filename = tokens[2]; - - n_flows = APP_PIPELINE_FA_MAX_RECORDS_IN_FILE; - flow_ids = malloc(n_flows * sizeof(uint32_t)); - if (flow_ids == NULL) { - printf(CMD_MSG_OUT_OF_MEMORY); - return; - } - - flow_params = malloc(n_flows * sizeof(struct pipeline_fa_flow_params)); - if (flow_params == NULL) { - printf(CMD_MSG_OUT_OF_MEMORY); - free(flow_ids); - return; - } - - status = app_pipeline_fa_load_file(filename, - flow_ids, - flow_params, - &n_flows, - &line); - if (status) { - printf(CMD_MSG_FILE_ERR, filename, line); - free(flow_params); - free(flow_ids); - return; - } - - status = app_pipeline_fa_flow_config_bulk(app, - params->pipeline_id, - flow_ids, - n_flows, - 0xF, - 0xF, - 1, - flow_params); - if (status) - printf(CMD_MSG_FAIL, "action flow bulk"); - - free(flow_params); - free(flow_ids); - return; - } /* action flow bulk */ - - /* action flow ls */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "flow") == 0) && - (strcmp(tokens[1], "ls") == 0)) { - if (n_tokens != 2) { - printf(CMD_MSG_MISMATCH_ARGS, "action flow ls"); - return; - } - - status = app_pipeline_fa_flow_ls(app, - params->pipeline_id); - if (status) - printf(CMD_MSG_FAIL, "action flow ls"); - - return; - } /* action flow ls */ - - /* action dscp */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "dscp") == 0) && - strcmp(tokens[1], "ls")) { - uint32_t dscp_id, tc_id; - enum rte_meter_color color; - - if (n_tokens != 6) { - printf(CMD_MSG_MISMATCH_ARGS, "action dscp"); - return; - } - - if (parser_read_uint32(&dscp_id, tokens[1])) { - printf(CMD_MSG_INVALID_ARG, "dscpid"); - return; - } - - if (strcmp(tokens[2], "class")) { - printf(CMD_MSG_ARG_NOT_FOUND, "class"); - return; - } - - if (parser_read_uint32(&tc_id, tokens[3])) { - printf(CMD_MSG_INVALID_ARG, "classid"); - return; - } - - if (strcmp(tokens[4], "color")) { - printf(CMD_MSG_ARG_NOT_FOUND, "color"); - return; - } - - if (string_to_color(tokens[5], &color)) { - printf(CMD_MSG_INVALID_ARG, "colorid"); - return; - } - - status = app_pipeline_fa_dscp_config(app, - params->pipeline_id, - dscp_id, - tc_id, - color); - if (status != 0) - printf(CMD_MSG_FAIL, "action dscp"); - - return; - } /* action dscp */ - - /* action dscp ls */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "dscp") == 0) && - (strcmp(tokens[1], "ls") == 0)) { - if (n_tokens != 2) { - printf(CMD_MSG_MISMATCH_ARGS, "action dscp ls"); - return; - } - - status = app_pipeline_fa_dscp_ls(app, - params->pipeline_id); - if (status) - printf(CMD_MSG_FAIL, "action dscp ls"); - - return; - } /* action dscp ls */ - - printf(CMD_MSG_FAIL, "action"); -} - -static cmdline_parse_token_string_t cmd_action_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_action_result, p_string, "p"); - -static cmdline_parse_token_num_t cmd_action_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_action_result, pipeline_id, UINT32); - -static cmdline_parse_token_string_t cmd_action_action_string = - TOKEN_STRING_INITIALIZER(struct cmd_action_result, action_string, "action"); - -static cmdline_parse_token_string_t cmd_action_multi_string = - TOKEN_STRING_INITIALIZER(struct cmd_action_result, multi_string, - TOKEN_STRING_MULTI); - -cmdline_parse_inst_t cmd_action = { - .f = cmd_action_parsed, - .data = NULL, - .help_str = "flow actions (meter, policer, policer stats, dscp table)", - .tokens = { - (void *) &cmd_action_p_string, - (void *) &cmd_action_pipeline_id, - (void *) &cmd_action_action_string, - (void *) &cmd_action_multi_string, - NULL, - }, -}; - -static cmdline_parse_ctx_t pipeline_cmds[] = { - (cmdline_parse_inst_t *) &cmd_action, - NULL, -}; - -static struct pipeline_fe_ops pipeline_flow_actions_fe_ops = { - .f_init = app_pipeline_fa_init, - .f_post_init = NULL, - .f_free = app_pipeline_fa_free, - .f_track = app_pipeline_track_default, - .cmds = pipeline_cmds, -}; - -struct pipeline_type pipeline_flow_actions = { - .name = "FLOW_ACTIONS", - .be_ops = &pipeline_flow_actions_be_ops, - .fe_ops = &pipeline_flow_actions_fe_ops, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.h b/examples/ip_pipeline/pipeline/pipeline_flow_actions.h deleted file mode 100644 index 885923e4..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_FLOW_ACTIONS_H__ -#define __INCLUDE_PIPELINE_FLOW_ACTIONS_H__ - -#include <rte_meter.h> - -#include "pipeline.h" -#include "pipeline_flow_actions_be.h" - -int -app_pipeline_fa_flow_config(struct app_params *app, - uint32_t pipeline_id, - uint32_t flow_id, - uint32_t meter_update_mask, - uint32_t policer_update_mask, - uint32_t port_update, - struct pipeline_fa_flow_params *params); - -int -app_pipeline_fa_flow_config_bulk(struct app_params *app, - uint32_t pipeline_id, - uint32_t *flow_id, - uint32_t n_flows, - uint32_t meter_update_mask, - uint32_t policer_update_mask, - uint32_t port_update, - struct pipeline_fa_flow_params *params); - -int -app_pipeline_fa_dscp_config(struct app_params *app, - uint32_t pipeline_id, - uint32_t dscp, - uint32_t traffic_class, - enum rte_meter_color color); - -int -app_pipeline_fa_flow_policer_stats_read(struct app_params *app, - uint32_t pipeline_id, - uint32_t flow_id, - uint32_t policer_id, - int clear, - struct pipeline_fa_policer_stats *stats); - -#ifndef APP_PIPELINE_FA_MAX_RECORDS_IN_FILE -#define APP_PIPELINE_FA_MAX_RECORDS_IN_FILE 65536 -#endif - -int -app_pipeline_fa_load_file(char *filename, - uint32_t *flow_ids, - struct pipeline_fa_flow_params *p, - uint32_t *n_flows, - uint32_t *line); - -extern struct pipeline_type pipeline_flow_actions; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c deleted file mode 100644 index 9599b7d8..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c +++ /dev/null @@ -1,960 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <string.h> - -#include <rte_common.h> -#include <rte_malloc.h> -#include <rte_cycles.h> -#include <rte_table_array.h> -#include <rte_byteorder.h> -#include <rte_ip.h> - -#include "pipeline_actions_common.h" -#include "pipeline_flow_actions_be.h" -#include "parser.h" -#include "hash_func.h" - -int -pipeline_fa_flow_params_set_default(struct pipeline_fa_flow_params *params) -{ - uint32_t i; - - if (params == NULL) - return -1; - - for (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) { - struct rte_meter_trtcm_params *m = ¶ms->m[i]; - - m->cir = 1; - m->cbs = 1; - m->pir = 1; - m->pbs = 2; - } - - for (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) { - struct pipeline_fa_policer_params *p = ¶ms->p[i]; - uint32_t j; - - for (j = 0; j < e_RTE_METER_COLORS; j++) { - struct pipeline_fa_policer_action *a = &p->action[j]; - - a->drop = 0; - a->color = (enum rte_meter_color) j; - } - } - - params->port_id = 0; - - return 0; -} - -struct dscp_entry { - uint32_t traffic_class; - enum rte_meter_color color; -}; - -struct pipeline_flow_actions { - struct pipeline p; - struct pipeline_fa_params params; - pipeline_msg_req_handler custom_handlers[PIPELINE_FA_MSG_REQS]; - - struct dscp_entry dscp[PIPELINE_FA_N_DSCP]; -} __rte_cache_aligned; - -static void * -pipeline_fa_msg_req_custom_handler(struct pipeline *p, void *msg); - -static pipeline_msg_req_handler handlers[] = { - [PIPELINE_MSG_REQ_PING] = - pipeline_msg_req_ping_handler, - [PIPELINE_MSG_REQ_STATS_PORT_IN] = - pipeline_msg_req_stats_port_in_handler, - [PIPELINE_MSG_REQ_STATS_PORT_OUT] = - pipeline_msg_req_stats_port_out_handler, - [PIPELINE_MSG_REQ_STATS_TABLE] = - pipeline_msg_req_stats_table_handler, - [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = - pipeline_msg_req_port_in_enable_handler, - [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = - pipeline_msg_req_port_in_disable_handler, - [PIPELINE_MSG_REQ_CUSTOM] = - pipeline_fa_msg_req_custom_handler, -}; - -static void * -pipeline_fa_msg_req_flow_config_handler(struct pipeline *p, void *msg); - -static void * -pipeline_fa_msg_req_flow_config_bulk_handler(struct pipeline *p, void *msg); - -static void * -pipeline_fa_msg_req_dscp_config_handler(struct pipeline *p, void *msg); - -static void * -pipeline_fa_msg_req_policer_stats_read_handler(struct pipeline *p, void *msg); - -static pipeline_msg_req_handler custom_handlers[] = { - [PIPELINE_FA_MSG_REQ_FLOW_CONFIG] = - pipeline_fa_msg_req_flow_config_handler, - [PIPELINE_FA_MSG_REQ_FLOW_CONFIG_BULK] = - pipeline_fa_msg_req_flow_config_bulk_handler, - [PIPELINE_FA_MSG_REQ_DSCP_CONFIG] = - pipeline_fa_msg_req_dscp_config_handler, - [PIPELINE_FA_MSG_REQ_POLICER_STATS_READ] = - pipeline_fa_msg_req_policer_stats_read_handler, -}; - -/* - * Flow table - */ -struct meter_policer { - struct rte_meter_trtcm meter; - struct pipeline_fa_policer_params policer; - struct pipeline_fa_policer_stats stats; -}; - -struct flow_table_entry { - struct rte_pipeline_table_entry head; - struct meter_policer mp[PIPELINE_FA_N_TC_MAX]; -}; - -static int -flow_table_entry_set_meter(struct flow_table_entry *entry, - uint32_t meter_id, - struct pipeline_fa_flow_params *params) -{ - struct rte_meter_trtcm *meter = &entry->mp[meter_id].meter; - struct rte_meter_trtcm_params *meter_params = ¶ms->m[meter_id]; - - return rte_meter_trtcm_config(meter, meter_params); -} - -static void -flow_table_entry_set_policer(struct flow_table_entry *entry, - uint32_t policer_id, - struct pipeline_fa_flow_params *params) -{ - struct pipeline_fa_policer_params *p0 = &entry->mp[policer_id].policer; - struct pipeline_fa_policer_params *p1 = ¶ms->p[policer_id]; - - memcpy(p0, p1, sizeof(*p0)); -} - -static void -flow_table_entry_set_port_id(struct pipeline_flow_actions *p, - struct flow_table_entry *entry, - struct pipeline_fa_flow_params *params) -{ - entry->head.action = RTE_PIPELINE_ACTION_PORT; - entry->head.port_id = p->p.port_out_id[params->port_id]; -} - -static int -flow_table_entry_set_default(struct pipeline_flow_actions *p, - struct flow_table_entry *entry) -{ - struct pipeline_fa_flow_params params; - uint32_t i; - - pipeline_fa_flow_params_set_default(¶ms); - - memset(entry, 0, sizeof(*entry)); - - flow_table_entry_set_port_id(p, entry, ¶ms); - - for (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) { - int status; - - status = flow_table_entry_set_meter(entry, i, ¶ms); - if (status) - return status; - } - - for (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) - flow_table_entry_set_policer(entry, i, ¶ms); - - return 0; -} - -static inline uint64_t -pkt_work( - struct rte_mbuf *pkt, - struct rte_pipeline_table_entry *table_entry, - void *arg, - uint64_t time) -{ - struct pipeline_flow_actions *p = arg; - struct flow_table_entry *entry = - (struct flow_table_entry *) table_entry; - - struct ipv4_hdr *pkt_ip = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT32_PTR(pkt, p->params.ip_hdr_offset); - enum rte_meter_color *pkt_color = (enum rte_meter_color *) - RTE_MBUF_METADATA_UINT32_PTR(pkt, p->params.color_offset); - - /* Read (IP header) */ - uint32_t total_length = rte_bswap16(pkt_ip->total_length); - uint32_t dscp = pkt_ip->type_of_service >> 2; - - uint32_t tc = p->dscp[dscp].traffic_class; - enum rte_meter_color color = p->dscp[dscp].color; - - struct rte_meter_trtcm *meter = &entry->mp[tc].meter; - struct pipeline_fa_policer_params *policer = &entry->mp[tc].policer; - struct pipeline_fa_policer_stats *stats = &entry->mp[tc].stats; - - /* Read (entry), compute */ - enum rte_meter_color color2 = rte_meter_trtcm_color_aware_check(meter, - time, - total_length, - color); - - enum rte_meter_color color3 = policer->action[color2].color; - uint64_t drop = policer->action[color2].drop; - - /* Read (entry), write (entry, color) */ - stats->n_pkts[color3] += drop ^ 1LLU; - stats->n_pkts_drop += drop; - *pkt_color = color3; - - return drop; -} - -static inline uint64_t -pkt4_work( - struct rte_mbuf **pkts, - struct rte_pipeline_table_entry **table_entries, - void *arg, - uint64_t time) -{ - struct pipeline_flow_actions *p = arg; - - struct flow_table_entry *entry0 = - (struct flow_table_entry *) table_entries[0]; - struct flow_table_entry *entry1 = - (struct flow_table_entry *) table_entries[1]; - struct flow_table_entry *entry2 = - (struct flow_table_entry *) table_entries[2]; - struct flow_table_entry *entry3 = - (struct flow_table_entry *) table_entries[3]; - - struct ipv4_hdr *pkt0_ip = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT32_PTR(pkts[0], p->params.ip_hdr_offset); - struct ipv4_hdr *pkt1_ip = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT32_PTR(pkts[1], p->params.ip_hdr_offset); - struct ipv4_hdr *pkt2_ip = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT32_PTR(pkts[2], p->params.ip_hdr_offset); - struct ipv4_hdr *pkt3_ip = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT32_PTR(pkts[3], p->params.ip_hdr_offset); - - enum rte_meter_color *pkt0_color = (enum rte_meter_color *) - RTE_MBUF_METADATA_UINT32_PTR(pkts[0], p->params.color_offset); - enum rte_meter_color *pkt1_color = (enum rte_meter_color *) - RTE_MBUF_METADATA_UINT32_PTR(pkts[1], p->params.color_offset); - enum rte_meter_color *pkt2_color = (enum rte_meter_color *) - RTE_MBUF_METADATA_UINT32_PTR(pkts[2], p->params.color_offset); - enum rte_meter_color *pkt3_color = (enum rte_meter_color *) - RTE_MBUF_METADATA_UINT32_PTR(pkts[3], p->params.color_offset); - - /* Read (IP header) */ - uint32_t total_length0 = rte_bswap16(pkt0_ip->total_length); - uint32_t dscp0 = pkt0_ip->type_of_service >> 2; - - uint32_t total_length1 = rte_bswap16(pkt1_ip->total_length); - uint32_t dscp1 = pkt1_ip->type_of_service >> 2; - - uint32_t total_length2 = rte_bswap16(pkt2_ip->total_length); - uint32_t dscp2 = pkt2_ip->type_of_service >> 2; - - uint32_t total_length3 = rte_bswap16(pkt3_ip->total_length); - uint32_t dscp3 = pkt3_ip->type_of_service >> 2; - - uint32_t tc0 = p->dscp[dscp0].traffic_class; - enum rte_meter_color color0 = p->dscp[dscp0].color; - - uint32_t tc1 = p->dscp[dscp1].traffic_class; - enum rte_meter_color color1 = p->dscp[dscp1].color; - - uint32_t tc2 = p->dscp[dscp2].traffic_class; - enum rte_meter_color color2 = p->dscp[dscp2].color; - - uint32_t tc3 = p->dscp[dscp3].traffic_class; - enum rte_meter_color color3 = p->dscp[dscp3].color; - - struct rte_meter_trtcm *meter0 = &entry0->mp[tc0].meter; - struct pipeline_fa_policer_params *policer0 = &entry0->mp[tc0].policer; - struct pipeline_fa_policer_stats *stats0 = &entry0->mp[tc0].stats; - - struct rte_meter_trtcm *meter1 = &entry1->mp[tc1].meter; - struct pipeline_fa_policer_params *policer1 = &entry1->mp[tc1].policer; - struct pipeline_fa_policer_stats *stats1 = &entry1->mp[tc1].stats; - - struct rte_meter_trtcm *meter2 = &entry2->mp[tc2].meter; - struct pipeline_fa_policer_params *policer2 = &entry2->mp[tc2].policer; - struct pipeline_fa_policer_stats *stats2 = &entry2->mp[tc2].stats; - - struct rte_meter_trtcm *meter3 = &entry3->mp[tc3].meter; - struct pipeline_fa_policer_params *policer3 = &entry3->mp[tc3].policer; - struct pipeline_fa_policer_stats *stats3 = &entry3->mp[tc3].stats; - - /* Read (entry), compute, write (entry) */ - enum rte_meter_color color2_0 = rte_meter_trtcm_color_aware_check( - meter0, - time, - total_length0, - color0); - - enum rte_meter_color color2_1 = rte_meter_trtcm_color_aware_check( - meter1, - time, - total_length1, - color1); - - enum rte_meter_color color2_2 = rte_meter_trtcm_color_aware_check( - meter2, - time, - total_length2, - color2); - - enum rte_meter_color color2_3 = rte_meter_trtcm_color_aware_check( - meter3, - time, - total_length3, - color3); - - enum rte_meter_color color3_0 = policer0->action[color2_0].color; - enum rte_meter_color color3_1 = policer1->action[color2_1].color; - enum rte_meter_color color3_2 = policer2->action[color2_2].color; - enum rte_meter_color color3_3 = policer3->action[color2_3].color; - - uint64_t drop0 = policer0->action[color2_0].drop; - uint64_t drop1 = policer1->action[color2_1].drop; - uint64_t drop2 = policer2->action[color2_2].drop; - uint64_t drop3 = policer3->action[color2_3].drop; - - /* Read (entry), write (entry, color) */ - stats0->n_pkts[color3_0] += drop0 ^ 1LLU; - stats0->n_pkts_drop += drop0; - - stats1->n_pkts[color3_1] += drop1 ^ 1LLU; - stats1->n_pkts_drop += drop1; - - stats2->n_pkts[color3_2] += drop2 ^ 1LLU; - stats2->n_pkts_drop += drop2; - - stats3->n_pkts[color3_3] += drop3 ^ 1LLU; - stats3->n_pkts_drop += drop3; - - *pkt0_color = color3_0; - *pkt1_color = color3_1; - *pkt2_color = color3_2; - *pkt3_color = color3_3; - - return drop0 | (drop1 << 1) | (drop2 << 2) | (drop3 << 3); -} - -PIPELINE_TABLE_AH_HIT_DROP_TIME(fa_table_ah_hit, pkt_work, pkt4_work); - -static rte_pipeline_table_action_handler_hit -get_fa_table_ah_hit(__rte_unused struct pipeline_flow_actions *p) -{ - return fa_table_ah_hit; -} - -/* - * Argument parsing - */ -int -pipeline_fa_parse_args(struct pipeline_fa_params *p, - struct pipeline_params *params) -{ - uint32_t n_flows_present = 0; - uint32_t n_meters_per_flow_present = 0; - uint32_t flow_id_offset_present = 0; - uint32_t ip_hdr_offset_present = 0; - uint32_t color_offset_present = 0; - uint32_t i; - - /* Default values */ - p->n_meters_per_flow = 1; - p->dscp_enabled = 0; - - for (i = 0; i < params->n_args; i++) { - char *arg_name = params->args_name[i]; - char *arg_value = params->args_value[i]; - - /* n_flows */ - if (strcmp(arg_name, "n_flows") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - n_flows_present == 0, params->name, - arg_name); - n_flows_present = 1; - - status = parser_read_uint32(&p->n_flows, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && - (p->n_flows != 0)), params->name, - arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* n_meters_per_flow */ - if (strcmp(arg_name, "n_meters_per_flow") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - n_meters_per_flow_present == 0, - params->name, arg_name); - n_meters_per_flow_present = 1; - - status = parser_read_uint32(&p->n_meters_per_flow, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && - (p->n_meters_per_flow != 0)), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) && - (p->n_meters_per_flow <= - PIPELINE_FA_N_TC_MAX)), params->name, - arg_name, arg_value); - - continue; - } - - /* flow_id_offset */ - if (strcmp(arg_name, "flow_id_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - flow_id_offset_present == 0, - params->name, arg_name); - flow_id_offset_present = 1; - - status = parser_read_uint32(&p->flow_id_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* ip_hdr_offset */ - if (strcmp(arg_name, "ip_hdr_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - ip_hdr_offset_present == 0, - params->name, arg_name); - ip_hdr_offset_present = 1; - - status = parser_read_uint32(&p->ip_hdr_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* color_offset */ - if (strcmp(arg_name, "color_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - color_offset_present == 0, params->name, - arg_name); - color_offset_present = 1; - - status = parser_read_uint32(&p->color_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - p->dscp_enabled = 1; - - continue; - } - - /* Unknown argument */ - PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); - } - - /* Check that mandatory arguments are present */ - PIPELINE_PARSE_ERR_MANDATORY((n_flows_present), params->name, - "n_flows"); - PIPELINE_PARSE_ERR_MANDATORY((flow_id_offset_present), - params->name, "flow_id_offset"); - PIPELINE_PARSE_ERR_MANDATORY((ip_hdr_offset_present), - params->name, "ip_hdr_offset"); - PIPELINE_PARSE_ERR_MANDATORY((color_offset_present), params->name, - "color_offset"); - - return 0; -} - -static void -dscp_init(struct pipeline_flow_actions *p) -{ - uint32_t i; - - for (i = 0; i < PIPELINE_FA_N_DSCP; i++) { - p->dscp[i].traffic_class = 0; - p->dscp[i].color = e_RTE_METER_GREEN; - } -} - -static void *pipeline_fa_init(struct pipeline_params *params, - __rte_unused void *arg) -{ - struct pipeline *p; - struct pipeline_flow_actions *p_fa; - uint32_t size, i; - - /* Check input arguments */ - if (params == NULL) - return NULL; - - if (params->n_ports_in != params->n_ports_out) - return NULL; - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP( - sizeof(struct pipeline_flow_actions)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - if (p == NULL) - return NULL; - p_fa = (struct pipeline_flow_actions *) p; - - strcpy(p->name, params->name); - p->log_level = params->log_level; - - PLOG(p, HIGH, "Flow actions"); - - /* Parse arguments */ - if (pipeline_fa_parse_args(&p_fa->params, params)) - return NULL; - - dscp_init(p_fa); - - /* Pipeline */ - { - struct rte_pipeline_params pipeline_params = { - .name = params->name, - .socket_id = params->socket_id, - .offset_port_id = 0, - }; - - p->p = rte_pipeline_create(&pipeline_params); - if (p->p == NULL) { - rte_free(p); - return NULL; - } - } - - /* Input ports */ - p->n_ports_in = params->n_ports_in; - for (i = 0; i < p->n_ports_in; i++) { - struct rte_pipeline_port_in_params port_params = { - .ops = pipeline_port_in_params_get_ops( - ¶ms->port_in[i]), - .arg_create = pipeline_port_in_params_convert( - ¶ms->port_in[i]), - .f_action = NULL, - .arg_ah = NULL, - .burst_size = params->port_in[i].burst_size, - }; - - int status = rte_pipeline_port_in_create(p->p, - &port_params, - &p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Output ports */ - p->n_ports_out = params->n_ports_out; - for (i = 0; i < p->n_ports_out; i++) { - struct rte_pipeline_port_out_params port_params = { - .ops = pipeline_port_out_params_get_ops( - ¶ms->port_out[i]), - .arg_create = pipeline_port_out_params_convert( - ¶ms->port_out[i]), - .f_action = NULL, - .arg_ah = NULL, - }; - - int status = rte_pipeline_port_out_create(p->p, - &port_params, - &p->port_out_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Tables */ - p->n_tables = 1; - { - struct rte_table_array_params table_array_params = { - .n_entries = p_fa->params.n_flows, - .offset = p_fa->params.flow_id_offset, - }; - - struct rte_pipeline_table_params table_params = { - .ops = &rte_table_array_ops, - .arg_create = &table_array_params, - .f_action_hit = get_fa_table_ah_hit(p_fa), - .f_action_miss = NULL, - .arg_ah = p_fa, - .action_data_size = - sizeof(struct flow_table_entry) - - sizeof(struct rte_pipeline_table_entry), - }; - - int status; - - status = rte_pipeline_table_create(p->p, - &table_params, - &p->table_id[0]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Connecting input ports to tables */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_connect_to_table(p->p, - p->port_in_id[i], - p->table_id[0]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Enable input ports */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_enable(p->p, - p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Initialize table entries */ - for (i = 0; i < p_fa->params.n_flows; i++) { - struct rte_table_array_key key = { - .pos = i, - }; - - struct flow_table_entry entry; - struct rte_pipeline_table_entry *entry_ptr; - int key_found, status; - - flow_table_entry_set_default(p_fa, &entry); - - status = rte_pipeline_table_entry_add(p->p, - p->table_id[0], - &key, - (struct rte_pipeline_table_entry *) &entry, - &key_found, - &entry_ptr); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Check pipeline consistency */ - if (rte_pipeline_check(p->p) < 0) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - - /* Message queues */ - p->n_msgq = params->n_msgq; - for (i = 0; i < p->n_msgq; i++) - p->msgq_in[i] = params->msgq_in[i]; - for (i = 0; i < p->n_msgq; i++) - p->msgq_out[i] = params->msgq_out[i]; - - /* Message handlers */ - memcpy(p->handlers, handlers, sizeof(p->handlers)); - memcpy(p_fa->custom_handlers, - custom_handlers, - sizeof(p_fa->custom_handlers)); - - return p; -} - -static int -pipeline_fa_free(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if (p == NULL) - return -1; - - /* Free resources */ - rte_pipeline_free(p->p); - rte_free(p); - return 0; -} - -static int -pipeline_fa_timer(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - pipeline_msg_req_handle(p); - rte_pipeline_flush(p->p); - - return 0; -} - -void * -pipeline_fa_msg_req_custom_handler(struct pipeline *p, void *msg) -{ - struct pipeline_flow_actions *p_fa = - (struct pipeline_flow_actions *) p; - struct pipeline_custom_msg_req *req = msg; - pipeline_msg_req_handler f_handle; - - f_handle = (req->subtype < PIPELINE_FA_MSG_REQS) ? - p_fa->custom_handlers[req->subtype] : - pipeline_msg_req_invalid_handler; - - if (f_handle == NULL) - f_handle = pipeline_msg_req_invalid_handler; - - return f_handle(p, req); -} - -void * -pipeline_fa_msg_req_flow_config_handler(struct pipeline *p, void *msg) -{ - struct pipeline_flow_actions *p_fa = (struct pipeline_flow_actions *) p; - struct pipeline_fa_flow_config_msg_req *req = msg; - struct pipeline_fa_flow_config_msg_rsp *rsp = msg; - struct flow_table_entry *entry; - uint32_t mask, i; - - /* Set flow table entry to default if not configured before */ - if (req->entry_ptr == NULL) { - struct rte_table_array_key key = { - .pos = req->flow_id % p_fa->params.n_flows, - }; - - struct flow_table_entry default_entry; - - int key_found, status; - - flow_table_entry_set_default(p_fa, &default_entry); - - status = rte_pipeline_table_entry_add(p->p, - p->table_id[0], - &key, - (struct rte_pipeline_table_entry *) &default_entry, - &key_found, - (struct rte_pipeline_table_entry **) &entry); - if (status) { - rsp->status = -1; - return rsp; - } - } else - entry = (struct flow_table_entry *) req->entry_ptr; - - /* Meter */ - for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) { - int status; - - if ((mask & req->meter_update_mask) == 0) - continue; - - status = flow_table_entry_set_meter(entry, i, &req->params); - if (status) { - rsp->status = -1; - return rsp; - } - } - - /* Policer */ - for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) { - if ((mask & req->policer_update_mask) == 0) - continue; - - flow_table_entry_set_policer(entry, i, &req->params); - } - - /* Port */ - if (req->port_update) - flow_table_entry_set_port_id(p_fa, entry, &req->params); - - /* Response */ - rsp->status = 0; - rsp->entry_ptr = (void *) entry; - return rsp; -} - -void * -pipeline_fa_msg_req_flow_config_bulk_handler(struct pipeline *p, void *msg) -{ - struct pipeline_flow_actions *p_fa = (struct pipeline_flow_actions *) p; - struct pipeline_fa_flow_config_bulk_msg_req *req = msg; - struct pipeline_fa_flow_config_bulk_msg_rsp *rsp = msg; - uint32_t i; - - for (i = 0; i < req->n_flows; i++) { - struct flow_table_entry *entry; - uint32_t j, mask; - - /* Set flow table entry to default if not configured before */ - if (req->entry_ptr[i] == NULL) { - struct rte_table_array_key key = { - .pos = req->flow_id[i] % p_fa->params.n_flows, - }; - - struct flow_table_entry entry_to_add; - - int key_found, status; - - flow_table_entry_set_default(p_fa, &entry_to_add); - - status = rte_pipeline_table_entry_add(p->p, - p->table_id[0], - &key, - (struct rte_pipeline_table_entry *) &entry_to_add, - &key_found, - (struct rte_pipeline_table_entry **) &entry); - if (status) { - rsp->n_flows = i; - return rsp; - } - - req->entry_ptr[i] = (void *) entry; - } else - entry = (struct flow_table_entry *) req->entry_ptr[i]; - - /* Meter */ - for (j = 0, mask = 1; - j < PIPELINE_FA_N_TC_MAX; - j++, mask <<= 1) { - int status; - - if ((mask & req->meter_update_mask) == 0) - continue; - - status = flow_table_entry_set_meter(entry, - j, &req->params[i]); - if (status) { - rsp->n_flows = i; - return rsp; - } - } - - /* Policer */ - for (j = 0, mask = 1; - j < PIPELINE_FA_N_TC_MAX; - j++, mask <<= 1) { - if ((mask & req->policer_update_mask) == 0) - continue; - - flow_table_entry_set_policer(entry, - j, &req->params[i]); - } - - /* Port */ - if (req->port_update) - flow_table_entry_set_port_id(p_fa, - entry, &req->params[i]); - } - - /* Response */ - rsp->n_flows = i; - return rsp; -} - -void * -pipeline_fa_msg_req_dscp_config_handler(struct pipeline *p, void *msg) -{ - struct pipeline_flow_actions *p_fa = (struct pipeline_flow_actions *) p; - struct pipeline_fa_dscp_config_msg_req *req = msg; - struct pipeline_fa_dscp_config_msg_rsp *rsp = msg; - - /* Check request */ - if ((req->dscp >= PIPELINE_FA_N_DSCP) || - (req->traffic_class >= PIPELINE_FA_N_TC_MAX) || - (req->color >= e_RTE_METER_COLORS)) { - rsp->status = -1; - return rsp; - } - - p_fa->dscp[req->dscp].traffic_class = req->traffic_class; - p_fa->dscp[req->dscp].color = req->color; - rsp->status = 0; - return rsp; -} - -void * -pipeline_fa_msg_req_policer_stats_read_handler(__rte_unused struct pipeline *p, - void *msg) -{ - struct pipeline_fa_policer_stats_msg_req *req = msg; - struct pipeline_fa_policer_stats_msg_rsp *rsp = msg; - - struct flow_table_entry *entry = req->entry_ptr; - uint32_t policer_id = req->policer_id; - int clear = req->clear; - - /* Check request */ - if ((req->entry_ptr == NULL) || - (req->policer_id >= PIPELINE_FA_N_TC_MAX)) { - rsp->status = -1; - return rsp; - } - - memcpy(&rsp->stats, - &entry->mp[policer_id].stats, - sizeof(rsp->stats)); - if (clear) - memset(&entry->mp[policer_id].stats, - 0, sizeof(entry->mp[policer_id].stats)); - rsp->status = 0; - return rsp; -} - -struct pipeline_be_ops pipeline_flow_actions_be_ops = { - .f_init = pipeline_fa_init, - .f_free = pipeline_fa_free, - .f_run = NULL, - .f_timer = pipeline_fa_timer, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.h b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.h deleted file mode 100644 index ef6cb263..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.h +++ /dev/null @@ -1,139 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_FLOW_ACTIONS_BE_H__ -#define __INCLUDE_PIPELINE_FLOW_ACTIONS_BE_H__ - -#include <rte_meter.h> - -#include "pipeline_common_be.h" - -#ifndef PIPELINE_FA_N_TC_MAX -#define PIPELINE_FA_N_TC_MAX 4 -#endif - -#define PIPELINE_FA_N_DSCP 64 - -struct pipeline_fa_params { - uint32_t n_flows; - uint32_t n_meters_per_flow; - uint32_t flow_id_offset; - uint32_t ip_hdr_offset; - uint32_t color_offset; - uint32_t dscp_enabled; -}; - -int -pipeline_fa_parse_args(struct pipeline_fa_params *p, - struct pipeline_params *params); - -struct pipeline_fa_policer_action { - uint32_t drop; - enum rte_meter_color color; -}; - -struct pipeline_fa_policer_params { - struct pipeline_fa_policer_action action[e_RTE_METER_COLORS]; -}; - -struct pipeline_fa_flow_params { - struct rte_meter_trtcm_params m[PIPELINE_FA_N_TC_MAX]; - struct pipeline_fa_policer_params p[PIPELINE_FA_N_TC_MAX]; - uint32_t port_id; -}; - -int -pipeline_fa_flow_params_set_default(struct pipeline_fa_flow_params *params); - -struct pipeline_fa_policer_stats { - uint64_t n_pkts[e_RTE_METER_COLORS]; - uint64_t n_pkts_drop; -}; - -enum pipeline_fa_msg_req_type { - PIPELINE_FA_MSG_REQ_FLOW_CONFIG = 0, - PIPELINE_FA_MSG_REQ_FLOW_CONFIG_BULK, - PIPELINE_FA_MSG_REQ_DSCP_CONFIG, - PIPELINE_FA_MSG_REQ_POLICER_STATS_READ, - PIPELINE_FA_MSG_REQS, -}; - -/* - * MSG FLOW CONFIG - */ -struct pipeline_fa_flow_config_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_fa_msg_req_type subtype; - - void *entry_ptr; - uint32_t flow_id; - - uint32_t meter_update_mask; - uint32_t policer_update_mask; - uint32_t port_update; - struct pipeline_fa_flow_params params; -}; - -struct pipeline_fa_flow_config_msg_rsp { - int status; - void *entry_ptr; -}; - -/* - * MSG FLOW CONFIG BULK - */ -struct pipeline_fa_flow_config_bulk_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_fa_msg_req_type subtype; - - void **entry_ptr; - uint32_t *flow_id; - uint32_t n_flows; - - uint32_t meter_update_mask; - uint32_t policer_update_mask; - uint32_t port_update; - struct pipeline_fa_flow_params *params; -}; - -struct pipeline_fa_flow_config_bulk_msg_rsp { - uint32_t n_flows; -}; - -/* - * MSG DSCP CONFIG - */ -struct pipeline_fa_dscp_config_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_fa_msg_req_type subtype; - - uint32_t dscp; - uint32_t traffic_class; - enum rte_meter_color color; -}; - -struct pipeline_fa_dscp_config_msg_rsp { - int status; -}; - -/* - * MSG POLICER STATS READ - */ -struct pipeline_fa_policer_stats_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_fa_msg_req_type subtype; - - void *entry_ptr; - uint32_t policer_id; - int clear; -}; - -struct pipeline_fa_policer_stats_msg_rsp { - int status; - struct pipeline_fa_policer_stats stats; -}; - -extern struct pipeline_be_ops pipeline_flow_actions_be_ops; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c deleted file mode 100644 index d39e0fb1..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c +++ /dev/null @@ -1,1878 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <stdio.h> -#include <string.h> -#include <sys/queue.h> -#include <netinet/in.h> -#include <unistd.h> - -#include <rte_common.h> -#include <rte_hexdump.h> -#include <rte_malloc.h> -#include <cmdline_rdline.h> -#include <cmdline_parse.h> -#include <cmdline_parse_num.h> -#include <cmdline_parse_string.h> - -#include "app.h" -#include "pipeline_common_fe.h" -#include "pipeline_flow_classification.h" -#include "hash_func.h" -#include "parser.h" - -/* - * Key conversion - */ - -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 ttl; - uint8_t proto; - uint16_t checksum; - uint32_t ip_src; - uint32_t ip_dst; - uint16_t port_src; - uint16_t port_dst; -} __attribute__((__packed__)); - -struct pkt_key_ipv6_5tuple { - uint16_t payload_length; - uint8_t proto; - uint8_t hop_limit; - uint8_t ip_src[16]; - uint8_t ip_dst[16]; - uint16_t port_src; - uint16_t port_dst; -} __attribute__((__packed__)); - -static int -app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in, - uint8_t *key_out, - uint32_t *signature) -{ - uint8_t buffer[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; - uint8_t m[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; /* key mask */ - void *key_buffer = (key_out) ? key_out : buffer; - - memset(m, 0xFF, sizeof(m)); - switch (key_in->type) { - case FLOW_KEY_QINQ: - { - struct pkt_key_qinq *qinq = key_buffer; - - qinq->ethertype_svlan = 0; - qinq->svlan = rte_cpu_to_be_16(key_in->key.qinq.svlan); - qinq->ethertype_cvlan = 0; - qinq->cvlan = rte_cpu_to_be_16(key_in->key.qinq.cvlan); - - if (signature) - *signature = (uint32_t) hash_default_key8(qinq, m, 8, 0); - return 0; - } - - case FLOW_KEY_IPV4_5TUPLE: - { - struct pkt_key_ipv4_5tuple *ipv4 = key_buffer; - - ipv4->ttl = 0; - ipv4->proto = key_in->key.ipv4_5tuple.proto; - ipv4->checksum = 0; - ipv4->ip_src = rte_cpu_to_be_32(key_in->key.ipv4_5tuple.ip_src); - ipv4->ip_dst = rte_cpu_to_be_32(key_in->key.ipv4_5tuple.ip_dst); - ipv4->port_src = rte_cpu_to_be_16(key_in->key.ipv4_5tuple.port_src); - ipv4->port_dst = rte_cpu_to_be_16(key_in->key.ipv4_5tuple.port_dst); - - if (signature) - *signature = (uint32_t) hash_default_key16(ipv4, m, 16, 0); - return 0; - } - - case FLOW_KEY_IPV6_5TUPLE: - { - struct pkt_key_ipv6_5tuple *ipv6 = key_buffer; - - memset(ipv6, 0, 64); - ipv6->payload_length = 0; - ipv6->proto = key_in->key.ipv6_5tuple.proto; - ipv6->hop_limit = 0; - memcpy(&ipv6->ip_src, &key_in->key.ipv6_5tuple.ip_src, 16); - memcpy(&ipv6->ip_dst, &key_in->key.ipv6_5tuple.ip_dst, 16); - ipv6->port_src = rte_cpu_to_be_16(key_in->key.ipv6_5tuple.port_src); - ipv6->port_dst = rte_cpu_to_be_16(key_in->key.ipv6_5tuple.port_dst); - - if (signature) - *signature = (uint32_t) hash_default_key64(ipv6, m, 64, 0); - return 0; - } - - default: - return -1; - } -} - -/* - * Flow classification pipeline - */ - -struct app_pipeline_fc_flow { - struct pipeline_fc_key key; - uint32_t port_id; - uint32_t flow_id; - uint32_t signature; - void *entry_ptr; - - TAILQ_ENTRY(app_pipeline_fc_flow) node; -}; - -#define N_BUCKETS 65536 - -struct app_pipeline_fc { - /* Parameters */ - uint32_t n_ports_in; - uint32_t n_ports_out; - - /* Flows */ - TAILQ_HEAD(, app_pipeline_fc_flow) flows[N_BUCKETS]; - uint32_t n_flows; - - /* Default flow */ - uint32_t default_flow_present; - uint32_t default_flow_port_id; - void *default_flow_entry_ptr; -}; - -static struct app_pipeline_fc_flow * -app_pipeline_fc_flow_find(struct app_pipeline_fc *p, - struct pipeline_fc_key *key) -{ - struct app_pipeline_fc_flow *f; - uint32_t signature, bucket_id; - - app_pipeline_fc_key_convert(key, NULL, &signature); - bucket_id = signature & (N_BUCKETS - 1); - - TAILQ_FOREACH(f, &p->flows[bucket_id], node) - if ((signature == f->signature) && - (memcmp(key, - &f->key, - sizeof(struct pipeline_fc_key)) == 0)) - return f; - - return NULL; -} - -static void* -app_pipeline_fc_init(struct pipeline_params *params, - __rte_unused void *arg) -{ - struct app_pipeline_fc *p; - uint32_t size, i; - - /* Check input arguments */ - if ((params == NULL) || - (params->n_ports_in == 0) || - (params->n_ports_out == 0)) - return NULL; - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fc)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - if (p == NULL) - return NULL; - - /* Initialization */ - p->n_ports_in = params->n_ports_in; - p->n_ports_out = params->n_ports_out; - - for (i = 0; i < N_BUCKETS; i++) - TAILQ_INIT(&p->flows[i]); - p->n_flows = 0; - - return (void *) p; -} - -static int -app_pipeline_fc_free(void *pipeline) -{ - struct app_pipeline_fc *p = pipeline; - uint32_t i; - - /* Check input arguments */ - if (p == NULL) - return -1; - - /* Free resources */ - for (i = 0; i < N_BUCKETS; i++) - while (!TAILQ_EMPTY(&p->flows[i])) { - struct app_pipeline_fc_flow *flow; - - flow = TAILQ_FIRST(&p->flows[i]); - TAILQ_REMOVE(&p->flows[i], flow, node); - rte_free(flow); - } - - rte_free(p); - return 0; -} - -static int -app_pipeline_fc_key_check(struct pipeline_fc_key *key) -{ - switch (key->type) { - case FLOW_KEY_QINQ: - { - uint16_t svlan = key->key.qinq.svlan; - uint16_t cvlan = key->key.qinq.cvlan; - - if ((svlan & 0xF000) || - (cvlan & 0xF000)) - return -1; - - return 0; - } - - case FLOW_KEY_IPV4_5TUPLE: - return 0; - - case FLOW_KEY_IPV6_5TUPLE: - return 0; - - default: - return -1; - } -} - -int -app_pipeline_fc_load_file_qinq(char *filename, - struct pipeline_fc_key *keys, - uint32_t *port_ids, - uint32_t *flow_ids, - uint32_t *n_keys, - uint32_t *line) -{ - FILE *f = NULL; - char file_buf[1024]; - uint32_t i, l; - - /* Check input arguments */ - if ((filename == NULL) || - (keys == NULL) || - (port_ids == NULL) || - (flow_ids == NULL) || - (n_keys == NULL) || - (*n_keys == 0) || - (line == NULL)) { - if (line) - *line = 0; - return -1; - } - - /* Open input file */ - f = fopen(filename, "r"); - if (f == NULL) { - *line = 0; - return -1; - } - - /* Read file */ - for (i = 0, l = 1; i < *n_keys; l++) { - char *tokens[32]; - uint32_t n_tokens = RTE_DIM(tokens); - - uint16_t svlan, cvlan; - uint32_t portid, flowid; - int status; - - if (fgets(file_buf, sizeof(file_buf), f) == NULL) - break; - - status = parse_tokenize_string(file_buf, tokens, &n_tokens); - if (status) - goto error1; - - if ((n_tokens == 0) || (tokens[0][0] == '#')) - continue; - - if ((n_tokens != 7) || - strcmp(tokens[0], "qinq") || - parser_read_uint16(&svlan, tokens[1]) || - parser_read_uint16(&cvlan, tokens[2]) || - strcmp(tokens[3], "port") || - parser_read_uint32(&portid, tokens[4]) || - strcmp(tokens[5], "id") || - parser_read_uint32(&flowid, tokens[6])) - goto error1; - - keys[i].type = FLOW_KEY_QINQ; - keys[i].key.qinq.svlan = svlan; - keys[i].key.qinq.cvlan = cvlan; - - port_ids[i] = portid; - flow_ids[i] = flowid; - - if (app_pipeline_fc_key_check(&keys[i])) - goto error1; - - i++; - } - - /* Close file */ - *n_keys = i; - fclose(f); - return 0; - -error1: - *line = l; - fclose(f); - return -1; -} - -int -app_pipeline_fc_load_file_ipv4(char *filename, - struct pipeline_fc_key *keys, - uint32_t *port_ids, - uint32_t *flow_ids, - uint32_t *n_keys, - uint32_t *line) -{ - FILE *f = NULL; - char file_buf[1024]; - uint32_t i, l; - - /* Check input arguments */ - if ((filename == NULL) || - (keys == NULL) || - (port_ids == NULL) || - (flow_ids == NULL) || - (n_keys == NULL) || - (*n_keys == 0) || - (line == NULL)) { - if (line) - *line = 0; - return -1; - } - - /* Open input file */ - f = fopen(filename, "r"); - if (f == NULL) { - *line = 0; - return -1; - } - - /* Read file */ - for (i = 0, l = 1; i < *n_keys; l++) { - char *tokens[32]; - uint32_t n_tokens = RTE_DIM(tokens); - - struct in_addr sipaddr, dipaddr; - uint16_t sport, dport; - uint8_t proto; - uint32_t portid, flowid; - int status; - - if (fgets(file_buf, sizeof(file_buf), f) == NULL) - break; - - status = parse_tokenize_string(file_buf, tokens, &n_tokens); - if (status) - goto error2; - - if ((n_tokens == 0) || (tokens[0][0] == '#')) - continue; - - if ((n_tokens != 10) || - strcmp(tokens[0], "ipv4") || - parse_ipv4_addr(tokens[1], &sipaddr) || - parse_ipv4_addr(tokens[2], &dipaddr) || - parser_read_uint16(&sport, tokens[3]) || - parser_read_uint16(&dport, tokens[4]) || - parser_read_uint8(&proto, tokens[5]) || - strcmp(tokens[6], "port") || - parser_read_uint32(&portid, tokens[7]) || - strcmp(tokens[8], "id") || - parser_read_uint32(&flowid, tokens[9])) - goto error2; - - keys[i].type = FLOW_KEY_IPV4_5TUPLE; - keys[i].key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr); - keys[i].key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr); - keys[i].key.ipv4_5tuple.port_src = sport; - keys[i].key.ipv4_5tuple.port_dst = dport; - keys[i].key.ipv4_5tuple.proto = proto; - - port_ids[i] = portid; - flow_ids[i] = flowid; - - if (app_pipeline_fc_key_check(&keys[i])) - goto error2; - - i++; - } - - /* Close file */ - *n_keys = i; - fclose(f); - return 0; - -error2: - *line = l; - fclose(f); - return -1; -} - -int -app_pipeline_fc_load_file_ipv6(char *filename, - struct pipeline_fc_key *keys, - uint32_t *port_ids, - uint32_t *flow_ids, - uint32_t *n_keys, - uint32_t *line) -{ - FILE *f = NULL; - char file_buf[1024]; - uint32_t i, l; - - /* Check input arguments */ - if ((filename == NULL) || - (keys == NULL) || - (port_ids == NULL) || - (flow_ids == NULL) || - (n_keys == NULL) || - (*n_keys == 0) || - (line == NULL)) { - if (line) - *line = 0; - return -1; - } - - /* Open input file */ - f = fopen(filename, "r"); - if (f == NULL) { - *line = 0; - return -1; - } - - /* Read file */ - for (i = 0, l = 1; i < *n_keys; l++) { - char *tokens[32]; - uint32_t n_tokens = RTE_DIM(tokens); - - struct in6_addr sipaddr, dipaddr; - uint16_t sport, dport; - uint8_t proto; - uint32_t portid, flowid; - int status; - - if (fgets(file_buf, sizeof(file_buf), f) == NULL) - break; - - status = parse_tokenize_string(file_buf, tokens, &n_tokens); - if (status) - goto error3; - - if ((n_tokens == 0) || (tokens[0][0] == '#')) - continue; - - if ((n_tokens != 10) || - strcmp(tokens[0], "ipv6") || - parse_ipv6_addr(tokens[1], &sipaddr) || - parse_ipv6_addr(tokens[2], &dipaddr) || - parser_read_uint16(&sport, tokens[3]) || - parser_read_uint16(&dport, tokens[4]) || - parser_read_uint8(&proto, tokens[5]) || - strcmp(tokens[6], "port") || - parser_read_uint32(&portid, tokens[7]) || - strcmp(tokens[8], "id") || - parser_read_uint32(&flowid, tokens[9])) - goto error3; - - keys[i].type = FLOW_KEY_IPV6_5TUPLE; - memcpy(keys[i].key.ipv6_5tuple.ip_src, - sipaddr.s6_addr, - sizeof(sipaddr.s6_addr)); - memcpy(keys[i].key.ipv6_5tuple.ip_dst, - dipaddr.s6_addr, - sizeof(dipaddr.s6_addr)); - keys[i].key.ipv6_5tuple.port_src = sport; - keys[i].key.ipv6_5tuple.port_dst = dport; - keys[i].key.ipv6_5tuple.proto = proto; - - port_ids[i] = portid; - flow_ids[i] = flowid; - - if (app_pipeline_fc_key_check(&keys[i])) - goto error3; - - i++; - } - - /* Close file */ - *n_keys = i; - fclose(f); - return 0; - -error3: - *line = l; - fclose(f); - return -1; -} - - - -int -app_pipeline_fc_add(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_fc_key *key, - uint32_t port_id, - uint32_t flow_id) -{ - struct app_pipeline_fc *p; - struct app_pipeline_fc_flow *flow; - - struct pipeline_fc_add_msg_req *req; - struct pipeline_fc_add_msg_rsp *rsp; - - uint32_t signature; - int new_flow; - - /* Check input arguments */ - if ((app == NULL) || - (key == NULL)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); - if (p == NULL) - return -1; - - if (port_id >= p->n_ports_out) - return -1; - - if (app_pipeline_fc_key_check(key) != 0) - return -1; - - /* Find existing flow or allocate new flow */ - flow = app_pipeline_fc_flow_find(p, key); - new_flow = (flow == NULL); - if (flow == NULL) { - flow = rte_malloc(NULL, sizeof(*flow), RTE_CACHE_LINE_SIZE); - - if (flow == NULL) - return -1; - } - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD; - app_pipeline_fc_key_convert(key, req->key, &signature); - req->port_id = port_id; - req->flow_id = flow_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) { - if (new_flow) - rte_free(flow); - return -1; - } - - /* Read response and write flow */ - if (rsp->status || - (rsp->entry_ptr == NULL) || - ((new_flow == 0) && (rsp->key_found == 0)) || - ((new_flow == 1) && (rsp->key_found == 1))) { - app_msg_free(app, rsp); - if (new_flow) - rte_free(flow); - return -1; - } - - memset(&flow->key, 0, sizeof(flow->key)); - memcpy(&flow->key, key, sizeof(flow->key)); - flow->port_id = port_id; - flow->flow_id = flow_id; - flow->signature = signature; - flow->entry_ptr = rsp->entry_ptr; - - /* Commit rule */ - if (new_flow) { - uint32_t bucket_id = signature & (N_BUCKETS - 1); - - TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow, node); - p->n_flows++; - } - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_fc_add_bulk(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_fc_key *key, - uint32_t *port_id, - uint32_t *flow_id, - uint32_t n_keys) -{ - struct app_pipeline_fc *p; - struct pipeline_fc_add_bulk_msg_req *req; - struct pipeline_fc_add_bulk_msg_rsp *rsp; - - struct app_pipeline_fc_flow **flow; - uint32_t *signature; - int *new_flow; - struct pipeline_fc_add_bulk_flow_req *flow_req; - struct pipeline_fc_add_bulk_flow_rsp *flow_rsp; - - uint32_t i; - int status; - - /* Check input arguments */ - if ((app == NULL) || - (key == NULL) || - (port_id == NULL) || - (flow_id == NULL) || - (n_keys == 0)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); - if (p == NULL) - return -1; - - for (i = 0; i < n_keys; i++) - if (port_id[i] >= p->n_ports_out) - return -1; - - for (i = 0; i < n_keys; i++) - if (app_pipeline_fc_key_check(&key[i]) != 0) - return -1; - - /* Memory allocation */ - flow = rte_malloc(NULL, - n_keys * sizeof(struct app_pipeline_fc_flow *), - RTE_CACHE_LINE_SIZE); - if (flow == NULL) - return -1; - - signature = rte_malloc(NULL, - n_keys * sizeof(uint32_t), - RTE_CACHE_LINE_SIZE); - if (signature == NULL) { - rte_free(flow); - return -1; - } - - new_flow = rte_malloc( - NULL, - n_keys * sizeof(int), - RTE_CACHE_LINE_SIZE); - if (new_flow == NULL) { - rte_free(signature); - rte_free(flow); - return -1; - } - - flow_req = rte_malloc(NULL, - n_keys * sizeof(struct pipeline_fc_add_bulk_flow_req), - RTE_CACHE_LINE_SIZE); - if (flow_req == NULL) { - rte_free(new_flow); - rte_free(signature); - rte_free(flow); - return -1; - } - - flow_rsp = rte_malloc(NULL, - n_keys * sizeof(struct pipeline_fc_add_bulk_flow_rsp), - RTE_CACHE_LINE_SIZE); - if (flow_rsp == NULL) { - rte_free(flow_req); - rte_free(new_flow); - rte_free(signature); - rte_free(flow); - return -1; - } - - /* Find existing flow or allocate new flow */ - for (i = 0; i < n_keys; i++) { - flow[i] = app_pipeline_fc_flow_find(p, &key[i]); - new_flow[i] = (flow[i] == NULL); - if (flow[i] == NULL) { - flow[i] = rte_zmalloc(NULL, - sizeof(struct app_pipeline_fc_flow), - RTE_CACHE_LINE_SIZE); - - if (flow[i] == NULL) { - uint32_t j; - - for (j = 0; j < i; j++) - if (new_flow[j]) - rte_free(flow[j]); - - rte_free(flow_rsp); - rte_free(flow_req); - rte_free(new_flow); - rte_free(signature); - rte_free(flow); - return -1; - } - } - } - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) { - for (i = 0; i < n_keys; i++) - if (new_flow[i]) - rte_free(flow[i]); - - rte_free(flow_rsp); - rte_free(flow_req); - rte_free(new_flow); - rte_free(signature); - rte_free(flow); - return -1; - } - - for (i = 0; i < n_keys; i++) { - app_pipeline_fc_key_convert(&key[i], - flow_req[i].key, - &signature[i]); - flow_req[i].port_id = port_id[i]; - flow_req[i].flow_id = flow_id[i]; - } - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK; - req->req = flow_req; - req->rsp = flow_rsp; - req->n_keys = n_keys; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, 10000); - if (rsp == NULL) { - for (i = 0; i < n_keys; i++) - if (new_flow[i]) - rte_free(flow[i]); - - rte_free(flow_rsp); - rte_free(flow_req); - rte_free(new_flow); - rte_free(signature); - rte_free(flow); - return -1; - } - - /* Read response */ - status = 0; - - for (i = 0; i < rsp->n_keys; i++) - if ((flow_rsp[i].entry_ptr == NULL) || - ((new_flow[i] == 0) && (flow_rsp[i].key_found == 0)) || - ((new_flow[i] == 1) && (flow_rsp[i].key_found == 1))) - status = -1; - - if (rsp->n_keys < n_keys) - status = -1; - - /* Commit flows */ - for (i = 0; i < rsp->n_keys; i++) { - memcpy(&flow[i]->key, &key[i], sizeof(flow[i]->key)); - flow[i]->port_id = port_id[i]; - flow[i]->flow_id = flow_id[i]; - flow[i]->signature = signature[i]; - flow[i]->entry_ptr = flow_rsp[i].entry_ptr; - - if (new_flow[i]) { - uint32_t bucket_id = signature[i] & (N_BUCKETS - 1); - - TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow[i], node); - p->n_flows++; - } - } - - /* Free resources */ - - for (i = rsp->n_keys; i < n_keys; i++) - if (new_flow[i]) - rte_free(flow[i]); - - app_msg_free(app, rsp); - rte_free(flow_rsp); - rte_free(flow_req); - rte_free(new_flow); - rte_free(signature); - rte_free(flow); - - return status; -} - -int -app_pipeline_fc_del(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_fc_key *key) -{ - struct app_pipeline_fc *p; - struct app_pipeline_fc_flow *flow; - - struct pipeline_fc_del_msg_req *req; - struct pipeline_fc_del_msg_rsp *rsp; - - uint32_t signature, bucket_id; - - /* Check input arguments */ - if ((app == NULL) || - (key == NULL)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); - if (p == NULL) - return -1; - - if (app_pipeline_fc_key_check(key) != 0) - return -1; - - /* Find rule */ - flow = app_pipeline_fc_flow_find(p, key); - if (flow == NULL) - return 0; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL; - app_pipeline_fc_key_convert(key, req->key, &signature); - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response */ - if (rsp->status || !rsp->key_found) { - app_msg_free(app, rsp); - return -1; - } - - /* Remove rule */ - bucket_id = signature & (N_BUCKETS - 1); - TAILQ_REMOVE(&p->flows[bucket_id], flow, node); - p->n_flows--; - rte_free(flow); - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_fc_add_default(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id) -{ - struct app_pipeline_fc *p; - - struct pipeline_fc_add_default_msg_req *req; - struct pipeline_fc_add_default_msg_rsp *rsp; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); - if (p == NULL) - return -1; - - if (port_id >= p->n_ports_out) - return -1; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT; - req->port_id = port_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response and write flow */ - if (rsp->status || (rsp->entry_ptr == NULL)) { - app_msg_free(app, rsp); - return -1; - } - - p->default_flow_port_id = port_id; - p->default_flow_entry_ptr = rsp->entry_ptr; - - /* Commit route */ - p->default_flow_present = 1; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_fc_del_default(struct app_params *app, - uint32_t pipeline_id) -{ - struct app_pipeline_fc *p; - - struct pipeline_fc_del_default_msg_req *req; - struct pipeline_fc_del_default_msg_rsp *rsp; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); - if (p == NULL) - return -EINVAL; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response */ - if (rsp->status) { - app_msg_free(app, rsp); - return -1; - } - - /* Commit route */ - p->default_flow_present = 0; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -/* - * Flow ls - */ - -static void -print_fc_qinq_flow(struct app_pipeline_fc_flow *flow) -{ - printf("(SVLAN = %" PRIu32 ", " - "CVLAN = %" PRIu32 ") => " - "Port = %" PRIu32 ", " - "Flow ID = %" PRIu32 ", " - "(signature = 0x%08" PRIx32 ", " - "entry_ptr = %p)\n", - - flow->key.key.qinq.svlan, - flow->key.key.qinq.cvlan, - flow->port_id, - flow->flow_id, - flow->signature, - flow->entry_ptr); -} - -static void -print_fc_ipv4_5tuple_flow(struct app_pipeline_fc_flow *flow) -{ - printf("(SA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", " - "DA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", " - "SP = %" PRIu32 ", " - "DP = %" PRIu32 ", " - "Proto = %" PRIu32 ") => " - "Port = %" PRIu32 ", " - "Flow ID = %" PRIu32 " " - "(signature = 0x%08" PRIx32 ", " - "entry_ptr = %p)\n", - - (flow->key.key.ipv4_5tuple.ip_src >> 24) & 0xFF, - (flow->key.key.ipv4_5tuple.ip_src >> 16) & 0xFF, - (flow->key.key.ipv4_5tuple.ip_src >> 8) & 0xFF, - flow->key.key.ipv4_5tuple.ip_src & 0xFF, - - (flow->key.key.ipv4_5tuple.ip_dst >> 24) & 0xFF, - (flow->key.key.ipv4_5tuple.ip_dst >> 16) & 0xFF, - (flow->key.key.ipv4_5tuple.ip_dst >> 8) & 0xFF, - flow->key.key.ipv4_5tuple.ip_dst & 0xFF, - - flow->key.key.ipv4_5tuple.port_src, - flow->key.key.ipv4_5tuple.port_dst, - - flow->key.key.ipv4_5tuple.proto, - - flow->port_id, - flow->flow_id, - flow->signature, - flow->entry_ptr); -} - -static void -print_fc_ipv6_5tuple_flow(struct app_pipeline_fc_flow *flow) { - printf("(SA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 - ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 - ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 - ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", " - "DA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 - ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 - ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 - ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", " - "SP = %" PRIu32 ", " - "DP = %" PRIu32 " " - "Proto = %" PRIu32 " " - "=> Port = %" PRIu32 ", " - "Flow ID = %" PRIu32 " " - "(signature = 0x%08" PRIx32 ", " - "entry_ptr = %p)\n", - - flow->key.key.ipv6_5tuple.ip_src[0], - flow->key.key.ipv6_5tuple.ip_src[1], - flow->key.key.ipv6_5tuple.ip_src[2], - flow->key.key.ipv6_5tuple.ip_src[3], - flow->key.key.ipv6_5tuple.ip_src[4], - flow->key.key.ipv6_5tuple.ip_src[5], - flow->key.key.ipv6_5tuple.ip_src[6], - flow->key.key.ipv6_5tuple.ip_src[7], - flow->key.key.ipv6_5tuple.ip_src[8], - flow->key.key.ipv6_5tuple.ip_src[9], - flow->key.key.ipv6_5tuple.ip_src[10], - flow->key.key.ipv6_5tuple.ip_src[11], - flow->key.key.ipv6_5tuple.ip_src[12], - flow->key.key.ipv6_5tuple.ip_src[13], - flow->key.key.ipv6_5tuple.ip_src[14], - flow->key.key.ipv6_5tuple.ip_src[15], - - flow->key.key.ipv6_5tuple.ip_dst[0], - flow->key.key.ipv6_5tuple.ip_dst[1], - flow->key.key.ipv6_5tuple.ip_dst[2], - flow->key.key.ipv6_5tuple.ip_dst[3], - flow->key.key.ipv6_5tuple.ip_dst[4], - flow->key.key.ipv6_5tuple.ip_dst[5], - flow->key.key.ipv6_5tuple.ip_dst[6], - flow->key.key.ipv6_5tuple.ip_dst[7], - flow->key.key.ipv6_5tuple.ip_dst[8], - flow->key.key.ipv6_5tuple.ip_dst[9], - flow->key.key.ipv6_5tuple.ip_dst[10], - flow->key.key.ipv6_5tuple.ip_dst[11], - flow->key.key.ipv6_5tuple.ip_dst[12], - flow->key.key.ipv6_5tuple.ip_dst[13], - flow->key.key.ipv6_5tuple.ip_dst[14], - flow->key.key.ipv6_5tuple.ip_dst[15], - - flow->key.key.ipv6_5tuple.port_src, - flow->key.key.ipv6_5tuple.port_dst, - - flow->key.key.ipv6_5tuple.proto, - - flow->port_id, - flow->flow_id, - flow->signature, - flow->entry_ptr); -} - -static void -print_fc_flow(struct app_pipeline_fc_flow *flow) -{ - switch (flow->key.type) { - case FLOW_KEY_QINQ: - print_fc_qinq_flow(flow); - break; - - case FLOW_KEY_IPV4_5TUPLE: - print_fc_ipv4_5tuple_flow(flow); - break; - - case FLOW_KEY_IPV6_5TUPLE: - print_fc_ipv6_5tuple_flow(flow); - break; - } -} - -static int -app_pipeline_fc_ls(struct app_params *app, - uint32_t pipeline_id) -{ - struct app_pipeline_fc *p; - struct app_pipeline_fc_flow *flow; - uint32_t i; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); - if (p == NULL) - return -1; - - for (i = 0; i < N_BUCKETS; i++) - TAILQ_FOREACH(flow, &p->flows[i], node) - print_fc_flow(flow); - - if (p->default_flow_present) - printf("Default flow: port %" PRIu32 " (entry ptr = %p)\n", - p->default_flow_port_id, - p->default_flow_entry_ptr); - else - printf("Default: DROP\n"); - - return 0; -} -/* - * flow - * - * flow add: - * p <pipelineid> flow add qinq <svlan> <cvlan> port <portid> id <flowid> - * p <pipelineid> flow add qinq bulk <file> - * p <pipelineid> flow add ipv4 <sipaddr> <dipaddr> <sport> <dport> <proto> port <port ID> id <flowid> - * p <pipelineid> flow add ipv4 bulk <file> - * p <pipelineid> flow add ipv6 <sipaddr> <dipaddr> <sport> <dport> <proto> port <port ID> id <flowid> - * p <pipelineid> flow add ipv6 bulk <file> - * - * flow add default: - * p <pipelineid> flow add default <portid> - * - * flow del: - * p <pipelineid> flow del qinq <svlan> <cvlan> - * p <pipelineid> flow del ipv4 <sipaddr> <dipaddr> <sport> <dport> <proto> - * p <pipelineid> flow del ipv6 <sipaddr> <dipaddr> <sport> <dport> <proto> - * - * flow del default: - * p <pipelineid> flow del default - * - * flow ls: - * p <pipelineid> flow ls - */ - -struct cmd_flow_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_multi_string_t multi_string; -}; - -static void -cmd_flow_parsed(void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_flow_result *results = parsed_result; - struct app_params *app = data; - - char *tokens[16]; - uint32_t n_tokens = RTE_DIM(tokens); - int status; - - status = parse_tokenize_string(results->multi_string, tokens, &n_tokens); - if (status) { - printf(CMD_MSG_TOO_MANY_ARGS, "flow"); - return; - } - - /* flow add qinq */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "qinq") == 0) && - strcmp(tokens[2], "bulk")) { - struct pipeline_fc_key key; - uint32_t svlan; - uint32_t cvlan; - uint32_t port_id; - uint32_t flow_id; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 8) { - printf(CMD_MSG_MISMATCH_ARGS, "flow add qinq"); - return; - } - - if (parser_read_uint32(&svlan, tokens[2]) != 0) { - printf(CMD_MSG_INVALID_ARG, "svlan"); - return; - } - - if (parser_read_uint32(&cvlan, tokens[3]) != 0) { - printf(CMD_MSG_INVALID_ARG, "cvlan"); - return; - } - - if (strcmp(tokens[4], "port") != 0) { - printf(CMD_MSG_ARG_NOT_FOUND, "port"); - return; - } - - if (parser_read_uint32(&port_id, tokens[5]) != 0) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - if (strcmp(tokens[6], "id") != 0) { - printf(CMD_MSG_ARG_NOT_FOUND, "id"); - return; - } - - if (parser_read_uint32(&flow_id, tokens[7]) != 0) { - printf(CMD_MSG_INVALID_ARG, "flowid"); - return; - } - - key.type = FLOW_KEY_QINQ; - key.key.qinq.svlan = svlan; - key.key.qinq.cvlan = cvlan; - - status = app_pipeline_fc_add(app, - results->pipeline_id, - &key, - port_id, - flow_id); - if (status) - printf(CMD_MSG_FAIL, "flow add qinq"); - - return; - } /* flow add qinq */ - - /* flow add ipv4 */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "ipv4") == 0) && - strcmp(tokens[2], "bulk")) { - struct pipeline_fc_key key; - struct in_addr sipaddr; - struct in_addr dipaddr; - uint32_t sport; - uint32_t dport; - uint32_t proto; - uint32_t port_id; - uint32_t flow_id; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 11) { - printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv4"); - return; - } - - if (parse_ipv4_addr(tokens[2], &sipaddr) != 0) { - printf(CMD_MSG_INVALID_ARG, "sipv4addr"); - return; - } - if (parse_ipv4_addr(tokens[3], &dipaddr) != 0) { - printf(CMD_MSG_INVALID_ARG, "dipv4addr"); - return; - } - - if (parser_read_uint32(&sport, tokens[4]) != 0) { - printf(CMD_MSG_INVALID_ARG, "sport"); - return; - } - - if (parser_read_uint32(&dport, tokens[5]) != 0) { - printf(CMD_MSG_INVALID_ARG, "dport"); - return; - } - - if (parser_read_uint32(&proto, tokens[6]) != 0) { - printf(CMD_MSG_INVALID_ARG, "proto"); - return; - } - - if (strcmp(tokens[7], "port") != 0) { - printf(CMD_MSG_ARG_NOT_FOUND, "port"); - return; - } - - if (parser_read_uint32(&port_id, tokens[8]) != 0) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - if (strcmp(tokens[9], "id") != 0) { - printf(CMD_MSG_ARG_NOT_FOUND, "id"); - return; - } - - if (parser_read_uint32(&flow_id, tokens[10]) != 0) { - printf(CMD_MSG_INVALID_ARG, "flowid"); - return; - } - - key.type = FLOW_KEY_IPV4_5TUPLE; - key.key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr); - key.key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr); - key.key.ipv4_5tuple.port_src = sport; - key.key.ipv4_5tuple.port_dst = dport; - key.key.ipv4_5tuple.proto = proto; - - status = app_pipeline_fc_add(app, - results->pipeline_id, - &key, - port_id, - flow_id); - if (status) - printf(CMD_MSG_FAIL, "flow add ipv4"); - - return; - } /* flow add ipv4 */ - - /* flow add ipv6 */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "ipv6") == 0) && - strcmp(tokens[2], "bulk")) { - struct pipeline_fc_key key; - struct in6_addr sipaddr; - struct in6_addr dipaddr; - uint32_t sport; - uint32_t dport; - uint32_t proto; - uint32_t port_id; - uint32_t flow_id; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 11) { - printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv6"); - return; - } - - if (parse_ipv6_addr(tokens[2], &sipaddr) != 0) { - printf(CMD_MSG_INVALID_ARG, "sipv6addr"); - return; - } - if (parse_ipv6_addr(tokens[3], &dipaddr) != 0) { - printf(CMD_MSG_INVALID_ARG, "dipv6addr"); - return; - } - - if (parser_read_uint32(&sport, tokens[4]) != 0) { - printf(CMD_MSG_INVALID_ARG, "sport"); - return; - } - - if (parser_read_uint32(&dport, tokens[5]) != 0) { - printf(CMD_MSG_INVALID_ARG, "dport"); - return; - } - - if (parser_read_uint32(&proto, tokens[6]) != 0) { - printf(CMD_MSG_INVALID_ARG, "proto"); - return; - } - - if (strcmp(tokens[7], "port") != 0) { - printf(CMD_MSG_ARG_NOT_FOUND, "port"); - return; - } - - if (parser_read_uint32(&port_id, tokens[8]) != 0) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - if (strcmp(tokens[9], "id") != 0) { - printf(CMD_MSG_ARG_NOT_FOUND, "id"); - return; - } - - if (parser_read_uint32(&flow_id, tokens[10]) != 0) { - printf(CMD_MSG_INVALID_ARG, "flowid"); - return; - } - - key.type = FLOW_KEY_IPV6_5TUPLE; - memcpy(key.key.ipv6_5tuple.ip_src, (void *)&sipaddr, 16); - memcpy(key.key.ipv6_5tuple.ip_dst, (void *)&dipaddr, 16); - key.key.ipv6_5tuple.port_src = sport; - key.key.ipv6_5tuple.port_dst = dport; - key.key.ipv6_5tuple.proto = proto; - - status = app_pipeline_fc_add(app, - results->pipeline_id, - &key, - port_id, - flow_id); - if (status) - printf(CMD_MSG_FAIL, "flow add ipv6"); - - return; - } /* flow add ipv6 */ - - /* flow add qinq bulk */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "qinq") == 0) && - (strcmp(tokens[2], "bulk") == 0)) { - struct pipeline_fc_key *keys; - uint32_t *port_ids, *flow_ids, n_keys, line; - char *filename; - - if (n_tokens != 4) { - printf(CMD_MSG_MISMATCH_ARGS, "flow add qinq bulk"); - return; - } - - filename = tokens[3]; - - n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE; - keys = malloc(n_keys * sizeof(struct pipeline_fc_key)); - if (keys == NULL) - return; - memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key)); - - port_ids = malloc(n_keys * sizeof(uint32_t)); - if (port_ids == NULL) { - free(keys); - return; - } - - flow_ids = malloc(n_keys * sizeof(uint32_t)); - if (flow_ids == NULL) { - free(port_ids); - free(keys); - return; - } - - status = app_pipeline_fc_load_file_qinq(filename, - keys, - port_ids, - flow_ids, - &n_keys, - &line); - if (status != 0) { - printf(CMD_MSG_FILE_ERR, filename, line); - free(flow_ids); - free(port_ids); - free(keys); - return; - } - - status = app_pipeline_fc_add_bulk(app, - results->pipeline_id, - keys, - port_ids, - flow_ids, - n_keys); - if (status) - printf(CMD_MSG_FAIL, "flow add qinq bulk"); - - free(flow_ids); - free(port_ids); - free(keys); - return; - } /* flow add qinq bulk */ - - /* flow add ipv4 bulk */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "ipv4") == 0) && - (strcmp(tokens[2], "bulk") == 0)) { - struct pipeline_fc_key *keys; - uint32_t *port_ids, *flow_ids, n_keys, line; - char *filename; - - if (n_tokens != 4) { - printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv4 bulk"); - return; - } - - filename = tokens[3]; - - n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE; - keys = malloc(n_keys * sizeof(struct pipeline_fc_key)); - if (keys == NULL) - return; - memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key)); - - port_ids = malloc(n_keys * sizeof(uint32_t)); - if (port_ids == NULL) { - free(keys); - return; - } - - flow_ids = malloc(n_keys * sizeof(uint32_t)); - if (flow_ids == NULL) { - free(port_ids); - free(keys); - return; - } - - status = app_pipeline_fc_load_file_ipv4(filename, - keys, - port_ids, - flow_ids, - &n_keys, - &line); - if (status != 0) { - printf(CMD_MSG_FILE_ERR, filename, line); - free(flow_ids); - free(port_ids); - free(keys); - return; - } - - status = app_pipeline_fc_add_bulk(app, - results->pipeline_id, - keys, - port_ids, - flow_ids, - n_keys); - if (status) - printf(CMD_MSG_FAIL, "flow add ipv4 bulk"); - - free(flow_ids); - free(port_ids); - free(keys); - return; - } /* flow add ipv4 bulk */ - - /* flow add ipv6 bulk */ - if ((n_tokens >= 3) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "ipv6") == 0) && - (strcmp(tokens[2], "bulk") == 0)) { - struct pipeline_fc_key *keys; - uint32_t *port_ids, *flow_ids, n_keys, line; - char *filename; - - if (n_tokens != 4) { - printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv6 bulk"); - return; - } - - filename = tokens[3]; - - n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE; - keys = malloc(n_keys * sizeof(struct pipeline_fc_key)); - if (keys == NULL) - return; - memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key)); - - port_ids = malloc(n_keys * sizeof(uint32_t)); - if (port_ids == NULL) { - free(keys); - return; - } - - flow_ids = malloc(n_keys * sizeof(uint32_t)); - if (flow_ids == NULL) { - free(port_ids); - free(keys); - return; - } - - status = app_pipeline_fc_load_file_ipv6(filename, - keys, - port_ids, - flow_ids, - &n_keys, - &line); - if (status != 0) { - printf(CMD_MSG_FILE_ERR, filename, line); - free(flow_ids); - free(port_ids); - free(keys); - return; - } - - status = app_pipeline_fc_add_bulk(app, - results->pipeline_id, - keys, - port_ids, - flow_ids, - n_keys); - if (status) - printf(CMD_MSG_FAIL, "flow add ipv6 bulk"); - - free(flow_ids); - free(port_ids); - free(keys); - return; - } /* flow add ipv6 bulk */ - - /* flow add default*/ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "default") == 0)) { - uint32_t port_id; - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "flow add default"); - return; - } - - if (parser_read_uint32(&port_id, tokens[2]) != 0) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - status = app_pipeline_fc_add_default(app, - results->pipeline_id, - port_id); - if (status) - printf(CMD_MSG_FAIL, "flow add default"); - - return; - } /* flow add default */ - - /* flow del qinq */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - (strcmp(tokens[1], "qinq") == 0)) { - struct pipeline_fc_key key; - uint32_t svlan; - uint32_t cvlan; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 4) { - printf(CMD_MSG_MISMATCH_ARGS, "flow del qinq"); - return; - } - - if (parser_read_uint32(&svlan, tokens[2]) != 0) { - printf(CMD_MSG_INVALID_ARG, "svlan"); - return; - } - - if (parser_read_uint32(&cvlan, tokens[3]) != 0) { - printf(CMD_MSG_INVALID_ARG, "cvlan"); - return; - } - - key.type = FLOW_KEY_QINQ; - key.key.qinq.svlan = svlan; - key.key.qinq.cvlan = cvlan; - - status = app_pipeline_fc_del(app, - results->pipeline_id, - &key); - if (status) - printf(CMD_MSG_FAIL, "flow del qinq"); - - return; - } /* flow del qinq */ - - /* flow del ipv4 */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - (strcmp(tokens[1], "ipv4") == 0)) { - struct pipeline_fc_key key; - struct in_addr sipaddr; - struct in_addr dipaddr; - uint32_t sport; - uint32_t dport; - uint32_t proto; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 7) { - printf(CMD_MSG_MISMATCH_ARGS, "flow del ipv4"); - return; - } - - if (parse_ipv4_addr(tokens[2], &sipaddr) != 0) { - printf(CMD_MSG_INVALID_ARG, "sipv4addr"); - return; - } - if (parse_ipv4_addr(tokens[3], &dipaddr) != 0) { - printf(CMD_MSG_INVALID_ARG, "dipv4addr"); - return; - } - - if (parser_read_uint32(&sport, tokens[4]) != 0) { - printf(CMD_MSG_INVALID_ARG, "sport"); - return; - } - - if (parser_read_uint32(&dport, tokens[5]) != 0) { - printf(CMD_MSG_INVALID_ARG, "dport"); - return; - } - - if (parser_read_uint32(&proto, tokens[6]) != 0) { - printf(CMD_MSG_INVALID_ARG, "proto"); - return; - } - - key.type = FLOW_KEY_IPV4_5TUPLE; - key.key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr); - key.key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr); - key.key.ipv4_5tuple.port_src = sport; - key.key.ipv4_5tuple.port_dst = dport; - key.key.ipv4_5tuple.proto = proto; - - status = app_pipeline_fc_del(app, - results->pipeline_id, - &key); - if (status) - printf(CMD_MSG_FAIL, "flow del ipv4"); - - return; - } /* flow del ipv4 */ - - /* flow del ipv6 */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - (strcmp(tokens[1], "ipv6") == 0)) { - struct pipeline_fc_key key; - struct in6_addr sipaddr; - struct in6_addr dipaddr; - uint32_t sport; - uint32_t dport; - uint32_t proto; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 7) { - printf(CMD_MSG_MISMATCH_ARGS, "flow del ipv6"); - return; - } - - if (parse_ipv6_addr(tokens[2], &sipaddr) != 0) { - printf(CMD_MSG_INVALID_ARG, "sipv6addr"); - return; - } - - if (parse_ipv6_addr(tokens[3], &dipaddr) != 0) { - printf(CMD_MSG_INVALID_ARG, "dipv6addr"); - return; - } - - if (parser_read_uint32(&sport, tokens[4]) != 0) { - printf(CMD_MSG_INVALID_ARG, "sport"); - return; - } - - if (parser_read_uint32(&dport, tokens[5]) != 0) { - printf(CMD_MSG_INVALID_ARG, "dport"); - return; - } - - if (parser_read_uint32(&proto, tokens[6]) != 0) { - printf(CMD_MSG_INVALID_ARG, "proto"); - return; - } - - key.type = FLOW_KEY_IPV6_5TUPLE; - memcpy(key.key.ipv6_5tuple.ip_src, &sipaddr, 16); - memcpy(key.key.ipv6_5tuple.ip_dst, &dipaddr, 16); - key.key.ipv6_5tuple.port_src = sport; - key.key.ipv6_5tuple.port_dst = dport; - key.key.ipv6_5tuple.proto = proto; - - status = app_pipeline_fc_del(app, - results->pipeline_id, - &key); - if (status) - printf(CMD_MSG_FAIL, "flow del ipv6"); - - return; - } /* flow del ipv6 */ - - /* flow del default*/ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - (strcmp(tokens[1], "default") == 0)) { - if (n_tokens != 2) { - printf(CMD_MSG_MISMATCH_ARGS, "flow del default"); - return; - } - - status = app_pipeline_fc_del_default(app, - results->pipeline_id); - if (status) - printf(CMD_MSG_FAIL, "flow del default"); - - return; - } /* flow del default */ - - /* flow ls */ - if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) { - if (n_tokens != 1) { - printf(CMD_MSG_MISMATCH_ARGS, "flow ls"); - return; - } - - status = app_pipeline_fc_ls(app, results->pipeline_id); - if (status) - printf(CMD_MSG_FAIL, "flow ls"); - - return; - } /* flow ls */ - - printf(CMD_MSG_MISMATCH_ARGS, "flow"); -} - -static cmdline_parse_token_string_t cmd_flow_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_flow_result, p_string, "p"); - -static cmdline_parse_token_num_t cmd_flow_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_flow_result, pipeline_id, UINT32); - -static cmdline_parse_token_string_t cmd_flow_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_flow_result, flow_string, "flow"); - -static cmdline_parse_token_string_t cmd_flow_multi_string = - TOKEN_STRING_INITIALIZER(struct cmd_flow_result, multi_string, - TOKEN_STRING_MULTI); - -static cmdline_parse_inst_t cmd_flow = { - .f = cmd_flow_parsed, - .data = NULL, - .help_str = "flow add / add bulk / add default / del / del default / ls", - .tokens = { - (void *) &cmd_flow_p_string, - (void *) &cmd_flow_pipeline_id, - (void *) &cmd_flow_flow_string, - (void *) &cmd_flow_multi_string, - NULL, - }, -}; - -static cmdline_parse_ctx_t pipeline_cmds[] = { - (cmdline_parse_inst_t *) &cmd_flow, - NULL, -}; - -static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = { - .f_init = app_pipeline_fc_init, - .f_post_init = NULL, - .f_free = app_pipeline_fc_free, - .f_track = app_pipeline_track_default, - .cmds = pipeline_cmds, -}; - -struct pipeline_type pipeline_flow_classification = { - .name = "FLOW_CLASSIFICATION", - .be_ops = &pipeline_flow_classification_be_ops, - .fe_ops = &pipeline_flow_classification_fe_ops, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.h b/examples/ip_pipeline/pipeline/pipeline_flow_classification.h deleted file mode 100644 index 8c354989..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.h +++ /dev/null @@ -1,106 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_H__ -#define __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_H__ - -#include "pipeline.h" -#include "pipeline_flow_classification_be.h" - -enum flow_key_type { - FLOW_KEY_QINQ, - FLOW_KEY_IPV4_5TUPLE, - FLOW_KEY_IPV6_5TUPLE, -}; - -struct flow_key_qinq { - uint16_t svlan; - uint16_t cvlan; -}; - -struct flow_key_ipv4_5tuple { - uint32_t ip_src; - uint32_t ip_dst; - uint16_t port_src; - uint16_t port_dst; - uint32_t proto; -}; - -struct flow_key_ipv6_5tuple { - uint8_t ip_src[16]; - uint8_t ip_dst[16]; - uint16_t port_src; - uint16_t port_dst; - uint32_t proto; -}; - -struct pipeline_fc_key { - enum flow_key_type type; - union { - struct flow_key_qinq qinq; - struct flow_key_ipv4_5tuple ipv4_5tuple; - struct flow_key_ipv6_5tuple ipv6_5tuple; - } key; -}; - -int -app_pipeline_fc_add(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_fc_key *key, - uint32_t port_id, - uint32_t flow_id); - -int -app_pipeline_fc_add_bulk(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_fc_key *key, - uint32_t *port_id, - uint32_t *flow_id, - uint32_t n_keys); - -int -app_pipeline_fc_del(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_fc_key *key); - -int -app_pipeline_fc_add_default(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id); - -int -app_pipeline_fc_del_default(struct app_params *app, - uint32_t pipeline_id); - -#ifndef APP_PIPELINE_FC_MAX_FLOWS_IN_FILE -#define APP_PIPELINE_FC_MAX_FLOWS_IN_FILE (16 * 1024 * 1024) -#endif - -int -app_pipeline_fc_load_file_qinq(char *filename, - struct pipeline_fc_key *keys, - uint32_t *port_ids, - uint32_t *flow_ids, - uint32_t *n_keys, - uint32_t *line); - -int -app_pipeline_fc_load_file_ipv4(char *filename, - struct pipeline_fc_key *keys, - uint32_t *port_ids, - uint32_t *flow_ids, - uint32_t *n_keys, - uint32_t *line); - -int -app_pipeline_fc_load_file_ipv6(char *filename, - struct pipeline_fc_key *keys, - uint32_t *port_ids, - uint32_t *flow_ids, - uint32_t *n_keys, - uint32_t *line); - -extern struct pipeline_type pipeline_flow_classification; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c deleted file mode 100644 index 097ec346..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c +++ /dev/null @@ -1,723 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <string.h> - -#include <rte_common.h> -#include <rte_malloc.h> -#include <rte_table_hash.h> -#include <rte_byteorder.h> -#include <pipeline.h> - -#include "pipeline_flow_classification_be.h" -#include "pipeline_actions_common.h" -#include "parser.h" -#include "hash_func.h" - -struct pipeline_flow_classification { - struct pipeline p; - pipeline_msg_req_handler custom_handlers[PIPELINE_FC_MSG_REQS]; - - uint32_t n_flows; - uint32_t key_size; - uint32_t flow_id; - - uint32_t key_offset; - uint32_t hash_offset; - uint8_t key_mask[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; - uint32_t key_mask_present; - uint32_t flow_id_offset; - -} __rte_cache_aligned; - -static void * -pipeline_fc_msg_req_custom_handler(struct pipeline *p, void *msg); - -static pipeline_msg_req_handler handlers[] = { - [PIPELINE_MSG_REQ_PING] = - pipeline_msg_req_ping_handler, - [PIPELINE_MSG_REQ_STATS_PORT_IN] = - pipeline_msg_req_stats_port_in_handler, - [PIPELINE_MSG_REQ_STATS_PORT_OUT] = - pipeline_msg_req_stats_port_out_handler, - [PIPELINE_MSG_REQ_STATS_TABLE] = - pipeline_msg_req_stats_table_handler, - [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = - pipeline_msg_req_port_in_enable_handler, - [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = - pipeline_msg_req_port_in_disable_handler, - [PIPELINE_MSG_REQ_CUSTOM] = - pipeline_fc_msg_req_custom_handler, -}; - -static void * -pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg); - -static void * -pipeline_fc_msg_req_add_bulk_handler(struct pipeline *p, void *msg); - -static void * -pipeline_fc_msg_req_del_handler(struct pipeline *p, void *msg); - -static void * -pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg); - -static void * -pipeline_fc_msg_req_del_default_handler(struct pipeline *p, void *msg); - -static pipeline_msg_req_handler custom_handlers[] = { - [PIPELINE_FC_MSG_REQ_FLOW_ADD] = - pipeline_fc_msg_req_add_handler, - [PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK] = - pipeline_fc_msg_req_add_bulk_handler, - [PIPELINE_FC_MSG_REQ_FLOW_DEL] = - pipeline_fc_msg_req_del_handler, - [PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT] = - pipeline_fc_msg_req_add_default_handler, - [PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT] = - pipeline_fc_msg_req_del_default_handler, -}; - -/* - * Flow table - */ -struct flow_table_entry { - struct rte_pipeline_table_entry head; - - uint32_t flow_id; - uint32_t pad; -}; - -rte_table_hash_op_hash hash_func[] = { - hash_default_key8, - hash_default_key16, - hash_default_key24, - hash_default_key32, - hash_default_key40, - hash_default_key48, - hash_default_key56, - hash_default_key64 -}; - -/* - * Flow table AH - Write flow_id to packet meta-data - */ -static inline void -pkt_work_flow_id( - struct rte_mbuf *pkt, - struct rte_pipeline_table_entry *table_entry, - void *arg) -{ - struct pipeline_flow_classification *p_fc = arg; - uint32_t *flow_id_ptr = - RTE_MBUF_METADATA_UINT32_PTR(pkt, p_fc->flow_id_offset); - struct flow_table_entry *entry = - (struct flow_table_entry *) table_entry; - - /* Read */ - uint32_t flow_id = entry->flow_id; - - /* Compute */ - - /* Write */ - *flow_id_ptr = flow_id; -} - -static inline void -pkt4_work_flow_id( - struct rte_mbuf **pkts, - struct rte_pipeline_table_entry **table_entries, - void *arg) -{ - struct pipeline_flow_classification *p_fc = arg; - - uint32_t *flow_id_ptr0 = - RTE_MBUF_METADATA_UINT32_PTR(pkts[0], p_fc->flow_id_offset); - uint32_t *flow_id_ptr1 = - RTE_MBUF_METADATA_UINT32_PTR(pkts[1], p_fc->flow_id_offset); - uint32_t *flow_id_ptr2 = - RTE_MBUF_METADATA_UINT32_PTR(pkts[2], p_fc->flow_id_offset); - uint32_t *flow_id_ptr3 = - RTE_MBUF_METADATA_UINT32_PTR(pkts[3], p_fc->flow_id_offset); - - struct flow_table_entry *entry0 = - (struct flow_table_entry *) table_entries[0]; - struct flow_table_entry *entry1 = - (struct flow_table_entry *) table_entries[1]; - struct flow_table_entry *entry2 = - (struct flow_table_entry *) table_entries[2]; - struct flow_table_entry *entry3 = - (struct flow_table_entry *) table_entries[3]; - - /* Read */ - uint32_t flow_id0 = entry0->flow_id; - uint32_t flow_id1 = entry1->flow_id; - uint32_t flow_id2 = entry2->flow_id; - uint32_t flow_id3 = entry3->flow_id; - - /* Compute */ - - /* Write */ - *flow_id_ptr0 = flow_id0; - *flow_id_ptr1 = flow_id1; - *flow_id_ptr2 = flow_id2; - *flow_id_ptr3 = flow_id3; -} - -PIPELINE_TABLE_AH_HIT(fc_table_ah_hit, - pkt_work_flow_id, pkt4_work_flow_id); - -static rte_pipeline_table_action_handler_hit -get_fc_table_ah_hit(struct pipeline_flow_classification *p) -{ - if (p->flow_id) - return fc_table_ah_hit; - - return NULL; -} - -/* - * Argument parsing - */ -static int -pipeline_fc_parse_args(struct pipeline_flow_classification *p, - struct pipeline_params *params) -{ - uint32_t n_flows_present = 0; - uint32_t key_offset_present = 0; - uint32_t key_size_present = 0; - uint32_t hash_offset_present = 0; - uint32_t key_mask_present = 0; - uint32_t flow_id_offset_present = 0; - - uint32_t i; - char key_mask_str[PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2 + 1]; - - p->hash_offset = 0; - - /* default values */ - p->flow_id = 0; - - for (i = 0; i < params->n_args; i++) { - char *arg_name = params->args_name[i]; - char *arg_value = params->args_value[i]; - - /* n_flows */ - if (strcmp(arg_name, "n_flows") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - n_flows_present == 0, params->name, - arg_name); - n_flows_present = 1; - - status = parser_read_uint32(&p->n_flows, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && - (p->n_flows != 0)), params->name, - arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* key_offset */ - if (strcmp(arg_name, "key_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - key_offset_present == 0, params->name, - arg_name); - key_offset_present = 1; - - status = parser_read_uint32(&p->key_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* key_size */ - if (strcmp(arg_name, "key_size") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - key_size_present == 0, params->name, - arg_name); - key_size_present = 1; - - status = parser_read_uint32(&p->key_size, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && - (p->key_size != 0) && - (p->key_size % 8 == 0)), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) && - (p->key_size <= - PIPELINE_FC_FLOW_KEY_MAX_SIZE)), - params->name, arg_name, arg_value); - - continue; - } - - /* key_mask */ - if (strcmp(arg_name, "key_mask") == 0) { - int mask_str_len = strlen(arg_value); - - PIPELINE_PARSE_ERR_DUPLICATE( - key_mask_present == 0, - params->name, arg_name); - key_mask_present = 1; - - PIPELINE_ARG_CHECK((mask_str_len <= - (PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2)), - "Parse error in section \"%s\": entry " - "\"%s\" is too long", params->name, - arg_name); - - snprintf(key_mask_str, mask_str_len + 1, "%s", - arg_value); - - continue; - } - - /* hash_offset */ - if (strcmp(arg_name, "hash_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - hash_offset_present == 0, params->name, - arg_name); - hash_offset_present = 1; - - status = parser_read_uint32(&p->hash_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* flow_id_offset */ - if (strcmp(arg_name, "flowid_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - flow_id_offset_present == 0, params->name, - arg_name); - flow_id_offset_present = 1; - - status = parser_read_uint32(&p->flow_id_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - p->flow_id = 1; - - continue; - } - - /* Unknown argument */ - PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); - } - - /* Check that mandatory arguments are present */ - PIPELINE_PARSE_ERR_MANDATORY((n_flows_present), params->name, - "n_flows"); - PIPELINE_PARSE_ERR_MANDATORY((key_offset_present), params->name, - "key_offset"); - PIPELINE_PARSE_ERR_MANDATORY((key_size_present), params->name, - "key_size"); - - if (key_mask_present) { - uint32_t key_size = p->key_size; - int status; - - PIPELINE_ARG_CHECK(((key_size == 8) || (key_size == 16)), - "Parse error in section \"%s\": entry key_mask " - "only allowed for key_size of 8 or 16 bytes", - params->name); - - PIPELINE_ARG_CHECK((strlen(key_mask_str) == - (key_size * 2)), "Parse error in section " - "\"%s\": key_mask should have exactly %u hex " - "digits", params->name, (key_size * 2)); - - PIPELINE_ARG_CHECK((hash_offset_present == 0), "Parse " - "error in section \"%s\": entry hash_offset only " - "allowed when key_mask is not present", - params->name); - - status = parse_hex_string(key_mask_str, p->key_mask, - &p->key_size); - - PIPELINE_PARSE_ERR_INV_VAL(((status == 0) && - (key_size == p->key_size)), params->name, - "key_mask", key_mask_str); - } - - p->key_mask_present = key_mask_present; - - return 0; -} - -static void *pipeline_fc_init(struct pipeline_params *params, - __rte_unused void *arg) -{ - struct pipeline *p; - struct pipeline_flow_classification *p_fc; - uint32_t size, i; - - /* Check input arguments */ - if (params == NULL) - return NULL; - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP( - sizeof(struct pipeline_flow_classification)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - if (p == NULL) - return NULL; - p_fc = (struct pipeline_flow_classification *) p; - - strcpy(p->name, params->name); - p->log_level = params->log_level; - - PLOG(p, HIGH, "Flow classification"); - - /* Parse arguments */ - if (pipeline_fc_parse_args(p_fc, params)) - return NULL; - - /* Pipeline */ - { - struct rte_pipeline_params pipeline_params = { - .name = params->name, - .socket_id = params->socket_id, - .offset_port_id = 0, - }; - - p->p = rte_pipeline_create(&pipeline_params); - if (p->p == NULL) { - rte_free(p); - return NULL; - } - } - - /* Input ports */ - p->n_ports_in = params->n_ports_in; - for (i = 0; i < p->n_ports_in; i++) { - struct rte_pipeline_port_in_params port_params = { - .ops = pipeline_port_in_params_get_ops( - ¶ms->port_in[i]), - .arg_create = pipeline_port_in_params_convert( - ¶ms->port_in[i]), - .f_action = NULL, - .arg_ah = NULL, - .burst_size = params->port_in[i].burst_size, - }; - - int status = rte_pipeline_port_in_create(p->p, - &port_params, - &p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Output ports */ - p->n_ports_out = params->n_ports_out; - for (i = 0; i < p->n_ports_out; i++) { - struct rte_pipeline_port_out_params port_params = { - .ops = pipeline_port_out_params_get_ops( - ¶ms->port_out[i]), - .arg_create = pipeline_port_out_params_convert( - ¶ms->port_out[i]), - .f_action = NULL, - .arg_ah = NULL, - }; - - int status = rte_pipeline_port_out_create(p->p, - &port_params, - &p->port_out_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Tables */ - p->n_tables = 1; - { - struct rte_table_hash_params table_hash_params = { - .name = p->name, - .key_size = p_fc->key_size, - .key_offset = p_fc->key_offset, - .key_mask = (p_fc->key_mask_present) ? - p_fc->key_mask : NULL, - .n_keys = p_fc->n_flows, - .n_buckets = rte_align32pow2(p_fc->n_flows / 4), - .f_hash = hash_func[(p_fc->key_size / 8) - 1], - .seed = 0, - }; - - struct rte_pipeline_table_params table_params = { - .ops = NULL, /* set below */ - .arg_create = NULL, /* set below */ - .f_action_hit = get_fc_table_ah_hit(p_fc), - .f_action_miss = NULL, - .arg_ah = p_fc, - .action_data_size = sizeof(struct flow_table_entry) - - sizeof(struct rte_pipeline_table_entry), - }; - - int status; - - switch (p_fc->key_size) { - case 8: - table_params.ops = &rte_table_hash_key8_ext_ops; - break; - - case 16: - table_params.ops = &rte_table_hash_key16_ext_ops; - break; - - default: - table_params.ops = &rte_table_hash_ext_ops; - } - - table_params.arg_create = &table_hash_params; - - status = rte_pipeline_table_create(p->p, - &table_params, - &p->table_id[0]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Connecting input ports to tables */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_connect_to_table(p->p, - p->port_in_id[i], - p->table_id[0]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Enable input ports */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_enable(p->p, - p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Check pipeline consistency */ - if (rte_pipeline_check(p->p) < 0) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - - /* Message queues */ - p->n_msgq = params->n_msgq; - for (i = 0; i < p->n_msgq; i++) - p->msgq_in[i] = params->msgq_in[i]; - for (i = 0; i < p->n_msgq; i++) - p->msgq_out[i] = params->msgq_out[i]; - - /* Message handlers */ - memcpy(p->handlers, handlers, sizeof(p->handlers)); - memcpy(p_fc->custom_handlers, - custom_handlers, - sizeof(p_fc->custom_handlers)); - - return p; -} - -static int -pipeline_fc_free(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if (p == NULL) - return -1; - - /* Free resources */ - rte_pipeline_free(p->p); - rte_free(p); - return 0; -} - -static int -pipeline_fc_timer(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - pipeline_msg_req_handle(p); - rte_pipeline_flush(p->p); - - return 0; -} - -static void * -pipeline_fc_msg_req_custom_handler(struct pipeline *p, void *msg) -{ - struct pipeline_flow_classification *p_fc = - (struct pipeline_flow_classification *) p; - struct pipeline_custom_msg_req *req = msg; - pipeline_msg_req_handler f_handle; - - f_handle = (req->subtype < PIPELINE_FC_MSG_REQS) ? - p_fc->custom_handlers[req->subtype] : - pipeline_msg_req_invalid_handler; - - if (f_handle == NULL) - f_handle = pipeline_msg_req_invalid_handler; - - return f_handle(p, req); -} - -static void * -pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg) -{ - struct pipeline_fc_add_msg_req *req = msg; - struct pipeline_fc_add_msg_rsp *rsp = msg; - - struct flow_table_entry entry = { - .head = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[req->port_id]}, - }, - .flow_id = req->flow_id, - }; - - rsp->status = rte_pipeline_table_entry_add(p->p, - p->table_id[0], - &req->key, - (struct rte_pipeline_table_entry *) &entry, - &rsp->key_found, - (struct rte_pipeline_table_entry **) &rsp->entry_ptr); - - return rsp; -} - -static void * -pipeline_fc_msg_req_add_bulk_handler(struct pipeline *p, void *msg) -{ - struct pipeline_fc_add_bulk_msg_req *req = msg; - struct pipeline_fc_add_bulk_msg_rsp *rsp = msg; - uint32_t i; - - for (i = 0; i < req->n_keys; i++) { - struct pipeline_fc_add_bulk_flow_req *flow_req = &req->req[i]; - struct pipeline_fc_add_bulk_flow_rsp *flow_rsp = &req->rsp[i]; - - struct flow_table_entry entry = { - .head = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[flow_req->port_id]}, - }, - .flow_id = flow_req->flow_id, - }; - - int status = rte_pipeline_table_entry_add(p->p, - p->table_id[0], - &flow_req->key, - (struct rte_pipeline_table_entry *) &entry, - &flow_rsp->key_found, - (struct rte_pipeline_table_entry **) - &flow_rsp->entry_ptr); - - if (status) - break; - } - - rsp->n_keys = i; - - return rsp; -} - -static void * -pipeline_fc_msg_req_del_handler(struct pipeline *p, void *msg) -{ - struct pipeline_fc_del_msg_req *req = msg; - struct pipeline_fc_del_msg_rsp *rsp = msg; - - rsp->status = rte_pipeline_table_entry_delete(p->p, - p->table_id[0], - &req->key, - &rsp->key_found, - NULL); - - return rsp; -} - -static void * -pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg) -{ - struct pipeline_fc_add_default_msg_req *req = msg; - struct pipeline_fc_add_default_msg_rsp *rsp = msg; - - struct flow_table_entry default_entry = { - .head = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[req->port_id]}, - }, - - .flow_id = 0, - }; - - rsp->status = rte_pipeline_table_default_entry_add(p->p, - p->table_id[0], - (struct rte_pipeline_table_entry *) &default_entry, - (struct rte_pipeline_table_entry **) &rsp->entry_ptr); - - return rsp; -} - -static void * -pipeline_fc_msg_req_del_default_handler(struct pipeline *p, void *msg) -{ - struct pipeline_fc_del_default_msg_rsp *rsp = msg; - - rsp->status = rte_pipeline_table_default_entry_delete(p->p, - p->table_id[0], - NULL); - - return rsp; -} - -struct pipeline_be_ops pipeline_flow_classification_be_ops = { - .f_init = pipeline_fc_init, - .f_free = pipeline_fc_free, - .f_run = NULL, - .f_timer = pipeline_fc_timer, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h deleted file mode 100644 index 18f5bb42..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h +++ /dev/null @@ -1,113 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_BE_H__ -#define __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_BE_H__ - -#include "pipeline_common_be.h" - -enum pipeline_fc_msg_req_type { - PIPELINE_FC_MSG_REQ_FLOW_ADD = 0, - PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK, - PIPELINE_FC_MSG_REQ_FLOW_DEL, - PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT, - PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT, - PIPELINE_FC_MSG_REQS, -}; - -#ifndef PIPELINE_FC_FLOW_KEY_MAX_SIZE -#define PIPELINE_FC_FLOW_KEY_MAX_SIZE 64 -#endif - -/* - * MSG ADD - */ -struct pipeline_fc_add_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_fc_msg_req_type subtype; - - uint8_t key[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; - - uint32_t port_id; - uint32_t flow_id; -}; - -struct pipeline_fc_add_msg_rsp { - int status; - int key_found; - void *entry_ptr; -}; - -/* - * MSG ADD BULK - */ -struct pipeline_fc_add_bulk_flow_req { - uint8_t key[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; - uint32_t port_id; - uint32_t flow_id; -}; - -struct pipeline_fc_add_bulk_flow_rsp { - int key_found; - void *entry_ptr; -}; - -struct pipeline_fc_add_bulk_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_fc_msg_req_type subtype; - - struct pipeline_fc_add_bulk_flow_req *req; - struct pipeline_fc_add_bulk_flow_rsp *rsp; - uint32_t n_keys; -}; - -struct pipeline_fc_add_bulk_msg_rsp { - uint32_t n_keys; -}; - -/* - * MSG DEL - */ -struct pipeline_fc_del_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_fc_msg_req_type subtype; - - uint8_t key[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; -}; - -struct pipeline_fc_del_msg_rsp { - int status; - int key_found; -}; - -/* - * MSG ADD DEFAULT - */ -struct pipeline_fc_add_default_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_fc_msg_req_type subtype; - - uint32_t port_id; -}; - -struct pipeline_fc_add_default_msg_rsp { - int status; - void *entry_ptr; -}; - -/* - * MSG DEL DEFAULT - */ -struct pipeline_fc_del_default_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_fc_msg_req_type subtype; -}; - -struct pipeline_fc_del_default_msg_rsp { - int status; -}; - -extern struct pipeline_be_ops pipeline_flow_classification_be_ops; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_master.c b/examples/ip_pipeline/pipeline/pipeline_master.c deleted file mode 100644 index b0d730a6..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_master.c +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#include "pipeline_master.h" -#include "pipeline_master_be.h" - -static struct pipeline_fe_ops pipeline_master_fe_ops = { - .f_init = NULL, - .f_post_init = NULL, - .f_free = NULL, - .f_track = NULL, - .cmds = NULL, -}; - -struct pipeline_type pipeline_master = { - .name = "MASTER", - .be_ops = &pipeline_master_be_ops, - .fe_ops = &pipeline_master_fe_ops, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_master.h b/examples/ip_pipeline/pipeline/pipeline_master.h deleted file mode 100644 index a5183e33..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_master.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_MASTER_H__ -#define __INCLUDE_PIPELINE_MASTER_H__ - -#include "pipeline.h" - -extern struct pipeline_type pipeline_master; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_master_be.c b/examples/ip_pipeline/pipeline/pipeline_master_be.c deleted file mode 100644 index c72038ea..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_master_be.c +++ /dev/null @@ -1,141 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#include <fcntl.h> -#include <unistd.h> - -#include <rte_common.h> -#include <rte_malloc.h> - -#include <cmdline_parse.h> -#include <cmdline_parse_string.h> -#include <cmdline_socket.h> -#include <cmdline.h> - -#include "app.h" -#include "pipeline_master_be.h" - -struct pipeline_master { - struct app_params *app; - struct cmdline *cl; - int post_init_done; - int script_file_done; -} __rte_cache_aligned; - -static void* -pipeline_init(__rte_unused struct pipeline_params *params, void *arg) -{ - struct app_params *app = (struct app_params *) arg; - struct pipeline_master *p; - uint32_t size; - - /* Check input arguments */ - if (app == NULL) - return NULL; - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_master)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - if (p == NULL) - return NULL; - - /* Initialization */ - p->app = app; - - p->cl = cmdline_stdin_new(app->cmds, "pipeline> "); - if (p->cl == NULL) { - rte_free(p); - return NULL; - } - - p->post_init_done = 0; - p->script_file_done = 0; - if (app->script_file == NULL) - p->script_file_done = 1; - - return (void *) p; -} - -static int -pipeline_free(void *pipeline) -{ - struct pipeline_master *p = (struct pipeline_master *) pipeline; - - if (p == NULL) - return -EINVAL; - - cmdline_stdin_exit(p->cl); - rte_free(p); - - return 0; -} - -static int -pipeline_run(void *pipeline) -{ - struct pipeline_master *p = (struct pipeline_master *) pipeline; - struct app_params *app = p->app; - int status; -#ifdef RTE_LIBRTE_KNI - uint32_t i; -#endif /* RTE_LIBRTE_KNI */ - - /* Application post-init phase */ - if (p->post_init_done == 0) { - app_post_init(app); - - p->post_init_done = 1; - } - - /* Run startup script file */ - if (p->script_file_done == 0) { - struct app_params *app = p->app; - int fd = open(app->script_file, O_RDONLY); - - if (fd < 0) - printf("Cannot open CLI script file \"%s\"\n", - app->script_file); - else { - struct cmdline *file_cl; - - printf("Running CLI script file \"%s\" ...\n", - app->script_file); - file_cl = cmdline_new(p->cl->ctx, "", fd, 1); - cmdline_interact(file_cl); - close(fd); - } - - p->script_file_done = 1; - } - - /* Command Line Interface (CLI) */ - status = cmdline_poll(p->cl); - if (status < 0) - rte_panic("CLI poll error (%" PRId32 ")\n", status); - else if (status == RDLINE_EXITED) { - cmdline_stdin_exit(p->cl); - rte_exit(0, "Bye!\n"); - } - -#ifdef RTE_LIBRTE_KNI - /* Handle KNI requests from Linux kernel */ - for (i = 0; i < app->n_pktq_kni; i++) - rte_kni_handle_request(app->kni[i]); -#endif /* RTE_LIBRTE_KNI */ - - return 0; -} - -static int -pipeline_timer(__rte_unused void *pipeline) -{ - return 0; -} - -struct pipeline_be_ops pipeline_master_be_ops = { - .f_init = pipeline_init, - .f_free = pipeline_free, - .f_run = pipeline_run, - .f_timer = pipeline_timer, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_master_be.h b/examples/ip_pipeline/pipeline/pipeline_master_be.h deleted file mode 100644 index 847c564c..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_master_be.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_MASTER_BE_H__ -#define __INCLUDE_PIPELINE_MASTER_BE_H__ - -#include "pipeline_common_be.h" - -extern struct pipeline_be_ops pipeline_master_be_ops; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough.c b/examples/ip_pipeline/pipeline/pipeline_passthrough.c deleted file mode 100644 index 031f5f05..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_passthrough.c +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#include "pipeline_passthrough.h" -#include "pipeline_passthrough_be.h" - -static int -app_pipeline_passthrough_track(struct pipeline_params *p, - uint32_t port_in, - uint32_t *port_out) -{ - struct pipeline_passthrough_params pp; - int status; - - /* Check input arguments */ - if ((p == NULL) || - (port_in >= p->n_ports_in) || - (port_out == NULL)) - return -1; - - status = pipeline_passthrough_parse_args(&pp, p); - if (status) - return -1; - - if (pp.dma_hash_lb_enabled) - return -1; - - *port_out = port_in / (p->n_ports_in / p->n_ports_out); - return 0; -} - -static struct pipeline_fe_ops pipeline_passthrough_fe_ops = { - .f_init = NULL, - .f_post_init = NULL, - .f_free = NULL, - .f_track = app_pipeline_passthrough_track, - .cmds = NULL, -}; - -struct pipeline_type pipeline_passthrough = { - .name = "PASS-THROUGH", - .be_ops = &pipeline_passthrough_be_ops, - .fe_ops = &pipeline_passthrough_fe_ops, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough.h b/examples/ip_pipeline/pipeline/pipeline_passthrough.h deleted file mode 100644 index 7a7a2fc6..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_passthrough.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_PASSTHROUGH_H__ -#define __INCLUDE_PIPELINE_PASSTHROUGH_H__ - -#include "pipeline.h" - -extern struct pipeline_type pipeline_passthrough; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c deleted file mode 100644 index b2bbaedd..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c +++ /dev/null @@ -1,929 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <stdio.h> -#include <string.h> - -#include <rte_common.h> -#include <rte_malloc.h> -#include <rte_byteorder.h> -#include <rte_table_stub.h> -#include <rte_table_hash.h> -#include <rte_pipeline.h> - -#include "pipeline_passthrough_be.h" -#include "pipeline_actions_common.h" -#include "parser.h" -#include "hash_func.h" - -#define SWAP_DIM (PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX * \ - (PIPELINE_PASSTHROUGH_SWAP_FIELD_SIZE_MAX / sizeof(uint64_t))) - -struct pipeline_passthrough { - struct pipeline p; - struct pipeline_passthrough_params params; - rte_table_hash_op_hash f_hash; - uint32_t swap_field0_offset[SWAP_DIM]; - uint32_t swap_field1_offset[SWAP_DIM]; - uint64_t swap_field_mask[SWAP_DIM]; - uint32_t swap_n_fields; -} __rte_cache_aligned; - -static pipeline_msg_req_handler handlers[] = { - [PIPELINE_MSG_REQ_PING] = - pipeline_msg_req_ping_handler, - [PIPELINE_MSG_REQ_STATS_PORT_IN] = - pipeline_msg_req_stats_port_in_handler, - [PIPELINE_MSG_REQ_STATS_PORT_OUT] = - pipeline_msg_req_stats_port_out_handler, - [PIPELINE_MSG_REQ_STATS_TABLE] = - pipeline_msg_req_stats_table_handler, - [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = - pipeline_msg_req_port_in_enable_handler, - [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = - pipeline_msg_req_port_in_disable_handler, - [PIPELINE_MSG_REQ_CUSTOM] = - pipeline_msg_req_invalid_handler, -}; - -static __rte_always_inline void -pkt_work_dma( - struct rte_mbuf *pkt, - void *arg, - uint32_t dma_size, - uint32_t hash_enabled, - uint32_t lb_hash, - uint32_t port_out_pow2) -{ - struct pipeline_passthrough *p = arg; - - uint64_t *dma_dst = RTE_MBUF_METADATA_UINT64_PTR(pkt, - p->params.dma_dst_offset); - uint64_t *dma_src = RTE_MBUF_METADATA_UINT64_PTR(pkt, - p->params.dma_src_offset); - uint64_t *dma_mask = (uint64_t *) p->params.dma_src_mask; - uint32_t *dma_hash = RTE_MBUF_METADATA_UINT32_PTR(pkt, - p->params.dma_hash_offset); - uint32_t i; - - /* Read (dma_src), compute (dma_dst), write (dma_dst) */ - for (i = 0; i < (dma_size / 8); i++) - dma_dst[i] = dma_src[i] & dma_mask[i]; - - /* Read (dma_dst), compute (hash), write (hash) */ - if (hash_enabled) { - uint32_t hash = p->f_hash(dma_src, dma_mask, dma_size, 0); - *dma_hash = hash; - - if (lb_hash) { - uint32_t port_out; - - if (port_out_pow2) - port_out - = hash & (p->p.n_ports_out - 1); - else - port_out - = hash % p->p.n_ports_out; - - rte_pipeline_port_out_packet_insert(p->p.p, - port_out, pkt); - } - } -} - -static __rte_always_inline void -pkt4_work_dma( - struct rte_mbuf **pkts, - void *arg, - uint32_t dma_size, - uint32_t hash_enabled, - uint32_t lb_hash, - uint32_t port_out_pow2) -{ - struct pipeline_passthrough *p = arg; - - uint64_t *dma_dst0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], - p->params.dma_dst_offset); - uint64_t *dma_dst1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], - p->params.dma_dst_offset); - uint64_t *dma_dst2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], - p->params.dma_dst_offset); - uint64_t *dma_dst3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], - p->params.dma_dst_offset); - - uint64_t *dma_src0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], - p->params.dma_src_offset); - uint64_t *dma_src1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], - p->params.dma_src_offset); - uint64_t *dma_src2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], - p->params.dma_src_offset); - uint64_t *dma_src3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], - p->params.dma_src_offset); - - uint64_t *dma_mask = (uint64_t *) p->params.dma_src_mask; - - uint32_t *dma_hash0 = RTE_MBUF_METADATA_UINT32_PTR(pkts[0], - p->params.dma_hash_offset); - uint32_t *dma_hash1 = RTE_MBUF_METADATA_UINT32_PTR(pkts[1], - p->params.dma_hash_offset); - uint32_t *dma_hash2 = RTE_MBUF_METADATA_UINT32_PTR(pkts[2], - p->params.dma_hash_offset); - uint32_t *dma_hash3 = RTE_MBUF_METADATA_UINT32_PTR(pkts[3], - p->params.dma_hash_offset); - - uint32_t i; - - /* Read (dma_src), compute (dma_dst), write (dma_dst) */ - for (i = 0; i < (dma_size / 8); i++) { - dma_dst0[i] = dma_src0[i] & dma_mask[i]; - dma_dst1[i] = dma_src1[i] & dma_mask[i]; - dma_dst2[i] = dma_src2[i] & dma_mask[i]; - dma_dst3[i] = dma_src3[i] & dma_mask[i]; - } - - /* Read (dma_dst), compute (hash), write (hash) */ - if (hash_enabled) { - uint32_t hash0 = p->f_hash(dma_src0, dma_mask, dma_size, 0); - uint32_t hash1 = p->f_hash(dma_src1, dma_mask, dma_size, 0); - uint32_t hash2 = p->f_hash(dma_src2, dma_mask, dma_size, 0); - uint32_t hash3 = p->f_hash(dma_src3, dma_mask, dma_size, 0); - - *dma_hash0 = hash0; - *dma_hash1 = hash1; - *dma_hash2 = hash2; - *dma_hash3 = hash3; - - if (lb_hash) { - uint32_t port_out0, port_out1, port_out2, port_out3; - - if (port_out_pow2) { - port_out0 - = hash0 & (p->p.n_ports_out - 1); - port_out1 - = hash1 & (p->p.n_ports_out - 1); - port_out2 - = hash2 & (p->p.n_ports_out - 1); - port_out3 - = hash3 & (p->p.n_ports_out - 1); - } else { - port_out0 - = hash0 % p->p.n_ports_out; - port_out1 - = hash1 % p->p.n_ports_out; - port_out2 - = hash2 % p->p.n_ports_out; - port_out3 - = hash3 % p->p.n_ports_out; - } - rte_pipeline_port_out_packet_insert(p->p.p, - port_out0, pkts[0]); - rte_pipeline_port_out_packet_insert(p->p.p, - port_out1, pkts[1]); - rte_pipeline_port_out_packet_insert(p->p.p, - port_out2, pkts[2]); - rte_pipeline_port_out_packet_insert(p->p.p, - port_out3, pkts[3]); - } - } -} - -static __rte_always_inline void -pkt_work_swap( - struct rte_mbuf *pkt, - void *arg) -{ - struct pipeline_passthrough *p = arg; - uint32_t i; - - /* Read(field0, field1), compute(field0, field1), write(field0, field1) */ - for (i = 0; i < p->swap_n_fields; i++) { - uint64_t *field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, - p->swap_field0_offset[i]); - uint64_t *field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, - p->swap_field1_offset[i]); - uint64_t mask = p->swap_field_mask[i]; - - uint64_t field0 = *field0_ptr; - uint64_t field1 = *field1_ptr; - - *field0_ptr = (field0 & (~mask)) + (field1 & mask); - *field1_ptr = (field0 & mask) + (field1 & (~mask)); - } -} - -static __rte_always_inline void -pkt4_work_swap( - struct rte_mbuf **pkts, - void *arg) -{ - struct pipeline_passthrough *p = arg; - uint32_t i; - - /* Read(field0, field1), compute(field0, field1), write(field0, field1) */ - for (i = 0; i < p->swap_n_fields; i++) { - uint64_t *pkt0_field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], - p->swap_field0_offset[i]); - uint64_t *pkt1_field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], - p->swap_field0_offset[i]); - uint64_t *pkt2_field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], - p->swap_field0_offset[i]); - uint64_t *pkt3_field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], - p->swap_field0_offset[i]); - - uint64_t *pkt0_field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], - p->swap_field1_offset[i]); - uint64_t *pkt1_field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], - p->swap_field1_offset[i]); - uint64_t *pkt2_field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], - p->swap_field1_offset[i]); - uint64_t *pkt3_field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], - p->swap_field1_offset[i]); - - uint64_t mask = p->swap_field_mask[i]; - - uint64_t pkt0_field0 = *pkt0_field0_ptr; - uint64_t pkt1_field0 = *pkt1_field0_ptr; - uint64_t pkt2_field0 = *pkt2_field0_ptr; - uint64_t pkt3_field0 = *pkt3_field0_ptr; - - uint64_t pkt0_field1 = *pkt0_field1_ptr; - uint64_t pkt1_field1 = *pkt1_field1_ptr; - uint64_t pkt2_field1 = *pkt2_field1_ptr; - uint64_t pkt3_field1 = *pkt3_field1_ptr; - - *pkt0_field0_ptr = (pkt0_field0 & (~mask)) + (pkt0_field1 & mask); - *pkt1_field0_ptr = (pkt1_field0 & (~mask)) + (pkt1_field1 & mask); - *pkt2_field0_ptr = (pkt2_field0 & (~mask)) + (pkt2_field1 & mask); - *pkt3_field0_ptr = (pkt3_field0 & (~mask)) + (pkt3_field1 & mask); - - *pkt0_field1_ptr = (pkt0_field0 & mask) + (pkt0_field1 & (~mask)); - *pkt1_field1_ptr = (pkt1_field0 & mask) + (pkt1_field1 & (~mask)); - *pkt2_field1_ptr = (pkt2_field0 & mask) + (pkt2_field1 & (~mask)); - *pkt3_field1_ptr = (pkt3_field0 & mask) + (pkt3_field1 & (~mask)); - } -} - -#define PKT_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \ -static inline void \ -pkt_work_dma_size##dma_size##_hash##hash_enabled \ - ##_lb##lb_hash##_pw##port_pow2( \ - struct rte_mbuf *pkt, \ - void *arg) \ -{ \ - pkt_work_dma(pkt, arg, dma_size, hash_enabled, lb_hash, port_pow2); \ -} - -#define PKT4_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \ -static inline void \ -pkt4_work_dma_size##dma_size##_hash##hash_enabled \ - ##_lb##lb_hash##_pw##port_pow2( \ - struct rte_mbuf **pkts, \ - void *arg) \ -{ \ - pkt4_work_dma(pkts, arg, dma_size, hash_enabled, lb_hash, port_pow2); \ -} - -#define port_in_ah_dma(dma_size, hash_enabled, lb_hash, port_pow2) \ -PKT_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \ -PKT4_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \ -PIPELINE_PORT_IN_AH(port_in_ah_dma_size##dma_size##_hash \ - ##hash_enabled##_lb##lb_hash##_pw##port_pow2, \ - pkt_work_dma_size##dma_size##_hash##hash_enabled \ - ##_lb##lb_hash##_pw##port_pow2, \ - pkt4_work_dma_size##dma_size##_hash##hash_enabled \ - ##_lb##lb_hash##_pw##port_pow2) - - -#define port_in_ah_lb(dma_size, hash_enabled, lb_hash, port_pow2) \ -PKT_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \ -PKT4_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \ -PIPELINE_PORT_IN_AH_HIJACK_ALL( \ - port_in_ah_lb_size##dma_size##_hash##hash_enabled \ - ##_lb##lb_hash##_pw##port_pow2, \ - pkt_work_dma_size##dma_size##_hash##hash_enabled \ - ##_lb##lb_hash##_pw##port_pow2, \ - pkt4_work_dma_size##dma_size##_hash##hash_enabled \ - ##_lb##lb_hash##_pw##port_pow2) - -PIPELINE_PORT_IN_AH(port_in_ah_swap, pkt_work_swap, pkt4_work_swap) - - -/* Port in AH DMA(dma_size, hash_enabled, lb_hash, port_pow2) */ - -port_in_ah_dma(8, 0, 0, 0) -port_in_ah_dma(8, 1, 0, 0) -port_in_ah_lb(8, 1, 1, 0) -port_in_ah_lb(8, 1, 1, 1) - -port_in_ah_dma(16, 0, 0, 0) -port_in_ah_dma(16, 1, 0, 0) -port_in_ah_lb(16, 1, 1, 0) -port_in_ah_lb(16, 1, 1, 1) - -port_in_ah_dma(24, 0, 0, 0) -port_in_ah_dma(24, 1, 0, 0) -port_in_ah_lb(24, 1, 1, 0) -port_in_ah_lb(24, 1, 1, 1) - -port_in_ah_dma(32, 0, 0, 0) -port_in_ah_dma(32, 1, 0, 0) -port_in_ah_lb(32, 1, 1, 0) -port_in_ah_lb(32, 1, 1, 1) - -port_in_ah_dma(40, 0, 0, 0) -port_in_ah_dma(40, 1, 0, 0) -port_in_ah_lb(40, 1, 1, 0) -port_in_ah_lb(40, 1, 1, 1) - -port_in_ah_dma(48, 0, 0, 0) -port_in_ah_dma(48, 1, 0, 0) -port_in_ah_lb(48, 1, 1, 0) -port_in_ah_lb(48, 1, 1, 1) - -port_in_ah_dma(56, 0, 0, 0) -port_in_ah_dma(56, 1, 0, 0) -port_in_ah_lb(56, 1, 1, 0) -port_in_ah_lb(56, 1, 1, 1) - -port_in_ah_dma(64, 0, 0, 0) -port_in_ah_dma(64, 1, 0, 0) -port_in_ah_lb(64, 1, 1, 0) -port_in_ah_lb(64, 1, 1, 1) - -static rte_pipeline_port_in_action_handler -get_port_in_ah(struct pipeline_passthrough *p) -{ - if ((p->params.dma_enabled == 0) && - (p->params.swap_enabled == 0)) - return NULL; - - if (p->params.swap_enabled) - return port_in_ah_swap; - - if (p->params.dma_hash_enabled) { - if (p->params.dma_hash_lb_enabled) { - if (rte_is_power_of_2(p->p.n_ports_out)) - switch (p->params.dma_size) { - - case 8: return port_in_ah_lb_size8_hash1_lb1_pw1; - case 16: return port_in_ah_lb_size16_hash1_lb1_pw1; - case 24: return port_in_ah_lb_size24_hash1_lb1_pw1; - case 32: return port_in_ah_lb_size32_hash1_lb1_pw1; - case 40: return port_in_ah_lb_size40_hash1_lb1_pw1; - case 48: return port_in_ah_lb_size48_hash1_lb1_pw1; - case 56: return port_in_ah_lb_size56_hash1_lb1_pw1; - case 64: return port_in_ah_lb_size64_hash1_lb1_pw1; - default: return NULL; - } - else - switch (p->params.dma_size) { - - case 8: return port_in_ah_lb_size8_hash1_lb1_pw0; - case 16: return port_in_ah_lb_size16_hash1_lb1_pw0; - case 24: return port_in_ah_lb_size24_hash1_lb1_pw0; - case 32: return port_in_ah_lb_size32_hash1_lb1_pw0; - case 40: return port_in_ah_lb_size40_hash1_lb1_pw0; - case 48: return port_in_ah_lb_size48_hash1_lb1_pw0; - case 56: return port_in_ah_lb_size56_hash1_lb1_pw0; - case 64: return port_in_ah_lb_size64_hash1_lb1_pw0; - default: return NULL; - } - } else - switch (p->params.dma_size) { - - case 8: return port_in_ah_dma_size8_hash1_lb0_pw0; - case 16: return port_in_ah_dma_size16_hash1_lb0_pw0; - case 24: return port_in_ah_dma_size24_hash1_lb0_pw0; - case 32: return port_in_ah_dma_size32_hash1_lb0_pw0; - case 40: return port_in_ah_dma_size40_hash1_lb0_pw0; - case 48: return port_in_ah_dma_size48_hash1_lb0_pw0; - case 56: return port_in_ah_dma_size56_hash1_lb0_pw0; - case 64: return port_in_ah_dma_size64_hash1_lb0_pw0; - default: return NULL; - } - } else - switch (p->params.dma_size) { - - case 8: return port_in_ah_dma_size8_hash0_lb0_pw0; - case 16: return port_in_ah_dma_size16_hash0_lb0_pw0; - case 24: return port_in_ah_dma_size24_hash0_lb0_pw0; - case 32: return port_in_ah_dma_size32_hash0_lb0_pw0; - case 40: return port_in_ah_dma_size40_hash0_lb0_pw0; - case 48: return port_in_ah_dma_size48_hash0_lb0_pw0; - case 56: return port_in_ah_dma_size56_hash0_lb0_pw0; - case 64: return port_in_ah_dma_size64_hash0_lb0_pw0; - default: return NULL; - } -} - -int -pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, - struct pipeline_params *params) -{ - uint32_t dma_dst_offset_present = 0; - uint32_t dma_src_offset_present = 0; - uint32_t dma_src_mask_present = 0; - char dma_mask_str[PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2 + 1]; - uint32_t dma_size_present = 0; - uint32_t dma_hash_offset_present = 0; - uint32_t dma_hash_lb_present = 0; - uint32_t i; - - /* default values */ - p->dma_enabled = 0; - p->dma_hash_enabled = 0; - p->dma_hash_lb_enabled = 0; - memset(p->dma_src_mask, 0xFF, sizeof(p->dma_src_mask)); - p->swap_enabled = 0; - p->swap_n_fields = 0; - - for (i = 0; i < params->n_args; i++) { - char *arg_name = params->args_name[i]; - char *arg_value = params->args_value[i]; - - /* dma_dst_offset */ - if (strcmp(arg_name, "dma_dst_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - dma_dst_offset_present == 0, params->name, - arg_name); - dma_dst_offset_present = 1; - - status = parser_read_uint32(&p->dma_dst_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - p->dma_enabled = 1; - - continue; - } - - /* dma_src_offset */ - if (strcmp(arg_name, "dma_src_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - dma_src_offset_present == 0, params->name, - arg_name); - dma_src_offset_present = 1; - - status = parser_read_uint32(&p->dma_src_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - p->dma_enabled = 1; - - continue; - } - - /* dma_size */ - if (strcmp(arg_name, "dma_size") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - dma_size_present == 0, params->name, - arg_name); - dma_size_present = 1; - - status = parser_read_uint32(&p->dma_size, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && - (p->dma_size != 0) && - ((p->dma_size % 8) == 0)), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) && - (p->dma_size <= - PIPELINE_PASSTHROUGH_DMA_SIZE_MAX)), - params->name, arg_name, arg_value); - - p->dma_enabled = 1; - - continue; - } - - /* dma_src_mask */ - if (strcmp(arg_name, "dma_src_mask") == 0) { - int mask_str_len = strlen(arg_value); - - PIPELINE_PARSE_ERR_DUPLICATE( - dma_src_mask_present == 0, - params->name, arg_name); - dma_src_mask_present = 1; - - PIPELINE_ARG_CHECK((mask_str_len <= - (PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2)), - "Parse error in section \"%s\": entry " - "\"%s\" too long", params->name, - arg_name); - - snprintf(dma_mask_str, mask_str_len + 1, - "%s", arg_value); - - p->dma_enabled = 1; - - continue; - } - - /* dma_hash_offset */ - if (strcmp(arg_name, "dma_hash_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - dma_hash_offset_present == 0, - params->name, arg_name); - dma_hash_offset_present = 1; - - status = parser_read_uint32(&p->dma_hash_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - p->dma_hash_enabled = 1; - - continue; - } - - /* load_balance mode */ - if (strcmp(arg_name, "lb") == 0) { - PIPELINE_PARSE_ERR_DUPLICATE( - dma_hash_lb_present == 0, - params->name, arg_name); - dma_hash_lb_present = 1; - - if (strcmp(arg_value, "hash") && - strcmp(arg_value, "HASH")) - - PIPELINE_PARSE_ERR_INV_VAL(0, - params->name, - arg_name, - arg_value); - - p->dma_hash_lb_enabled = 1; - - continue; - } - - /* swap */ - if (strcmp(arg_name, "swap") == 0) { - uint32_t a, b, n_args; - int len; - - n_args = sscanf(arg_value, "%" SCNu32 " %" SCNu32 "%n", - &a, &b, &len); - PIPELINE_PARSE_ERR_INV_VAL(((n_args == 2) && - ((size_t) len == strlen(arg_value))), - params->name, arg_name, arg_value); - - p->swap_field0_offset[p->swap_n_fields] = a; - p->swap_field1_offset[p->swap_n_fields] = b; - p->swap_n_fields++; - p->swap_enabled = 1; - - continue; - } - - /* any other */ - PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); - } - - /* Check correlations between arguments */ - PIPELINE_ARG_CHECK((p->dma_enabled + p->swap_enabled < 2), - "Parse error in section \"%s\": DMA and SWAP actions are both enabled", - params->name); - PIPELINE_ARG_CHECK((dma_dst_offset_present == p->dma_enabled), - "Parse error in section \"%s\": missing entry " - "\"dma_dst_offset\"", params->name); - PIPELINE_ARG_CHECK((dma_src_offset_present == p->dma_enabled), - "Parse error in section \"%s\": missing entry " - "\"dma_src_offset\"", params->name); - PIPELINE_ARG_CHECK((dma_size_present == p->dma_enabled), - "Parse error in section \"%s\": missing entry " - "\"dma_size\"", params->name); - PIPELINE_ARG_CHECK((p->dma_hash_enabled <= p->dma_enabled), - "Parse error in section \"%s\": missing all DMA entries", - params->name); - PIPELINE_ARG_CHECK((p->dma_hash_lb_enabled <= p->dma_hash_enabled), - "Parse error in section \"%s\": missing all DMA hash entries ", - params->name); - - if (dma_src_mask_present) { - uint32_t dma_size = p->dma_size; - int status; - - PIPELINE_ARG_CHECK((strlen(dma_mask_str) == - (dma_size * 2)), "Parse error in section " - "\"%s\": dma_src_mask should have exactly %u hex " - "digits", params->name, (dma_size * 2)); - - status = parse_hex_string(dma_mask_str, p->dma_src_mask, - &p->dma_size); - - PIPELINE_PARSE_ERR_INV_VAL(((status == 0) && - (dma_size == p->dma_size)), params->name, - "dma_src_mask", dma_mask_str); - } - - if (p->dma_hash_lb_enabled) - PIPELINE_ARG_CHECK((params->n_ports_out > 1), - "Parse error in section \"%s\": entry \"lb\" not " - "allowed for single output port pipeline", - params->name); - else - PIPELINE_ARG_CHECK(((params->n_ports_in >= params->n_ports_out) - && ((params->n_ports_in % params->n_ports_out) == 0)), - "Parse error in section \"%s\": n_ports_in needs to be " - "a multiple of n_ports_out (lb mode disabled)", - params->name); - - return 0; -} - -static rte_table_hash_op_hash -get_hash_function(struct pipeline_passthrough *p) -{ - switch (p->params.dma_size) { - - case 8: return hash_default_key8; - case 16: return hash_default_key16; - case 24: return hash_default_key24; - case 32: return hash_default_key32; - case 40: return hash_default_key40; - case 48: return hash_default_key48; - case 56: return hash_default_key56; - case 64: return hash_default_key64; - default: return NULL; - } -} - -static int -pipeline_passthrough_swap_convert(struct pipeline_passthrough *p) -{ - uint32_t i; - - p->swap_n_fields = 0; - - for (i = 0; i < p->params.swap_n_fields; i++) { - uint32_t offset0 = p->params.swap_field0_offset[i]; - uint32_t offset1 = p->params.swap_field1_offset[i]; - uint32_t size = offset1 - offset0; - uint32_t j; - - /* Check */ - if ((offset0 >= offset1) || - (size > PIPELINE_PASSTHROUGH_SWAP_FIELD_SIZE_MAX) || - (p->swap_n_fields >= SWAP_DIM)) - return -1; - - for (j = 0; j < (size / sizeof(uint64_t)); j++) { - p->swap_field0_offset[p->swap_n_fields] = offset0; - p->swap_field1_offset[p->swap_n_fields] = offset1; - p->swap_field_mask[p->swap_n_fields] = UINT64_MAX; - p->swap_n_fields++; - offset0 += sizeof(uint64_t); - offset1 += sizeof(uint64_t); - } - if (size % sizeof(uint64_t)) { - uint32_t n_bits = (size % sizeof(uint64_t)) * 8; - - p->swap_field0_offset[p->swap_n_fields] = offset0; - p->swap_field1_offset[p->swap_n_fields] = offset1; - p->swap_field_mask[p->swap_n_fields] = - RTE_LEN2MASK(n_bits, uint64_t); - p->swap_n_fields++; - } - } - - return 0; -} - -static void* -pipeline_passthrough_init(struct pipeline_params *params, - __rte_unused void *arg) -{ - struct pipeline *p; - struct pipeline_passthrough *p_pt; - uint32_t size, i; - - /* Check input arguments */ - if ((params == NULL) || - (params->n_ports_in == 0) || - (params->n_ports_out == 0)) - return NULL; - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_passthrough)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - p_pt = (struct pipeline_passthrough *) p; - if (p == NULL) - return NULL; - - strcpy(p->name, params->name); - p->log_level = params->log_level; - - PLOG(p, HIGH, "Pass-through"); - - /* Parse arguments */ - if (pipeline_passthrough_parse_args(&p_pt->params, params)) - return NULL; - if (pipeline_passthrough_swap_convert(p_pt)) - return NULL; - p_pt->f_hash = get_hash_function(p_pt); - - /* Pipeline */ - { - struct rte_pipeline_params pipeline_params = { - .name = "PASS-THROUGH", - .socket_id = params->socket_id, - .offset_port_id = 0, - }; - - p->p = rte_pipeline_create(&pipeline_params); - if (p->p == NULL) { - rte_free(p); - return NULL; - } - } - - p->n_ports_in = params->n_ports_in; - p->n_ports_out = params->n_ports_out; - p->n_tables = p->n_ports_in; - - /*Input ports*/ - for (i = 0; i < p->n_ports_in; i++) { - struct rte_pipeline_port_in_params port_params = { - .ops = pipeline_port_in_params_get_ops( - ¶ms->port_in[i]), - .arg_create = pipeline_port_in_params_convert( - ¶ms->port_in[i]), - .f_action = get_port_in_ah(p_pt), - .arg_ah = p_pt, - .burst_size = params->port_in[i].burst_size, - }; - - int status = rte_pipeline_port_in_create(p->p, - &port_params, - &p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Output ports */ - for (i = 0; i < p->n_ports_out; i++) { - struct rte_pipeline_port_out_params port_params = { - .ops = pipeline_port_out_params_get_ops( - ¶ms->port_out[i]), - .arg_create = pipeline_port_out_params_convert( - ¶ms->port_out[i]), - .f_action = NULL, - .arg_ah = NULL, - }; - - int status = rte_pipeline_port_out_create(p->p, - &port_params, - &p->port_out_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Tables */ - for (i = 0; i < p->n_ports_in; i++) { - struct rte_pipeline_table_params table_params = { - .ops = &rte_table_stub_ops, - .arg_create = NULL, - .f_action_hit = NULL, - .f_action_miss = NULL, - .arg_ah = NULL, - .action_data_size = 0, - }; - - int status = rte_pipeline_table_create(p->p, - &table_params, - &p->table_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Connecting input ports to tables */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_connect_to_table(p->p, - p->port_in_id[i], - p->table_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Add entries to tables */ - for (i = 0; i < p->n_ports_in; i++) { - uint32_t port_out_id = (p_pt->params.dma_hash_lb_enabled == 0) ? - (i / (p->n_ports_in / p->n_ports_out)) : - 0; - - struct rte_pipeline_table_entry default_entry = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[port_out_id]}, - }; - - struct rte_pipeline_table_entry *default_entry_ptr; - - int status = rte_pipeline_table_default_entry_add(p->p, - p->table_id[i], - &default_entry, - &default_entry_ptr); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Enable input ports */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_enable(p->p, - p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Check pipeline consistency */ - if (rte_pipeline_check(p->p) < 0) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - - /* Message queues */ - p->n_msgq = params->n_msgq; - for (i = 0; i < p->n_msgq; i++) - p->msgq_in[i] = params->msgq_in[i]; - for (i = 0; i < p->n_msgq; i++) - p->msgq_out[i] = params->msgq_out[i]; - - /* Message handlers */ - memcpy(p->handlers, handlers, sizeof(p->handlers)); - - return p; -} - -static int -pipeline_passthrough_free(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if (p == NULL) - return -1; - - /* Free resources */ - rte_pipeline_free(p->p); - rte_free(p); - return 0; -} - -static int -pipeline_passthrough_timer(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - pipeline_msg_req_handle(p); - rte_pipeline_flush(p->p); - - return 0; -} - -struct pipeline_be_ops pipeline_passthrough_be_ops = { - .f_init = pipeline_passthrough_init, - .f_free = pipeline_passthrough_free, - .f_run = NULL, - .f_timer = pipeline_passthrough_timer, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h deleted file mode 100644 index 94d1d1cf..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_PASSTHROUGH_BE_H__ -#define __INCLUDE_PIPELINE_PASSTHROUGH_BE_H__ - -#include "pipeline_common_be.h" - -#define PIPELINE_PASSTHROUGH_DMA_SIZE_MAX 64 - -#ifndef PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX -#define PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX 8 -#endif - -#ifndef PIPELINE_PASSTHROUGH_SWAP_FIELD_SIZE_MAX -#define PIPELINE_PASSTHROUGH_SWAP_FIELD_SIZE_MAX 16 -#endif - -struct pipeline_passthrough_params { - uint32_t dma_enabled; - uint32_t dma_dst_offset; - uint32_t dma_src_offset; - uint8_t dma_src_mask[PIPELINE_PASSTHROUGH_DMA_SIZE_MAX]; - uint32_t dma_size; - - uint32_t dma_hash_enabled; - uint32_t dma_hash_offset; - - uint32_t dma_hash_lb_enabled; - - uint32_t swap_enabled; - uint32_t swap_field0_offset[PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX]; - uint32_t swap_field1_offset[PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX]; - uint32_t swap_n_fields; -}; - -int -pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, - struct pipeline_params *params); - -extern struct pipeline_be_ops pipeline_passthrough_be_ops; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.c b/examples/ip_pipeline/pipeline/pipeline_routing.c deleted file mode 100644 index 0562c63a..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_routing.c +++ /dev/null @@ -1,1613 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <cmdline_parse.h> -#include <cmdline_parse_num.h> -#include <cmdline_parse_string.h> - -#include "app.h" -#include "pipeline_common_fe.h" -#include "pipeline_routing.h" -#include "parser.h" - -struct app_pipeline_routing_route { - struct pipeline_routing_route_key key; - struct pipeline_routing_route_data data; - void *entry_ptr; - - TAILQ_ENTRY(app_pipeline_routing_route) node; -}; - -struct app_pipeline_routing_arp_entry { - struct pipeline_routing_arp_key key; - struct ether_addr macaddr; - void *entry_ptr; - - TAILQ_ENTRY(app_pipeline_routing_arp_entry) node; -}; - -struct pipeline_routing { - /* Parameters */ - struct app_params *app; - uint32_t pipeline_id; - uint32_t n_ports_in; - uint32_t n_ports_out; - struct pipeline_routing_params rp; - - /* Links */ - uint32_t link_id[PIPELINE_MAX_PORT_OUT]; - - /* Routes */ - TAILQ_HEAD(, app_pipeline_routing_route) routes; - uint32_t n_routes; - - uint32_t default_route_present; - uint32_t default_route_port_id; - void *default_route_entry_ptr; - - /* ARP entries */ - TAILQ_HEAD(, app_pipeline_routing_arp_entry) arp_entries; - uint32_t n_arp_entries; - - uint32_t default_arp_entry_present; - uint32_t default_arp_entry_port_id; - void *default_arp_entry_ptr; -}; - -static int -app_pipeline_routing_find_link(struct pipeline_routing *p, - uint32_t link_id, - uint32_t *port_id) -{ - uint32_t i; - - for (i = 0; i < p->n_ports_out; i++) - if (p->link_id[i] == link_id) { - *port_id = i; - return 0; - } - - return -1; -} - -static void -app_pipeline_routing_link_op(__rte_unused struct app_params *app, - uint32_t link_id, - uint32_t up, - void *arg) -{ - struct pipeline_routing_route_key key0, key1; - struct pipeline_routing *p = arg; - struct app_link_params *lp; - uint32_t port_id, netmask; - int status; - - if (app == NULL) - return; - - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, lp); - if (lp == NULL) - return; - - status = app_pipeline_routing_find_link(p, - link_id, - &port_id); - if (status) - return; - - netmask = (~0U) << (32 - lp->depth); - - /* Local network (directly attached network) */ - key0.type = PIPELINE_ROUTING_ROUTE_IPV4; - key0.key.ipv4.ip = lp->ip & netmask; - key0.key.ipv4.depth = lp->depth; - - /* Local termination */ - key1.type = PIPELINE_ROUTING_ROUTE_IPV4; - key1.key.ipv4.ip = lp->ip; - key1.key.ipv4.depth = 32; - - if (up) { - struct pipeline_routing_route_data data0, data1; - - /* Local network (directly attached network) */ - memset(&data0, 0, sizeof(data0)); - data0.flags = PIPELINE_ROUTING_ROUTE_LOCAL | - PIPELINE_ROUTING_ROUTE_ARP; - if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) - data0.flags |= PIPELINE_ROUTING_ROUTE_QINQ; - if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) { - data0.flags |= PIPELINE_ROUTING_ROUTE_MPLS; - data0.l2.mpls.n_labels = 1; - } - data0.port_id = port_id; - - if (p->rp.n_arp_entries) - app_pipeline_routing_add_route(app, - p->pipeline_id, - &key0, - &data0); - - /* Local termination */ - memset(&data1, 0, sizeof(data1)); - data1.flags = PIPELINE_ROUTING_ROUTE_LOCAL | - PIPELINE_ROUTING_ROUTE_ARP; - if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) - data1.flags |= PIPELINE_ROUTING_ROUTE_QINQ; - if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) { - data1.flags |= PIPELINE_ROUTING_ROUTE_MPLS; - data1.l2.mpls.n_labels = 1; - } - data1.port_id = p->rp.port_local_dest; - - app_pipeline_routing_add_route(app, - p->pipeline_id, - &key1, - &data1); - } else { - /* Local network (directly attached network) */ - if (p->rp.n_arp_entries) - app_pipeline_routing_delete_route(app, - p->pipeline_id, - &key0); - - /* Local termination */ - app_pipeline_routing_delete_route(app, - p->pipeline_id, - &key1); - } -} - -static int -app_pipeline_routing_set_link_op( - struct app_params *app, - struct pipeline_routing *p) -{ - uint32_t port_id; - - for (port_id = 0; port_id < p->n_ports_out; port_id++) { - struct app_link_params *link; - uint32_t link_id; - int status; - - link = app_pipeline_track_pktq_out_to_link(app, - p->pipeline_id, - port_id); - if (link == NULL) - continue; - - link_id = link - app->link_params; - p->link_id[port_id] = link_id; - - status = app_link_set_op(app, - link_id, - p->pipeline_id, - app_pipeline_routing_link_op, - (void *) p); - if (status) - return status; - } - - return 0; -} - -static void * -app_pipeline_routing_init(struct pipeline_params *params, - void *arg) -{ - struct app_params *app = (struct app_params *) arg; - struct pipeline_routing *p; - uint32_t pipeline_id, size; - int status; - - /* Check input arguments */ - if ((params == NULL) || - (params->n_ports_in == 0) || - (params->n_ports_out == 0)) - return NULL; - - APP_PARAM_GET_ID(params, "PIPELINE", pipeline_id); - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - if (p == NULL) - return NULL; - - /* Initialization */ - p->app = app; - p->pipeline_id = pipeline_id; - p->n_ports_in = params->n_ports_in; - p->n_ports_out = params->n_ports_out; - - status = pipeline_routing_parse_args(&p->rp, params); - if (status) { - rte_free(p); - return NULL; - } - TAILQ_INIT(&p->routes); - p->n_routes = 0; - - TAILQ_INIT(&p->arp_entries); - p->n_arp_entries = 0; - - app_pipeline_routing_set_link_op(app, p); - - return p; -} - -static int -app_pipeline_routing_post_init(void *pipeline) -{ - struct pipeline_routing *p = pipeline; - - /* Check input arguments */ - if (p == NULL) - return -1; - - return app_pipeline_routing_set_macaddr(p->app, p->pipeline_id); -} - -static int -app_pipeline_routing_free(void *pipeline) -{ - struct pipeline_routing *p = pipeline; - - /* Check input arguments */ - if (p == NULL) - return -1; - - /* Free resources */ - while (!TAILQ_EMPTY(&p->routes)) { - struct app_pipeline_routing_route *route; - - route = TAILQ_FIRST(&p->routes); - TAILQ_REMOVE(&p->routes, route, node); - rte_free(route); - } - - while (!TAILQ_EMPTY(&p->arp_entries)) { - struct app_pipeline_routing_arp_entry *arp_entry; - - arp_entry = TAILQ_FIRST(&p->arp_entries); - TAILQ_REMOVE(&p->arp_entries, arp_entry, node); - rte_free(arp_entry); - } - - rte_free(p); - return 0; -} - -static struct app_pipeline_routing_route * -app_pipeline_routing_find_route(struct pipeline_routing *p, - const struct pipeline_routing_route_key *key) -{ - struct app_pipeline_routing_route *it, *found; - - found = NULL; - TAILQ_FOREACH(it, &p->routes, node) { - if ((key->type == it->key.type) && - (key->key.ipv4.ip == it->key.key.ipv4.ip) && - (key->key.ipv4.depth == it->key.key.ipv4.depth)) { - found = it; - break; - } - } - - return found; -} - -static struct app_pipeline_routing_arp_entry * -app_pipeline_routing_find_arp_entry(struct pipeline_routing *p, - const struct pipeline_routing_arp_key *key) -{ - struct app_pipeline_routing_arp_entry *it, *found; - - found = NULL; - TAILQ_FOREACH(it, &p->arp_entries, node) { - if ((key->type == it->key.type) && - (key->key.ipv4.port_id == it->key.key.ipv4.port_id) && - (key->key.ipv4.ip == it->key.key.ipv4.ip)) { - found = it; - break; - } - } - - return found; -} - -static void -print_route(const struct app_pipeline_routing_route *route) -{ - if (route->key.type == PIPELINE_ROUTING_ROUTE_IPV4) { - const struct pipeline_routing_route_key_ipv4 *key = - &route->key.key.ipv4; - - printf("IP Prefix = %" PRIu32 ".%" PRIu32 - ".%" PRIu32 ".%" PRIu32 "/%" PRIu32 - " => (Port = %" PRIu32, - - (key->ip >> 24) & 0xFF, - (key->ip >> 16) & 0xFF, - (key->ip >> 8) & 0xFF, - key->ip & 0xFF, - - key->depth, - route->data.port_id); - - if (route->data.flags & PIPELINE_ROUTING_ROUTE_LOCAL) - printf(", Local"); - else if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP) - printf( - ", Next Hop IP = %" PRIu32 ".%" PRIu32 - ".%" PRIu32 ".%" PRIu32, - - (route->data.ethernet.ip >> 24) & 0xFF, - (route->data.ethernet.ip >> 16) & 0xFF, - (route->data.ethernet.ip >> 8) & 0xFF, - route->data.ethernet.ip & 0xFF); - else - printf( - ", Next Hop HWaddress = %02" PRIx32 - ":%02" PRIx32 ":%02" PRIx32 - ":%02" PRIx32 ":%02" PRIx32 - ":%02" PRIx32, - - route->data.ethernet.macaddr.addr_bytes[0], - route->data.ethernet.macaddr.addr_bytes[1], - route->data.ethernet.macaddr.addr_bytes[2], - route->data.ethernet.macaddr.addr_bytes[3], - route->data.ethernet.macaddr.addr_bytes[4], - route->data.ethernet.macaddr.addr_bytes[5]); - - if (route->data.flags & PIPELINE_ROUTING_ROUTE_QINQ) - printf(", QinQ SVLAN = %" PRIu32 " CVLAN = %" PRIu32, - route->data.l2.qinq.svlan, - route->data.l2.qinq.cvlan); - - if (route->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) { - uint32_t i; - - printf(", MPLS labels"); - for (i = 0; i < route->data.l2.mpls.n_labels; i++) - printf(" %" PRIu32, - route->data.l2.mpls.labels[i]); - } - - printf(")\n"); - } -} - -static void -print_arp_entry(const struct app_pipeline_routing_arp_entry *entry) -{ - printf("(Port = %" PRIu32 ", IP = %" PRIu32 ".%" PRIu32 - ".%" PRIu32 ".%" PRIu32 - ") => HWaddress = %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 - ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n", - - entry->key.key.ipv4.port_id, - (entry->key.key.ipv4.ip >> 24) & 0xFF, - (entry->key.key.ipv4.ip >> 16) & 0xFF, - (entry->key.key.ipv4.ip >> 8) & 0xFF, - entry->key.key.ipv4.ip & 0xFF, - - entry->macaddr.addr_bytes[0], - entry->macaddr.addr_bytes[1], - entry->macaddr.addr_bytes[2], - entry->macaddr.addr_bytes[3], - entry->macaddr.addr_bytes[4], - entry->macaddr.addr_bytes[5]); -} - -static int -app_pipeline_routing_route_ls(struct app_params *app, uint32_t pipeline_id) -{ - struct pipeline_routing *p; - struct app_pipeline_routing_route *it; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -EINVAL; - - TAILQ_FOREACH(it, &p->routes, node) - print_route(it); - - if (p->default_route_present) - printf("Default route: port %" PRIu32 " (entry ptr = %p)\n", - p->default_route_port_id, - p->default_route_entry_ptr); - else - printf("Default: DROP\n"); - - return 0; -} - -int -app_pipeline_routing_add_route(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_routing_route_key *key, - struct pipeline_routing_route_data *data) -{ - struct pipeline_routing *p; - - struct pipeline_routing_route_add_msg_req *req; - struct pipeline_routing_route_add_msg_rsp *rsp; - - struct app_pipeline_routing_route *entry; - - int new_entry; - - /* Check input arguments */ - if ((app == NULL) || - (key == NULL) || - (data == NULL)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -1; - - switch (key->type) { - case PIPELINE_ROUTING_ROUTE_IPV4: - { - uint32_t depth = key->key.ipv4.depth; - uint32_t netmask; - - /* key */ - if ((depth == 0) || (depth > 32)) - return -1; - - netmask = (~0U) << (32 - depth); - key->key.ipv4.ip &= netmask; - - /* data */ - if (data->port_id >= p->n_ports_out) - return -1; - - /* Valid range of VLAN tags 12 bits */ - if (data->flags & PIPELINE_ROUTING_ROUTE_QINQ) - if ((data->l2.qinq.svlan & 0xF000) || - (data->l2.qinq.cvlan & 0xF000)) - return -1; - - /* Max number of MPLS labels supported */ - if (data->flags & PIPELINE_ROUTING_ROUTE_MPLS) { - uint32_t i; - - if (data->l2.mpls.n_labels > - PIPELINE_ROUTING_MPLS_LABELS_MAX) - return -1; - - /* Max MPLS label value 20 bits */ - for (i = 0; i < data->l2.mpls.n_labels; i++) - if (data->l2.mpls.labels[i] & 0xFFF00000) - return -1; - } - } - break; - - default: - return -1; - } - - /* Find existing rule or allocate new rule */ - entry = app_pipeline_routing_find_route(p, key); - new_entry = (entry == NULL); - if (entry == NULL) { - entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE); - - if (entry == NULL) - return -1; - } - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) { - if (new_entry) - rte_free(entry); - return -1; - } - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD; - memcpy(&req->key, key, sizeof(*key)); - memcpy(&req->data, data, sizeof(*data)); - - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) { - if (new_entry) - rte_free(entry); - return -1; - } - - /* Read response and write entry */ - if (rsp->status || - (rsp->entry_ptr == NULL) || - ((new_entry == 0) && (rsp->key_found == 0)) || - ((new_entry == 1) && (rsp->key_found == 1))) { - app_msg_free(app, rsp); - if (new_entry) - rte_free(entry); - return -1; - } - - memcpy(&entry->key, key, sizeof(*key)); - memcpy(&entry->data, data, sizeof(*data)); - entry->entry_ptr = rsp->entry_ptr; - - /* Commit entry */ - if (new_entry) { - TAILQ_INSERT_TAIL(&p->routes, entry, node); - p->n_routes++; - } - - /* Message buffer free */ - app_msg_free(app, rsp); - return 0; -} - -int -app_pipeline_routing_delete_route(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_routing_route_key *key) -{ - struct pipeline_routing *p; - - struct pipeline_routing_route_delete_msg_req *req; - struct pipeline_routing_route_delete_msg_rsp *rsp; - - struct app_pipeline_routing_route *entry; - - /* Check input arguments */ - if ((app == NULL) || - (key == NULL)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -1; - - switch (key->type) { - case PIPELINE_ROUTING_ROUTE_IPV4: - { - uint32_t depth = key->key.ipv4.depth; - uint32_t netmask; - - /* key */ - if ((depth == 0) || (depth > 32)) - return -1; - - netmask = (~0U) << (32 - depth); - key->key.ipv4.ip &= netmask; - } - break; - - default: - return -1; - } - - /* Find rule */ - entry = app_pipeline_routing_find_route(p, key); - if (entry == NULL) - return 0; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL; - memcpy(&req->key, key, sizeof(*key)); - - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response */ - if (rsp->status || !rsp->key_found) { - app_msg_free(app, rsp); - return -1; - } - - /* Remove route */ - TAILQ_REMOVE(&p->routes, entry, node); - p->n_routes--; - rte_free(entry); - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_routing_add_default_route(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id) -{ - struct pipeline_routing *p; - - struct pipeline_routing_route_add_default_msg_req *req; - struct pipeline_routing_route_add_default_msg_rsp *rsp; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -1; - - if (port_id >= p->n_ports_out) - return -1; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT; - req->port_id = port_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response and write route */ - if (rsp->status || (rsp->entry_ptr == NULL)) { - app_msg_free(app, rsp); - return -1; - } - - p->default_route_port_id = port_id; - p->default_route_entry_ptr = rsp->entry_ptr; - - /* Commit route */ - p->default_route_present = 1; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_routing_delete_default_route(struct app_params *app, - uint32_t pipeline_id) -{ - struct pipeline_routing *p; - - struct pipeline_routing_arp_delete_default_msg_req *req; - struct pipeline_routing_arp_delete_default_msg_rsp *rsp; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -1; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response and write route */ - if (rsp->status) { - app_msg_free(app, rsp); - return -1; - } - - /* Commit route */ - p->default_route_present = 0; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -static int -app_pipeline_routing_arp_ls(struct app_params *app, uint32_t pipeline_id) -{ - struct pipeline_routing *p; - struct app_pipeline_routing_arp_entry *it; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -EINVAL; - - TAILQ_FOREACH(it, &p->arp_entries, node) - print_arp_entry(it); - - if (p->default_arp_entry_present) - printf("Default entry: port %" PRIu32 " (entry ptr = %p)\n", - p->default_arp_entry_port_id, - p->default_arp_entry_ptr); - else - printf("Default: DROP\n"); - - return 0; -} - -int -app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id, - struct pipeline_routing_arp_key *key, - struct ether_addr *macaddr) -{ - struct pipeline_routing *p; - - struct pipeline_routing_arp_add_msg_req *req; - struct pipeline_routing_arp_add_msg_rsp *rsp; - - struct app_pipeline_routing_arp_entry *entry; - - int new_entry; - - /* Check input arguments */ - if ((app == NULL) || - (key == NULL) || - (macaddr == NULL)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -1; - - switch (key->type) { - case PIPELINE_ROUTING_ARP_IPV4: - { - uint32_t port_id = key->key.ipv4.port_id; - - /* key */ - if (port_id >= p->n_ports_out) - return -1; - } - break; - - default: - return -1; - } - - /* Find existing entry or allocate new */ - entry = app_pipeline_routing_find_arp_entry(p, key); - new_entry = (entry == NULL); - if (entry == NULL) { - entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE); - - if (entry == NULL) - return -1; - } - - /* Message buffer allocation */ - req = app_msg_alloc(app); - if (req == NULL) { - if (new_entry) - rte_free(entry); - return -1; - } - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD; - memcpy(&req->key, key, sizeof(*key)); - ether_addr_copy(macaddr, &req->macaddr); - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) { - if (new_entry) - rte_free(entry); - return -1; - } - - /* Read response and write entry */ - if (rsp->status || - (rsp->entry_ptr == NULL) || - ((new_entry == 0) && (rsp->key_found == 0)) || - ((new_entry == 1) && (rsp->key_found == 1))) { - app_msg_free(app, rsp); - if (new_entry) - rte_free(entry); - return -1; - } - - memcpy(&entry->key, key, sizeof(*key)); - ether_addr_copy(macaddr, &entry->macaddr); - entry->entry_ptr = rsp->entry_ptr; - - /* Commit entry */ - if (new_entry) { - TAILQ_INSERT_TAIL(&p->arp_entries, entry, node); - p->n_arp_entries++; - } - - /* Message buffer free */ - app_msg_free(app, rsp); - return 0; -} - -int -app_pipeline_routing_delete_arp_entry(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_routing_arp_key *key) -{ - struct pipeline_routing *p; - - struct pipeline_routing_arp_delete_msg_req *req; - struct pipeline_routing_arp_delete_msg_rsp *rsp; - - struct app_pipeline_routing_arp_entry *entry; - - /* Check input arguments */ - if ((app == NULL) || - (key == NULL)) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -EINVAL; - - switch (key->type) { - case PIPELINE_ROUTING_ARP_IPV4: - { - uint32_t port_id = key->key.ipv4.port_id; - - /* key */ - if (port_id >= p->n_ports_out) - return -1; - } - break; - - default: - return -1; - } - - /* Find rule */ - entry = app_pipeline_routing_find_arp_entry(p, key); - if (entry == NULL) - return 0; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL; - memcpy(&req->key, key, sizeof(*key)); - - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response */ - if (rsp->status || !rsp->key_found) { - app_msg_free(app, rsp); - return -1; - } - - /* Remove entry */ - TAILQ_REMOVE(&p->arp_entries, entry, node); - p->n_arp_entries--; - rte_free(entry); - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_routing_add_default_arp_entry(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id) -{ - struct pipeline_routing *p; - - struct pipeline_routing_arp_add_default_msg_req *req; - struct pipeline_routing_arp_add_default_msg_rsp *rsp; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -1; - - if (port_id >= p->n_ports_out) - return -1; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT; - req->port_id = port_id; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - /* Read response and write entry */ - if (rsp->status || rsp->entry_ptr == NULL) { - app_msg_free(app, rsp); - return -1; - } - - p->default_arp_entry_port_id = port_id; - p->default_arp_entry_ptr = rsp->entry_ptr; - - /* Commit entry */ - p->default_arp_entry_present = 1; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_routing_delete_default_arp_entry(struct app_params *app, - uint32_t pipeline_id) -{ - struct pipeline_routing *p; - - struct pipeline_routing_arp_delete_default_msg_req *req; - struct pipeline_routing_arp_delete_default_msg_rsp *rsp; - - /* Check input arguments */ - if (app == NULL) - return -1; - - p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); - if (p == NULL) - return -EINVAL; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -ENOMEM; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT; - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -ETIMEDOUT; - - /* Read response and write entry */ - if (rsp->status) { - app_msg_free(app, rsp); - return rsp->status; - } - - /* Commit entry */ - p->default_arp_entry_present = 0; - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -int -app_pipeline_routing_set_macaddr(struct app_params *app, - uint32_t pipeline_id) -{ - struct app_pipeline_params *p; - struct pipeline_routing_set_macaddr_msg_req *req; - struct pipeline_routing_set_macaddr_msg_rsp *rsp; - uint32_t port_id; - - /* Check input arguments */ - if (app == NULL) - return -EINVAL; - - APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); - if (p == NULL) - return -EINVAL; - - /* Allocate and write request */ - req = app_msg_alloc(app); - if (req == NULL) - return -ENOMEM; - - req->type = PIPELINE_MSG_REQ_CUSTOM; - req->subtype = PIPELINE_ROUTING_MSG_REQ_SET_MACADDR; - - memset(req->macaddr, 0, sizeof(req->macaddr)); - for (port_id = 0; port_id < p->n_pktq_out; port_id++) { - struct app_link_params *link; - - link = app_pipeline_track_pktq_out_to_link(app, - pipeline_id, - port_id); - if (link) - req->macaddr[port_id] = link->mac_addr; - } - - /* Send request and wait for response */ - rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -ETIMEDOUT; - - /* Read response and write entry */ - if (rsp->status) { - app_msg_free(app, rsp); - return rsp->status; - } - - /* Free response */ - app_msg_free(app, rsp); - - return 0; -} - -/* - * route - * - * route add (ARP = ON/OFF, MPLS = ON/OFF, QINQ = ON/OFF): - * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> - * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> - * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> qinq <svlan> <cvlan> - * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> qinq <svlan> <cvlan> - * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> mpls <mpls labels> - * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> mpls <mpls labels> - * - * route add default: - * p <pipelineid> route add default <portid> - * - * route del: - * p <pipelineid> route del <ipaddr> <depth> - * - * route del default: - * p <pipelineid> route del default - * - * route ls: - * p <pipelineid> route ls - */ - -struct cmd_route_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_multi_string_t multi_string; -}; - -static void -cmd_route_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_route_result *params = parsed_result; - struct app_params *app = data; - - char *tokens[16]; - uint32_t n_tokens = RTE_DIM(tokens); - int status; - - status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); - if (status != 0) { - printf(CMD_MSG_TOO_MANY_ARGS, "route"); - return; - } - - /* route add */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "add") == 0) && - strcmp(tokens[1], "default")) { - struct pipeline_routing_route_key key; - struct pipeline_routing_route_data route_data; - struct in_addr ipv4, nh_ipv4; - struct ether_addr mac_addr; - uint32_t depth, port_id, svlan, cvlan, i; - uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX]; - uint32_t n_labels = RTE_DIM(mpls_labels); - - memset(&key, 0, sizeof(key)); - memset(&route_data, 0, sizeof(route_data)); - - if (n_tokens < 7) { - printf(CMD_MSG_NOT_ENOUGH_ARGS, "route add"); - return; - } - - if (parse_ipv4_addr(tokens[1], &ipv4)) { - printf(CMD_MSG_INVALID_ARG, "ipaddr"); - return; - } - - if (parser_read_uint32(&depth, tokens[2])) { - printf(CMD_MSG_INVALID_ARG, "depth"); - return; - } - - if (strcmp(tokens[3], "port")) { - printf(CMD_MSG_ARG_NOT_FOUND, "port"); - return; - } - - if (parser_read_uint32(&port_id, tokens[4])) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - if (strcmp(tokens[5], "ether")) { - printf(CMD_MSG_ARG_NOT_FOUND, "ether"); - return; - } - - if (parse_mac_addr(tokens[6], &mac_addr)) { - if (parse_ipv4_addr(tokens[6], &nh_ipv4)) { - printf(CMD_MSG_INVALID_ARG, "nhmacaddr or nhipaddr"); - return; - } - - route_data.flags |= PIPELINE_ROUTING_ROUTE_ARP; - } - - if (n_tokens > 7) { - if (strcmp(tokens[7], "mpls") == 0) { - if (n_tokens != 9) { - printf(CMD_MSG_MISMATCH_ARGS, "route add mpls"); - return; - } - - if (parse_mpls_labels(tokens[8], mpls_labels, &n_labels)) { - printf(CMD_MSG_INVALID_ARG, "mpls labels"); - return; - } - - route_data.flags |= PIPELINE_ROUTING_ROUTE_MPLS; - } else if (strcmp(tokens[7], "qinq") == 0) { - if (n_tokens != 10) { - printf(CMD_MSG_MISMATCH_ARGS, "route add qinq"); - return; - } - - if (parser_read_uint32(&svlan, tokens[8])) { - printf(CMD_MSG_INVALID_ARG, "svlan"); - return; - } - if (parser_read_uint32(&cvlan, tokens[9])) { - printf(CMD_MSG_INVALID_ARG, "cvlan"); - return; - } - - route_data.flags |= PIPELINE_ROUTING_ROUTE_QINQ; - } else { - printf(CMD_MSG_ARG_NOT_FOUND, "mpls or qinq"); - return; - } - } - - switch (route_data.flags) { - case 0: - route_data.port_id = port_id; - route_data.ethernet.macaddr = mac_addr; - break; - - case PIPELINE_ROUTING_ROUTE_ARP: - route_data.port_id = port_id; - route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr); - break; - - case PIPELINE_ROUTING_ROUTE_MPLS: - route_data.port_id = port_id; - route_data.ethernet.macaddr = mac_addr; - for (i = 0; i < n_labels; i++) - route_data.l2.mpls.labels[i] = mpls_labels[i]; - route_data.l2.mpls.n_labels = n_labels; - break; - - case PIPELINE_ROUTING_ROUTE_MPLS | PIPELINE_ROUTING_ROUTE_ARP: - route_data.port_id = port_id; - route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr); - for (i = 0; i < n_labels; i++) - route_data.l2.mpls.labels[i] = mpls_labels[i]; - route_data.l2.mpls.n_labels = n_labels; - break; - - case PIPELINE_ROUTING_ROUTE_QINQ: - route_data.port_id = port_id; - route_data.ethernet.macaddr = mac_addr; - route_data.l2.qinq.svlan = svlan; - route_data.l2.qinq.cvlan = cvlan; - break; - - case PIPELINE_ROUTING_ROUTE_QINQ | PIPELINE_ROUTING_ROUTE_ARP: - default: - route_data.port_id = port_id; - route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr); - route_data.l2.qinq.svlan = svlan; - route_data.l2.qinq.cvlan = cvlan; - break; - } - - key.type = PIPELINE_ROUTING_ROUTE_IPV4; - key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr); - key.key.ipv4.depth = depth; - - status = app_pipeline_routing_add_route(app, - params->p, - &key, - &route_data); - if (status != 0) - printf(CMD_MSG_FAIL, "route add"); - - return; - } /* route add */ - - /* route add default */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "default") == 0)) { - uint32_t port_id; - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "route add default"); - return; - } - - if (parser_read_uint32(&port_id, tokens[2])) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - status = app_pipeline_routing_add_default_route(app, - params->p, - port_id); - if (status != 0) - printf(CMD_MSG_FAIL, "route add default"); - - return; - } /* route add default */ - - /* route del*/ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - strcmp(tokens[1], "default")) { - struct pipeline_routing_route_key key; - struct in_addr ipv4; - uint32_t depth; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "route del"); - return; - } - - if (parse_ipv4_addr(tokens[1], &ipv4)) { - printf(CMD_MSG_INVALID_ARG, "ipaddr"); - return; - } - - if (parser_read_uint32(&depth, tokens[2])) { - printf(CMD_MSG_INVALID_ARG, "depth"); - return; - } - - key.type = PIPELINE_ROUTING_ROUTE_IPV4; - key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr); - key.key.ipv4.depth = depth; - - status = app_pipeline_routing_delete_route(app, params->p, &key); - if (status != 0) - printf(CMD_MSG_FAIL, "route del"); - - return; - } /* route del */ - - /* route del default */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - (strcmp(tokens[1], "default") == 0)) { - if (n_tokens != 2) { - printf(CMD_MSG_MISMATCH_ARGS, "route del default"); - return; - } - - status = app_pipeline_routing_delete_default_route(app, - params->p); - if (status != 0) - printf(CMD_MSG_FAIL, "route del default"); - - return; - } /* route del default */ - - /* route ls */ - if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) { - if (n_tokens != 1) { - printf(CMD_MSG_MISMATCH_ARGS, "route ls"); - return; - } - - status = app_pipeline_routing_route_ls(app, params->p); - if (status != 0) - printf(CMD_MSG_FAIL, "route ls"); - - return; - } /* route ls */ - - printf(CMD_MSG_MISMATCH_ARGS, "route"); -} - -static cmdline_parse_token_string_t cmd_route_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_result, p_string, "p"); - -static cmdline_parse_token_num_t cmd_route_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_route_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_result, route_string, "route"); - -static cmdline_parse_token_string_t cmd_route_multi_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_result, multi_string, - TOKEN_STRING_MULTI); - -static cmdline_parse_inst_t cmd_route = { - .f = cmd_route_parsed, - .data = NULL, - .help_str = "route add / add default / del / del default / ls", - .tokens = { - (void *)&cmd_route_p_string, - (void *)&cmd_route_p, - (void *)&cmd_route_route_string, - (void *)&cmd_route_multi_string, - NULL, - }, -}; - -/* - * arp - * - * arp add: - * p <pipelineid> arp add <portid> <ipaddr> <macaddr> - * - * arp add default: - * p <pipelineid> arp add default <portid> - * - * arp del: - * p <pipelineid> arp del <portid> <ipaddr> - * - * arp del default: - * p <pipelineid> arp del default - * - * arp ls: - * p <pipelineid> arp ls - */ - -struct cmd_arp_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t arp_string; - cmdline_multi_string_t multi_string; -}; - -static void -cmd_arp_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_arp_result *params = parsed_result; - struct app_params *app = data; - - char *tokens[16]; - uint32_t n_tokens = RTE_DIM(tokens); - int status; - - status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); - if (status != 0) { - printf(CMD_MSG_TOO_MANY_ARGS, "arp"); - return; - } - - /* arp add */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "add") == 0) && - strcmp(tokens[1], "default")) { - struct pipeline_routing_arp_key key; - struct in_addr ipv4; - struct ether_addr mac_addr; - uint32_t port_id; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 4) { - printf(CMD_MSG_MISMATCH_ARGS, "arp add"); - return; - } - - if (parser_read_uint32(&port_id, tokens[1])) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - if (parse_ipv4_addr(tokens[2], &ipv4)) { - printf(CMD_MSG_INVALID_ARG, "ipaddr"); - return; - } - - if (parse_mac_addr(tokens[3], &mac_addr)) { - printf(CMD_MSG_INVALID_ARG, "macaddr"); - return; - } - - key.type = PIPELINE_ROUTING_ARP_IPV4; - key.key.ipv4.port_id = port_id; - key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr); - - status = app_pipeline_routing_add_arp_entry(app, - params->p, - &key, - &mac_addr); - if (status != 0) - printf(CMD_MSG_FAIL, "arp add"); - - return; - } /* arp add */ - - /* arp add default */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "add") == 0) && - (strcmp(tokens[1], "default") == 0)) { - uint32_t port_id; - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "arp add default"); - return; - } - - if (parser_read_uint32(&port_id, tokens[2])) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - status = app_pipeline_routing_add_default_arp_entry(app, - params->p, - port_id); - if (status != 0) - printf(CMD_MSG_FAIL, "arp add default"); - - return; - } /* arp add default */ - - /* arp del*/ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - strcmp(tokens[1], "default")) { - struct pipeline_routing_arp_key key; - struct in_addr ipv4; - uint32_t port_id; - - memset(&key, 0, sizeof(key)); - - if (n_tokens != 3) { - printf(CMD_MSG_MISMATCH_ARGS, "arp del"); - return; - } - - if (parser_read_uint32(&port_id, tokens[1])) { - printf(CMD_MSG_INVALID_ARG, "portid"); - return; - } - - if (parse_ipv4_addr(tokens[2], &ipv4)) { - printf(CMD_MSG_INVALID_ARG, "ipaddr"); - return; - } - - key.type = PIPELINE_ROUTING_ARP_IPV4; - key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr); - key.key.ipv4.port_id = port_id; - - status = app_pipeline_routing_delete_arp_entry(app, - params->p, - &key); - if (status != 0) - printf(CMD_MSG_FAIL, "arp del"); - - return; - } /* arp del */ - - /* arp del default */ - if ((n_tokens >= 2) && - (strcmp(tokens[0], "del") == 0) && - (strcmp(tokens[1], "default") == 0)) { - if (n_tokens != 2) { - printf(CMD_MSG_MISMATCH_ARGS, "arp del default"); - return; - } - - status = app_pipeline_routing_delete_default_arp_entry(app, - params->p); - if (status != 0) - printf(CMD_MSG_FAIL, "arp del default"); - - return; - } /* arp del default */ - - /* arp ls */ - if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) { - if (n_tokens != 1) { - printf(CMD_MSG_MISMATCH_ARGS, "arp ls"); - return; - } - - status = app_pipeline_routing_arp_ls(app, params->p); - if (status != 0) - printf(CMD_MSG_FAIL, "arp ls"); - - return; - } /* arp ls */ - - printf(CMD_MSG_FAIL, "arp"); -} - -static cmdline_parse_token_string_t cmd_arp_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_result, p_string, "p"); - -static cmdline_parse_token_num_t cmd_arp_p = - TOKEN_NUM_INITIALIZER(struct cmd_arp_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_arp_arp_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_result, arp_string, "arp"); - -static cmdline_parse_token_string_t cmd_arp_multi_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_result, multi_string, - TOKEN_STRING_MULTI); - -static cmdline_parse_inst_t cmd_arp = { - .f = cmd_arp_parsed, - .data = NULL, - .help_str = "arp add / add default / del / del default / ls", - .tokens = { - (void *)&cmd_arp_p_string, - (void *)&cmd_arp_p, - (void *)&cmd_arp_arp_string, - (void *)&cmd_arp_multi_string, - NULL, - }, -}; - -static cmdline_parse_ctx_t pipeline_cmds[] = { - (cmdline_parse_inst_t *)&cmd_route, - (cmdline_parse_inst_t *)&cmd_arp, - NULL, -}; - -static struct pipeline_fe_ops pipeline_routing_fe_ops = { - .f_init = app_pipeline_routing_init, - .f_post_init = app_pipeline_routing_post_init, - .f_free = app_pipeline_routing_free, - .f_track = app_pipeline_track_default, - .cmds = pipeline_cmds, -}; - -struct pipeline_type pipeline_routing = { - .name = "ROUTING", - .be_ops = &pipeline_routing_be_ops, - .fe_ops = &pipeline_routing_fe_ops, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.h b/examples/ip_pipeline/pipeline/pipeline_routing.h deleted file mode 100644 index f2492957..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_routing.h +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_ROUTING_H__ -#define __INCLUDE_PIPELINE_ROUTING_H__ - -#include "pipeline.h" -#include "pipeline_routing_be.h" - -/* - * Route - */ - -int -app_pipeline_routing_add_route(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_routing_route_key *key, - struct pipeline_routing_route_data *data); - -int -app_pipeline_routing_delete_route(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_routing_route_key *key); - -int -app_pipeline_routing_add_default_route(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id); - -int -app_pipeline_routing_delete_default_route(struct app_params *app, - uint32_t pipeline_id); - -/* - * ARP - */ - -int -app_pipeline_routing_add_arp_entry(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_routing_arp_key *key, - struct ether_addr *macaddr); - -int -app_pipeline_routing_delete_arp_entry(struct app_params *app, - uint32_t pipeline_id, - struct pipeline_routing_arp_key *key); - -int -app_pipeline_routing_add_default_arp_entry(struct app_params *app, - uint32_t pipeline_id, - uint32_t port_id); - -int -app_pipeline_routing_delete_default_arp_entry(struct app_params *app, - uint32_t pipeline_id); - -/* - * SETTINGS - */ -int -app_pipeline_routing_set_macaddr(struct app_params *app, - uint32_t pipeline_id); - -/* - * Pipeline type - */ -extern struct pipeline_type pipeline_routing; - -#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.c b/examples/ip_pipeline/pipeline/pipeline_routing_be.c deleted file mode 100644 index 6258a1a9..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_routing_be.c +++ /dev/null @@ -1,1966 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <unistd.h> - -#include <rte_common.h> -#include <rte_malloc.h> -#include <rte_ip.h> -#include <rte_byteorder.h> -#include <rte_table_lpm.h> -#include <rte_table_hash.h> -#include <rte_pipeline.h> - -#include "pipeline_routing_be.h" -#include "pipeline_actions_common.h" -#include "parser.h" -#include "hash_func.h" - -#define MPLS_LABEL(label, exp, s, ttl) \ - (((((uint64_t) (label)) & 0xFFFFFLLU) << 12) | \ - ((((uint64_t) (exp)) & 0x7LLU) << 9) | \ - ((((uint64_t) (s)) & 0x1LLU) << 8) | \ - (((uint64_t) (ttl)) & 0xFFLU)) - -#define RTE_SCHED_PORT_HIERARCHY(subport, pipe, \ - traffic_class, queue, color) \ - ((((uint64_t) (queue)) & 0x3) | \ - ((((uint64_t) (traffic_class)) & 0x3) << 2) | \ - ((((uint64_t) (color)) & 0x3) << 4) | \ - ((((uint64_t) (subport)) & 0xFFFF) << 16) | \ - ((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32)) - - -/* Network Byte Order (NBO) */ -#define SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr, ethertype) \ - (((uint64_t) macaddr) | (((uint64_t) rte_cpu_to_be_16(ethertype)) << 48)) - -#ifndef PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s -#define PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s 256 -#endif - -struct pipeline_routing { - struct pipeline p; - struct pipeline_routing_params params; - pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS]; - uint64_t macaddr[PIPELINE_MAX_PORT_OUT]; -} __rte_cache_aligned; - -/* - * Message handlers - */ -static void * -pipeline_routing_msg_req_custom_handler(struct pipeline *p, void *msg); - -static pipeline_msg_req_handler handlers[] = { - [PIPELINE_MSG_REQ_PING] = - pipeline_msg_req_ping_handler, - [PIPELINE_MSG_REQ_STATS_PORT_IN] = - pipeline_msg_req_stats_port_in_handler, - [PIPELINE_MSG_REQ_STATS_PORT_OUT] = - pipeline_msg_req_stats_port_out_handler, - [PIPELINE_MSG_REQ_STATS_TABLE] = - pipeline_msg_req_stats_table_handler, - [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = - pipeline_msg_req_port_in_enable_handler, - [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = - pipeline_msg_req_port_in_disable_handler, - [PIPELINE_MSG_REQ_CUSTOM] = - pipeline_routing_msg_req_custom_handler, -}; - -static void * -pipeline_routing_msg_req_route_add_handler(struct pipeline *p, - void *msg); - -static void * -pipeline_routing_msg_req_route_del_handler(struct pipeline *p, - void *msg); - -static void * -pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p, - void *msg); - -static void * -pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p, - void *msg); - -static void * -pipeline_routing_msg_req_arp_add_handler(struct pipeline *p, - void *msg); - -static void * -pipeline_routing_msg_req_arp_del_handler(struct pipeline *p, - void *msg); - -static void * -pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p, - void *msg); - -static void * -pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, - void *msg); - -static void * -pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p, - void *msg); - -static pipeline_msg_req_handler custom_handlers[] = { - [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] = - pipeline_routing_msg_req_route_add_handler, - [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL] = - pipeline_routing_msg_req_route_del_handler, - [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT] = - pipeline_routing_msg_req_route_add_default_handler, - [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT] = - pipeline_routing_msg_req_route_del_default_handler, - [PIPELINE_ROUTING_MSG_REQ_ARP_ADD] = - pipeline_routing_msg_req_arp_add_handler, - [PIPELINE_ROUTING_MSG_REQ_ARP_DEL] = - pipeline_routing_msg_req_arp_del_handler, - [PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT] = - pipeline_routing_msg_req_arp_add_default_handler, - [PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] = - pipeline_routing_msg_req_arp_del_default_handler, - [PIPELINE_ROUTING_MSG_REQ_SET_MACADDR] = - pipeline_routing_msg_req_set_macaddr_handler, -}; - -/* - * Routing table - */ -struct routing_table_entry { - struct rte_pipeline_table_entry head; - uint32_t flags; - uint32_t port_id; /* Output port ID */ - uint32_t ip; /* Next hop IP address (only valid for remote routes) */ - - /* ether_l2 */ - uint16_t data_offset; - uint16_t ether_l2_length; - uint64_t slab[4]; - uint16_t slab_offset[4]; -}; - -struct layout { - uint16_t a; - uint32_t b; - uint16_t c; -} __attribute__((__packed__)); - -#define MACADDR_DST_WRITE(slab_ptr, slab) \ -{ \ - struct layout *dst = (struct layout *) (slab_ptr); \ - struct layout *src = (struct layout *) &(slab); \ - \ - dst->b = src->b; \ - dst->c = src->c; \ -} - -static __rte_always_inline void -pkt_work_routing( - struct rte_mbuf *pkt, - struct rte_pipeline_table_entry *table_entry, - void *arg, - int arp, - int qinq, - int qinq_sched, - int mpls, - int mpls_color_mark) -{ - struct pipeline_routing *p_rt = arg; - - struct routing_table_entry *entry = - (struct routing_table_entry *) table_entry; - - struct ipv4_hdr *ip = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->params.ip_hdr_offset); - - enum rte_meter_color pkt_color = (enum rte_meter_color) - RTE_MBUF_METADATA_UINT32(pkt, p_rt->params.color_offset); - - struct pipeline_routing_arp_key_ipv4 *arp_key = - (struct pipeline_routing_arp_key_ipv4 *) - RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->params.arp_key_offset); - - uint64_t *slab0_ptr, *slab1_ptr, *slab2_ptr, *slab3_ptr, sched; - uint32_t ip_da, nh_ip, port_id; - uint16_t total_length, data_offset, ether_l2_length; - - /* Read */ - total_length = rte_bswap16(ip->total_length); - ip_da = ip->dst_addr; - data_offset = entry->data_offset; - ether_l2_length = entry->ether_l2_length; - slab0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[0]); - slab1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[1]); - slab2_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[2]); - slab3_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[3]); - - if (arp) { - port_id = entry->port_id; - nh_ip = entry->ip; - if (entry->flags & PIPELINE_ROUTING_ROUTE_LOCAL) - nh_ip = ip_da; - } - - /* Compute */ - total_length += ether_l2_length; - - if (qinq && qinq_sched) { - uint32_t dscp = ip->type_of_service >> 2; - uint32_t svlan, cvlan, tc, tc_q; - - if (qinq_sched == 1) { - uint64_t slab_qinq = rte_bswap64(entry->slab[0]); - - svlan = (slab_qinq >> 48) & 0xFFF; - cvlan = (slab_qinq >> 16) & 0xFFF; - tc = (dscp >> 2) & 0x3; - tc_q = dscp & 0x3; - } else { - uint32_t ip_src = rte_bswap32(ip->src_addr); - - svlan = 0; - cvlan = (ip_src >> 16) & 0xFFF; - tc = (ip_src >> 2) & 0x3; - tc_q = ip_src & 0x3; - } - sched = RTE_SCHED_PORT_HIERARCHY(svlan, - cvlan, - tc, - tc_q, - e_RTE_METER_GREEN); - } - - /* Write */ - pkt->data_off = data_offset; - pkt->data_len = total_length; - pkt->pkt_len = total_length; - - if ((qinq == 0) && (mpls == 0)) { - *slab0_ptr = entry->slab[0]; - - if (arp == 0) - MACADDR_DST_WRITE(slab1_ptr, entry->slab[1]); - } - - if (qinq) { - *slab0_ptr = entry->slab[0]; - *slab1_ptr = entry->slab[1]; - - if (arp == 0) - MACADDR_DST_WRITE(slab2_ptr, entry->slab[2]); - - if (qinq_sched) { - pkt->hash.sched.lo = sched & 0xFFFFFFFF; - pkt->hash.sched.hi = sched >> 32; - } - } - - if (mpls) { - if (mpls_color_mark) { - uint64_t mpls_exp = rte_bswap64( - (MPLS_LABEL(0, pkt_color, 0, 0) << 32) | - MPLS_LABEL(0, pkt_color, 0, 0)); - - *slab0_ptr = entry->slab[0] | mpls_exp; - *slab1_ptr = entry->slab[1] | mpls_exp; - *slab2_ptr = entry->slab[2]; - } else { - *slab0_ptr = entry->slab[0]; - *slab1_ptr = entry->slab[1]; - *slab2_ptr = entry->slab[2]; - } - - if (arp == 0) - MACADDR_DST_WRITE(slab3_ptr, entry->slab[3]); - } - - if (arp) { - arp_key->port_id = port_id; - arp_key->ip = nh_ip; - } -} - -static __rte_always_inline void -pkt4_work_routing( - struct rte_mbuf **pkts, - struct rte_pipeline_table_entry **table_entries, - void *arg, - int arp, - int qinq, - int qinq_sched, - int mpls, - int mpls_color_mark) -{ - struct pipeline_routing *p_rt = arg; - - struct routing_table_entry *entry0 = - (struct routing_table_entry *) table_entries[0]; - struct routing_table_entry *entry1 = - (struct routing_table_entry *) table_entries[1]; - struct routing_table_entry *entry2 = - (struct routing_table_entry *) table_entries[2]; - struct routing_table_entry *entry3 = - (struct routing_table_entry *) table_entries[3]; - - struct ipv4_hdr *ip0 = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT8_PTR(pkts[0], - p_rt->params.ip_hdr_offset); - struct ipv4_hdr *ip1 = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT8_PTR(pkts[1], - p_rt->params.ip_hdr_offset); - struct ipv4_hdr *ip2 = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT8_PTR(pkts[2], - p_rt->params.ip_hdr_offset); - struct ipv4_hdr *ip3 = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT8_PTR(pkts[3], - p_rt->params.ip_hdr_offset); - - enum rte_meter_color pkt0_color = (enum rte_meter_color) - RTE_MBUF_METADATA_UINT32(pkts[0], p_rt->params.color_offset); - enum rte_meter_color pkt1_color = (enum rte_meter_color) - RTE_MBUF_METADATA_UINT32(pkts[1], p_rt->params.color_offset); - enum rte_meter_color pkt2_color = (enum rte_meter_color) - RTE_MBUF_METADATA_UINT32(pkts[2], p_rt->params.color_offset); - enum rte_meter_color pkt3_color = (enum rte_meter_color) - RTE_MBUF_METADATA_UINT32(pkts[3], p_rt->params.color_offset); - - struct pipeline_routing_arp_key_ipv4 *arp_key0 = - (struct pipeline_routing_arp_key_ipv4 *) - RTE_MBUF_METADATA_UINT8_PTR(pkts[0], - p_rt->params.arp_key_offset); - struct pipeline_routing_arp_key_ipv4 *arp_key1 = - (struct pipeline_routing_arp_key_ipv4 *) - RTE_MBUF_METADATA_UINT8_PTR(pkts[1], - p_rt->params.arp_key_offset); - struct pipeline_routing_arp_key_ipv4 *arp_key2 = - (struct pipeline_routing_arp_key_ipv4 *) - RTE_MBUF_METADATA_UINT8_PTR(pkts[2], - p_rt->params.arp_key_offset); - struct pipeline_routing_arp_key_ipv4 *arp_key3 = - (struct pipeline_routing_arp_key_ipv4 *) - RTE_MBUF_METADATA_UINT8_PTR(pkts[3], - p_rt->params.arp_key_offset); - - uint64_t *slab0_ptr0, *slab1_ptr0, *slab2_ptr0, *slab3_ptr0; - uint64_t *slab0_ptr1, *slab1_ptr1, *slab2_ptr1, *slab3_ptr1; - uint64_t *slab0_ptr2, *slab1_ptr2, *slab2_ptr2, *slab3_ptr2; - uint64_t *slab0_ptr3, *slab1_ptr3, *slab2_ptr3, *slab3_ptr3; - uint64_t sched0, sched1, sched2, sched3; - - uint32_t ip_da0, nh_ip0, port_id0; - uint32_t ip_da1, nh_ip1, port_id1; - uint32_t ip_da2, nh_ip2, port_id2; - uint32_t ip_da3, nh_ip3, port_id3; - - uint16_t total_length0, data_offset0, ether_l2_length0; - uint16_t total_length1, data_offset1, ether_l2_length1; - uint16_t total_length2, data_offset2, ether_l2_length2; - uint16_t total_length3, data_offset3, ether_l2_length3; - - /* Read */ - total_length0 = rte_bswap16(ip0->total_length); - total_length1 = rte_bswap16(ip1->total_length); - total_length2 = rte_bswap16(ip2->total_length); - total_length3 = rte_bswap16(ip3->total_length); - - ip_da0 = ip0->dst_addr; - ip_da1 = ip1->dst_addr; - ip_da2 = ip2->dst_addr; - ip_da3 = ip3->dst_addr; - - data_offset0 = entry0->data_offset; - data_offset1 = entry1->data_offset; - data_offset2 = entry2->data_offset; - data_offset3 = entry3->data_offset; - - ether_l2_length0 = entry0->ether_l2_length; - ether_l2_length1 = entry1->ether_l2_length; - ether_l2_length2 = entry2->ether_l2_length; - ether_l2_length3 = entry3->ether_l2_length; - - slab0_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], - entry0->slab_offset[0]); - slab1_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], - entry0->slab_offset[1]); - slab2_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], - entry0->slab_offset[2]); - slab3_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], - entry0->slab_offset[3]); - - slab0_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], - entry1->slab_offset[0]); - slab1_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], - entry1->slab_offset[1]); - slab2_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], - entry1->slab_offset[2]); - slab3_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], - entry1->slab_offset[3]); - - slab0_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], - entry2->slab_offset[0]); - slab1_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], - entry2->slab_offset[1]); - slab2_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], - entry2->slab_offset[2]); - slab3_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], - entry2->slab_offset[3]); - - slab0_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], - entry3->slab_offset[0]); - slab1_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], - entry3->slab_offset[1]); - slab2_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], - entry3->slab_offset[2]); - slab3_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], - entry3->slab_offset[3]); - - if (arp) { - port_id0 = entry0->port_id; - nh_ip0 = entry0->ip; - if (entry0->flags & PIPELINE_ROUTING_ROUTE_LOCAL) - nh_ip0 = ip_da0; - - port_id1 = entry1->port_id; - nh_ip1 = entry1->ip; - if (entry1->flags & PIPELINE_ROUTING_ROUTE_LOCAL) - nh_ip1 = ip_da1; - - port_id2 = entry2->port_id; - nh_ip2 = entry2->ip; - if (entry2->flags & PIPELINE_ROUTING_ROUTE_LOCAL) - nh_ip2 = ip_da2; - - port_id3 = entry3->port_id; - nh_ip3 = entry3->ip; - if (entry3->flags & PIPELINE_ROUTING_ROUTE_LOCAL) - nh_ip3 = ip_da3; - } - - /* Compute */ - total_length0 += ether_l2_length0; - total_length1 += ether_l2_length1; - total_length2 += ether_l2_length2; - total_length3 += ether_l2_length3; - - if (qinq && qinq_sched) { - uint32_t dscp0 = ip0->type_of_service >> 2; - uint32_t dscp1 = ip1->type_of_service >> 2; - uint32_t dscp2 = ip2->type_of_service >> 2; - uint32_t dscp3 = ip3->type_of_service >> 2; - uint32_t svlan0, cvlan0, tc0, tc_q0; - uint32_t svlan1, cvlan1, tc1, tc_q1; - uint32_t svlan2, cvlan2, tc2, tc_q2; - uint32_t svlan3, cvlan3, tc3, tc_q3; - - if (qinq_sched == 1) { - uint64_t slab_qinq0 = rte_bswap64(entry0->slab[0]); - uint64_t slab_qinq1 = rte_bswap64(entry1->slab[0]); - uint64_t slab_qinq2 = rte_bswap64(entry2->slab[0]); - uint64_t slab_qinq3 = rte_bswap64(entry3->slab[0]); - - svlan0 = (slab_qinq0 >> 48) & 0xFFF; - svlan1 = (slab_qinq1 >> 48) & 0xFFF; - svlan2 = (slab_qinq2 >> 48) & 0xFFF; - svlan3 = (slab_qinq3 >> 48) & 0xFFF; - - cvlan0 = (slab_qinq0 >> 16) & 0xFFF; - cvlan1 = (slab_qinq1 >> 16) & 0xFFF; - cvlan2 = (slab_qinq2 >> 16) & 0xFFF; - cvlan3 = (slab_qinq3 >> 16) & 0xFFF; - - tc0 = (dscp0 >> 2) & 0x3; - tc1 = (dscp1 >> 2) & 0x3; - tc2 = (dscp2 >> 2) & 0x3; - tc3 = (dscp3 >> 2) & 0x3; - - tc_q0 = dscp0 & 0x3; - tc_q1 = dscp1 & 0x3; - tc_q2 = dscp2 & 0x3; - tc_q3 = dscp3 & 0x3; - } else { - uint32_t ip_src0 = rte_bswap32(ip0->src_addr); - uint32_t ip_src1 = rte_bswap32(ip1->src_addr); - uint32_t ip_src2 = rte_bswap32(ip2->src_addr); - uint32_t ip_src3 = rte_bswap32(ip3->src_addr); - - svlan0 = 0; - svlan1 = 0; - svlan2 = 0; - svlan3 = 0; - - cvlan0 = (ip_src0 >> 16) & 0xFFF; - cvlan1 = (ip_src1 >> 16) & 0xFFF; - cvlan2 = (ip_src2 >> 16) & 0xFFF; - cvlan3 = (ip_src3 >> 16) & 0xFFF; - - tc0 = (ip_src0 >> 2) & 0x3; - tc1 = (ip_src1 >> 2) & 0x3; - tc2 = (ip_src2 >> 2) & 0x3; - tc3 = (ip_src3 >> 2) & 0x3; - - tc_q0 = ip_src0 & 0x3; - tc_q1 = ip_src1 & 0x3; - tc_q2 = ip_src2 & 0x3; - tc_q3 = ip_src3 & 0x3; - } - - sched0 = RTE_SCHED_PORT_HIERARCHY(svlan0, - cvlan0, - tc0, - tc_q0, - e_RTE_METER_GREEN); - sched1 = RTE_SCHED_PORT_HIERARCHY(svlan1, - cvlan1, - tc1, - tc_q1, - e_RTE_METER_GREEN); - sched2 = RTE_SCHED_PORT_HIERARCHY(svlan2, - cvlan2, - tc2, - tc_q2, - e_RTE_METER_GREEN); - sched3 = RTE_SCHED_PORT_HIERARCHY(svlan3, - cvlan3, - tc3, - tc_q3, - e_RTE_METER_GREEN); - - } - - /* Write */ - pkts[0]->data_off = data_offset0; - pkts[1]->data_off = data_offset1; - pkts[2]->data_off = data_offset2; - pkts[3]->data_off = data_offset3; - - pkts[0]->data_len = total_length0; - pkts[1]->data_len = total_length1; - pkts[2]->data_len = total_length2; - pkts[3]->data_len = total_length3; - - pkts[0]->pkt_len = total_length0; - pkts[1]->pkt_len = total_length1; - pkts[2]->pkt_len = total_length2; - pkts[3]->pkt_len = total_length3; - - if ((qinq == 0) && (mpls == 0)) { - *slab0_ptr0 = entry0->slab[0]; - *slab0_ptr1 = entry1->slab[0]; - *slab0_ptr2 = entry2->slab[0]; - *slab0_ptr3 = entry3->slab[0]; - - if (arp == 0) { - MACADDR_DST_WRITE(slab1_ptr0, entry0->slab[1]); - MACADDR_DST_WRITE(slab1_ptr1, entry1->slab[1]); - MACADDR_DST_WRITE(slab1_ptr2, entry2->slab[1]); - MACADDR_DST_WRITE(slab1_ptr3, entry3->slab[1]); - } - } - - if (qinq) { - *slab0_ptr0 = entry0->slab[0]; - *slab0_ptr1 = entry1->slab[0]; - *slab0_ptr2 = entry2->slab[0]; - *slab0_ptr3 = entry3->slab[0]; - - *slab1_ptr0 = entry0->slab[1]; - *slab1_ptr1 = entry1->slab[1]; - *slab1_ptr2 = entry2->slab[1]; - *slab1_ptr3 = entry3->slab[1]; - - if (arp == 0) { - MACADDR_DST_WRITE(slab2_ptr0, entry0->slab[2]); - MACADDR_DST_WRITE(slab2_ptr1, entry1->slab[2]); - MACADDR_DST_WRITE(slab2_ptr2, entry2->slab[2]); - MACADDR_DST_WRITE(slab2_ptr3, entry3->slab[2]); - } - - if (qinq_sched) { - pkts[0]->hash.sched.lo = sched0 & 0xFFFFFFFF; - pkts[0]->hash.sched.hi = sched0 >> 32; - pkts[1]->hash.sched.lo = sched1 & 0xFFFFFFFF; - pkts[1]->hash.sched.hi = sched1 >> 32; - pkts[2]->hash.sched.lo = sched2 & 0xFFFFFFFF; - pkts[2]->hash.sched.hi = sched2 >> 32; - pkts[3]->hash.sched.lo = sched3 & 0xFFFFFFFF; - pkts[3]->hash.sched.hi = sched3 >> 32; - } - } - - if (mpls) { - if (mpls_color_mark) { - uint64_t mpls_exp0 = rte_bswap64( - (MPLS_LABEL(0, pkt0_color, 0, 0) << 32) | - MPLS_LABEL(0, pkt0_color, 0, 0)); - uint64_t mpls_exp1 = rte_bswap64( - (MPLS_LABEL(0, pkt1_color, 0, 0) << 32) | - MPLS_LABEL(0, pkt1_color, 0, 0)); - uint64_t mpls_exp2 = rte_bswap64( - (MPLS_LABEL(0, pkt2_color, 0, 0) << 32) | - MPLS_LABEL(0, pkt2_color, 0, 0)); - uint64_t mpls_exp3 = rte_bswap64( - (MPLS_LABEL(0, pkt3_color, 0, 0) << 32) | - MPLS_LABEL(0, pkt3_color, 0, 0)); - - *slab0_ptr0 = entry0->slab[0] | mpls_exp0; - *slab0_ptr1 = entry1->slab[0] | mpls_exp1; - *slab0_ptr2 = entry2->slab[0] | mpls_exp2; - *slab0_ptr3 = entry3->slab[0] | mpls_exp3; - - *slab1_ptr0 = entry0->slab[1] | mpls_exp0; - *slab1_ptr1 = entry1->slab[1] | mpls_exp1; - *slab1_ptr2 = entry2->slab[1] | mpls_exp2; - *slab1_ptr3 = entry3->slab[1] | mpls_exp3; - - *slab2_ptr0 = entry0->slab[2]; - *slab2_ptr1 = entry1->slab[2]; - *slab2_ptr2 = entry2->slab[2]; - *slab2_ptr3 = entry3->slab[2]; - } else { - *slab0_ptr0 = entry0->slab[0]; - *slab0_ptr1 = entry1->slab[0]; - *slab0_ptr2 = entry2->slab[0]; - *slab0_ptr3 = entry3->slab[0]; - - *slab1_ptr0 = entry0->slab[1]; - *slab1_ptr1 = entry1->slab[1]; - *slab1_ptr2 = entry2->slab[1]; - *slab1_ptr3 = entry3->slab[1]; - - *slab2_ptr0 = entry0->slab[2]; - *slab2_ptr1 = entry1->slab[2]; - *slab2_ptr2 = entry2->slab[2]; - *slab2_ptr3 = entry3->slab[2]; - } - - if (arp == 0) { - MACADDR_DST_WRITE(slab3_ptr0, entry0->slab[3]); - MACADDR_DST_WRITE(slab3_ptr1, entry1->slab[3]); - MACADDR_DST_WRITE(slab3_ptr2, entry2->slab[3]); - MACADDR_DST_WRITE(slab3_ptr3, entry3->slab[3]); - } - } - - if (arp) { - arp_key0->port_id = port_id0; - arp_key1->port_id = port_id1; - arp_key2->port_id = port_id2; - arp_key3->port_id = port_id3; - - arp_key0->ip = nh_ip0; - arp_key1->ip = nh_ip1; - arp_key2->ip = nh_ip2; - arp_key3->ip = nh_ip3; - } -} - -#define PKT_WORK_ROUTING_ETHERNET(arp) \ -static inline void \ -pkt_work_routing_ether_arp##arp( \ - struct rte_mbuf *pkt, \ - struct rte_pipeline_table_entry *table_entry, \ - void *arg) \ -{ \ - pkt_work_routing(pkt, table_entry, arg, arp, 0, 0, 0, 0);\ -} - -#define PKT4_WORK_ROUTING_ETHERNET(arp) \ -static inline void \ -pkt4_work_routing_ether_arp##arp( \ - struct rte_mbuf **pkts, \ - struct rte_pipeline_table_entry **table_entries, \ - void *arg) \ -{ \ - pkt4_work_routing(pkts, table_entries, arg, arp, 0, 0, 0, 0);\ -} - -#define routing_table_ah_hit_ether(arp) \ -PKT_WORK_ROUTING_ETHERNET(arp) \ -PKT4_WORK_ROUTING_ETHERNET(arp) \ -PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_arp##arp, \ - pkt_work_routing_ether_arp##arp, \ - pkt4_work_routing_ether_arp##arp) - -routing_table_ah_hit_ether(0) -routing_table_ah_hit_ether(1) - -#define PKT_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \ -static inline void \ -pkt_work_routing_ether_qinq_sched##sched##_arp##arp( \ - struct rte_mbuf *pkt, \ - struct rte_pipeline_table_entry *table_entry, \ - void *arg) \ -{ \ - pkt_work_routing(pkt, table_entry, arg, arp, 1, sched, 0, 0);\ -} - -#define PKT4_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \ -static inline void \ -pkt4_work_routing_ether_qinq_sched##sched##_arp##arp( \ - struct rte_mbuf **pkts, \ - struct rte_pipeline_table_entry **table_entries, \ - void *arg) \ -{ \ - pkt4_work_routing(pkts, table_entries, arg, arp, 1, sched, 0, 0);\ -} - -#define routing_table_ah_hit_ether_qinq(sched, arp) \ -PKT_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \ -PKT4_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \ -PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_qinq_sched##sched##_arp##arp,\ - pkt_work_routing_ether_qinq_sched##sched##_arp##arp, \ - pkt4_work_routing_ether_qinq_sched##sched##_arp##arp) - -routing_table_ah_hit_ether_qinq(0, 0) -routing_table_ah_hit_ether_qinq(1, 0) -routing_table_ah_hit_ether_qinq(2, 0) -routing_table_ah_hit_ether_qinq(0, 1) -routing_table_ah_hit_ether_qinq(1, 1) -routing_table_ah_hit_ether_qinq(2, 1) - -#define PKT_WORK_ROUTING_ETHERNET_MPLS(color, arp) \ -static inline void \ -pkt_work_routing_ether_mpls_color##color##_arp##arp( \ - struct rte_mbuf *pkt, \ - struct rte_pipeline_table_entry *table_entry, \ - void *arg) \ -{ \ - pkt_work_routing(pkt, table_entry, arg, arp, 0, 0, 1, color);\ -} - -#define PKT4_WORK_ROUTING_ETHERNET_MPLS(color, arp) \ -static inline void \ -pkt4_work_routing_ether_mpls_color##color##_arp##arp( \ - struct rte_mbuf **pkts, \ - struct rte_pipeline_table_entry **table_entries, \ - void *arg) \ -{ \ - pkt4_work_routing(pkts, table_entries, arg, arp, 0, 0, 1, color);\ -} - -#define routing_table_ah_hit_ether_mpls(color, arp) \ -PKT_WORK_ROUTING_ETHERNET_MPLS(color, arp) \ -PKT4_WORK_ROUTING_ETHERNET_MPLS(color, arp) \ -PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_mpls_color##color##_arp##arp,\ - pkt_work_routing_ether_mpls_color##color##_arp##arp, \ - pkt4_work_routing_ether_mpls_color##color##_arp##arp) - -routing_table_ah_hit_ether_mpls(0, 0) -routing_table_ah_hit_ether_mpls(1, 0) -routing_table_ah_hit_ether_mpls(0, 1) -routing_table_ah_hit_ether_mpls(1, 1) - -static rte_pipeline_table_action_handler_hit -get_routing_table_ah_hit(struct pipeline_routing *p) -{ - if (p->params.dbg_ah_disable) - return NULL; - - switch (p->params.encap) { - case PIPELINE_ROUTING_ENCAP_ETHERNET: - return (p->params.n_arp_entries) ? - routing_table_ah_hit_ether_arp1 : - routing_table_ah_hit_ether_arp0; - - case PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ: - if (p->params.n_arp_entries) - switch (p->params.qinq_sched) { - case 0: - return routing_table_ah_hit_ether_qinq_sched0_arp1; - case 1: - return routing_table_ah_hit_ether_qinq_sched1_arp1; - case 2: - return routing_table_ah_hit_ether_qinq_sched2_arp1; - default: - return NULL; - } - else - switch (p->params.qinq_sched) { - case 0: - return routing_table_ah_hit_ether_qinq_sched0_arp0; - case 1: - return routing_table_ah_hit_ether_qinq_sched1_arp0; - case 2: - return routing_table_ah_hit_ether_qinq_sched2_arp0; - default: - return NULL; - } - - case PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS: - if (p->params.n_arp_entries) - if (p->params.mpls_color_mark) - return routing_table_ah_hit_ether_mpls_color1_arp1; - else - return routing_table_ah_hit_ether_mpls_color0_arp1; - else - if (p->params.mpls_color_mark) - return routing_table_ah_hit_ether_mpls_color1_arp0; - else - return routing_table_ah_hit_ether_mpls_color0_arp0; - - default: - return NULL; - } -} - -/* - * ARP table - */ -struct arp_table_entry { - struct rte_pipeline_table_entry head; - uint64_t macaddr; -}; - -/** - * ARP table AH - */ -static inline void -pkt_work_arp( - struct rte_mbuf *pkt, - struct rte_pipeline_table_entry *table_entry, - __rte_unused void *arg) -{ - struct arp_table_entry *entry = (struct arp_table_entry *) table_entry; - - /* Read */ - uint64_t macaddr_dst = entry->macaddr; - uint64_t *slab_ptr = (uint64_t *) ((char *) pkt->buf_addr + - (pkt->data_off - 2)); - - /* Compute */ - - /* Write */ - MACADDR_DST_WRITE(slab_ptr, macaddr_dst); -} - -static inline void -pkt4_work_arp( - struct rte_mbuf **pkts, - struct rte_pipeline_table_entry **table_entries, - __rte_unused void *arg) -{ - struct arp_table_entry *entry0 = - (struct arp_table_entry *) table_entries[0]; - struct arp_table_entry *entry1 = - (struct arp_table_entry *) table_entries[1]; - struct arp_table_entry *entry2 = - (struct arp_table_entry *) table_entries[2]; - struct arp_table_entry *entry3 = - (struct arp_table_entry *) table_entries[3]; - - /* Read */ - uint64_t macaddr_dst0 = entry0->macaddr; - uint64_t macaddr_dst1 = entry1->macaddr; - uint64_t macaddr_dst2 = entry2->macaddr; - uint64_t macaddr_dst3 = entry3->macaddr; - - uint64_t *slab_ptr0 = (uint64_t *) ((char *) pkts[0]->buf_addr + - (pkts[0]->data_off - 2)); - uint64_t *slab_ptr1 = (uint64_t *) ((char *) pkts[1]->buf_addr + - (pkts[1]->data_off - 2)); - uint64_t *slab_ptr2 = (uint64_t *) ((char *) pkts[2]->buf_addr + - (pkts[2]->data_off - 2)); - uint64_t *slab_ptr3 = (uint64_t *) ((char *) pkts[3]->buf_addr + - (pkts[3]->data_off - 2)); - - /* Compute */ - - /* Write */ - MACADDR_DST_WRITE(slab_ptr0, macaddr_dst0); - MACADDR_DST_WRITE(slab_ptr1, macaddr_dst1); - MACADDR_DST_WRITE(slab_ptr2, macaddr_dst2); - MACADDR_DST_WRITE(slab_ptr3, macaddr_dst3); -} - -PIPELINE_TABLE_AH_HIT(arp_table_ah_hit, - pkt_work_arp, - pkt4_work_arp); - -static rte_pipeline_table_action_handler_hit -get_arp_table_ah_hit(struct pipeline_routing *p) -{ - if (p->params.dbg_ah_disable) - return NULL; - - return arp_table_ah_hit; -} - -/* - * Argument parsing - */ -int -pipeline_routing_parse_args(struct pipeline_routing_params *p, - struct pipeline_params *params) -{ - uint32_t n_routes_present = 0; - uint32_t port_local_dest_present = 0; - uint32_t encap_present = 0; - uint32_t qinq_sched_present = 0; - uint32_t mpls_color_mark_present = 0; - uint32_t n_arp_entries_present = 0; - uint32_t ip_hdr_offset_present = 0; - uint32_t arp_key_offset_present = 0; - uint32_t color_offset_present = 0; - uint32_t dbg_ah_disable_present = 0; - uint32_t i; - - /* default values */ - p->n_routes = PIPELINE_ROUTING_N_ROUTES_DEFAULT; - p->port_local_dest = params->n_ports_out - 1; - p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET; - p->qinq_sched = 0; - p->mpls_color_mark = 0; - p->n_arp_entries = 0; - p->dbg_ah_disable = 0; - - for (i = 0; i < params->n_args; i++) { - char *arg_name = params->args_name[i]; - char *arg_value = params->args_value[i]; - - /* n_routes */ - if (strcmp(arg_name, "n_routes") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - n_routes_present == 0, params->name, - arg_name); - n_routes_present = 1; - - status = parser_read_uint32(&p->n_routes, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && - (p->n_routes != 0)), params->name, - arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - /* port_local_dest */ - if (strcmp(arg_name, "port_local_dest") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - port_local_dest_present == 0, params->name, - arg_name); - port_local_dest_present = 1; - - status = parser_read_uint32(&p->port_local_dest, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL(((status == 0) && - (p->port_local_dest < params->n_ports_out)), - params->name, arg_name, arg_value); - - continue; - } - - /* encap */ - if (strcmp(arg_name, "encap") == 0) { - PIPELINE_PARSE_ERR_DUPLICATE(encap_present == 0, - params->name, arg_name); - encap_present = 1; - - /* ethernet */ - if (strcmp(arg_value, "ethernet") == 0) { - p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET; - continue; - } - - /* ethernet_qinq */ - if (strcmp(arg_value, "ethernet_qinq") == 0) { - p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ; - continue; - } - - /* ethernet_mpls */ - if (strcmp(arg_value, "ethernet_mpls") == 0) { - p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS; - continue; - } - - /* any other */ - PIPELINE_PARSE_ERR_INV_VAL(0, params->name, - arg_name, arg_value); - } - - /* qinq_sched */ - if (strcmp(arg_name, "qinq_sched") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - qinq_sched_present == 0, params->name, - arg_name); - qinq_sched_present = 1; - - status = parser_read_arg_bool(arg_value); - if (status == -EINVAL) { - if (strcmp(arg_value, "test") == 0) { - p->qinq_sched = 2; - continue; - } - } else { - p->qinq_sched = status; - continue; - } - - PIPELINE_PARSE_ERR_INV_VAL(0, params->name, - arg_name, arg_value); - } - - /* mpls_color_mark */ - if (strcmp(arg_name, "mpls_color_mark") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - mpls_color_mark_present == 0, - params->name, arg_name); - mpls_color_mark_present = 1; - - - status = parser_read_arg_bool(arg_value); - if (status >= 0) { - p->mpls_color_mark = status; - continue; - } - - PIPELINE_PARSE_ERR_INV_VAL(0, params->name, - arg_name, arg_value); - } - - /* n_arp_entries */ - if (strcmp(arg_name, "n_arp_entries") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - n_arp_entries_present == 0, params->name, - arg_name); - n_arp_entries_present = 1; - - status = parser_read_uint32(&p->n_arp_entries, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* ip_hdr_offset */ - if (strcmp(arg_name, "ip_hdr_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - ip_hdr_offset_present == 0, params->name, - arg_name); - ip_hdr_offset_present = 1; - - status = parser_read_uint32(&p->ip_hdr_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* arp_key_offset */ - if (strcmp(arg_name, "arp_key_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - arp_key_offset_present == 0, params->name, - arg_name); - arp_key_offset_present = 1; - - status = parser_read_uint32(&p->arp_key_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* color_offset */ - if (strcmp(arg_name, "color_offset") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - color_offset_present == 0, params->name, - arg_name); - color_offset_present = 1; - - status = parser_read_uint32(&p->color_offset, - arg_value); - PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), - params->name, arg_name, arg_value); - PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), - params->name, arg_name, arg_value); - - continue; - } - - /* debug */ - if (strcmp(arg_name, "dbg_ah_disable") == 0) { - int status; - - PIPELINE_PARSE_ERR_DUPLICATE( - dbg_ah_disable_present == 0, params->name, - arg_name); - dbg_ah_disable_present = 1; - - status = parser_read_arg_bool(arg_value); - if (status >= 0) { - p->dbg_ah_disable = status; - continue; - } - - PIPELINE_PARSE_ERR_INV_VAL(0, params->name, - arg_name, arg_value); - - continue; - } - - /* any other */ - PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); - } - - /* Check that mandatory arguments are present */ - PIPELINE_PARSE_ERR_MANDATORY(ip_hdr_offset_present, params->name, - "ip_hdr_offset"); - - /* Check relations between arguments */ - switch (p->encap) { - case PIPELINE_ROUTING_ENCAP_ETHERNET: - PIPELINE_ARG_CHECK((!p->qinq_sched), "Parse error in " - "section \"%s\": encap = ethernet, therefore " - "qinq_sched = yes/test is not allowed", - params->name); - PIPELINE_ARG_CHECK((!p->mpls_color_mark), "Parse error " - "in section \"%s\": encap = ethernet, therefore " - "mpls_color_mark = yes is not allowed", - params->name); - PIPELINE_ARG_CHECK((!color_offset_present), "Parse error " - "in section \"%s\": encap = ethernet, therefore " - "color_offset is not allowed", - params->name); - break; - - case PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ: - PIPELINE_ARG_CHECK((!p->mpls_color_mark), "Parse error " - "in section \"%s\": encap = ethernet_qinq, " - "therefore mpls_color_mark = yes is not allowed", - params->name); - PIPELINE_ARG_CHECK((!color_offset_present), "Parse error " - "in section \"%s\": encap = ethernet_qinq, " - "therefore color_offset is not allowed", - params->name); - break; - - case PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS: - PIPELINE_ARG_CHECK((!p->qinq_sched), "Parse error in " - "section \"%s\": encap = ethernet_mpls, therefore " - "qinq_sched = yes/test is not allowed", - params->name); - break; - } - - PIPELINE_ARG_CHECK((!(p->n_arp_entries && - (!arp_key_offset_present))), "Parse error in section " - "\"%s\": n_arp_entries is set while " - "arp_key_offset is not set", params->name); - - PIPELINE_ARG_CHECK((!((p->n_arp_entries == 0) && - arp_key_offset_present)), "Parse error in section " - "\"%s\": arp_key_offset present while " - "n_arp_entries is not set", params->name); - - return 0; -} - -static void * -pipeline_routing_init(struct pipeline_params *params, - __rte_unused void *arg) -{ - struct pipeline *p; - struct pipeline_routing *p_rt; - uint32_t size, i; - - /* Check input arguments */ - if ((params == NULL) || - (params->n_ports_in == 0) || - (params->n_ports_out == 0)) - return NULL; - - /* Memory allocation */ - size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing)); - p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); - p_rt = (struct pipeline_routing *) p; - if (p == NULL) - return NULL; - - strcpy(p->name, params->name); - p->log_level = params->log_level; - - PLOG(p, HIGH, "Routing"); - - /* Parse arguments */ - if (pipeline_routing_parse_args(&p_rt->params, params)) - return NULL; - - /* Pipeline */ - { - struct rte_pipeline_params pipeline_params = { - .name = params->name, - .socket_id = params->socket_id, - .offset_port_id = 0, - }; - - p->p = rte_pipeline_create(&pipeline_params); - if (p->p == NULL) { - rte_free(p); - return NULL; - } - } - - /* Input ports */ - p->n_ports_in = params->n_ports_in; - for (i = 0; i < p->n_ports_in; i++) { - struct rte_pipeline_port_in_params port_params = { - .ops = pipeline_port_in_params_get_ops( - ¶ms->port_in[i]), - .arg_create = pipeline_port_in_params_convert( - ¶ms->port_in[i]), - .f_action = NULL, - .arg_ah = NULL, - .burst_size = params->port_in[i].burst_size, - }; - - int status = rte_pipeline_port_in_create(p->p, - &port_params, - &p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Output ports */ - p->n_ports_out = params->n_ports_out; - for (i = 0; i < p->n_ports_out; i++) { - struct rte_pipeline_port_out_params port_params = { - .ops = pipeline_port_out_params_get_ops( - ¶ms->port_out[i]), - .arg_create = pipeline_port_out_params_convert( - ¶ms->port_out[i]), - .f_action = NULL, - .arg_ah = NULL, - }; - - int status = rte_pipeline_port_out_create(p->p, - &port_params, - &p->port_out_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Routing table */ - p->n_tables = 1; - { - struct rte_table_lpm_params table_lpm_params = { - .name = p->name, - .n_rules = p_rt->params.n_routes, - .number_tbl8s = PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s, - .flags = 0, - .entry_unique_size = sizeof(struct routing_table_entry), - .offset = p_rt->params.ip_hdr_offset + - __builtin_offsetof(struct ipv4_hdr, dst_addr), - }; - - struct rte_pipeline_table_params table_params = { - .ops = &rte_table_lpm_ops, - .arg_create = &table_lpm_params, - .f_action_hit = get_routing_table_ah_hit(p_rt), - .f_action_miss = NULL, - .arg_ah = p_rt, - .action_data_size = - sizeof(struct routing_table_entry) - - sizeof(struct rte_pipeline_table_entry), - }; - - int status; - - status = rte_pipeline_table_create(p->p, - &table_params, - &p->table_id[0]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* ARP table configuration */ - if (p_rt->params.n_arp_entries) { - struct rte_table_hash_params table_arp_params = { - .name = p->name, - .key_size = 8, - .key_offset = p_rt->params.arp_key_offset, - .key_mask = NULL, - .n_keys = p_rt->params.n_arp_entries, - .n_buckets = - rte_align32pow2(p_rt->params.n_arp_entries / 4), - .f_hash = hash_default_key8, - .seed = 0, - }; - - struct rte_pipeline_table_params table_params = { - .ops = &rte_table_hash_key8_ext_ops, - .arg_create = &table_arp_params, - .f_action_hit = get_arp_table_ah_hit(p_rt), - .f_action_miss = NULL, - .arg_ah = p_rt, - .action_data_size = sizeof(struct arp_table_entry) - - sizeof(struct rte_pipeline_table_entry), - }; - - int status; - - status = rte_pipeline_table_create(p->p, - &table_params, - &p->table_id[1]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - - p->n_tables++; - } - - /* Connecting input ports to tables */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_connect_to_table(p->p, - p->port_in_id[i], - p->table_id[0]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Enable input ports */ - for (i = 0; i < p->n_ports_in; i++) { - int status = rte_pipeline_port_in_enable(p->p, - p->port_in_id[i]); - - if (status) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - } - - /* Check pipeline consistency */ - if (rte_pipeline_check(p->p) < 0) { - rte_pipeline_free(p->p); - rte_free(p); - return NULL; - } - - /* Message queues */ - p->n_msgq = params->n_msgq; - for (i = 0; i < p->n_msgq; i++) - p->msgq_in[i] = params->msgq_in[i]; - for (i = 0; i < p->n_msgq; i++) - p->msgq_out[i] = params->msgq_out[i]; - - /* Message handlers */ - memcpy(p->handlers, handlers, sizeof(p->handlers)); - memcpy(p_rt->custom_handlers, - custom_handlers, - sizeof(p_rt->custom_handlers)); - - return p; -} - -static int -pipeline_routing_free(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if (p == NULL) - return -1; - - /* Free resources */ - rte_pipeline_free(p->p); - rte_free(p); - return 0; -} - -static int -pipeline_routing_timer(void *pipeline) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - pipeline_msg_req_handle(p); - rte_pipeline_flush(p->p); - - return 0; -} - -void * -pipeline_routing_msg_req_custom_handler(struct pipeline *p, - void *msg) -{ - struct pipeline_routing *p_rt = (struct pipeline_routing *) p; - struct pipeline_custom_msg_req *req = msg; - pipeline_msg_req_handler f_handle; - - f_handle = (req->subtype < PIPELINE_ROUTING_MSG_REQS) ? - p_rt->custom_handlers[req->subtype] : - pipeline_msg_req_invalid_handler; - - if (f_handle == NULL) - f_handle = pipeline_msg_req_invalid_handler; - - return f_handle(p, req); -} - -void * -pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) -{ - struct pipeline_routing *p_rt = (struct pipeline_routing *) p; - struct pipeline_routing_route_add_msg_req *req = msg; - struct pipeline_routing_route_add_msg_rsp *rsp = msg; - - struct rte_table_lpm_key key = { - .ip = req->key.key.ipv4.ip, - .depth = req->key.key.ipv4.depth, - }; - - struct routing_table_entry entry_arp0 = { - .head = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[req->data.port_id]}, - }, - - .flags = req->data.flags, - .port_id = req->data.port_id, - .ip = 0, - .data_offset = 0, - .ether_l2_length = 0, - .slab = {0}, - .slab_offset = {0}, - }; - - struct routing_table_entry entry_arp1 = { - .head = { - .action = RTE_PIPELINE_ACTION_TABLE, - {.table_id = p->table_id[1]}, - }, - - .flags = req->data.flags, - .port_id = req->data.port_id, - .ip = rte_bswap32(req->data.ethernet.ip), - .data_offset = 0, - .ether_l2_length = 0, - .slab = {0}, - .slab_offset = {0}, - }; - - struct rte_pipeline_table_entry *entry = (p_rt->params.n_arp_entries) ? - (struct rte_pipeline_table_entry *) &entry_arp1 : - (struct rte_pipeline_table_entry *) &entry_arp0; - - if ((req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) || - ((p_rt->params.n_arp_entries == 0) && - (req->data.flags & PIPELINE_ROUTING_ROUTE_ARP)) || - (p_rt->params.n_arp_entries && - ((req->data.flags & PIPELINE_ROUTING_ROUTE_ARP) == 0)) || - ((p_rt->params.encap != PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) && - (req->data.flags & PIPELINE_ROUTING_ROUTE_QINQ)) || - ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) && - ((req->data.flags & PIPELINE_ROUTING_ROUTE_QINQ) == 0)) || - ((p_rt->params.encap != PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) && - (req->data.flags & PIPELINE_ROUTING_ROUTE_MPLS)) || - ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) && - ((req->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) == 0))) { - rsp->status = -1; - return rsp; - } - - /* Ether - ARP off */ - if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) && - (p_rt->params.n_arp_entries == 0)) { - uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; - uint64_t macaddr_dst; - uint64_t ethertype = ETHER_TYPE_IPv4; - - macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr)); - macaddr_dst = rte_bswap64(macaddr_dst << 16); - - entry_arp0.slab[0] = - SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype); - entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8; - - entry_arp0.slab[1] = rte_bswap64(macaddr_dst); - entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8; - - entry_arp0.data_offset = entry_arp0.slab_offset[1] + 2 - - sizeof(struct rte_mbuf); - entry_arp0.ether_l2_length = 14; - } - - /* Ether - ARP on */ - if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) && - p_rt->params.n_arp_entries) { - uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; - uint64_t ethertype = ETHER_TYPE_IPv4; - - entry_arp1.slab[0] = - SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype); - entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8; - - entry_arp1.data_offset = entry_arp1.slab_offset[0] - 6 - - sizeof(struct rte_mbuf); - entry_arp1.ether_l2_length = 14; - } - - /* Ether QinQ - ARP off */ - if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) && - (p_rt->params.n_arp_entries == 0)) { - uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; - uint64_t macaddr_dst; - uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4; - uint64_t ethertype_vlan = 0x8100; - uint64_t ethertype_qinq = 0x9100; - uint64_t svlan = req->data.l2.qinq.svlan; - uint64_t cvlan = req->data.l2.qinq.cvlan; - - macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr)); - macaddr_dst = rte_bswap64(macaddr_dst << 16); - - entry_arp0.slab[0] = rte_bswap64((svlan << 48) | - (ethertype_vlan << 32) | - (cvlan << 16) | - ethertype_ipv4); - entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8; - - entry_arp0.slab[1] = - SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_qinq); - entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8; - - entry_arp0.slab[2] = rte_bswap64(macaddr_dst); - entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset - 3 * 8; - - entry_arp0.data_offset = entry_arp0.slab_offset[2] + 2 - - sizeof(struct rte_mbuf); - entry_arp0.ether_l2_length = 22; - } - - /* Ether QinQ - ARP on */ - if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) && - p_rt->params.n_arp_entries) { - uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; - uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4; - uint64_t ethertype_vlan = 0x8100; - uint64_t ethertype_qinq = 0x9100; - uint64_t svlan = req->data.l2.qinq.svlan; - uint64_t cvlan = req->data.l2.qinq.cvlan; - - entry_arp1.slab[0] = rte_bswap64((svlan << 48) | - (ethertype_vlan << 32) | - (cvlan << 16) | - ethertype_ipv4); - entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8; - - entry_arp1.slab[1] = - SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_qinq); - entry_arp1.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8; - - entry_arp1.data_offset = entry_arp1.slab_offset[1] - 6 - - sizeof(struct rte_mbuf); - entry_arp1.ether_l2_length = 22; - } - - /* Ether MPLS - ARP off */ - if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) && - (p_rt->params.n_arp_entries == 0)) { - uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; - uint64_t macaddr_dst; - uint64_t ethertype_mpls = 0x8847; - - uint64_t label0 = req->data.l2.mpls.labels[0]; - uint64_t label1 = req->data.l2.mpls.labels[1]; - uint64_t label2 = req->data.l2.mpls.labels[2]; - uint64_t label3 = req->data.l2.mpls.labels[3]; - uint32_t n_labels = req->data.l2.mpls.n_labels; - - macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr)); - macaddr_dst = rte_bswap64(macaddr_dst << 16); - - switch (n_labels) { - case 1: - entry_arp0.slab[0] = 0; - entry_arp0.slab_offset[0] = - p_rt->params.ip_hdr_offset - 8; - - entry_arp0.slab[1] = rte_bswap64( - MPLS_LABEL(label0, 0, 1, 0)); - entry_arp0.slab_offset[1] = - p_rt->params.ip_hdr_offset - 8; - break; - - case 2: - entry_arp0.slab[0] = 0; - entry_arp0.slab_offset[0] = - p_rt->params.ip_hdr_offset - 8; - - entry_arp0.slab[1] = rte_bswap64( - (MPLS_LABEL(label0, 0, 0, 0) << 32) | - MPLS_LABEL(label1, 0, 1, 0)); - entry_arp0.slab_offset[1] = - p_rt->params.ip_hdr_offset - 8; - break; - - case 3: - entry_arp0.slab[0] = rte_bswap64( - (MPLS_LABEL(label1, 0, 0, 0) << 32) | - MPLS_LABEL(label2, 0, 1, 0)); - entry_arp0.slab_offset[0] = - p_rt->params.ip_hdr_offset - 8; - - entry_arp0.slab[1] = rte_bswap64( - MPLS_LABEL(label0, 0, 0, 0)); - entry_arp0.slab_offset[1] = - p_rt->params.ip_hdr_offset - 2 * 8; - break; - - case 4: - entry_arp0.slab[0] = rte_bswap64( - (MPLS_LABEL(label2, 0, 0, 0) << 32) | - MPLS_LABEL(label3, 0, 1, 0)); - entry_arp0.slab_offset[0] = - p_rt->params.ip_hdr_offset - 8; - - entry_arp0.slab[1] = rte_bswap64( - (MPLS_LABEL(label0, 0, 0, 0) << 32) | - MPLS_LABEL(label1, 0, 0, 0)); - entry_arp0.slab_offset[1] = - p_rt->params.ip_hdr_offset - 2 * 8; - break; - - default: - rsp->status = -1; - return rsp; - } - - entry_arp0.slab[2] = - SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_mpls); - entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset - - (n_labels * 4 + 8); - - entry_arp0.slab[3] = rte_bswap64(macaddr_dst); - entry_arp0.slab_offset[3] = p_rt->params.ip_hdr_offset - - (n_labels * 4 + 2 * 8); - - entry_arp0.data_offset = entry_arp0.slab_offset[3] + 2 - - sizeof(struct rte_mbuf); - entry_arp0.ether_l2_length = n_labels * 4 + 14; - } - - /* Ether MPLS - ARP on */ - if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) && - p_rt->params.n_arp_entries) { - uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; - uint64_t ethertype_mpls = 0x8847; - - uint64_t label0 = req->data.l2.mpls.labels[0]; - uint64_t label1 = req->data.l2.mpls.labels[1]; - uint64_t label2 = req->data.l2.mpls.labels[2]; - uint64_t label3 = req->data.l2.mpls.labels[3]; - uint32_t n_labels = req->data.l2.mpls.n_labels; - - switch (n_labels) { - case 1: - entry_arp1.slab[0] = 0; - entry_arp1.slab_offset[0] = - p_rt->params.ip_hdr_offset - 8; - - entry_arp1.slab[1] = rte_bswap64( - MPLS_LABEL(label0, 0, 1, 0)); - entry_arp1.slab_offset[1] = - p_rt->params.ip_hdr_offset - 8; - break; - - case 2: - entry_arp1.slab[0] = 0; - entry_arp1.slab_offset[0] = - p_rt->params.ip_hdr_offset - 8; - - entry_arp1.slab[1] = rte_bswap64( - (MPLS_LABEL(label0, 0, 0, 0) << 32) | - MPLS_LABEL(label1, 0, 1, 0)); - entry_arp1.slab_offset[1] = - p_rt->params.ip_hdr_offset - 8; - break; - - case 3: - entry_arp1.slab[0] = rte_bswap64( - (MPLS_LABEL(label1, 0, 0, 0) << 32) | - MPLS_LABEL(label2, 0, 1, 0)); - entry_arp1.slab_offset[0] = - p_rt->params.ip_hdr_offset - 8; - - entry_arp1.slab[1] = rte_bswap64( - MPLS_LABEL(label0, 0, 0, 0)); - entry_arp1.slab_offset[1] = - p_rt->params.ip_hdr_offset - 2 * 8; - break; - - case 4: - entry_arp1.slab[0] = rte_bswap64( - (MPLS_LABEL(label2, 0, 0, 0) << 32) | - MPLS_LABEL(label3, 0, 1, 0)); - entry_arp1.slab_offset[0] = - p_rt->params.ip_hdr_offset - 8; - - entry_arp1.slab[1] = rte_bswap64( - (MPLS_LABEL(label0, 0, 0, 0) << 32) | - MPLS_LABEL(label1, 0, 0, 0)); - entry_arp1.slab_offset[1] = - p_rt->params.ip_hdr_offset - 2 * 8; - break; - - default: - rsp->status = -1; - return rsp; - } - - entry_arp1.slab[2] = - SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_mpls); - entry_arp1.slab_offset[2] = p_rt->params.ip_hdr_offset - - (n_labels * 4 + 8); - - entry_arp1.data_offset = entry_arp1.slab_offset[2] - 6 - - sizeof(struct rte_mbuf); - entry_arp1.ether_l2_length = n_labels * 4 + 14; - } - - rsp->status = rte_pipeline_table_entry_add(p->p, - p->table_id[0], - &key, - entry, - &rsp->key_found, - (struct rte_pipeline_table_entry **) &rsp->entry_ptr); - - return rsp; -} - -void * -pipeline_routing_msg_req_route_del_handler(struct pipeline *p, void *msg) -{ - struct pipeline_routing_route_delete_msg_req *req = msg; - struct pipeline_routing_route_delete_msg_rsp *rsp = msg; - - struct rte_table_lpm_key key = { - .ip = req->key.key.ipv4.ip, - .depth = req->key.key.ipv4.depth, - }; - - if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) { - rsp->status = -1; - return rsp; - } - - rsp->status = rte_pipeline_table_entry_delete(p->p, - p->table_id[0], - &key, - &rsp->key_found, - NULL); - - return rsp; -} - -void * -pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p, - void *msg) -{ - struct pipeline_routing_route_add_default_msg_req *req = msg; - struct pipeline_routing_route_add_default_msg_rsp *rsp = msg; - - struct routing_table_entry default_entry = { - .head = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[req->port_id]}, - }, - - .flags = 0, - .port_id = 0, - .ip = 0, - }; - - rsp->status = rte_pipeline_table_default_entry_add(p->p, - p->table_id[0], - (struct rte_pipeline_table_entry *) &default_entry, - (struct rte_pipeline_table_entry **) &rsp->entry_ptr); - - return rsp; -} - -void * -pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p, - void *msg) -{ - struct pipeline_routing_route_delete_default_msg_rsp *rsp = msg; - - rsp->status = rte_pipeline_table_default_entry_delete(p->p, - p->table_id[0], - NULL); - - return rsp; -} - -void * -pipeline_routing_msg_req_arp_add_handler(struct pipeline *p, void *msg) -{ - struct pipeline_routing_arp_add_msg_req *req = msg; - struct pipeline_routing_arp_add_msg_rsp *rsp = msg; - - struct pipeline_routing_arp_key_ipv4 key = { - .port_id = req->key.key.ipv4.port_id, - .ip = rte_bswap32(req->key.key.ipv4.ip), - }; - - struct arp_table_entry entry = { - .head = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[req->key.key.ipv4.port_id]}, - }, - - .macaddr = 0, /* set below */ - }; - - if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) { - rsp->status = -1; - return rsp; - } - - entry.macaddr = *((uint64_t *)&(req->macaddr)); - entry.macaddr = entry.macaddr << 16; - - rsp->status = rte_pipeline_table_entry_add(p->p, - p->table_id[1], - &key, - (struct rte_pipeline_table_entry *) &entry, - &rsp->key_found, - (struct rte_pipeline_table_entry **) &rsp->entry_ptr); - - return rsp; -} - -void * -pipeline_routing_msg_req_arp_del_handler(struct pipeline *p, void *msg) -{ - struct pipeline_routing_arp_delete_msg_req *req = msg; - struct pipeline_routing_arp_delete_msg_rsp *rsp = msg; - - struct pipeline_routing_arp_key_ipv4 key = { - .port_id = req->key.key.ipv4.port_id, - .ip = rte_bswap32(req->key.key.ipv4.ip), - }; - - if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) { - rsp->status = -1; - return rsp; - } - - rsp->status = rte_pipeline_table_entry_delete(p->p, - p->table_id[1], - &key, - &rsp->key_found, - NULL); - - return rsp; -} - -void * -pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p, void *msg) -{ - struct pipeline_routing_arp_add_default_msg_req *req = msg; - struct pipeline_routing_arp_add_default_msg_rsp *rsp = msg; - - struct arp_table_entry default_entry = { - .head = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[req->port_id]}, - }, - - .macaddr = 0, - }; - - rsp->status = rte_pipeline_table_default_entry_add(p->p, - p->table_id[1], - (struct rte_pipeline_table_entry *) &default_entry, - (struct rte_pipeline_table_entry **) &rsp->entry_ptr); - - return rsp; -} - -void * -pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg) -{ - struct pipeline_routing_arp_delete_default_msg_rsp *rsp = msg; - - rsp->status = rte_pipeline_table_default_entry_delete(p->p, - p->table_id[1], - NULL); - - return rsp; -} - -void * -pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p, void *msg) -{ - struct pipeline_routing *p_rt = (struct pipeline_routing *) p; - struct pipeline_routing_set_macaddr_msg_req *req = msg; - struct pipeline_routing_set_macaddr_msg_rsp *rsp = msg; - uint32_t port_id; - - for (port_id = 0; port_id < p->n_ports_out; port_id++) - p_rt->macaddr[port_id] = req->macaddr[port_id]; - - rsp->status = 0; - - return rsp; -} - -struct pipeline_be_ops pipeline_routing_be_ops = { - .f_init = pipeline_routing_init, - .f_free = pipeline_routing_free, - .f_run = NULL, - .f_timer = pipeline_routing_timer, -}; diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.h b/examples/ip_pipeline/pipeline/pipeline_routing_be.h deleted file mode 100644 index 7140ee40..00000000 --- a/examples/ip_pipeline/pipeline/pipeline_routing_be.h +++ /dev/null @@ -1,283 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_ROUTING_BE_H__ -#define __INCLUDE_PIPELINE_ROUTING_BE_H__ - -#include <rte_ether.h> - -#include "pipeline_common_be.h" - -/* - * Pipeline argument parsing - */ -#ifndef PIPELINE_ROUTING_N_ROUTES_DEFAULT -#define PIPELINE_ROUTING_N_ROUTES_DEFAULT 4096 -#endif - -enum pipeline_routing_encap { - PIPELINE_ROUTING_ENCAP_ETHERNET = 0, - PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ, - PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS, -}; - -struct pipeline_routing_params { - /* routing */ - uint32_t n_routes; - uint32_t port_local_dest; - - /* routing packet encapsulation */ - enum pipeline_routing_encap encap; - uint32_t qinq_sched; - uint32_t mpls_color_mark; - - /* arp */ - uint32_t n_arp_entries; - - /* packet buffer offsets */ - uint32_t ip_hdr_offset; - uint32_t arp_key_offset; - uint32_t color_offset; - - /* debug */ - uint32_t dbg_ah_disable; -}; - -int -pipeline_routing_parse_args(struct pipeline_routing_params *p, - struct pipeline_params *params); - -/* - * Route - */ -enum pipeline_routing_route_key_type { - PIPELINE_ROUTING_ROUTE_IPV4, -}; - -struct pipeline_routing_route_key_ipv4 { - uint32_t ip; - uint32_t depth; -}; - -struct pipeline_routing_route_key { - enum pipeline_routing_route_key_type type; - union { - struct pipeline_routing_route_key_ipv4 ipv4; - } key; -}; - -enum pipeline_routing_route_flags { - PIPELINE_ROUTING_ROUTE_LOCAL = 1 << 0, /* 0 = remote; 1 = local */ - PIPELINE_ROUTING_ROUTE_ARP = 1 << 1, /* 0 = ARP OFF; 1 = ARP ON */ - PIPELINE_ROUTING_ROUTE_QINQ = 1 << 2, /* 0 = QINQ OFF; 1 = QINQ ON */ - PIPELINE_ROUTING_ROUTE_MPLS = 1 << 3, /* 0 = MPLS OFF; 1 = MPLS ON */ -}; - -#define PIPELINE_ROUTING_MPLS_LABELS_MAX 4 - -struct pipeline_routing_route_data { - uint32_t flags; - uint32_t port_id; /* Output port ID */ - - union { - /* Next hop IP (valid only when ARP is enabled) */ - uint32_t ip; - - /* Next hop MAC address (valid only when ARP disabled */ - struct ether_addr macaddr; - } ethernet; - - union { - struct { - uint16_t svlan; - uint16_t cvlan; - } qinq; - - struct { - uint32_t labels[PIPELINE_ROUTING_MPLS_LABELS_MAX]; - uint32_t n_labels; - } mpls; - } l2; -}; - -/* - * ARP - */ -enum pipeline_routing_arp_key_type { - PIPELINE_ROUTING_ARP_IPV4, -}; - -struct pipeline_routing_arp_key_ipv4 { - uint32_t port_id; - uint32_t ip; -}; - -struct pipeline_routing_arp_key { - enum pipeline_routing_arp_key_type type; - union { - struct pipeline_routing_arp_key_ipv4 ipv4; - } key; -}; - -/* - * Messages - */ -enum pipeline_routing_msg_req_type { - PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD, - PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL, - PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT, - PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT, - PIPELINE_ROUTING_MSG_REQ_ARP_ADD, - PIPELINE_ROUTING_MSG_REQ_ARP_DEL, - PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT, - PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT, - PIPELINE_ROUTING_MSG_REQ_SET_MACADDR, - PIPELINE_ROUTING_MSG_REQS -}; - -/* - * MSG ROUTE ADD - */ -struct pipeline_routing_route_add_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_routing_msg_req_type subtype; - - /* key */ - struct pipeline_routing_route_key key; - - /* data */ - struct pipeline_routing_route_data data; -}; - -struct pipeline_routing_route_add_msg_rsp { - int status; - int key_found; - void *entry_ptr; -}; - -/* - * MSG ROUTE DELETE - */ -struct pipeline_routing_route_delete_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_routing_msg_req_type subtype; - - /* key */ - struct pipeline_routing_route_key key; -}; - -struct pipeline_routing_route_delete_msg_rsp { - int status; - int key_found; -}; - -/* - * MSG ROUTE ADD DEFAULT - */ -struct pipeline_routing_route_add_default_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_routing_msg_req_type subtype; - - /* data */ - uint32_t port_id; -}; - -struct pipeline_routing_route_add_default_msg_rsp { - int status; - void *entry_ptr; -}; - -/* - * MSG ROUTE DELETE DEFAULT - */ -struct pipeline_routing_route_delete_default_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_routing_msg_req_type subtype; -}; - -struct pipeline_routing_route_delete_default_msg_rsp { - int status; -}; - -/* - * MSG ARP ADD - */ -struct pipeline_routing_arp_add_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_routing_msg_req_type subtype; - - /* key */ - struct pipeline_routing_arp_key key; - - /* data */ - struct ether_addr macaddr; -}; - -struct pipeline_routing_arp_add_msg_rsp { - int status; - int key_found; - void *entry_ptr; -}; - -/* - * MSG ARP DELETE - */ -struct pipeline_routing_arp_delete_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_routing_msg_req_type subtype; - - /* key */ - struct pipeline_routing_arp_key key; -}; - -struct pipeline_routing_arp_delete_msg_rsp { - int status; - int key_found; -}; - -/* - * MSG ARP ADD DEFAULT - */ -struct pipeline_routing_arp_add_default_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_routing_msg_req_type subtype; - - /* data */ - uint32_t port_id; -}; - -struct pipeline_routing_arp_add_default_msg_rsp { - int status; - void *entry_ptr; -}; - -/* - * MSG ARP DELETE DEFAULT - */ -struct pipeline_routing_arp_delete_default_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_routing_msg_req_type subtype; -}; - -struct pipeline_routing_arp_delete_default_msg_rsp { - int status; -}; - -/* - * MSG SET MACADDR - */ -struct pipeline_routing_set_macaddr_msg_req { - enum pipeline_msg_req_type type; - enum pipeline_routing_msg_req_type subtype; - - uint64_t macaddr[PIPELINE_MAX_PORT_OUT]; -}; - -struct pipeline_routing_set_macaddr_msg_rsp { - int status; -}; - -extern struct pipeline_be_ops pipeline_routing_be_ops; - -#endif diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h deleted file mode 100644 index 6c0c97a4..00000000 --- a/examples/ip_pipeline/pipeline_be.h +++ /dev/null @@ -1,322 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#ifndef __INCLUDE_PIPELINE_BE_H__ -#define __INCLUDE_PIPELINE_BE_H__ - -#include <rte_port_ethdev.h> -#include <rte_port_ring.h> -#include <rte_port_frag.h> -#include <rte_port_ras.h> -#include <rte_port_sched.h> -#include <rte_port_fd.h> -#include <rte_port_source_sink.h> -#ifdef RTE_LIBRTE_KNI -#include <rte_port_kni.h> -#endif -#include <rte_pipeline.h> - -enum pipeline_port_in_type { - PIPELINE_PORT_IN_ETHDEV_READER, - PIPELINE_PORT_IN_RING_READER, - PIPELINE_PORT_IN_RING_MULTI_READER, - PIPELINE_PORT_IN_RING_READER_IPV4_FRAG, - PIPELINE_PORT_IN_RING_READER_IPV6_FRAG, - PIPELINE_PORT_IN_SCHED_READER, - PIPELINE_PORT_IN_FD_READER, - PIPELINE_PORT_IN_KNI_READER, - PIPELINE_PORT_IN_SOURCE, -}; - -struct pipeline_port_in_params { - enum pipeline_port_in_type type; - union { - struct rte_port_ethdev_reader_params ethdev; - struct rte_port_ring_reader_params ring; - struct rte_port_ring_multi_reader_params ring_multi; - struct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag; - struct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag; - struct rte_port_sched_reader_params sched; - struct rte_port_fd_reader_params fd; -#ifdef RTE_LIBRTE_KNI - struct rte_port_kni_reader_params kni; -#endif - struct rte_port_source_params source; - } params; - uint32_t burst_size; -}; - -static inline void * -pipeline_port_in_params_convert(struct pipeline_port_in_params *p) -{ - switch (p->type) { - case PIPELINE_PORT_IN_ETHDEV_READER: - return (void *) &p->params.ethdev; - case PIPELINE_PORT_IN_RING_READER: - return (void *) &p->params.ring; - case PIPELINE_PORT_IN_RING_MULTI_READER: - return (void *) &p->params.ring_multi; - case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG: - return (void *) &p->params.ring_ipv4_frag; - case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG: - return (void *) &p->params.ring_ipv6_frag; - case PIPELINE_PORT_IN_SCHED_READER: - return (void *) &p->params.sched; - case PIPELINE_PORT_IN_FD_READER: - return (void *) &p->params.fd; -#ifdef RTE_LIBRTE_KNI - case PIPELINE_PORT_IN_KNI_READER: - return (void *) &p->params.kni; -#endif - case PIPELINE_PORT_IN_SOURCE: - return (void *) &p->params.source; - default: - return NULL; - } -} - -static inline struct rte_port_in_ops * -pipeline_port_in_params_get_ops(struct pipeline_port_in_params *p) -{ - switch (p->type) { - case PIPELINE_PORT_IN_ETHDEV_READER: - return &rte_port_ethdev_reader_ops; - case PIPELINE_PORT_IN_RING_READER: - return &rte_port_ring_reader_ops; - case PIPELINE_PORT_IN_RING_MULTI_READER: - return &rte_port_ring_multi_reader_ops; - case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG: - return &rte_port_ring_reader_ipv4_frag_ops; - case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG: - return &rte_port_ring_reader_ipv6_frag_ops; - case PIPELINE_PORT_IN_SCHED_READER: - return &rte_port_sched_reader_ops; - case PIPELINE_PORT_IN_FD_READER: - return &rte_port_fd_reader_ops; -#ifdef RTE_LIBRTE_KNI - case PIPELINE_PORT_IN_KNI_READER: - return &rte_port_kni_reader_ops; -#endif - case PIPELINE_PORT_IN_SOURCE: - return &rte_port_source_ops; - default: - return NULL; - } -} - -enum pipeline_port_out_type { - PIPELINE_PORT_OUT_ETHDEV_WRITER, - PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP, - PIPELINE_PORT_OUT_RING_WRITER, - PIPELINE_PORT_OUT_RING_MULTI_WRITER, - PIPELINE_PORT_OUT_RING_WRITER_NODROP, - PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP, - PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS, - PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS, - PIPELINE_PORT_OUT_SCHED_WRITER, - PIPELINE_PORT_OUT_FD_WRITER, - PIPELINE_PORT_OUT_KNI_WRITER, - PIPELINE_PORT_OUT_KNI_WRITER_NODROP, - PIPELINE_PORT_OUT_SINK, -}; - -struct pipeline_port_out_params { - enum pipeline_port_out_type type; - union { - struct rte_port_ethdev_writer_params ethdev; - struct rte_port_ethdev_writer_nodrop_params ethdev_nodrop; - struct rte_port_ring_writer_params ring; - struct rte_port_ring_multi_writer_params ring_multi; - struct rte_port_ring_writer_nodrop_params ring_nodrop; - struct rte_port_ring_multi_writer_nodrop_params ring_multi_nodrop; - struct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras; - struct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras; - struct rte_port_sched_writer_params sched; - struct rte_port_fd_writer_params fd; -#ifdef RTE_LIBRTE_KNI - struct rte_port_kni_writer_params kni; - struct rte_port_kni_writer_nodrop_params kni_nodrop; -#endif - struct rte_port_sink_params sink; - } params; -}; - -static inline void * -pipeline_port_out_params_convert(struct pipeline_port_out_params *p) -{ - switch (p->type) { - case PIPELINE_PORT_OUT_ETHDEV_WRITER: - return (void *) &p->params.ethdev; - case PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP: - return (void *) &p->params.ethdev_nodrop; - case PIPELINE_PORT_OUT_RING_WRITER: - return (void *) &p->params.ring; - case PIPELINE_PORT_OUT_RING_MULTI_WRITER: - return (void *) &p->params.ring_multi; - case PIPELINE_PORT_OUT_RING_WRITER_NODROP: - return (void *) &p->params.ring_nodrop; - case PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP: - return (void *) &p->params.ring_multi_nodrop; - case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS: - return (void *) &p->params.ring_ipv4_ras; - case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS: - return (void *) &p->params.ring_ipv6_ras; - case PIPELINE_PORT_OUT_SCHED_WRITER: - return (void *) &p->params.sched; - case PIPELINE_PORT_OUT_FD_WRITER: - return (void *) &p->params.fd; -#ifdef RTE_LIBRTE_KNI - case PIPELINE_PORT_OUT_KNI_WRITER: - return (void *) &p->params.kni; - case PIPELINE_PORT_OUT_KNI_WRITER_NODROP: - return (void *) &p->params.kni_nodrop; -#endif - case PIPELINE_PORT_OUT_SINK: - return (void *) &p->params.sink; - default: - return NULL; - } -} - -static inline void * -pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p) -{ - switch (p->type) { - case PIPELINE_PORT_OUT_ETHDEV_WRITER: - return &rte_port_ethdev_writer_ops; - case PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP: - return &rte_port_ethdev_writer_nodrop_ops; - case PIPELINE_PORT_OUT_RING_WRITER: - return &rte_port_ring_writer_ops; - case PIPELINE_PORT_OUT_RING_MULTI_WRITER: - return &rte_port_ring_multi_writer_ops; - case PIPELINE_PORT_OUT_RING_WRITER_NODROP: - return &rte_port_ring_writer_nodrop_ops; - case PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP: - return &rte_port_ring_multi_writer_nodrop_ops; - case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS: - return &rte_port_ring_writer_ipv4_ras_ops; - case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS: - return &rte_port_ring_writer_ipv6_ras_ops; - case PIPELINE_PORT_OUT_SCHED_WRITER: - return &rte_port_sched_writer_ops; - case PIPELINE_PORT_OUT_FD_WRITER: - return &rte_port_fd_writer_ops; -#ifdef RTE_LIBRTE_KNI - case PIPELINE_PORT_OUT_KNI_WRITER: - return &rte_port_kni_writer_ops; - case PIPELINE_PORT_OUT_KNI_WRITER_NODROP: - return &rte_port_kni_writer_nodrop_ops; -#endif - case PIPELINE_PORT_OUT_SINK: - return &rte_port_sink_ops; - default: - return NULL; - } -} - -#ifndef PIPELINE_NAME_SIZE -#define PIPELINE_NAME_SIZE 64 -#endif - -#ifndef PIPELINE_TYPE_SIZE -#define PIPELINE_TYPE_SIZE 64 -#endif - -#ifndef PIPELINE_MAX_PORT_IN -#define PIPELINE_MAX_PORT_IN 64 -#endif - -#ifndef PIPELINE_MAX_PORT_OUT -#define PIPELINE_MAX_PORT_OUT 64 -#endif - -#ifndef PIPELINE_MAX_TABLES -#define PIPELINE_MAX_TABLES 16 -#endif - -#ifndef PIPELINE_MAX_MSGQ_IN -#define PIPELINE_MAX_MSGQ_IN 16 -#endif - -#ifndef PIPELINE_MAX_MSGQ_OUT -#define PIPELINE_MAX_MSGQ_OUT 16 -#endif - -#ifndef PIPELINE_MAX_ARGS -#define PIPELINE_MAX_ARGS 64 -#endif - -struct pipeline_params { - char name[PIPELINE_NAME_SIZE]; - char type[PIPELINE_TYPE_SIZE]; - - struct pipeline_port_in_params port_in[PIPELINE_MAX_PORT_IN]; - struct pipeline_port_out_params port_out[PIPELINE_MAX_PORT_OUT]; - struct rte_ring *msgq_in[PIPELINE_MAX_MSGQ_IN]; - struct rte_ring *msgq_out[PIPELINE_MAX_MSGQ_OUT]; - - uint32_t n_ports_in; - uint32_t n_ports_out; - uint32_t n_msgq; - - int socket_id; - - char *args_name[PIPELINE_MAX_ARGS]; - char *args_value[PIPELINE_MAX_ARGS]; - uint32_t n_args; - - uint32_t log_level; -}; - -/* - * Pipeline type back-end operations - */ - -typedef void* (*pipeline_be_op_init)(struct pipeline_params *params, - void *arg); - -typedef int (*pipeline_be_op_free)(void *pipeline); - -typedef int (*pipeline_be_op_run)(void *pipeline); - -typedef int (*pipeline_be_op_timer)(void *pipeline); - -struct pipeline_be_ops { - pipeline_be_op_init f_init; - pipeline_be_op_free f_free; - pipeline_be_op_run f_run; - pipeline_be_op_timer f_timer; -}; - -/* Pipeline specific config parse error messages */ -#define PIPELINE_ARG_CHECK(exp, fmt, ...) \ -do { \ - if (!(exp)) { \ - fprintf(stderr, fmt "\n", ## __VA_ARGS__); \ - return -1; \ - } \ -} while (0) - -#define PIPELINE_PARSE_ERR_INV_VAL(exp, section, entry, val) \ -PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": entry \"%s\" " \ - "has invalid value (\"%s\")", section, entry, val) - -#define PIPELINE_PARSE_ERR_OUT_RNG(exp, section, entry, val) \ -PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": entry \"%s\" " \ - "value is out of range (\"%s\")", section, entry, val) - -#define PIPELINE_PARSE_ERR_DUPLICATE(exp, section, entry) \ -PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": duplicated " \ - "entry \"%s\"", section, entry) - -#define PIPELINE_PARSE_ERR_INV_ENT(exp, section, entry) \ -PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": invalid entry " \ - "\"%s\"", section, entry) - -#define PIPELINE_PARSE_ERR_MANDATORY(exp, section, entry) \ -PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": mandatory " \ - "entry \"%s\" is missing", section, entry) - -#endif diff --git a/examples/ip_pipeline/swq.c b/examples/ip_pipeline/swq.c new file mode 100644 index 00000000..7e54a1db --- /dev/null +++ b/examples/ip_pipeline/swq.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <stdlib.h> +#include <string.h> + +#include <rte_string_fns.h> + +#include "swq.h" + +static struct swq_list swq_list; + +int +swq_init(void) +{ + TAILQ_INIT(&swq_list); + + return 0; +} + +struct swq * +swq_find(const char *name) +{ + struct swq *swq; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(swq, &swq_list, node) + if (strcmp(swq->name, name) == 0) + return swq; + + return NULL; +} + +struct swq * +swq_create(const char *name, struct swq_params *params) +{ + struct swq *swq; + struct rte_ring *r; + unsigned int flags = RING_F_SP_ENQ | RING_F_SC_DEQ; + + /* Check input params */ + if ((name == NULL) || + swq_find(name) || + (params == NULL) || + (params->size == 0)) + return NULL; + + /* Resource create */ + r = rte_ring_create( + name, + params->size, + params->cpu_id, + flags); + + if (r == NULL) + return NULL; + + /* Node allocation */ + swq = calloc(1, sizeof(struct swq)); + if (swq == NULL) { + rte_ring_free(r); + return NULL; + } + + /* Node fill in */ + strlcpy(swq->name, name, sizeof(swq->name)); + swq->r = r; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&swq_list, swq, node); + + return swq; +} diff --git a/examples/ip_pipeline/swq.h b/examples/ip_pipeline/swq.h new file mode 100644 index 00000000..c8440ee3 --- /dev/null +++ b/examples/ip_pipeline/swq.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _INCLUDE_SWQ_H_ +#define _INCLUDE_SWQ_H_ + +#include <stdint.h> +#include <sys/queue.h> + +#include <rte_ring.h> + +#include "common.h" + +struct swq { + TAILQ_ENTRY(swq) node; + char name[NAME_SIZE]; + struct rte_ring *r; +}; + +TAILQ_HEAD(swq_list, swq); + +int +swq_init(void); + +struct swq * +swq_find(const char *name); + +struct swq_params { + uint32_t size; + uint32_t cpu_id; +}; + +struct swq * +swq_create(const char *name, struct swq_params *params); + +#endif /* _INCLUDE_SWQ_H_ */ diff --git a/examples/ip_pipeline/tap.c b/examples/ip_pipeline/tap.c new file mode 100644 index 00000000..11e4ad20 --- /dev/null +++ b/examples/ip_pipeline/tap.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <netinet/in.h> +#ifdef RTE_EXEC_ENV_LINUXAPP +#include <linux/if.h> +#include <linux/if_tun.h> +#endif +#include <sys/ioctl.h> + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <rte_string_fns.h> + +#include "tap.h" + +#define TAP_DEV "/dev/net/tun" + +static struct tap_list tap_list; + +int +tap_init(void) +{ + TAILQ_INIT(&tap_list); + + return 0; +} + +struct tap * +tap_find(const char *name) +{ + struct tap *tap; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(tap, &tap_list, node) + if (strcmp(tap->name, name) == 0) + return tap; + + return NULL; +} + +#ifndef RTE_EXEC_ENV_LINUXAPP + +struct tap * +tap_create(const char *name __rte_unused) +{ + return NULL; +} + +#else + +struct tap * +tap_create(const char *name) +{ + struct tap *tap; + struct ifreq ifr; + int fd, status; + + /* Check input params */ + if ((name == NULL) || + tap_find(name)) + return NULL; + + /* Resource create */ + fd = open(TAP_DEV, O_RDWR | O_NONBLOCK); + if (fd < 0) + return NULL; + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */ + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", name); + + status = ioctl(fd, TUNSETIFF, (void *) &ifr); + if (status < 0) { + close(fd); + return NULL; + } + + /* Node allocation */ + tap = calloc(1, sizeof(struct tap)); + if (tap == NULL) { + close(fd); + return NULL; + } + /* Node fill in */ + strlcpy(tap->name, name, sizeof(tap->name)); + tap->fd = fd; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&tap_list, tap, node); + + return tap; +} + +#endif diff --git a/examples/ip_pipeline/tap.h b/examples/ip_pipeline/tap.h new file mode 100644 index 00000000..0dce72fe --- /dev/null +++ b/examples/ip_pipeline/tap.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _INCLUDE_TAP_H_ +#define _INCLUDE_TAP_H_ + +#include <sys/queue.h> + +#include "common.h" + +struct tap { + TAILQ_ENTRY(tap) node; + char name[NAME_SIZE]; + int fd; +}; + +TAILQ_HEAD(tap_list, tap); + +int +tap_init(void); + +struct tap * +tap_find(const char *name); + +struct tap * +tap_create(const char *name); + +#endif /* _INCLUDE_TAP_H_ */ diff --git a/examples/ip_pipeline/thread.c b/examples/ip_pipeline/thread.c index 9013afd1..7fc03332 100644 --- a/examples/ip_pipeline/thread.c +++ b/examples/ip_pipeline/thread.c @@ -1,291 +1,2968 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation + * Copyright(c) 2010-2018 Intel Corporation */ +#include <stdlib.h> + #include <rte_common.h> #include <rte_cycles.h> -#include <rte_pipeline.h> +#include <rte_lcore.h> +#include <rte_ring.h> + +#include <rte_table_acl.h> +#include <rte_table_array.h> +#include <rte_table_hash.h> +#include <rte_table_lpm.h> +#include <rte_table_lpm_ipv6.h> -#include "pipeline_common_be.h" -#include "app.h" +#include "common.h" #include "thread.h" +#include "pipeline.h" -#if APP_THREAD_HEADROOM_STATS_COLLECT - -#define PIPELINE_RUN_REGULAR(thread, pipeline) \ -do { \ - uint64_t t0 = rte_rdtsc_precise(); \ - int n_pkts = rte_pipeline_run(pipeline->p); \ - \ - if (n_pkts == 0) { \ - uint64_t t1 = rte_rdtsc_precise(); \ - \ - thread->headroom_cycles += t1 - t0; \ - } \ -} while (0) - - -#define PIPELINE_RUN_CUSTOM(thread, data) \ -do { \ - uint64_t t0 = rte_rdtsc_precise(); \ - int n_pkts = data->f_run(data->be); \ - \ - if (n_pkts == 0) { \ - uint64_t t1 = rte_rdtsc_precise(); \ - \ - thread->headroom_cycles += t1 - t0; \ - } \ -} while (0) - -#else - -#define PIPELINE_RUN_REGULAR(thread, pipeline) \ - rte_pipeline_run(pipeline->p) - -#define PIPELINE_RUN_CUSTOM(thread, data) \ - data->f_run(data->be) +#ifndef THREAD_PIPELINES_MAX +#define THREAD_PIPELINES_MAX 256 +#endif +#ifndef THREAD_MSGQ_SIZE +#define THREAD_MSGQ_SIZE 64 #endif -static inline void * -thread_msg_recv(struct rte_ring *r) +#ifndef THREAD_TIMER_PERIOD_MS +#define THREAD_TIMER_PERIOD_MS 100 +#endif + +/** + * Master thead: data plane thread context + */ +struct thread { + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + + uint32_t enabled; +}; + +static struct thread thread[RTE_MAX_LCORE]; + +/** + * Data plane threads: context + */ +struct table_data { + struct rte_table_action *a; +}; + +struct pipeline_data { + struct rte_pipeline *p; + struct table_data table_data[RTE_PIPELINE_TABLE_MAX]; + uint32_t n_tables; + + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + uint64_t timer_period; /* Measured in CPU cycles. */ + uint64_t time_next; + + uint8_t buffer[TABLE_RULE_ACTION_SIZE_MAX]; +}; + +struct thread_data { + struct rte_pipeline *p[THREAD_PIPELINES_MAX]; + uint32_t n_pipelines; + + struct pipeline_data pipeline_data[THREAD_PIPELINES_MAX]; + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + uint64_t timer_period; /* Measured in CPU cycles. */ + uint64_t time_next; + uint64_t time_next_min; +} __rte_cache_aligned; + +static struct thread_data thread_data[RTE_MAX_LCORE]; + +/** + * Master thread: data plane thread init + */ +static void +thread_free(void) +{ + uint32_t i; + + for (i = 0; i < RTE_MAX_LCORE; i++) { + struct thread *t = &thread[i]; + + if (!rte_lcore_is_enabled(i)) + continue; + + /* MSGQs */ + if (t->msgq_req) + rte_ring_free(t->msgq_req); + + if (t->msgq_rsp) + rte_ring_free(t->msgq_rsp); + } +} + +int +thread_init(void) +{ + uint32_t i; + + RTE_LCORE_FOREACH_SLAVE(i) { + char name[NAME_MAX]; + struct rte_ring *msgq_req, *msgq_rsp; + struct thread *t = &thread[i]; + struct thread_data *t_data = &thread_data[i]; + uint32_t cpu_id = rte_lcore_to_socket_id(i); + + /* MSGQs */ + snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-REQ", i); + + msgq_req = rte_ring_create(name, + THREAD_MSGQ_SIZE, + cpu_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + + if (msgq_req == NULL) { + thread_free(); + return -1; + } + + snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-RSP", i); + + msgq_rsp = rte_ring_create(name, + THREAD_MSGQ_SIZE, + cpu_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + + if (msgq_rsp == NULL) { + thread_free(); + return -1; + } + + /* Master thread records */ + t->msgq_req = msgq_req; + t->msgq_rsp = msgq_rsp; + t->enabled = 1; + + /* Data plane thread records */ + t_data->n_pipelines = 0; + t_data->msgq_req = msgq_req; + t_data->msgq_rsp = msgq_rsp; + t_data->timer_period = + (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000; + t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period; + t_data->time_next_min = t_data->time_next; + } + + return 0; +} + +static inline int +thread_is_running(uint32_t thread_id) +{ + enum rte_lcore_state_t thread_state; + + thread_state = rte_eal_get_lcore_state(thread_id); + return (thread_state == RUNNING) ? 1 : 0; +} + +/** + * Pipeline is running when: + * (A) Pipeline is mapped to a data plane thread AND + * (B) Its data plane thread is in RUNNING state. + */ +static inline int +pipeline_is_running(struct pipeline *p) +{ + if (p->enabled == 0) + return 0; + + return thread_is_running(p->thread_id); +} + +/** + * Master thread & data plane threads: message passing + */ +enum thread_req_type { + THREAD_REQ_PIPELINE_ENABLE = 0, + THREAD_REQ_PIPELINE_DISABLE, + THREAD_REQ_MAX +}; + +struct thread_msg_req { + enum thread_req_type type; + + union { + struct { + struct rte_pipeline *p; + struct { + struct rte_table_action *a; + } table[RTE_PIPELINE_TABLE_MAX]; + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + uint32_t timer_period_ms; + uint32_t n_tables; + } pipeline_enable; + + struct { + struct rte_pipeline *p; + } pipeline_disable; + }; +}; + +struct thread_msg_rsp { + int status; +}; + +/** + * Master thread + */ +static struct thread_msg_req * +thread_msg_alloc(void) +{ + size_t size = RTE_MAX(sizeof(struct thread_msg_req), + sizeof(struct thread_msg_rsp)); + + return calloc(1, size); +} + +static void +thread_msg_free(struct thread_msg_rsp *rsp) +{ + free(rsp); +} + +static struct thread_msg_rsp * +thread_msg_send_recv(uint32_t thread_id, + struct thread_msg_req *req) +{ + struct thread *t = &thread[thread_id]; + struct rte_ring *msgq_req = t->msgq_req; + struct rte_ring *msgq_rsp = t->msgq_rsp; + struct thread_msg_rsp *rsp; + int status; + + /* send */ + do { + status = rte_ring_sp_enqueue(msgq_req, req); + } while (status == -ENOBUFS); + + /* recv */ + do { + status = rte_ring_sc_dequeue(msgq_rsp, (void **) &rsp); + } while (status != 0); + + return rsp; +} + +int +thread_pipeline_enable(uint32_t thread_id, + const char *pipeline_name) +{ + struct pipeline *p = pipeline_find(pipeline_name); + struct thread *t; + struct thread_msg_req *req; + struct thread_msg_rsp *rsp; + uint32_t i; + int status; + + /* Check input params */ + if ((thread_id >= RTE_MAX_LCORE) || + (p == NULL) || + (p->n_ports_in == 0) || + (p->n_ports_out == 0) || + (p->n_tables == 0)) + return -1; + + t = &thread[thread_id]; + if ((t->enabled == 0) || + p->enabled) + return -1; + + if (!thread_is_running(thread_id)) { + struct thread_data *td = &thread_data[thread_id]; + struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines]; + + if (td->n_pipelines >= THREAD_PIPELINES_MAX) + return -1; + + /* Data plane thread */ + td->p[td->n_pipelines] = p->p; + + tdp->p = p->p; + for (i = 0; i < p->n_tables; i++) + tdp->table_data[i].a = p->table[i].a; + + tdp->n_tables = p->n_tables; + + tdp->msgq_req = p->msgq_req; + tdp->msgq_rsp = p->msgq_rsp; + tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000; + tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period; + + td->n_pipelines++; + + /* Pipeline */ + p->thread_id = thread_id; + p->enabled = 1; + + return 0; + } + + /* Allocate request */ + req = thread_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = THREAD_REQ_PIPELINE_ENABLE; + req->pipeline_enable.p = p->p; + for (i = 0; i < p->n_tables; i++) + req->pipeline_enable.table[i].a = + p->table[i].a; + req->pipeline_enable.msgq_req = p->msgq_req; + req->pipeline_enable.msgq_rsp = p->msgq_rsp; + req->pipeline_enable.timer_period_ms = p->timer_period_ms; + req->pipeline_enable.n_tables = p->n_tables; + + /* Send request and wait for response */ + rsp = thread_msg_send_recv(thread_id, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + thread_msg_free(rsp); + + /* Request completion */ + if (status) + return status; + + p->thread_id = thread_id; + p->enabled = 1; + + return 0; +} + +int +thread_pipeline_disable(uint32_t thread_id, + const char *pipeline_name) +{ + struct pipeline *p = pipeline_find(pipeline_name); + struct thread *t; + struct thread_msg_req *req; + struct thread_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((thread_id >= RTE_MAX_LCORE) || + (p == NULL)) + return -1; + + t = &thread[thread_id]; + if (t->enabled == 0) + return -1; + + if (p->enabled == 0) + return 0; + + if (p->thread_id != thread_id) + return -1; + + if (!thread_is_running(thread_id)) { + struct thread_data *td = &thread_data[thread_id]; + uint32_t i; + + for (i = 0; i < td->n_pipelines; i++) { + struct pipeline_data *tdp = &td->pipeline_data[i]; + + if (tdp->p != p->p) + continue; + + /* Data plane thread */ + if (i < td->n_pipelines - 1) { + struct rte_pipeline *pipeline_last = + td->p[td->n_pipelines - 1]; + struct pipeline_data *tdp_last = + &td->pipeline_data[td->n_pipelines - 1]; + + td->p[i] = pipeline_last; + memcpy(tdp, tdp_last, sizeof(*tdp)); + } + + td->n_pipelines--; + + /* Pipeline */ + p->enabled = 0; + + break; + } + + return 0; + } + + /* Allocate request */ + req = thread_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = THREAD_REQ_PIPELINE_DISABLE; + req->pipeline_disable.p = p->p; + + /* Send request and wait for response */ + rsp = thread_msg_send_recv(thread_id, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + thread_msg_free(rsp); + + /* Request completion */ + if (status) + return status; + + p->enabled = 0; + + return 0; +} + +/** + * Data plane threads: message handling + */ +static inline struct thread_msg_req * +thread_msg_recv(struct rte_ring *msgq_req) { - void *msg; - int status = rte_ring_sc_dequeue(r, &msg); + struct thread_msg_req *req; + + int status = rte_ring_sc_dequeue(msgq_req, (void **) &req); if (status != 0) return NULL; - return msg; + return req; } static inline void -thread_msg_send(struct rte_ring *r, - void *msg) +thread_msg_send(struct rte_ring *msgq_rsp, + struct thread_msg_rsp *rsp) { int status; do { - status = rte_ring_sp_enqueue(r, msg); + status = rte_ring_sp_enqueue(msgq_rsp, rsp); } while (status == -ENOBUFS); } +static struct thread_msg_rsp * +thread_msg_handle_pipeline_enable(struct thread_data *t, + struct thread_msg_req *req) +{ + struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req; + struct pipeline_data *p = &t->pipeline_data[t->n_pipelines]; + uint32_t i; + + /* Request */ + if (t->n_pipelines >= THREAD_PIPELINES_MAX) { + rsp->status = -1; + return rsp; + } + + t->p[t->n_pipelines] = req->pipeline_enable.p; + + p->p = req->pipeline_enable.p; + for (i = 0; i < req->pipeline_enable.n_tables; i++) + p->table_data[i].a = + req->pipeline_enable.table[i].a; + + p->n_tables = req->pipeline_enable.n_tables; + + p->msgq_req = req->pipeline_enable.msgq_req; + p->msgq_rsp = req->pipeline_enable.msgq_rsp; + p->timer_period = + (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000; + p->time_next = rte_get_tsc_cycles() + p->timer_period; + + t->n_pipelines++; + + /* Response */ + rsp->status = 0; + return rsp; +} + +static struct thread_msg_rsp * +thread_msg_handle_pipeline_disable(struct thread_data *t, + struct thread_msg_req *req) +{ + struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req; + uint32_t n_pipelines = t->n_pipelines; + struct rte_pipeline *pipeline = req->pipeline_disable.p; + uint32_t i; + + /* find pipeline */ + for (i = 0; i < n_pipelines; i++) { + struct pipeline_data *p = &t->pipeline_data[i]; + + if (p->p != pipeline) + continue; + + if (i < n_pipelines - 1) { + struct rte_pipeline *pipeline_last = + t->p[n_pipelines - 1]; + struct pipeline_data *p_last = + &t->pipeline_data[n_pipelines - 1]; + + t->p[i] = pipeline_last; + memcpy(p, p_last, sizeof(*p)); + } + + t->n_pipelines--; + + rsp->status = 0; + return rsp; + } + + /* should not get here */ + rsp->status = 0; + return rsp; +} + +static void +thread_msg_handle(struct thread_data *t) +{ + for ( ; ; ) { + struct thread_msg_req *req; + struct thread_msg_rsp *rsp; + + req = thread_msg_recv(t->msgq_req); + if (req == NULL) + break; + + switch (req->type) { + case THREAD_REQ_PIPELINE_ENABLE: + rsp = thread_msg_handle_pipeline_enable(t, req); + break; + + case THREAD_REQ_PIPELINE_DISABLE: + rsp = thread_msg_handle_pipeline_disable(t, req); + break; + + default: + rsp = (struct thread_msg_rsp *) req; + rsp->status = -1; + } + + thread_msg_send(t->msgq_rsp, rsp); + } +} + +/** + * Master thread & data plane threads: message passing + */ +enum pipeline_req_type { + /* Port IN */ + PIPELINE_REQ_PORT_IN_STATS_READ, + PIPELINE_REQ_PORT_IN_ENABLE, + PIPELINE_REQ_PORT_IN_DISABLE, + + /* Port OUT */ + PIPELINE_REQ_PORT_OUT_STATS_READ, + + /* Table */ + PIPELINE_REQ_TABLE_STATS_READ, + PIPELINE_REQ_TABLE_RULE_ADD, + PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT, + PIPELINE_REQ_TABLE_RULE_ADD_BULK, + PIPELINE_REQ_TABLE_RULE_DELETE, + PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT, + PIPELINE_REQ_TABLE_RULE_STATS_READ, + PIPELINE_REQ_TABLE_MTR_PROFILE_ADD, + PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE, + PIPELINE_REQ_TABLE_RULE_MTR_READ, + PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE, + PIPELINE_REQ_TABLE_RULE_TTL_READ, + PIPELINE_REQ_MAX +}; + +struct pipeline_msg_req_port_in_stats_read { + int clear; +}; + +struct pipeline_msg_req_port_out_stats_read { + int clear; +}; + +struct pipeline_msg_req_table_stats_read { + int clear; +}; + +struct pipeline_msg_req_table_rule_add { + struct table_rule_match match; + struct table_rule_action action; +}; + +struct pipeline_msg_req_table_rule_add_default { + struct table_rule_action action; +}; + +struct pipeline_msg_req_table_rule_add_bulk { + struct table_rule_match *match; + struct table_rule_action *action; + void **data; + uint32_t n_rules; + int bulk; +}; + +struct pipeline_msg_req_table_rule_delete { + struct table_rule_match match; +}; + +struct pipeline_msg_req_table_rule_stats_read { + void *data; + int clear; +}; + +struct pipeline_msg_req_table_mtr_profile_add { + uint32_t meter_profile_id; + struct rte_table_action_meter_profile profile; +}; + +struct pipeline_msg_req_table_mtr_profile_delete { + uint32_t meter_profile_id; +}; + +struct pipeline_msg_req_table_rule_mtr_read { + void *data; + uint32_t tc_mask; + int clear; +}; + +struct pipeline_msg_req_table_dscp_table_update { + uint64_t dscp_mask; + struct rte_table_action_dscp_table dscp_table; +}; + +struct pipeline_msg_req_table_rule_ttl_read { + void *data; + int clear; +}; + +struct pipeline_msg_req { + enum pipeline_req_type type; + uint32_t id; /* Port IN, port OUT or table ID */ + + RTE_STD_C11 + union { + struct pipeline_msg_req_port_in_stats_read port_in_stats_read; + struct pipeline_msg_req_port_out_stats_read port_out_stats_read; + struct pipeline_msg_req_table_stats_read table_stats_read; + struct pipeline_msg_req_table_rule_add table_rule_add; + struct pipeline_msg_req_table_rule_add_default table_rule_add_default; + struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk; + struct pipeline_msg_req_table_rule_delete table_rule_delete; + struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read; + struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add; + struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete; + struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read; + struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update; + struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read; + }; +}; + +struct pipeline_msg_rsp_port_in_stats_read { + struct rte_pipeline_port_in_stats stats; +}; + +struct pipeline_msg_rsp_port_out_stats_read { + struct rte_pipeline_port_out_stats stats; +}; + +struct pipeline_msg_rsp_table_stats_read { + struct rte_pipeline_table_stats stats; +}; + +struct pipeline_msg_rsp_table_rule_add { + void *data; +}; + +struct pipeline_msg_rsp_table_rule_add_default { + void *data; +}; + +struct pipeline_msg_rsp_table_rule_add_bulk { + uint32_t n_rules; +}; + +struct pipeline_msg_rsp_table_rule_stats_read { + struct rte_table_action_stats_counters stats; +}; + +struct pipeline_msg_rsp_table_rule_mtr_read { + struct rte_table_action_mtr_counters stats; +}; + +struct pipeline_msg_rsp_table_rule_ttl_read { + struct rte_table_action_ttl_counters stats; +}; + +struct pipeline_msg_rsp { + int status; + + RTE_STD_C11 + union { + struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read; + struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read; + struct pipeline_msg_rsp_table_stats_read table_stats_read; + struct pipeline_msg_rsp_table_rule_add table_rule_add; + struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default; + struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk; + struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read; + struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read; + struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read; + }; +}; + +/** + * Master thread + */ +static struct pipeline_msg_req * +pipeline_msg_alloc(void) +{ + size_t size = RTE_MAX(sizeof(struct pipeline_msg_req), + sizeof(struct pipeline_msg_rsp)); + + return calloc(1, size); +} + +static void +pipeline_msg_free(struct pipeline_msg_rsp *rsp) +{ + free(rsp); +} + +static struct pipeline_msg_rsp * +pipeline_msg_send_recv(struct pipeline *p, + struct pipeline_msg_req *req) +{ + struct rte_ring *msgq_req = p->msgq_req; + struct rte_ring *msgq_rsp = p->msgq_rsp; + struct pipeline_msg_rsp *rsp; + int status; + + /* send */ + do { + status = rte_ring_sp_enqueue(msgq_req, req); + } while (status == -ENOBUFS); + + /* recv */ + do { + status = rte_ring_sc_dequeue(msgq_rsp, (void **) &rsp); + } while (status != 0); + + return rsp; +} + +int +pipeline_port_in_stats_read(const char *pipeline_name, + uint32_t port_id, + struct rte_pipeline_port_in_stats *stats, + int clear) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (stats == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (port_id >= p->n_ports_in)) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_in_stats_read(p->p, + port_id, + stats, + clear); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_PORT_IN_STATS_READ; + req->id = port_id; + req->port_in_stats_read.clear = clear; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + if (status) + memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats)); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_port_in_enable(const char *pipeline_name, + uint32_t port_id) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if (pipeline_name == NULL) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (port_id >= p->n_ports_in)) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_in_enable(p->p, port_id); + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_PORT_IN_ENABLE; + req->id = port_id; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_port_in_disable(const char *pipeline_name, + uint32_t port_id) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if (pipeline_name == NULL) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (port_id >= p->n_ports_in)) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_in_disable(p->p, port_id); + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_PORT_IN_DISABLE; + req->id = port_id; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_port_out_stats_read(const char *pipeline_name, + uint32_t port_id, + struct rte_pipeline_port_out_stats *stats, + int clear) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (stats == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (port_id >= p->n_ports_out)) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_out_stats_read(p->p, + port_id, + stats, + clear); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_PORT_OUT_STATS_READ; + req->id = port_id; + req->port_out_stats_read.clear = clear; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + if (status) + memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats)); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_stats_read(const char *pipeline_name, + uint32_t table_id, + struct rte_pipeline_table_stats *stats, + int clear) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (stats == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_pipeline_table_stats_read(p->p, + table_id, + stats, + clear); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_STATS_READ; + req->id = table_id; + req->table_stats_read.clear = clear; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + if (status) + memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats)); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +static int +match_check(struct table_rule_match *match, + struct pipeline *p, + uint32_t table_id) +{ + struct table *table; + + if ((match == NULL) || + (p == NULL) || + (table_id >= p->n_tables)) + return -1; + + table = &p->table[table_id]; + if (match->match_type != table->params.match_type) + return -1; + + switch (match->match_type) { + case TABLE_ACL: + { + struct table_acl_params *t = &table->params.match.acl; + struct table_rule_match_acl *r = &match->match.acl; + + if ((r->ip_version && (t->ip_version == 0)) || + ((r->ip_version == 0) && t->ip_version)) + return -1; + + if (r->ip_version) { + if ((r->sa_depth > 32) || + (r->da_depth > 32)) + return -1; + } else { + if ((r->sa_depth > 128) || + (r->da_depth > 128)) + return -1; + } + return 0; + } + + case TABLE_ARRAY: + return 0; + + case TABLE_HASH: + return 0; + + case TABLE_LPM: + { + struct table_lpm_params *t = &table->params.match.lpm; + struct table_rule_match_lpm *r = &match->match.lpm; + + if ((r->ip_version && (t->key_size != 4)) || + ((r->ip_version == 0) && (t->key_size != 16))) + return -1; + + if (r->ip_version) { + if (r->depth > 32) + return -1; + } else { + if (r->depth > 128) + return -1; + } + return 0; + } + + case TABLE_STUB: + return -1; + + default: + return -1; + } +} + static int -thread_pipeline_enable(struct app_thread_data *t, - struct thread_pipeline_enable_msg_req *req) +action_check(struct table_rule_action *action, + struct pipeline *p, + uint32_t table_id) { - struct app_thread_pipeline_data *p; + struct table_action_profile *ap; + + if ((action == NULL) || + (p == NULL) || + (table_id >= p->n_tables)) + return -1; + + ap = p->table[table_id].ap; + if (action->action_mask != ap->params.action_mask) + return -1; + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { + if ((action->fwd.action == RTE_PIPELINE_ACTION_PORT) && + (action->fwd.id >= p->n_ports_out)) + return -1; - if (req->f_run == NULL) { - if (t->n_regular >= APP_MAX_THREAD_PIPELINES) + if ((action->fwd.action == RTE_PIPELINE_ACTION_TABLE) && + (action->fwd.id >= p->n_tables)) return -1; - } else { - if (t->n_custom >= APP_MAX_THREAD_PIPELINES) + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { + uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1; + uint32_t tc_mask1 = action->mtr.tc_mask; + + if (tc_mask1 != tc_mask0) return -1; } - p = (req->f_run == NULL) ? - &t->regular[t->n_regular] : - &t->custom[t->n_custom]; + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { + uint32_t n_subports_per_port = + ap->params.tm.n_subports_per_port; + uint32_t n_pipes_per_subport = + ap->params.tm.n_pipes_per_subport; + uint32_t subport_id = action->tm.subport_id; + uint32_t pipe_id = action->tm.pipe_id; - p->pipeline_id = req->pipeline_id; - p->be = req->be; - p->f_run = req->f_run; - p->f_timer = req->f_timer; - p->timer_period = req->timer_period; - p->deadline = 0; + if ((subport_id >= n_subports_per_port) || + (pipe_id >= n_pipes_per_subport)) + return -1; + } - if (req->f_run == NULL) - t->n_regular++; - else - t->n_custom++; + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { + uint64_t encap_mask = ap->params.encap.encap_mask; + enum rte_table_action_encap_type type = action->encap.type; + + if ((encap_mask & (1LLU << type)) == 0) + return -1; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { + int ip_version0 = ap->params.common.ip_version; + int ip_version1 = action->nat.ip_version; + + if ((ip_version1 && (ip_version0 == 0)) || + ((ip_version1 == 0) && ip_version0)) + return -1; + } return 0; } static int -thread_pipeline_disable(struct app_thread_data *t, - struct thread_pipeline_disable_msg_req *req) +action_default_check(struct table_rule_action *action, + struct pipeline *p, + uint32_t table_id) { - uint32_t n_regular = RTE_MIN(t->n_regular, RTE_DIM(t->regular)); - uint32_t n_custom = RTE_MIN(t->n_custom, RTE_DIM(t->custom)); - uint32_t i; + if ((action == NULL) || + (action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD)) || + (p == NULL) || + (table_id >= p->n_tables)) + return -1; - /* search regular pipelines of current thread */ - for (i = 0; i < n_regular; i++) { - if (t->regular[i].pipeline_id != req->pipeline_id) - continue; + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { + if ((action->fwd.action == RTE_PIPELINE_ACTION_PORT) && + (action->fwd.id >= p->n_ports_out)) + return -1; + + if ((action->fwd.action == RTE_PIPELINE_ACTION_TABLE) && + (action->fwd.id >= p->n_tables)) + return -1; + } - if (i < n_regular - 1) - memcpy(&t->regular[i], - &t->regular[i+1], - (n_regular - 1 - i) * sizeof(struct app_thread_pipeline_data)); + return 0; +} - n_regular--; - t->n_regular = n_regular; +union table_rule_match_low_level { + struct rte_table_acl_rule_add_params acl_add; + struct rte_table_acl_rule_delete_params acl_delete; + struct rte_table_array_key array; + uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX]; + struct rte_table_lpm_key lpm_ipv4; + struct rte_table_lpm_ipv6_key lpm_ipv6; +}; +static int +match_convert(struct table_rule_match *mh, + union table_rule_match_low_level *ml, + int add); + +static int +action_convert(struct rte_table_action *a, + struct table_rule_action *action, + struct rte_pipeline_table_entry *data); + +int +pipeline_table_rule_add(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match, + struct table_rule_action *action, + void **data) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (match == NULL) || + (action == NULL) || + (data == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables) || + match_check(match, p, table_id) || + action_check(action, p, table_id)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + union table_rule_match_low_level match_ll; + struct rte_pipeline_table_entry *data_in, *data_out; + int key_found; + uint8_t *buffer; + + buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); + if (buffer == NULL) + return -1; + + /* Table match-action rule conversion */ + data_in = (struct rte_pipeline_table_entry *)buffer; + + status = match_convert(match, &match_ll, 1); + if (status) { + free(buffer); + return -1; + } + + status = action_convert(a, action, data_in); + if (status) { + free(buffer); + return -1; + } + + /* Add rule (match, action) to table */ + status = rte_pipeline_table_entry_add(p->p, + table_id, + &match_ll, + data_in, + &key_found, + &data_out); + if (status) { + free(buffer); + return -1; + } + + /* Write Response */ + *data = data_out; + + free(buffer); return 0; } - /* search custom pipelines of current thread */ - for (i = 0; i < n_custom; i++) { - if (t->custom[i].pipeline_id != req->pipeline_id) - continue; + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_ADD; + req->id = table_id; + memcpy(&req->table_rule_add.match, match, sizeof(*match)); + memcpy(&req->table_rule_add.action, action, sizeof(*action)); + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; - if (i < n_custom - 1) - memcpy(&t->custom[i], - &t->custom[i+1], - (n_custom - 1 - i) * sizeof(struct app_thread_pipeline_data)); + /* Read response */ + status = rsp->status; + if (status == 0) + *data = rsp->table_rule_add.data; - n_custom--; - t->n_custom = n_custom; + /* Free response */ + pipeline_msg_free(rsp); + return status; +} + +int +pipeline_table_rule_add_default(const char *pipeline_name, + uint32_t table_id, + struct table_rule_action *action, + void **data) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (action == NULL) || + (data == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables) || + action_default_check(action, p, table_id)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_pipeline_table_entry *data_in, *data_out; + uint8_t *buffer; + + buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); + if (buffer == NULL) + return -1; + + /* Apply actions */ + data_in = (struct rte_pipeline_table_entry *)buffer; + + data_in->action = action->fwd.action; + if (action->fwd.action == RTE_PIPELINE_ACTION_PORT) + data_in->port_id = action->fwd.id; + if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE) + data_in->table_id = action->fwd.id; + + /* Add default rule to table */ + status = rte_pipeline_table_default_entry_add(p->p, + table_id, + data_in, + &data_out); + if (status) { + free(buffer); + return -1; + } + + /* Write Response */ + *data = data_out; + + free(buffer); return 0; } - /* return if pipeline not found */ - return -1; + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT; + req->id = table_id; + memcpy(&req->table_rule_add_default.action, action, sizeof(*action)); + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + if (status == 0) + *data = rsp->table_rule_add_default.data; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; } -static int -thread_msg_req_handle(struct app_thread_data *t) +int +pipeline_table_rule_add_bulk(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match, + struct table_rule_action *action, + void **data, + uint32_t *n_rules) { - void *msg_ptr; - struct thread_msg_req *req; - struct thread_msg_rsp *rsp; + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + uint32_t i; + int status; - msg_ptr = thread_msg_recv(t->msgq_in); - req = msg_ptr; - rsp = msg_ptr; + /* Check input params */ + if ((pipeline_name == NULL) || + (match == NULL) || + (action == NULL) || + (data == NULL) || + (n_rules == NULL) || + (*n_rules == 0)) + return -1; - if (req != NULL) - switch (req->type) { - case THREAD_MSG_REQ_PIPELINE_ENABLE: { - rsp->status = thread_pipeline_enable(t, - (struct thread_pipeline_enable_msg_req *) req); - thread_msg_send(t->msgq_out, rsp); - break; + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + for (i = 0; i < *n_rules; i++) + if (match_check(match, p, table_id) || + action_check(action, p, table_id)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + union table_rule_match_low_level *match_ll; + uint8_t *action_ll; + void **match_ll_ptr; + struct rte_pipeline_table_entry **action_ll_ptr; + struct rte_pipeline_table_entry **entries_ptr = + (struct rte_pipeline_table_entry **)data; + uint32_t bulk = + (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0; + int *found; + + /* Memory allocation */ + match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level)); + action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX); + match_ll_ptr = calloc(*n_rules, sizeof(void *)); + action_ll_ptr = + calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *)); + found = calloc(*n_rules, sizeof(int)); + + if (match_ll == NULL || + action_ll == NULL || + match_ll_ptr == NULL || + action_ll_ptr == NULL || + found == NULL) + goto fail; + + for (i = 0; i < *n_rules; i++) { + match_ll_ptr[i] = (void *)&match_ll[i]; + action_ll_ptr[i] = + (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX]; } - case THREAD_MSG_REQ_PIPELINE_DISABLE: { - rsp->status = thread_pipeline_disable(t, - (struct thread_pipeline_disable_msg_req *) req); - thread_msg_send(t->msgq_out, rsp); - break; + /* Rule match conversion */ + for (i = 0; i < *n_rules; i++) { + status = match_convert(&match[i], match_ll_ptr[i], 1); + if (status) + goto fail; } - case THREAD_MSG_REQ_HEADROOM_READ: { - struct thread_headroom_read_msg_rsp *rsp = - (struct thread_headroom_read_msg_rsp *) - req; + /* Rule action conversion */ + for (i = 0; i < *n_rules; i++) { + status = action_convert(a, &action[i], action_ll_ptr[i]); + if (status) + goto fail; + } - rsp->headroom_ratio = t->headroom_ratio; - rsp->status = 0; - thread_msg_send(t->msgq_out, rsp); - break; + /* Add rule (match, action) to table */ + if (bulk) { + status = rte_pipeline_table_entry_add_bulk(p->p, + table_id, + match_ll_ptr, + action_ll_ptr, + *n_rules, + found, + entries_ptr); + if (status) + *n_rules = 0; + } else { + for (i = 0; i < *n_rules; i++) { + status = rte_pipeline_table_entry_add(p->p, + table_id, + match_ll_ptr[i], + action_ll_ptr[i], + &found[i], + &entries_ptr[i]); + if (status) { + *n_rules = i; + break; + } + } } - default: - break; + + /* Free */ + free(found); + free(action_ll_ptr); + free(match_ll_ptr); + free(action_ll); + free(match_ll); + + return status; + +fail: + free(found); + free(action_ll_ptr); + free(match_ll_ptr); + free(action_ll); + free(match_ll); + + *n_rules = 0; + return -1; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK; + req->id = table_id; + req->table_rule_add_bulk.match = match; + req->table_rule_add_bulk.action = action; + req->table_rule_add_bulk.data = data; + req->table_rule_add_bulk.n_rules = *n_rules; + req->table_rule_add_bulk.bulk = + (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + if (status == 0) + *n_rules = rsp->table_rule_add_bulk.n_rules; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_rule_delete(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (match == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables) || + match_check(match, p, table_id)) + return -1; + + if (!pipeline_is_running(p)) { + union table_rule_match_low_level match_ll; + int key_found; + + status = match_convert(match, &match_ll, 0); + if (status) + return -1; + + status = rte_pipeline_table_entry_delete(p->p, + table_id, + &match_ll, + &key_found, + NULL); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_DELETE; + req->id = table_id; + memcpy(&req->table_rule_delete.match, match, sizeof(*match)); + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_rule_delete_default(const char *pipeline_name, + uint32_t table_id) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if (pipeline_name == NULL) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_pipeline_table_default_entry_delete(p->p, + table_id, + NULL); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT; + req->id = table_id; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_rule_stats_read(const char *pipeline_name, + uint32_t table_id, + void *data, + struct rte_table_action_stats_counters *stats, + int clear) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (data == NULL) || + (stats == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_stats_read(a, + data, + stats, + clear); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ; + req->id = table_id; + req->table_rule_stats_read.data = data; + req->table_rule_stats_read.clear = clear; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + if (status) + memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats)); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_mtr_profile_add(const char *pipeline_name, + uint32_t table_id, + uint32_t meter_profile_id, + struct rte_table_action_meter_profile *profile) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (profile == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_meter_profile_add(a, + meter_profile_id, + profile); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD; + req->id = table_id; + req->table_mtr_profile_add.meter_profile_id = meter_profile_id; + memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile)); + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_mtr_profile_delete(const char *pipeline_name, + uint32_t table_id, + uint32_t meter_profile_id) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if (pipeline_name == NULL) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_meter_profile_delete(a, + meter_profile_id); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE; + req->id = table_id; + req->table_mtr_profile_delete.meter_profile_id = meter_profile_id; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_rule_mtr_read(const char *pipeline_name, + uint32_t table_id, + void *data, + uint32_t tc_mask, + struct rte_table_action_mtr_counters *stats, + int clear) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (data == NULL) || + (stats == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_meter_read(a, + data, + tc_mask, + stats, + clear); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ; + req->id = table_id; + req->table_rule_mtr_read.data = data; + req->table_rule_mtr_read.tc_mask = tc_mask; + req->table_rule_mtr_read.clear = clear; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + if (status) + memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats)); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_dscp_table_update(const char *pipeline_name, + uint32_t table_id, + uint64_t dscp_mask, + struct rte_table_action_dscp_table *dscp_table) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (dscp_table == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_dscp_table_update(a, + dscp_mask, + dscp_table); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE; + req->id = table_id; + req->table_dscp_table_update.dscp_mask = dscp_mask; + memcpy(&req->table_dscp_table_update.dscp_table, + dscp_table, sizeof(*dscp_table)); + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_rule_ttl_read(const char *pipeline_name, + uint32_t table_id, + void *data, + struct rte_table_action_ttl_counters *stats, + int clear) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (data == NULL) || + (stats == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_ttl_read(a, + data, + stats, + clear); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ; + req->id = table_id; + req->table_rule_ttl_read.data = data; + req->table_rule_ttl_read.clear = clear; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + if (status) + memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats)); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +/** + * Data plane threads: message handling + */ +static inline struct pipeline_msg_req * +pipeline_msg_recv(struct rte_ring *msgq_req) +{ + struct pipeline_msg_req *req; + + int status = rte_ring_sc_dequeue(msgq_req, (void **) &req); + + if (status != 0) + return NULL; + + return req; +} + +static inline void +pipeline_msg_send(struct rte_ring *msgq_rsp, + struct pipeline_msg_rsp *rsp) +{ + int status; + + do { + status = rte_ring_sp_enqueue(msgq_rsp, rsp); + } while (status == -ENOBUFS); +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t port_id = req->id; + int clear = req->port_in_stats_read.clear; + + rsp->status = rte_pipeline_port_in_stats_read(p->p, + port_id, + &rsp->port_in_stats_read.stats, + clear); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_port_in_enable(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t port_id = req->id; + + rsp->status = rte_pipeline_port_in_enable(p->p, + port_id); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_port_in_disable(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t port_id = req->id; + + rsp->status = rte_pipeline_port_in_disable(p->p, + port_id); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t port_id = req->id; + int clear = req->port_out_stats_read.clear; + + rsp->status = rte_pipeline_port_out_stats_read(p->p, + port_id, + &rsp->port_out_stats_read.stats, + clear); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_stats_read(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t port_id = req->id; + int clear = req->table_stats_read.clear; + + rsp->status = rte_pipeline_table_stats_read(p->p, + port_id, + &rsp->table_stats_read.stats, + clear); + + return rsp; +} + +static int +match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32) +{ + if (depth > 128) + return -1; + + switch (depth / 32) { + case 0: + depth32[0] = depth; + depth32[1] = 0; + depth32[2] = 0; + depth32[3] = 0; + return 0; + + case 1: + depth32[0] = 32; + depth32[1] = depth - 32; + depth32[2] = 0; + depth32[3] = 0; + return 0; + + case 2: + depth32[0] = 32; + depth32[1] = 32; + depth32[2] = depth - 64; + depth32[3] = 0; + return 0; + + case 3: + depth32[0] = 32; + depth32[1] = 32; + depth32[2] = 32; + depth32[3] = depth - 96; + return 0; + + case 4: + depth32[0] = 32; + depth32[1] = 32; + depth32[2] = 32; + depth32[3] = 32; + return 0; + + default: + return -1; + } +} + +static int +match_convert(struct table_rule_match *mh, + union table_rule_match_low_level *ml, + int add) +{ + memset(ml, 0, sizeof(*ml)); + + switch (mh->match_type) { + case TABLE_ACL: + if (mh->match.acl.ip_version) + if (add) { + ml->acl_add.field_value[0].value.u8 = + mh->match.acl.proto; + ml->acl_add.field_value[0].mask_range.u8 = + mh->match.acl.proto_mask; + + ml->acl_add.field_value[1].value.u32 = + mh->match.acl.ipv4.sa; + ml->acl_add.field_value[1].mask_range.u32 = + mh->match.acl.sa_depth; + + ml->acl_add.field_value[2].value.u32 = + mh->match.acl.ipv4.da; + ml->acl_add.field_value[2].mask_range.u32 = + mh->match.acl.da_depth; + + ml->acl_add.field_value[3].value.u16 = + mh->match.acl.sp0; + ml->acl_add.field_value[3].mask_range.u16 = + mh->match.acl.sp1; + + ml->acl_add.field_value[4].value.u16 = + mh->match.acl.dp0; + ml->acl_add.field_value[4].mask_range.u16 = + mh->match.acl.dp1; + + ml->acl_add.priority = + (int32_t) mh->match.acl.priority; + } else { + ml->acl_delete.field_value[0].value.u8 = + mh->match.acl.proto; + ml->acl_delete.field_value[0].mask_range.u8 = + mh->match.acl.proto_mask; + + ml->acl_delete.field_value[1].value.u32 = + mh->match.acl.ipv4.sa; + ml->acl_delete.field_value[1].mask_range.u32 = + mh->match.acl.sa_depth; + + ml->acl_delete.field_value[2].value.u32 = + mh->match.acl.ipv4.da; + ml->acl_delete.field_value[2].mask_range.u32 = + mh->match.acl.da_depth; + + ml->acl_delete.field_value[3].value.u16 = + mh->match.acl.sp0; + ml->acl_delete.field_value[3].mask_range.u16 = + mh->match.acl.sp1; + + ml->acl_delete.field_value[4].value.u16 = + mh->match.acl.dp0; + ml->acl_delete.field_value[4].mask_range.u16 = + mh->match.acl.dp1; + } + else + if (add) { + uint32_t *sa32 = + (uint32_t *) mh->match.acl.ipv6.sa; + uint32_t *da32 = + (uint32_t *) mh->match.acl.ipv6.da; + uint32_t sa32_depth[4], da32_depth[4]; + int status; + + status = match_convert_ipv6_depth( + mh->match.acl.sa_depth, + sa32_depth); + if (status) + return status; + + status = match_convert_ipv6_depth( + mh->match.acl.da_depth, + da32_depth); + if (status) + return status; + + ml->acl_add.field_value[0].value.u8 = + mh->match.acl.proto; + ml->acl_add.field_value[0].mask_range.u8 = + mh->match.acl.proto_mask; + + ml->acl_add.field_value[1].value.u32 = sa32[0]; + ml->acl_add.field_value[1].mask_range.u32 = + sa32_depth[0]; + ml->acl_add.field_value[2].value.u32 = sa32[1]; + ml->acl_add.field_value[2].mask_range.u32 = + sa32_depth[1]; + ml->acl_add.field_value[3].value.u32 = sa32[2]; + ml->acl_add.field_value[3].mask_range.u32 = + sa32_depth[2]; + ml->acl_add.field_value[4].value.u32 = sa32[3]; + ml->acl_add.field_value[4].mask_range.u32 = + sa32_depth[3]; + + ml->acl_add.field_value[5].value.u32 = da32[0]; + ml->acl_add.field_value[5].mask_range.u32 = + da32_depth[0]; + ml->acl_add.field_value[6].value.u32 = da32[1]; + ml->acl_add.field_value[6].mask_range.u32 = + da32_depth[1]; + ml->acl_add.field_value[7].value.u32 = da32[2]; + ml->acl_add.field_value[7].mask_range.u32 = + da32_depth[2]; + ml->acl_add.field_value[8].value.u32 = da32[3]; + ml->acl_add.field_value[8].mask_range.u32 = + da32_depth[3]; + + ml->acl_add.field_value[9].value.u16 = + mh->match.acl.sp0; + ml->acl_add.field_value[9].mask_range.u16 = + mh->match.acl.sp1; + + ml->acl_add.field_value[10].value.u16 = + mh->match.acl.dp0; + ml->acl_add.field_value[10].mask_range.u16 = + mh->match.acl.dp1; + + ml->acl_add.priority = + (int32_t) mh->match.acl.priority; + } else { + uint32_t *sa32 = + (uint32_t *) mh->match.acl.ipv6.sa; + uint32_t *da32 = + (uint32_t *) mh->match.acl.ipv6.da; + uint32_t sa32_depth[4], da32_depth[4]; + int status; + + status = match_convert_ipv6_depth( + mh->match.acl.sa_depth, + sa32_depth); + if (status) + return status; + + status = match_convert_ipv6_depth( + mh->match.acl.da_depth, + da32_depth); + if (status) + return status; + + ml->acl_delete.field_value[0].value.u8 = + mh->match.acl.proto; + ml->acl_delete.field_value[0].mask_range.u8 = + mh->match.acl.proto_mask; + + ml->acl_delete.field_value[1].value.u32 = + sa32[0]; + ml->acl_delete.field_value[1].mask_range.u32 = + sa32_depth[0]; + ml->acl_delete.field_value[2].value.u32 = + sa32[1]; + ml->acl_delete.field_value[2].mask_range.u32 = + sa32_depth[1]; + ml->acl_delete.field_value[3].value.u32 = + sa32[2]; + ml->acl_delete.field_value[3].mask_range.u32 = + sa32_depth[2]; + ml->acl_delete.field_value[4].value.u32 = + sa32[3]; + ml->acl_delete.field_value[4].mask_range.u32 = + sa32_depth[3]; + + ml->acl_delete.field_value[5].value.u32 = + da32[0]; + ml->acl_delete.field_value[5].mask_range.u32 = + da32_depth[0]; + ml->acl_delete.field_value[6].value.u32 = + da32[1]; + ml->acl_delete.field_value[6].mask_range.u32 = + da32_depth[1]; + ml->acl_delete.field_value[7].value.u32 = + da32[2]; + ml->acl_delete.field_value[7].mask_range.u32 = + da32_depth[2]; + ml->acl_delete.field_value[8].value.u32 = + da32[3]; + ml->acl_delete.field_value[8].mask_range.u32 = + da32_depth[3]; + + ml->acl_delete.field_value[9].value.u16 = + mh->match.acl.sp0; + ml->acl_delete.field_value[9].mask_range.u16 = + mh->match.acl.sp1; + + ml->acl_delete.field_value[10].value.u16 = + mh->match.acl.dp0; + ml->acl_delete.field_value[10].mask_range.u16 = + mh->match.acl.dp1; + } + return 0; + + case TABLE_ARRAY: + ml->array.pos = mh->match.array.pos; + return 0; + + case TABLE_HASH: + memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash)); + return 0; + + case TABLE_LPM: + if (mh->match.lpm.ip_version) { + ml->lpm_ipv4.ip = mh->match.lpm.ipv4; + ml->lpm_ipv4.depth = mh->match.lpm.depth; + } else { + memcpy(ml->lpm_ipv6.ip, + mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip)); + ml->lpm_ipv6.depth = mh->match.lpm.depth; } + return 0; + + default: + return -1; + } +} + +static int +action_convert(struct rte_table_action *a, + struct table_rule_action *action, + struct rte_pipeline_table_entry *data) +{ + int status; + + /* Apply actions */ + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_FWD, + &action->fwd); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_LB, + &action->lb); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_MTR, + &action->mtr); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_TM, + &action->tm); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_ENCAP, + &action->encap); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_NAT, + &action->nat); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_TTL, + &action->ttl); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_STATS, + &action->stats); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_TIME, + &action->time); + + if (status) + return status; + } + return 0; } -static void -thread_headroom_update(struct app_thread_data *t, uint64_t time) +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_add(struct pipeline_data *p, + struct pipeline_msg_req *req) { - uint64_t time_diff = time - t->headroom_time; + union table_rule_match_low_level match_ll; + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + struct table_rule_match *match = &req->table_rule_add.match; + struct table_rule_action *action = &req->table_rule_add.action; + struct rte_pipeline_table_entry *data_in, *data_out; + uint32_t table_id = req->id; + int key_found, status; + struct rte_table_action *a = p->table_data[table_id].a; + + /* Apply actions */ + memset(p->buffer, 0, sizeof(p->buffer)); + data_in = (struct rte_pipeline_table_entry *) p->buffer; + + status = match_convert(match, &match_ll, 1); + if (status) { + rsp->status = -1; + return rsp; + } + + status = action_convert(a, action, data_in); + if (status) { + rsp->status = -1; + return rsp; + } + + status = rte_pipeline_table_entry_add(p->p, + table_id, + &match_ll, + data_in, + &key_found, + &data_out); + if (status) { + rsp->status = -1; + return rsp; + } - t->headroom_ratio = - ((double) t->headroom_cycles) / ((double) time_diff); + /* Write response */ + rsp->status = 0; + rsp->table_rule_add.data = data_out; - t->headroom_cycles = 0; - t->headroom_time = rte_rdtsc_precise(); + return rsp; } -int -app_thread(void *arg) +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p, + struct pipeline_msg_req *req) { - struct app_params *app = (struct app_params *) arg; - uint32_t core_id = rte_lcore_id(), i, j; - struct app_thread_data *t = &app->thread_data[core_id]; + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + struct table_rule_action *action = &req->table_rule_add_default.action; + struct rte_pipeline_table_entry *data_in, *data_out; + uint32_t table_id = req->id; + int status; - for (i = 0; ; i++) { - uint32_t n_regular = RTE_MIN(t->n_regular, RTE_DIM(t->regular)); - uint32_t n_custom = RTE_MIN(t->n_custom, RTE_DIM(t->custom)); + /* Apply actions */ + memset(p->buffer, 0, sizeof(p->buffer)); + data_in = (struct rte_pipeline_table_entry *) p->buffer; + + data_in->action = action->fwd.action; + if (action->fwd.action == RTE_PIPELINE_ACTION_PORT) + data_in->port_id = action->fwd.id; + if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE) + data_in->table_id = action->fwd.id; + + /* Add default rule to table */ + status = rte_pipeline_table_default_entry_add(p->p, + table_id, + data_in, + &data_out); + if (status) { + rsp->status = -1; + return rsp; + } - /* Run regular pipelines */ - for (j = 0; j < n_regular; j++) { - struct app_thread_pipeline_data *data = &t->regular[j]; - struct pipeline *p = data->be; + /* Write response */ + rsp->status = 0; + rsp->table_rule_add_default.data = data_out; - PIPELINE_RUN_REGULAR(t, p); + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + + uint32_t table_id = req->id; + struct table_rule_match *match = req->table_rule_add_bulk.match; + struct table_rule_action *action = req->table_rule_add_bulk.action; + struct rte_pipeline_table_entry **data = + (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data; + uint32_t n_rules = req->table_rule_add_bulk.n_rules; + uint32_t bulk = req->table_rule_add_bulk.bulk; + + struct rte_table_action *a = p->table_data[table_id].a; + union table_rule_match_low_level *match_ll; + uint8_t *action_ll; + void **match_ll_ptr; + struct rte_pipeline_table_entry **action_ll_ptr; + int *found, status; + uint32_t i; + + /* Memory allocation */ + match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level)); + action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX); + match_ll_ptr = calloc(n_rules, sizeof(void *)); + action_ll_ptr = + calloc(n_rules, sizeof(struct rte_pipeline_table_entry *)); + found = calloc(n_rules, sizeof(int)); + + if ((match_ll == NULL) || + (action_ll == NULL) || + (match_ll_ptr == NULL) || + (action_ll_ptr == NULL) || + (found == NULL)) + goto fail; + + for (i = 0; i < n_rules; i++) { + match_ll_ptr[i] = (void *)&match_ll[i]; + action_ll_ptr[i] = + (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX]; + } + + /* Rule match conversion */ + for (i = 0; i < n_rules; i++) { + status = match_convert(&match[i], match_ll_ptr[i], 1); + if (status) + goto fail; + } + + /* Rule action conversion */ + for (i = 0; i < n_rules; i++) { + status = action_convert(a, &action[i], action_ll_ptr[i]); + if (status) + goto fail; + } + + /* Add rule (match, action) to table */ + if (bulk) { + status = rte_pipeline_table_entry_add_bulk(p->p, + table_id, + match_ll_ptr, + action_ll_ptr, + n_rules, + found, + data); + if (status) + n_rules = 0; + } else + for (i = 0; i < n_rules; i++) { + status = rte_pipeline_table_entry_add(p->p, + table_id, + match_ll_ptr[i], + action_ll_ptr[i], + &found[i], + &data[i]); + if (status) { + n_rules = i; + break; + } } - /* Run custom pipelines */ - for (j = 0; j < n_custom; j++) { - struct app_thread_pipeline_data *data = &t->custom[j]; + /* Write response */ + rsp->status = 0; + rsp->table_rule_add_bulk.n_rules = n_rules; + + /* Free */ + free(found); + free(action_ll_ptr); + free(match_ll_ptr); + free(action_ll); + free(match_ll); + + return rsp; + +fail: + free(found); + free(action_ll_ptr); + free(match_ll_ptr); + free(action_ll); + free(match_ll); + + rsp->status = -1; + rsp->table_rule_add_bulk.n_rules = 0; + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_delete(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + union table_rule_match_low_level match_ll; + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + struct table_rule_match *match = &req->table_rule_delete.match; + uint32_t table_id = req->id; + int key_found, status; + + status = match_convert(match, &match_ll, 0); + if (status) { + rsp->status = -1; + return rsp; + } + + rsp->status = rte_pipeline_table_entry_delete(p->p, + table_id, + &match_ll, + &key_found, + NULL); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t table_id = req->id; + + rsp->status = rte_pipeline_table_default_entry_delete(p->p, + table_id, + NULL); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t table_id = req->id; + void *data = req->table_rule_stats_read.data; + int clear = req->table_rule_stats_read.clear; + struct rte_table_action *a = p->table_data[table_id].a; + + rsp->status = rte_table_action_stats_read(a, + data, + &rsp->table_rule_stats_read.stats, + clear); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t table_id = req->id; + uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id; + struct rte_table_action_meter_profile *profile = + &req->table_mtr_profile_add.profile; + struct rte_table_action *a = p->table_data[table_id].a; + + rsp->status = rte_table_action_meter_profile_add(a, + meter_profile_id, + profile); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t table_id = req->id; + uint32_t meter_profile_id = + req->table_mtr_profile_delete.meter_profile_id; + struct rte_table_action *a = p->table_data[table_id].a; + + rsp->status = rte_table_action_meter_profile_delete(a, + meter_profile_id); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t table_id = req->id; + void *data = req->table_rule_mtr_read.data; + uint32_t tc_mask = req->table_rule_mtr_read.tc_mask; + int clear = req->table_rule_mtr_read.clear; + struct rte_table_action *a = p->table_data[table_id].a; + + rsp->status = rte_table_action_meter_read(a, + data, + tc_mask, + &rsp->table_rule_mtr_read.stats, + clear); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t table_id = req->id; + uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask; + struct rte_table_action_dscp_table *dscp_table = + &req->table_dscp_table_update.dscp_table; + struct rte_table_action *a = p->table_data[table_id].a; + + rsp->status = rte_table_action_dscp_table_update(a, + dscp_mask, + dscp_table); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + uint32_t table_id = req->id; + void *data = req->table_rule_ttl_read.data; + int clear = req->table_rule_ttl_read.clear; + struct rte_table_action *a = p->table_data[table_id].a; + + rsp->status = rte_table_action_ttl_read(a, + data, + &rsp->table_rule_ttl_read.stats, + clear); + + return rsp; +} + +static void +pipeline_msg_handle(struct pipeline_data *p) +{ + for ( ; ; ) { + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; - PIPELINE_RUN_CUSTOM(t, data); + req = pipeline_msg_recv(p->msgq_req); + if (req == NULL) + break; + + switch (req->type) { + case PIPELINE_REQ_PORT_IN_STATS_READ: + rsp = pipeline_msg_handle_port_in_stats_read(p, req); + break; + + case PIPELINE_REQ_PORT_IN_ENABLE: + rsp = pipeline_msg_handle_port_in_enable(p, req); + break; + + case PIPELINE_REQ_PORT_IN_DISABLE: + rsp = pipeline_msg_handle_port_in_disable(p, req); + break; + + case PIPELINE_REQ_PORT_OUT_STATS_READ: + rsp = pipeline_msg_handle_port_out_stats_read(p, req); + break; + + case PIPELINE_REQ_TABLE_STATS_READ: + rsp = pipeline_msg_handle_table_stats_read(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_ADD: + rsp = pipeline_msg_handle_table_rule_add(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT: + rsp = pipeline_msg_handle_table_rule_add_default(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_ADD_BULK: + rsp = pipeline_msg_handle_table_rule_add_bulk(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_DELETE: + rsp = pipeline_msg_handle_table_rule_delete(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT: + rsp = pipeline_msg_handle_table_rule_delete_default(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_STATS_READ: + rsp = pipeline_msg_handle_table_rule_stats_read(p, req); + break; + + case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD: + rsp = pipeline_msg_handle_table_mtr_profile_add(p, req); + break; + + case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE: + rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_MTR_READ: + rsp = pipeline_msg_handle_table_rule_mtr_read(p, req); + break; + + case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE: + rsp = pipeline_msg_handle_table_dscp_table_update(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_TTL_READ: + rsp = pipeline_msg_handle_table_rule_ttl_read(p, req); + break; + + default: + rsp = (struct pipeline_msg_rsp *) req; + rsp->status = -1; } - /* Timer */ - if ((i & 0xF) == 0) { - uint64_t time = rte_get_tsc_cycles(); - uint64_t t_deadline = UINT64_MAX; + pipeline_msg_send(p->msgq_rsp, rsp); + } +} - if (time < t->deadline) - continue; +/** + * Data plane threads: main + */ +int +thread_main(void *arg __rte_unused) +{ + struct thread_data *t; + uint32_t thread_id, i; - /* Timer for regular pipelines */ - for (j = 0; j < n_regular; j++) { - struct app_thread_pipeline_data *data = - &t->regular[j]; - uint64_t p_deadline = data->deadline; + thread_id = rte_lcore_id(); + t = &thread_data[thread_id]; - if (p_deadline <= time) { - data->f_timer(data->be); - p_deadline = time + data->timer_period; - data->deadline = p_deadline; - } + /* Dispatch loop */ + for (i = 0; ; i++) { + uint32_t j; - if (p_deadline < t_deadline) - t_deadline = p_deadline; - } + /* Data Plane */ + for (j = 0; j < t->n_pipelines; j++) + rte_pipeline_run(t->p[j]); - /* Timer for custom pipelines */ - for (j = 0; j < n_custom; j++) { - struct app_thread_pipeline_data *data = - &t->custom[j]; - uint64_t p_deadline = data->deadline; + /* Control Plane */ + if ((i & 0xF) == 0) { + uint64_t time = rte_get_tsc_cycles(); + uint64_t time_next_min = UINT64_MAX; + + if (time < t->time_next_min) + continue; + + /* Pipeline message queues */ + for (j = 0; j < t->n_pipelines; j++) { + struct pipeline_data *p = + &t->pipeline_data[j]; + uint64_t time_next = p->time_next; - if (p_deadline <= time) { - data->f_timer(data->be); - p_deadline = time + data->timer_period; - data->deadline = p_deadline; + if (time_next <= time) { + pipeline_msg_handle(p); + rte_pipeline_flush(p->p); + time_next = time + p->timer_period; + p->time_next = time_next; } - if (p_deadline < t_deadline) - t_deadline = p_deadline; + if (time_next < time_next_min) + time_next_min = time_next; } - /* Timer for thread message request */ + /* Thread message queues */ { - uint64_t deadline = t->thread_req_deadline; + uint64_t time_next = t->time_next; - if (deadline <= time) { - thread_msg_req_handle(t); - thread_headroom_update(t, time); - deadline = time + t->timer_period; - t->thread_req_deadline = deadline; + if (time_next <= time) { + thread_msg_handle(t); + time_next = time + t->timer_period; + t->time_next = time_next; } - if (deadline < t_deadline) - t_deadline = deadline; + if (time_next < time_next_min) + time_next_min = time_next; } - - t->deadline = t_deadline; + t->time_next_min = time_next_min; } } diff --git a/examples/ip_pipeline/thread.h b/examples/ip_pipeline/thread.h index 2c4fb6ae..facdf004 100644 --- a/examples/ip_pipeline/thread.h +++ b/examples/ip_pipeline/thread.h @@ -1,69 +1,24 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation + * Copyright(c) 2010-2018 Intel Corporation */ -#ifndef THREAD_H_ -#define THREAD_H_ +#ifndef _INCLUDE_THREAD_H_ +#define _INCLUDE_THREAD_H_ -#include "app.h" -#include "pipeline_be.h" +#include <stdint.h> -enum thread_msg_req_type { - THREAD_MSG_REQ_PIPELINE_ENABLE = 0, - THREAD_MSG_REQ_PIPELINE_DISABLE, - THREAD_MSG_REQ_HEADROOM_READ, - THREAD_MSG_REQS -}; +int +thread_pipeline_enable(uint32_t thread_id, + const char *pipeline_name); -struct thread_msg_req { - enum thread_msg_req_type type; -}; +int +thread_pipeline_disable(uint32_t thread_id, + const char *pipeline_name); -struct thread_msg_rsp { - int status; -}; +int +thread_init(void); -/* - * PIPELINE ENABLE - */ -struct thread_pipeline_enable_msg_req { - enum thread_msg_req_type type; - - uint32_t pipeline_id; - void *be; - pipeline_be_op_run f_run; - pipeline_be_op_timer f_timer; - uint64_t timer_period; -}; - -struct thread_pipeline_enable_msg_rsp { - int status; -}; - -/* - * PIPELINE DISABLE - */ -struct thread_pipeline_disable_msg_req { - enum thread_msg_req_type type; - - uint32_t pipeline_id; -}; - -struct thread_pipeline_disable_msg_rsp { - int status; -}; - -/* - * THREAD HEADROOM - */ -struct thread_headroom_read_msg_req { - enum thread_msg_req_type type; -}; - -struct thread_headroom_read_msg_rsp { - int status; - - double headroom_ratio; -}; +int +thread_main(void *arg); -#endif /* THREAD_H_ */ +#endif /* _INCLUDE_THREAD_H_ */ diff --git a/examples/ip_pipeline/thread_fe.c b/examples/ip_pipeline/thread_fe.c deleted file mode 100644 index 4590c2b5..00000000 --- a/examples/ip_pipeline/thread_fe.c +++ /dev/null @@ -1,457 +0,0 @@ -#include <rte_common.h> -#include <rte_ring.h> -#include <rte_malloc.h> -#include <cmdline_rdline.h> -#include <cmdline_parse.h> -#include <cmdline_parse_num.h> -#include <cmdline_parse_string.h> - -#include "thread.h" -#include "thread_fe.h" -#include "pipeline.h" -#include "pipeline_common_fe.h" -#include "app.h" - -static inline void * -thread_msg_send_recv(struct app_params *app, - uint32_t socket_id, uint32_t core_id, uint32_t ht_id, - void *msg, - uint32_t timeout_ms) -{ - struct rte_ring *r_req = app_thread_msgq_in_get(app, - socket_id, core_id, ht_id); - struct rte_ring *r_rsp = app_thread_msgq_out_get(app, - socket_id, core_id, ht_id); - uint64_t hz = rte_get_tsc_hz(); - void *msg_recv; - uint64_t deadline; - int status; - - /* send */ - do { - status = rte_ring_sp_enqueue(r_req, (void *) msg); - } while (status == -ENOBUFS); - - /* recv */ - deadline = (timeout_ms) ? - (rte_rdtsc() + ((hz * timeout_ms) / 1000)) : - UINT64_MAX; - - do { - if (rte_rdtsc() > deadline) - return NULL; - - status = rte_ring_sc_dequeue(r_rsp, &msg_recv); - } while (status != 0); - - return msg_recv; -} - -int -app_pipeline_enable(struct app_params *app, - uint32_t socket_id, - uint32_t core_id, - uint32_t hyper_th_id, - uint32_t pipeline_id) -{ - struct thread_pipeline_enable_msg_req *req; - struct thread_pipeline_enable_msg_rsp *rsp; - int thread_id; - struct app_pipeline_data *p; - struct app_pipeline_params *p_params; - struct pipeline_type *p_type; - int status; - - if (app == NULL) - return -1; - - thread_id = cpu_core_map_get_lcore_id(app->core_map, - socket_id, - core_id, - hyper_th_id); - - if ((thread_id < 0) || !app_core_is_enabled(app, thread_id)) - return -1; - - if (app_pipeline_data(app, pipeline_id) == NULL) - return -1; - - p = &app->pipeline_data[pipeline_id]; - p_params = &app->pipeline_params[pipeline_id]; - p_type = app_pipeline_type_find(app, p_params->type); - - if (p_type == NULL) - return -1; - - if (p->enabled == 1) - return -1; - - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = THREAD_MSG_REQ_PIPELINE_ENABLE; - req->pipeline_id = pipeline_id; - req->be = p->be; - req->f_run = p_type->be_ops->f_run; - req->f_timer = p_type->be_ops->f_timer; - req->timer_period = p->timer_period; - - rsp = thread_msg_send_recv(app, - socket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT); - if (rsp == NULL) - return -1; - - status = rsp->status; - app_msg_free(app, rsp); - - if (status != 0) - return -1; - - p->enabled = 1; - return 0; -} - -int -app_pipeline_disable(struct app_params *app, - uint32_t socket_id, - uint32_t core_id, - uint32_t hyper_th_id, - uint32_t pipeline_id) -{ - struct thread_pipeline_disable_msg_req *req; - struct thread_pipeline_disable_msg_rsp *rsp; - int thread_id; - struct app_pipeline_data *p; - int status; - - if (app == NULL) - return -1; - - thread_id = cpu_core_map_get_lcore_id(app->core_map, - socket_id, - core_id, - hyper_th_id); - - if ((thread_id < 0) || !app_core_is_enabled(app, thread_id)) - return -1; - - if (app_pipeline_data(app, pipeline_id) == NULL) - return -1; - - p = &app->pipeline_data[pipeline_id]; - - if (p->enabled == 0) - return -1; - - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = THREAD_MSG_REQ_PIPELINE_DISABLE; - req->pipeline_id = pipeline_id; - - rsp = thread_msg_send_recv(app, - socket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT); - - if (rsp == NULL) - return -1; - - status = rsp->status; - app_msg_free(app, rsp); - - if (status != 0) - return -1; - - p->enabled = 0; - return 0; -} - -int -app_thread_headroom(struct app_params *app, - uint32_t socket_id, - uint32_t core_id, - uint32_t hyper_th_id) -{ - struct thread_headroom_read_msg_req *req; - struct thread_headroom_read_msg_rsp *rsp; - int thread_id; - int status; - - if (app == NULL) - return -1; - - thread_id = cpu_core_map_get_lcore_id(app->core_map, - socket_id, - core_id, - hyper_th_id); - - if ((thread_id < 0) || !app_core_is_enabled(app, thread_id)) - return -1; - - req = app_msg_alloc(app); - if (req == NULL) - return -1; - - req->type = THREAD_MSG_REQ_HEADROOM_READ; - - rsp = thread_msg_send_recv(app, - socket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT); - - if (rsp == NULL) - return -1; - - status = rsp->status; - - if (status != 0) - return -1; - - printf("%.3f%%\n", rsp->headroom_ratio * 100); - - - app_msg_free(app, rsp); - - return 0; -} - -/* - * pipeline enable - */ - -struct cmd_pipeline_enable_result { - cmdline_fixed_string_t t_string; - cmdline_fixed_string_t t_id_string; - cmdline_fixed_string_t pipeline_string; - uint32_t pipeline_id; - cmdline_fixed_string_t enable_string; -}; - -static void -cmd_pipeline_enable_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_pipeline_enable_result *params = parsed_result; - struct app_params *app = data; - int status; - uint32_t core_id, socket_id, hyper_th_id; - - if (parse_pipeline_core(&socket_id, - &core_id, - &hyper_th_id, - params->t_id_string) != 0) { - printf("Command failed\n"); - return; - } - - status = app_pipeline_enable(app, - socket_id, - core_id, - hyper_th_id, - params->pipeline_id); - - if (status != 0) - printf("Command failed\n"); -} - -static cmdline_parse_token_string_t cmd_pipeline_enable_t_string = - TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_string, "t"); - -static cmdline_parse_token_string_t cmd_pipeline_enable_t_id_string = - TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_id_string, - NULL); - -static cmdline_parse_token_string_t cmd_pipeline_enable_pipeline_string = - TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_string, - "pipeline"); - -static cmdline_parse_token_num_t cmd_pipeline_enable_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_id, - UINT32); - -static cmdline_parse_token_string_t cmd_pipeline_enable_enable_string = - TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, enable_string, - "enable"); - -static cmdline_parse_inst_t cmd_pipeline_enable = { - .f = cmd_pipeline_enable_parsed, - .data = NULL, - .help_str = "Enable pipeline on specified core", - .tokens = { - (void *)&cmd_pipeline_enable_t_string, - (void *)&cmd_pipeline_enable_t_id_string, - (void *)&cmd_pipeline_enable_pipeline_string, - (void *)&cmd_pipeline_enable_pipeline_id, - (void *)&cmd_pipeline_enable_enable_string, - NULL, - }, -}; - -/* - * pipeline disable - */ - -struct cmd_pipeline_disable_result { - cmdline_fixed_string_t t_string; - cmdline_fixed_string_t t_id_string; - cmdline_fixed_string_t pipeline_string; - uint32_t pipeline_id; - cmdline_fixed_string_t disable_string; -}; - -static void -cmd_pipeline_disable_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_pipeline_disable_result *params = parsed_result; - struct app_params *app = data; - int status; - uint32_t core_id, socket_id, hyper_th_id; - - if (parse_pipeline_core(&socket_id, - &core_id, - &hyper_th_id, - params->t_id_string) != 0) { - printf("Command failed\n"); - return; - } - - status = app_pipeline_disable(app, - socket_id, - core_id, - hyper_th_id, - params->pipeline_id); - - if (status != 0) - printf("Command failed\n"); -} - -static cmdline_parse_token_string_t cmd_pipeline_disable_t_string = - TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_string, "t"); - -static cmdline_parse_token_string_t cmd_pipeline_disable_t_id_string = - TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_id_string, - NULL); - -static cmdline_parse_token_string_t cmd_pipeline_disable_pipeline_string = - TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, - pipeline_string, "pipeline"); - -static cmdline_parse_token_num_t cmd_pipeline_disable_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_pipeline_disable_result, pipeline_id, - UINT32); - -static cmdline_parse_token_string_t cmd_pipeline_disable_disable_string = - TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, disable_string, - "disable"); - -static cmdline_parse_inst_t cmd_pipeline_disable = { - .f = cmd_pipeline_disable_parsed, - .data = NULL, - .help_str = "Disable pipeline on specified core", - .tokens = { - (void *)&cmd_pipeline_disable_t_string, - (void *)&cmd_pipeline_disable_t_id_string, - (void *)&cmd_pipeline_disable_pipeline_string, - (void *)&cmd_pipeline_disable_pipeline_id, - (void *)&cmd_pipeline_disable_disable_string, - NULL, - }, -}; - - -/* - * thread headroom - */ - -struct cmd_thread_headroom_result { - cmdline_fixed_string_t t_string; - cmdline_fixed_string_t t_id_string; - cmdline_fixed_string_t headroom_string; -}; - -static void -cmd_thread_headroom_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_thread_headroom_result *params = parsed_result; - struct app_params *app = data; - int status; - uint32_t core_id, socket_id, hyper_th_id; - - if (parse_pipeline_core(&socket_id, - &core_id, - &hyper_th_id, - params->t_id_string) != 0) { - printf("Command failed\n"); - return; - } - - status = app_thread_headroom(app, - socket_id, - core_id, - hyper_th_id); - - if (status != 0) - printf("Command failed\n"); -} - -static cmdline_parse_token_string_t cmd_thread_headroom_t_string = - TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result, - t_string, "t"); - -static cmdline_parse_token_string_t cmd_thread_headroom_t_id_string = - TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result, - t_id_string, NULL); - -static cmdline_parse_token_string_t cmd_thread_headroom_headroom_string = - TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result, - headroom_string, "headroom"); - -static cmdline_parse_inst_t cmd_thread_headroom = { - .f = cmd_thread_headroom_parsed, - .data = NULL, - .help_str = "Display thread headroom", - .tokens = { - (void *)&cmd_thread_headroom_t_string, - (void *)&cmd_thread_headroom_t_id_string, - (void *)&cmd_thread_headroom_headroom_string, - NULL, - }, -}; - - -static cmdline_parse_ctx_t thread_cmds[] = { - (cmdline_parse_inst_t *) &cmd_pipeline_enable, - (cmdline_parse_inst_t *) &cmd_pipeline_disable, - (cmdline_parse_inst_t *) &cmd_thread_headroom, - NULL, -}; - -int -app_pipeline_thread_cmd_push(struct app_params *app) -{ - uint32_t n_cmds, i; - - /* Check for available slots in the application commands array */ - n_cmds = RTE_DIM(thread_cmds) - 1; - if (n_cmds > APP_MAX_CMDS - app->n_cmds) - return -ENOMEM; - - /* Push thread commands into the application */ - memcpy(&app->cmds[app->n_cmds], thread_cmds, - n_cmds * sizeof(cmdline_parse_ctx_t)); - - for (i = 0; i < n_cmds; i++) - app->cmds[app->n_cmds + i]->data = app; - - app->n_cmds += n_cmds; - app->cmds[app->n_cmds] = NULL; - - return 0; -} diff --git a/examples/ip_pipeline/thread_fe.h b/examples/ip_pipeline/thread_fe.h deleted file mode 100644 index 056a5e8a..00000000 --- a/examples/ip_pipeline/thread_fe.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef THREAD_FE_H_ -#define THREAD_FE_H_ - -static inline struct rte_ring * -app_thread_msgq_in_get(struct app_params *app, - uint32_t socket_id, uint32_t core_id, uint32_t ht_id) -{ - char msgq_name[32]; - ssize_t param_idx; - - snprintf(msgq_name, sizeof(msgq_name), - "MSGQ-REQ-CORE-s%" PRIu32 "c%" PRIu32 "%s", - socket_id, - core_id, - (ht_id) ? "h" : ""); - param_idx = APP_PARAM_FIND(app->msgq_params, msgq_name); - - if (param_idx < 0) - return NULL; - - return app->msgq[param_idx]; -} - -static inline struct rte_ring * -app_thread_msgq_out_get(struct app_params *app, - uint32_t socket_id, uint32_t core_id, uint32_t ht_id) -{ - char msgq_name[32]; - ssize_t param_idx; - - snprintf(msgq_name, sizeof(msgq_name), - "MSGQ-RSP-CORE-s%" PRIu32 "c%" PRIu32 "%s", - socket_id, - core_id, - (ht_id) ? "h" : ""); - param_idx = APP_PARAM_FIND(app->msgq_params, msgq_name); - - if (param_idx < 0) - return NULL; - - return app->msgq[param_idx]; - -} - -int -app_pipeline_thread_cmd_push(struct app_params *app); - -int -app_pipeline_enable(struct app_params *app, - uint32_t core_id, - uint32_t socket_id, - uint32_t hyper_th_id, - uint32_t pipeline_id); - -int -app_pipeline_disable(struct app_params *app, - uint32_t core_id, - uint32_t socket_id, - uint32_t hyper_th_id, - uint32_t pipeline_id); - -int -app_thread_headroom(struct app_params *app, - uint32_t core_id, - uint32_t socket_id, - uint32_t hyper_th_id); - -#endif /* THREAD_FE_H_ */ diff --git a/examples/ip_pipeline/tmgr.c b/examples/ip_pipeline/tmgr.c new file mode 100644 index 00000000..40cbf1d0 --- /dev/null +++ b/examples/ip_pipeline/tmgr.c @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <stdlib.h> + +#include <rte_string_fns.h> + +#include "tmgr.h" + +static struct rte_sched_subport_params + subport_profile[TMGR_SUBPORT_PROFILE_MAX]; + +static uint32_t n_subport_profiles; + +static struct rte_sched_pipe_params + pipe_profile[TMGR_PIPE_PROFILE_MAX]; + +static uint32_t n_pipe_profiles; + +static struct tmgr_port_list tmgr_port_list; + +int +tmgr_init(void) +{ + TAILQ_INIT(&tmgr_port_list); + + return 0; +} + +struct tmgr_port * +tmgr_port_find(const char *name) +{ + struct tmgr_port *tmgr_port; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(tmgr_port, &tmgr_port_list, node) + if (strcmp(tmgr_port->name, name) == 0) + return tmgr_port; + + return NULL; +} + +int +tmgr_subport_profile_add(struct rte_sched_subport_params *p) +{ + /* Check input params */ + if (p == NULL) + return -1; + + /* Save profile */ + memcpy(&subport_profile[n_subport_profiles], + p, + sizeof(*p)); + + n_subport_profiles++; + + return 0; +} + +int +tmgr_pipe_profile_add(struct rte_sched_pipe_params *p) +{ + /* Check input params */ + if (p == NULL) + return -1; + + /* Save profile */ + memcpy(&pipe_profile[n_pipe_profiles], + p, + sizeof(*p)); + + n_pipe_profiles++; + + return 0; +} + +struct tmgr_port * +tmgr_port_create(const char *name, struct tmgr_port_params *params) +{ + struct rte_sched_port_params p; + struct tmgr_port *tmgr_port; + struct rte_sched_port *s; + uint32_t i, j; + + /* Check input params */ + if ((name == NULL) || + tmgr_port_find(name) || + (params == NULL) || + (params->n_subports_per_port == 0) || + (params->n_pipes_per_subport == 0) || + (params->cpu_id >= RTE_MAX_NUMA_NODES) || + (n_subport_profiles == 0) || + (n_pipe_profiles == 0)) + return NULL; + + /* Resource create */ + p.name = name; + p.socket = (int) params->cpu_id; + p.rate = params->rate; + p.mtu = params->mtu; + p.frame_overhead = params->frame_overhead; + p.n_subports_per_port = params->n_subports_per_port; + p.n_pipes_per_subport = params->n_pipes_per_subport; + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + p.qsize[i] = params->qsize[i]; + + p.pipe_profiles = pipe_profile; + p.n_pipe_profiles = n_pipe_profiles; + + s = rte_sched_port_config(&p); + if (s == NULL) + return NULL; + + for (i = 0; i < params->n_subports_per_port; i++) { + int status; + + status = rte_sched_subport_config( + s, + i, + &subport_profile[0]); + + if (status) { + rte_sched_port_free(s); + return NULL; + } + + for (j = 0; j < params->n_pipes_per_subport; j++) { + status = rte_sched_pipe_config( + s, + i, + j, + 0); + + if (status) { + rte_sched_port_free(s); + return NULL; + } + } + } + + /* Node allocation */ + tmgr_port = calloc(1, sizeof(struct tmgr_port)); + if (tmgr_port == NULL) { + rte_sched_port_free(s); + return NULL; + } + + /* Node fill in */ + strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name)); + tmgr_port->s = s; + tmgr_port->n_subports_per_port = params->n_subports_per_port; + tmgr_port->n_pipes_per_subport = params->n_pipes_per_subport; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&tmgr_port_list, tmgr_port, node); + + return tmgr_port; +} + +int +tmgr_subport_config(const char *port_name, + uint32_t subport_id, + uint32_t subport_profile_id) +{ + struct tmgr_port *port; + int status; + + /* Check input params */ + if (port_name == NULL) + return -1; + + port = tmgr_port_find(port_name); + if ((port == NULL) || + (subport_id >= port->n_subports_per_port) || + (subport_profile_id >= n_subport_profiles)) + return -1; + + /* Resource config */ + status = rte_sched_subport_config( + port->s, + subport_id, + &subport_profile[subport_profile_id]); + + return status; +} + +int +tmgr_pipe_config(const char *port_name, + uint32_t subport_id, + uint32_t pipe_id_first, + uint32_t pipe_id_last, + uint32_t pipe_profile_id) +{ + struct tmgr_port *port; + uint32_t i; + + /* Check input params */ + if (port_name == NULL) + return -1; + + port = tmgr_port_find(port_name); + if ((port == NULL) || + (subport_id >= port->n_subports_per_port) || + (pipe_id_first >= port->n_pipes_per_subport) || + (pipe_id_last >= port->n_pipes_per_subport) || + (pipe_id_first > pipe_id_last) || + (pipe_profile_id >= n_pipe_profiles)) + return -1; + + /* Resource config */ + for (i = pipe_id_first; i <= pipe_id_last; i++) { + int status; + + status = rte_sched_pipe_config( + port->s, + subport_id, + i, + (int) pipe_profile_id); + + if (status) + return status; + } + + return 0; +} diff --git a/examples/ip_pipeline/tmgr.h b/examples/ip_pipeline/tmgr.h new file mode 100644 index 00000000..0b497e79 --- /dev/null +++ b/examples/ip_pipeline/tmgr.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _INCLUDE_TMGR_H_ +#define _INCLUDE_TMGR_H_ + +#include <stdint.h> +#include <sys/queue.h> + +#include <rte_sched.h> + +#include "common.h" + +#ifndef TMGR_SUBPORT_PROFILE_MAX +#define TMGR_SUBPORT_PROFILE_MAX 256 +#endif + +#ifndef TMGR_PIPE_PROFILE_MAX +#define TMGR_PIPE_PROFILE_MAX 256 +#endif + +struct tmgr_port { + TAILQ_ENTRY(tmgr_port) node; + char name[NAME_SIZE]; + struct rte_sched_port *s; + uint32_t n_subports_per_port; + uint32_t n_pipes_per_subport; +}; + +TAILQ_HEAD(tmgr_port_list, tmgr_port); + +int +tmgr_init(void); + +struct tmgr_port * +tmgr_port_find(const char *name); + +struct tmgr_port_params { + uint32_t rate; + uint32_t n_subports_per_port; + uint32_t n_pipes_per_subport; + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t frame_overhead; + uint32_t mtu; + uint32_t cpu_id; +}; + +int +tmgr_subport_profile_add(struct rte_sched_subport_params *p); + +int +tmgr_pipe_profile_add(struct rte_sched_pipe_params *p); + +struct tmgr_port * +tmgr_port_create(const char *name, struct tmgr_port_params *params); + +int +tmgr_subport_config(const char *port_name, + uint32_t subport_id, + uint32_t subport_profile_id); + +int +tmgr_pipe_config(const char *port_name, + uint32_t subport_id, + uint32_t pipe_id_first, + uint32_t pipe_id_last, + uint32_t pipe_profile_id); + +#endif /* _INCLUDE_TMGR_H_ */ diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c index 350a9739..b830f67a 100644 --- a/examples/ip_reassembly/main.c +++ b/examples/ip_reassembly/main.c @@ -164,7 +164,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_JUMBO_FRAME | DEV_RX_OFFLOAD_CRC_STRIP), @@ -702,7 +701,7 @@ print_ethaddr(const char *name, const struct ether_addr *eth_addr) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -714,7 +713,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -1008,7 +1007,7 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid IP reassembly parameters\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No ports found!\n"); @@ -1023,7 +1022,7 @@ main(int argc, char **argv) rte_exit(EXIT_FAILURE, "Non-existent ports in portmask!\n"); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_rxconf rxq_conf; struct rte_eth_conf local_port_conf = port_conf; @@ -1083,6 +1082,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, 1, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) { @@ -1121,7 +1132,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, @@ -1141,7 +1151,7 @@ main(int argc, char **argv) printf("\n"); /* start ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } @@ -1157,7 +1167,7 @@ main(int argc, char **argv) if (init_routing_table() < 0) rte_exit(EXIT_FAILURE, "Cannot init routing table\n"); - check_all_ports_link_status(nb_ports, enabled_port_mask); + check_all_ports_link_status(enabled_port_mask); signal(SIGUSR1, signal_handler); signal(SIGTERM, signal_handler); diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c index 3a8562ee..b45b87bd 100644 --- a/examples/ipsec-secgw/ipsec-secgw.c +++ b/examples/ipsec-secgw/ipsec-secgw.c @@ -40,6 +40,7 @@ #include <rte_hash.h> #include <rte_jhash.h> #include <rte_cryptodev.h> +#include <rte_security.h> #include "ipsec.h" #include "parser.h" @@ -58,10 +59,6 @@ #define CDEV_MP_CACHE_SZ 64 #define MAX_QUEUE_PAIRS 1 -#define OPTION_CONFIG "config" -#define OPTION_SINGLE_SA "single-sa" -#define OPTION_CRYPTODEV_MASK "cryptodev_mask" - #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ #define NB_SOCKETS 4 @@ -124,6 +121,29 @@ struct ethaddr_info ethaddr_tbl[RTE_MAX_ETHPORTS] = { { 0, ETHADDR(0x00, 0x16, 0x3e, 0x49, 0x9e, 0xdd) } }; +#define CMD_LINE_OPT_CONFIG "config" +#define CMD_LINE_OPT_SINGLE_SA "single-sa" +#define CMD_LINE_OPT_CRYPTODEV_MASK "cryptodev_mask" + +enum { + /* long options mapped to a short option */ + + /* first long only option value must be >= 256, so that we won't + * conflict with short options + */ + CMD_LINE_OPT_MIN_NUM = 256, + CMD_LINE_OPT_CONFIG_NUM, + CMD_LINE_OPT_SINGLE_SA_NUM, + CMD_LINE_OPT_CRYPTODEV_MASK_NUM, +}; + +static const struct option lgopts[] = { + {CMD_LINE_OPT_CONFIG, 1, 0, CMD_LINE_OPT_CONFIG_NUM}, + {CMD_LINE_OPT_SINGLE_SA, 1, 0, CMD_LINE_OPT_SINGLE_SA_NUM}, + {CMD_LINE_OPT_CRYPTODEV_MASK, 1, 0, CMD_LINE_OPT_CRYPTODEV_MASK_NUM}, + {NULL, 0, 0, 0} +}; + /* mask of enabled ports */ static uint32_t enabled_port_mask; static uint64_t enabled_cryptodev_mask = UINT64_MAX; @@ -179,7 +199,6 @@ static struct rte_eth_conf port_conf = { .split_hdr_size = 0, .offloads = DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP, - .ignore_offload_bitfield = 1, }, .rx_adv_conf = { .rss_conf = { @@ -311,6 +330,7 @@ prepare_tx_pkt(struct rte_mbuf *pkt, uint16_t port) pkt->l3_len = sizeof(struct ip); pkt->l2_len = ETHER_HDR_LEN; + ip->ip_sum = 0; ethhdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); } else { pkt->ol_flags |= PKT_TX_IPV6; @@ -490,11 +510,13 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip, sa_idx = ip->res[i] & PROTECT_MASK; if (ip->res[i] & DISCARD) rte_pktmbuf_free(m); + else if (ip->res[i] & BYPASS) + ip->pkts[j++] = m; else if (sa_idx < IPSEC_SA_MAX_ENTRIES) { ipsec->res[ipsec->num] = sa_idx; ipsec->pkts[ipsec->num++] = m; - } else /* BYPASS */ - ip->pkts[j++] = m; + } else /* invalid SA idx */ + rte_pktmbuf_free(m); } ip->num = j; } @@ -848,7 +870,7 @@ static int32_t check_params(void) { uint8_t lcore; - uint16_t portid, nb_ports; + uint16_t portid; uint16_t i; int32_t socket_id; @@ -857,8 +879,6 @@ check_params(void) return -1; } - nb_ports = rte_eth_dev_count(); - for (i = 0; i < nb_lcore_params; ++i) { lcore = lcore_params[i].lcore_id; if (!rte_lcore_is_enabled(lcore)) { @@ -877,7 +897,7 @@ check_params(void) printf("port %u is not enabled in port mask\n", portid); return -1; } - if (portid >= nb_ports) { + if (!rte_eth_dev_is_valid_port(portid)) { printf("port %u is not present on the board\n", portid); return -1; } @@ -926,20 +946,28 @@ init_lcore_rx_queues(void) static void print_usage(const char *prgname) { - printf("%s [EAL options] -- -p PORTMASK -P -u PORTMASK" - " --"OPTION_CONFIG" (port,queue,lcore)[,(port,queue,lcore]" - " --single-sa SAIDX -f CONFIG_FILE\n" - " -p PORTMASK: hexadecimal bitmask of ports to configure\n" - " -P : enable promiscuous mode\n" - " -u PORTMASK: hexadecimal bitmask of unprotected ports\n" - " -j FRAMESIZE: jumbo frame maximum size\n" - " --"OPTION_CONFIG": (port,queue,lcore): " - "rx queues configuration\n" - " --single-sa SAIDX: use single SA index for outbound, " - "bypassing the SP\n" - " --cryptodev_mask MASK: hexadecimal bitmask of the " - "crypto devices to configure\n" - " -f CONFIG_FILE: Configuration file path\n", + fprintf(stderr, "%s [EAL options] --" + " -p PORTMASK" + " [-P]" + " [-u PORTMASK]" + " [-j FRAMESIZE]" + " -f CONFIG_FILE" + " --config (port,queue,lcore)[,(port,queue,lcore)]" + " [--single-sa SAIDX]" + " [--cryptodev_mask MASK]" + "\n\n" + " -p PORTMASK: Hexadecimal bitmask of ports to configure\n" + " -P : Enable promiscuous mode\n" + " -u PORTMASK: Hexadecimal bitmask of unprotected ports\n" + " -j FRAMESIZE: Enable jumbo frame with 'FRAMESIZE' as maximum\n" + " packet size\n" + " -f CONFIG_FILE: Configuration file\n" + " --config (port,queue,lcore): Rx queue configuration\n" + " --single-sa SAIDX: Use single SA index for outbound traffic,\n" + " bypassing the SP\n" + " --cryptodev_mask MASK: Hexadecimal bitmask of the crypto\n" + " devices to configure\n" + "\n", prgname); } @@ -1029,42 +1057,6 @@ parse_config(const char *q_arg) return 0; } -#define __STRNCMP(name, opt) (!strncmp(name, opt, sizeof(opt))) -static int32_t -parse_args_long_options(struct option *lgopts, int32_t option_index) -{ - int32_t ret = -1; - const char *optname = lgopts[option_index].name; - - if (__STRNCMP(optname, OPTION_CONFIG)) { - ret = parse_config(optarg); - if (ret) - printf("invalid config\n"); - } - - if (__STRNCMP(optname, OPTION_SINGLE_SA)) { - ret = parse_decimal(optarg); - if (ret != -1) { - single_sa = 1; - single_sa_idx = ret; - printf("Configured with single SA index %u\n", - single_sa_idx); - ret = 0; - } - } - - if (__STRNCMP(optname, OPTION_CRYPTODEV_MASK)) { - ret = parse_portmask(optarg); - if (ret != -1) { - enabled_cryptodev_mask = ret; - ret = 0; - } - } - - return ret; -} -#undef __STRNCMP - static int32_t parse_args(int32_t argc, char **argv) { @@ -1072,12 +1064,6 @@ parse_args(int32_t argc, char **argv) char **argvopt; int32_t option_index; char *prgname = argv[0]; - static struct option lgopts[] = { - {OPTION_CONFIG, 1, 0, 0}, - {OPTION_SINGLE_SA, 1, 0, 0}, - {OPTION_CRYPTODEV_MASK, 1, 0, 0}, - {NULL, 0, 0, 0} - }; int32_t f_present = 0; argvopt = argv; @@ -1138,11 +1124,38 @@ parse_args(int32_t argc, char **argv) } printf("Enabled jumbo frames size %u\n", frame_size); break; - case 0: - if (parse_args_long_options(lgopts, option_index)) { + case CMD_LINE_OPT_CONFIG_NUM: + ret = parse_config(optarg); + if (ret) { + printf("Invalid config\n"); + print_usage(prgname); + return -1; + } + break; + case CMD_LINE_OPT_SINGLE_SA_NUM: + ret = parse_decimal(optarg); + if (ret == -1) { + printf("Invalid argument[sa_idx]\n"); print_usage(prgname); return -1; } + + /* else */ + single_sa = 1; + single_sa_idx = ret; + printf("Configured with single SA index %u\n", + single_sa_idx); + break; + case CMD_LINE_OPT_CRYPTODEV_MASK_NUM: + ret = parse_portmask(optarg); + if (ret == -1) { + printf("Invalid argument[portmask]\n"); + print_usage(prgname); + return -1; + } + + /* else */ + enabled_cryptodev_mask = ret; break; default: print_usage(prgname); @@ -1173,7 +1186,7 @@ print_ethaddr(const char *name, const struct ether_addr *eth_addr) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -1185,7 +1198,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -1379,11 +1392,11 @@ cryptodevs_init(void) uint32_t max_sess_sz = 0, sess_sz; for (cdev_id = 0; cdev_id < rte_cryptodev_count(); cdev_id++) { - sess_sz = rte_cryptodev_get_private_session_size(cdev_id); + sess_sz = rte_cryptodev_sym_get_private_session_size(cdev_id); if (sess_sz > max_sess_sz) max_sess_sz = sess_sz; } - for (port_id = 0; port_id < rte_eth_dev_count(); port_id++) { + RTE_ETH_FOREACH_DEV(port_id) { void *sec_ctx; if ((enabled_port_mask & (1 << port_id)) == 0) @@ -1429,6 +1442,12 @@ cryptodevs_init(void) dev_conf.socket_id = rte_cryptodev_socket_id(cdev_id); dev_conf.nb_queue_pairs = qp; + uint32_t dev_max_sess = cdev_info.sym.max_nb_sessions; + if (dev_max_sess != 0 && dev_max_sess < (CDEV_MP_NB_OBJS / 2)) + rte_exit(EXIT_FAILURE, + "Device does not support at least %u " + "sessions", CDEV_MP_NB_OBJS / 2); + if (!socket_ctx[dev_conf.socket_id].session_pool) { char mp_name[RTE_MEMPOOL_NAMESIZE]; struct rte_mempool *sess_mp; @@ -1470,7 +1489,7 @@ cryptodevs_init(void) } /* create session pools for eth devices that implement security */ - for (port_id = 0; port_id < rte_eth_dev_count(); port_id++) { + RTE_ETH_FOREACH_DEV(port_id) { if ((enabled_port_mask & (1 << port_id)) && rte_eth_dev_get_sec_ctx(port_id)) { int socket_id = rte_eth_dev_socket_id(port_id); @@ -1555,6 +1574,18 @@ port_init(uint16_t portid) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, nb_tx_queue, &local_port_conf); if (ret < 0) @@ -1581,7 +1612,6 @@ port_init(uint16_t portid) printf("Setup txq=%u,%d,%d\n", lcore_id, tx_queueid, socket_id); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, tx_queueid, nb_txd, @@ -1640,13 +1670,68 @@ pool_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t nb_mbuf) printf("Allocated mbuf pool on socket %d\n", socket_id); } +static inline int +inline_ipsec_event_esn_overflow(struct rte_security_ctx *ctx, uint64_t md) +{ + struct ipsec_sa *sa; + + /* For inline protocol processing, the metadata in the event will + * uniquely identify the security session which raised the event. + * Application would then need the userdata it had registered with the + * security session to process the event. + */ + + sa = (struct ipsec_sa *)rte_security_get_userdata(ctx, md); + + if (sa == NULL) { + /* userdata could not be retrieved */ + return -1; + } + + /* Sequence number over flow. SA need to be re-established */ + RTE_SET_USED(sa); + return 0; +} + +static int +inline_ipsec_event_callback(uint16_t port_id, enum rte_eth_event_type type, + void *param, void *ret_param) +{ + uint64_t md; + struct rte_eth_event_ipsec_desc *event_desc = NULL; + struct rte_security_ctx *ctx = (struct rte_security_ctx *) + rte_eth_dev_get_sec_ctx(port_id); + + RTE_SET_USED(param); + + if (type != RTE_ETH_EVENT_IPSEC) + return -1; + + event_desc = ret_param; + if (event_desc == NULL) { + printf("Event descriptor not set\n"); + return -1; + } + + md = event_desc->metadata; + + if (event_desc->subtype == RTE_ETH_EVENT_IPSEC_ESN_OVERFLOW) + return inline_ipsec_event_esn_overflow(ctx, md); + else if (event_desc->subtype >= RTE_ETH_EVENT_IPSEC_MAX) { + printf("Invalid IPsec event reported\n"); + return -1; + } + + return -1; +} + int32_t main(int32_t argc, char **argv) { int32_t ret; uint32_t lcore_id; uint8_t socket_id; - uint16_t portid, nb_ports; + uint16_t portid; /* init EAL */ ret = rte_eal_init(argc, argv); @@ -1665,8 +1750,6 @@ main(int32_t argc, char **argv) rte_exit(EXIT_FAILURE, "Invalid unprotected portmask 0x%x\n", unprotected_port_mask); - nb_ports = rte_eth_dev_count(); - if (check_params() < 0) rte_exit(EXIT_FAILURE, "check_params failed\n"); @@ -1700,7 +1783,7 @@ main(int32_t argc, char **argv) pool_init(&socket_ctx[socket_id], socket_id, NB_MBUF); } - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) continue; @@ -1710,7 +1793,7 @@ main(int32_t argc, char **argv) cryptodevs_init(); /* start ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) continue; @@ -1727,9 +1810,12 @@ main(int32_t argc, char **argv) */ if (promiscuous_on) rte_eth_promiscuous_enable(portid); + + rte_eth_dev_callback_register(portid, + RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback, NULL); } - check_all_ports_link_status(nb_ports, enabled_port_mask); + check_all_ports_link_status(enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c index 5fb5bc16..3d415f1a 100644 --- a/examples/ipsec-secgw/ipsec.c +++ b/examples/ipsec-secgw/ipsec.c @@ -36,6 +36,7 @@ set_ipsec_conf(struct ipsec_sa *sa, struct rte_security_ipsec_xform *ipsec) } /* TODO support for Transport and IPV6 tunnel */ } + ipsec->esn_soft_limit = IPSEC_OFFLOAD_ESN_SOFTLIMIT; } static inline int @@ -186,14 +187,8 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa) .rss_key_len = 40, }; struct rte_eth_dev *eth_dev; - union { - struct rte_flow_action_rss rss; - struct { - const struct rte_eth_rss_conf *rss_conf; - uint16_t num; - uint16_t queue[RTE_MAX_QUEUES_PER_PORT]; - } local; - } action_rss; + uint16_t queue[RTE_MAX_QUEUES_PER_PORT]; + struct rte_flow_action_rss action_rss; unsigned int i; unsigned int j; @@ -207,9 +202,14 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa) for (i = 0, j = 0; i < eth_dev->data->nb_rx_queues; ++i) if (eth_dev->data->rx_queues[i]) - action_rss.local.queue[j++] = i; - action_rss.local.num = j; - action_rss.local.rss_conf = &rss_conf; + queue[j++] = i; + action_rss = (struct rte_flow_action_rss){ + .types = rss_conf.rss_hf, + .key_len = rss_conf.rss_key_len, + .queue_num = j, + .key = rss_key, + .queue = queue, + }; ret = rte_flow_validate(sa->portid, &sa->attr, sa->pattern, sa->action, &err); @@ -270,11 +270,14 @@ flow_create_failure: * the packet is received, this userdata will be * retrieved using the metadata from the packet. * - * This is required only for inbound SAs. + * The PMD is expected to set similar metadata for other + * operations, like rte_eth_event, which are tied to + * security session. In such cases, the userdata could + * be obtained to uniquely identify the security + * parameters denoted. */ - if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) - sess_conf.userdata = (void *) sa; + sess_conf.userdata = (void *) sa; sa->sec_session = rte_security_session_create(ctx, &sess_conf, ipsec_ctx->session_pool); @@ -324,18 +327,6 @@ flow_create_failure: rte_cryptodev_info_get(ipsec_ctx->tbl[cdev_id_qp].id, &cdev_info); - if (cdev_info.sym.max_nb_sessions_per_qp > 0) { - ret = rte_cryptodev_queue_pair_attach_sym_session( - ipsec_ctx->tbl[cdev_id_qp].id, - ipsec_ctx->tbl[cdev_id_qp].qp, - sa->crypto_session); - if (ret < 0) { - RTE_LOG(ERR, IPSEC, - "Session cannot be attached to qp %u\n", - ipsec_ctx->tbl[cdev_id_qp].qp); - return -1; - } - } } sa->cdev_id_qp = cdev_id_qp; @@ -345,13 +336,19 @@ flow_create_failure: static inline void enqueue_cop(struct cdev_qp *cqp, struct rte_crypto_op *cop) { - int32_t ret, i; + int32_t ret = 0, i; cqp->buf[cqp->len++] = cop; if (cqp->len == MAX_PKT_BURST) { - ret = rte_cryptodev_enqueue_burst(cqp->id, cqp->qp, - cqp->buf, cqp->len); + int enq_size = cqp->len; + if ((cqp->in_flight + enq_size) > MAX_INFLIGHT) + enq_size -= + (int)((cqp->in_flight + enq_size) - MAX_INFLIGHT); + + if (enq_size > 0) + ret = rte_cryptodev_enqueue_burst(cqp->id, cqp->qp, + cqp->buf, enq_size); if (ret < cqp->len) { RTE_LOG_DP(DEBUG, IPSEC, "Cryptodev %u queue %u:" " enqueued %u crypto ops out of %u\n", @@ -486,9 +483,12 @@ ipsec_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa; struct rte_mbuf *pkt; - for (i = 0; i < ipsec_ctx->nb_qps && nb_pkts < max_pkts;) { + for (i = 0; i < ipsec_ctx->nb_qps && nb_pkts < max_pkts; i++) { struct cdev_qp *cqp; - cqp = &ipsec_ctx->tbl[ipsec_ctx->last_qp]; + + cqp = &ipsec_ctx->tbl[ipsec_ctx->last_qp++]; + if (ipsec_ctx->last_qp == ipsec_ctx->nb_qps) + ipsec_ctx->last_qp %= ipsec_ctx->nb_qps; while (ipsec_ctx->ol_pkts_cnt > 0 && nb_pkts < max_pkts) { pkt = ipsec_ctx->ol_pkts[--ipsec_ctx->ol_pkts_cnt]; @@ -503,13 +503,8 @@ ipsec_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx, pkts[nb_pkts++] = pkt; } - if (cqp->in_flight == 0) { - ipsec_ctx->last_qp++; - if (ipsec_ctx->last_qp == ipsec_ctx->nb_qps) - ipsec_ctx->last_qp %= ipsec_ctx->nb_qps; - i++; + if (cqp->in_flight == 0) continue; - } nb_cops = rte_cryptodev_dequeue_burst(cqp->id, cqp->qp, cops, max_pkts - nb_pkts); @@ -533,12 +528,6 @@ ipsec_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx, } } pkts[nb_pkts++] = pkt; - if (cqp->in_flight < max_pkts) { - ipsec_ctx->last_qp++; - if (ipsec_ctx->last_qp == ipsec_ctx->nb_qps) - ipsec_ctx->last_qp %= ipsec_ctx->nb_qps; - i++; - } } } diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h index 6059f6cc..c998c807 100644 --- a/examples/ipsec-secgw/ipsec.h +++ b/examples/ipsec-secgw/ipsec.h @@ -17,10 +17,13 @@ #define RTE_LOGTYPE_IPSEC_IPIP RTE_LOGTYPE_USER3 #define MAX_PKT_BURST 32 +#define MAX_INFLIGHT 128 #define MAX_QP_PER_LCORE 256 #define MAX_DIGEST_SIZE 32 /* Bytes -- 256 bits */ +#define IPSEC_OFFLOAD_ESN_SOFTLIMIT 0xffffff00 + #define IV_OFFSET (sizeof(struct rte_crypto_op) + \ sizeof(struct rte_crypto_sym_op)) @@ -188,7 +191,7 @@ ipsec_metadata_size(void) static inline struct ipsec_mbuf_metadata * get_priv(struct rte_mbuf *m) { - return RTE_PTR_ADD(m, sizeof(struct rte_mbuf)); + return rte_mbuf_to_priv(m); } static inline void * diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c index 2403b564..91282ca9 100644 --- a/examples/ipsec-secgw/parser.c +++ b/examples/ipsec-secgw/parser.c @@ -3,6 +3,7 @@ */ #include <rte_common.h> #include <rte_crypto.h> +#include <rte_string_fns.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> @@ -207,23 +208,24 @@ inet_pton6(const char *src, unsigned char *dst) int parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask) { - char ip_str[256] = {0}; + char ip_str[INET_ADDRSTRLEN] = {0}; char *pch; pch = strchr(token, '/'); if (pch != NULL) { - strncpy(ip_str, token, pch - token); + strlcpy(ip_str, token, + RTE_MIN((unsigned int long)(pch - token + 1), + sizeof(ip_str))); pch += 1; if (is_str_num(pch) != 0) return -EINVAL; if (mask) *mask = atoi(pch); } else { - strncpy(ip_str, token, sizeof(ip_str) - 1); + strlcpy(ip_str, token, sizeof(ip_str)); if (mask) *mask = 0; } - if (strlen(ip_str) >= INET_ADDRSTRLEN) return -EINVAL; @@ -241,14 +243,16 @@ parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask) pch = strchr(token, '/'); if (pch != NULL) { - strncpy(ip_str, token, pch - token); + strlcpy(ip_str, token, + RTE_MIN((unsigned int long)(pch - token + 1), + sizeof(ip_str))); pch += 1; if (is_str_num(pch) != 0) return -EINVAL; if (mask) *mask = atoi(pch); } else { - strncpy(ip_str, token, sizeof(ip_str) - 1); + strlcpy(ip_str, token, sizeof(ip_str)); if (mask) *mask = 0; } @@ -515,9 +519,7 @@ parse_cfg_file(const char *cfg_filename) goto error_exit; } - strncpy(str + strlen(str), oneline, - strlen(oneline)); - + strcpy(str + strlen(str), oneline); continue; } @@ -528,8 +530,7 @@ parse_cfg_file(const char *cfg_filename) cfg_filename, line_num); goto error_exit; } - strncpy(str + strlen(str), oneline, - strlen(oneline)); + strcpy(str + strlen(str), oneline); str[strlen(str)] = '\n'; if (cmdline_parse(cl, str) < 0) { diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c index d9dcc0e0..4ab8e098 100644 --- a/examples/ipsec-secgw/sa.c +++ b/examples/ipsec-secgw/sa.c @@ -939,7 +939,7 @@ inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx) { struct ipsec_mbuf_metadata *priv; - priv = RTE_PTR_ADD(m, sizeof(struct rte_mbuf)); + priv = get_priv(m); return (sa_ctx->sa[sa_idx].spi == priv->sa->spi); } diff --git a/examples/ipv4_multicast/main.c b/examples/ipv4_multicast/main.c index c3bcf2c8..331c32e7 100644 --- a/examples/ipv4_multicast/main.c +++ b/examples/ipv4_multicast/main.c @@ -109,7 +109,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_JUMBO_FRAME | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -578,7 +577,7 @@ init_mcast_hash(void) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -590,7 +589,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -674,7 +673,7 @@ main(int argc, char **argv) if (clone_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init clone mbuf pool\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No physical ports!\n"); if (nb_ports > MAX_PORTS) @@ -683,7 +682,7 @@ main(int argc, char **argv) nb_lcores = rte_lcore_count(); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_rxconf rxq_conf; struct rte_eth_conf local_port_conf = port_conf; @@ -764,7 +763,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, rte_lcore_to_socket_id(lcore_id), txconf); @@ -786,7 +784,7 @@ main(int argc, char **argv) printf("done:\n"); } - check_all_ports_link_status(nb_ports, enabled_port_mask); + check_all_ports_link_status(enabled_port_mask); /* initialize the multicast hash */ int retval = init_mcast_hash(); diff --git a/examples/kni/Makefile b/examples/kni/Makefile index 562dc274..7e19d2e2 100644 --- a/examples/kni/Makefile +++ b/examples/kni/Makefile @@ -48,7 +48,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif diff --git a/examples/kni/main.c b/examples/kni/main.c index 0d9980ee..81336087 100644 --- a/examples/kni/main.c +++ b/examples/kni/main.c @@ -95,7 +95,6 @@ static struct kni_port_params *kni_port_params_array[RTE_MAX_ETHPORTS]; /* Options for configuring ethernet port */ static struct rte_eth_conf port_conf = { .rxmode = { - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -275,7 +274,7 @@ kni_egress(struct kni_port_params *p) static int main_loop(__rte_unused void *arg) { - uint8_t i, nb_ports = rte_eth_dev_count(); + uint16_t i; int32_t f_stop; const unsigned lcore_id = rte_lcore_id(); enum lcore_rxtx { @@ -286,7 +285,7 @@ main_loop(__rte_unused void *arg) }; enum lcore_rxtx flag = LCORE_NONE; - for (i = 0; i < nb_ports; i++) { + RTE_ETH_FOREACH_DEV(i) { if (!kni_port_params_array[i]) continue; if (kni_port_params_array[i]->lcore_rx == (uint8_t)lcore_id) { @@ -607,7 +606,6 @@ init_port(uint16_t port) "port%u (%d)\n", (unsigned)port, ret); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port, 0, nb_txd, rte_eth_dev_socket_id(port), &txq_conf); @@ -626,7 +624,7 @@ init_port(uint16_t port) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -638,7 +636,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -689,7 +687,7 @@ kni_change_mtu(uint16_t port_id, unsigned int new_mtu) struct rte_eth_dev_info dev_info; struct rte_eth_rxconf rxq_conf; - if (port_id >= rte_eth_dev_count()) { + if (!rte_eth_dev_is_valid_port(port_id)) { RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); return -EINVAL; } @@ -748,7 +746,7 @@ kni_config_network_interface(uint16_t port_id, uint8_t if_up) { int ret = 0; - if (port_id >= rte_eth_dev_count() || port_id >= RTE_MAX_ETHPORTS) { + if (!rte_eth_dev_is_valid_port(port_id)) { RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); return -EINVAL; } @@ -782,7 +780,7 @@ kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[]) { int ret = 0; - if (port_id >= rte_eth_dev_count() || port_id >= RTE_MAX_ETHPORTS) { + if (!rte_eth_dev_is_valid_port(port_id)) { RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); return -EINVAL; } @@ -834,13 +832,18 @@ kni_alloc(uint16_t port_id) if (i == 0) { struct rte_kni_ops ops; struct rte_eth_dev_info dev_info; + const struct rte_pci_device *pci_dev; + const struct rte_bus *bus = NULL; memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(port_id, &dev_info); - if (dev_info.pci_dev) { - conf.addr = dev_info.pci_dev->addr; - conf.id = dev_info.pci_dev->id; + if (dev_info.device) + bus = rte_bus_find_by_device(dev_info.device); + if (bus && !strcmp(bus->name, "pci")) { + pci_dev = RTE_DEV_TO_PCI(dev_info.device); + conf.addr = pci_dev->addr; + conf.id = pci_dev->id; } /* Get the interface default mac address */ rte_eth_macaddr_get(port_id, @@ -921,13 +924,13 @@ main(int argc, char** argv) } /* Get number of ports found in scan */ - nb_sys_ports = rte_eth_dev_count(); + nb_sys_ports = rte_eth_dev_count_avail(); if (nb_sys_ports == 0) rte_exit(EXIT_FAILURE, "No supported Ethernet device found\n"); /* Check if the configured port ID is valid */ for (i = 0; i < RTE_MAX_ETHPORTS; i++) - if (kni_port_params_array[i] && i >= nb_sys_ports) + if (kni_port_params_array[i] && !rte_eth_dev_is_valid_port(i)) rte_exit(EXIT_FAILURE, "Configured invalid " "port ID %u\n", i); @@ -935,7 +938,7 @@ main(int argc, char** argv) init_kni(); /* Initialise each port */ - for (port = 0; port < nb_sys_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { /* Skip ports that are not enabled */ if (!(ports_mask & (1 << port))) continue; @@ -947,7 +950,7 @@ main(int argc, char** argv) kni_alloc(port); } - check_all_ports_link_status(nb_sys_ports, ports_mask); + check_all_ports_link_status(ports_mask); /* Launch per-lcore function on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); @@ -957,7 +960,7 @@ main(int argc, char** argv) } /* Release resources */ - for (port = 0; port < nb_sys_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { if (!(ports_mask & (1 << port))) continue; kni_free_kni(port); diff --git a/examples/kni/meson.build b/examples/kni/meson.build index c39aead6..79131639 100644 --- a/examples/kni/meson.build +++ b/examples/kni/meson.build @@ -6,6 +6,8 @@ # To build this example as a standalone application with an already-installed # DPDK instance, use 'make' +# this app can be built if-and-only-if KNI library is buildable +build = dpdk_conf.has('RTE_LIBRTE_KNI') deps += ['kni', 'bus_pci'] sources = files( 'main.c' diff --git a/examples/l2fwd-cat/l2fwd-cat.c b/examples/l2fwd-cat/l2fwd-cat.c index 69339cca..0e6078aa 100644 --- a/examples/l2fwd-cat/l2fwd-cat.c +++ b/examples/l2fwd-cat/l2fwd-cat.c @@ -39,7 +39,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) uint16_t nb_rxd = RX_RING_SIZE; uint16_t nb_txd = TX_RING_SIZE; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; /* Configure the Ethernet device. */ @@ -95,14 +95,13 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) static __attribute__((noreturn)) void lcore_main(void) { - const uint16_t nb_ports = rte_eth_dev_count(); uint16_t port; /* * Check that the port is on the same NUMA node as the polling thread * for best performance. */ - for (port = 0; port < nb_ports; port++) + RTE_ETH_FOREACH_DEV(port) if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != (int)rte_socket_id()) @@ -119,7 +118,7 @@ lcore_main(void) * Receive packets on a port and forward them on the paired * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc. */ - for (port = 0; port < nb_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { /* Get burst of RX packets, from first port of pair. */ struct rte_mbuf *bufs[BURST_SIZE]; @@ -174,7 +173,7 @@ main(int argc, char *argv[]) argv += ret; /* Check that there is an even number of ports to send/receive on. */ - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports < 2 || (nb_ports & 1)) rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); @@ -186,7 +185,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* Initialize all ports. */ - for (portid = 0; portid < nb_ports; portid++) + RTE_ETH_FOREACH_DEV(portid) if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu16 "\n", portid); diff --git a/examples/l2fwd-cat/meson.build b/examples/l2fwd-cat/meson.build index b6deabc9..1234e7b5 100644 --- a/examples/l2fwd-cat/meson.build +++ b/examples/l2fwd-cat/meson.build @@ -6,7 +6,9 @@ # To build this example as a standalone application with an already-installed # DPDK instance, use 'make' -ext_deps += cc.find_library('pqos') +pqos = cc.find_library('pqos', required: false) +build = pqos.found() +ext_deps += pqos cflags += '-D_GNU_SOURCE' cflags += '-I/usr/local/include' # assume pqos lib installed in /usr/local sources = files( diff --git a/examples/l2fwd-crypto/Makefile b/examples/l2fwd-crypto/Makefile index a67f087b..6658fd0d 100644 --- a/examples/l2fwd-crypto/Makefile +++ b/examples/l2fwd-crypto/Makefile @@ -51,5 +51,11 @@ include $(RTE_SDK)/mk/rte.vars.mk CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) +ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) +ifeq ($(CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER),y) +LDLIBS += -lrte_pmd_crypto_scheduler +endif +endif + include $(RTE_SDK)/mk/rte.extapp.mk endif diff --git a/examples/l2fwd-crypto/main.c b/examples/l2fwd-crypto/main.c index 4d8341e2..6061b751 100644 --- a/examples/l2fwd-crypto/main.c +++ b/examples/l2fwd-crypto/main.c @@ -42,6 +42,9 @@ #include <rte_prefetch.h> #include <rte_random.h> #include <rte_hexdump.h> +#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER +#include <rte_cryptodev_scheduler.h> +#endif enum cdev_type { CDEV_TYPE_ANY, @@ -59,7 +62,6 @@ enum cdev_type { #define MAX_AAD_SIZE 65535 #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ -#define MAX_SESSIONS 32 #define SESSION_POOL_CACHE_SIZE 0 #define MAXIMUM_IV_LENGTH 16 @@ -211,7 +213,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -407,7 +408,7 @@ l2fwd_simple_crypto_enqueue(struct rte_mbuf *m, /* Zero pad data to be crypto'd so it is block aligned */ data_len = rte_pktmbuf_data_len(m) - ipdata_offset; - if (cparams->do_hash && cparams->hash_verify) + if ((cparams->do_hash || cparams->do_aead) && cparams->hash_verify) data_len -= cparams->digest_length; if (cparams->do_cipher) { @@ -1474,8 +1475,8 @@ l2fwd_crypto_default_options(struct l2fwd_crypto_options *options) options->aead_iv_random_size = -1; options->aead_iv.length = 0; - options->auth_xform.aead.algo = RTE_CRYPTO_AEAD_AES_GCM; - options->auth_xform.aead.op = RTE_CRYPTO_AEAD_OP_ENCRYPT; + options->aead_xform.aead.algo = RTE_CRYPTO_AEAD_AES_GCM; + options->aead_xform.aead.op = RTE_CRYPTO_AEAD_OP_ENCRYPT; options->aad_param = 0; options->aad_random_size = -1; @@ -1721,7 +1722,7 @@ l2fwd_crypto_parse_args(struct l2fwd_crypto_options *options, /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -1733,7 +1734,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -1930,21 +1931,19 @@ check_supported_size(uint16_t length, uint16_t min, uint16_t max, static int check_iv_param(const struct rte_crypto_param_range *iv_range_size, unsigned int iv_param, int iv_random_size, - uint16_t *iv_length) + uint16_t iv_length) { /* * Check if length of provided IV is supported * by the algorithm chosen. */ if (iv_param) { - if (check_supported_size(*iv_length, + if (check_supported_size(iv_length, iv_range_size->min, iv_range_size->max, iv_range_size->increment) - != 0) { - printf("Unsupported IV length\n"); + != 0) return -1; - } /* * Check if length of IV to be randomly generated * is supported by the algorithm chosen. @@ -1954,14 +1953,250 @@ check_iv_param(const struct rte_crypto_param_range *iv_range_size, iv_range_size->min, iv_range_size->max, iv_range_size->increment) - != 0) { - printf("Unsupported IV length\n"); + != 0) + return -1; + } + + return 0; +} + +static int +check_capabilities(struct l2fwd_crypto_options *options, uint8_t cdev_id) +{ + struct rte_cryptodev_info dev_info; + const struct rte_cryptodev_capabilities *cap; + + rte_cryptodev_info_get(cdev_id, &dev_info); + + /* Set AEAD parameters */ + if (options->xform_chain == L2FWD_CRYPTO_AEAD) { + /* Check if device supports AEAD algo */ + cap = check_device_support_aead_algo(options, &dev_info, + cdev_id); + if (cap == NULL) + return -1; + + if (check_iv_param(&cap->sym.aead.iv_size, + options->aead_iv_param, + options->aead_iv_random_size, + options->aead_iv.length) != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support IV length\n", + cdev_id); return -1; } - *iv_length = iv_random_size; - /* No size provided, use minimum size. */ - } else - *iv_length = iv_range_size->min; + + /* + * Check if length of provided AEAD key is supported + * by the algorithm chosen. + */ + if (options->aead_key_param) { + if (check_supported_size( + options->aead_xform.aead.key.length, + cap->sym.aead.key_size.min, + cap->sym.aead.key_size.max, + cap->sym.aead.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "AEAD key length\n", + cdev_id); + return -1; + } + /* + * Check if length of the aead key to be randomly generated + * is supported by the algorithm chosen. + */ + } else if (options->aead_key_random_size != -1) { + if (check_supported_size(options->aead_key_random_size, + cap->sym.aead.key_size.min, + cap->sym.aead.key_size.max, + cap->sym.aead.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "AEAD key length\n", + cdev_id); + return -1; + } + } + + + /* + * Check if length of provided AAD is supported + * by the algorithm chosen. + */ + if (options->aad_param) { + if (check_supported_size(options->aad.length, + cap->sym.aead.aad_size.min, + cap->sym.aead.aad_size.max, + cap->sym.aead.aad_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "AAD length\n", + cdev_id); + return -1; + } + /* + * Check if length of AAD to be randomly generated + * is supported by the algorithm chosen. + */ + } else if (options->aad_random_size != -1) { + if (check_supported_size(options->aad_random_size, + cap->sym.aead.aad_size.min, + cap->sym.aead.aad_size.max, + cap->sym.aead.aad_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "AAD length\n", + cdev_id); + return -1; + } + } + + /* Check if digest size is supported by the algorithm. */ + if (options->digest_size != -1) { + if (check_supported_size(options->digest_size, + cap->sym.aead.digest_size.min, + cap->sym.aead.digest_size.max, + cap->sym.aead.digest_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "digest length\n", + cdev_id); + return -1; + } + } + } + + /* Set cipher parameters */ + if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH || + options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER || + options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) { + /* Check if device supports cipher algo */ + cap = check_device_support_cipher_algo(options, &dev_info, + cdev_id); + if (cap == NULL) + return -1; + + if (check_iv_param(&cap->sym.cipher.iv_size, + options->cipher_iv_param, + options->cipher_iv_random_size, + options->cipher_iv.length) != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support IV length\n", + cdev_id); + return -1; + } + + /* + * Check if length of provided cipher key is supported + * by the algorithm chosen. + */ + if (options->ckey_param) { + if (check_supported_size( + options->cipher_xform.cipher.key.length, + cap->sym.cipher.key_size.min, + cap->sym.cipher.key_size.max, + cap->sym.cipher.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support cipher " + "key length\n", + cdev_id); + return -1; + } + /* + * Check if length of the cipher key to be randomly generated + * is supported by the algorithm chosen. + */ + } else if (options->ckey_random_size != -1) { + if (check_supported_size(options->ckey_random_size, + cap->sym.cipher.key_size.min, + cap->sym.cipher.key_size.max, + cap->sym.cipher.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support cipher " + "key length\n", + cdev_id); + return -1; + } + } + } + + /* Set auth parameters */ + if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH || + options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER || + options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) { + /* Check if device supports auth algo */ + cap = check_device_support_auth_algo(options, &dev_info, + cdev_id); + if (cap == NULL) + return -1; + + if (check_iv_param(&cap->sym.auth.iv_size, + options->auth_iv_param, + options->auth_iv_random_size, + options->auth_iv.length) != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support IV length\n", + cdev_id); + return -1; + } + /* + * Check if length of provided auth key is supported + * by the algorithm chosen. + */ + if (options->akey_param) { + if (check_supported_size( + options->auth_xform.auth.key.length, + cap->sym.auth.key_size.min, + cap->sym.auth.key_size.max, + cap->sym.auth.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support auth " + "key length\n", + cdev_id); + return -1; + } + /* + * Check if length of the auth key to be randomly generated + * is supported by the algorithm chosen. + */ + } else if (options->akey_random_size != -1) { + if (check_supported_size(options->akey_random_size, + cap->sym.auth.key_size.min, + cap->sym.auth.key_size.max, + cap->sym.auth.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support auth " + "key length\n", + cdev_id); + return -1; + } + } + + /* Check if digest size is supported by the algorithm. */ + if (options->digest_size != -1) { + if (check_supported_size(options->digest_size, + cap->sym.auth.digest_size.min, + cap->sym.auth.digest_size.max, + cap->sym.auth.digest_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "digest length\n", + cdev_id); + return -1; + } + } + } return 0; } @@ -1970,9 +2205,10 @@ static int initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, uint8_t *enabled_cdevs) { - unsigned int cdev_id, cdev_count, enabled_cdev_count = 0; + uint8_t cdev_id, cdev_count, enabled_cdev_count = 0; const struct rte_cryptodev_capabilities *cap; unsigned int sess_sz, max_sess_sz = 0; + uint32_t sessions_needed = 0; int retval; cdev_count = rte_cryptodev_count(); @@ -1981,16 +2217,31 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, return -1; } - for (cdev_id = 0; cdev_id < cdev_count; cdev_id++) { - sess_sz = rte_cryptodev_get_private_session_size(cdev_id); + for (cdev_id = 0; cdev_id < cdev_count && enabled_cdev_count < nb_ports; + cdev_id++) { + if (check_cryptodev_mask(options, cdev_id) < 0) + continue; + + if (check_capabilities(options, cdev_id) < 0) + continue; + + sess_sz = rte_cryptodev_sym_get_private_session_size(cdev_id); if (sess_sz > max_sess_sz) max_sess_sz = sess_sz; + + l2fwd_enabled_crypto_mask |= (((uint64_t)1) << cdev_id); + + enabled_cdevs[cdev_id] = 1; + enabled_cdev_count++; } - for (cdev_id = 0; cdev_id < cdev_count && enabled_cdev_count < nb_ports; - cdev_id++) { + for (cdev_id = 0; cdev_id < cdev_count; cdev_id++) { struct rte_cryptodev_qp_conf qp_conf; struct rte_cryptodev_info dev_info; + + if (enabled_cdevs[cdev_id] == 0) + continue; + retval = rte_cryptodev_socket_id(cdev_id); if (retval < 0) { @@ -2005,11 +2256,23 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, .socket_id = socket_id, }; - if (check_cryptodev_mask(options, (uint8_t)cdev_id)) - continue; - rte_cryptodev_info_get(cdev_id, &dev_info); + /* + * Two sessions objects are required for each session + * (one for the header, one for the private data) + */ + if (!strcmp(dev_info.driver_name, "crypto_scheduler")) { +#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER + uint32_t nb_slaves = + rte_cryptodev_scheduler_slaves_get(cdev_id, + NULL); + + sessions_needed = 2 * enabled_cdev_count * nb_slaves; +#endif + } else + sessions_needed = 2 * enabled_cdev_count; + if (session_pool_socket[socket_id] == NULL) { char mp_name[RTE_MEMPOOL_NAMESIZE]; struct rte_mempool *sess_mp; @@ -2022,7 +2285,7 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, * device private data */ sess_mp = rte_mempool_create(mp_name, - MAX_SESSIONS * 2, + sessions_needed, max_sess_sz, SESSION_POOL_CACHE_SIZE, 0, NULL, NULL, NULL, @@ -2041,106 +2304,57 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, /* Set AEAD parameters */ if (options->xform_chain == L2FWD_CRYPTO_AEAD) { - /* Check if device supports AEAD algo */ cap = check_device_support_aead_algo(options, &dev_info, cdev_id); - if (cap == NULL) - continue; options->block_size = cap->sym.aead.block_size; - check_iv_param(&cap->sym.aead.iv_size, - options->aead_iv_param, - options->aead_iv_random_size, - &options->aead_iv.length); + /* Set IV if not provided from command line */ + if (options->aead_iv_param == 0) { + if (options->aead_iv_random_size != -1) + options->aead_iv.length = + options->aead_iv_random_size; + /* No size provided, use minimum size. */ + else + options->aead_iv.length = + cap->sym.aead.iv_size.min; + } - /* - * Check if length of provided AEAD key is supported - * by the algorithm chosen. - */ - if (options->aead_key_param) { - if (check_supported_size( - options->aead_xform.aead.key.length, - cap->sym.aead.key_size.min, - cap->sym.aead.key_size.max, - cap->sym.aead.key_size.increment) - != 0) { - printf("Unsupported aead key length\n"); - return -1; - } - /* - * Check if length of the aead key to be randomly generated - * is supported by the algorithm chosen. - */ - } else if (options->aead_key_random_size != -1) { - if (check_supported_size(options->aead_key_random_size, - cap->sym.aead.key_size.min, - cap->sym.aead.key_size.max, - cap->sym.aead.key_size.increment) - != 0) { - printf("Unsupported aead key length\n"); - return -1; - } - options->aead_xform.aead.key.length = - options->aead_key_random_size; - /* No size provided, use minimum size. */ - } else - options->aead_xform.aead.key.length = + /* Set key if not provided from command line */ + if (options->aead_key_param == 0) { + if (options->aead_key_random_size != -1) + options->aead_xform.aead.key.length = + options->aead_key_random_size; + /* No size provided, use minimum size. */ + else + options->aead_xform.aead.key.length = cap->sym.aead.key_size.min; - if (!options->aead_key_param) generate_random_key( options->aead_xform.aead.key.data, options->aead_xform.aead.key.length); + } - /* - * Check if length of provided AAD is supported - * by the algorithm chosen. - */ - if (options->aad_param) { - if (check_supported_size(options->aad.length, - cap->sym.aead.aad_size.min, - cap->sym.aead.aad_size.max, - cap->sym.aead.aad_size.increment) - != 0) { - printf("Unsupported AAD length\n"); - return -1; - } - /* - * Check if length of AAD to be randomly generated - * is supported by the algorithm chosen. - */ - } else if (options->aad_random_size != -1) { - if (check_supported_size(options->aad_random_size, - cap->sym.aead.aad_size.min, - cap->sym.aead.aad_size.max, - cap->sym.aead.aad_size.increment) - != 0) { - printf("Unsupported AAD length\n"); - return -1; - } - options->aad.length = options->aad_random_size; - /* No size provided, use minimum size. */ - } else - options->aad.length = cap->sym.auth.aad_size.min; + /* Set AAD if not provided from command line */ + if (options->aad_param == 0) { + if (options->aad_random_size != -1) + options->aad.length = + options->aad_random_size; + /* No size provided, use minimum size. */ + else + options->aad.length = + cap->sym.auth.aad_size.min; + } options->aead_xform.aead.aad_length = options->aad.length; - /* Check if digest size is supported by the algorithm. */ - if (options->digest_size != -1) { - if (check_supported_size(options->digest_size, - cap->sym.aead.digest_size.min, - cap->sym.aead.digest_size.max, - cap->sym.aead.digest_size.increment) - != 0) { - printf("Unsupported digest length\n"); - return -1; - } + /* Set digest size if not provided from command line */ + if (options->digest_size != -1) options->aead_xform.aead.digest_length = options->digest_size; - /* No size provided, use minimum size. */ - } else + /* No size provided, use minimum size. */ + else options->aead_xform.aead.digest_length = cap->sym.aead.digest_size.min; } @@ -2149,127 +2363,76 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH || options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER || options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) { - /* Check if device supports cipher algo */ cap = check_device_support_cipher_algo(options, &dev_info, cdev_id); - if (cap == NULL) - continue; - options->block_size = cap->sym.cipher.block_size; - check_iv_param(&cap->sym.cipher.iv_size, - options->cipher_iv_param, - options->cipher_iv_random_size, - &options->cipher_iv.length); + /* Set IV if not provided from command line */ + if (options->cipher_iv_param == 0) { + if (options->cipher_iv_random_size != -1) + options->cipher_iv.length = + options->cipher_iv_random_size; + /* No size provided, use minimum size. */ + else + options->cipher_iv.length = + cap->sym.cipher.iv_size.min; + } - /* - * Check if length of provided cipher key is supported - * by the algorithm chosen. - */ - if (options->ckey_param) { - if (check_supported_size( - options->cipher_xform.cipher.key.length, - cap->sym.cipher.key_size.min, - cap->sym.cipher.key_size.max, - cap->sym.cipher.key_size.increment) - != 0) { - printf("Unsupported cipher key length\n"); - return -1; - } - /* - * Check if length of the cipher key to be randomly generated - * is supported by the algorithm chosen. - */ - } else if (options->ckey_random_size != -1) { - if (check_supported_size(options->ckey_random_size, - cap->sym.cipher.key_size.min, - cap->sym.cipher.key_size.max, - cap->sym.cipher.key_size.increment) - != 0) { - printf("Unsupported cipher key length\n"); - return -1; - } - options->cipher_xform.cipher.key.length = - options->ckey_random_size; - /* No size provided, use minimum size. */ - } else - options->cipher_xform.cipher.key.length = + /* Set key if not provided from command line */ + if (options->ckey_param == 0) { + if (options->ckey_random_size != -1) + options->cipher_xform.cipher.key.length = + options->ckey_random_size; + /* No size provided, use minimum size. */ + else + options->cipher_xform.cipher.key.length = cap->sym.cipher.key_size.min; - if (!options->ckey_param) generate_random_key( options->cipher_xform.cipher.key.data, options->cipher_xform.cipher.key.length); - + } } /* Set auth parameters */ if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH || options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER || options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) { - /* Check if device supports auth algo */ cap = check_device_support_auth_algo(options, &dev_info, cdev_id); - if (cap == NULL) - continue; - check_iv_param(&cap->sym.auth.iv_size, - options->auth_iv_param, - options->auth_iv_random_size, - &options->auth_iv.length); - /* - * Check if length of provided auth key is supported - * by the algorithm chosen. - */ - if (options->akey_param) { - if (check_supported_size( - options->auth_xform.auth.key.length, - cap->sym.auth.key_size.min, - cap->sym.auth.key_size.max, - cap->sym.auth.key_size.increment) - != 0) { - printf("Unsupported auth key length\n"); - return -1; - } - /* - * Check if length of the auth key to be randomly generated - * is supported by the algorithm chosen. - */ - } else if (options->akey_random_size != -1) { - if (check_supported_size(options->akey_random_size, - cap->sym.auth.key_size.min, - cap->sym.auth.key_size.max, - cap->sym.auth.key_size.increment) - != 0) { - printf("Unsupported auth key length\n"); - return -1; - } - options->auth_xform.auth.key.length = - options->akey_random_size; - /* No size provided, use minimum size. */ - } else - options->auth_xform.auth.key.length = + /* Set IV if not provided from command line */ + if (options->auth_iv_param == 0) { + if (options->auth_iv_random_size != -1) + options->auth_iv.length = + options->auth_iv_random_size; + /* No size provided, use minimum size. */ + else + options->auth_iv.length = + cap->sym.auth.iv_size.min; + } + + /* Set key if not provided from command line */ + if (options->akey_param == 0) { + if (options->akey_random_size != -1) + options->auth_xform.auth.key.length = + options->akey_random_size; + /* No size provided, use minimum size. */ + else + options->auth_xform.auth.key.length = cap->sym.auth.key_size.min; - if (!options->akey_param) generate_random_key( options->auth_xform.auth.key.data, options->auth_xform.auth.key.length); + } - /* Check if digest size is supported by the algorithm. */ - if (options->digest_size != -1) { - if (check_supported_size(options->digest_size, - cap->sym.auth.digest_size.min, - cap->sym.auth.digest_size.max, - cap->sym.auth.digest_size.increment) - != 0) { - printf("Unsupported digest length\n"); - return -1; - } + /* Set digest size if not provided from command line */ + if (options->digest_size != -1) options->auth_xform.auth.digest_length = options->digest_size; - /* No size provided, use minimum size. */ - } else + /* No size provided, use minimum size. */ + else options->auth_xform.auth.digest_length = cap->sym.auth.digest_size.min; } @@ -2296,11 +2459,6 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, cdev_id, retval); return -1; } - - l2fwd_enabled_crypto_mask |= (((uint64_t)1) << cdev_id); - - enabled_cdevs[cdev_id] = 1; - enabled_cdev_count++; } return enabled_cdev_count; @@ -2309,9 +2467,9 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, static int initialize_ports(struct l2fwd_crypto_options *options) { - uint16_t last_portid, portid; + uint16_t last_portid = 0, portid; unsigned enabled_portcount = 0; - unsigned nb_ports = rte_eth_dev_count(); + unsigned nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) { printf("No Ethernet ports - bye\n"); @@ -2322,7 +2480,7 @@ initialize_ports(struct l2fwd_crypto_options *options) for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) l2fwd_dst_ports[portid] = 0; - for (last_portid = 0, portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { int retval; struct rte_eth_dev_info dev_info; struct rte_eth_rxconf rxq_conf; @@ -2371,7 +2529,6 @@ initialize_ports(struct l2fwd_crypto_options *options) /* init one TX queue on each port */ fflush(stdout); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; retval = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), @@ -2426,7 +2583,7 @@ initialize_ports(struct l2fwd_crypto_options *options) return -1; } - check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); + check_all_ports_link_status(l2fwd_enabled_port_mask); return enabled_portcount; } @@ -2470,12 +2627,12 @@ reserve_key_memory(struct l2fwd_crypto_options *options) int main(int argc, char **argv) { - struct lcore_queue_conf *qconf; + struct lcore_queue_conf *qconf = NULL; struct l2fwd_crypto_options options; uint8_t nb_cryptodevs, cdev_id; - uint16_t nb_ports, portid; - unsigned lcore_id, rx_lcore_id; + uint16_t portid; + unsigned lcore_id, rx_lcore_id = 0; int ret, enabled_cdevcount, enabled_portcount; uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = {0}; @@ -2516,10 +2673,8 @@ main(int argc, char **argv) if (enabled_portcount < 1) rte_exit(EXIT_FAILURE, "Failed to initial Ethernet ports\n"); - nb_ports = rte_eth_dev_count(); /* Initialize the port/queue configuration of each logical core */ - for (rx_lcore_id = 0, qconf = NULL, portid = 0; - portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((options.portmask & (1 << portid)) == 0) diff --git a/examples/l2fwd-jobstats/main.c b/examples/l2fwd-jobstats/main.c index 2554f448..af542338 100644 --- a/examples/l2fwd-jobstats/main.c +++ b/examples/l2fwd-jobstats/main.c @@ -90,7 +90,6 @@ struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -680,7 +679,7 @@ l2fwd_parse_args(int argc, char **argv) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -692,7 +691,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -742,7 +741,7 @@ main(int argc, char **argv) int ret; char name[RTE_JOBSTATS_NAMESIZE]; uint16_t nb_ports; - uint16_t nb_ports_available; + uint16_t nb_ports_available = 0; uint16_t portid, last_port; uint8_t i; @@ -770,7 +769,7 @@ main(int argc, char **argv) if (l2fwd_pktmbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); @@ -782,7 +781,7 @@ main(int argc, char **argv) /* * Each logical core is assigned a dedicated TX queue on each port. */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; @@ -804,7 +803,7 @@ main(int argc, char **argv) qconf = NULL; /* Initialize the port/queue configuration of each logical core */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; @@ -827,10 +826,8 @@ main(int argc, char **argv) printf("Lcore %u: RX port %u\n", rx_lcore_id, portid); } - nb_ports_available = nb_ports; - /* Initialise each port */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_dev_info dev_info; struct rte_eth_rxconf rxq_conf; struct rte_eth_txconf txq_conf; @@ -839,9 +836,10 @@ main(int argc, char **argv) /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %u\n", portid); - nb_ports_available--; continue; } + nb_ports_available++; + /* init port */ printf("Initializing port %u... ", portid); fflush(stdout); @@ -877,7 +875,6 @@ main(int argc, char **argv) /* init one TX queue on each port */ txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, @@ -934,7 +931,7 @@ main(int argc, char **argv) "All available ports are disabled. Please set portmask.\n"); } - check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); + check_all_ports_link_status(l2fwd_enabled_port_mask); drain_tsc = (hz + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; diff --git a/examples/l2fwd-keepalive/main.c b/examples/l2fwd-keepalive/main.c index 39b8c328..2d8b4d1c 100644 --- a/examples/l2fwd-keepalive/main.c +++ b/examples/l2fwd-keepalive/main.c @@ -81,7 +81,6 @@ struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -445,7 +444,7 @@ l2fwd_parse_args(int argc, char **argv) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -457,7 +456,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -526,7 +525,7 @@ main(int argc, char **argv) struct lcore_queue_conf *qconf; int ret; uint16_t nb_ports; - uint16_t nb_ports_available; + uint16_t nb_ports_available = 0; uint16_t portid, last_port; unsigned lcore_id, rx_lcore_id; unsigned nb_ports_in_mask = 0; @@ -561,7 +560,7 @@ main(int argc, char **argv) if (l2fwd_pktmbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); @@ -573,7 +572,7 @@ main(int argc, char **argv) /* * Each logical core is assigned a dedicated TX queue on each port. */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; @@ -595,7 +594,7 @@ main(int argc, char **argv) qconf = NULL; /* Initialize the port/queue configuration of each logical core */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; @@ -619,10 +618,8 @@ main(int argc, char **argv) rx_lcore_id, portid); } - nb_ports_available = nb_ports; - /* Initialise each port */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_dev_info dev_info; struct rte_eth_rxconf rxq_conf; struct rte_eth_txconf txq_conf; @@ -631,9 +628,10 @@ main(int argc, char **argv) /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %u\n", portid); - nb_ports_available--; continue; } + nb_ports_available++; + /* init port */ printf("Initializing port %u... ", portid); fflush(stdout); @@ -672,7 +670,6 @@ main(int argc, char **argv) /* init one TX queue on each port */ fflush(stdout); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), @@ -728,7 +725,7 @@ main(int argc, char **argv) "All available ports are disabled. Please set portmask.\n"); } - check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); + check_all_ports_link_status(l2fwd_enabled_port_mask); struct rte_timer hb_timer, stats_timer; diff --git a/examples/l2fwd/main.c b/examples/l2fwd/main.c index e4a4a7c3..9bb4c5bc 100644 --- a/examples/l2fwd/main.c +++ b/examples/l2fwd/main.c @@ -82,7 +82,6 @@ static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -444,7 +443,7 @@ l2fwd_parse_args(int argc, char **argv) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -458,7 +457,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) if (force_quit) return; all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if (force_quit) return; if ((port_mask & (1 << portid)) == 0) @@ -517,7 +516,7 @@ main(int argc, char **argv) struct lcore_queue_conf *qconf; int ret; uint16_t nb_ports; - uint16_t nb_ports_available; + uint16_t nb_ports_available = 0; uint16_t portid, last_port; unsigned lcore_id, rx_lcore_id; unsigned nb_ports_in_mask = 0; @@ -545,7 +544,7 @@ main(int argc, char **argv) /* convert to number of cycles */ timer_period *= rte_get_timer_hz(); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); @@ -562,7 +561,7 @@ main(int argc, char **argv) /* * Each logical core is assigned a dedicated TX queue on each port. */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; @@ -585,7 +584,7 @@ main(int argc, char **argv) qconf = NULL; /* Initialize the port/queue configuration of each logical core */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; @@ -610,8 +609,6 @@ main(int argc, char **argv) printf("Lcore %u: RX port %u\n", rx_lcore_id, portid); } - nb_ports_available = nb_ports; - nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST + nb_lcores * MEMPOOL_CACHE_SIZE), 8192U); @@ -623,7 +620,7 @@ main(int argc, char **argv) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); /* Initialise each port */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_rxconf rxq_conf; struct rte_eth_txconf txq_conf; struct rte_eth_conf local_port_conf = port_conf; @@ -632,9 +629,10 @@ main(int argc, char **argv) /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %u\n", portid); - nb_ports_available--; continue; } + nb_ports_available++; + /* init port */ printf("Initializing port %u... ", portid); fflush(stdout); @@ -671,7 +669,6 @@ main(int argc, char **argv) /* init one TX queue on each port */ fflush(stdout); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), @@ -726,7 +723,7 @@ main(int argc, char **argv) "All available ports are disabled. Please set portmask.\n"); } - check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); + check_all_ports_link_status(l2fwd_enabled_port_mask); ret = 0; /* launch per-lcore init on every lcore */ @@ -738,7 +735,7 @@ main(int argc, char **argv) } } - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; printf("Closing port %d...", portid); diff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c index 9aebb331..7c063a8d 100644 --- a/examples/l3fwd-acl/main.c +++ b/examples/l3fwd-acl/main.c @@ -127,7 +127,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CRC_STRIP | DEV_RX_OFFLOAD_CHECKSUM), }, @@ -1452,7 +1451,7 @@ check_lcore_params(void) } static int -check_port_config(const unsigned nb_ports) +check_port_config(void) { unsigned portid; uint16_t i; @@ -1464,7 +1463,7 @@ check_port_config(const unsigned nb_ports) printf("port %u is not enabled in port mask\n", portid); return -1; } - if (portid >= nb_ports) { + if (!rte_eth_dev_is_valid_port(portid)) { printf("port %u is not present on the board\n", portid); return -1; } @@ -1805,7 +1804,7 @@ init_mem(unsigned nb_mbuf) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -1817,7 +1816,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -1891,9 +1890,9 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); - if (check_port_config(nb_ports) < 0) + if (check_port_config() < 0) rte_exit(EXIT_FAILURE, "check_port_config failed\n"); /* Add ACL rules and route entries, build trie */ @@ -1903,7 +1902,7 @@ main(int argc, char **argv) nb_lcores = rte_lcore_count(); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_conf local_port_conf = port_conf; /* skip ports that are not enabled */ @@ -1926,6 +1925,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) @@ -1982,7 +1993,6 @@ main(int argc, char **argv) rte_eth_dev_info_get(portid, &dev_info); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); @@ -2043,7 +2053,7 @@ main(int argc, char **argv) printf("\n"); /* start ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) continue; @@ -2064,7 +2074,7 @@ main(int argc, char **argv) rte_eth_promiscuous_enable(portid); } - check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask); + check_all_ports_link_status(enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); diff --git a/examples/l3fwd-power/Makefile b/examples/l3fwd-power/Makefile index 390b7d6b..d7e39a34 100644 --- a/examples/l3fwd-power/Makefile +++ b/examples/l3fwd-power/Makefile @@ -1,11 +1,11 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation +# Copyright(c) 2010-2018 Intel Corporation # binary name APP = l3fwd-power # all source are stored in SRCS-y -SRCS-y := main.c +SRCS-y := main.c perf_core.c # Build using pkg-config variables if possible $(shell pkg-config --exists libdpdk) @@ -48,7 +48,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +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: diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c index b2a7c79e..d15cd520 100644 --- a/examples/l3fwd-power/main.c +++ b/examples/l3fwd-power/main.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation + * Copyright(c) 2010-2018 Intel Corporation */ #include <stdio.h> @@ -44,6 +44,9 @@ #include <rte_power.h> #include <rte_spinlock.h> +#include "perf_core.h" +#include "main.h" + #define RTE_LOGTYPE_L3FWD_POWER RTE_LOGTYPE_USER1 #define MAX_PKT_BURST 32 @@ -155,14 +158,7 @@ struct lcore_rx_queue { #define MAX_RX_QUEUE_INTERRUPT_PER_PORT 16 -#define MAX_LCORE_PARAMS 1024 -struct lcore_params { - uint16_t port_id; - uint8_t queue_id; - uint8_t lcore_id; -} __rte_cache_aligned; - -static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; +struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; static struct lcore_params lcore_params_array_default[] = { {0, 0, 2}, {0, 1, 2}, @@ -175,8 +171,8 @@ static struct lcore_params lcore_params_array_default[] = { {3, 1, 3}, }; -static struct lcore_params * lcore_params = lcore_params_array_default; -static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / +struct lcore_params *lcore_params = lcore_params_array_default; +uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / sizeof(lcore_params_array_default[0]); static struct rte_eth_conf port_conf = { @@ -184,7 +180,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CRC_STRIP | DEV_RX_OFFLOAD_CHECKSUM), }, @@ -341,7 +336,7 @@ static void signal_exit_now(int sigtype) { unsigned lcore_id; - unsigned int portid, nb_ports; + unsigned int portid; int ret; if (sigtype == SIGINT) { @@ -357,8 +352,7 @@ signal_exit_now(int sigtype) "core%u\n", lcore_id); } - nb_ports = rte_eth_dev_count(); - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) continue; @@ -1057,7 +1051,7 @@ check_lcore_params(void) } static int -check_port_config(const unsigned nb_ports) +check_port_config(void) { unsigned portid; uint16_t i; @@ -1069,7 +1063,7 @@ check_port_config(const unsigned nb_ports) portid); return -1; } - if (portid >= nb_ports) { + if (!rte_eth_dev_is_valid_port(portid)) { printf("port %u is not present on the board\n", portid); return -1; @@ -1122,10 +1116,15 @@ print_usage(const char *prgname) { printf ("%s [EAL options] -- -p PORTMASK -P" " [--config (port,queue,lcore)[,(port,queue,lcore]]" + " [--high-perf-cores CORELIST" + " [--perf-config (port,queue,hi_perf,lcore_index)[,(port,queue,hi_perf,lcore_index]]" " [--enable-jumbo [--max-pkt-len PKTLEN]]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -P : enable promiscuous mode\n" " --config (port,queue,lcore): rx queues configuration\n" + " --high-perf-cores CORELIST: list of high performance cores\n" + " --perf-config: similar as config, cores specified as indices" + " for bins containing high or regular performance cores\n" " --no-numa: optional, disable numa awareness\n" " --enable-jumbo: enable jumbo frame" " which max packet len is PKTLEN in decimal (64-9600)\n" @@ -1235,6 +1234,8 @@ parse_args(int argc, char **argv) char *prgname = argv[0]; static struct option lgopts[] = { {"config", 1, 0, 0}, + {"perf-config", 1, 0, 0}, + {"high-perf-cores", 1, 0, 0}, {"no-numa", 0, 0, 0}, {"enable-jumbo", 0, 0, 0}, {CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0}, @@ -1273,6 +1274,26 @@ parse_args(int argc, char **argv) } if (!strncmp(lgopts[option_index].name, + "perf-config", 11)) { + ret = parse_perf_config(optarg); + if (ret) { + printf("invalid perf-config\n"); + print_usage(prgname); + return -1; + } + } + + if (!strncmp(lgopts[option_index].name, + "high-perf-cores", 15)) { + ret = parse_perf_core_list(optarg); + if (ret) { + printf("invalid high-perf-cores\n"); + print_usage(prgname); + return -1; + } + } + + if (!strncmp(lgopts[option_index].name, "no-numa", 7)) { printf("numa is disabled \n"); numa_on = 0; @@ -1512,7 +1533,7 @@ init_mem(unsigned nb_mbuf) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -1524,7 +1545,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -1610,6 +1631,23 @@ static int check_ptype(uint16_t portid) } +static int +init_power_library(void) +{ + int ret = 0, lcore_id; + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (rte_lcore_is_enabled(lcore_id)) { + /* init power management library */ + ret = rte_power_init(lcore_id); + if (ret) + RTE_LOG(ERR, POWER, + "Library initialization failed on core %u\n", + lcore_id); + } + } + return ret; +} + int main(int argc, char **argv) { @@ -1644,6 +1682,12 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); + if (init_power_library()) + rte_exit(EXIT_FAILURE, "init_power_library failed\n"); + + if (update_lcore_params() < 0) + rte_exit(EXIT_FAILURE, "update_lcore_params failed\n"); + if (check_lcore_params() < 0) rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); @@ -1651,15 +1695,15 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); - if (check_port_config(nb_ports) < 0) + if (check_port_config() < 0) rte_exit(EXIT_FAILURE, "check_port_config failed\n"); nb_lcores = rte_lcore_count(); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_conf local_port_conf = port_conf; /* skip ports that are not enabled */ @@ -1694,6 +1738,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) @@ -1751,7 +1807,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); @@ -1774,12 +1829,6 @@ main(int argc, char **argv) if (rte_lcore_is_enabled(lcore_id) == 0) continue; - /* init power management library */ - ret = rte_power_init(lcore_id); - if (ret) - RTE_LOG(ERR, POWER, - "Library initialization failed on core %u\n", lcore_id); - /* init timer structures for each enabled lcore */ rte_timer_init(&power_timers[lcore_id]); hz = rte_get_timer_hz(); @@ -1834,7 +1883,7 @@ main(int argc, char **argv) printf("\n"); /* start ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } @@ -1855,7 +1904,7 @@ main(int argc, char **argv) rte_spinlock_init(&(locks[portid])); } - check_all_ports_link_status(nb_ports, enabled_port_mask); + check_all_ports_link_status(enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); diff --git a/examples/l3fwd-power/main.h b/examples/l3fwd-power/main.h new file mode 100644 index 00000000..258de98f --- /dev/null +++ b/examples/l3fwd-power/main.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _MAIN_H_ +#define _MAIN_H_ + + +#define MAX_LCORE_PARAMS 1024 +struct lcore_params { + uint16_t port_id; + uint8_t queue_id; + uint8_t lcore_id; +} __rte_cache_aligned; + +extern struct lcore_params *lcore_params; +extern uint16_t nb_lcore_params; +extern struct lcore_params lcore_params_array[]; + +#endif /* _MAIN_H_ */ diff --git a/examples/l3fwd-power/meson.build b/examples/l3fwd-power/meson.build index 61e8daa9..20c80543 100644 --- a/examples/l3fwd-power/meson.build +++ b/examples/l3fwd-power/meson.build @@ -1,12 +1,15 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2017 Intel Corporation +# Copyright(c) 2018 Intel Corporation # meson file, for building this example as part of a main DPDK build. # # To build this example as a standalone application with an already-installed # DPDK instance, use 'make' +if host_machine.system() != 'linux' + build = false +endif deps += ['power', 'timer', 'lpm', 'hash'] sources = files( - 'main.c' + 'main.c', 'perf_core.c' ) diff --git a/examples/l3fwd-power/perf_core.c b/examples/l3fwd-power/perf_core.c new file mode 100644 index 00000000..83948ea2 --- /dev/null +++ b/examples/l3fwd-power/perf_core.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_memory.h> +#include <rte_lcore.h> +#include <rte_power.h> +#include <rte_string_fns.h> + +#include "perf_core.h" +#include "main.h" + + +static uint16_t hp_lcores[RTE_MAX_LCORE]; +static uint16_t nb_hp_lcores; + +struct perf_lcore_params { + uint16_t port_id; + uint8_t queue_id; + uint8_t high_perf; + uint8_t lcore_idx; +} __rte_cache_aligned; + +static struct perf_lcore_params prf_lc_prms[MAX_LCORE_PARAMS]; +static uint16_t nb_prf_lc_prms; + +int +update_lcore_params(void) +{ + uint8_t non_perf_lcores[RTE_MAX_LCORE]; + uint16_t nb_non_perf_lcores = 0; + int i, j, ret; + + /* if perf-config option was not used do nothing */ + if (nb_prf_lc_prms == 0) + return 0; + + /* if high-perf-cores option was not used query every available core */ + if (nb_hp_lcores == 0) { + for (i = 0; i < RTE_MAX_LCORE; i++) { + if (rte_lcore_is_enabled(i)) { + struct rte_power_core_capabilities caps; + ret = rte_power_get_capabilities(i, &caps); + if (ret == 0 && caps.turbo) { + hp_lcores[nb_hp_lcores] = i; + nb_hp_lcores++; + } + } + } + } + + /* create a list on non high performance cores*/ + for (i = 0; i < RTE_MAX_LCORE; i++) { + if (rte_lcore_is_enabled(i)) { + int hp = 0; + for (j = 0; j < nb_hp_lcores; j++) { + if (hp_lcores[j] == i) { + hp = 1; + break; + } + } + if (!hp) + non_perf_lcores[nb_non_perf_lcores++] = i; + } + } + + /* update the lcore config */ + for (i = 0; i < nb_prf_lc_prms; i++) { + int lcore = -1; + if (prf_lc_prms[i].high_perf) { + if (prf_lc_prms[i].lcore_idx < nb_hp_lcores) + lcore = hp_lcores[prf_lc_prms[i].lcore_idx]; + } else { + if (prf_lc_prms[i].lcore_idx < nb_non_perf_lcores) + lcore = + non_perf_lcores[prf_lc_prms[i].lcore_idx]; + } + + if (lcore < 0) { + printf("Performance cores configuration error\n"); + return -1; + } + + lcore_params_array[i].lcore_id = lcore; + lcore_params_array[i].queue_id = prf_lc_prms[i].queue_id; + lcore_params_array[i].port_id = prf_lc_prms[i].port_id; + } + + lcore_params = lcore_params_array; + nb_lcore_params = nb_prf_lc_prms; + + printf("Updated performance core configuration\n"); + for (i = 0; i < nb_prf_lc_prms; i++) + printf("\t(%d,%d,%d)\n", lcore_params[i].port_id, + lcore_params[i].queue_id, + lcore_params[i].lcore_id); + + return 0; +} + +int +parse_perf_config(const char *q_arg) +{ + char s[256]; + const char *p, *p0 = q_arg; + char *end; + enum fieldnames { + FLD_PORT = 0, + FLD_QUEUE, + FLD_LCORE_HP, + FLD_LCORE_IDX, + _NUM_FLD + }; + unsigned long int_fld[_NUM_FLD]; + char *str_fld[_NUM_FLD]; + int i; + unsigned int size; + + nb_prf_lc_prms = 0; + + while ((p = strchr(p0, '(')) != NULL) { + ++p; + p0 = strchr(p, ')'); + if (p0 == NULL) + return -1; + + size = p0 - p; + if (size >= sizeof(s)) + return -1; + + snprintf(s, sizeof(s), "%.*s", size, p); + if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != + _NUM_FLD) + return -1; + for (i = 0; i < _NUM_FLD; i++) { + errno = 0; + int_fld[i] = strtoul(str_fld[i], &end, 0); + if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) + return -1; + } + if (nb_prf_lc_prms >= MAX_LCORE_PARAMS) { + printf("exceeded max number of lcore params: %hu\n", + nb_prf_lc_prms); + return -1; + } + prf_lc_prms[nb_prf_lc_prms].port_id = + (uint8_t)int_fld[FLD_PORT]; + prf_lc_prms[nb_prf_lc_prms].queue_id = + (uint8_t)int_fld[FLD_QUEUE]; + prf_lc_prms[nb_prf_lc_prms].high_perf = + !!(uint8_t)int_fld[FLD_LCORE_HP]; + prf_lc_prms[nb_prf_lc_prms].lcore_idx = + (uint8_t)int_fld[FLD_LCORE_IDX]; + ++nb_prf_lc_prms; + } + + return 0; +} + +int +parse_perf_core_list(const char *corelist) +{ + int i, idx = 0; + unsigned int count = 0; + char *end = NULL; + int min, max; + + if (corelist == NULL) { + printf("invalid core list\n"); + return -1; + } + + + /* Remove all blank characters ahead and after */ + while (isblank(*corelist)) + corelist++; + i = strlen(corelist); + while ((i > 0) && isblank(corelist[i - 1])) + i--; + + /* Get list of cores */ + min = RTE_MAX_LCORE; + do { + while (isblank(*corelist)) + corelist++; + if (*corelist == '\0') + return -1; + errno = 0; + idx = strtoul(corelist, &end, 10); + if (errno || end == NULL) + return -1; + while (isblank(*end)) + end++; + if (*end == '-') { + min = idx; + } else if ((*end == ',') || (*end == '\0')) { + max = idx; + if (min == RTE_MAX_LCORE) + min = idx; + for (idx = min; idx <= max; idx++) { + hp_lcores[count] = idx; + count++; + } + min = RTE_MAX_LCORE; + } else { + printf("invalid core list\n"); + return -1; + } + corelist = end + 1; + } while (*end != '\0'); + + if (count == 0) { + printf("invalid core list\n"); + return -1; + } + + nb_hp_lcores = count; + + printf("Configured %d high performance cores\n", nb_hp_lcores); + for (i = 0; i < nb_hp_lcores; i++) + printf("\tHigh performance core %d %d\n", + i, hp_lcores[i]); + + return 0; +} + diff --git a/examples/l3fwd-power/perf_core.h b/examples/l3fwd-power/perf_core.h new file mode 100644 index 00000000..7b7b747b --- /dev/null +++ b/examples/l3fwd-power/perf_core.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _PERF_CORE_H_ +#define _PERF_CORE_H_ + +int parse_perf_config(const char *q_arg); +int parse_perf_core_list(const char *corelist); +int update_lcore_params(void); + +#endif /* _PERF_CORE_H_ */ diff --git a/examples/l3fwd-vf/main.c b/examples/l3fwd-vf/main.c index c69bd62f..5edd91a7 100644 --- a/examples/l3fwd-vf/main.c +++ b/examples/l3fwd-vf/main.c @@ -161,7 +161,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CRC_STRIP | DEV_RX_OFFLOAD_CHECKSUM), }, @@ -575,7 +574,7 @@ check_lcore_params(void) } static int -check_port_config(const unsigned nb_ports) +check_port_config(void) { unsigned portid; uint16_t i; @@ -586,7 +585,7 @@ check_port_config(const unsigned nb_ports) printf("port %u is not enabled in port mask\n", portid); return -1; } - if (portid >= nb_ports) { + if (!rte_eth_dev_is_valid_port(portid)) { printf("port %u is not present on the board\n", portid); return -1; } @@ -648,11 +647,10 @@ static void signal_handler(int signum) { uint16_t portid; - uint16_t nb_ports = rte_eth_dev_count(); /* When we receive a SIGINT signal */ if (signum == SIGINT) { - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) continue; @@ -950,15 +948,15 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); - if (check_port_config(nb_ports) < 0) + if (check_port_config() < 0) rte_exit(EXIT_FAILURE, "check_port_config failed\n"); nb_lcores = rte_lcore_count(); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_conf local_port_conf = port_conf; /* skip ports that are not enabled */ @@ -982,6 +980,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, n_tx_queue, &local_port_conf); if (ret < 0) @@ -1010,7 +1020,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, socketid, txconf); @@ -1063,7 +1072,7 @@ main(int argc, char **argv) printf("\n"); /* start ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } diff --git a/examples/l3fwd/l3fwd_common.h b/examples/l3fwd/l3fwd_common.h index 7002a43a..0f4fcb42 100644 --- a/examples/l3fwd/l3fwd_common.h +++ b/examples/l3fwd/l3fwd_common.h @@ -1,35 +1,6 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * Copyright(c) 2017, Linaro Limited - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2016-2018 Intel Corporation. + * Copyright(c) 2017-2018 Linaro Limited. */ diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c index 9dc3b8c4..fa8f82be 100644 --- a/examples/l3fwd/l3fwd_em.c +++ b/examples/l3fwd/l3fwd_em.c @@ -18,7 +18,6 @@ #include <rte_debug.h> #include <rte_ether.h> #include <rte_ethdev.h> -#include <rte_mempool.h> #include <rte_cycles.h> #include <rte_mbuf.h> #include <rte_ip.h> diff --git a/examples/l3fwd/l3fwd_em_hlm.h b/examples/l3fwd/l3fwd_em_hlm.h index 9d7afe05..22c26dce 100644 --- a/examples/l3fwd/l3fwd_em_hlm.h +++ b/examples/l3fwd/l3fwd_em_hlm.h @@ -1,35 +1,6 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * Copyright(c) 2017, Linaro Limited - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2016-2018 Intel Corporation. + * Copyright(c) 2017-2018 Linaro Limited. */ #ifndef __L3FWD_EM_HLM_H__ diff --git a/examples/l3fwd/l3fwd_em_hlm_neon.h b/examples/l3fwd/l3fwd_em_hlm_neon.h index dae1acfb..16c8b04a 100644 --- a/examples/l3fwd/l3fwd_em_hlm_neon.h +++ b/examples/l3fwd/l3fwd_em_hlm_neon.h @@ -1,35 +1,6 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * Copyright(c) 2017, Linaro Limited - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2016-2018 Intel Corporation. + * Copyright(c) 2017-2018 Linaro Limited. */ #ifndef __L3FWD_EM_HLM_NEON_H__ diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c index a747126a..b1dc195a 100644 --- a/examples/l3fwd/l3fwd_lpm.c +++ b/examples/l3fwd/l3fwd_lpm.c @@ -17,7 +17,6 @@ #include <rte_debug.h> #include <rte_ether.h> #include <rte_ethdev.h> -#include <rte_mempool.h> #include <rte_cycles.h> #include <rte_mbuf.h> #include <rte_ip.h> diff --git a/examples/l3fwd/l3fwd_lpm_neon.h b/examples/l3fwd/l3fwd_lpm_neon.h index 85f314d1..02ec0d80 100644 --- a/examples/l3fwd/l3fwd_lpm_neon.h +++ b/examples/l3fwd/l3fwd_lpm_neon.h @@ -1,35 +1,6 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. - * Copyright(c) 2017, Linaro Limited - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation. + * Copyright(c) 2017-2018 Linaro Limited. */ #ifndef __L3FWD_LPM_NEON_H__ diff --git a/examples/l3fwd/l3fwd_neon.h b/examples/l3fwd/l3fwd_neon.h index b319b5a9..76ccdfa7 100644 --- a/examples/l3fwd/l3fwd_neon.h +++ b/examples/l3fwd/l3fwd_neon.h @@ -1,38 +1,8 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * Copyright(c) 2017, Linaro Limited - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2016-2018 Intel Corporation. + * Copyright(c) 2017-2018 Linaro Limited. */ - #ifndef _L3FWD_NEON_H_ #define _L3FWD_NEON_H_ diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c index e7111fa1..ab019b9e 100644 --- a/examples/l3fwd/main.c +++ b/examples/l3fwd/main.c @@ -120,7 +120,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CRC_STRIP | DEV_RX_OFFLOAD_CHECKSUM), }, @@ -210,7 +209,7 @@ check_lcore_params(void) } static int -check_port_config(const unsigned nb_ports) +check_port_config(void) { uint16_t portid; uint16_t i; @@ -221,7 +220,7 @@ check_port_config(const unsigned nb_ports) printf("port %u is not enabled in port mask\n", portid); return -1; } - if (portid >= nb_ports) { + if (!rte_eth_dev_is_valid_port(portid)) { printf("port %u is not present on the board\n", portid); return -1; } @@ -694,7 +693,7 @@ init_mem(unsigned nb_mbuf) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -708,7 +707,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) if (force_quit) return; all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if (force_quit) return; if ((port_mask & (1 << portid)) == 0) @@ -826,9 +825,9 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); - if (check_port_config(nb_ports) < 0) + if (check_port_config() < 0) rte_exit(EXIT_FAILURE, "check_port_config failed\n"); nb_lcores = rte_lcore_count(); @@ -837,7 +836,7 @@ main(int argc, char **argv) setup_l3fwd_lookup_tables(); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_conf local_port_conf = port_conf; /* skip ports that are not enabled */ @@ -861,6 +860,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) @@ -909,7 +920,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); @@ -971,7 +981,7 @@ main(int argc, char **argv) printf("\n"); /* start ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } @@ -1007,7 +1017,7 @@ main(int argc, char **argv) } - check_all_ports_link_status(nb_ports, enabled_port_mask); + check_all_ports_link_status(enabled_port_mask); ret = 0; /* launch per-lcore init on every lcore */ @@ -1020,7 +1030,7 @@ main(int argc, char **argv) } /* stop ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) continue; printf("Closing port %d...", portid); diff --git a/examples/link_status_interrupt/main.c b/examples/link_status_interrupt/main.c index ad0dd390..3b732076 100644 --- a/examples/link_status_interrupt/main.c +++ b/examples/link_status_interrupt/main.c @@ -79,7 +79,6 @@ struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -542,7 +541,7 @@ main(int argc, char **argv) if (lsi_pktmbuf_pool == NULL) rte_panic("Cannot init mbuf pool\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_panic("No Ethernet port - bye\n"); @@ -653,7 +652,6 @@ main(int argc, char **argv) /* init one TX queue logical core on each port */ fflush(stdout); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), diff --git a/examples/load_balancer/config.c b/examples/load_balancer/config.c index b5b66368..972c85c5 100644 --- a/examples/load_balancer/config.c +++ b/examples/load_balancer/config.c @@ -121,7 +121,7 @@ str_to_unsigned_array( int i, num_splits = 0; /* copy s so we don't modify original string */ - snprintf(str, sizeof(str), "%s", s); + strlcpy(str, s, sizeof(str)); num_splits = rte_strsplit(str, sizeof(str), splits, num_vals, separator); errno = 0; diff --git a/examples/load_balancer/init.c b/examples/load_balancer/init.c index 8d8dbe61..f2045f23 100644 --- a/examples/load_balancer/init.c +++ b/examples/load_balancer/init.c @@ -45,7 +45,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -417,6 +416,18 @@ app_init_nics(void) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure( port, (uint8_t) n_rx_queues, @@ -466,7 +477,6 @@ app_init_nics(void) } txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; /* Init TX queues */ if (app.nic_tx_port_mask[port] == 1) { diff --git a/examples/meson.build b/examples/meson.build index 2c6b3f88..4ee7a111 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -7,27 +7,54 @@ if get_option('default_library') == 'static' endif execinfo = cc.find_library('execinfo', required: false) -foreach example: get_option('examples').split(',') + +allow_skips = true # don't flag an error if we can't build an app + +if get_option('examples').to_lower() == 'all' + dirs = run_command('sh', '-c', + 'cd $MESON_SOURCE_ROOT/$MESON_SUBDIR && for d in * ; do if [ -d $d ] ; then echo $d ; fi ; done') + examples = dirs.stdout().split() +else + examples = get_option('examples').split(',') + allow_skips = false # error out if we can't build a requested app +endif +default_cflags = machine_args +if cc.has_argument('-Wno-format-truncation') + default_cflags += '-Wno-format-truncation' +endif +foreach example: examples name = example + build = true sources = [] allow_experimental_apis = false - cflags = machine_args + cflags = default_cflags + ext_deps = [execinfo] includes = [include_directories(example)] deps = ['eal', 'mempool', 'net', 'mbuf', 'ethdev', 'cmdline'] subdir(example) - dep_objs = ext_deps - foreach d:deps - dep_objs += [get_variable(get_option('default_library') + '_rte_' + d)] - endforeach - if allow_experimental_apis - cflags += '-DALLOW_EXPERIMENTAL_API' + if build + dep_objs = ext_deps + foreach d:deps + var_name = get_option('default_library') + '_rte_' + d + if not is_variable(var_name) + error('Missing dependency "@0@" for example "@1@"'.format(d, name)) + endif + dep_objs += [get_variable(var_name)] + endforeach + if allow_experimental_apis + cflags += '-DALLOW_EXPERIMENTAL_API' + endif + executable('dpdk-' + name, sources, + include_directories: includes, + link_whole: driver_libs, + link_args: dpdk_extra_ldflags, + c_args: cflags, + dependencies: dep_objs) + elif not allow_skips + error('Cannot build requested example "' + name + '"') + else + message('Skipping example "' + name + '"') endif - executable('dpdk-' + name, sources, - include_directories: includes, - link_whole: driver_libs, - link_args: dpdk_extra_ldflags, - c_args: cflags, - dependencies: dep_objs) endforeach diff --git a/examples/multi_process/client_server_mp/mp_client/client.c b/examples/multi_process/client_server_mp/mp_client/client.c index 92955e97..c23dd3f3 100644 --- a/examples/multi_process/client_server_mp/mp_client/client.c +++ b/examples/multi_process/client_server_mp/mp_client/client.c @@ -220,7 +220,7 @@ main(int argc, char *argv[]) if (parse_app_args(argc, argv) < 0) rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n"); - if (rte_eth_dev_count() == 0) + if (rte_eth_dev_count_avail() == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); rx_ring = rte_ring_lookup(get_rx_queue_name(client_id)); diff --git a/examples/multi_process/client_server_mp/mp_server/Makefile b/examples/multi_process/client_server_mp/mp_server/Makefile index 3e244e28..9c1caae7 100644 --- a/examples/multi_process/client_server_mp/mp_server/Makefile +++ b/examples/multi_process/client_server_mp/mp_server/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif @@ -23,6 +23,7 @@ SRCS-y := main.c init.c args.c INC := $(sort $(wildcard *.h)) +CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += $(WERROR_FLAGS) -O3 CFLAGS += -I$(SRCDIR)/../shared diff --git a/examples/multi_process/client_server_mp/mp_server/init.c b/examples/multi_process/client_server_mp/mp_server/init.c index 1c465ccb..30c8e44b 100644 --- a/examples/multi_process/client_server_mp/mp_server/init.c +++ b/examples/multi_process/client_server_mp/mp_server/init.c @@ -243,7 +243,7 @@ init(int argc, char *argv[]) argv += retval; /* get total number of ports */ - total_ports = rte_eth_dev_count(); + total_ports = rte_eth_dev_count_total(); /* set up array for port data */ mz = rte_memzone_reserve(MZ_PORT_INFO, sizeof(*ports), diff --git a/examples/multi_process/l2fwd_fork/flib.c b/examples/multi_process/l2fwd_fork/flib.c deleted file mode 100644 index 52c6152b..00000000 --- a/examples/multi_process/l2fwd_fork/flib.c +++ /dev/null @@ -1,280 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <inttypes.h> -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/wait.h> -#include <sys/prctl.h> -#include <netinet/in.h> -#include <setjmp.h> -#include <stdarg.h> -#include <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <dirent.h> -#include <signal.h> - -#include <rte_common.h> -#include <rte_log.h> -#include <rte_malloc.h> -#include <rte_memory.h> -#include <rte_memcpy.h> -#include <rte_eal.h> -#include <rte_launch.h> -#include <rte_atomic.h> -#include <rte_cycles.h> -#include <rte_prefetch.h> -#include <rte_lcore.h> -#include <rte_per_lcore.h> -#include <rte_branch_prediction.h> -#include <rte_interrupts.h> -#include <rte_random.h> -#include <rte_debug.h> -#include <rte_ether.h> -#include <rte_ethdev.h> -#include <rte_mempool.h> -#include <rte_mbuf.h> -#include <rte_string_fns.h> - -#include "flib.h" - -#define SIG_PARENT_EXIT SIGUSR1 - -struct lcore_stat { - pid_t pid; /**< pthread identifier */ - lcore_function_t *f; /**< function to call */ - void *arg; /**< argument of function */ - slave_exit_notify *cb_fn; -} __rte_cache_aligned; - - -static struct lcore_stat *core_cfg; -static uint16_t *lcore_cfg = NULL; - -/* signal handler to be notified after parent leaves */ -static void -sighand_parent_exit(int sig) -{ - printf("lcore = %u : Find parent leaves, sig=%d\n", rte_lcore_id(), - sig); - printf("Child leaving\n"); - exit(0); - - return; -} - -/** - * Real function entrance ran in slave process - **/ -static int -slave_proc_func(void) -{ - struct rte_config *config; - unsigned slave_id = rte_lcore_id(); - struct lcore_stat *cfg = &core_cfg[slave_id]; - - if (prctl(PR_SET_PDEATHSIG, SIG_PARENT_EXIT, 0, 0, 0, 0) != 0) - printf("Warning: Slave can't register for being notified in" - "case master process exited\n"); - else { - struct sigaction act; - memset(&act, 0 , sizeof(act)); - act.sa_handler = sighand_parent_exit; - if (sigaction(SIG_PARENT_EXIT, &act, NULL) != 0) - printf("Fail to register signal handler:%d\n", SIG_PARENT_EXIT); - } - - /* Set slave process to SECONDARY to avoid operation like dev_start/stop etc */ - config = rte_eal_get_configuration(); - if (NULL == config) - printf("Warning:Can't get rte_config\n"); - else - config->process_type = RTE_PROC_SECONDARY; - - printf("Core %u is ready (pid=%d)\n", slave_id, (int)cfg->pid); - - exit(cfg->f(cfg->arg)); -} - -/** - * function entrance ran in master thread, which will spawn slave process and wait until - * specific slave exited. - **/ -static int -lcore_func(void *arg __attribute__((unused))) -{ - unsigned slave_id = rte_lcore_id(); - struct lcore_stat *cfg = &core_cfg[slave_id]; - int pid, stat; - - if (rte_get_master_lcore() == slave_id) - return cfg->f(cfg->arg); - - /* fork a slave process */ - pid = fork(); - - if (pid == -1) { - printf("Failed to fork\n"); - return -1; - } else if (pid == 0) /* child */ - return slave_proc_func(); - else { /* parent */ - cfg->pid = pid; - - waitpid(pid, &stat, 0); - - cfg->pid = 0; - cfg->f = NULL; - cfg->arg = NULL; - /* Notify slave's exit if applicable */ - if(cfg->cb_fn) - cfg->cb_fn(slave_id, stat); - return stat; - } -} - -static int -lcore_id_init(void) -{ - int i; - /* Setup lcore ID allocation map */ - lcore_cfg = rte_zmalloc("LCORE_ID_MAP", - sizeof(uint16_t) * RTE_MAX_LCORE, - RTE_CACHE_LINE_SIZE); - - if(lcore_cfg == NULL) - rte_panic("Failed to malloc\n"); - - for (i = 0; i < RTE_MAX_LCORE; i++) { - if (rte_lcore_is_enabled(i)) - lcore_cfg[i] = 1; - } - return 0; -} - -int -flib_assign_lcore_id(void) -{ - unsigned i; - int ret; - - /** - * thread assigned a lcore id previously, or a slave thread. But still have - * a bug here: If the core mask includes core 0, and that core call this - * function, it still can get a new lcore id. - **/ - if (rte_lcore_id() != 0) - return -1; - - do { - /* Find a lcore id not used yet, avoid to use lcore ID 0 */ - for (i = 1; i < RTE_MAX_LCORE; i++) { - if (lcore_cfg[i] == 0) - break; - } - if (i == RTE_MAX_LCORE) - return -1; - - /* Assign new lcore id to this thread */ - - ret = rte_atomic16_cmpset(&lcore_cfg[i], 0, 1); - } while (unlikely(ret == 0)); - - RTE_PER_LCORE(_lcore_id) = i; - return i; -} - -void -flib_free_lcore_id(unsigned lcore_id) -{ - /* id is not valid or belongs to pinned core id */ - if (lcore_id >= RTE_MAX_LCORE || lcore_id == 0 || - rte_lcore_is_enabled(lcore_id)) - return; - - lcore_cfg[lcore_id] = 0; -} - -int -flib_register_slave_exit_notify(unsigned slave_id, - slave_exit_notify *cb) -{ - if (cb == NULL) - return -EFAULT; - - if (!rte_lcore_is_enabled(slave_id)) - return -ENOENT; - - core_cfg[slave_id].cb_fn = cb; - - return 0; -} - -enum slave_stat -flib_query_slave_status(unsigned slave_id) -{ - if (!rte_lcore_is_enabled(slave_id)) - return ST_FREEZE; - /* pid only be set when slave process spawned */ - if (core_cfg[slave_id].pid != 0) - return ST_RUN; - else - return ST_IDLE; -} - -int -flib_remote_launch(lcore_function_t *f, - void *arg, unsigned slave_id) -{ - if (f == NULL) - return -1; - - if (!rte_lcore_is_enabled(slave_id)) - return -1; - - /* Wait until specific lcore state change to WAIT */ - rte_eal_wait_lcore(slave_id); - - core_cfg[slave_id].f = f; - core_cfg[slave_id].arg = arg; - - return rte_eal_remote_launch(lcore_func, NULL, slave_id); -} - -int -flib_mp_remote_launch(lcore_function_t *f, void *arg, - enum rte_rmt_call_master_t call_master) -{ - int i; - - RTE_LCORE_FOREACH_SLAVE(i) { - core_cfg[i].arg = arg; - core_cfg[i].f = f; - } - - return rte_eal_mp_remote_launch(lcore_func, NULL, call_master); -} - -int -flib_init(void) -{ - if ((core_cfg = rte_zmalloc("core_cfg", - sizeof(struct lcore_stat) * RTE_MAX_LCORE, - RTE_CACHE_LINE_SIZE)) == NULL ) { - printf("rte_zmalloc failed\n"); - return -1; - } - - if (lcore_id_init() != 0) { - printf("lcore_id_init failed\n"); - return -1; - } - - return 0; -} diff --git a/examples/multi_process/l2fwd_fork/flib.h b/examples/multi_process/l2fwd_fork/flib.h deleted file mode 100644 index 8bc13a1f..00000000 --- a/examples/multi_process/l2fwd_fork/flib.h +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef __FLIB_H -#define __FLIB_H - -/* callback function pointer when specific slave leaves */ -typedef void (slave_exit_notify)(unsigned slaveid, int stat); - -enum slave_stat{ - ST_FREEZE = 1, - ST_IDLE, - ST_RUN, - ST_ZOMBIE, /* Not implemented yet */ -}; - -/** - * Initialize the fork lib. - * - * @return - * - 0 : fork lib initialized successfully - * - -1 : fork lib initialized failed - */ -int flib_init(void); - -/** - * Check that every SLAVE lcores are in WAIT state, then call - * flib_remote_launch() for all of them. If call_master is true - * (set to CALL_MASTER), also call the function on the master lcore. - * - * @param f: - * function pointer need to run - * @param arg: - * argument for f to carry - * @param call_master - * - SKIP_MASTER : only launch function on slave lcores - * - CALL_MASTER : launch function on master and slave lcores - * @return - * - 0 : function execute successfully - * - -1 : function execute failed - */ -int flib_mp_remote_launch(lcore_function_t *f, - void *arg, enum rte_rmt_call_master_t call_master); - -/** - * Send a message to a slave lcore identified by slave_id to call a - * function f with argument arg. - * - * @param f: - * function pointer need to run - * @param arg: - * argument for f to carry - * @param slave_id - * slave lcore id to run on - * @return - * - 0 : function execute successfully - * - -1 : function execute failed - */ -int flib_remote_launch(lcore_function_t *f, - void *arg, unsigned slave_id); - -/** - * Query the running stat for specific slave, wont' work in with master id - * - * @param slave_id: - * lcore id which should not be master id - * @return - * - ST_FREEZE : lcore is not in enabled core mask - * - ST_IDLE : lcore is idle - * - ST_RUN : lcore is running something - */ -enum slave_stat -flib_query_slave_status(unsigned slave_id); - -/** - * Register a callback function to be notified in case specific slave exit. - * - * @param slave_id: - * lcore id which should not be master id - * @param cb: - * callback pointer to register - * @return - * - 0 : function execute successfully - * - -EFAULT : argument error - * - -ENOENT : slave_id not correct - */ -int flib_register_slave_exit_notify(unsigned slave_id, - slave_exit_notify *cb); - -/** - * Assign a lcore ID to non-slave thread. Non-slave thread refers to thread that - * not created by function rte_eal_remote_launch or rte_eal_mp_remote_launch. - * These threads can either bind lcore or float among different lcores. - * This lcore ID will be unique in multi-thread or multi-process DPDK running - * environment, then it can benefit from using the cache mechanism provided in - * mempool library. - * After calling successfully, use rte_lcore_id() to get the assigned lcore ID, but - * other lcore funtions can't guarantee to work correctly. - * - * @return - * - -1 : can't assign a lcore id with 3 possibilities. - * - it's not non-slave thread. - * - it had assign a lcore id previously - * - the lcore id is running out. - * - > 0 : the assigned lcore id. - */ -int flib_assign_lcore_id(void); - -/** - * Free the lcore_id that assigned in flib_assign_lcore_id(). - * call it in case non-slave thread is leaving or left. - * - * @param lcore_id - * The identifier of the lcore, which MUST be between 1 and - * RTE_MAX_LCORE-1. - */ -void flib_free_lcore_id(unsigned lcore_id); - -#endif /* __FLIB_H */ diff --git a/examples/multi_process/l2fwd_fork/main.c b/examples/multi_process/l2fwd_fork/main.c deleted file mode 100644 index bc9ceb5c..00000000 --- a/examples/multi_process/l2fwd_fork/main.c +++ /dev/null @@ -1,1261 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <stdint.h> -#include <sched.h> -#include <inttypes.h> -#include <sys/types.h> -#include <sys/queue.h> -#include <netinet/in.h> -#include <setjmp.h> -#include <stdarg.h> -#include <ctype.h> -#include <errno.h> -#include <getopt.h> - -#include <rte_common.h> -#include <rte_log.h> -#include <rte_memory.h> -#include <rte_memcpy.h> -#include <rte_eal.h> -#include <rte_launch.h> -#include <rte_atomic.h> -#include <rte_spinlock.h> -#include <rte_cycles.h> -#include <rte_prefetch.h> -#include <rte_lcore.h> -#include <rte_per_lcore.h> -#include <rte_branch_prediction.h> -#include <rte_interrupts.h> -#include <rte_random.h> -#include <rte_debug.h> -#include <rte_ether.h> -#include <rte_ethdev.h> -#include <rte_ring.h> -#include <rte_mempool.h> -#include <rte_mbuf.h> -#include <rte_malloc.h> - -#include "flib.h" - -#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 -#define MBUF_NAME "mbuf_pool_%d" -#define MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE -#define NB_MBUF 8192 -#define RING_MASTER_NAME "l2fwd_ring_m2s_" -#define RING_SLAVE_NAME "l2fwd_ring_s2m_" -#define MAX_NAME_LEN 32 -/* RECREATE flag indicate needs initialize resource and launch slave_core again */ -#define SLAVE_RECREATE_FLAG 0x1 -/* RESTART flag indicate needs restart port and send START command again */ -#define SLAVE_RESTART_FLAG 0x2 -#define INVALID_MAPPING_ID ((unsigned)LCORE_ID_ANY) -/* Maximum message buffer per slave */ -#define NB_CORE_MSGBUF 32 -enum l2fwd_cmd{ - CMD_START, - CMD_STOP, -}; - -#define MAX_PKT_BURST 32 -#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ - -/* - * Configurable number of RX/TX ring descriptors - */ -#define RTE_TEST_RX_DESC_DEFAULT 1024 -#define RTE_TEST_TX_DESC_DEFAULT 1024 -static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; -static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; - -/* ethernet addresses of ports */ -static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; - -/* mask of enabled ports */ -static uint32_t l2fwd_enabled_port_mask = 0; - -/* list of enabled ports */ -static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; - -static unsigned int l2fwd_rx_queue_per_lcore = 1; - -struct mbuf_table { - unsigned len; - struct rte_mbuf *m_table[MAX_PKT_BURST]; -}; - -#define MAX_RX_QUEUE_PER_LCORE 16 -#define MAX_TX_QUEUE_PER_PORT 16 -struct lcore_queue_conf { - unsigned n_rx_port; - unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; -} __rte_cache_aligned; -struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; - -struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; - -struct lcore_resource_struct { - int enabled; /* Only set in case this lcore involved into packet forwarding */ - int flags; /* Set only slave need to restart or recreate */ - unsigned lcore_id; /* lcore ID */ - unsigned pair_id; /* dependency lcore ID on port */ - char ring_name[2][MAX_NAME_LEN]; - /* ring[0] for master send cmd, slave read */ - /* ring[1] for slave send ack, master read */ - struct rte_ring *ring[2]; - int port_num; /* Total port numbers */ - /* Port id for that lcore to receive packets */ - uint16_t port[RTE_MAX_ETHPORTS]; -}__attribute__((packed)) __rte_cache_aligned; - -static struct lcore_resource_struct lcore_resource[RTE_MAX_LCORE]; -static struct rte_mempool *message_pool; -static rte_spinlock_t res_lock = RTE_SPINLOCK_INITIALIZER; -/* use floating processes */ -static int float_proc = 0; -/* Save original cpu affinity */ -struct cpu_aff_arg{ - cpu_set_t set; - size_t size; -}cpu_aff; - -static const struct rte_eth_conf port_conf = { - .rxmode = { - .split_hdr_size = 0, - .ignore_offload_bitfield = 1, - .offloads = DEV_RX_OFFLOAD_CRC_STRIP, - }, - .txmode = { - .mq_mode = ETH_MQ_TX_NONE, - }, -}; - -static struct rte_mempool * l2fwd_pktmbuf_pool[RTE_MAX_ETHPORTS]; - -/* Per-port statistics struct */ -struct l2fwd_port_statistics { - uint64_t tx; - uint64_t rx; - uint64_t dropped; -} __rte_cache_aligned; -struct l2fwd_port_statistics *port_statistics; -/** - * pointer to lcore ID mapping array, used to return lcore id in case slave - * process exited unexpectedly, use only floating process option applied - **/ -unsigned *mapping_id; - -/* A tsc-based timer responsible for triggering statistics printout */ -#define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */ -#define MAX_TIMER_PERIOD 86400 /* 1 day max */ -static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */ - -static int l2fwd_launch_one_lcore(void *dummy); - -/* Print out statistics on packets dropped */ -static void -print_stats(void) -{ - uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; - unsigned portid; - - total_packets_dropped = 0; - total_packets_tx = 0; - total_packets_rx = 0; - - const char clr[] = { 27, '[', '2', 'J', '\0' }; - const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; - - /* Clear screen and move to top left */ - printf("%s%s", clr, topLeft); - - printf("\nPort statistics ===================================="); - - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { - /* skip disabled ports */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - printf("\nStatistics for port %u ------------------------------" - "\nPackets sent: %24"PRIu64 - "\nPackets received: %20"PRIu64 - "\nPackets dropped: %21"PRIu64, - portid, - port_statistics[portid].tx, - port_statistics[portid].rx, - port_statistics[portid].dropped); - - total_packets_dropped += port_statistics[portid].dropped; - total_packets_tx += port_statistics[portid].tx; - total_packets_rx += port_statistics[portid].rx; - } - printf("\nAggregate statistics ===============================" - "\nTotal packets sent: %18"PRIu64 - "\nTotal packets received: %14"PRIu64 - "\nTotal packets dropped: %15"PRIu64, - total_packets_tx, - total_packets_rx, - total_packets_dropped); - printf("\n====================================================\n"); -} - -static int -clear_cpu_affinity(void) -{ - int s; - - s = sched_setaffinity(0, cpu_aff.size, &cpu_aff.set); - if (s != 0) { - printf("sched_setaffinity failed:%s\n", strerror(errno)); - return -1; - } - - return 0; -} - -static int -get_cpu_affinity(void) -{ - int s; - - cpu_aff.size = sizeof(cpu_set_t); - CPU_ZERO(&cpu_aff.set); - - s = sched_getaffinity(0, cpu_aff.size, &cpu_aff.set); - if (s != 0) { - printf("sched_getaffinity failed:%s\n", strerror(errno)); - return -1; - } - - return 0; -} - -/** - * This fnciton demonstrates the approach to create ring in first instance - * or re-attach an existed ring in later instance. - **/ -static struct rte_ring * -create_ring(const char *name, unsigned count, - int socket_id,unsigned flags) -{ - struct rte_ring *ring; - - if (name == NULL) - return NULL; - - /* If already create, just attached it */ - if (likely((ring = rte_ring_lookup(name)) != NULL)) - return ring; - - /* First call it, create one */ - return rte_ring_create(name, count, socket_id, flags); -} - -/* Malloc with rte_malloc on structures that shared by master and slave */ -static int -l2fwd_malloc_shared_struct(void) -{ - port_statistics = rte_zmalloc("port_stat", - sizeof(struct l2fwd_port_statistics) * RTE_MAX_ETHPORTS, - 0); - if (port_statistics == NULL) - return -1; - - /* allocate mapping_id array */ - if (float_proc) { - int i; - mapping_id = rte_malloc("mapping_id", sizeof(unsigned) * RTE_MAX_LCORE, - 0); - - if (mapping_id == NULL) - return -1; - - for (i = 0 ;i < RTE_MAX_LCORE; i++) - mapping_id[i] = INVALID_MAPPING_ID; - } - return 0; -} - -/* Create ring which used for communicate among master and slave */ -static int -create_ms_ring(unsigned slaveid) -{ - unsigned flag = RING_F_SP_ENQ | RING_F_SC_DEQ; - struct lcore_resource_struct *res = &lcore_resource[slaveid]; - unsigned socketid = rte_socket_id(); - - /* Always assume create ring on master socket_id */ - /* Default only create a ring size 32 */ - snprintf(res->ring_name[0], MAX_NAME_LEN, "%s%u", - RING_MASTER_NAME, slaveid); - if ((res->ring[0] = create_ring(res->ring_name[0], NB_CORE_MSGBUF, - socketid, flag)) == NULL) { - printf("Create m2s ring %s failed\n", res->ring_name[0]); - return -1; - } - - snprintf(res->ring_name[1], MAX_NAME_LEN, "%s%u", - RING_SLAVE_NAME, slaveid); - if ((res->ring[1] = create_ring(res->ring_name[1], NB_CORE_MSGBUF, - socketid, flag)) == NULL) { - printf("Create s2m ring %s failed\n", res->ring_name[1]); - return -1; - } - - return 0; -} - -/* send command to pair in paired master and slave ring */ -static inline int -sendcmd(unsigned slaveid, enum l2fwd_cmd cmd, int is_master) -{ - struct lcore_resource_struct *res = &lcore_resource[slaveid]; - void *msg; - int fd = !is_master; - - /* Only check master, it must be enabled and running if it is slave */ - if (is_master && !res->enabled) - return -1; - - if (res->ring[fd] == NULL) - return -1; - - if (rte_mempool_get(message_pool, &msg) < 0) { - printf("Error to get message buffer\n"); - return -1; - } - - *(enum l2fwd_cmd *)msg = cmd; - - if (rte_ring_enqueue(res->ring[fd], msg) != 0) { - printf("Enqueue error\n"); - rte_mempool_put(message_pool, msg); - return -1; - } - - return 0; -} - -/* Get command from pair in paired master and slave ring */ -static inline int -getcmd(unsigned slaveid, enum l2fwd_cmd *cmd, int is_master) -{ - struct lcore_resource_struct *res = &lcore_resource[slaveid]; - void *msg; - int fd = !!is_master; - int ret; - /* Only check master, it must be enabled and running if it is slave */ - if (is_master && (!res->enabled)) - return -1; - - if (res->ring[fd] == NULL) - return -1; - - ret = rte_ring_dequeue(res->ring[fd], &msg); - - if (ret == 0) { - *cmd = *(enum l2fwd_cmd *)msg; - rte_mempool_put(message_pool, msg); - } - return ret; -} - -/* Master send command to slave and wait until ack received or error met */ -static int -master_sendcmd_with_ack(unsigned slaveid, enum l2fwd_cmd cmd) -{ - enum l2fwd_cmd ack_cmd; - int ret = -1; - - if (sendcmd(slaveid, cmd, 1) != 0) - rte_exit(EXIT_FAILURE, "Failed to send message\n"); - - /* Get ack */ - while (1) { - ret = getcmd(slaveid, &ack_cmd, 1); - if (ret == 0 && cmd == ack_cmd) - break; - - /* If slave not running yet, return an error */ - if (flib_query_slave_status(slaveid) != ST_RUN) { - ret = -ENOENT; - break; - } - } - - return ret; -} - -/* restart all port that assigned to that slave lcore */ -static int -reset_slave_all_ports(unsigned slaveid) -{ - struct lcore_resource_struct *slave = &lcore_resource[slaveid]; - int i, ret = 0; - - /* stop/start port */ - for (i = 0; i < slave->port_num; i++) { - char buf_name[RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *pool; - printf("Stop port :%d\n", slave->port[i]); - rte_eth_dev_stop(slave->port[i]); - snprintf(buf_name, RTE_MEMPOOL_NAMESIZE, MBUF_NAME, slave->port[i]); - pool = rte_mempool_lookup(buf_name); - if (pool) - printf("Port %d mempool free object is %u(%u)\n", slave->port[i], - rte_mempool_avail_count(pool), - (unsigned int)NB_MBUF); - else - printf("Can't find mempool %s\n", buf_name); - - printf("Start port :%d\n", slave->port[i]); - ret = rte_eth_dev_start(slave->port[i]); - if (ret != 0) - break; - } - return ret; -} - -static int -reset_shared_structures(unsigned slaveid) -{ - int ret; - /* Only port are shared resource here */ - ret = reset_slave_all_ports(slaveid); - - return ret; -} - -/** - * Call this function to re-create resource that needed for slave process that - * exited in last instance - **/ -static int -init_slave_res(unsigned slaveid) -{ - struct lcore_resource_struct *slave = &lcore_resource[slaveid]; - enum l2fwd_cmd cmd; - - if (!slave->enabled) { - printf("Something wrong with lcore=%u enabled=%d\n",slaveid, - slave->enabled); - return -1; - } - - /* Initialize ring */ - if (create_ms_ring(slaveid) != 0) - rte_exit(EXIT_FAILURE, "failed to create ring for slave %u\n", - slaveid); - - /* drain un-read buffer if have */ - while (getcmd(slaveid, &cmd, 1) == 0); - while (getcmd(slaveid, &cmd, 0) == 0); - - return 0; -} - -static int -recreate_one_slave(unsigned slaveid) -{ - int ret = 0; - /* Re-initialize resource for stalled slave */ - if ((ret = init_slave_res(slaveid)) != 0) { - printf("Init slave=%u failed\n", slaveid); - return ret; - } - - if ((ret = flib_remote_launch(l2fwd_launch_one_lcore, NULL, slaveid)) - != 0) - printf("Launch slave %u failed\n", slaveid); - - return ret; -} - -/** - * remapping resource belong to slave_id to new lcore that gets from flib_assign_lcore_id(), - * used only floating process option applied. - * - * @param slaveid - * original lcore_id that apply for remapping - */ -static void -remapping_slave_resource(unsigned slaveid, unsigned map_id) -{ - - /* remapping lcore_resource */ - memcpy(&lcore_resource[map_id], &lcore_resource[slaveid], - sizeof(struct lcore_resource_struct)); - - /* remapping lcore_queue_conf */ - memcpy(&lcore_queue_conf[map_id], &lcore_queue_conf[slaveid], - sizeof(struct lcore_queue_conf)); -} - -static int -reset_pair(unsigned slaveid, unsigned pairid) -{ - int ret; - if ((ret = reset_shared_structures(slaveid)) != 0) - goto back; - - if((ret = reset_shared_structures(pairid)) != 0) - goto back; - - if (float_proc) { - unsigned map_id = mapping_id[slaveid]; - - if (map_id != INVALID_MAPPING_ID) { - printf("%u return mapping id %u\n", slaveid, map_id); - flib_free_lcore_id(map_id); - mapping_id[slaveid] = INVALID_MAPPING_ID; - } - - map_id = mapping_id[pairid]; - if (map_id != INVALID_MAPPING_ID) { - printf("%u return mapping id %u\n", pairid, map_id); - flib_free_lcore_id(map_id); - mapping_id[pairid] = INVALID_MAPPING_ID; - } - } - - if((ret = recreate_one_slave(slaveid)) != 0) - goto back; - - ret = recreate_one_slave(pairid); - -back: - return ret; -} - -static void -slave_exit_cb(unsigned slaveid, __attribute__((unused))int stat) -{ - struct lcore_resource_struct *slave = &lcore_resource[slaveid]; - - printf("Get slave %u leave info\n", slaveid); - if (!slave->enabled) { - printf("Lcore=%u not registered for it's exit\n", slaveid); - return; - } - rte_spinlock_lock(&res_lock); - - /* Change the state and wait master to start them */ - slave->flags = SLAVE_RECREATE_FLAG; - - rte_spinlock_unlock(&res_lock); -} - -static void -l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) -{ - struct ether_hdr *eth; - void *tmp; - unsigned dst_port; - int sent; - struct rte_eth_dev_tx_buffer *buffer; - - dst_port = l2fwd_dst_ports[portid]; - eth = rte_pktmbuf_mtod(m, struct ether_hdr *); - - /* 02:00:00:00:00:xx */ - tmp = ð->d_addr.addr_bytes[0]; - *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); - - /* src addr */ - ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); - - buffer = tx_buffer[dst_port]; - sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); - if (sent) - port_statistics[dst_port].tx += sent; -} - -/* main processing loop */ -static void -l2fwd_main_loop(void) -{ - struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; - struct rte_mbuf *m; - int sent; - unsigned lcore_id; - uint64_t prev_tsc, diff_tsc, cur_tsc; - unsigned i, j, portid, nb_rx; - struct lcore_queue_conf *qconf; - const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * - BURST_TX_DRAIN_US; - struct rte_eth_dev_tx_buffer *buffer; - - prev_tsc = 0; - - lcore_id = rte_lcore_id(); - - qconf = &lcore_queue_conf[lcore_id]; - - if (qconf->n_rx_port == 0) { - RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); - return; - } - - RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); - - for (i = 0; i < qconf->n_rx_port; i++) { - portid = qconf->rx_port_list[i]; - RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, - portid); - } - - while (1) { - enum l2fwd_cmd cmd; - cur_tsc = rte_rdtsc(); - - if (unlikely(getcmd(lcore_id, &cmd, 0) == 0)) { - sendcmd(lcore_id, cmd, 0); - - /* If get stop command, stop forwarding and exit */ - if (cmd == CMD_STOP) { - return; - } - } - - /* - * TX burst queue drain - */ - diff_tsc = cur_tsc - prev_tsc; - if (unlikely(diff_tsc > drain_tsc)) { - - for (i = 0; i < qconf->n_rx_port; i++) { - - portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; - buffer = tx_buffer[portid]; - - sent = rte_eth_tx_buffer_flush(portid, 0, buffer); - if (sent) - port_statistics[portid].tx += sent; - - } - - prev_tsc = cur_tsc; - } - - /* - * Read packet from RX queues - */ - for (i = 0; i < qconf->n_rx_port; i++) { - - portid = qconf->rx_port_list[i]; - nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, - pkts_burst, MAX_PKT_BURST); - - port_statistics[portid].rx += nb_rx; - - for (j = 0; j < nb_rx; j++) { - m = pkts_burst[j]; - rte_prefetch0(rte_pktmbuf_mtod(m, void *)); - l2fwd_simple_forward(m, portid); - } - } - } -} - -static int -l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy) -{ - unsigned lcore_id = rte_lcore_id(); - - if (float_proc) { - unsigned flcore_id; - - /* Change it to floating process, also change it's lcore_id */ - clear_cpu_affinity(); - RTE_PER_LCORE(_lcore_id) = 0; - /* Get a lcore_id */ - if (flib_assign_lcore_id() < 0 ) { - printf("flib_assign_lcore_id failed\n"); - return -1; - } - flcore_id = rte_lcore_id(); - /* Set mapping id, so master can return it after slave exited */ - mapping_id[lcore_id] = flcore_id; - printf("Org lcore_id = %u, cur lcore_id = %u\n", - lcore_id, flcore_id); - remapping_slave_resource(lcore_id, flcore_id); - } - - l2fwd_main_loop(); - - /* return lcore_id before return */ - if (float_proc) { - flib_free_lcore_id(rte_lcore_id()); - mapping_id[lcore_id] = INVALID_MAPPING_ID; - } - return 0; -} - -/* display usage */ -static void -l2fwd_usage(const char *prgname) -{ - printf("%s [EAL options] -- -p PORTMASK -s COREMASK [-q NQ] -f\n" - " -p PORTMASK: hexadecimal bitmask of ports to configure\n" - " -q NQ: number of queue (=ports) per lcore (default is 1)\n" - " -f use floating process which won't bind to any core to run\n" - " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n", - prgname); -} - -static int -l2fwd_parse_portmask(const char *portmask) -{ - char *end = NULL; - unsigned long pm; - - /* parse hexadecimal string */ - pm = strtoul(portmask, &end, 16); - if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) - return -1; - - if (pm == 0) - return -1; - - return pm; -} - -static unsigned int -l2fwd_parse_nqueue(const char *q_arg) -{ - char *end = NULL; - unsigned long n; - - /* parse hexadecimal string */ - n = strtoul(q_arg, &end, 10); - if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) - return 0; - if (n == 0) - return 0; - if (n >= MAX_RX_QUEUE_PER_LCORE) - return 0; - - return n; -} - -static int -l2fwd_parse_timer_period(const char *q_arg) -{ - char *end = NULL; - int n; - - /* parse number string */ - n = strtol(q_arg, &end, 10); - if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) - return -1; - if (n >= MAX_TIMER_PERIOD) - return -1; - - return n; -} - -/* Parse the argument given in the command line of the application */ -static int -l2fwd_parse_args(int argc, char **argv) -{ - int opt, ret; - char **argvopt; - int option_index; - char *prgname = argv[0]; - static struct option lgopts[] = { - {NULL, 0, 0, 0} - }; - int has_pmask = 0; - - argvopt = argv; - - while ((opt = getopt_long(argc, argvopt, "p:q:T:f", - lgopts, &option_index)) != EOF) { - - switch (opt) { - /* portmask */ - case 'p': - l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); - if (l2fwd_enabled_port_mask == 0) { - printf("invalid portmask\n"); - l2fwd_usage(prgname); - return -1; - } - has_pmask = 1; - break; - - /* nqueue */ - case 'q': - l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); - if (l2fwd_rx_queue_per_lcore == 0) { - printf("invalid queue number\n"); - l2fwd_usage(prgname); - return -1; - } - break; - - /* timer period */ - case 'T': - timer_period = l2fwd_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND; - if (timer_period < 0) { - printf("invalid timer period\n"); - l2fwd_usage(prgname); - return -1; - } - break; - - /* use floating process */ - case 'f': - float_proc = 1; - break; - - /* long options */ - case 0: - l2fwd_usage(prgname); - return -1; - - default: - l2fwd_usage(prgname); - return -1; - } - } - - if (optind >= 0) - argv[optind-1] = prgname; - - if (!has_pmask) { - l2fwd_usage(prgname); - return -1; - } - ret = optind-1; - optind = 1; /* reset getopt lib */ - return ret; -} - -/* Check the link status of all ports in up to 9s, and print them finally */ -static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) -{ -#define CHECK_INTERVAL 100 /* 100ms */ -#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ - uint16_t portid; - uint8_t count, all_ports_up, print_flag = 0; - struct rte_eth_link link; - - printf("\nChecking link status"); - fflush(stdout); - for (count = 0; count <= MAX_CHECK_TIME; count++) { - all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { - if ((port_mask & (1 << portid)) == 0) - continue; - memset(&link, 0, sizeof(link)); - rte_eth_link_get_nowait(portid, &link); - /* print link status if flag set */ - if (print_flag == 1) { - if (link.link_status) - printf( - "Port%d Link Up- speed %u Mbps- %s\n", - portid, link.link_speed, - (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? - ("full-duplex") : ("half-duplex\n")); - else - printf("Port %d Link Down\n", portid); - continue; - } - /* clear all_ports_up flag if any link down */ - if (link.link_status == ETH_LINK_DOWN) { - all_ports_up = 0; - break; - } - } - /* after finally printing all link status, get out */ - if (print_flag == 1) - break; - - if (all_ports_up == 0) { - printf("."); - fflush(stdout); - rte_delay_ms(CHECK_INTERVAL); - } - - /* set the print_flag if all ports up or timeout */ - if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { - print_flag = 1; - printf("done\n"); - } - } -} - -int -main(int argc, char **argv) -{ - struct lcore_queue_conf *qconf; - int ret; - uint16_t nb_ports; - uint16_t nb_ports_available; - uint16_t portid, last_port; - unsigned rx_lcore_id; - unsigned nb_ports_in_mask = 0; - unsigned i; - uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; - - /* Save cpu_affinity first, restore it in case it's floating process option */ - if (get_cpu_affinity() != 0) - rte_exit(EXIT_FAILURE, "get_cpu_affinity error\n"); - - /* Also tries to set cpu affinity to detect whether it will fail in child process */ - if(clear_cpu_affinity() != 0) - rte_exit(EXIT_FAILURE, "clear_cpu_affinity error\n"); - - /* init EAL */ - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); - argc -= ret; - argv += ret; - - /* parse application arguments (after the EAL ones) */ - ret = l2fwd_parse_args(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); - - /*flib init */ - if (flib_init() != 0) - rte_exit(EXIT_FAILURE, "flib init error"); - - /** - * Allocated structures that slave lcore would change. For those that slaves are - * read only, needn't use malloc to share and global or static variables is ok since - * slave inherit all the knowledge that master initialized. - **/ - if (l2fwd_malloc_shared_struct() != 0) - rte_exit(EXIT_FAILURE, "malloc mem failed\n"); - - /* Initialize lcore_resource structures */ - memset(lcore_resource, 0, sizeof(lcore_resource)); - for (i = 0; i < RTE_MAX_LCORE; i++) - lcore_resource[i].lcore_id = i; - - nb_ports = rte_eth_dev_count(); - if (nb_ports == 0) - rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); - - /* create the mbuf pool */ - for (portid = 0; portid < nb_ports; portid++) { - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - char buf_name[RTE_MEMPOOL_NAMESIZE]; - snprintf(buf_name, RTE_MEMPOOL_NAMESIZE, MBUF_NAME, portid); - l2fwd_pktmbuf_pool[portid] = - rte_pktmbuf_pool_create(buf_name, NB_MBUF, 32, - 0, MBUF_DATA_SIZE, rte_socket_id()); - if (l2fwd_pktmbuf_pool[portid] == NULL) - rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); - - printf("Create mbuf %s\n", buf_name); - } - - /* reset l2fwd_dst_ports */ - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) - l2fwd_dst_ports[portid] = 0; - last_port = 0; - - /* - * Each logical core is assigned a dedicated TX queue on each port. - */ - for (portid = 0; portid < nb_ports; portid++) { - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - - if (nb_ports_in_mask % 2) { - l2fwd_dst_ports[portid] = last_port; - l2fwd_dst_ports[last_port] = portid; - } - else - last_port = portid; - - nb_ports_in_mask++; - } - if (nb_ports_in_mask % 2) { - printf("Notice: odd number of ports in portmask.\n"); - l2fwd_dst_ports[last_port] = last_port; - } - - rx_lcore_id = 0; - qconf = NULL; - - /* Initialize the port/queue configuration of each logical core */ - for (portid = 0; portid < nb_ports; portid++) { - struct lcore_resource_struct *res; - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - - /* get the lcore_id for this port */ - /* skip master lcore */ - while (rte_lcore_is_enabled(rx_lcore_id) == 0 || - rte_get_master_lcore() == rx_lcore_id || - lcore_queue_conf[rx_lcore_id].n_rx_port == - l2fwd_rx_queue_per_lcore) { - - rx_lcore_id++; - if (rx_lcore_id >= RTE_MAX_LCORE) - rte_exit(EXIT_FAILURE, "Not enough cores\n"); - } - - if (qconf != &lcore_queue_conf[rx_lcore_id]) - /* Assigned a new logical core in the loop above. */ - qconf = &lcore_queue_conf[rx_lcore_id]; - - qconf->rx_port_list[qconf->n_rx_port] = portid; - qconf->n_rx_port++; - - /* Save the port resource info into lcore_resource strucutres */ - res = &lcore_resource[rx_lcore_id]; - res->enabled = 1; - res->port[res->port_num++] = portid; - - printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned) portid); - } - - nb_ports_available = nb_ports; - - /* Initialise each port */ - for (portid = 0; portid < nb_ports; portid++) { - struct rte_eth_rxconf rxq_conf; - struct rte_eth_txconf txq_conf; - struct rte_eth_conf local_port_conf = port_conf; - - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { - printf("Skipping disabled port %u\n", (unsigned) portid); - nb_ports_available--; - continue; - } - /* init port */ - printf("Initializing port %u... ", (unsigned) portid); - fflush(stdout); - rte_eth_dev_info_get(portid, &dev_info); - if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) - local_port_conf.txmode.offloads |= - DEV_TX_OFFLOAD_MBUF_FAST_FREE; - ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", - ret, (unsigned) portid); - - ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, - &nb_txd); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "rte_eth_dev_adjust_nb_rx_tx_desc: err=%d, port=%u\n", - ret, (unsigned) portid); - - rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); - - /* init one RX queue */ - fflush(stdout); - rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = local_port_conf.rxmode.offloads; - ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, - rte_eth_dev_socket_id(portid), - &rxq_conf, - l2fwd_pktmbuf_pool[portid]); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", - ret, (unsigned) portid); - - /* init one TX queue on each port */ - fflush(stdout); - txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; - txq_conf.tx_offloads = local_port_conf.txmode.offloads; - ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, - rte_eth_dev_socket_id(portid), - &txq_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", - ret, (unsigned) portid); - - /* Initialize TX buffers */ - tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", - RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, - rte_eth_dev_socket_id(portid)); - if (tx_buffer[portid] == NULL) - rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", - (unsigned) portid); - - rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); - - ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], - rte_eth_tx_buffer_count_callback, - &port_statistics[portid].dropped); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot set error callback for " - "tx buffer on port %u\n", (unsigned) portid); - - /* Start device */ - ret = rte_eth_dev_start(portid); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", - ret, (unsigned) portid); - - printf("done: \n"); - - rte_eth_promiscuous_enable(portid); - - printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", - (unsigned) portid, - l2fwd_ports_eth_addr[portid].addr_bytes[0], - l2fwd_ports_eth_addr[portid].addr_bytes[1], - l2fwd_ports_eth_addr[portid].addr_bytes[2], - l2fwd_ports_eth_addr[portid].addr_bytes[3], - l2fwd_ports_eth_addr[portid].addr_bytes[4], - l2fwd_ports_eth_addr[portid].addr_bytes[5]); - - /* initialize port stats */ - //memset(&port_statistics, 0, sizeof(port_statistics)); - } - - if (!nb_ports_available) { - rte_exit(EXIT_FAILURE, - "All available ports are disabled. Please set portmask.\n"); - } - - check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); - - /* Record pair lcore */ - /** - * Since l2fwd example would create pair between different neighbour port, that's - * port 0 receive and forward to port 1, the same to port 1, these 2 ports will have - * dependency. If one port stopped working (killed, for example), the port need to - * be stopped/started again. During the time, another port need to wait until stop/start - * procedure completed. So, record the pair relationship for those lcores working - * on ports. - **/ - for (portid = 0; portid < nb_ports; portid++) { - uint32_t pair_port; - unsigned lcore = 0, pair_lcore = 0; - unsigned j, find_lcore, find_pair_lcore; - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - - /* Find pair ports' lcores */ - find_lcore = find_pair_lcore = 0; - pair_port = l2fwd_dst_ports[portid]; - for (i = 0; i < RTE_MAX_LCORE; i++) { - if (!rte_lcore_is_enabled(i)) - continue; - for (j = 0; j < lcore_queue_conf[i].n_rx_port;j++) { - if (lcore_queue_conf[i].rx_port_list[j] == portid) { - lcore = i; - find_lcore = 1; - break; - } - if (lcore_queue_conf[i].rx_port_list[j] == pair_port) { - pair_lcore = i; - find_pair_lcore = 1; - break; - } - } - if (find_lcore && find_pair_lcore) - break; - } - if (!find_lcore || !find_pair_lcore) - rte_exit(EXIT_FAILURE, "Not find port=%d pair\n", portid); - - printf("lcore %u and %u paired\n", lcore, pair_lcore); - lcore_resource[lcore].pair_id = pair_lcore; - lcore_resource[pair_lcore].pair_id = lcore; - } - - /* Create message buffer for all master and slave */ - message_pool = rte_mempool_create("ms_msg_pool", - NB_CORE_MSGBUF * RTE_MAX_LCORE, - sizeof(enum l2fwd_cmd), NB_CORE_MSGBUF / 2, - 0, NULL, NULL, NULL, NULL, rte_socket_id(), 0); - - if (message_pool == NULL) - rte_exit(EXIT_FAILURE, "Create msg mempool failed\n"); - - /* Create ring for each master and slave pair, also register cb when slave leaves */ - for (i = 0; i < RTE_MAX_LCORE; i++) { - /** - * Only create ring and register slave_exit cb in case that core involved into - * packet forwarding - **/ - if (lcore_resource[i].enabled) { - /* Create ring for master and slave communication */ - ret = create_ms_ring(i); - if (ret != 0) - rte_exit(EXIT_FAILURE, "Create ring for lcore=%u failed", - i); - - if (flib_register_slave_exit_notify(i, - slave_exit_cb) != 0) - rte_exit(EXIT_FAILURE, - "Register master_trace_slave_exit failed"); - } - } - - /* launch per-lcore init on every lcore except master */ - flib_mp_remote_launch(l2fwd_launch_one_lcore, NULL, SKIP_MASTER); - - /* print statistics 10 second */ - prev_tsc = cur_tsc = rte_rdtsc(); - timer_tsc = 0; - while (1) { - sleep(1); - cur_tsc = rte_rdtsc(); - diff_tsc = cur_tsc - prev_tsc; - /* if timer is enabled */ - if (timer_period > 0) { - - /* advance the timer */ - timer_tsc += diff_tsc; - - /* if timer has reached its timeout */ - if (unlikely(timer_tsc >= (uint64_t) timer_period)) { - - print_stats(); - /* reset the timer */ - timer_tsc = 0; - } - } - - prev_tsc = cur_tsc; - - /* Check any slave need restart or recreate */ - rte_spinlock_lock(&res_lock); - for (i = 0; i < RTE_MAX_LCORE; i++) { - struct lcore_resource_struct *res = &lcore_resource[i]; - struct lcore_resource_struct *pair = &lcore_resource[res->pair_id]; - - /* If find slave exited, try to reset pair */ - if (res->enabled && res->flags && pair->enabled) { - if (!pair->flags) { - master_sendcmd_with_ack(pair->lcore_id, CMD_STOP); - rte_spinlock_unlock(&res_lock); - sleep(1); - rte_spinlock_lock(&res_lock); - if (pair->flags) - continue; - } - if (reset_pair(res->lcore_id, pair->lcore_id) != 0) - rte_exit(EXIT_FAILURE, "failed to reset slave"); - res->flags = 0; - pair->flags = 0; - } - } - rte_spinlock_unlock(&res_lock); - } - -} diff --git a/examples/multi_process/meson.build b/examples/multi_process/meson.build new file mode 100644 index 00000000..c370d747 --- /dev/null +++ b/examples/multi_process/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +# Example app currently unsupported by meson build +build = false diff --git a/examples/multi_process/symmetric_mp/main.c b/examples/multi_process/symmetric_mp/main.c index 1ada4ef5..c6c6a537 100644 --- a/examples/multi_process/symmetric_mp/main.c +++ b/examples/multi_process/symmetric_mp/main.c @@ -115,7 +115,7 @@ smp_parse_args(int argc, char **argv) int opt, ret; char **argvopt; int option_index; - unsigned i, port_mask = 0; + uint16_t i, port_mask = 0; char *prgname = argv[0]; static struct option lgopts[] = { {PARAM_NUM_PROCS, 1, 0, 0}, @@ -156,7 +156,7 @@ smp_parse_args(int argc, char **argv) smp_usage(prgname, "Invalid or missing port mask\n"); /* get the port numbers from the port mask */ - for(i = 0; i < rte_eth_dev_count(); i++) + RTE_ETH_FOREACH_DEV(i) if(port_mask & (1 << i)) ports[num_ports++] = (uint8_t)i; @@ -178,7 +178,6 @@ smp_port_init(uint16_t port, struct rte_mempool *mbuf_pool, .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -200,11 +199,12 @@ smp_port_init(uint16_t port, struct rte_mempool *mbuf_pool, uint16_t q; uint16_t nb_rxd = RX_RING_SIZE; uint16_t nb_txd = TX_RING_SIZE; + uint64_t rss_hf_tmp; if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; printf("# Initialising port %u... ", port); @@ -216,6 +216,17 @@ smp_port_init(uint16_t port, struct rte_mempool *mbuf_pool, if (info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + rss_hf_tmp = port_conf.rx_adv_conf.rss_conf.rss_hf; + port_conf.rx_adv_conf.rss_conf.rss_hf &= info.flow_type_rss_offloads; + if (port_conf.rx_adv_conf.rss_conf.rss_hf != rss_hf_tmp) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + rss_hf_tmp, + port_conf.rx_adv_conf.rss_conf.rss_hf); + } + retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval < 0) return retval; @@ -236,7 +247,6 @@ smp_port_init(uint16_t port, struct rte_mempool *mbuf_pool, } txq_conf = info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = port_conf.txmode.offloads; for (q = 0; q < tx_rings; q ++) { retval = rte_eth_tx_queue_setup(port, q, nb_txd, @@ -418,7 +428,7 @@ main(int argc, char **argv) argv += ret; /* determine the NIC devices available */ - if (rte_eth_dev_count() == 0) + if (rte_eth_dev_count_avail() == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); /* parse application arguments (those after the EAL ones) */ diff --git a/examples/netmap_compat/bridge/Makefile b/examples/netmap_compat/bridge/Makefile index a7c9c14a..856c847b 100644 --- a/examples/netmap_compat/bridge/Makefile +++ b/examples/netmap_compat/bridge/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +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: diff --git a/examples/netmap_compat/bridge/bridge.c b/examples/netmap_compat/bridge/bridge.c index 59c5e436..7afca28c 100644 --- a/examples/netmap_compat/bridge/bridge.c +++ b/examples/netmap_compat/bridge/bridge.c @@ -26,7 +26,6 @@ struct rte_eth_conf eth_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -236,7 +235,7 @@ int main(int argc, char *argv[]) if (ports.num == 0) rte_exit(EXIT_FAILURE, "no ports specified\n"); - if (rte_eth_dev_count() < 1) + if (rte_eth_dev_count_avail() < 1) rte_exit(EXIT_FAILURE, "Not enough ethernet ports available\n"); pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0, diff --git a/examples/netmap_compat/lib/compat_netmap.c b/examples/netmap_compat/lib/compat_netmap.c index af3dd223..0be0663e 100644 --- a/examples/netmap_compat/lib/compat_netmap.c +++ b/examples/netmap_compat/lib/compat_netmap.c @@ -708,7 +708,6 @@ rte_netmap_init_port(uint16_t portid, const struct rte_netmap_port_conf *conf) rxq_conf = dev_info.default_rxconf; rxq_conf.offloads = conf->eth_conf->rxmode.offloads; txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = conf->eth_conf->txmode.offloads; for (i = 0; i < conf->nr_tx_rings; i++) { ret = rte_eth_tx_queue_setup(portid, i, tx_slots, diff --git a/examples/netmap_compat/meson.build b/examples/netmap_compat/meson.build new file mode 100644 index 00000000..c370d747 --- /dev/null +++ b/examples/netmap_compat/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +# Example app currently unsupported by meson build +build = false diff --git a/examples/packet_ordering/main.c b/examples/packet_ordering/main.c index 97a58dda..149bfdd0 100644 --- a/examples/packet_ordering/main.c +++ b/examples/packet_ordering/main.c @@ -35,11 +35,7 @@ volatile uint8_t quit_signal; static struct rte_mempool *mbuf_pool; -static struct rte_eth_conf port_conf_default = { - .rxmode = { - .ignore_offload_bitfield = 1, - }, -}; +static struct rte_eth_conf port_conf_default; struct worker_thread_args { struct rte_ring *ring_in; @@ -211,11 +207,10 @@ flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count, static inline int free_tx_buffers(struct rte_eth_dev_tx_buffer *tx_buffer[]) { - const uint8_t nb_ports = rte_eth_dev_count(); - unsigned port_id; + uint16_t port_id; /* initialize buffers for all ports */ - for (port_id = 0; port_id < nb_ports; port_id++) { + RTE_ETH_FOREACH_DEV(port_id) { /* skip ports that are not enabled */ if ((portmask & (1 << port_id)) == 0) continue; @@ -228,12 +223,11 @@ free_tx_buffers(struct rte_eth_dev_tx_buffer *tx_buffer[]) { static inline int configure_tx_buffers(struct rte_eth_dev_tx_buffer *tx_buffer[]) { - const uint8_t nb_ports = rte_eth_dev_count(); - unsigned port_id; + uint16_t port_id; int ret; /* initialize buffers for all ports */ - for (port_id = 0; port_id < nb_ports; port_id++) { + RTE_ETH_FOREACH_DEV(port_id) { /* skip ports that are not enabled */ if ((portmask & (1 << port_id)) == 0) continue; @@ -263,7 +257,6 @@ configure_eth_port(uint16_t port_id) { struct ether_addr addr; const uint16_t rxRings = 1, txRings = 1; - const uint8_t nb_ports = rte_eth_dev_count(); int ret; uint16_t q; uint16_t nb_rxd = RX_DESC_PER_QUEUE; @@ -272,7 +265,7 @@ configure_eth_port(uint16_t port_id) struct rte_eth_txconf txconf; struct rte_eth_conf port_conf = port_conf_default; - if (port_id > nb_ports) + if (!rte_eth_dev_is_valid_port(port_id)) return -1; rte_eth_dev_info_get(port_id, &dev_info); @@ -296,7 +289,6 @@ configure_eth_port(uint16_t port_id) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; for (q = 0; q < txRings; q++) { ret = rte_eth_tx_queue_setup(port_id, q, nb_txd, @@ -325,8 +317,7 @@ configure_eth_port(uint16_t port_id) static void print_stats(void) { - const uint8_t nb_ports = rte_eth_dev_count(); - unsigned i; + uint16_t i; struct rte_eth_stats eth_stats; printf("\nRX thread stats:\n"); @@ -355,7 +346,7 @@ print_stats(void) printf(" - Pkts tx failed w/o reorder: %"PRIu64"\n", app_stats.tx.early_pkts_tx_failed_woro); - for (i = 0; i < nb_ports; i++) { + RTE_ETH_FOREACH_DEV(i) { rte_eth_stats_get(i, ð_stats); printf("\nPort %u stats:\n", i); printf(" - Pkts in: %"PRIu64"\n", eth_stats.ipackets); @@ -383,7 +374,6 @@ int_handler(int sig_num) static int rx_thread(struct rte_ring *ring_out) { - const uint8_t nb_ports = rte_eth_dev_count(); uint32_t seqn = 0; uint16_t i, ret = 0; uint16_t nb_rx_pkts; @@ -395,7 +385,7 @@ rx_thread(struct rte_ring *ring_out) while (!quit_signal) { - for (port_id = 0; port_id < nb_ports; port_id++) { + RTE_ETH_FOREACH_DEV(port_id) { if ((portmask & (1 << port_id)) != 0) { /* receive packets */ @@ -435,7 +425,7 @@ rx_thread(struct rte_ring *ring_out) static int worker_thread(void *args_ptr) { - const uint8_t nb_ports = rte_eth_dev_count(); + const uint16_t nb_ports = rte_eth_dev_count_avail(); uint16_t i, ret = 0; uint16_t burst_size = 0; struct worker_thread_args *args; @@ -649,7 +639,7 @@ main(int argc, char **argv) "1 lcore for packet TX\n" "and at least 1 lcore for worker threads\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n"); if (nb_ports != 1 && (nb_ports & 1)) @@ -665,7 +655,7 @@ main(int argc, char **argv) nb_ports_available = nb_ports; /* initialize all ports */ - for (port_id = 0; port_id < nb_ports; port_id++) { + RTE_ETH_FOREACH_DEV(port_id) { /* skip ports that are not enabled */ if ((portmask & (1 << port_id)) == 0) { printf("\nSkipping disabled port %d\n", port_id); diff --git a/examples/performance-thread/common/arch/x86/ctx.c b/examples/performance-thread/common/arch/x86/ctx.c index 1e8e2717..d63fd9fc 100644 --- a/examples/performance-thread/common/arch/x86/ctx.c +++ b/examples/performance-thread/common/arch/x86/ctx.c @@ -1,65 +1,9 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /* - * https://github.com/halayli/lthread which carries the following license. - * - * Copyright (C) 2012, Hasan Alayli <halayli@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2012 Hasan Alayli <halayli@gmail.com> */ - - #if defined(__x86_64__) __asm__ ( ".text\n" diff --git a/examples/performance-thread/common/lthread.c b/examples/performance-thread/common/lthread.c index 7d76c8c4..3f1f48db 100644 --- a/examples/performance-thread/common/lthread.c +++ b/examples/performance-thread/common/lthread.c @@ -1,62 +1,7 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /* - * Some portions of this software is derived from the - * https://github.com/halayli/lthread which carrys the following license. - * - * Copyright (C) 2012, Hasan Alayli <halayli@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2012 Hasan Alayli <halayli@gmail.com> */ #define RTE_MEM 1 @@ -320,13 +265,14 @@ struct lthread *lthread_current(void) /* * Tasklet to cancel a thread */ -static void +static void * _cancel(void *arg) { struct lthread *lt = (struct lthread *) arg; lt->state |= BIT(ST_LT_CANCELLED); lthread_detach(); + return NULL; } diff --git a/examples/performance-thread/common/lthread.h b/examples/performance-thread/common/lthread.h index 0cde5919..4c945cf7 100644 --- a/examples/performance-thread/common/lthread.h +++ b/examples/performance-thread/common/lthread.h @@ -1,64 +1,8 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /* - * Some portions of this software is derived from the - * https://github.com/halayli/lthread which carrys the following license. - * - * Copyright (C) 2012, Hasan Alayli <halayli@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2012 Hasan Alayli <halayli@gmail.com> */ - #ifndef LTHREAD_H_ #define LTHREAD_H_ diff --git a/examples/performance-thread/common/lthread_api.h b/examples/performance-thread/common/lthread_api.h index ff245a08..995deb4d 100644 --- a/examples/performance-thread/common/lthread_api.h +++ b/examples/performance-thread/common/lthread_api.h @@ -1,64 +1,8 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /* - * Some portions of this software may have been derived from the - * https://github.com/halayli/lthread which carrys the following license. - * - * Copyright (C) 2012, Hasan Alayli <halayli@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2012 Hasan Alayli <halayli@gmail.com> */ - /** * @file lthread_api.h * @@ -143,7 +87,7 @@ struct lthread_mutex; struct lthread_condattr; struct lthread_mutexattr; -typedef void (*lthread_func_t) (void *); +typedef void *(*lthread_func_t) (void *); /* * Define the size of stack for an lthread diff --git a/examples/performance-thread/common/lthread_cond.c b/examples/performance-thread/common/lthread_cond.c index 96fcce04..cdcc7a7b 100644 --- a/examples/performance-thread/common/lthread_cond.c +++ b/examples/performance-thread/common/lthread_cond.c @@ -1,62 +1,7 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /* - * Some portions of this software may have been derived from the - * https://github.com/halayli/lthread which carrys the following license. - * - * Copyright (C) 2012, Hasan Alayli <halayli@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2012 Hasan Alayli <halayli@gmail.com> */ #include <stdio.h> diff --git a/examples/performance-thread/common/lthread_cond.h b/examples/performance-thread/common/lthread_cond.h index 5e5f14be..616a55c4 100644 --- a/examples/performance-thread/common/lthread_cond.h +++ b/examples/performance-thread/common/lthread_cond.h @@ -1,62 +1,7 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /* - * Some portions of this software may have been derived from the - * https://github.com/halayli/lthread which carrys the following license. - * - * Copyright (C) 2012, Hasan Alayli <halayli@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2012 Hasan Alayli <halayli@gmail.com> */ #ifndef LTHREAD_COND_H_ diff --git a/examples/performance-thread/common/lthread_int.h b/examples/performance-thread/common/lthread_int.h index e1da2462..a352f13b 100644 --- a/examples/performance-thread/common/lthread_int.h +++ b/examples/performance-thread/common/lthread_int.h @@ -1,62 +1,7 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /* - * Some portions of this software may have been derived from the - * https://github.com/halayli/lthread which carrys the following license. - * - * Copyright (C) 2012, Hasan Alayli <halayli@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2012 Hasan Alayli <halayli@gmail.com> */ #ifndef LTHREAD_INT_H #define LTHREAD_INT_H diff --git a/examples/performance-thread/common/lthread_pool.h b/examples/performance-thread/common/lthread_pool.h index 315a2e21..6f93775f 100644 --- a/examples/performance-thread/common/lthread_pool.h +++ b/examples/performance-thread/common/lthread_pool.h @@ -1,69 +1,7 @@ /* - *- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Some portions of this software is derived from the producer - * consumer queues described by Dmitry Vyukov and published here - * http://www.1024cores.net - * - * Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY VYUKOV OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are - * those of the authors and should not be interpreted as representing official - * policies, either expressed or implied, of Dmitry Vyukov. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2010-2011 Dmitry Vyukov */ #ifndef LTHREAD_POOL_H_ diff --git a/examples/performance-thread/common/lthread_queue.h b/examples/performance-thread/common/lthread_queue.h index 833ed92b..5b63ba22 100644 --- a/examples/performance-thread/common/lthread_queue.h +++ b/examples/performance-thread/common/lthread_queue.h @@ -1,69 +1,7 @@ /* - *- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Some portions of this software is derived from the producer - * consumer queues described by Dmitry Vyukov and published here - * http://www.1024cores.net - * - * Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY VYUKOV OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are - * those of the authors and should not be interpreted as representing official - * policies, either expressed or implied, of Dmitry Vyukov. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2010-2011 Dmitry Vyukov */ #ifndef LTHREAD_QUEUE_H_ diff --git a/examples/performance-thread/common/lthread_sched.c b/examples/performance-thread/common/lthread_sched.c index 779aeb17..38ca0c45 100644 --- a/examples/performance-thread/common/lthread_sched.c +++ b/examples/performance-thread/common/lthread_sched.c @@ -1,65 +1,9 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /* - * Some portions of this software is derived from the - * https://github.com/halayli/lthread which carrys the following license. - * - * Copyright (C) 2012, Hasan Alayli <halayli@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2012 Hasan Alayli <halayli@gmail.com> */ - #define RTE_MEM 1 #include <stdio.h> diff --git a/examples/performance-thread/common/lthread_sched.h b/examples/performance-thread/common/lthread_sched.h index aa2f0c48..d14bec1c 100644 --- a/examples/performance-thread/common/lthread_sched.h +++ b/examples/performance-thread/common/lthread_sched.h @@ -1,62 +1,7 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /* - * Some portions of this software is derived from the - * https://github.com/halayli/lthread which carrys the following license. - * - * Copyright (C) 2012, Hasan Alayli <halayli@gmail.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2012 Hasan Alayli <halayli@gmail.com> */ #ifndef LTHREAD_SCHED_H_ diff --git a/examples/performance-thread/l3fwd-thread/main.c b/examples/performance-thread/l3fwd-thread/main.c index c04294cf..5392fcea 100644 --- a/examples/performance-thread/l3fwd-thread/main.c +++ b/examples/performance-thread/l3fwd-thread/main.c @@ -306,7 +306,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -1990,17 +1989,18 @@ cpu_load_collector(__rte_unused void *arg) { * * This loop is used to start empty scheduler on lcore. */ -static void +static void * lthread_null(__rte_unused void *args) { int lcore_id = rte_lcore_id(); RTE_LOG(INFO, L3FWD, "Starting scheduler on lcore %d.\n", lcore_id); lthread_exit(NULL); + return NULL; } /* main processing loop */ -static void +static void * lthread_tx_per_ring(void *dummy) { int nb_rx; @@ -2045,6 +2045,7 @@ lthread_tx_per_ring(void *dummy) lthread_cond_wait(ready, 0); } + return NULL; } /* @@ -2053,7 +2054,7 @@ lthread_tx_per_ring(void *dummy) * This lthread is used to spawn one new lthread per ring from producers. * */ -static void +static void * lthread_tx(void *args) { struct lthread *lt; @@ -2098,9 +2099,10 @@ lthread_tx(void *args) } } + return NULL; } -static void +static void * lthread_rx(void *dummy) { int ret; @@ -2124,7 +2126,7 @@ lthread_rx(void *dummy) if (rx_conf->n_rx_queue == 0) { RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", rte_lcore_id()); - return; + return NULL; } RTE_LOG(INFO, L3FWD, "Entering main Rx loop on lcore %u\n", rte_lcore_id()); @@ -2196,6 +2198,7 @@ lthread_rx(void *dummy) lthread_yield(); } } + return NULL; } /* @@ -2204,8 +2207,9 @@ lthread_rx(void *dummy) * This lthread loop spawns all rx and tx lthreads on master lcore */ -static void -lthread_spawner(__rte_unused void *arg) { +static void * +lthread_spawner(__rte_unused void *arg) +{ struct lthread *lt[MAX_THREAD]; int i; int n_thread = 0; @@ -2246,6 +2250,7 @@ lthread_spawner(__rte_unused void *arg) { for (i = 0; i < n_thread; i++) lthread_join(lt[i], NULL); + return NULL; } /* @@ -2491,7 +2496,7 @@ check_lcore_params(void) } static int -check_port_config(const unsigned nb_ports) +check_port_config(void) { unsigned portid; uint16_t i; @@ -2502,7 +2507,7 @@ check_port_config(const unsigned nb_ports) printf("port %u is not enabled in port mask\n", portid); return -1; } - if (portid >= nb_ports) { + if (!rte_eth_dev_is_valid_port(portid)) { printf("port %u is not present on the board\n", portid); return -1; } @@ -3411,7 +3416,7 @@ init_mem(unsigned nb_mbuf) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -3423,7 +3428,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -3514,15 +3519,15 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "init_rx_rings failed\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); - if (check_port_config(nb_ports) < 0) + if (check_port_config() < 0) rte_exit(EXIT_FAILURE, "check_port_config failed\n"); nb_lcores = rte_lcore_count(); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_conf local_port_conf = port_conf; /* skip ports that are not enabled */ @@ -3545,6 +3550,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) @@ -3591,7 +3608,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); @@ -3654,7 +3670,7 @@ main(int argc, char **argv) printf("\n"); /* start ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) continue; @@ -3699,7 +3715,7 @@ main(int argc, char **argv) } } - check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask); + check_all_ports_link_status(enabled_port_mask); if (lthreads_on) { printf("Starting L-Threading Model\n"); diff --git a/examples/performance-thread/meson.build b/examples/performance-thread/meson.build new file mode 100644 index 00000000..c370d747 --- /dev/null +++ b/examples/performance-thread/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +# Example app currently unsupported by meson build +build = false diff --git a/examples/performance-thread/pthread_shim/main.c b/examples/performance-thread/pthread_shim/main.c index 964ea252..7d0d5811 100644 --- a/examples/performance-thread/pthread_shim/main.c +++ b/examples/performance-thread/pthread_shim/main.c @@ -119,8 +119,7 @@ void *helloworld_pthread(void *arg) */ __thread pthread_t tid[HELLOW_WORLD_MAX_LTHREADS]; -static void initial_lthread(void *args); -static void initial_lthread(void *args __attribute__((unused))) +static void *initial_lthread(void *args __attribute__((unused))) { int lcore = (int) rte_lcore_id(); /* @@ -195,6 +194,7 @@ static void initial_lthread(void *args __attribute__((unused))) /* shutdown the lthread scheduler */ lthread_scheduler_shutdown(rte_lcore_id()); lthread_detach(); + return NULL; } @@ -205,8 +205,6 @@ static void initial_lthread(void *args __attribute__((unused))) * in the core mask */ static int -lthread_scheduler(void *args); -static int lthread_scheduler(void *args __attribute__((unused))) { /* create initial thread */ diff --git a/examples/performance-thread/pthread_shim/pthread_shim.c b/examples/performance-thread/pthread_shim/pthread_shim.c index c31de4e9..53f12437 100644 --- a/examples/performance-thread/pthread_shim/pthread_shim.c +++ b/examples/performance-thread/pthread_shim/pthread_shim.c @@ -365,7 +365,7 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) int pthread_create(pthread_t *__restrict tid, const pthread_attr_t *__restrict attr, - void *(func) (void *), + lthread_func_t func, void *__restrict arg) { if (override) { @@ -390,7 +390,7 @@ pthread_create(pthread_t *__restrict tid, } } return lthread_create((struct lthread **)tid, lcore, - (void (*)(void *))func, arg); + func, arg); } return _sys_pthread_funcs.f_pthread_create(tid, attr, func, arg); } diff --git a/examples/ptpclient/ptpclient.c b/examples/ptpclient/ptpclient.c index 83821eb8..82ae71c1 100644 --- a/examples/ptpclient/ptpclient.c +++ b/examples/ptpclient/ptpclient.c @@ -50,7 +50,6 @@ static uint8_t ptp_enabled_ports[RTE_MAX_ETHPORTS]; static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; @@ -187,7 +186,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) uint16_t nb_rxd = RX_RING_SIZE; uint16_t nb_txd = TX_RING_SIZE; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; rte_eth_dev_info_get(port, &dev_info); @@ -217,11 +216,9 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { - /* Setup txq_flags */ struct rte_eth_txconf *txconf; txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = port_conf.txmode.offloads; retval = rte_eth_tx_queue_setup(port, q, nb_txd, @@ -727,7 +724,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Error with PTP initialization\n"); /* Check that there is an even number of ports to send/receive on. */ - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); /* Creates a new mempool in memory to hold the mbufs. */ mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, @@ -737,7 +734,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* Initialize all ports. */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((ptp_enabled_port_mask & (1 << portid)) != 0) { if (port_init(portid, mbuf_pool) == 0) { ptp_enabled_ports[ptp_enabled_port_nb] = portid; diff --git a/examples/qos_meter/Makefile b/examples/qos_meter/Makefile index 69ac6617..46341b1a 100644 --- a/examples/qos_meter/Makefile +++ b/examples/qos_meter/Makefile @@ -23,6 +23,8 @@ CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) +CFLAGS += -DALLOW_EXPERIMENTAL_API + build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) diff --git a/examples/qos_meter/main.c b/examples/qos_meter/main.c index f0f9bcaf..5cf4e9df 100644 --- a/examples/qos_meter/main.c +++ b/examples/qos_meter/main.c @@ -56,7 +56,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -90,14 +89,23 @@ static uint16_t port_tx; static struct rte_mbuf *pkts_rx[PKT_RX_BURST_MAX]; struct rte_eth_dev_tx_buffer *tx_buffer; -struct rte_meter_srtcm_params app_srtcm_params[] = { - {.cir = 1000000 * 46, .cbs = 2048, .ebs = 2048}, +struct rte_meter_srtcm_params app_srtcm_params = { + .cir = 1000000 * 46, + .cbs = 2048, + .ebs = 2048 }; -struct rte_meter_trtcm_params app_trtcm_params[] = { - {.cir = 1000000 * 46, .pir = 1500000 * 46, .cbs = 2048, .pbs = 2048}, +struct rte_meter_srtcm_profile app_srtcm_profile; + +struct rte_meter_trtcm_params app_trtcm_params = { + .cir = 1000000 * 46, + .pir = 1500000 * 46, + .cbs = 2048, + .pbs = 2048 }; +struct rte_meter_trtcm_profile app_trtcm_profile; + #define APP_FLOWS_MAX 256 FLOW_METER app_flows[APP_FLOWS_MAX]; @@ -105,12 +113,21 @@ FLOW_METER app_flows[APP_FLOWS_MAX]; static int app_configure_flow_table(void) { - uint32_t i, j; + uint32_t i; int ret; - for (i = 0, j = 0; i < APP_FLOWS_MAX; - i ++, j = (j + 1) % RTE_DIM(PARAMS)) { - ret = FUNC_CONFIG(&app_flows[i], &PARAMS[j]); + ret = rte_meter_srtcm_profile_config(&app_srtcm_profile, + &app_srtcm_params); + if (ret) + return ret; + + ret = rte_meter_trtcm_profile_config(&app_trtcm_profile, + &app_trtcm_params); + if (ret) + return ret; + + for (i = 0; i < APP_FLOWS_MAX; i++) { + ret = FUNC_CONFIG(&app_flows[i], &PROFILE); if (ret) return ret; } @@ -135,7 +152,10 @@ app_pkt_handle(struct rte_mbuf *pkt, uint64_t time) enum policer_action action; /* color input is not used for blind modes */ - output_color = (uint8_t) FUNC_METER(&app_flows[flow_id], time, pkt_len, + output_color = (uint8_t) FUNC_METER(&app_flows[flow_id], + &PROFILE, + time, + pkt_len, (enum rte_meter_color) input_color); /* Apply policing and set the output color */ @@ -312,6 +332,17 @@ main(int argc, char **argv) rte_eth_dev_info_get(port_rx, &dev_info); if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + conf.rx_adv_conf.rss_conf.rss_hf &= dev_info.flow_type_rss_offloads; + if (conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port_rx, + port_conf.rx_adv_conf.rss_conf.rss_hf, + conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(port_rx, 1, 1, &conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d configuration error (%d)\n", port_rx, ret); @@ -330,7 +361,6 @@ main(int argc, char **argv) rte_exit(EXIT_FAILURE, "Port %d RX queue setup error (%d)\n", port_rx, ret); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port_rx, NIC_TX_QUEUE, nb_txd, rte_eth_dev_socket_id(port_rx), @@ -342,6 +372,17 @@ main(int argc, char **argv) rte_eth_dev_info_get(port_tx, &dev_info); if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + conf.rx_adv_conf.rss_conf.rss_hf &= dev_info.flow_type_rss_offloads; + if (conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port_tx, + port_conf.rx_adv_conf.rss_conf.rss_hf, + conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(port_tx, 1, 1, &conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d configuration error (%d)\n", port_tx, ret); @@ -362,7 +403,6 @@ main(int argc, char **argv) rte_exit(EXIT_FAILURE, "Port %d RX queue setup error (%d)\n", port_tx, ret); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port_tx, NIC_TX_QUEUE, nb_txd, rte_eth_dev_socket_id(port_tx), diff --git a/examples/qos_meter/main.h b/examples/qos_meter/main.h index b27e8eb8..f51eb664 100644 --- a/examples/qos_meter/main.h +++ b/examples/qos_meter/main.h @@ -21,44 +21,52 @@ enum policer_action policer_table[e_RTE_METER_COLORS][e_RTE_METER_COLORS] = #if APP_MODE == APP_MODE_FWD -#define FUNC_METER(a,b,c,d) color, flow_id=flow_id, pkt_len=pkt_len, time=time +#define FUNC_METER(m, p, time, pkt_len, pkt_color) \ +({ \ + void *mp = m; \ + void *pp = p; \ + mp = mp; \ + pp = pp; \ + time = time; \ + pkt_len = pkt_len; \ + pkt_color; \ +}) #define FUNC_CONFIG(a, b) 0 -#define PARAMS app_srtcm_params #define FLOW_METER int +#define PROFILE app_srtcm_profile #elif APP_MODE == APP_MODE_SRTCM_COLOR_BLIND -#define FUNC_METER(a,b,c,d) rte_meter_srtcm_color_blind_check(a,b,c) +#define FUNC_METER(m, p, time, pkt_len, pkt_color) \ + rte_meter_srtcm_color_blind_check(m, p, time, pkt_len) #define FUNC_CONFIG rte_meter_srtcm_config -#define PARAMS app_srtcm_params #define FLOW_METER struct rte_meter_srtcm +#define PROFILE app_srtcm_profile #elif (APP_MODE == APP_MODE_SRTCM_COLOR_AWARE) #define FUNC_METER rte_meter_srtcm_color_aware_check #define FUNC_CONFIG rte_meter_srtcm_config -#define PARAMS app_srtcm_params #define FLOW_METER struct rte_meter_srtcm +#define PROFILE app_srtcm_profile #elif (APP_MODE == APP_MODE_TRTCM_COLOR_BLIND) -#define FUNC_METER(a,b,c,d) rte_meter_trtcm_color_blind_check(a,b,c) +#define FUNC_METER(m, p, time, pkt_len, pkt_color) \ + rte_meter_trtcm_color_blind_check(m, p, time, pkt_len) #define FUNC_CONFIG rte_meter_trtcm_config -#define PARAMS app_trtcm_params #define FLOW_METER struct rte_meter_trtcm +#define PROFILE app_trtcm_profile #elif (APP_MODE == APP_MODE_TRTCM_COLOR_AWARE) -#define FUNC_METER rte_meter_trtcm_color_aware_check +#define FUNC_METER rte_meter_trtcm_color_aware_check #define FUNC_CONFIG rte_meter_trtcm_config -#define PARAMS app_trtcm_params #define FLOW_METER struct rte_meter_trtcm +#define PROFILE app_trtcm_profile #else #error Invalid value for APP_MODE #endif - - - #endif /* _MAIN_H_ */ diff --git a/examples/qos_sched/Makefile b/examples/qos_sched/Makefile index 0f0a31ff..a7ecf978 100644 --- a/examples/qos_sched/Makefile +++ b/examples/qos_sched/Makefile @@ -48,7 +48,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +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: diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index 8914f766..94cbb26f 100644 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -59,7 +59,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -96,7 +95,6 @@ app_init_port(uint16_t portid, struct rte_mempool *mp) tx_conf.tx_free_thresh = 0; tx_conf.tx_rs_thresh = 0; tx_conf.tx_deferred_start = 0; - tx_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; /* init port */ RTE_LOG(INFO, APP, "Initializing port %"PRIu16"... ", portid); @@ -298,7 +296,7 @@ int app_init(void) char ring_name[MAX_NAME_LEN]; char pool_name[MAX_NAME_LEN]; - if (rte_eth_dev_count() == 0) + if (rte_eth_dev_count_avail() == 0) rte_exit(EXIT_FAILURE, "No Ethernet port - bye\n"); /* load configuration profile */ diff --git a/examples/quota_watermark/meson.build b/examples/quota_watermark/meson.build new file mode 100644 index 00000000..c370d747 --- /dev/null +++ b/examples/quota_watermark/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +# Example app currently unsupported by meson build +build = false diff --git a/examples/quota_watermark/qw/init.c b/examples/quota_watermark/qw/init.c index d4a69183..19164385 100644 --- a/examples/quota_watermark/qw/init.c +++ b/examples/quota_watermark/qw/init.c @@ -24,7 +24,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -82,7 +81,6 @@ void configure_eth_port(uint16_t port_id) /* Initialize the port's TX queue */ txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd, rte_eth_dev_socket_id(port_id), @@ -112,7 +110,7 @@ void configure_eth_port(uint16_t port_id) void init_dpdk(void) { - if (rte_eth_dev_count() < 2) + if (rte_eth_dev_count_avail() < 2) rte_exit(EXIT_FAILURE, "Not enough ethernet port available\n"); } diff --git a/examples/quota_watermark/qw/main.c b/examples/quota_watermark/qw/main.c index 313216f3..c55d3874 100644 --- a/examples/quota_watermark/qw/main.c +++ b/examples/quota_watermark/qw/main.c @@ -181,7 +181,7 @@ receive_stage(__attribute__((unused)) void *args) } } -static void +static int pipeline_stage(__attribute__((unused)) void *args) { int i, ret; @@ -243,9 +243,11 @@ pipeline_stage(__attribute__((unused)) void *args) } } } + + return 0; } -static void +static int send_stage(__attribute__((unused)) void *args) { uint16_t nb_dq_pkts; @@ -287,6 +289,8 @@ send_stage(__attribute__((unused)) void *args) /* TODO: Check if nb_dq_pkts == nb_tx_pkts? */ } } + + return 0; } int @@ -346,15 +350,13 @@ main(int argc, char **argv) if (is_bit_set(port_id, portmask)) init_ring(lcore_id, port_id); - /* typecast is a workaround for GCC 4.3 bug */ - rte_eal_remote_launch((int (*)(void *))pipeline_stage, + rte_eal_remote_launch(pipeline_stage, NULL, lcore_id); } } /* Start send_stage() on the last slave core */ - /* typecast is a workaround for GCC 4.3 bug */ - rte_eal_remote_launch((int (*)(void *))send_stage, NULL, last_lcore_id); + rte_eal_remote_launch(send_stage, NULL, last_lcore_id); /* Start receive_stage() on the master core */ receive_stage(NULL); diff --git a/examples/rxtx_callbacks/main.c b/examples/rxtx_callbacks/main.c index d2e5e19e..2058be62 100644 --- a/examples/rxtx_callbacks/main.c +++ b/examples/rxtx_callbacks/main.c @@ -20,12 +20,9 @@ static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; -static unsigned nb_ports; - static struct { uint64_t total_cycles; uint64_t total_pkts; @@ -82,7 +79,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) struct rte_eth_dev_info dev_info; struct rte_eth_txconf txconf; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; rte_eth_dev_info_get(port, &dev_info); @@ -106,7 +103,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; for (q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port, q, nb_txd, @@ -145,7 +141,7 @@ lcore_main(void) { uint16_t port; - for (port = 0; port < nb_ports; port++) + RTE_ETH_FOREACH_DEV(port) if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != (int)rte_socket_id()) @@ -156,7 +152,7 @@ lcore_main(void) printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n", rte_lcore_id()); for (;;) { - for (port = 0; port < nb_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { struct rte_mbuf *bufs[BURST_SIZE]; const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); @@ -179,6 +175,7 @@ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool; + uint16_t nb_ports; uint16_t portid; /* init EAL */ @@ -189,7 +186,7 @@ main(int argc, char *argv[]) argc -= ret; argv += ret; - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports < 2 || (nb_ports & 1)) rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); @@ -200,7 +197,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) + RTE_ETH_FOREACH_DEV(portid) if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8"\n", portid); diff --git a/examples/server_node_efd/meson.build b/examples/server_node_efd/meson.build new file mode 100644 index 00000000..c370d747 --- /dev/null +++ b/examples/server_node_efd/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +# Example app currently unsupported by meson build +build = false diff --git a/examples/server_node_efd/node/node.c b/examples/server_node_efd/node/node.c index 84f7bcff..3b97fbd4 100644 --- a/examples/server_node_efd/node/node.c +++ b/examples/server_node_efd/node/node.c @@ -320,7 +320,7 @@ main(int argc, char *argv[]) if (parse_app_args(argc, argv) < 0) rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n"); - if (rte_eth_dev_count() == 0) + if (rte_eth_dev_count_avail() == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); rx_ring = rte_ring_lookup(get_rx_queue_name(node_id)); diff --git a/examples/server_node_efd/server/Makefile b/examples/server_node_efd/server/Makefile index cbb91ebe..df6614c6 100644 --- a/examples/server_node_efd/server/Makefile +++ b/examples/server_node_efd/server/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV), "linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif diff --git a/examples/server_node_efd/server/init.c b/examples/server_node_efd/server/init.c index 07b6882f..af5a18e2 100644 --- a/examples/server_node_efd/server/init.c +++ b/examples/server_node_efd/server/init.c @@ -97,7 +97,6 @@ init_port(uint16_t port_num) struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, - .ignore_offload_bitfield = 1, }, }; const uint16_t rx_rings = 1, tx_rings = num_nodes; @@ -139,7 +138,6 @@ init_port(uint16_t port_num) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; for (q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port_num, q, tx_ring_size, @@ -310,7 +308,7 @@ init(int argc, char *argv[]) argv += retval; /* get total number of ports */ - total_ports = rte_eth_dev_count(); + total_ports = rte_eth_dev_count_avail(); /* set up array for port data */ mz = rte_memzone_reserve(MZ_SHARED_INFO, sizeof(*info), diff --git a/examples/service_cores/Makefile b/examples/service_cores/Makefile index 3156e35d..a4d6b7b4 100644 --- a/examples/service_cores/Makefile +++ b/examples/service_cores/Makefile @@ -23,8 +23,6 @@ CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) -CFLAGS += -DALLOW_EXPERIMENTAL_API - build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) @@ -50,7 +48,6 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute diff --git a/examples/service_cores/meson.build b/examples/service_cores/meson.build index 2b0a2503..c34e11e3 100644 --- a/examples/service_cores/meson.build +++ b/examples/service_cores/meson.build @@ -6,7 +6,6 @@ # To build this example as a standalone application with an already-installed # DPDK instance, use 'make' -allow_experimental_apis = true sources = files( 'main.c' ) diff --git a/examples/skeleton/basicfwd.c b/examples/skeleton/basicfwd.c index e62cc0a5..4aba1dc3 100644 --- a/examples/skeleton/basicfwd.c +++ b/examples/skeleton/basicfwd.c @@ -20,7 +20,6 @@ static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; @@ -42,7 +41,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) struct rte_eth_dev_info dev_info; struct rte_eth_txconf txconf; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; rte_eth_dev_info_get(port, &dev_info); @@ -68,7 +67,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { @@ -106,14 +104,13 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) static __attribute__((noreturn)) void lcore_main(void) { - const uint16_t nb_ports = rte_eth_dev_count(); uint16_t port; /* * Check that the port is on the same NUMA node as the polling thread * for best performance. */ - for (port = 0; port < nb_ports; port++) + RTE_ETH_FOREACH_DEV(port) if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != (int)rte_socket_id()) @@ -130,7 +127,7 @@ lcore_main(void) * Receive packets on a port and forward them on the paired * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc. */ - for (port = 0; port < nb_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { /* Get burst of RX packets, from first port of pair. */ struct rte_mbuf *bufs[BURST_SIZE]; @@ -174,7 +171,7 @@ main(int argc, char *argv[]) argv += ret; /* Check that there is an even number of ports to send/receive on. */ - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); if (nb_ports < 2 || (nb_ports & 1)) rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); @@ -186,7 +183,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* Initialize all ports. */ - for (portid = 0; portid < nb_ports; portid++) + RTE_ETH_FOREACH_DEV(portid) if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu16 "\n", portid); diff --git a/examples/tep_termination/Makefile b/examples/tep_termination/Makefile index d2c357a1..8ec1a38e 100644 --- a/examples/tep_termination/Makefile +++ b/examples/tep_termination/Makefile @@ -25,6 +25,8 @@ CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) +CFLAGS += -DALLOW_EXPERIMENTAL_API + build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) @@ -50,11 +52,12 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif +CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) CFLAGS += -D_GNU_SOURCE diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c index 27073913..7795d089 100644 --- a/examples/tep_termination/main.c +++ b/examples/tep_termination/main.c @@ -515,11 +515,10 @@ check_ports_num(unsigned max_nb_ports) } for (portid = 0; portid < nb_ports; portid++) { - if (ports[portid] >= max_nb_ports) { + if (!rte_eth_dev_is_valid_port(ports[portid])) { RTE_LOG(INFO, VHOST_PORT, - "\nSpecified port ID(%u) exceeds max " - " system port ID(%u)\n", - ports[portid], (max_nb_ports - 1)); + "\nSpecified port ID(%u) is not valid\n", + ports[portid]); ports[portid] = INVALID_PORT_ID; valid_nb_ports--; } @@ -1062,8 +1061,8 @@ static const struct vhost_device_ops virtio_net_device_ops = { * This is a thread will wake up after a period to print stats if the user has * enabled them. */ -static void -print_stats(void) +static void * +print_stats(__rte_unused void *arg) { struct virtio_net_data_ll *dev_ll; uint64_t tx_dropped, rx_dropped; @@ -1120,6 +1119,8 @@ print_stats(void) } printf("\n================================================\n"); } + + return NULL; } /** @@ -1135,7 +1136,6 @@ main(int argc, char *argv[]) uint16_t portid; uint16_t queue_id; static pthread_t tid; - char thread_name[RTE_MAX_THREAD_NAME_LEN]; /* init EAL */ ret = rte_eal_init(argc, argv); @@ -1157,7 +1157,7 @@ main(int argc, char *argv[]) nb_switching_cores = rte_lcore_count()-1; /* Get the number of physical ports. */ - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); /* * Update the global var NB_PORTS and global array PORTS @@ -1185,7 +1185,7 @@ main(int argc, char *argv[]) vpool_array[queue_id].pool = mbuf_pool; /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { RTE_LOG(INFO, VHOST_PORT, @@ -1206,13 +1206,10 @@ main(int argc, char *argv[]) /* Enable stats if the user option is set. */ if (enable_stats) { - ret = pthread_create(&tid, NULL, (void *)print_stats, NULL); - if (ret != 0) + ret = rte_ctrl_thread_create(&tid, "print-stats", NULL, + print_stats, NULL); + if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot create print-stats thread\n"); - snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "print-stats"); - ret = rte_thread_setname(tid, thread_name); - if (ret != 0) - RTE_LOG(DEBUG, VHOST_CONFIG, "Cannot set print-stats name\n"); } /* Launch all data cores. */ diff --git a/examples/tep_termination/meson.build b/examples/tep_termination/meson.build index 68c940aa..6d363624 100644 --- a/examples/tep_termination/meson.build +++ b/examples/tep_termination/meson.build @@ -6,7 +6,11 @@ # To build this example as a standalone application with an already-installed # DPDK instance, use 'make' +if host_machine.system() != 'linux' + build = false +endif deps += ['hash', 'vhost'] +allow_experimental_apis = true sources = files( 'main.c', 'vxlan.c', 'vxlan_setup.c' ) diff --git a/examples/tep_termination/vxlan_setup.c b/examples/tep_termination/vxlan_setup.c index ba7d92aa..b99ab97d 100644 --- a/examples/tep_termination/vxlan_setup.c +++ b/examples/tep_termination/vxlan_setup.c @@ -69,7 +69,6 @@ uint8_t tep_filter_type[] = {RTE_TUNNEL_FILTER_IMAC_TENID, static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -131,9 +130,8 @@ vxlan_port_init(uint16_t port, struct rte_mempool *mbuf_pool) rxconf = &dev_info.default_rxconf; txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; rx_rings = nb_devices; diff --git a/examples/vhost/Makefile b/examples/vhost/Makefile index 2dc62ebf..a2ea97a0 100644 --- a/examples/vhost/Makefile +++ b/examples/vhost/Makefile @@ -25,6 +25,8 @@ CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) +CFLAGS += -DALLOW_EXPERIMENTAL_API + build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) @@ -50,12 +52,13 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +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: else +CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O2 -D_FILE_OFFSET_BITS=64 CFLAGS += $(WERROR_FLAGS) CFLAGS += -D_GNU_SOURCE diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 60d862b4..2175c118 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -116,7 +116,6 @@ static struct rte_eth_conf vmdq_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_ONLY, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, /* * VLAN strip is necessary for 1G NIC such as I350, * this fixes bug of ipv4 forwarding in guest can't @@ -256,7 +255,6 @@ port_init(uint16_t port) rxconf = &dev_info.default_rxconf; txconf = &dev_info.default_txconf; rxconf->rx_drop_en = 1; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; /*configure the number of supported virtio devices based on VMDQ limits */ num_devices = dev_info.max_vmdq_pools; @@ -294,7 +292,8 @@ port_init(uint16_t port) printf("pf queue num: %u, configured vmdq pool num: %u, each vmdq pool has %u queues\n", num_pf_queues, num_devices, queues_per_pool); - if (port >= rte_eth_dev_count()) return -1; + if (!rte_eth_dev_is_valid_port(port)) + return -1; rx_rings = (uint16_t)dev_info.max_rx_queues; if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) @@ -667,9 +666,10 @@ static unsigned check_ports_num(unsigned nb_ports) } for (portid = 0; portid < num_ports; portid ++) { - if (ports[portid] >= nb_ports) { - RTE_LOG(INFO, VHOST_PORT, "\nSpecified port ID(%u) exceeds max system port ID(%u)\n", - ports[portid], (nb_ports - 1)); + if (!rte_eth_dev_is_valid_port(ports[portid])) { + RTE_LOG(INFO, VHOST_PORT, + "\nSpecified port ID(%u) is not valid\n", + ports[portid]); ports[portid] = INVALID_PORT_ID; valid_num_ports--; } @@ -1290,8 +1290,8 @@ static const struct vhost_device_ops virtio_net_device_ops = * This is a thread will wake up after a period to print stats if the user has * enabled them. */ -static void -print_stats(void) +static void * +print_stats(__rte_unused void *arg) { struct vhost_dev *vdev; uint64_t tx_dropped, rx_dropped; @@ -1330,6 +1330,8 @@ print_stats(void) printf("===================================================\n"); } + + return NULL; } static void @@ -1418,7 +1420,6 @@ main(int argc, char *argv[]) int ret, i; uint16_t portid; static pthread_t tid; - char thread_name[RTE_MAX_THREAD_NAME_LEN]; uint64_t flags = 0; signal(SIGINT, sigint_handler); @@ -1446,7 +1447,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE,"Not enough cores\n"); /* Get the number of physical ports. */ - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); /* * Update the global var NUM_PORTS and global array PORTS @@ -1477,7 +1478,7 @@ main(int argc, char *argv[]) } /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { RTE_LOG(INFO, VHOST_PORT, @@ -1491,17 +1492,11 @@ main(int argc, char *argv[]) /* Enable stats if the user option is set. */ if (enable_stats) { - ret = pthread_create(&tid, NULL, (void *)print_stats, NULL); - if (ret != 0) + ret = rte_ctrl_thread_create(&tid, "print-stats", NULL, + print_stats, NULL); + if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot create print-stats thread\n"); - - /* Set thread_name for aid in debugging. */ - snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "print-stats"); - ret = rte_thread_setname(tid, thread_name); - if (ret != 0) - RTE_LOG(DEBUG, VHOST_CONFIG, - "Cannot set print-stats name\n"); } /* Launch all data cores. */ diff --git a/examples/vhost/meson.build b/examples/vhost/meson.build index 3e6e6904..7b498076 100644 --- a/examples/vhost/meson.build +++ b/examples/vhost/meson.build @@ -6,7 +6,11 @@ # To build this example as a standalone application with an already-installed # DPDK instance, use 'make' +if host_machine.system() != 'linux' + build = false +endif deps += 'vhost' +allow_experimental_apis = true sources = files( 'main.c', 'virtio_net.c' ) diff --git a/examples/vhost/virtio_net.c b/examples/vhost/virtio_net.c index f6e00674..8ea6b36d 100644 --- a/examples/vhost/virtio_net.c +++ b/examples/vhost/virtio_net.c @@ -56,16 +56,20 @@ enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, struct rte_mbuf *m, uint16_t desc_idx) { uint32_t desc_avail, desc_offset; + uint64_t desc_chunck_len; uint32_t mbuf_avail, mbuf_offset; uint32_t cpy_len; struct vring_desc *desc; - uint64_t desc_addr; + uint64_t desc_addr, desc_gaddr; struct virtio_net_hdr virtio_hdr = {0, 0, 0, 0, 0, 0}; /* A counter to avoid desc dead loop chain */ uint16_t nr_desc = 1; desc = &vr->desc[desc_idx]; - desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr); + desc_chunck_len = desc->len; + desc_gaddr = desc->addr; + desc_addr = rte_vhost_va_from_guest_pa( + dev->mem, desc_gaddr, &desc_chunck_len); /* * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid * performance issue with some versions of gcc (4.8.4 and 5.3.0) which @@ -77,9 +81,42 @@ enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, rte_prefetch0((void *)(uintptr_t)desc_addr); /* write virtio-net header */ - *(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr; + if (likely(desc_chunck_len >= dev->hdr_len)) { + *(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr; + desc_offset = dev->hdr_len; + } else { + uint64_t len; + uint64_t remain = dev->hdr_len; + uint64_t src = (uint64_t)(uintptr_t)&virtio_hdr, dst; + uint64_t guest_addr = desc_gaddr; + + while (remain) { + len = remain; + dst = rte_vhost_va_from_guest_pa(dev->mem, + guest_addr, &len); + if (unlikely(!dst || !len)) + return -1; + + rte_memcpy((void *)(uintptr_t)dst, + (void *)(uintptr_t)src, + len); + + remain -= len; + guest_addr += len; + src += len; + } + + desc_chunck_len = desc->len - dev->hdr_len; + desc_gaddr += dev->hdr_len; + desc_addr = rte_vhost_va_from_guest_pa( + dev->mem, desc_gaddr, + &desc_chunck_len); + if (unlikely(!desc_addr)) + return -1; + + desc_offset = 0; + } - desc_offset = dev->hdr_len; desc_avail = desc->len - dev->hdr_len; mbuf_avail = rte_pktmbuf_data_len(m); @@ -104,15 +141,28 @@ enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, return -1; desc = &vr->desc[desc->next]; - desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr); + desc_chunck_len = desc->len; + desc_gaddr = desc->addr; + desc_addr = rte_vhost_va_from_guest_pa( + dev->mem, desc_gaddr, &desc_chunck_len); if (unlikely(!desc_addr)) return -1; desc_offset = 0; desc_avail = desc->len; + } else if (unlikely(desc_chunck_len == 0)) { + desc_chunck_len = desc_avail; + desc_gaddr += desc_offset; + desc_addr = rte_vhost_va_from_guest_pa(dev->mem, + desc_gaddr, + &desc_chunck_len); + if (unlikely(!desc_addr)) + return -1; + + desc_offset = 0; } - cpy_len = RTE_MIN(desc_avail, mbuf_avail); + cpy_len = RTE_MIN(desc_chunck_len, mbuf_avail); rte_memcpy((void *)((uintptr_t)(desc_addr + desc_offset)), rte_pktmbuf_mtod_offset(m, void *, mbuf_offset), cpy_len); @@ -121,6 +171,7 @@ enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, mbuf_offset += cpy_len; desc_avail -= cpy_len; desc_offset += cpy_len; + desc_chunck_len -= cpy_len; } return 0; @@ -189,8 +240,9 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, struct rte_mempool *mbuf_pool) { struct vring_desc *desc; - uint64_t desc_addr; + uint64_t desc_addr, desc_gaddr; uint32_t desc_avail, desc_offset; + uint64_t desc_chunck_len; uint32_t mbuf_avail, mbuf_offset; uint32_t cpy_len; struct rte_mbuf *cur = m, *prev = m; @@ -202,7 +254,10 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, (desc->flags & VRING_DESC_F_INDIRECT)) return -1; - desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr); + desc_chunck_len = desc->len; + desc_gaddr = desc->addr; + desc_addr = rte_vhost_va_from_guest_pa( + dev->mem, desc_gaddr, &desc_chunck_len); if (unlikely(!desc_addr)) return -1; @@ -216,7 +271,10 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, * header. */ desc = &vr->desc[desc->next]; - desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr); + desc_chunck_len = desc->len; + desc_gaddr = desc->addr; + desc_addr = rte_vhost_va_from_guest_pa( + dev->mem, desc_gaddr, &desc_chunck_len); if (unlikely(!desc_addr)) return -1; rte_prefetch0((void *)(uintptr_t)desc_addr); @@ -228,7 +286,7 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, mbuf_offset = 0; mbuf_avail = m->buf_len - RTE_PKTMBUF_HEADROOM; while (1) { - cpy_len = RTE_MIN(desc_avail, mbuf_avail); + cpy_len = RTE_MIN(desc_chunck_len, mbuf_avail); rte_memcpy(rte_pktmbuf_mtod_offset(cur, void *, mbuf_offset), (void *)((uintptr_t)(desc_addr + desc_offset)), @@ -238,6 +296,7 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, mbuf_offset += cpy_len; desc_avail -= cpy_len; desc_offset += cpy_len; + desc_chunck_len -= cpy_len; /* This desc reaches to its end, get the next one */ if (desc_avail == 0) { @@ -249,13 +308,26 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr, return -1; desc = &vr->desc[desc->next]; - desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr); + desc_chunck_len = desc->len; + desc_gaddr = desc->addr; + desc_addr = rte_vhost_va_from_guest_pa( + dev->mem, desc_gaddr, &desc_chunck_len); if (unlikely(!desc_addr)) return -1; rte_prefetch0((void *)(uintptr_t)desc_addr); desc_offset = 0; desc_avail = desc->len; + } else if (unlikely(desc_chunck_len == 0)) { + desc_chunck_len = desc_avail; + desc_gaddr += desc_offset; + desc_addr = rte_vhost_va_from_guest_pa(dev->mem, + desc_gaddr, + &desc_chunck_len); + if (unlikely(!desc_addr)) + return -1; + + desc_offset = 0; } /* diff --git a/examples/multi_process/l2fwd_fork/Makefile b/examples/vhost_crypto/Makefile index b65582ef..83d33101 100644 --- a/examples/multi_process/l2fwd_fork/Makefile +++ b/examples/vhost_crypto/Makefile @@ -1,11 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -# binary name -APP = l2fwd-fork - -# all source are stored in SRCS-y -SRCS-y := main.c flib.c +# Copyright(c) 2017-2018 Intel Corporation ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") @@ -16,7 +10,23 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -CFLAGS += -O3 +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: +else + +# binary name +APP = vhost-crypto + +# all source are stored in SRCS-y +SRCS-y := main.c + +CFLAGS += -DALLOW_EXPERIMENTAL_API +CFLAGS += -O2 -D_FILE_OFFSET_BITS=64 CFLAGS += $(WERROR_FLAGS) +CFLAGS += -D_GNU_SOURCE include $(RTE_SDK)/mk/rte.extapp.mk + +endif diff --git a/examples/vhost_crypto/main.c b/examples/vhost_crypto/main.c new file mode 100644 index 00000000..f334d712 --- /dev/null +++ b/examples/vhost_crypto/main.c @@ -0,0 +1,536 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Intel Corporation + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdbool.h> +#include <assert.h> +#include <getopt.h> + +#include <rte_malloc.h> +#include <rte_cycles.h> +#include <rte_vhost.h> +#include <rte_cryptodev.h> +#include <rte_vhost_crypto.h> + +#include <cmdline_rdline.h> +#include <cmdline_parse.h> +#include <cmdline_parse_string.h> +#include <cmdline.h> + +#define NB_VIRTIO_QUEUES (1) +#define MAX_PKT_BURST (64) +#define MAX_IV_LEN (32) +#define NB_MEMPOOL_OBJS (8192) +#define NB_CRYPTO_DESCRIPTORS (4096) +#define NB_CACHE_OBJS (128) +#define SESSION_MAP_ENTRIES (1024) +#define REFRESH_TIME_SEC (3) + +#define MAX_NB_SOCKETS (32) +#define DEF_SOCKET_FILE "/tmp/vhost_crypto1.socket" + +struct vhost_crypto_options { + char *socket_files[MAX_NB_SOCKETS]; + uint32_t nb_sockets; + uint8_t cid; + uint16_t qid; + uint32_t zero_copy; + uint32_t guest_polling; +} options; + +struct vhost_crypto_info { + int vids[MAX_NB_SOCKETS]; + struct rte_mempool *sess_pool; + struct rte_mempool *cop_pool; + uint32_t lcore_id; + uint8_t cid; + uint32_t qid; + uint32_t nb_vids; + volatile uint32_t initialized[MAX_NB_SOCKETS]; + +} info; + +#define SOCKET_FILE_KEYWORD "socket-file" +#define CRYPTODEV_ID_KEYWORD "cdev-id" +#define CRYPTODEV_QUEUE_KEYWORD "cdev-queue-id" +#define ZERO_COPY_KEYWORD "zero-copy" +#define POLLING_KEYWORD "guest-polling" + +uint64_t vhost_cycles[2], last_v_cycles[2]; +uint64_t outpkt_amount; + +/** support *SOCKET_FILE_PATH:CRYPTODEV_ID* format */ +static int +parse_socket_arg(char *arg) +{ + uint32_t nb_sockets = options.nb_sockets; + size_t len = strlen(arg); + + if (nb_sockets >= MAX_NB_SOCKETS) { + RTE_LOG(ERR, USER1, "Too many socket files!\n"); + return -ENOMEM; + } + + options.socket_files[nb_sockets] = rte_malloc(NULL, len, 0); + if (!options.socket_files[nb_sockets]) { + RTE_LOG(ERR, USER1, "Insufficient memory\n"); + return -ENOMEM; + } + + rte_memcpy(options.socket_files[nb_sockets], arg, len); + + options.nb_sockets++; + + return 0; +} + +static int +parse_cryptodev_id(const char *q_arg) +{ + char *end = NULL; + uint64_t pm; + + /* parse decimal string */ + pm = strtoul(q_arg, &end, 10); + if (pm > rte_cryptodev_count()) { + RTE_LOG(ERR, USER1, "Invalid Cryptodev ID %s\n", q_arg); + return -1; + } + + options.cid = (uint8_t)pm; + + return 0; +} + +static int +parse_cdev_queue_id(const char *q_arg) +{ + char *end = NULL; + uint64_t pm; + + /* parse decimal string */ + pm = strtoul(q_arg, &end, 10); + if (pm == UINT64_MAX) { + RTE_LOG(ERR, USER1, "Invalid Cryptodev Queue ID %s\n", q_arg); + return -1; + } + + options.qid = (uint16_t)pm; + + return 0; +} + +static void +vhost_crypto_usage(const char *prgname) +{ + printf("%s [EAL options] --\n" + " --%s SOCKET-FILE-PATH\n" + " --%s CRYPTODEV_ID: crypto device id\n" + " --%s CDEV_QUEUE_ID: crypto device queue id\n" + " --%s: zero copy\n" + " --%s: guest polling\n", + prgname, SOCKET_FILE_KEYWORD, CRYPTODEV_ID_KEYWORD, + CRYPTODEV_QUEUE_KEYWORD, ZERO_COPY_KEYWORD, POLLING_KEYWORD); +} + +static int +vhost_crypto_parse_args(int argc, char **argv) +{ + int opt, ret; + char *prgname = argv[0]; + char **argvopt; + int option_index; + struct option lgopts[] = { + {SOCKET_FILE_KEYWORD, required_argument, 0, 0}, + {CRYPTODEV_ID_KEYWORD, required_argument, 0, 0}, + {CRYPTODEV_QUEUE_KEYWORD, required_argument, 0, 0}, + {ZERO_COPY_KEYWORD, no_argument, 0, 0}, + {POLLING_KEYWORD, no_argument, 0, 0}, + {NULL, 0, 0, 0} + }; + + options.cid = 0; + options.qid = 0; + options.nb_sockets = 0; + options.guest_polling = 0; + options.zero_copy = RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE; + + argvopt = argv; + + while ((opt = getopt_long(argc, argvopt, "s:", + lgopts, &option_index)) != EOF) { + + switch (opt) { + case 0: + if (strcmp(lgopts[option_index].name, + SOCKET_FILE_KEYWORD) == 0) { + ret = parse_socket_arg(optarg); + if (ret < 0) { + vhost_crypto_usage(prgname); + return ret; + } + } else if (strcmp(lgopts[option_index].name, + CRYPTODEV_ID_KEYWORD) == 0) { + ret = parse_cryptodev_id(optarg); + if (ret < 0) { + vhost_crypto_usage(prgname); + return ret; + } + } else if (strcmp(lgopts[option_index].name, + CRYPTODEV_QUEUE_KEYWORD) == 0) { + ret = parse_cdev_queue_id(optarg); + if (ret < 0) { + vhost_crypto_usage(prgname); + return ret; + } + } else if (strcmp(lgopts[option_index].name, + ZERO_COPY_KEYWORD) == 0) { + options.zero_copy = + RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE; + } else if (strcmp(lgopts[option_index].name, + POLLING_KEYWORD) == 0) { + options.guest_polling = 1; + } else { + vhost_crypto_usage(prgname); + return -EINVAL; + } + break; + default: + return -1; + } + } + + if (options.nb_sockets == 0) { + options.socket_files[0] = strdup(DEF_SOCKET_FILE); + options.nb_sockets = 1; + RTE_LOG(INFO, USER1, + "VHOST-CRYPTO: use default socket file %s\n", + DEF_SOCKET_FILE); + } + + return 0; +} + +static int +new_device(int vid) +{ + char path[PATH_MAX]; + uint32_t idx, i; + int ret; + + ret = rte_vhost_get_ifname(vid, path, PATH_MAX); + if (ret) { + RTE_LOG(ERR, USER1, "Cannot find matched socket\n"); + return ret; + } + + for (idx = 0; idx < options.nb_sockets; idx++) { + if (strcmp(path, options.socket_files[idx]) == 0) + break; + } + + if (idx == options.nb_sockets) { + RTE_LOG(ERR, USER1, "Cannot find recorded socket\n"); + return -ENOENT; + } + + for (i = 0; i < 2; i++) { + vhost_cycles[i] = 0; + last_v_cycles[i] = 0; + } + + ret = rte_vhost_crypto_create(vid, info.cid, info.sess_pool, + rte_lcore_to_socket_id(info.lcore_id)); + if (ret) { + RTE_LOG(ERR, USER1, "Cannot create vhost crypto\n"); + return ret; + } + + ret = rte_vhost_crypto_set_zero_copy(vid, options.zero_copy); + if (ret) { + RTE_LOG(ERR, USER1, "Cannot %s zero copy feature\n", + options.zero_copy == 1 ? "enable" : "disable"); + return ret; + } + + info.vids[idx] = vid; + info.initialized[idx] = 1; + + rte_wmb(); + + RTE_LOG(INFO, USER1, "New Vhost-crypto Device %s, Device ID %d\n", path, + vid); + return 0; +} + +static void +destroy_device(int vid) +{ + uint32_t i; + + for (i = 0; i < info.nb_vids; i++) { + if (vid == info.vids[i]) + break; + } + + if (i == info.nb_vids) { + RTE_LOG(ERR, USER1, "Cannot find socket file from list\n"); + return; + } + + info.initialized[i] = 0; + + rte_wmb(); + + rte_vhost_crypto_free(vid); + + RTE_LOG(INFO, USER1, "Vhost Crypto Device %i Removed\n", vid); +} + +static const struct vhost_device_ops virtio_crypto_device_ops = { + .new_device = new_device, + .destroy_device = destroy_device, +}; + +__attribute__((unused)) +static void clrscr(void) +{ + system("@cls||clear"); +} + +static int +vhost_crypto_worker(__rte_unused void *arg) +{ + struct rte_crypto_op *ops[NB_VIRTIO_QUEUES][MAX_PKT_BURST + 1]; + struct rte_crypto_op *ops_deq[NB_VIRTIO_QUEUES][MAX_PKT_BURST + 1]; + uint32_t nb_inflight_ops = 0; + uint16_t nb_callfds; + int callfds[VIRTIO_CRYPTO_MAX_NUM_BURST_VQS]; + uint32_t lcore_id = rte_lcore_id(); + uint32_t burst_size = MAX_PKT_BURST; + uint32_t i, j, k; + uint32_t to_fetch, fetched; + uint64_t t_start, t_end, interval; + + int ret = 0; + + RTE_LOG(INFO, USER1, "Processing on Core %u started\n", lcore_id); + + for (i = 0; i < NB_VIRTIO_QUEUES; i++) { + if (rte_crypto_op_bulk_alloc(info.cop_pool, + RTE_CRYPTO_OP_TYPE_SYMMETRIC, ops[i], + burst_size) < burst_size) { + RTE_LOG(ERR, USER1, "Failed to alloc cops\n"); + ret = -1; + goto exit; + } + } + + while (1) { + for (i = 0; i < info.nb_vids; i++) { + if (unlikely(info.initialized[i] == 0)) + continue; + + for (j = 0; j < NB_VIRTIO_QUEUES; j++) { + t_start = rte_rdtsc_precise(); + + to_fetch = RTE_MIN(burst_size, + (NB_CRYPTO_DESCRIPTORS - + nb_inflight_ops)); + fetched = rte_vhost_crypto_fetch_requests( + info.vids[i], j, ops[j], + to_fetch); + nb_inflight_ops += rte_cryptodev_enqueue_burst( + info.cid, info.qid, ops[j], + fetched); + if (unlikely(rte_crypto_op_bulk_alloc( + info.cop_pool, + RTE_CRYPTO_OP_TYPE_SYMMETRIC, + ops[j], fetched) < fetched)) { + RTE_LOG(ERR, USER1, "Failed realloc\n"); + return -1; + } + t_end = rte_rdtsc_precise(); + interval = t_end - t_start; + + vhost_cycles[fetched > 0] += interval; + + t_start = t_end; + fetched = rte_cryptodev_dequeue_burst( + info.cid, info.qid, + ops_deq[j], RTE_MIN(burst_size, + nb_inflight_ops)); + fetched = rte_vhost_crypto_finalize_requests( + ops_deq[j], fetched, callfds, + &nb_callfds); + + nb_inflight_ops -= fetched; + outpkt_amount += fetched; + + if (!options.guest_polling) { + for (k = 0; k < nb_callfds; k++) + eventfd_write(callfds[k], + (eventfd_t)1); + } + + rte_mempool_put_bulk(info.cop_pool, + (void **)ops_deq[j], fetched); + interval = rte_rdtsc_precise() - t_start; + + vhost_cycles[fetched > 0] += interval; + } + } + } +exit: + return ret; +} + + +static void +unregister_drivers(int socket_num) +{ + int ret; + + ret = rte_vhost_driver_unregister(options.socket_files[socket_num]); + if (ret != 0) + RTE_LOG(ERR, USER1, + "Fail to unregister vhost driver for %s.\n", + options.socket_files[socket_num]); +} + +int +main(int argc, char *argv[]) +{ + struct rte_cryptodev_qp_conf qp_conf = {NB_CRYPTO_DESCRIPTORS}; + struct rte_cryptodev_config config; + struct rte_cryptodev_info dev_info; + uint32_t cryptodev_id; + uint32_t worker_lcore; + char name[128]; + uint32_t i = 0; + int ret; + + ret = rte_eal_init(argc, argv); + if (ret < 0) + return -1; + argc -= ret; + argv += ret; + + ret = vhost_crypto_parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n"); + + info.cid = options.cid; + info.qid = options.qid; + + worker_lcore = rte_get_next_lcore(0, 1, 0); + if (worker_lcore == RTE_MAX_LCORE) + rte_exit(EXIT_FAILURE, "Not enough lcore\n"); + + cryptodev_id = info.cid; + rte_cryptodev_info_get(cryptodev_id, &dev_info); + if (dev_info.max_nb_queue_pairs < info.qid + 1) { + RTE_LOG(ERR, USER1, "Number of queues cannot over %u", + dev_info.max_nb_queue_pairs); + goto error_exit; + } + + config.nb_queue_pairs = dev_info.max_nb_queue_pairs; + config.socket_id = rte_lcore_to_socket_id(worker_lcore); + + ret = rte_cryptodev_configure(cryptodev_id, &config); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Failed to configure cryptodev %u", + cryptodev_id); + goto error_exit; + } + + snprintf(name, 127, "SESS_POOL_%u", worker_lcore); + info.sess_pool = rte_mempool_create(name, SESSION_MAP_ENTRIES, + rte_cryptodev_sym_get_private_session_size( + cryptodev_id), 64, 0, NULL, NULL, NULL, NULL, + rte_lcore_to_socket_id(worker_lcore), 0); + if (!info.sess_pool) { + RTE_LOG(ERR, USER1, "Failed to create mempool"); + goto error_exit; + } + + snprintf(name, 127, "COPPOOL_%u", worker_lcore); + info.cop_pool = rte_crypto_op_pool_create(name, + RTE_CRYPTO_OP_TYPE_SYMMETRIC, NB_MEMPOOL_OBJS, + NB_CACHE_OBJS, 0, rte_lcore_to_socket_id(worker_lcore)); + + if (!info.cop_pool) { + RTE_LOG(ERR, USER1, "Lcore %u failed to create crypto pool", + worker_lcore); + ret = -1; + goto error_exit; + } + + info.nb_vids = options.nb_sockets; + for (i = 0; i < MAX_NB_SOCKETS; i++) + info.vids[i] = -1; + + for (i = 0; i < dev_info.max_nb_queue_pairs; i++) { + ret = rte_cryptodev_queue_pair_setup(cryptodev_id, i, + &qp_conf, rte_lcore_to_socket_id(worker_lcore), + info.sess_pool); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Failed to configure qp %u\n", + info.cid); + goto error_exit; + } + } + + ret = rte_cryptodev_start(cryptodev_id); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Failed to start cryptodev %u\n", info.cid); + goto error_exit; + } + + info.cid = cryptodev_id; + info.lcore_id = worker_lcore; + + if (rte_eal_remote_launch(vhost_crypto_worker, NULL, worker_lcore) + < 0) { + RTE_LOG(ERR, USER1, "Failed to start worker lcore"); + goto error_exit; + } + + for (i = 0; i < options.nb_sockets; i++) { + if (rte_vhost_driver_register(options.socket_files[i], + RTE_VHOST_USER_DEQUEUE_ZERO_COPY) < 0) { + RTE_LOG(ERR, USER1, "socket %s already exists\n", + options.socket_files[i]); + goto error_exit; + } + + rte_vhost_driver_callback_register(options.socket_files[i], + &virtio_crypto_device_ops); + + if (rte_vhost_driver_start(options.socket_files[i]) < 0) { + RTE_LOG(ERR, USER1, "failed to start vhost driver.\n"); + goto error_exit; + } + } + + RTE_LCORE_FOREACH(worker_lcore) + rte_eal_wait_lcore(worker_lcore); + + rte_mempool_free(info.sess_pool); + rte_mempool_free(info.cop_pool); + + return 0; + +error_exit: + for (i = 0; i < options.nb_sockets; i++) + unregister_drivers(i); + + rte_mempool_free(info.cop_pool); + rte_mempool_free(info.sess_pool); + + return -1; +} diff --git a/examples/vhost_crypto/meson.build b/examples/vhost_crypto/meson.build new file mode 100644 index 00000000..0f4876f0 --- /dev/null +++ b/examples/vhost_crypto/meson.build @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017-2018 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +allow_experimental_apis = true +deps += ['vhost', 'cryptodev'] +cflags += ['-D_GNU_SOURCE','-D_FILE_OFFSET_BITS=64'] +sources = files( + 'main.c' +) diff --git a/examples/vhost_scsi/Makefile b/examples/vhost_scsi/Makefile index 31bd2563..fa0cf727 100644 --- a/examples/vhost_scsi/Makefile +++ b/examples/vhost_scsi/Makefile @@ -51,7 +51,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +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: diff --git a/examples/vhost_scsi/meson.build b/examples/vhost_scsi/meson.build index bd78e84b..5f92370f 100644 --- a/examples/vhost_scsi/meson.build +++ b/examples/vhost_scsi/meson.build @@ -6,6 +6,9 @@ # To build this example as a standalone application with an already-installed # DPDK instance, use 'make' +if host_machine.system() != 'linux' + build = false +endif deps += 'vhost' cflags += ['-D_GNU_SOURCE','-D_FILE_OFFSET_BITS=64'] sources = files( diff --git a/examples/vhost_scsi/scsi.c b/examples/vhost_scsi/scsi.c index 2a034bb9..0c2fa3e6 100644 --- a/examples/vhost_scsi/scsi.c +++ b/examples/vhost_scsi/scsi.c @@ -20,6 +20,7 @@ #include <rte_log.h> #include <rte_malloc.h> #include <rte_byteorder.h> +#include <rte_string_fns.h> #include "vhost_scsi.h" #include "scsi_spec.h" @@ -181,7 +182,8 @@ vhost_bdev_scsi_inquiry_command(struct vhost_block_dev *bdev, break; case SPC_VPD_UNIT_SERIAL_NUMBER: hlen = 4; - strncpy((char *)vpage->params, bdev->name, 32); + strlcpy((char *)vpage->params, bdev->name, + sizeof(vpage->params)); vpage->alloc_len = rte_cpu_to_be_16(32); break; case SPC_VPD_DEVICE_IDENTIFICATION: @@ -215,10 +217,10 @@ vhost_bdev_scsi_inquiry_command(struct vhost_block_dev *bdev, desig->piv = 1; desig->reserved1 = 0; desig->len = 8 + 16 + 32; - strncpy((char *)desig->desig, "INTEL", 8); + strlcpy((char *)desig->desig, "INTEL", 8); vhost_strcpy_pad((char *)&desig->desig[8], bdev->product_name, 16, ' '); - strncpy((char *)&desig->desig[24], bdev->name, 32); + strlcpy((char *)&desig->desig[24], bdev->name, 32); len += sizeof(struct scsi_desig_desc) + 8 + 16 + 32; buf += sizeof(struct scsi_desig_desc) + desig->len; @@ -275,7 +277,8 @@ vhost_bdev_scsi_inquiry_command(struct vhost_block_dev *bdev, inqdata->flags3 = 0x2; /* T10 VENDOR IDENTIFICATION */ - strncpy((char *)inqdata->t10_vendor_id, "INTEL", 8); + strlcpy((char *)inqdata->t10_vendor_id, "INTEL", + sizeof(inqdata->t10_vendor_id)); /* PRODUCT IDENTIFICATION */ snprintf((char *)inqdata->product_id, @@ -283,7 +286,8 @@ vhost_bdev_scsi_inquiry_command(struct vhost_block_dev *bdev, bdev->product_name); /* PRODUCT REVISION LEVEL */ - strncpy((char *)inqdata->product_rev, "0001", 4); + strlcpy((char *)inqdata->product_rev, "0001", + sizeof(inqdata->product_rev)); /* Standard inquiry data ends here. Only populate * remaining fields if alloc_len indicates enough diff --git a/examples/vhost_scsi/scsi_spec.h b/examples/vhost_scsi/scsi_spec.h index 5c7a894b..27be0268 100644 --- a/examples/vhost_scsi/scsi_spec.h +++ b/examples/vhost_scsi/scsi_spec.h @@ -367,7 +367,7 @@ struct scsi_vpd_page { uint8_t peripheral; uint8_t page_code; uint16_t alloc_len; - uint8_t params[]; + uint8_t params[32]; }; #define SCSI_VEXT_REF_CHK 0x01 diff --git a/examples/vhost_scsi/vhost_scsi.c b/examples/vhost_scsi/vhost_scsi.c index 3cb4383e..2908ff68 100644 --- a/examples/vhost_scsi/vhost_scsi.c +++ b/examples/vhost_scsi/vhost_scsi.c @@ -38,7 +38,7 @@ vhost_scsi_ctrlr_find(__rte_unused const char *ctrlr_name) return g_vhost_ctrlr; } -static uint64_t gpa_to_vva(int vid, uint64_t gpa) +static uint64_t gpa_to_vva(int vid, uint64_t gpa, uint64_t *len) { char path[PATH_MAX]; struct vhost_scsi_ctrlr *ctrlr; @@ -58,7 +58,7 @@ static uint64_t gpa_to_vva(int vid, uint64_t gpa) assert(ctrlr->mem != NULL); - return rte_vhost_gpa_to_vva(ctrlr->mem, gpa); + return rte_vhost_va_from_guest_pa(ctrlr->mem, gpa, len); } static struct vring_desc * @@ -108,15 +108,29 @@ static void vhost_process_read_payload_chain(struct vhost_scsi_task *task) { void *data; + uint64_t chunck_len; task->iovs_cnt = 0; + chunck_len = task->desc->len; task->resp = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid, - task->desc->addr); + task->desc->addr, + &chunck_len); + if (!task->resp || chunck_len != task->desc->len) { + fprintf(stderr, "failed to translate desc address.\n"); + return; + } while (descriptor_has_next(task->desc)) { task->desc = descriptor_get_next(task->vq->desc, task->desc); + chunck_len = task->desc->len; data = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid, - task->desc->addr); + task->desc->addr, + &chunck_len); + if (!data || chunck_len != task->desc->len) { + fprintf(stderr, "failed to translate desc address.\n"); + return; + } + task->iovs[task->iovs_cnt].iov_base = data; task->iovs[task->iovs_cnt].iov_len = task->desc->len; task->data_len += task->desc->len; @@ -128,12 +142,20 @@ static void vhost_process_write_payload_chain(struct vhost_scsi_task *task) { void *data; + uint64_t chunck_len; task->iovs_cnt = 0; do { + chunck_len = task->desc->len; data = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid, - task->desc->addr); + task->desc->addr, + &chunck_len); + if (!data || chunck_len != task->desc->len) { + fprintf(stderr, "failed to translate desc address.\n"); + return; + } + task->iovs[task->iovs_cnt].iov_base = data; task->iovs[task->iovs_cnt].iov_len = task->desc->len; task->data_len += task->desc->len; @@ -141,8 +163,12 @@ vhost_process_write_payload_chain(struct vhost_scsi_task *task) task->desc = descriptor_get_next(task->vq->desc, task->desc); } while (descriptor_has_next(task->desc)); + chunck_len = task->desc->len; task->resp = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid, - task->desc->addr); + task->desc->addr, + &chunck_len); + if (!task->resp || chunck_len != task->desc->len) + fprintf(stderr, "failed to translate desc address.\n"); } static struct vhost_block_dev * @@ -188,6 +214,7 @@ process_requestq(struct vhost_scsi_ctrlr *ctrlr, uint32_t q_idx) int req_idx; uint16_t last_idx; struct vhost_scsi_task *task; + uint64_t chunck_len; last_idx = scsi_vq->last_used_idx & (vq->size - 1); req_idx = vq->avail->ring[last_idx]; @@ -205,16 +232,27 @@ process_requestq(struct vhost_scsi_ctrlr *ctrlr, uint32_t q_idx) assert((task->desc->flags & VRING_DESC_F_INDIRECT) == 0); scsi_vq->last_used_idx++; + chunck_len = task->desc->len; task->req = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid, - task->desc->addr); + task->desc->addr, + &chunck_len); + if (!task->req || chunck_len != task->desc->len) { + fprintf(stderr, "failed to translate desc address.\n"); + return; + } task->desc = descriptor_get_next(task->vq->desc, task->desc); if (!descriptor_has_next(task->desc)) { task->dxfer_dir = SCSI_DIR_NONE; + chunck_len = task->desc->len; task->resp = (void *)(uintptr_t) gpa_to_vva(task->bdev->vid, - task->desc->addr); - + task->desc->addr, + &chunck_len); + if (!task->resp || chunck_len != task->desc->len) { + fprintf(stderr, "failed to translate desc address.\n"); + return; + } } else if (!descriptor_is_wr(task->desc)) { task->dxfer_dir = SCSI_DIR_TO_DEV; vhost_process_write_payload_chain(task); diff --git a/examples/vm_power_manager/Makefile b/examples/vm_power_manager/Makefile index ef2a9f95..13a5205b 100644 --- a/examples/vm_power_manager/Makefile +++ b/examples/vm_power_manager/Makefile @@ -19,7 +19,12 @@ APP = vm_power_mgr # all source are stored in SRCS-y SRCS-y := main.c vm_power_cli.c power_manager.c channel_manager.c -SRCS-y += channel_monitor.c +SRCS-y += channel_monitor.c parse.c +ifeq ($(CONFIG_RTE_ARCH_X86_64),y) +SRCS-y += oob_monitor_x86.c +else +SRCS-y += oob_monitor_nop.c +endif CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/ CFLAGS += $(WERROR_FLAGS) diff --git a/examples/vm_power_manager/channel_monitor.c b/examples/vm_power_manager/channel_monitor.c index 1c7b6eb2..7fa47ba9 100644 --- a/examples/vm_power_manager/channel_monitor.c +++ b/examples/vm_power_manager/channel_monitor.c @@ -27,6 +27,7 @@ #include "channel_commands.h" #include "channel_manager.h" #include "power_manager.h" +#include "oob_monitor.h" #define RTE_LOGTYPE_CHANNEL_MONITOR RTE_LOGTYPE_USER1 @@ -92,6 +93,10 @@ get_pcpu_to_control(struct policy *pol) struct vm_info info; int pcpu, count; uint64_t mask_u64b; + struct core_info *ci; + int ret; + + ci = get_core_info(); RTE_LOG(INFO, CHANNEL_MONITOR, "Looking for pcpu for %s\n", pol->pkt.vm_name); @@ -100,8 +105,22 @@ get_pcpu_to_control(struct policy *pol) for (count = 0; count < pol->pkt.num_vcpu; count++) { mask_u64b = info.pcpu_mask[pol->pkt.vcpu_to_control[count]]; for (pcpu = 0; mask_u64b; mask_u64b &= ~(1ULL << pcpu++)) { - if ((mask_u64b >> pcpu) & 1) - pol->core_share[count].pcpu = pcpu; + if ((mask_u64b >> pcpu) & 1) { + if (pol->pkt.policy_to_use == BRANCH_RATIO) { + ci->cd[pcpu].oob_enabled = 1; + ret = add_core_to_monitor(pcpu); + if (ret == 0) + printf("Monitoring pcpu %d via Branch Ratio\n", + pcpu); + else + printf("Failed to start OOB Monitoring pcpu %d\n", + pcpu); + + } else { + pol->core_share[count].pcpu = pcpu; + printf("Monitoring pcpu %d\n", pcpu); + } + } } } } @@ -110,12 +129,11 @@ static int get_pfid(struct policy *pol) { - int i, x, ret = 0, nb_ports; + int i, x, ret = 0; - nb_ports = rte_eth_dev_count(); for (i = 0; i < pol->pkt.nb_mac_to_monitor; i++) { - for (x = 0; x < nb_ports; x++) { + RTE_ETH_FOREACH_DEV(x) { ret = rte_pmd_i40e_query_vfid_by_mac(x, (struct ether_addr *)&(pol->pkt.vfid[i])); if (ret != -EINVAL) { diff --git a/examples/vm_power_manager/guest_cli/Makefile b/examples/vm_power_manager/guest_cli/Makefile index d710e22d..8b1db861 100644 --- a/examples/vm_power_manager/guest_cli/Makefile +++ b/examples/vm_power_manager/guest_cli/Makefile @@ -14,7 +14,7 @@ include $(RTE_SDK)/mk/rte.vars.mk APP = guest_vm_power_mgr # all source are stored in SRCS-y -SRCS-y := main.c vm_power_cli_guest.c +SRCS-y := main.c vm_power_cli_guest.c parse.c CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/ CFLAGS += $(WERROR_FLAGS) diff --git a/examples/vm_power_manager/guest_cli/main.c b/examples/vm_power_manager/guest_cli/main.c index b17936d6..36365b12 100644 --- a/examples/vm_power_manager/guest_cli/main.c +++ b/examples/vm_power_manager/guest_cli/main.c @@ -2,23 +2,20 @@ * Copyright(c) 2010-2014 Intel Corporation */ -/* #include <stdio.h> -#include <string.h> -#include <stdint.h> -#include <sys/epoll.h> -#include <fcntl.h> -#include <unistd.h> #include <stdlib.h> -#include <errno.h> -*/ #include <signal.h> +#include <getopt.h> +#include <string.h> #include <rte_lcore.h> #include <rte_power.h> #include <rte_debug.h> +#include <rte_eal.h> +#include <rte_log.h> #include "vm_power_cli_guest.h" +#include "parse.h" static void sig_handler(int signo) @@ -32,6 +29,136 @@ sig_handler(int signo) } +#define MAX_HOURS 24 + +/* Parse the argument given in the command line of the application */ +static int +parse_args(int argc, char **argv) +{ + int opt, ret; + char **argvopt; + int option_index; + char *prgname = argv[0]; + const struct option lgopts[] = { + { "vm-name", required_argument, 0, 'n'}, + { "busy-hours", required_argument, 0, 'b'}, + { "quiet-hours", required_argument, 0, 'q'}, + { "port-list", required_argument, 0, 'p'}, + { "vcpu-list", required_argument, 0, 'l'}, + { "policy", required_argument, 0, 'o'}, + {NULL, 0, 0, 0} + }; + struct channel_packet *policy; + unsigned short int hours[MAX_HOURS]; + unsigned short int cores[MAX_VCPU_PER_VM]; + unsigned short int ports[MAX_VCPU_PER_VM]; + int i, cnt, idx; + + policy = get_policy(); + set_policy_defaults(policy); + + argvopt = argv; + + while ((opt = getopt_long(argc, argvopt, "n:b:q:p:", + lgopts, &option_index)) != EOF) { + + switch (opt) { + /* portmask */ + case 'n': + strcpy(policy->vm_name, optarg); + printf("Setting VM Name to [%s]\n", policy->vm_name); + break; + case 'b': + case 'q': + //printf("***Processing set using [%s]\n", optarg); + cnt = parse_set(optarg, hours, MAX_HOURS); + if (cnt < 0) { + printf("Invalid value passed to quiet/busy hours - [%s]\n", + optarg); + break; + } + idx = 0; + for (i = 0; i < MAX_HOURS; i++) { + if (hours[i]) { + if (opt == 'b') { + printf("***Busy Hour %d\n", i); + policy->timer_policy.busy_hours + [idx++] = i; + } else { + printf("***Quiet Hour %d\n", i); + policy->timer_policy.quiet_hours + [idx++] = i; + } + } + } + break; + case 'l': + cnt = parse_set(optarg, cores, MAX_VCPU_PER_VM); + if (cnt < 0) { + printf("Invalid value passed to vcpu-list - [%s]\n", + optarg); + break; + } + idx = 0; + for (i = 0; i < MAX_VCPU_PER_VM; i++) { + if (cores[i]) { + printf("***Using core %d\n", i); + policy->vcpu_to_control[idx++] = i; + } + } + policy->num_vcpu = idx; + printf("Total cores: %d\n", idx); + break; + case 'p': + cnt = parse_set(optarg, ports, MAX_VCPU_PER_VM); + if (cnt < 0) { + printf("Invalid value passed to port-list - [%s]\n", + optarg); + break; + } + idx = 0; + for (i = 0; i < MAX_VCPU_PER_VM; i++) { + if (ports[i]) { + printf("***Using port %d\n", i); + set_policy_mac(i, idx++); + } + } + policy->nb_mac_to_monitor = idx; + printf("Total Ports: %d\n", idx); + break; + case 'o': + if (!strcmp(optarg, "TRAFFIC")) + policy->policy_to_use = TRAFFIC; + else if (!strcmp(optarg, "TIME")) + policy->policy_to_use = TIME; + else if (!strcmp(optarg, "WORKLOAD")) + policy->policy_to_use = WORKLOAD; + else if (!strcmp(optarg, "BRANCH_RATIO")) + policy->policy_to_use = BRANCH_RATIO; + else { + printf("Invalid policy specified: %s\n", + optarg); + return -1; + } + break; + /* long options */ + + case 0: + break; + + default: + return -1; + } + } + + if (optind >= 0) + argv[optind-1] = prgname; + + ret = optind-1; + optind = 0; /* reset getopt lib */ + return ret; +} + int main(int argc, char **argv) { @@ -45,6 +172,14 @@ main(int argc, char **argv) signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); + argc -= ret; + argv += ret; + + /* parse application arguments (after the EAL ones) */ + ret = parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid arguments\n"); + rte_power_set_env(PM_ENV_KVM_VM); RTE_LCORE_FOREACH(lcore_id) { rte_power_init(lcore_id); diff --git a/examples/vm_power_manager/guest_cli/parse.c b/examples/vm_power_manager/guest_cli/parse.c new file mode 100644 index 00000000..528df6d6 --- /dev/null +++ b/examples/vm_power_manager/guest_cli/parse.c @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation. + * Copyright(c) 2014 6WIND S.A. + */ + +#include <stdlib.h> +#include <string.h> +#include <rte_log.h> +#include "parse.h" + +/* + * Parse elem, the elem could be single number/range or group + * 1) A single number elem, it's just a simple digit. e.g. 9 + * 2) A single range elem, two digits with a '-' between. e.g. 2-6 + * 3) A group elem, combines multiple 1) or 2) e.g 0,2-4,6 + * Within group, '-' used for a range separator; + * ',' used for a single number. + */ +int +parse_set(const char *input, uint16_t set[], unsigned int num) +{ + unsigned int idx; + const char *str = input; + char *end = NULL; + unsigned int min, max; + + memset(set, 0, num * sizeof(uint16_t)); + + while (isblank(*str)) + str++; + + /* only digit or left bracket is qualify for start point */ + if (!isdigit(*str) || *str == '\0') + return -1; + + while (isblank(*str)) + str++; + if (*str == '\0') + return -1; + + min = num; + do { + + /* go ahead to the first digit */ + while (isblank(*str)) + str++; + if (!isdigit(*str)) + return -1; + + /* get the digit value */ + errno = 0; + idx = strtoul(str, &end, 10); + if (errno || end == NULL || idx >= num) + return -1; + + /* go ahead to separator '-' and ',' */ + while (isblank(*end)) + end++; + if (*end == '-') { + if (min == num) + min = idx; + else /* avoid continuous '-' */ + return -1; + } else if ((*end == ',') || (*end == '\0')) { + max = idx; + + if (min == num) + min = idx; + + for (idx = RTE_MIN(min, max); + idx <= RTE_MAX(min, max); idx++) { + set[idx] = 1; + } + min = num; + } else + return -1; + + str = end + 1; + } while (*end != '\0'); + + return str - input; +} diff --git a/examples/vm_power_manager/guest_cli/parse.h b/examples/vm_power_manager/guest_cli/parse.h new file mode 100644 index 00000000..c8aa0ea5 --- /dev/null +++ b/examples/vm_power_manager/guest_cli/parse.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#ifndef PARSE_H_ +#define PARSE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int +parse_set(const char *, uint16_t [], unsigned int); + +#ifdef __cplusplus +} +#endif + +#endif /* PARSE_H_ */ diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c index 43bdeace..0db1b804 100644 --- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c +++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c @@ -33,6 +33,71 @@ struct cmd_quit_result { cmdline_fixed_string_t quit; }; +union PFID { + struct ether_addr addr; + uint64_t pfid; +}; + +static struct channel_packet policy; + +struct channel_packet * +get_policy(void) +{ + return &policy; +} + +int +set_policy_mac(int port, int idx) +{ + struct channel_packet *policy; + union PFID pfid; + + /* Use port MAC address as the vfid */ + rte_eth_macaddr_get(port, &pfid.addr); + + printf("Port %u MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":" + "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n", + port, + pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1], + pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3], + pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]); + policy = get_policy(); + policy->vfid[idx] = pfid.pfid; + return 0; +} + +void +set_policy_defaults(struct channel_packet *pkt) +{ + set_policy_mac(0, 0); + pkt->nb_mac_to_monitor = 1; + + pkt->t_boost_status.tbEnabled = false; + + pkt->vcpu_to_control[0] = 0; + pkt->vcpu_to_control[1] = 1; + pkt->num_vcpu = 2; + /* Dummy Population. */ + pkt->traffic_policy.min_packet_thresh = 96000; + pkt->traffic_policy.avg_max_packet_thresh = 1800000; + pkt->traffic_policy.max_max_packet_thresh = 2000000; + + pkt->timer_policy.busy_hours[0] = 3; + pkt->timer_policy.busy_hours[1] = 4; + pkt->timer_policy.busy_hours[2] = 5; + pkt->timer_policy.quiet_hours[0] = 11; + pkt->timer_policy.quiet_hours[1] = 12; + pkt->timer_policy.quiet_hours[2] = 13; + + pkt->timer_policy.hours_to_use_traffic_profile[0] = 8; + pkt->timer_policy.hours_to_use_traffic_profile[1] = 10; + + pkt->workload = LOW; + pkt->policy_to_use = TIME; + pkt->command = PKT_POLICY; + strcpy(pkt->vm_name, "ubuntu2"); +} + static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) @@ -118,54 +183,12 @@ struct cmd_send_policy_result { cmdline_fixed_string_t cmd; }; -union PFID { - struct ether_addr addr; - uint64_t pfid; -}; - static inline int -send_policy(void) +send_policy(struct channel_packet *pkt) { - struct channel_packet pkt; int ret; - union PFID pfid; - /* Use port MAC address as the vfid */ - rte_eth_macaddr_get(0, &pfid.addr); - printf("Port %u MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":" - "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n", - 1, - pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1], - pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3], - pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]); - pkt.vfid[0] = pfid.pfid; - - pkt.nb_mac_to_monitor = 1; - pkt.t_boost_status.tbEnabled = false; - - pkt.vcpu_to_control[0] = 0; - pkt.vcpu_to_control[1] = 1; - pkt.num_vcpu = 2; - /* Dummy Population. */ - pkt.traffic_policy.min_packet_thresh = 96000; - pkt.traffic_policy.avg_max_packet_thresh = 1800000; - pkt.traffic_policy.max_max_packet_thresh = 2000000; - - pkt.timer_policy.busy_hours[0] = 3; - pkt.timer_policy.busy_hours[1] = 4; - pkt.timer_policy.busy_hours[2] = 5; - pkt.timer_policy.quiet_hours[0] = 11; - pkt.timer_policy.quiet_hours[1] = 12; - pkt.timer_policy.quiet_hours[2] = 13; - - pkt.timer_policy.hours_to_use_traffic_profile[0] = 8; - pkt.timer_policy.hours_to_use_traffic_profile[1] = 10; - - pkt.workload = LOW; - pkt.policy_to_use = TIME; - pkt.command = PKT_POLICY; - strcpy(pkt.vm_name, "ubuntu2"); - ret = rte_power_guest_channel_send_msg(&pkt, 1); + ret = rte_power_guest_channel_send_msg(pkt, 1); if (ret == 0) return 1; RTE_LOG(DEBUG, POWER, "Error sending message: %s\n", @@ -182,7 +205,7 @@ cmd_send_policy_parsed(void *parsed_result, struct cmdline *cl, if (!strcmp(res->cmd, "now")) { printf("Sending Policy down now!\n"); - ret = send_policy(); + ret = send_policy(&policy); } if (ret != 1) cmdline_printf(cl, "Error sending message: %s\n", diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h index 75a26296..fd77f6a6 100644 --- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h +++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h @@ -11,6 +11,12 @@ extern "C" { #include "channel_commands.h" +struct channel_packet *get_policy(void); + +int set_policy_mac(int port, int idx); + +void set_policy_defaults(struct channel_packet *pkt); + void run_cli(__attribute__((unused)) void *arg); #ifdef __cplusplus diff --git a/examples/vm_power_manager/main.c b/examples/vm_power_manager/main.c index 8a1e95bd..58c5fa45 100644 --- a/examples/vm_power_manager/main.c +++ b/examples/vm_power_manager/main.c @@ -29,6 +29,8 @@ #include "channel_monitor.h" #include "power_manager.h" #include "vm_power_cli.h" +#include "oob_monitor.h" +#include "parse.h" #include <rte_pmd_ixgbe.h> #include <rte_pmd_i40e.h> #include <rte_pmd_bnxt.h> @@ -47,7 +49,6 @@ static volatile bool force_quit; static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; @@ -61,7 +62,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) struct rte_eth_dev_info dev_info; struct rte_eth_txconf txq_conf; - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; rte_eth_dev_info_get(port, &dev_info); @@ -83,7 +84,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = port_conf.txmode.offloads; /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { @@ -135,18 +135,25 @@ parse_portmask(const char *portmask) static int parse_args(int argc, char **argv) { - int opt, ret; + int opt, ret, cnt, i; char **argvopt; + uint16_t *oob_enable; int option_index; char *prgname = argv[0]; + struct core_info *ci; + float branch_ratio; static struct option lgopts[] = { { "mac-updating", no_argument, 0, 1}, { "no-mac-updating", no_argument, 0, 0}, + { "core-list", optional_argument, 0, 'l'}, + { "port-list", optional_argument, 0, 'p'}, + { "branch-ratio", optional_argument, 0, 'b'}, {NULL, 0, 0, 0} }; argvopt = argv; + ci = get_core_info(); - while ((opt = getopt_long(argc, argvopt, "p:q:T:", + while ((opt = getopt_long(argc, argvopt, "l:p:q:T:b:", lgopts, &option_index)) != EOF) { switch (opt) { @@ -158,6 +165,39 @@ parse_args(int argc, char **argv) return -1; } break; + case 'l': + oob_enable = malloc(ci->core_count * sizeof(uint16_t)); + if (oob_enable == NULL) { + printf("Error - Unable to allocate memory\n"); + return -1; + } + cnt = parse_set(optarg, oob_enable, ci->core_count); + if (cnt < 0) { + printf("Invalid core-list - [%s]\n", + optarg); + break; + } + for (i = 0; i < ci->core_count; i++) { + if (oob_enable[i]) { + printf("***Using core %d\n", i); + ci->cd[i].oob_enabled = 1; + ci->cd[i].global_enabled_cpus = 1; + } + } + free(oob_enable); + break; + case 'b': + branch_ratio = 0.0; + if (strlen(optarg)) + branch_ratio = atof(optarg); + if (branch_ratio <= 0.0) { + printf("invalid branch ratio specified\n"); + return -1; + } + ci->branch_ratio_threshold = branch_ratio; + printf("***Setting branch ratio to %f\n", + branch_ratio); + break; /* long options */ case 0: break; @@ -176,7 +216,7 @@ parse_args(int argc, char **argv) } static void -check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -189,7 +229,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) if (force_quit) return; all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if (force_quit) return; if ((port_mask & (1 << portid)) == 0) @@ -243,6 +283,17 @@ run_monitor(__attribute__((unused)) void *arg) return 0; } +static int +run_core_monitor(__attribute__((unused)) void *arg) +{ + if (branch_monitor_init() < 0) { + printf("Unable to initialize core monitor\n"); + return -1; + } + run_branch_monitor(); + return 0; +} + static void sig_handler(int signo) { @@ -261,7 +312,14 @@ main(int argc, char **argv) unsigned int nb_ports; struct rte_mempool *mbuf_pool; uint16_t portid; + struct core_info *ci; + + + ret = core_info_init(); + if (ret < 0) + rte_panic("Cannot allocate core info\n"); + ci = get_core_info(); ret = rte_eal_init(argc, argv); if (ret < 0) @@ -278,53 +336,58 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid arguments\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); - mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, - MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); + if (nb_ports > 0) { + mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", + NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, + RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); - if (mbuf_pool == NULL) - rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); + if (mbuf_pool == NULL) + rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); - /* Initialize ports. */ - for (portid = 0; portid < nb_ports; portid++) { - struct ether_addr eth; - int w, j; - int ret; + /* Initialize ports. */ + RTE_ETH_FOREACH_DEV(portid) { + struct ether_addr eth; + int w, j; + int ret; - if ((enabled_port_mask & (1 << portid)) == 0) - continue; + if ((enabled_port_mask & (1 << portid)) == 0) + continue; - eth.addr_bytes[0] = 0xe0; - eth.addr_bytes[1] = 0xe0; - eth.addr_bytes[2] = 0xe0; - eth.addr_bytes[3] = 0xe0; - eth.addr_bytes[4] = portid + 0xf0; + eth.addr_bytes[0] = 0xe0; + eth.addr_bytes[1] = 0xe0; + eth.addr_bytes[2] = 0xe0; + eth.addr_bytes[3] = 0xe0; + eth.addr_bytes[4] = portid + 0xf0; - if (port_init(portid, mbuf_pool) != 0) - rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", + if (port_init(portid, mbuf_pool) != 0) + rte_exit(EXIT_FAILURE, + "Cannot init port %"PRIu8 "\n", portid); - for (w = 0; w < MAX_VFS; w++) { - eth.addr_bytes[5] = w + 0xf0; - - ret = rte_pmd_ixgbe_set_vf_mac_addr(portid, - w, ð); - if (ret == -ENOTSUP) - ret = rte_pmd_i40e_set_vf_mac_addr(portid, - w, ð); - if (ret == -ENOTSUP) - ret = rte_pmd_bnxt_set_vf_mac_addr(portid, - w, ð); - - switch (ret) { - case 0: - printf("Port %d VF %d MAC: ", - portid, w); - for (j = 0; j < 6; j++) { - printf("%02x", eth.addr_bytes[j]); - if (j < 5) - printf(":"); + for (w = 0; w < MAX_VFS; w++) { + eth.addr_bytes[5] = w + 0xf0; + + ret = rte_pmd_ixgbe_set_vf_mac_addr(portid, + w, ð); + if (ret == -ENOTSUP) + ret = rte_pmd_i40e_set_vf_mac_addr( + portid, w, ð); + if (ret == -ENOTSUP) + ret = rte_pmd_bnxt_set_vf_mac_addr( + portid, w, ð); + + switch (ret) { + case 0: + printf("Port %d VF %d MAC: ", + portid, w); + for (j = 0; j < 5; j++) { + printf("%02x:", + eth.addr_bytes[j]); + } + printf("%02x\n", eth.addr_bytes[5]); + break; } printf("\n"); break; @@ -332,16 +395,23 @@ main(int argc, char **argv) } } + check_all_ports_link_status(enabled_port_mask); + lcore_id = rte_get_next_lcore(-1, 1, 0); if (lcore_id == RTE_MAX_LCORE) { - RTE_LOG(ERR, EAL, "A minimum of two cores are required to run " + RTE_LOG(ERR, EAL, "A minimum of three cores are required to run " "application\n"); return 0; } - - check_all_ports_link_status(nb_ports, enabled_port_mask); + printf("Running channel monitor on lcore id %d\n", lcore_id); rte_eal_remote_launch(run_monitor, NULL, lcore_id); + lcore_id = rte_get_next_lcore(lcore_id, 1, 0); + if (lcore_id == RTE_MAX_LCORE) { + RTE_LOG(ERR, EAL, "A minimum of three cores are required to run " + "application\n"); + return 0; + } if (power_manager_init() < 0) { printf("Unable to initialize power manager\n"); return -1; @@ -350,8 +420,17 @@ main(int argc, char **argv) printf("Unable to initialize channel manager\n"); return -1; } + + printf("Running core monitor on lcore id %d\n", lcore_id); + rte_eal_remote_launch(run_core_monitor, NULL, lcore_id); + run_cli(NULL); + branch_monitor_exit(); + rte_eal_mp_wait_lcore(); + + free(ci->cd); + return 0; } diff --git a/examples/vm_power_manager/meson.build b/examples/vm_power_manager/meson.build new file mode 100644 index 00000000..c370d747 --- /dev/null +++ b/examples/vm_power_manager/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +# Example app currently unsupported by meson build +build = false diff --git a/examples/vm_power_manager/oob_monitor.h b/examples/vm_power_manager/oob_monitor.h new file mode 100644 index 00000000..b96e08df --- /dev/null +++ b/examples/vm_power_manager/oob_monitor.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#ifndef OOB_MONITOR_H_ +#define OOB_MONITOR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Setup the Branch Monitor resources required to initialize epoll. + * Must be called first before calling other functions. + * + * @return + * - 0 on success. + * - Negative on error. + */ +int branch_monitor_init(void); + +/** + * Run the OOB branch monitor, loops forever on on epoll_wait. + * + * + * @return + * None + */ +void run_branch_monitor(void); + +/** + * Exit the OOB Branch Monitor. + * + * @return + * None + */ +void branch_monitor_exit(void); + +/** + * Add a core to the list of cores to monitor. + * + * @param core + * Core Number + * + * @return + * - 0 on success. + * - Negative on error. + */ +int add_core_to_monitor(int core); + +/** + * Remove a previously added core from core list. + * + * @param core + * Core Number + * + * @return + * - 0 on success. + * - Negative on error. + */ +int remove_core_from_monitor(int core); + +#ifdef __cplusplus +} +#endif + + +#endif /* OOB_MONITOR_H_ */ diff --git a/examples/vm_power_manager/oob_monitor_nop.c b/examples/vm_power_manager/oob_monitor_nop.c new file mode 100644 index 00000000..7e7b8bc1 --- /dev/null +++ b/examples/vm_power_manager/oob_monitor_nop.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation + */ + +#include "oob_monitor.h" + +void branch_monitor_exit(void) +{ +} + +__attribute__((unused)) static float +apply_policy(__attribute__((unused)) int core) +{ + return 0.0; +} + +int +add_core_to_monitor(__attribute__((unused)) int core) +{ + return 0; +} + +int +remove_core_from_monitor(__attribute__((unused)) int core) +{ + return 0; +} + +int +branch_monitor_init(void) +{ + return 0; +} + +void +run_branch_monitor(void) +{ +} diff --git a/examples/vm_power_manager/oob_monitor_x86.c b/examples/vm_power_manager/oob_monitor_x86.c new file mode 100644 index 00000000..589c604e --- /dev/null +++ b/examples/vm_power_manager/oob_monitor_x86.c @@ -0,0 +1,258 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <unistd.h> +#include <fcntl.h> +#include <rte_log.h> + +#include "oob_monitor.h" +#include "power_manager.h" +#include "channel_manager.h" + +static volatile unsigned run_loop = 1; +static uint64_t g_branches, g_branch_misses; +static int g_active; + +void branch_monitor_exit(void) +{ + run_loop = 0; +} + +/* Number of microseconds between each poll */ +#define INTERVAL 100 +#define PRINT_LOOP_COUNT (1000000/INTERVAL) +#define IA32_PERFEVTSEL0 0x186 +#define IA32_PERFEVTSEL1 0x187 +#define IA32_PERFCTR0 0xc1 +#define IA32_PERFCTR1 0xc2 +#define IA32_PERFEVT_BRANCH_HITS 0x05300c4 +#define IA32_PERFEVT_BRANCH_MISS 0x05300c5 + +static float +apply_policy(int core) +{ + struct core_info *ci; + uint64_t counter; + uint64_t branches, branch_misses; + uint32_t last_branches, last_branch_misses; + int hits_diff, miss_diff; + float ratio; + int ret; + + g_active = 0; + ci = get_core_info(); + + last_branches = ci->cd[core].last_branches; + last_branch_misses = ci->cd[core].last_branch_misses; + + ret = pread(ci->cd[core].msr_fd, &counter, + sizeof(counter), IA32_PERFCTR0); + if (ret < 0) + RTE_LOG(ERR, POWER_MANAGER, + "unable to read counter for core %u\n", + core); + branches = counter; + + ret = pread(ci->cd[core].msr_fd, &counter, + sizeof(counter), IA32_PERFCTR1); + if (ret < 0) + RTE_LOG(ERR, POWER_MANAGER, + "unable to read counter for core %u\n", + core); + branch_misses = counter; + + + ci->cd[core].last_branches = branches; + ci->cd[core].last_branch_misses = branch_misses; + + hits_diff = (int)branches - (int)last_branches; + if (hits_diff <= 0) { + /* Likely a counter overflow condition, skip this round */ + return -1.0; + } + + miss_diff = (int)branch_misses - (int)last_branch_misses; + if (miss_diff <= 0) { + /* Likely a counter overflow condition, skip this round */ + return -1.0; + } + + g_branches = hits_diff; + g_branch_misses = miss_diff; + + if (hits_diff < (INTERVAL*100)) { + /* Likely no workload running on this core. Skip. */ + return -1.0; + } + + ratio = (float)miss_diff * (float)100 / (float)hits_diff; + + if (ratio < ci->branch_ratio_threshold) + power_manager_scale_core_min(core); + else + power_manager_scale_core_max(core); + + g_active = 1; + return ratio; +} + +int +add_core_to_monitor(int core) +{ + struct core_info *ci; + char proc_file[UNIX_PATH_MAX]; + int ret; + + ci = get_core_info(); + + if (core < ci->core_count) { + long setup; + + snprintf(proc_file, UNIX_PATH_MAX, "/dev/cpu/%d/msr", core); + ci->cd[core].msr_fd = open(proc_file, O_RDWR | O_SYNC); + if (ci->cd[core].msr_fd < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "Error opening MSR file for core %d " + "(is msr kernel module loaded?)\n", + core); + return -1; + } + /* + * Set up branch counters + */ + setup = IA32_PERFEVT_BRANCH_HITS; + ret = pwrite(ci->cd[core].msr_fd, &setup, + sizeof(setup), IA32_PERFEVTSEL0); + if (ret < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "unable to set counter for core %u\n", + core); + return ret; + } + setup = IA32_PERFEVT_BRANCH_MISS; + ret = pwrite(ci->cd[core].msr_fd, &setup, + sizeof(setup), IA32_PERFEVTSEL1); + if (ret < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "unable to set counter for core %u\n", + core); + return ret; + } + /* + * Close the file and re-open as read only so + * as not to hog the resource + */ + close(ci->cd[core].msr_fd); + ci->cd[core].msr_fd = open(proc_file, O_RDONLY); + if (ci->cd[core].msr_fd < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "Error opening MSR file for core %d " + "(is msr kernel module loaded?)\n", + core); + return -1; + } + ci->cd[core].oob_enabled = 1; + } + return 0; +} + +int +remove_core_from_monitor(int core) +{ + struct core_info *ci; + char proc_file[UNIX_PATH_MAX]; + int ret; + + ci = get_core_info(); + + if (ci->cd[core].oob_enabled) { + long setup; + + /* + * close the msr file, then reopen rw so we can + * disable the counters + */ + if (ci->cd[core].msr_fd != 0) + close(ci->cd[core].msr_fd); + snprintf(proc_file, UNIX_PATH_MAX, "/dev/cpu/%d/msr", core); + ci->cd[core].msr_fd = open(proc_file, O_RDWR | O_SYNC); + if (ci->cd[core].msr_fd < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "Error opening MSR file for core %d " + "(is msr kernel module loaded?)\n", + core); + return -1; + } + setup = 0x0; /* clear event */ + ret = pwrite(ci->cd[core].msr_fd, &setup, + sizeof(setup), IA32_PERFEVTSEL0); + if (ret < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "unable to set counter for core %u\n", + core); + return ret; + } + setup = 0x0; /* clear event */ + ret = pwrite(ci->cd[core].msr_fd, &setup, + sizeof(setup), IA32_PERFEVTSEL1); + if (ret < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "unable to set counter for core %u\n", + core); + return ret; + } + + close(ci->cd[core].msr_fd); + ci->cd[core].msr_fd = 0; + ci->cd[core].oob_enabled = 0; + } + return 0; +} + +int +branch_monitor_init(void) +{ + return 0; +} + +void +run_branch_monitor(void) +{ + struct core_info *ci; + int print = 0; + float ratio; + int printed; + int reads = 0; + + ci = get_core_info(); + + while (run_loop) { + + if (!run_loop) + break; + usleep(INTERVAL); + int j; + print++; + printed = 0; + for (j = 0; j < ci->core_count; j++) { + if (ci->cd[j].oob_enabled) { + ratio = apply_policy(j); + if ((print > PRINT_LOOP_COUNT) && (g_active)) { + printf(" %d: %.4f {%lu} {%d}", j, + ratio, g_branches, + reads); + printed = 1; + reads = 0; + } else { + reads++; + } + } + } + if (print > PRINT_LOOP_COUNT) { + if (printed) + printf("\n"); + print = 0; + } + } +} diff --git a/examples/vm_power_manager/parse.c b/examples/vm_power_manager/parse.c new file mode 100644 index 00000000..8231533b --- /dev/null +++ b/examples/vm_power_manager/parse.c @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation. + * Copyright(c) 2014 6WIND S.A. + */ + +#include <string.h> +#include <rte_log.h> +#include "parse.h" + +/* + * Parse elem, the elem could be single number/range or group + * 1) A single number elem, it's just a simple digit. e.g. 9 + * 2) A single range elem, two digits with a '-' between. e.g. 2-6 + * 3) A group elem, combines multiple 1) or 2) e.g 0,2-4,6 + * Within group, '-' used for a range separator; + * ',' used for a single number. + */ +int +parse_set(const char *input, uint16_t set[], unsigned int num) +{ + unsigned int idx; + const char *str = input; + char *end = NULL; + unsigned int min, max; + + memset(set, 0, num * sizeof(uint16_t)); + + while (isblank(*str)) + str++; + + /* only digit or left bracket is qualify for start point */ + if (!isdigit(*str) || *str == '\0') + return -1; + + while (isblank(*str)) + str++; + if (*str == '\0') + return -1; + + min = num; + do { + + /* go ahead to the first digit */ + while (isblank(*str)) + str++; + if (!isdigit(*str)) + return -1; + + /* get the digit value */ + errno = 0; + idx = strtoul(str, &end, 10); + if (errno || end == NULL || idx >= num) + return -1; + + /* go ahead to separator '-' and ',' */ + while (isblank(*end)) + end++; + if (*end == '-') { + if (min == num) + min = idx; + else /* avoid continuous '-' */ + return -1; + } else if ((*end == ',') || (*end == '\0')) { + max = idx; + + if (min == num) + min = idx; + + for (idx = RTE_MIN(min, max); + idx <= RTE_MAX(min, max); idx++) { + set[idx] = 1; + } + min = num; + } else + return -1; + + str = end + 1; + } while (*end != '\0'); + + return str - input; +} diff --git a/examples/vm_power_manager/parse.h b/examples/vm_power_manager/parse.h new file mode 100644 index 00000000..a5971e9a --- /dev/null +++ b/examples/vm_power_manager/parse.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#ifndef PARSE_H_ +#define PARSE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int +parse_set(const char *, uint16_t [], unsigned int); + +#ifdef __cplusplus +} +#endif + + +#endif /* PARSE_H_ */ diff --git a/examples/vm_power_manager/power_manager.c b/examples/vm_power_manager/power_manager.c index 35db2559..b7769c3c 100644 --- a/examples/vm_power_manager/power_manager.c +++ b/examples/vm_power_manager/power_manager.c @@ -12,20 +12,21 @@ #include <dirent.h> #include <errno.h> +#include <sys/sysinfo.h> #include <sys/types.h> #include <rte_log.h> #include <rte_power.h> #include <rte_spinlock.h> +#include "channel_manager.h" #include "power_manager.h" - -#define RTE_LOGTYPE_POWER_MANAGER RTE_LOGTYPE_USER1 +#include "oob_monitor.h" #define POWER_SCALE_CORE(DIRECTION, core_num , ret) do { \ - if (core_num >= POWER_MGR_MAX_CPUS) \ + if (core_num >= ci.core_count) \ return -1; \ - if (!(global_enabled_cpus & (1ULL << core_num))) \ + if (!(ci.cd[core_num].global_enabled_cpus)) \ return -1; \ rte_spinlock_lock(&global_core_freq_info[core_num].power_sl); \ ret = rte_power_freq_##DIRECTION(core_num); \ @@ -36,7 +37,7 @@ int i; \ for (i = 0; core_mask; core_mask &= ~(1 << i++)) { \ if ((core_mask >> i) & 1) { \ - if (!(global_enabled_cpus & (1ULL << i))) \ + if (!(ci.cd[i].global_enabled_cpus)) \ continue; \ rte_spinlock_lock(&global_core_freq_info[i].power_sl); \ if (rte_power_freq_##DIRECTION(i) != 1) \ @@ -54,63 +55,82 @@ struct freq_info { static struct freq_info global_core_freq_info[POWER_MGR_MAX_CPUS]; -static uint64_t global_enabled_cpus; +struct core_info ci; #define SYSFS_CPU_PATH "/sys/devices/system/cpu/cpu%u/topology/core_id" -static unsigned -set_host_cpus_mask(void) +struct core_info * +get_core_info(void) { - char path[PATH_MAX]; - unsigned i; - unsigned num_cpus = 0; - - for (i = 0; i < POWER_MGR_MAX_CPUS; i++) { - snprintf(path, sizeof(path), SYSFS_CPU_PATH, i); - if (access(path, F_OK) == 0) { - global_enabled_cpus |= 1ULL << i; - num_cpus++; - } else - return num_cpus; + return &ci; +} + +int +core_info_init(void) +{ + struct core_info *ci; + int i; + + ci = get_core_info(); + + ci->core_count = get_nprocs_conf(); + ci->branch_ratio_threshold = BRANCH_RATIO_THRESHOLD; + ci->cd = malloc(ci->core_count * sizeof(struct core_details)); + if (!ci->cd) { + RTE_LOG(ERR, POWER_MANAGER, "Failed to allocate memory for core info."); + return -1; } - return num_cpus; + for (i = 0; i < ci->core_count; i++) { + ci->cd[i].global_enabled_cpus = 1; + ci->cd[i].oob_enabled = 0; + ci->cd[i].msr_fd = 0; + } + printf("%d cores in system\n", ci->core_count); + return 0; } int power_manager_init(void) { - unsigned int i, num_cpus, num_freqs; - uint64_t cpu_mask; + unsigned int i, num_cpus = 0, num_freqs = 0; int ret = 0; + struct core_info *ci; + + rte_power_set_env(PM_ENV_ACPI_CPUFREQ); - num_cpus = set_host_cpus_mask(); - if (num_cpus == 0) { - RTE_LOG(ERR, POWER_MANAGER, "Unable to detected host CPUs, please " - "ensure that sufficient privileges exist to inspect sysfs\n"); + ci = get_core_info(); + if (!ci) { + RTE_LOG(ERR, POWER_MANAGER, + "Failed to get core info!\n"); return -1; } - rte_power_set_env(PM_ENV_ACPI_CPUFREQ); - cpu_mask = global_enabled_cpus; - for (i = 0; cpu_mask; cpu_mask &= ~(1 << i++)) { - if (rte_power_init(i) < 0) - RTE_LOG(ERR, POWER_MANAGER, - "Unable to initialize power manager " - "for core %u\n", i); - num_freqs = rte_power_freqs(i, global_core_freq_info[i].freqs, + + for (i = 0; i < ci->core_count; i++) { + if (ci->cd[i].global_enabled_cpus) { + if (rte_power_init(i) < 0) + RTE_LOG(ERR, POWER_MANAGER, + "Unable to initialize power manager " + "for core %u\n", i); + num_cpus++; + num_freqs = rte_power_freqs(i, + global_core_freq_info[i].freqs, RTE_MAX_LCORE_FREQS); - if (num_freqs == 0) { - RTE_LOG(ERR, POWER_MANAGER, - "Unable to get frequency list for core %u\n", - i); - global_enabled_cpus &= ~(1 << i); - num_cpus--; - ret = -1; + if (num_freqs == 0) { + RTE_LOG(ERR, POWER_MANAGER, + "Unable to get frequency list for core %u\n", + i); + ci->cd[i].oob_enabled = 0; + ret = -1; + } + global_core_freq_info[i].num_freqs = num_freqs; + + rte_spinlock_init(&global_core_freq_info[i].power_sl); } - global_core_freq_info[i].num_freqs = num_freqs; - rte_spinlock_init(&global_core_freq_info[i].power_sl); + if (ci->cd[i].oob_enabled) + add_core_to_monitor(i); } - RTE_LOG(INFO, POWER_MANAGER, "Detected %u host CPUs , enabled core mask:" - " 0x%"PRIx64"\n", num_cpus, global_enabled_cpus); + RTE_LOG(INFO, POWER_MANAGER, "Managing %u cores out of %u available host cores\n", + num_cpus, ci->core_count); return ret; } @@ -125,7 +145,7 @@ power_manager_get_current_frequency(unsigned core_num) core_num, POWER_MGR_MAX_CPUS-1); return -1; } - if (!(global_enabled_cpus & (1ULL << core_num))) + if (!(ci.cd[core_num].global_enabled_cpus)) return 0; rte_spinlock_lock(&global_core_freq_info[core_num].power_sl); @@ -144,15 +164,26 @@ power_manager_exit(void) { unsigned int i; int ret = 0; + struct core_info *ci; + + ci = get_core_info(); + if (!ci) { + RTE_LOG(ERR, POWER_MANAGER, + "Failed to get core info!\n"); + return -1; + } - for (i = 0; global_enabled_cpus; global_enabled_cpus &= ~(1 << i++)) { - if (rte_power_exit(i) < 0) { - RTE_LOG(ERR, POWER_MANAGER, "Unable to shutdown power manager " - "for core %u\n", i); - ret = -1; + for (i = 0; i < ci->core_count; i++) { + if (ci->cd[i].global_enabled_cpus) { + if (rte_power_exit(i) < 0) { + RTE_LOG(ERR, POWER_MANAGER, "Unable to shutdown power manager " + "for core %u\n", i); + ret = -1; + } + ci->cd[i].global_enabled_cpus = 0; } + remove_core_from_monitor(i); } - global_enabled_cpus = 0; return ret; } @@ -268,10 +299,12 @@ int power_manager_scale_core_med(unsigned int core_num) { int ret = 0; + struct core_info *ci; + ci = get_core_info(); if (core_num >= POWER_MGR_MAX_CPUS) return -1; - if (!(global_enabled_cpus & (1ULL << core_num))) + if (!(ci->cd[core_num].global_enabled_cpus)) return -1; rte_spinlock_lock(&global_core_freq_info[core_num].power_sl); ret = rte_power_set_freq(core_num, diff --git a/examples/vm_power_manager/power_manager.h b/examples/vm_power_manager/power_manager.h index 8a8a84aa..605b3c8f 100644 --- a/examples/vm_power_manager/power_manager.h +++ b/examples/vm_power_manager/power_manager.h @@ -8,6 +8,29 @@ #ifdef __cplusplus extern "C" { #endif +struct core_details { + uint64_t last_branches; + uint64_t last_branch_misses; + uint16_t global_enabled_cpus; + uint16_t oob_enabled; + int msr_fd; +}; + +struct core_info { + uint16_t core_count; + struct core_details *cd; + float branch_ratio_threshold; +}; + +#define BRANCH_RATIO_THRESHOLD 0.1 + +struct core_info * +get_core_info(void); + +int +core_info_init(void); + +#define RTE_LOGTYPE_POWER_MANAGER RTE_LOGTYPE_USER1 /* Maximum number of CPUS to manage */ #define POWER_MGR_MAX_CPUS 64 diff --git a/examples/vmdq/main.c b/examples/vmdq/main.c index d94a1831..627a5da4 100644 --- a/examples/vmdq/main.c +++ b/examples/vmdq/main.c @@ -65,7 +65,6 @@ static const struct rte_eth_conf vmdq_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_ONLY, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, }, .txmode = { @@ -201,7 +200,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) num_pf_queues, num_pools, queues_per_pool); printf("vmdq queue base: %d pool base %d\n", vmdq_queue_base, vmdq_pool_base); - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; /* @@ -237,7 +236,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) rxconf = &dev_info.default_rxconf; rxconf->rx_drop_en = 1; txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = port_conf.txmode.offloads; for (q = 0; q < rxRings; q++) { retval = rte_eth_rx_queue_setup(port, q, rxRingSize, @@ -539,9 +537,9 @@ static unsigned check_ports_num(unsigned nb_ports) } for (portid = 0; portid < num_ports; portid++) { - if (ports[portid] >= nb_ports) { - printf("\nSpecified port ID(%u) exceeds max system port ID(%u)\n", - ports[portid], (nb_ports - 1)); + if (!rte_eth_dev_is_valid_port(ports[portid])) { + printf("\nSpecified port ID(%u) is not valid\n", + ports[portid]); ports[portid] = INVALID_PORT_ID; valid_num_ports--; } @@ -580,7 +578,7 @@ main(int argc, char *argv[]) if (rte_lcore_count() > RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); /* * Update the global var NUM_PORTS and global array PORTS @@ -600,7 +598,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); diff --git a/examples/vmdq_dcb/main.c b/examples/vmdq_dcb/main.c index bfe72f8c..64636839 100644 --- a/examples/vmdq_dcb/main.c +++ b/examples/vmdq_dcb/main.c @@ -71,7 +71,6 @@ static const struct rte_eth_conf vmdq_dcb_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_DCB, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, }, .txmode = { .mq_mode = ETH_MQ_TX_VMDQ_DCB, @@ -197,6 +196,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) uint16_t queues_per_pool; uint32_t max_nb_pools; struct rte_eth_txconf txq_conf; + uint64_t rss_hf_tmp; /* * The max pool number from dev_info will be used to validate the pool @@ -246,7 +246,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) num_pools, queues_per_pool); } - if (port >= rte_eth_dev_count()) + if (!rte_eth_dev_is_valid_port(port)) return -1; retval = get_eth_conf(&port_conf); @@ -257,6 +257,18 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + rss_hf_tmp = port_conf.rx_adv_conf.rss_conf.rss_hf; + port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (port_conf.rx_adv_conf.rss_conf.rss_hf != rss_hf_tmp) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + rss_hf_tmp, + port_conf.rx_adv_conf.rss_conf.rss_hf); + } + /* * Though in this example, all queues including pf queues are setup. * This is because VMDQ queues doesn't always start from zero, and the @@ -290,7 +302,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = port_conf.txmode.offloads; for (q = 0; q < num_queues; q++) { retval = rte_eth_tx_queue_setup(port, q, txRingSize, @@ -599,9 +610,9 @@ static unsigned check_ports_num(unsigned nb_ports) } for (portid = 0; portid < num_ports; portid++) { - if (ports[portid] >= nb_ports) { - printf("\nSpecified port ID(%u) exceeds max system port ID(%u)\n", - ports[portid], (nb_ports - 1)); + if (!rte_eth_dev_is_valid_port(ports[portid])) { + printf("\nSpecified port ID(%u) is not valid\n", + ports[portid]); ports[portid] = INVALID_PORT_ID; valid_num_ports--; } @@ -642,7 +653,7 @@ main(int argc, char *argv[]) " number of cores(1-%d)\n\n", RTE_MAX_LCORE); } - nb_ports = rte_eth_dev_count(); + nb_ports = rte_eth_dev_count_avail(); /* * Update the global var NUM_PORTS and global array PORTS @@ -662,7 +673,7 @@ main(int argc, char *argv[]) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* initialize all ports */ - for (portid = 0; portid < nb_ports; portid++) { + RTE_ETH_FOREACH_DEV(portid) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); |