* [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements
@ 2015-06-25 11:15 Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 01/11] ip_pipeline: add parsing for config files with new syntax Maciej Gajdzica
` (11 more replies)
0 siblings, 12 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
This patchset enhances functionality of ip_pipeline application. New config
file syntax is introduced, so parser is changed. Changed structure of the
application. Now every global variable is stored in app_struct in app.h.
Syntax of pipeline cli commands was changed. Implementation of cli commands
for every pipeline is moved to the separate file.
Changes in v2:
- renamed some files
- added more config files
- reworked flow classification pipeline implementation
- fixed some bugs
Daniel Mrzyglod (1):
ip_pipeline: added new implementation of firewall pipeline
Jasvinder Singh (3):
ip_pipeline: added config checks
ip_pipeline: added master pipeline
ip_pipeline: added new implementation of passthrough pipeline
Maciej Gajdzica (5):
ip_pipeline: modified init to match new params struct
ip_pipeline: moved pipelines to separate folder
ip_pipeline: added application thread
ip_pipeline: moved config files to separate folder
ip_pipeline: added new implementation of flow classification pipeline
Pawel Wodkowski (2):
ip_pipeline: add parsing for config files with new syntax
ip_pipeline: added new implementation of routing pipeline
examples/ip_pipeline/Makefile | 36 +-
examples/ip_pipeline/app.h | 850 ++++++++
examples/ip_pipeline/cmdline.c | 1976 -----------------
examples/ip_pipeline/config.c | 419 ----
examples/ip_pipeline/config/fc_ipv4_5tuple.cfg | 23 +
examples/ip_pipeline/config/fc_ipv4_5tuple.sh | 9 +
examples/ip_pipeline/config/fc_ipv6_5tuple.cfg | 23 +
examples/ip_pipeline/config/fc_ipv6_5tuple.sh | 8 +
examples/ip_pipeline/config/fc_qinq.cfg | 23 +
examples/ip_pipeline/config/fc_qinq.sh | 8 +
examples/ip_pipeline/config/fw.cfg | 11 +
examples/ip_pipeline/config/fw.sh | 13 +
examples/ip_pipeline/config/ip_pipeline.cfg | 9 +
examples/ip_pipeline/config/ip_pipeline.sh | 5 +
examples/ip_pipeline/config/pt1.cfg | 9 +
examples/ip_pipeline/config/pt2.cfg | 15 +
examples/ip_pipeline/config/pt3.cfg | 21 +
examples/ip_pipeline/config/rt.cfg | 13 +
examples/ip_pipeline/config/rt.sh | 18 +
examples/ip_pipeline/config/test.cfg | 164 ++
examples/ip_pipeline/config/test.sh | 6 +
examples/ip_pipeline/config/tm_profile.cfg | 105 +
examples/ip_pipeline/config_check.c | 387 ++++
examples/ip_pipeline/config_parse.c | 2272 ++++++++++++++++++++
examples/ip_pipeline/config_parse_tm.c | 373 ++++
examples/ip_pipeline/cpu_core_map.c | 465 ++++
examples/ip_pipeline/cpu_core_map.h | 69 +
examples/ip_pipeline/init.c | 1563 ++++++++++----
examples/ip_pipeline/ip_pipeline.cfg | 56 -
examples/ip_pipeline/ip_pipeline.sh | 18 -
examples/ip_pipeline/main.c | 137 +-
examples/ip_pipeline/main.h | 298 ---
examples/ip_pipeline/pipeline.h | 87 +
examples/ip_pipeline/pipeline/hash_func.h | 351 +++
.../ip_pipeline/pipeline/pipeline_actions_common.h | 119 +
examples/ip_pipeline/pipeline/pipeline_common_be.c | 204 ++
examples/ip_pipeline/pipeline/pipeline_common_be.h | 161 ++
examples/ip_pipeline/pipeline/pipeline_common_fe.c | 1283 +++++++++++
examples/ip_pipeline/pipeline/pipeline_common_fe.h | 248 +++
examples/ip_pipeline/pipeline/pipeline_firewall.c | 960 +++++++++
examples/ip_pipeline/pipeline/pipeline_firewall.h | 63 +
.../ip_pipeline/pipeline/pipeline_firewall_be.c | 701 ++++++
.../ip_pipeline/pipeline/pipeline_firewall_be.h | 138 ++
.../pipeline/pipeline_flow_classification.c | 1927 +++++++++++++++++
.../pipeline/pipeline_flow_classification.h | 106 +
.../pipeline/pipeline_flow_classification_be.c | 569 +++++
.../pipeline/pipeline_flow_classification_be.h | 140 ++
examples/ip_pipeline/pipeline/pipeline_master.c | 47 +
examples/ip_pipeline/pipeline/pipeline_master.h | 41 +
examples/ip_pipeline/pipeline/pipeline_master_be.c | 146 ++
examples/ip_pipeline/pipeline/pipeline_master_be.h | 41 +
.../ip_pipeline/pipeline/pipeline_passthrough.c | 47 +
.../ip_pipeline/pipeline/pipeline_passthrough.h | 41 +
.../ip_pipeline/pipeline/pipeline_passthrough_be.c | 741 +++++++
.../ip_pipeline/pipeline/pipeline_passthrough_be.h | 41 +
examples/ip_pipeline/pipeline/pipeline_routing.c | 1537 +++++++++++++
examples/ip_pipeline/pipeline/pipeline_routing.h | 99 +
.../ip_pipeline/pipeline/pipeline_routing_be.c | 836 +++++++
.../ip_pipeline/pipeline/pipeline_routing_be.h | 230 ++
examples/ip_pipeline/pipeline_be.h | 253 +++
examples/ip_pipeline/pipeline_firewall.c | 313 ---
.../ip_pipeline/pipeline_flow_classification.c | 306 ---
examples/ip_pipeline/pipeline_ipv4_frag.c | 184 --
examples/ip_pipeline/pipeline_ipv4_ras.c | 181 --
examples/ip_pipeline/pipeline_passthrough.c | 213 --
examples/ip_pipeline/pipeline_routing.c | 474 ----
examples/ip_pipeline/pipeline_rx.c | 385 ----
examples/ip_pipeline/pipeline_tx.c | 283 ---
examples/ip_pipeline/thread.c | 105 +
69 files changed, 17332 insertions(+), 5671 deletions(-)
create mode 100644 examples/ip_pipeline/app.h
delete mode 100644 examples/ip_pipeline/cmdline.c
delete mode 100644 examples/ip_pipeline/config.c
create mode 100644 examples/ip_pipeline/config/fc_ipv4_5tuple.cfg
create mode 100644 examples/ip_pipeline/config/fc_ipv4_5tuple.sh
create mode 100644 examples/ip_pipeline/config/fc_ipv6_5tuple.cfg
create mode 100644 examples/ip_pipeline/config/fc_ipv6_5tuple.sh
create mode 100644 examples/ip_pipeline/config/fc_qinq.cfg
create mode 100644 examples/ip_pipeline/config/fc_qinq.sh
create mode 100644 examples/ip_pipeline/config/fw.cfg
create mode 100644 examples/ip_pipeline/config/fw.sh
create mode 100644 examples/ip_pipeline/config/ip_pipeline.cfg
create mode 100644 examples/ip_pipeline/config/ip_pipeline.sh
create mode 100644 examples/ip_pipeline/config/pt1.cfg
create mode 100644 examples/ip_pipeline/config/pt2.cfg
create mode 100644 examples/ip_pipeline/config/pt3.cfg
create mode 100644 examples/ip_pipeline/config/rt.cfg
create mode 100644 examples/ip_pipeline/config/rt.sh
create mode 100644 examples/ip_pipeline/config/test.cfg
create mode 100644 examples/ip_pipeline/config/test.sh
create mode 100644 examples/ip_pipeline/config/tm_profile.cfg
create mode 100644 examples/ip_pipeline/config_check.c
create mode 100644 examples/ip_pipeline/config_parse.c
create mode 100644 examples/ip_pipeline/config_parse_tm.c
create mode 100644 examples/ip_pipeline/cpu_core_map.c
create mode 100644 examples/ip_pipeline/cpu_core_map.h
delete mode 100644 examples/ip_pipeline/ip_pipeline.cfg
delete mode 100644 examples/ip_pipeline/ip_pipeline.sh
delete mode 100644 examples/ip_pipeline/main.h
create mode 100644 examples/ip_pipeline/pipeline.h
create mode 100644 examples/ip_pipeline/pipeline/hash_func.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_actions_common.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_be.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_fe.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_fe.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_master.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_master.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_master_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_master_be.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough_be.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_routing.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_routing.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_routing_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_routing_be.h
create mode 100644 examples/ip_pipeline/pipeline_be.h
delete mode 100644 examples/ip_pipeline/pipeline_firewall.c
delete mode 100644 examples/ip_pipeline/pipeline_flow_classification.c
delete mode 100644 examples/ip_pipeline/pipeline_ipv4_frag.c
delete mode 100644 examples/ip_pipeline/pipeline_ipv4_ras.c
delete mode 100644 examples/ip_pipeline/pipeline_passthrough.c
delete mode 100644 examples/ip_pipeline/pipeline_routing.c
delete mode 100644 examples/ip_pipeline/pipeline_rx.c
delete mode 100644 examples/ip_pipeline/pipeline_tx.c
create mode 100644 examples/ip_pipeline/thread.c
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 01/11] ip_pipeline: add parsing for config files with new syntax
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 02/11] ip_pipeline: added config checks Maciej Gajdzica
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
From: Pawel Wodkowski <pawelx.wodkowski@intel.com>
New syntax of config files is needed for ip_pipeline example
enhancements. Some old files are temporarily disabled in the Makefile.
It is part of a bigger change.
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
---
examples/ip_pipeline/Makefile | 17 +-
examples/ip_pipeline/app.h | 850 ++++++++++++
examples/ip_pipeline/config.c | 419 ------
examples/ip_pipeline/config_parse.c | 2272 ++++++++++++++++++++++++++++++++
examples/ip_pipeline/config_parse_tm.c | 373 ++++++
examples/ip_pipeline/cpu_core_map.c | 465 +++++++
examples/ip_pipeline/cpu_core_map.h | 69 +
examples/ip_pipeline/main.c | 130 +-
examples/ip_pipeline/main.h | 298 -----
examples/ip_pipeline/pipeline.h | 87 ++
examples/ip_pipeline/pipeline_be.h | 253 ++++
11 files changed, 4380 insertions(+), 853 deletions(-)
create mode 100644 examples/ip_pipeline/app.h
delete mode 100644 examples/ip_pipeline/config.c
create mode 100644 examples/ip_pipeline/config_parse.c
create mode 100644 examples/ip_pipeline/config_parse_tm.c
create mode 100644 examples/ip_pipeline/cpu_core_map.c
create mode 100644 examples/ip_pipeline/cpu_core_map.h
delete mode 100644 examples/ip_pipeline/main.h
create mode 100644 examples/ip_pipeline/pipeline.h
create mode 100644 examples/ip_pipeline/pipeline_be.h
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index e70fdc7..b0feb4f 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -43,20 +43,9 @@ APP = ip_pipeline
# all source are stored in SRCS-y
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cmdline.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_rx.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_tx.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_ipv4_frag.c
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_ipv4_ras.c
-
-ifeq ($(CONFIG_RTE_LIBRTE_ACL),y)
-SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c
-endif
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h
new file mode 100644
index 0000000..b6b0700
--- /dev/null
+++ b/examples/ip_pipeline/app.h
@@ -0,0 +1,850 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#ifndef __INCLUDE_APP_H__
+#define __INCLUDE_APP_H__
+
+#include <stdint.h>
+#include <string.h>
+
+#include <rte_mempool.h>
+#include <rte_ring.h>
+#include <rte_sched.h>
+#include <cmdline_parse.h>
+
+#include <rte_ethdev.h>
+
+#include "cpu_core_map.h"
+#include "pipeline.h"
+
+#define APP_PARAM_NAME_SIZE PIPELINE_NAME_SIZE
+
+struct app_mempool_params {
+ char name[APP_PARAM_NAME_SIZE];
+ uint32_t parsed; /* Used to check if object was parsed or only referenced */
+ uint32_t buffer_size;
+ uint32_t pool_size;
+ uint32_t cache_size;
+ uint32_t cpu_socket_id;
+};
+
+struct app_link_params {
+ char name[APP_PARAM_NAME_SIZE];
+ uint32_t parsed; /* Used to check if object was parsed or only referenced */
+ 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_local_q; /* 0 = Disabled (packets go to default queue 0) */
+ uint32_t ip_local_q; /* 0 = Disabled (packets go to default queue 0) */
+ uint32_t tcp_local_q; /* 0 = Disabled (packets go to default queue 0) */
+ uint32_t udp_local_q; /* 0 = Disabled (packets go to default queue 0) */
+ uint32_t sctp_local_q; /* 0 = Disabled (packets go to default queue 0) */
+ 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 */
+
+ struct rte_eth_conf conf;
+ uint8_t promisc;
+};
+
+struct app_pktq_hwq_in_params {
+ char name[APP_PARAM_NAME_SIZE];
+ uint32_t parsed; /* Used to check if object was parsed or only referenced */
+ 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[APP_PARAM_NAME_SIZE];
+ uint32_t parsed; /* Used to check if object was parsed or only referenced */
+ 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[APP_PARAM_NAME_SIZE];
+ uint32_t parsed; /* Used to check if object was parsed or only referenced */
+ uint32_t size;
+ uint32_t burst_read;
+ uint32_t burst_write;
+ uint32_t dropless;
+ uint64_t n_retries;
+ uint32_t cpu_socket_id;
+};
+
+#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[APP_PARAM_NAME_SIZE];
+ uint32_t parsed; /* Used to check if object was parsed or only referenced */
+ char file_name[APP_FILE_NAME_SIZE];
+ 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_source_params {
+ char name[APP_PARAM_NAME_SIZE];
+ uint32_t parsed; /* Used to check if object was parsed or only referenced */
+ uint32_t mempool_id; /* Position in the app->mempool_params array */
+ uint32_t burst;
+};
+
+struct app_pktq_sink_params {
+ char name[APP_PARAM_NAME_SIZE];
+ uint8_t parsed; /* Used to check if object was parsed or only referenced */
+};
+
+struct app_msgq_params {
+ char name[APP_PARAM_NAME_SIZE];
+ uint32_t parsed; /* Used to check if object was parsed or only referenced */
+ 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_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_SINK,
+};
+
+struct app_pktq_out_params {
+ enum app_pktq_out_type type;
+ uint32_t id; /* Position in the appropriate app array */
+};
+
+#ifndef APP_PIPELINE_TYPE_SIZE
+#define APP_PIPELINE_TYPE_SIZE 64
+#endif
+
+#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[APP_PARAM_NAME_SIZE];
+ 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_pipeline_data {
+ void *be;
+ void *fe;
+ uint64_t timer_period;
+};
+
+struct app_thread_pipeline_data {
+ 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 16
+#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 deadline;
+};
+
+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;
+
+ /* Add a PCI device in white list. */
+ char *pci_whitelist;
+
+ /* Add a virtual device. */
+ char *vdev;
+
+ /* 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;
+
+ /* Support running on Xen dom0 without hugetlbfs */
+ uint32_t xen_dom0_present;
+ int xen_dom0;
+};
+
+#ifndef APP_APPNAME_SIZE
+#define APP_APPNAME_SIZE 256
+#endif
+
+#ifndef APP_MAX_MEMPOOLS
+#define APP_MAX_MEMPOOLS 8
+#endif
+
+#ifndef APP_MAX_LINKS
+#define APP_MAX_LINKS 16
+#endif
+
+#ifndef APP_LINK_MAX_HWQ_IN
+#define APP_LINK_MAX_HWQ_IN 64
+#endif
+
+#ifndef APP_LINK_MAX_HWQ_OUT
+#define APP_LINK_MAX_HWQ_OUT 64
+#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_SOURCE
+#define APP_MAX_PKTQ_SOURCE 16
+#endif
+
+#ifndef APP_MAX_PKTQ_SINK
+#define APP_MAX_PKTQ_SINK 16
+#endif
+
+#ifndef APP_MAX_MSGQ
+#define APP_MAX_MSGQ 64
+#endif
+
+#ifndef APP_MAX_PIPELINES
+#define APP_MAX_PIPELINES 64
+#endif
+
+#ifndef APP_EAL_ARGC
+#define APP_EAL_ARGC 32
+#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
+
+struct app_params {
+ /* Config */
+ char app_name[APP_APPNAME_SIZE];
+ char config_file[APP_FILE_NAME_SIZE];
+ char script_file[APP_FILE_NAME_SIZE];
+ 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_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_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;
+ struct rte_mempool *mempool[APP_MAX_MEMPOOLS];
+ struct rte_ring *swq[APP_MAX_PKTQ_SWQ];
+ struct rte_sched_port *tm[APP_MAX_PKTQ_TM];
+ 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[0] != '\0')
+
+#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 "%u", 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 "%u", &id); \
+while (0) \
+
+#define APP_PARAM_ADD(obj_array, obj_name) \
+({ \
+ ssize_t obj_idx; \
+ ssize_t ret; \
+ const ssize_t obj_count = RTE_DIM(obj_array); \
+ \
+ obj_idx = APP_PARAM_FIND(obj_array, obj_name); \
+ if (obj_idx < 0) { \
+ for (obj_idx = 0; obj_idx < obj_count; obj_idx++) { \
+ if (!APP_PARAM_VALID(&((obj_array)[obj_idx]))) \
+ break; \
+ } \
+ \
+ if (obj_idx < obj_count) { \
+ ret = snprintf((obj_array)[obj_idx].name, \
+ RTE_DIM((obj_array)[obj_idx].name), \
+ "%s", obj_name); \
+ if (ret > (ssize_t)RTE_DIM((obj_array)[obj_idx].name)) \
+ obj_idx = -EINVAL; \
+ } else \
+ obj_idx = -ENOMEM; \
+ } \
+ obj_idx; \
+})
+
+#define APP_CHECK(exp, fmt, ...) \
+do { \
+ if (!(exp)) { \
+ fprintf(stderr, fmt "\n", ## __VA_ARGS__); \
+ abort(); \
+ } \
+} while (0)
+
+#define APP_LOG_HIGH 1
+
+#define APP_LOG_LOW 2
+
+#define APP_LOG(app, level, fmt, ...) \
+do { \
+ if (app->log_level >= APP_LOG_ ## level) \
+ fprintf(stdout, 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;
+
+ APP_PARAM_GET_ID(link, "LINK", link_id);
+
+ for (i = 0; i < app->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%u.%u", &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;
+
+ APP_PARAM_GET_ID(link, "LINK", link_id);
+
+ for (i = 0; i < app->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%u.%u", &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_readers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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_readers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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 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_readers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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 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_readers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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_readers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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_writers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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_writers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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 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_writers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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 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_writers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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_writers = 0, i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t j;
+
+ for (j = 0; j < p->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%u.%u", &rxq_link_id, &rxq_queue_id);
+ sprintf(link_name, "LINK%u", 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%u.%u", &txq_link_id, &txq_queue_id);
+ sprintf(link_name, "LINK%u", 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%u", &link_id);
+ sprintf(link_name, "LINK%u", 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];
+}
+
+int app_config_init(struct app_params *app);
+
+int app_config_args(struct app_params *app, int argc, char **argv);
+
+int app_config_parse(struct app_params *app, const char *file_name);
+
+int app_config_parse_tm(struct app_pktq_tm_params *tm);
+
+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_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/config.c b/examples/ip_pipeline/config.c
deleted file mode 100644
index 9414a7b..0000000
--- a/examples/ip_pipeline/config.c
+++ /dev/null
@@ -1,419 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <string.h>
-#include <sys/queue.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <getopt.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memcpy.h>
-#include <rte_memzone.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.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_pci.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_ip.h>
-#include <rte_tcp.h>
-#include <rte_lpm.h>
-#include <rte_lpm6.h>
-#include <rte_string_fns.h>
-#include <rte_cfgfile.h>
-
-#include "main.h"
-
-struct app_params app;
-
-static const char usage[] =
- "Usage: %s EAL_OPTIONS-- -p PORT_MASK [-f CONFIG_FILE]\n";
-
-void
-app_print_usage(char *prgname)
-{
- printf(usage, prgname);
-}
-
-const char *
-app_core_type_id_to_string(enum app_core_type id)
-{
- switch (id) {
- case APP_CORE_NONE: return "NONE";
- case APP_CORE_MASTER: return "MASTER";
- case APP_CORE_RX: return "RX";
- case APP_CORE_TX: return "TX";
- case APP_CORE_PT: return "PT";
- case APP_CORE_FC: return "FC";
- case APP_CORE_FW: return "FW";
- case APP_CORE_RT: return "RT";
- case APP_CORE_TM: return "TM";
- case APP_CORE_IPV4_FRAG: return "IPV4_FRAG";
- case APP_CORE_IPV4_RAS: return "IPV4_RAS";
- default: return NULL;
- }
-}
-
-int
-app_core_type_string_to_id(const char *string, enum app_core_type *id)
-{
- if (strcmp(string, "NONE") == 0) {
- *id = APP_CORE_NONE;
- return 0;
- }
- if (strcmp(string, "MASTER") == 0) {
- *id = APP_CORE_MASTER;
- return 0;
- }
- if (strcmp(string, "RX") == 0) {
- *id = APP_CORE_RX;
- return 0;
- }
- if (strcmp(string, "TX") == 0) {
- *id = APP_CORE_TX;
- return 0;
- }
- if (strcmp(string, "PT") == 0) {
- *id = APP_CORE_PT;
- return 0;
- }
- if (strcmp(string, "FC") == 0) {
- *id = APP_CORE_FC;
- return 0;
- }
- if (strcmp(string, "FW") == 0) {
- *id = APP_CORE_FW;
- return 0;
- }
- if (strcmp(string, "RT") == 0) {
- *id = APP_CORE_RT;
- return 0;
- }
- if (strcmp(string, "TM") == 0) {
- *id = APP_CORE_TM;
- return 0;
- }
- if (strcmp(string, "IPV4_FRAG") == 0) {
- *id = APP_CORE_IPV4_FRAG;
- return 0;
- }
- if (strcmp(string, "IPV4_RAS") == 0) {
- *id = APP_CORE_IPV4_RAS;
- return 0;
- }
-
- return -1;
-}
-
-static uint64_t
-app_get_core_mask(void)
-{
- uint64_t core_mask = 0;
- uint32_t i;
-
- for (i = 0; i < RTE_MAX_LCORE; i++) {
- if (rte_lcore_is_enabled(i) == 0)
- continue;
-
- core_mask |= 1LLU << i;
- }
-
- return core_mask;
-}
-
-static int
-app_install_coremask(uint64_t core_mask)
-{
- uint32_t n_cores, i;
-
- for (n_cores = 0, i = 0; i < RTE_MAX_LCORE; i++)
- if (app.cores[i].core_type != APP_CORE_NONE)
- n_cores++;
-
- if (n_cores != app.n_cores) {
- rte_panic("Number of cores in COREMASK should be %u instead "
- "of %u\n", n_cores, app.n_cores);
- return -1;
- }
-
- for (i = 0; i < RTE_MAX_LCORE; i++) {
- uint32_t core_id;
-
- if (app.cores[i].core_type == APP_CORE_NONE)
- continue;
-
- core_id = __builtin_ctzll(core_mask);
- core_mask &= ~(1LLU << core_id);
-
- app.cores[i].core_id = core_id;
- }
-
- return 0;
-}
-static int
-app_install_cfgfile(const char *file_name)
-{
- struct rte_cfgfile *file;
- uint32_t n_cores, i;
-
- memset(app.cores, 0, sizeof(app.cores));
-
- if (file_name[0] == '\0')
- return -1;
-
- file = rte_cfgfile_load(file_name, 0);
- if (file == NULL) {
- rte_panic("Config file %s not found\n", file_name);
- return -1;
- }
-
- n_cores = (uint32_t) rte_cfgfile_num_sections(file, "core",
- strnlen("core", 5));
- if (n_cores < app.n_cores) {
- rte_panic("Config file parse error: not enough cores specified "
- "(%u cores missing)\n", app.n_cores - n_cores);
- return -1;
- }
- if (n_cores > app.n_cores) {
- rte_panic("Config file parse error: too many cores specified "
- "(%u cores too many)\n", n_cores - app.n_cores);
- return -1;
- }
-
- for (i = 0; i < n_cores; i++) {
- struct app_core_params *p = &app.cores[i];
- char section_name[16];
- const char *entry;
- uint32_t j;
-
- /* [core X] */
- snprintf(section_name, sizeof(section_name), "core %u", i);
- if (!rte_cfgfile_has_section(file, section_name)) {
- rte_panic("Config file parse error: core IDs are not "
- "sequential (core %u missing)\n", i);
- return -1;
- }
-
- /* type */
- entry = rte_cfgfile_get_entry(file, section_name, "type");
- if (!entry) {
- rte_panic("Config file parse error: core %u type not "
- "defined\n", i);
- return -1;
- }
- if ((app_core_type_string_to_id(entry, &p->core_type) != 0) ||
- (p->core_type == APP_CORE_NONE)) {
- rte_panic("Config file parse error: core %u type "
- "error\n", i);
- return -1;
- }
-
- /* queues in */
- entry = rte_cfgfile_get_entry(file, section_name, "queues in");
- if (!entry) {
- rte_panic("Config file parse error: core %u queues in "
- "not defined\n", i);
- return -1;
- }
-
- for (j = 0; (j < APP_MAX_SWQ_PER_CORE) && (entry != NULL);
- j++) {
- char *next;
-
- p->swq_in[j] = (uint32_t) strtol(entry, &next, 10);
- if (next == entry)
- break;
- entry = next;
- }
-
- if ((j != APP_MAX_SWQ_PER_CORE) || (*entry != '\0')) {
- rte_panic("Config file parse error: core %u queues in "
- "error\n", i);
- return -1;
- }
-
- /* queues out */
- entry = rte_cfgfile_get_entry(file, section_name, "queues out");
- if (!entry) {
- rte_panic("Config file parse error: core %u queues out "
- "not defined\n", i);
- return -1;
- }
-
- for (j = 0; (j < APP_MAX_SWQ_PER_CORE) && (entry != NULL);
- j++) {
- char *next;
-
- p->swq_out[j] = (uint32_t) strtol(entry, &next, 10);
- if (next == entry)
- break;
- entry = next;
- }
- if ((j != APP_MAX_SWQ_PER_CORE) || (*entry != '\0')) {
- rte_panic("Config file parse error: core %u queues out "
- "error\n", i);
- return -1;
- }
- }
-
- rte_cfgfile_close(file);
-
- return 0;
-}
-
-void app_cores_config_print(void)
-{
- uint32_t i;
-
- for (i = 0; i < RTE_MAX_LCORE; i++) {
- struct app_core_params *p = &app.cores[i];
- uint32_t j;
-
- if (app.cores[i].core_type == APP_CORE_NONE)
- continue;
-
- printf("---> core %u: id = %u type = %6s [", i, p->core_id,
- app_core_type_id_to_string(p->core_type));
- for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++)
- printf("%2d ", (int) p->swq_in[j]);
-
- printf("] [");
- for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++)
- printf("%2d ", (int) p->swq_out[j]);
-
- printf("]\n");
- }
-}
-
-static int
-app_install_port_mask(const char *arg)
-{
- char *end = NULL;
- uint64_t port_mask;
- uint32_t i;
-
- if (arg[0] == '\0')
- return -1;
-
- port_mask = strtoul(arg, &end, 16);
- if ((end == NULL) || (*end != '\0'))
- return -2;
-
- if (port_mask == 0)
- return -3;
-
- app.n_ports = 0;
- for (i = 0; i < 64; i++) {
- if ((port_mask & (1LLU << i)) == 0)
- continue;
-
- if (app.n_ports >= APP_MAX_PORTS)
- return -4;
-
- app.ports[app.n_ports] = i;
- app.n_ports++;
- }
-
- if (!rte_is_power_of_2(app.n_ports))
- return -5;
-
- return 0;
-}
-
-int
-app_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}
- };
- uint64_t core_mask = app_get_core_mask();
-
- app.n_cores = __builtin_popcountll(core_mask);
-
- argvopt = argv;
- while ((opt = getopt_long(argc, argvopt, "p:f:", lgopts,
- &option_index)) != EOF) {
- switch (opt) {
- case 'p':
- if (app_install_port_mask(optarg) != 0)
- rte_panic("PORT_MASK should specify a number "
- "of ports that is power of 2 less or "
- "equal to %u\n", APP_MAX_PORTS);
- break;
-
- case 'f':
- app_install_cfgfile(optarg);
- break;
-
- default:
- return -1;
- }
- }
-
- app_install_coremask(core_mask);
-
- app_cores_config_print();
-
- if (optind >= 0)
- argv[optind - 1] = prgname;
-
- ret = optind - 1;
- optind = 0; /* reset getopt lib */
-
- return ret;
-}
diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c
new file mode 100644
index 0000000..18a3bf5
--- /dev/null
+++ b/examples/ip_pipeline/config_parse.c
@@ -0,0 +1,2272 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+#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"
+
+/**
+ * Default config values
+ **/
+
+#ifndef CONFIG_FILE_DEFAULT
+#define CONFIG_FILE_DEFAULT "./config/ip_pipeline.cfg"
+#endif
+
+#ifndef LOG_LEVEL_DEFAULT
+#define LOG_LEVEL_DEFAULT 1
+#endif
+
+struct app_eal_params eal_params_default = {
+ .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_local_q = 0,
+ .ip_local_q = 0,
+ .tcp_local_q = 0,
+ .udp_local_q = 0,
+ .sctp_local_q = 0,
+ .state = 0,
+ .ip = 0,
+ .depth = 0,
+ .mac_addr = 0,
+
+ .conf = {
+ .link_speed = 0,
+ .link_duplex = 0,
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_NONE,
+
+ .header_split = 0, /* Header split */
+ .hw_ip_checksum = 0, /* IP checksum offload */
+ .hw_vlan_filter = 0, /* VLAN filtering */
+ .hw_vlan_strip = 0, /* VLAN strip */
+ .hw_vlan_extend = 0, /* Extended VLAN */
+ .jumbo_frame = 0, /* Jumbo frame support */
+ .hw_strip_crc = 0, /* CRC strip by HW */
+ .enable_scatter = 0, /* Scattered packets RX handler */
+
+ .max_rx_pkt_len = 9000, /* Jumbo frame max packet length */
+ .split_hdr_size = 0, /* Header split buffer size */
+ },
+ .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_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS,
+ .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,
+};
+
+struct app_pktq_tm_params default_tm_params = {
+ .parsed = 0,
+ .burst_read = 64,
+ .burst_write = 32,
+};
+
+struct app_pktq_source_params default_source_params = {
+ .parsed = 0,
+ .mempool_id = 0,
+ .burst = 32,
+};
+
+struct app_pktq_sink_params default_sink_params = {
+ .parsed = 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]\n"
+ "\n"
+ "Arguments:\n"
+ "\t-f CONFIG_FILE: Default config file is " CONFIG_FILE_DEFAULT "\n"
+ "\t-p PORT_MASK: Mask of NIC port IDs in hexadecimal format\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"
+ "\n";
+
+static void
+app_print_usage(char *prgname)
+{
+ rte_exit(0, app_usage, prgname);
+}
+
+#define skip_white_spaces(pos) \
+({ \
+ __typeof__(pos) _p = (pos); \
+ for ( ; isspace(*_p); _p++) \
+ ; \
+ _p; \
+})
+
+#define PARSER_IMPLICIT_PARAM_ADD_CHECK(result, section_name) \
+do { \
+ APP_CHECK(result != -EINVAL, \
+ "CFG: [%s] name too long", section_name); \
+ APP_CHECK(result != -ENOMEM, \
+ "CFG: [%s] too much sections", section_name); \
+ APP_CHECK(result >= 0, \
+ "CFG: [%s] Unknown error while adding '%s'", section_name, \
+ section_name); \
+} while (0)
+
+#define PARSER_PARAM_ADD_CHECK(result, params_array, section_name) \
+do { \
+ APP_CHECK((result != -EINVAL), \
+ "CFG: [%s] name too long", section_name); \
+ APP_CHECK((result != -ENOMEM), \
+ "CFG: [%s] too much sections", section_name); \
+ APP_CHECK(((result >= 0) && (params_array)[result].parsed == 0), \
+ "CFG: [%s] duplicate section", section_name); \
+ APP_CHECK((result >= 0), \
+ "CFG: [%s] Unknown error while adding '%s'", section_name, \
+ section_name); \
+} while (0)
+
+static int
+parser_read_arg_bool(const char *p)
+{
+ p = skip_white_spaces(p);
+ int result = -EINVAL;
+
+ if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
+ ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
+ p += 3;
+ result = 1;
+ }
+
+ if (((p[0] == 'o') && (p[1] == 'n')) ||
+ ((p[0] == 'O') && (p[1] == 'N'))) {
+ p += 2;
+ result = 1;
+ }
+
+ if (((p[0] == 'n') && (p[1] == 'o')) ||
+ ((p[0] == 'N') && (p[1] == 'O'))) {
+ p += 2;
+ result = 0;
+ }
+
+ if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
+ ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
+ p += 3;
+ result = 0;
+ }
+
+ p = skip_white_spaces(p);
+
+ if (p[0] != '\0')
+ return -EINVAL;
+
+ return result;
+}
+
+#define PARSE_ERROR(exp, section, entry) \
+APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"\n", section, entry)
+
+#define PARSE_ERROR_MALLOC(exp) \
+APP_CHECK(exp, "Parse error: no free memory\n")
+
+#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\n", section)
+
+#define PARSE_WARNING_IGNORED(exp, section, entry) \
+do \
+if (!(exp)) \
+ fprintf(stderr, "Parse warning in section \"%s\": " \
+ "entry \"%s\" is ignored\n", section, entry); \
+while (0)
+
+#define PARSE_ERROR_INVALID(exp, section, entry) \
+APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"\n", section, entry)
+
+#define PARSE_ERROR_DUPLICATE(exp, section, entry) \
+APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"\n", section, entry)
+
+static int
+parser_read_uint64(uint64_t *value, const char *p)
+{
+ char *next;
+ uint64_t val;
+
+ p = skip_white_spaces(p);
+ if (!isdigit(*p))
+ return -EINVAL;
+
+ val = strtoul(p, &next, 10);
+ if (p == next)
+ return -EINVAL;
+
+ p = next;
+ switch (*p) {
+ case 'T':
+ val *= 1024ULL;
+ /* fall trought */
+ case 'G':
+ val *= 1024ULL;
+ /* fall trought */
+ case 'M':
+ val *= 1024ULL;
+ /* fall trought */
+ case 'k':
+ case 'K':
+ val *= 1024ULL;
+ p++;
+ break;
+ }
+
+ p = skip_white_spaces(p);
+ if (*p != '\0')
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+static int
+parser_read_uint32(uint32_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+ else if (val > UINT32_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+static int
+parse_pipeline_core(uint32_t *socket, uint32_t *core, uint32_t *ht,
+ const char *entry)
+{
+ size_t num_len;
+ char num[8];
+
+ uint32_t s = 0, c = 0, h = 0, val;
+ uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
+ const char *next = skip_white_spaces(entry);
+ char type;
+
+ /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
+ while (*next != '\0') {
+ /* If everything parsed nothing should left */
+ if (s_parsed && c_parsed && h_parsed)
+ return -EINVAL;
+
+ type = *next;
+ switch(type) {
+ case 's':
+ case 'S':
+ if (s_parsed)
+ return -EINVAL;
+ s_parsed = 1;
+ next++;
+ break;
+ case 'c':
+ case 'C':
+ if (c_parsed)
+ return -EINVAL;
+ c_parsed = 1;
+ next++;
+ break;
+ case 'h':
+ case 'H':
+ if (h_parsed)
+ return -EINVAL;
+ h_parsed = 1;
+ next++;
+ break;
+ default:
+ /* If it start from digit it must be only core id. */
+ if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
+ return -EINVAL;
+
+ type = 'C';
+ }
+
+ for (num_len = 0; *next != '\0'; next++, num_len++) {
+ if (num_len == RTE_DIM(num))
+ return -EINVAL;
+
+ if (!isdigit(*next))
+ break;
+
+ num[num_len] = *next;
+ }
+
+ if (num_len == 0 && type != 'h')
+ return -EINVAL;
+
+ num[num_len] = '\0';
+ val = strtol(num, NULL, 10);
+
+ h = 0;
+ switch(type) {
+ case 's':
+ case 'S':
+ s = val;
+ break;
+ case 'c':
+ case 'C':
+ c = val;
+ if (type == 'C' && *next != '\0')
+ return -EINVAL;
+
+ break;
+ case 'h':
+ case 'H':
+ h = 1;
+ break;
+ }
+ }
+
+ *socket = s;
+ *core = c;
+ *ht = h;
+ return 0;
+}
+
+static size_t
+skip_digits(const char *src)
+{
+ size_t i;
+
+ for (i = 0; isdigit(src[i]); i++)
+ ;
+
+ return i;
+}
+
+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);
+
+ 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)) {
+ PARSE_ERROR_DUPLICATE((p->pci_blacklist == NULL), section_name, entry->name);
+ p->pci_blacklist = strdup(entry->value);
+ continue;
+ }
+
+ /* pci_whitelist */
+ if ((strcmp(entry->name, "pci_whitelist") == 0) ||
+ (strcmp(entry->name, "w") == 0)) {
+ PARSE_ERROR_DUPLICATE((p->pci_whitelist == NULL), section_name, entry->name);
+ p->pci_whitelist = strdup(entry->value);
+ continue;
+ }
+
+ /* vdev */
+ if (strcmp(entry->name, "vdev") == 0) {
+ PARSE_ERROR_DUPLICATE((p->vdev == NULL), section_name, entry->name);
+ p->vdev = strdup(entry->value);
+ 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;
+ }
+
+ /* xen_dom0 */
+ if (strcmp(entry->name, "xen_dom0") == 0) {
+ int val;
+
+ PARSE_ERROR_DUPLICATE((p->xen_dom0_present == 0), section_name, entry->name);
+ p->xen_dom0_present = 1;
+
+ val = parser_read_arg_bool(entry->value);
+ PARSE_ERROR((val >= 0), section_name, entry->name);
+ p->xen_dom0 = val;
+ continue;
+ }
+
+ /* unrecognized */
+ PARSE_ERROR_INVALID(0, section_name, entry->name);
+ }
+
+ free(entries);
+}
+
+static int
+parse_pipeline_pktq_in(struct app_params *app,
+ struct app_pipeline_params *p, const char *value)
+{
+ const char *next = value;
+ char *end;
+ char name[APP_PARAM_NAME_SIZE];
+ size_t name_len;
+
+ while (*next != '\0') {
+ enum app_pktq_in_type type;
+ int id;
+
+ end = strchr(next, ' ');
+ if (!end)
+ name_len = strlen(next);
+ else
+ name_len = end - next;
+
+ if (name_len == 0 || name_len == sizeof(name))
+ return -EINVAL;
+
+ strncpy(name, next, name_len);
+ name[name_len] = '\0';
+ next += name_len;
+ if (*next != '\0')
+ next++;
+
+ if (validate_name(name, "RXQ", 2) == 0) {
+ type = APP_PKTQ_IN_HWQ;
+ id = APP_PARAM_ADD(app->hwq_in_params, 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);
+ } else if (validate_name(name, "SOURCE", 1) == 0) {
+ type = APP_PKTQ_IN_SOURCE;
+ id = APP_PARAM_ADD(app->source_params, name);
+ } else
+ return -EINVAL;
+
+ if (id < 0)
+ return id;
+
+ p->pktq_in[p->n_pktq_in].type = type;
+ p->pktq_in[p->n_pktq_in].id = (uint32_t) id;
+ p->n_pktq_in++;
+ }
+
+ return 0;
+}
+
+static int
+parse_pipeline_pktq_out(struct app_params *app,
+ struct app_pipeline_params *p, const char *value)
+{
+ const char *next = value;
+ char *end;
+ char name[APP_PARAM_NAME_SIZE];
+ size_t name_len;
+
+ while (*next != '\0') {
+ enum app_pktq_out_type type;
+ int id;
+
+ end = strchr(next, ' ');
+ if (!end)
+ name_len = strlen(next);
+ else
+ name_len = end - next;
+
+ if (name_len == 0 || name_len == sizeof(name))
+ return -EINVAL;
+
+ strncpy(name, next, name_len);
+ name[name_len] = '\0';
+ next += name_len;
+ if (*next != '\0')
+ next++;
+
+ if (validate_name(name, "TXQ", 2) == 0) {
+ type = APP_PKTQ_OUT_HWQ;
+ id = APP_PARAM_ADD(app->hwq_out_params, 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);
+ } else if (validate_name(name, "SINK", 1) == 0) {
+ type = APP_PKTQ_OUT_SINK;
+ id = APP_PARAM_ADD(app->sink_params, name);
+ } else
+ return -EINVAL;
+
+ if (id < 0)
+ return id;
+
+ p->pktq_out[p->n_pktq_out].type = type;
+ p->pktq_out[p->n_pktq_out].id = id;
+ p->n_pktq_out++;
+ }
+
+ return 0;
+}
+
+static int
+parse_pipeline_msgq_in(struct app_params *app,
+ struct app_pipeline_params *p, const char *value)
+{
+ const char *next = value;
+ char *end;
+ char name[APP_PARAM_NAME_SIZE];
+ size_t name_len;
+ ssize_t idx;
+
+ while (*next != '\0') {
+ end = strchr(next, ' ');
+ if (!end)
+ name_len = strlen(next);
+ else
+ name_len = end - next;
+
+ if (name_len == 0 || name_len == sizeof(name))
+ return -EINVAL;
+
+ strncpy(name, next, name_len);
+ name[name_len] = '\0';
+ next += name_len;
+ if (*next != '\0')
+ next++;
+
+ if (validate_name(name, "MSGQ", 1) == 0) {
+ idx = APP_PARAM_ADD(app->msgq_params, name);
+ } else
+ return -EINVAL;
+
+ if (idx < 0)
+ return idx;
+
+ p->msgq_in[p->n_msgq_in] = idx;
+ p->n_msgq_in++;
+ }
+
+ return 0;
+}
+
+static int
+parse_pipeline_msgq_out(struct app_params *app,
+ struct app_pipeline_params *p, const char *value)
+{
+ const char *next = value;
+ char *end;
+ char name[APP_PARAM_NAME_SIZE];
+ size_t name_len;
+ ssize_t idx;
+
+ while (*next != '\0') {
+ end = strchr(next, ' ');
+ if (!end)
+ name_len = strlen(next);
+ else
+ name_len = end - next;
+
+ if (name_len == 0 || name_len == sizeof(name))
+ return -EINVAL;
+
+ strncpy(name, next, name_len);
+ name[name_len] = '\0';
+ next += name_len;
+ if (*next != '\0')
+ next++;
+
+ if (validate_name(name, "MSGQ", 1) == 0) {
+ idx = APP_PARAM_ADD(app->msgq_params, name);
+ } else
+ return -EINVAL;
+
+ if (idx < 0)
+ return idx;
+
+ p->msgq_out[p->n_msgq_out] = idx;
+ p->n_msgq_out++;
+ }
+
+ return 0;
+}
+
+
+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, ret, 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);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->pipeline_params, section_name);
+
+ param = &app->pipeline_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ if (strcmp(ent->name, "type") == 0) {
+ ret = snprintf(param->type, RTE_DIM(param->type), "%s", ent->value);
+ if (ret > 0 && ret < (int)RTE_DIM(param->type))
+ ret = 0;
+ else
+ ret = -EINVAL;
+ }
+ else if(strcmp(ent->name, "core") == 0)
+ ret = parse_pipeline_core(¶m->socket_id, ¶m->core_id,
+ ¶m->hyper_th_id, ent->value);
+ else if(strcmp(ent->name, "pktq_in") == 0)
+ ret = parse_pipeline_pktq_in(app, param, ent->value);
+ else if(strcmp(ent->name, "pktq_out") == 0)
+ ret = parse_pipeline_pktq_out(app, param, ent->value);
+ else if(strcmp(ent->name, "msgq_in") == 0)
+ ret = parse_pipeline_msgq_in(app, param, ent->value);
+ else if(strcmp(ent->name, "msgq_out") == 0)
+ ret = parse_pipeline_msgq_out(app, param, ent->value);
+ else if(strcmp(ent->name, "timer_period") == 0)
+ ret = parser_read_uint32(¶m->timer_period, ent->value);
+ else {
+ 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),
+ "CFG: [%s] out of memory", section_name);
+
+ param->n_args++;
+ ret = 0;
+ }
+
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ snprintf(name, sizeof(name), "MSGQ-REQ-%s", section_name);
+ param_idx = APP_PARAM_ADD(app->msgq_params, name);
+ PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, 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);
+ PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, 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);
+ PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, 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);
+ PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, 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, ret, 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);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->mempool_params, section_name);
+
+ param = &app->mempool_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if (strcmp(ent->name, "buffer_size") == 0)
+ ret = parser_read_uint32(¶m->buffer_size, ent->value);
+ else if(strcmp(ent->name, "pool_size") == 0)
+ ret = parser_read_uint32(¶m->pool_size, ent->value);
+ else if(strcmp(ent->name, "cache_size") == 0)
+ ret = parser_read_uint32(¶m->cache_size, ent->value);
+ else if(strcmp(ent->name, "cpu") == 0)
+ ret = parser_read_uint32(¶m->cpu_socket_id, ent->value);
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ free(entries);
+}
+
+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, ret, 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->link_params, section_name);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->link_params, section_name);
+
+ param = &app->link_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if (strcmp(ent->name, "arp_q") == 0)
+ ret = parser_read_uint32(¶m->arp_q, ent->value);
+ else if(strcmp(ent->name, "tcp_syn_q") == 0)
+ ret = parser_read_uint32(¶m->tcp_syn_local_q, ent->value);
+ else if(strcmp(ent->name, "ip_local_q") == 0)
+ ret = parser_read_uint32(¶m->ip_local_q, ent->value);
+ else if(strcmp(ent->name, "tcp_local_q") == 0)
+ ret = parser_read_uint32(¶m->tcp_local_q, ent->value);
+ else if(strcmp(ent->name, "udp_local_q") == 0)
+ ret = parser_read_uint32(¶m->udp_local_q, ent->value);
+ else if(strcmp(ent->name, "sctp_local_q") == 0)
+ ret = parser_read_uint32(¶m->sctp_local_q, ent->value);
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ 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, ret, 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);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_in_params, section_name);
+
+ param = &app->hwq_in_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if (strcmp(ent->name, "mempool") == 0) {
+ ssize_t idx;
+
+ APP_CHECK((validate_name(ent->value, "MEMPOOL", 1) == 0),
+ "CFG: [%s] entry '%s': invalid mempool\n", section_name, ent->name);
+
+ idx = APP_PARAM_ADD(app->mempool_params, ent->value);
+ PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
+ param->mempool_id = idx;
+ ret = 0;
+ } else if(strcmp(ent->name, "size") == 0)
+ ret = parser_read_uint32(¶m->size, ent->value);
+ else if(strcmp(ent->name, "burst") == 0)
+ ret = parser_read_uint32(¶m->burst, ent->value);
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ 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, ret, 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);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_out_params, section_name);
+
+ param = &app->hwq_out_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if(strcmp(ent->name, "size") == 0)
+ ret = parser_read_uint32(¶m->size, ent->value);
+ else if (strcmp(ent->name, "burst") == 0)
+ ret = parser_read_uint32(¶m->burst, ent->value);
+ else if(strcmp(ent->name, "dropless") == 0) {
+ ret = parser_read_arg_bool(ent->value);
+ if (ret >= 0) {
+ param->dropless = ret;
+ ret = 0;
+ }
+ }
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ 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, ret, 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->swq_params, section_name);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->swq_params, section_name);
+
+ param = &app->swq_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if(strcmp(ent->name, "size") == 0)
+ ret = parser_read_uint32(¶m->size, ent->value);
+ else if (strcmp(ent->name, "burst_read") == 0)
+ ret = parser_read_uint32(¶m->burst_read, ent->value);
+ else if (strcmp(ent->name, "burst_write") == 0)
+ ret = parser_read_uint32(¶m->burst_write, ent->value);
+ else if(strcmp(ent->name, "dropless") == 0) {
+ ret = parser_read_arg_bool(ent->value);
+ if (ret >= 0) {
+ param->dropless = ret;
+ ret = 0;
+ }
+ } else if(strcmp(ent->name, "n_retries") == 0)
+ ret = parser_read_uint64(¶m->n_retries, ent->value);
+ else if(strcmp(ent->name, "cpu") == 0)
+ ret = parser_read_uint32(¶m->cpu_socket_id, ent->value);
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ 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, ret, 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);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->tm_params, section_name);
+
+ param = &app->tm_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if(strcmp(ent->name, "cfg") == 0) {
+ int status;
+
+ ret = 0;
+ status = snprintf(param->file_name,
+ sizeof(param->file_name), "%s", ent->value);
+ if (status >= (int) sizeof(param->file_name))
+ ret = -EINVAL;
+ else {
+ status = app_config_parse_tm(param);
+ if (status)
+ ret = -EBADF;
+ }
+ } else if (strcmp(ent->name, "burst_read") == 0)
+ ret = parser_read_uint32(¶m->burst_read, ent->value);
+ else if (strcmp(ent->name, "burst_write") == 0)
+ ret = parser_read_uint32(¶m->burst_write, ent->value);
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret != -EBADF, "CFG: [%s] entry '%s': TM cfg parse error '%s'\n",
+ section_name, ent->name, ent->value);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ 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, ret, 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->source_params, section_name);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->source_params, section_name);
+
+ param = &app->source_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if (strcmp(ent->name, "mempool") == 0) {
+ ssize_t idx;
+
+ APP_CHECK((validate_name(ent->value, "MEMPOOL", 1) == 0),
+ "CFG: [%s] entry '%s': invalid mempool\n", section_name, ent->name);
+
+ idx = APP_PARAM_ADD(app->mempool_params, ent->value);
+ PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
+ param->mempool_id = idx;
+ ret = 0;
+ } else if (strcmp(ent->name, "burst") == 0)
+ ret = parser_read_uint32(¶m->burst, ent->value);
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ 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, ret, 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);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name);
+
+ param = &app->msgq_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if(strcmp(ent->name, "size") == 0)
+ ret = parser_read_uint32(¶m->size, ent->value);
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ 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, ret, 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);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name);
+
+ param = &app->msgq_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if(strcmp(ent->name, "size") == 0)
+ ret = parser_read_uint32(¶m->size, ent->value);
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ 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, ret, 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);
+ PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name);
+
+ param = &app->msgq_params[param_idx];
+ param->parsed = 1;
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ ret = -ESRCH;
+ if(strcmp(ent->name, "size") == 0)
+ ret = parser_read_uint32(¶m->size, ent->value);
+ else if(strcmp(ent->name, "cpu") == 0)
+ ret = parser_read_uint32(¶m->cpu_socket_id, ent->value);
+
+ APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n",
+ section_name, ent->name);
+ APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n",
+ section_name, ent->name, ent->value);
+ }
+
+ free(entries);
+}
+
+struct config_section {
+ const char prefix[CFG_NAME_LEN];
+ int numbers;
+ void (*load)(struct app_params *p, const char *section_name,
+ struct rte_cfgfile *cfg);
+};
+
+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 },
+ { "SOURCE", 1, parse_source },
+ { "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)
+{
+ ssize_t idx;
+
+ idx = APP_PARAM_ADD(app->mempool_params, "MEMPOOL0");
+ PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, "start-up");
+}
+
+static void
+parse_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%u", link_id);
+ idx = APP_PARAM_ADD(app->link_params, name);
+ PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, name);
+
+ app->link_params[idx].pmd_id = pmd_id;
+ link_id ++;
+ }
+}
+
+int
+app_config_parse(struct app_params *app, const char *file_name)
+{
+ char config_file_out[APP_FILE_NAME_SIZE];
+
+ char **section_names;
+ struct rte_cfgfile *cfg;
+
+ const struct config_section *sch_s;
+ int i, j, sect_count;
+
+ create_implicit_mempools(app);
+
+ parse_port_mask(app, app->port_mask);
+
+ cfg = rte_cfgfile_load(file_name, 0);
+ APP_CHECK(cfg != NULL, "Unable to load config file %s", file_name);
+
+ sect_count = rte_cfgfile_num_sections(cfg, NULL, 0);
+ section_names = malloc(sect_count * sizeof(char *));
+ 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++) {
+ 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 ex:
+ * if shc_s if sch_s->name is "ABC"
+ * cfg_section_name "ABC0.0" match but
+ * cfg_section_name is "ABCDEF" does not match
+ */
+ 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), "Unknown section %s",
+ section_names[i]);
+
+ APP_CHECK(validate_name(section_names[i], sch_s->prefix, sch_s->numbers) == 0,
+ "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);
+
+ snprintf(config_file_out, APP_FILE_NAME_SIZE, "%s.out", app->config_file);
+ app_config_save(app, config_file_out);
+
+ 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->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);
+
+ return 0;
+}
+
+static void
+save_eal_params(struct app_params *app, FILE *f)
+{
+ struct app_eal_params *p = &app->eal_params;
+
+ fprintf(f, "[EAL]\n");
+
+ if (p->coremap)
+ fprintf(f, "%s = %s\n", "lcores", p->coremap);
+
+ if (p->master_lcore_present)
+ fprintf(f, "%s = %u\n", "master_lcore", p->master_lcore);
+
+ fprintf(f, "%s = %u\n", "n", p->channels);
+
+ if (p->memory_present)
+ fprintf(f, "%s = %u\n", "m", p->memory);
+
+ if (p->ranks_present)
+ fprintf(f, "%s = %u\n", "r", p->ranks);
+
+ if (p->pci_blacklist)
+ fprintf(f, "%s = %s\n", "pci_blacklist", p->pci_blacklist);
+
+ if (p->pci_whitelist)
+ fprintf(f, "%s = %s\n", "pci_whitelist", p->pci_whitelist);
+
+ if (p->vdev)
+ fprintf(f, "%s = %s\n", "vdev", p->vdev);
+
+ 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 = %d\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);
+
+ if (p->xen_dom0_present)
+ fprintf(f, "%s = %s\n", "xen_dom0", (p->xen_dom0)? "yes" : "no");
+
+ 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 = %" PRIu32 "\n", "arp_q", p->arp_q);
+ fprintf(f, "%s = %" PRIu32 "\n", "tcp_syn_local_q", p->tcp_syn_local_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);
+
+ 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");
+
+ 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);
+
+ 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 = %u\n", "burst_read", p->burst_read);
+ fprintf(f, "%s = %u\n", "burst_write", p->burst_write);
+
+ 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 = %u\n", "burst", p->burst);
+ 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%uc%u%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_SOURCE:
+ name = app->source_params[pp->id].name;
+ break;
+ default:
+ APP_CHECK(0, "Error\n");
+ }
+
+ 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_SINK:
+ name = app->sink_params[pp->id].name;
+ break;
+ default:
+ APP_CHECK(0, "Error\n");
+ }
+
+ 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_in) {
+ 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 = %u\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),
+ "Need write access to directory \"%s\" to save configuration\n", dir_name);
+
+ file = fopen(file_name, "w");
+ APP_CHECK((file != NULL),
+ "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_source_params(app, file);
+ save_msgq_params(app, file);
+
+ fclose(file);
+ free(name);
+}
+
+int
+app_config_init(struct app_params *app)
+{
+ size_t i;
+
+ memset(app, 0, sizeof(struct app_params));
+
+ strcpy(app->config_file, CONFIG_FILE_DEFAULT);
+
+ app->log_level = LOG_LEVEL_DEFAULT;
+
+ memcpy(&app->eal_params,
+ &eal_params_default,
+ sizeof(struct app_eal_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->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;
+}
+
+int
+app_config_args(struct app_params *app, int argc, char **argv)
+{
+ int opt;
+ int option_index, f_present, s_present, p_present, l_present;
+ int scaned = 0;
+
+ static struct option lgopts[] = {
+ {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;
+
+ while ((opt = getopt_long(argc, argv, "f:s:p:l:", lgopts,
+ &option_index)) != EOF) {
+ switch (opt) {
+ case 'f':
+ snprintf(app->config_file, sizeof(app->config_file), "%s", optarg);
+
+ if (!strlen(app->config_file))
+ rte_panic("Error: Config file name is null\n");
+
+ if (f_present)
+ rte_panic("Error: Config file is provided more than once\n");
+
+ f_present = 1;
+ break;
+
+ case 's':
+ snprintf(app->script_file, sizeof(app->script_file), "%s", optarg);
+
+ if (!strlen(app->script_file))
+ rte_panic("Error: Script file name is null\n");
+
+ if (s_present)
+ rte_panic("Error: Script file is provided more than once\n");
+
+ s_present = 1;
+ break;
+
+ case 'p':
+ 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");
+
+ if (p_present)
+ rte_panic("Error: PORT_MASK is provided more than once\n");
+
+ p_present = 1;
+ break;
+
+ case 'l':
+ if ((sscanf(optarg, "%" SCNu32 "%n", &app->log_level, &scaned) != 1) ||
+ ((size_t) scaned != strlen(optarg)) ||
+ (app->log_level > 2))
+ rte_panic("Error: LOG_LEVEL invalid value\n");
+
+ if (l_present)
+ rte_panic("Error: LOG_LEVEL is provided more than once\n");
+
+ l_present = 1;
+ break;
+
+ default:
+ app_print_usage(argv[0]);
+ }
+ }
+
+ optind = 0; /* reset getopt lib */
+
+ /* Check that mandatory args have been provided */
+ if (!p_present)
+ rte_panic("Error: PORT_MASK is not provided\n");
+
+ return 0;
+}
diff --git a/examples/ip_pipeline/config_parse_tm.c b/examples/ip_pipeline/config_parse_tm.c
new file mode 100644
index 0000000..4c69922
--- /dev/null
+++ b/examples/ip_pipeline/config_parse_tm.c
@@ -0,0 +1,373 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+#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 %d 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 %d 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 %d 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 %d 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 %d", 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 %d", 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];
+
+ 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 %d", 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;
+}
+
+int
+app_config_parse_tm(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_pipe_profiles));
+ 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;
+}
diff --git a/examples/ip_pipeline/cpu_core_map.c b/examples/ip_pipeline/cpu_core_map.c
new file mode 100644
index 0000000..0d83879
--- /dev/null
+++ b/examples/ip_pipeline/cpu_core_map.c
@@ -0,0 +1,465 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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%u/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%u/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 (lcore_socket_id < 0)
+ return -1;
+
+ 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 (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;
+
+ if ((((uint32_t) lcore_socket_id) == socket_id) &&
+ (((uint32_t) lcore_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;
+}
+
+void
+cpu_core_map_print(struct cpu_core_map *map)
+{
+#if 1
+ 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 %u:\n", socket_id);
+
+ for (core_id = 0; core_id < map->n_cores_per_socket; core_id++) {
+ printf("[%2u] = [", 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 = lcore_config[lcore_id].core_id;
+ uint32_t core_id_noncontig = cpu_core_map_get_core_id_linux(lcore_id);
+
+ printf(" %2d (%2u) ", lcore_id, core_id_noncontig);
+ }
+
+ printf("]\n");
+ }
+ }
+#else
+ uint32_t size, i;
+
+ if (map == NULL)
+ return;
+
+ size = map->n_max_sockets * map->n_max_cores_per_socket * map->n_max_ht_per_core;
+ printf("(n_sockets = %u, n_cores_per_socket = %u, n_ht_per_core = %u) [",
+ map->n_sockets, map->n_cores_per_socket, map->n_ht_per_core);
+ for (i = 0; i < size; i++)
+ printf("%d ", map->map[i]);
+ printf("]\n");
+#endif
+}
+
+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)
+{
+ if (map)
+ free(map);
+}
diff --git a/examples/ip_pipeline/cpu_core_map.h b/examples/ip_pipeline/cpu_core_map.h
new file mode 100644
index 0000000..5c2ec72
--- /dev/null
+++ b/examples/ip_pipeline/cpu_core_map.h
@@ -0,0 +1,69 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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/main.c b/examples/ip_pipeline/main.c
index eb750b6..a2d7ef0 100644
--- a/examples/ip_pipeline/main.c
+++ b/examples/ip_pipeline/main.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,135 +31,21 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <string.h>
-#include <sys/queue.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <getopt.h>
-#include <unistd.h>
+#include "app.h"
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memcpy.h>
-#include <rte_memzone.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.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_pci.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_ip.h>
-#include <rte_tcp.h>
-#include <rte_lpm.h>
-#include <rte_lpm6.h>
-
-#include "main.h"
+static struct app_params app;
int
main(int argc, char **argv)
{
- int ret;
-
- /* Init EAL */
- ret = rte_eal_init(argc, argv);
- if (ret < 0)
- return -1;
- argc -= ret;
- argv += ret;
+ rte_openlog_stream(stderr);
- /* Parse application arguments (after the EAL ones) */
- ret = app_parse_args(argc, argv);
- if (ret < 0) {
- app_print_usage(argv[0]);
- return -1;
- }
+ /* Config */
+ app_config_init(&app);
- /* Init */
- app_init();
+ app_config_args(&app, argc, argv);
- /* Launch per-lcore init on every lcore */
- rte_eal_mp_remote_launch(app_lcore_main_loop, NULL, CALL_MASTER);
+ app_config_parse(&app, app.config_file);
return 0;
}
-
-int
-app_lcore_main_loop(__attribute__((unused)) void *arg)
-{
- uint32_t core_id, i;
-
- core_id = rte_lcore_id();
-
- for (i = 0; i < app.n_cores; i++) {
- struct app_core_params *p = &app.cores[i];
-
- if (p->core_id != core_id)
- continue;
-
- switch (p->core_type) {
- case APP_CORE_MASTER:
- app_ping();
- app_main_loop_cmdline();
- return 0;
- case APP_CORE_RX:
- app_main_loop_pipeline_rx();
- /* app_main_loop_rx(); */
- return 0;
- case APP_CORE_TX:
- app_main_loop_pipeline_tx();
- /* app_main_loop_tx(); */
- return 0;
- case APP_CORE_PT:
- /* app_main_loop_pipeline_passthrough(); */
- app_main_loop_passthrough();
- return 0;
- case APP_CORE_FC:
- app_main_loop_pipeline_flow_classification();
- return 0;
- case APP_CORE_FW:
- case APP_CORE_RT:
- app_main_loop_pipeline_routing();
- return 0;
-
-#ifdef RTE_LIBRTE_ACL
- app_main_loop_pipeline_firewall();
- return 0;
-#else
- rte_exit(EXIT_FAILURE, "ACL not present in build\n");
-#endif
-
- case APP_CORE_IPV4_FRAG:
- app_main_loop_pipeline_ipv4_frag();
- return 0;
- case APP_CORE_IPV4_RAS:
- app_main_loop_pipeline_ipv4_ras();
- return 0;
-
- default:
- rte_panic("%s: Invalid core type for core %u\n",
- __func__, i);
- }
- }
-
- rte_panic("%s: Algorithmic error\n", __func__);
- return -1;
-}
diff --git a/examples/ip_pipeline/main.h b/examples/ip_pipeline/main.h
deleted file mode 100644
index 6085aaa..0000000
--- a/examples/ip_pipeline/main.h
+++ /dev/null
@@ -1,298 +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.
- */
-
-#ifndef _MAIN_H_
-#define _MAIN_H_
-
-#include <stdint.h>
-
-#include <rte_mempool.h>
-#include <rte_mbuf.h>
-#include <rte_ring.h>
-#include <rte_ethdev.h>
-
-#ifdef RTE_LIBRTE_ACL
-#include <rte_table_acl.h>
-#endif
-
-struct app_flow_key {
- union {
- struct {
- uint8_t ttl; /* needs to be set to 0 */
- uint8_t proto;
- uint16_t header_checksum; /* needs to be set to 0 */
- uint32_t ip_src;
- };
- uint64_t slab0;
- };
-
- union {
- struct {
- uint32_t ip_dst;
- uint16_t port_src;
- uint16_t port_dst;
- };
- uint64_t slab1;
- };
-} __attribute__((__packed__));
-
-struct app_arp_key {
- uint32_t nh_ip;
- uint32_t nh_iface;
-} __attribute__((__packed__));
-
-struct app_pkt_metadata {
- uint32_t signature;
- uint8_t reserved1[28];
-
- struct app_flow_key flow_key;
-
- struct app_arp_key arp_key;
- struct ether_addr nh_arp;
-
- uint8_t reserved3[2];
-} __attribute__((__packed__));
-
-#ifndef APP_MBUF_ARRAY_SIZE
-#define APP_MBUF_ARRAY_SIZE 256
-#endif
-
-struct app_mbuf_array {
- struct rte_mbuf *array[APP_MBUF_ARRAY_SIZE];
- uint32_t n_mbufs;
-};
-
-#ifndef APP_MAX_PORTS
-#define APP_MAX_PORTS 4
-#endif
-
-#ifndef APP_MAX_SWQ_PER_CORE
-#define APP_MAX_SWQ_PER_CORE 8
-#endif
-
-#define APP_SWQ_INVALID ((uint32_t)(-1))
-
-#define APP_SWQ_IN_REQ (APP_MAX_SWQ_PER_CORE - 1)
-
-#define APP_SWQ_OUT_RESP (APP_MAX_SWQ_PER_CORE - 1)
-
-enum app_core_type {
- APP_CORE_NONE = 0, /* Unused */
- APP_CORE_MASTER, /* Management */
- APP_CORE_RX, /* Reception */
- APP_CORE_TX, /* Transmission */
- APP_CORE_PT, /* Pass-through */
- APP_CORE_FC, /* Flow Classification */
- APP_CORE_FW, /* Firewall */
- APP_CORE_RT, /* Routing */
- APP_CORE_TM, /* Traffic Management */
- APP_CORE_IPV4_FRAG,/* IPv4 Fragmentation */
- APP_CORE_IPV4_RAS, /* IPv4 Reassembly */
-};
-
-struct app_core_params {
- uint32_t core_id;
- enum app_core_type core_type;
-
- /* SWQ map */
- uint32_t swq_in[APP_MAX_SWQ_PER_CORE];
- uint32_t swq_out[APP_MAX_SWQ_PER_CORE];
-} __rte_cache_aligned;
-
-struct app_params {
- /* CPU cores */
- struct app_core_params cores[RTE_MAX_LCORE];
- uint32_t n_cores;
-
- /* Ports*/
- uint32_t ports[APP_MAX_PORTS];
- uint32_t n_ports;
- uint32_t rsz_hwq_rx;
- uint32_t rsz_hwq_tx;
- uint32_t bsz_hwq_rd;
- uint32_t bsz_hwq_wr;
- struct rte_eth_conf port_conf;
- struct rte_eth_rxconf rx_conf;
- struct rte_eth_txconf tx_conf;
-
- /* SW Queues (SWQs) */
- struct rte_ring **rings;
- uint32_t rsz_swq;
- uint32_t bsz_swq_rd;
- uint32_t bsz_swq_wr;
-
- /* Buffer pool */
- struct rte_mempool *pool;
- struct rte_mempool *indirect_pool;
- uint32_t pool_buffer_size;
- uint32_t pool_size;
- uint32_t pool_cache_size;
-
- /* Message buffer pool */
- struct rte_mempool *msg_pool;
- uint32_t msg_pool_buffer_size;
- uint32_t msg_pool_size;
- uint32_t msg_pool_cache_size;
-
- /* Rule tables */
- uint32_t max_arp_rules;
- uint32_t max_routing_rules;
- uint32_t max_firewall_rules;
- uint32_t max_flow_rules;
-
- /* Processing */
- uint32_t ether_hdr_pop_push;
-} __rte_cache_aligned;
-
-extern struct app_params app;
-
-const char *app_core_type_id_to_string(enum app_core_type id);
-int app_core_type_string_to_id(const char *string, enum app_core_type *id);
-void app_cores_config_print(void);
-
-void app_check_core_params(void);
-struct app_core_params *app_get_core_params(uint32_t core_id);
-uint32_t app_get_first_core_id(enum app_core_type core_type);
-struct rte_ring *app_get_ring_req(uint32_t core_id);
-struct rte_ring *app_get_ring_resp(uint32_t core_id);
-
-int app_parse_args(int argc, char **argv);
-void app_print_usage(char *prgname);
-void app_init(void);
-void app_ping(void);
-int app_lcore_main_loop(void *arg);
-
-/* Hash functions */
-uint64_t test_hash(void *key, uint32_t key_size, uint64_t seed);
-uint32_t rte_jhash2_16(uint32_t *k, uint32_t initval);
-#if defined(__x86_64__)
-uint32_t rte_aeshash_16(uint64_t *k, uint64_t seed);
-uint32_t rte_crchash_16(uint64_t *k, uint64_t seed);
-#endif
-
-/* I/O with no pipeline */
-void app_main_loop_rx(void);
-void app_main_loop_tx(void);
-void app_main_loop_passthrough(void);
-
-/* Pipeline */
-void app_main_loop_pipeline_rx(void);
-void app_main_loop_pipeline_rx_frag(void);
-void app_main_loop_pipeline_tx(void);
-void app_main_loop_pipeline_tx_ras(void);
-void app_main_loop_pipeline_flow_classification(void);
-void app_main_loop_pipeline_firewall(void);
-void app_main_loop_pipeline_routing(void);
-void app_main_loop_pipeline_passthrough(void);
-void app_main_loop_pipeline_ipv4_frag(void);
-void app_main_loop_pipeline_ipv4_ras(void);
-
-/* Command Line Interface (CLI) */
-void app_main_loop_cmdline(void);
-
-/* Messages */
-enum app_msg_req_type {
- APP_MSG_REQ_PING,
- APP_MSG_REQ_FC_ADD,
- APP_MSG_REQ_FC_DEL,
- APP_MSG_REQ_FC_ADD_ALL,
- APP_MSG_REQ_FW_ADD,
- APP_MSG_REQ_FW_DEL,
- APP_MSG_REQ_RT_ADD,
- APP_MSG_REQ_RT_DEL,
- APP_MSG_REQ_ARP_ADD,
- APP_MSG_REQ_ARP_DEL,
- APP_MSG_REQ_RX_PORT_ENABLE,
- APP_MSG_REQ_RX_PORT_DISABLE,
-};
-
-struct app_msg_req {
- enum app_msg_req_type type;
- union {
- struct {
- uint32_t ip;
- uint8_t depth;
- uint8_t port;
- uint32_t nh_ip;
- } routing_add;
- struct {
- uint32_t ip;
- uint8_t depth;
- } routing_del;
- struct {
- uint8_t out_iface;
- uint32_t nh_ip;
- struct ether_addr nh_arp;
- } arp_add;
- struct {
- uint8_t out_iface;
- uint32_t nh_ip;
- } arp_del;
- struct {
- union {
- uint8_t key_raw[16];
- struct app_flow_key key;
- };
- uint8_t port;
- } flow_classif_add;
- struct {
- union {
- uint8_t key_raw[16];
- struct app_flow_key key;
- };
- } flow_classif_del;
-#ifdef RTE_LIBRTE_ACL
- struct {
- struct rte_table_acl_rule_add_params add_params;
- uint8_t port;
- } firewall_add;
- struct {
- struct rte_table_acl_rule_delete_params delete_params;
- } firewall_del;
-#endif
- struct {
- uint8_t port;
- } rx_up;
- struct {
- uint8_t port;
- } rx_down;
- };
-};
-
-struct app_msg_resp {
- int result;
-};
-
-#define APP_FLUSH 0xFF
-
-#endif /* _MAIN_H_ */
diff --git a/examples/ip_pipeline/pipeline.h b/examples/ip_pipeline/pipeline.h
new file mode 100644
index 0000000..400fd4b
--- /dev/null
+++ b/examples/ip_pipeline/pipeline.h
@@ -0,0 +1,87 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#ifndef __INCLUDE_PIPELINE_H__
+#define __INCLUDE_PIPELINE_H__
+
+#include <cmdline_parse.h>
+
+#include "pipeline_be.h"
+
+/*
+ * Pipeline type front-end operations
+ */
+
+typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params, void *arg);
+
+typedef int (*pipeline_fe_op_free)(void *pipeline);
+
+struct pipeline_fe_ops {
+ pipeline_fe_op_init f_init;
+ pipeline_fe_op_free f_free;
+ cmdline_parse_ctx_t *cmds;
+};
+
+/*
+ * Pipeline type
+ */
+
+struct pipeline_type {
+ const char *name;
+
+ /* pipeline back-end */
+ struct pipeline_be_ops *be_ops;
+
+ /* pipeline front-end */
+ struct pipeline_fe_ops *fe_ops;
+};
+
+static inline uint32_t
+pipeline_type_cmds_count(struct pipeline_type *ptype)
+{
+ cmdline_parse_ctx_t *cmds;
+ uint32_t n_cmds;
+
+ if (ptype->fe_ops == NULL)
+ return 0;
+
+ cmds = ptype->fe_ops->cmds;
+ if (cmds == NULL)
+ return 0;
+
+ for (n_cmds = 0; cmds[n_cmds]; n_cmds++);
+
+ return n_cmds;
+}
+
+#endif
diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h
new file mode 100644
index 0000000..a906553
--- /dev/null
+++ b/examples/ip_pipeline/pipeline_be.h
@@ -0,0 +1,253 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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_source_sink.h>
+#include <rte_pipeline.h>
+
+enum pipeline_port_in_type {
+ PIPELINE_PORT_IN_ETHDEV_READER,
+ PIPELINE_PORT_IN_RING_READER,
+ PIPELINE_PORT_IN_RING_READER_IPV4_FRAG,
+ PIPELINE_PORT_IN_RING_READER_IPV6_FRAG,
+ PIPELINE_PORT_IN_SCHED_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_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_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_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_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_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_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_WRITER_NODROP,
+ PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS,
+ PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS,
+ PIPELINE_PORT_OUT_SCHED_WRITER,
+ 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_writer_nodrop_params ring_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;
+ } 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_WRITER_NODROP:
+ return (void *) &p->params.ring_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_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_WRITER_NODROP:
+ return &rte_port_ring_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_SINK:
+ return &rte_port_sink_ops;
+ default:
+ return NULL;
+ }
+}
+
+#ifndef PIPELINE_NAME_SIZE
+#define PIPELINE_NAME_SIZE 32
+#endif
+
+#ifndef PIPELINE_MAX_PORT_IN
+#define PIPELINE_MAX_PORT_IN 16
+#endif
+
+#ifndef PIPELINE_MAX_PORT_OUT
+#define PIPELINE_MAX_PORT_OUT 16
+#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 32
+#endif
+
+struct pipeline_params {
+ char name[PIPELINE_NAME_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);
+
+typedef int (*pipeline_be_op_track)(void *pipeline, uint32_t port_in, uint32_t *port_out);
+
+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_be_op_track f_track;
+};
+
+#endif
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 02/11] ip_pipeline: added config checks
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 01/11] ip_pipeline: add parsing for config files with new syntax Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 03/11] ip_pipeline: modified init to match new params struct Maciej Gajdzica
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
From: Jasvinder Singh <jasvinder.singh@intel.com>
After loading configuration from a file, data integrity is checked.
Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
---
examples/ip_pipeline/Makefile | 1 +
examples/ip_pipeline/config_check.c | 387 +++++++++++++++++++++++++++++++++++
examples/ip_pipeline/main.c | 2 +
3 files changed, 390 insertions(+)
create mode 100644 examples/ip_pipeline/config_check.c
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index b0feb4f..bc50e71 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -45,6 +45,7 @@ APP = ip_pipeline
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c
CFLAGS += -O3
diff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c
new file mode 100644
index 0000000..972d0e7
--- /dev/null
+++ b/examples/ip_pipeline/config_check.c
@@ -0,0 +1,387 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#include <stdio.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 void
+check_links(struct app_params *app)
+{
+ uint32_t i;
+
+ /* Check that number of links matches the port mask */
+ APP_CHECK((app->n_links == __builtin_popcountll(app->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_local_q > rxq_max)
+ rxq_max = link->tcp_syn_local_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 = 1; i <= rxq_max; i++)
+ APP_CHECK(((link->arp_q == i) ||
+ (link->tcp_syn_local_q == i) ||
+ (link->ip_local_q == i) ||
+ (link->tcp_local_q == i) ||
+ (link->udp_local_q == i) ||
+ (link->sctp_local_q == i)),
+ "%s RXQs are not contiguous (A)\n", link->name);
+
+ n_rxq = app_link_get_n_rxq(app, link);
+
+ 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];
+
+ sprintf(name, "RXQ%u.%u", link_id, i);
+ APP_CHECK((APP_PARAM_FIND(app->hwq_in_params, name) >= 0),
+ "%s RXQs are not contiguous (C)\n", link->name);
+ }
+
+ /* Check that link RXQs are contiguous */
+ n_txq = app_link_get_n_txq(app, link);
+
+ for (i = 0; i < n_txq; i++){
+ char name[APP_PARAM_NAME_SIZE];
+
+ sprintf(name, "TXQ%u.%u", link_id, i);
+ APP_CHECK((APP_PARAM_FIND(app->hwq_out_params, name) >= 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);
+
+ 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);
+
+ 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_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_sources(struct app_params *app)
+{
+ uint32_t i;
+
+ for (i = 0; i < app->n_pktq_tm; 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 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_sources(app);
+ check_sinks(app);
+ check_msgqs(app);
+ check_pipelines(app);
+
+ return 0;
+}
diff --git a/examples/ip_pipeline/main.c b/examples/ip_pipeline/main.c
index a2d7ef0..612eea9 100644
--- a/examples/ip_pipeline/main.c
+++ b/examples/ip_pipeline/main.c
@@ -47,5 +47,7 @@ main(int argc, char **argv)
app_config_parse(&app, app.config_file);
+ app_config_check(&app);
+
return 0;
}
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 03/11] ip_pipeline: modified init to match new params struct
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 01/11] ip_pipeline: add parsing for config files with new syntax Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 02/11] ip_pipeline: added config checks Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 04/11] ip_pipeline: moved pipelines to separate folder Maciej Gajdzica
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
After changes in config parser, app params struct is changed and
requires modifications in initialization procedures.
Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
---
examples/ip_pipeline/Makefile | 1 +
examples/ip_pipeline/init.c | 1550 +++++++++++++++++++++++++++++------------
examples/ip_pipeline/main.c | 3 +
3 files changed, 1121 insertions(+), 433 deletions(-)
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index bc50e71..59bea5b 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -46,6 +46,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c
CFLAGS += -O3
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index d79762f..d6b1768 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,561 +32,1245 @@
*/
#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
#include <string.h>
-#include <sys/queue.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <getopt.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memcpy.h>
-#include <rte_memzone.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.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_pci.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_malloc.h>
-#include <rte_mbuf.h>
-#include <rte_string_fns.h>
+#include <rte_ether.h>
#include <rte_ip.h>
-#include <rte_tcp.h>
-#include <rte_lpm.h>
-#include <rte_lpm6.h>
-
-#include "main.h"
-
-#define NA APP_SWQ_INVALID
-
-struct app_params app = {
- /* CPU cores */
- .cores = {
- {0, APP_CORE_MASTER, {15, 16, 17, NA, NA, NA, NA, NA},
- {12, 13, 14, NA, NA, NA, NA, NA} },
- {0, APP_CORE_RX, {NA, NA, NA, NA, NA, NA, NA, 12},
- { 0, 1, 2, 3, NA, NA, NA, 15} },
- {0, APP_CORE_FC, { 0, 1, 2, 3, NA, NA, NA, 13},
- { 4, 5, 6, 7, NA, NA, NA, 16} },
- {0, APP_CORE_RT, { 4, 5, 6, 7, NA, NA, NA, 14},
- { 8, 9, 10, 11, NA, NA, NA, 17} },
- {0, APP_CORE_TX, { 8, 9, 10, 11, NA, NA, NA, NA},
- {NA, NA, NA, NA, NA, NA, NA, NA} },
- },
-
- /* Ports*/
- .n_ports = APP_MAX_PORTS,
- .rsz_hwq_rx = 128,
- .rsz_hwq_tx = 512,
- .bsz_hwq_rd = 64,
- .bsz_hwq_wr = 64,
-
- .port_conf = {
- .rxmode = {
- .split_hdr_size = 0,
- .header_split = 0, /* Header Split disabled */
- .hw_ip_checksum = 1, /* IP checksum offload enabled */
- .hw_vlan_filter = 0, /* VLAN filtering disabled */
- .jumbo_frame = 1, /* Jumbo Frame Support enabled */
- .max_rx_pkt_len = 9000, /* Jumbo Frame MAC pkt length */
- .hw_strip_crc = 0, /* CRC stripped by hardware */
- },
- .rx_adv_conf = {
- .rss_conf = {
- .rss_key = NULL,
- .rss_hf = ETH_RSS_IP,
- },
- },
- .txmode = {
- .mq_mode = ETH_MQ_TX_NONE,
- },
- },
-
- .rx_conf = {
- .rx_thresh = {
- .pthresh = 8,
- .hthresh = 8,
- .wthresh = 4,
- },
- .rx_free_thresh = 64,
- .rx_drop_en = 0,
- },
-
- .tx_conf = {
- .tx_thresh = {
- .pthresh = 36,
- .hthresh = 0,
- .wthresh = 0,
- },
- .tx_free_thresh = 0,
- .tx_rs_thresh = 0,
- },
-
- /* SWQs */
- .rsz_swq = 128,
- .bsz_swq_rd = 64,
- .bsz_swq_wr = 64,
-
- /* Buffer pool */
- .pool_buffer_size = RTE_MBUF_DEFAULT_BUF_SIZE,
- .pool_size = 32 * 1024,
- .pool_cache_size = 256,
-
- /* Message buffer pool */
- .msg_pool_buffer_size = 256,
- .msg_pool_size = 1024,
- .msg_pool_cache_size = 64,
-
- /* Rule tables */
- .max_arp_rules = 1 << 10,
- .max_firewall_rules = 1 << 5,
- .max_routing_rules = 1 << 24,
- .max_flow_rules = 1 << 24,
-
- /* Application processing */
- .ether_hdr_pop_push = 0,
-};
-
-struct app_core_params *
-app_get_core_params(uint32_t core_id)
-{
- uint32_t i;
+#include <rte_eal.h>
+#include <rte_malloc.h>
- for (i = 0; i < RTE_MAX_LCORE; i++) {
- struct app_core_params *p = &app.cores[i];
+#include "app.h"
+#include "pipeline.h"
- if (p->core_id != core_id)
- continue;
+#define APP_NAME_SIZE 32
- return p;
- }
+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(4, 32, 4, 0);
- return NULL;
+ if (app->core_map == NULL)
+ rte_panic("Cannot create CPU core map\n");
+
+ if (app->log_level >= APP_LOG_LOW)
+ cpu_core_map_print(app->core_map);
}
-static uint32_t
-app_get_n_swq_in(void)
+static void
+app_init_core_mask(struct app_params *app)
{
- uint32_t max_swq_id = 0, i, j;
+ uint64_t mask = 0;
+ uint32_t i;
- for (i = 0; i < RTE_MAX_LCORE; i++) {
- struct app_core_params *p = &app.cores[i];
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ int lcore_id;
- if (p->core_type == APP_CORE_NONE)
- continue;
+ lcore_id = cpu_core_map_get_lcore_id(app->core_map,
+ p->socket_id,
+ p->core_id,
+ p->hyper_th_id);
- for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++) {
- uint32_t swq_id = p->swq_in[j];
+ if (lcore_id < 0)
+ rte_panic("Cannot create CPU core mask\n");
- if ((swq_id != APP_SWQ_INVALID) &&
- (swq_id > max_swq_id))
- max_swq_id = swq_id;
- }
+ mask |= 1LLU << lcore_id;
}
- return (1 + max_swq_id);
+ app->core_mask = mask;
+ APP_LOG(app, HIGH, "CPU core mask = 0x%016lx", app->core_mask);
}
-static uint32_t
-app_get_n_swq_out(void)
+static void
+app_init_eal(struct app_params *app)
{
- uint32_t max_swq_id = 0, i, j;
+ char buffer[32];
+ struct app_eal_params *p = &app->eal_params;
+ uint32_t n_args = 0;
+ int status;
- for (i = 0; i < RTE_MAX_LCORE; i++) {
- struct app_core_params *p = &app.cores[i];
+ app->eal_argv[n_args++] = strdup(app->app_name);
- if (p->core_type == APP_CORE_NONE)
- continue;
+ snprintf(buffer, sizeof(buffer), "-c%lx", app->core_mask);
+ app->eal_argv[n_args++] = strdup(buffer);
- for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++) {
- uint32_t swq_id = p->swq_out[j];
+ if (p->coremap) {
+ snprintf(buffer, sizeof(buffer), "--lcores=%s", p->coremap);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- if ((swq_id != APP_SWQ_INVALID) &&
- (swq_id > max_swq_id))
- max_swq_id = swq_id;
- }
+ if (p->master_lcore_present) {
+ snprintf(buffer, sizeof(buffer), "--master-lcore=%u", p->master_lcore);
+ app->eal_argv[n_args++] = strdup(buffer);
}
- return (1 + max_swq_id);
-}
+ snprintf(buffer, sizeof(buffer), "-n%u", p->channels);
+ app->eal_argv[n_args++] = strdup(buffer);
-static uint32_t
-app_get_swq_in_count(uint32_t swq_id)
-{
- uint32_t n, i;
+ if (p->memory_present) {
+ snprintf(buffer, sizeof(buffer), "-m%u", p->memory);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->ranks_present) {
+ snprintf(buffer, sizeof(buffer), "-r%u", p->ranks);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- for (n = 0, i = 0; i < RTE_MAX_LCORE; i++) {
- struct app_core_params *p = &app.cores[i];
- uint32_t j;
+ if (p->pci_blacklist) {
+ snprintf(buffer, sizeof(buffer), "--pci-blacklist=%s", p->pci_blacklist);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- if (p->core_type == APP_CORE_NONE)
- continue;
+ if (p->pci_whitelist) {
+ snprintf(buffer, sizeof(buffer), "--pci-whitelist=%s", p->pci_whitelist);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++)
- if (p->swq_in[j] == swq_id)
- n++;
+ if (p->vdev) {
+ snprintf(buffer, sizeof(buffer), "--vdev=%s", p->vdev);
+ app->eal_argv[n_args++] = strdup(buffer);
}
- return n;
-}
+ if ((p->vmware_tsc_map_present) && p->vmware_tsc_map) {
+ snprintf(buffer, sizeof(buffer), "--vmware-tsc-map");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
-static uint32_t
-app_get_swq_out_count(uint32_t swq_id)
-{
- uint32_t n, i;
+ if (p->proc_type) {
+ snprintf(buffer, sizeof(buffer), "--proc-type=%s", p->proc_type);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- for (n = 0, i = 0; i < RTE_MAX_LCORE; i++) {
- struct app_core_params *p = &app.cores[i];
- uint32_t j;
+ if (p->syslog) {
+ snprintf(buffer, sizeof(buffer), "--syslog=%s", p->syslog);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- if (p->core_type == APP_CORE_NONE)
- continue;
+ if (p->log_level_present) {
+ snprintf(buffer, sizeof(buffer), "--log-level=%u", p->log_level);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++)
- if (p->swq_out[j] == swq_id)
- n++;
+ if ((p->version_present) && p->version) {
+ snprintf(buffer, sizeof(buffer), "-v");
+ app->eal_argv[n_args++] = strdup(buffer);
}
- return n;
-}
+ if ((p->help_present) && p->help) {
+ snprintf(buffer, sizeof(buffer), "--help");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
-void
-app_check_core_params(void)
-{
- uint32_t n_swq_in = app_get_n_swq_in();
- uint32_t n_swq_out = app_get_n_swq_out();
- uint32_t i;
+ if ((p->no_huge_present) && p->no_huge) {
+ snprintf(buffer, sizeof(buffer), "--no-huge");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- /* Check that range of SW queues is contiguous and each SW queue has
- exactly one reader and one writer */
- if (n_swq_in != n_swq_out)
- rte_panic("Number of input SW queues is not equal to the "
- "number of output SW queues\n");
+ if ((p->no_pci_present) && p->no_pci) {
+ snprintf(buffer, sizeof(buffer), "--no-pci");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- for (i = 0; i < n_swq_in; i++) {
- uint32_t n = app_get_swq_in_count(i);
+ if ((p->no_hpet_present) && p->no_hpet) {
+ snprintf(buffer, sizeof(buffer), "--no-hpet");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- if (n == 0)
- rte_panic("SW queue %u has no reader\n", i);
+ if ((p->no_shconf_present) && p->no_shconf) {
+ snprintf(buffer, sizeof(buffer), "--no-shconf");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- if (n > 1)
- rte_panic("SW queue %u has more than one reader\n", i);
+ if (p->add_driver) {
+ snprintf(buffer, sizeof(buffer), "-d=%s", p->add_driver);
+ app->eal_argv[n_args++] = strdup(buffer);
}
- for (i = 0; i < n_swq_out; i++) {
- uint32_t n = app_get_swq_out_count(i);
+ if (p->socket_mem) {
+ snprintf(buffer, sizeof(buffer), "--socket-mem=%s", p->socket_mem);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- if (n == 0)
- rte_panic("SW queue %u has no writer\n", i);
+ if (p->huge_dir) {
+ snprintf(buffer, sizeof(buffer), "--huge-dir=%s", p->huge_dir);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- if (n > 1)
- rte_panic("SW queue %u has more than one writer\n", i);
+ if (p->file_prefix) {
+ snprintf(buffer, sizeof(buffer), "--file-prefix=%s", p->file_prefix);
+ app->eal_argv[n_args++] = strdup(buffer);
}
- /* Check the request and response queues are valid */
- for (i = 0; i < RTE_MAX_LCORE; i++) {
- struct app_core_params *p = &app.cores[i];
- uint32_t ring_id_req, ring_id_resp;
+ if (p->base_virtaddr) {
+ snprintf(buffer, sizeof(buffer), "--base-virtaddr=%s", p->base_virtaddr);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- if ((p->core_type != APP_CORE_FC) &&
- (p->core_type != APP_CORE_FW) &&
- (p->core_type != APP_CORE_RT)) {
- continue;
- }
+ if ((p->create_uio_dev_present) && p->create_uio_dev) {
+ snprintf(buffer, sizeof(buffer), "--create-uio-dev");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- ring_id_req = p->swq_in[APP_SWQ_IN_REQ];
- if (ring_id_req == APP_SWQ_INVALID)
- rte_panic("Core %u of type %u has invalid request "
- "queue ID\n", p->core_id, p->core_type);
+ if (p->vfio_intr) {
+ snprintf(buffer, sizeof(buffer), "--vfio-intr=%s", p->vfio_intr);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
- ring_id_resp = p->swq_out[APP_SWQ_OUT_RESP];
- if (ring_id_resp == APP_SWQ_INVALID)
- rte_panic("Core %u of type %u has invalid response "
- "queue ID\n", p->core_id, p->core_type);
+ if ((p->xen_dom0_present) && (p->xen_dom0)) {
+ snprintf(buffer, sizeof(buffer), "--xen-dom0");
+ app->eal_argv[n_args++] = strdup(buffer);
}
- return;
+ snprintf(buffer, sizeof(buffer), "--");
+ app->eal_argv[n_args++] = strdup(buffer);
+
+ app->eal_argc = n_args;
+
+ APP_LOG(app, HIGH, "Initializing EAL ...");
+ status = rte_eal_init(app->eal_argc, app->eal_argv);
+ if (status < 0)
+ rte_panic("EAL init error\n");
}
-uint32_t
-app_get_first_core_id(enum app_core_type core_type)
+static void
+app_init_mempool(struct app_params *app)
{
uint32_t i;
- for (i = 0; i < RTE_MAX_LCORE; i++) {
- struct app_core_params *p = &app.cores[i];
-
- if (p->core_type == core_type)
- return p->core_id;
+ 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_mempool_create(
+ p->name,
+ p->pool_size,
+ p->buffer_size,
+ p->cache_size,
+ sizeof(struct rte_pktmbuf_pool_private),
+ rte_pktmbuf_pool_init, NULL,
+ rte_pktmbuf_init, NULL,
+ p->cpu_socket_id,
+ 0);
+
+ if (app->mempool[i] == NULL)
+ rte_panic("%s init error\n", p->name);
}
+}
- return RTE_MAX_LCORE;
+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_arp_del(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_DELETE,
+ &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_local_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_tcp_syn_del(struct app_link_params *link)
+{
+ struct rte_eth_syn_filter filter = {
+ .hig_pri = 1,
+ .queue = link->tcp_syn_local_q,
+ };
+
+ return rte_eth_dev_filter_ctrl(link->pmd_id,
+ RTE_ETH_FILTER_SYN,
+ RTE_ETH_FILTER_DELETE,
+ &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);
}
-struct rte_ring *
-app_get_ring_req(uint32_t core_id)
+static inline int
+app_link_filter_udp_add(struct app_link_params *l1, struct app_link_params *l2)
{
- struct app_core_params *p = app_get_core_params(core_id);
- uint32_t ring_req_id = p->swq_in[APP_SWQ_IN_REQ];
+ 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);
+}
- return app.rings[ring_req_id];
+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);
}
-struct rte_ring *
-app_get_ring_resp(uint32_t core_id)
+static inline int
+app_link_filter_sctp_add(struct app_link_params *l1, struct app_link_params *l2)
{
- struct app_core_params *p = app_get_core_params(core_id);
- uint32_t ring_resp_id = p->swq_out[APP_SWQ_OUT_RESP];
+ 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);
+}
- return app.rings[ring_resp_id];
+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_init_mbuf_pools(void)
-{
- /* Init the buffer pool */
- RTE_LOG(INFO, USER1, "Creating the mbuf pool ...\n");
- app.pool = rte_pktmbuf_pool_create("mempool", app.pool_size,
- app.pool_cache_size, 0, app.pool_buffer_size, rte_socket_id());
- if (app.pool == NULL)
- rte_panic("Cannot create mbuf pool\n");
-
- /* Init the indirect buffer pool */
- RTE_LOG(INFO, USER1, "Creating the indirect mbuf pool ...\n");
- app.indirect_pool = rte_pktmbuf_pool_create("indirect mempool",
- app.pool_size, app.pool_cache_size,
- sizeof(struct app_pkt_metadata), 0, rte_socket_id());
- if (app.indirect_pool == NULL)
- rte_panic("Cannot create mbuf pool\n");
-
- /* Init the message buffer pool */
- RTE_LOG(INFO, USER1, "Creating the message pool ...\n");
- app.msg_pool = rte_mempool_create(
- "mempool msg",
- app.msg_pool_size,
- app.msg_pool_buffer_size,
- app.msg_pool_cache_size,
- 0,
- NULL, NULL,
- rte_ctrlmbuf_init, NULL,
- rte_socket_id(),
- 0);
- if (app.msg_pool == NULL)
- rte_panic("Cannot create message pool\n");
+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 (%u): Adding ARP filter (queue = %u)",
+ cp->name, cp->pmd_id, cp->arp_q);
+
+ if (status)
+ rte_panic("%s (%u): Error adding ARP filter (queue = %u) (%d)\n",
+ cp->name, cp->pmd_id, cp->arp_q, status);
+ }
}
static void
-app_init_rings(void)
+app_link_set_tcp_syn_filter(struct app_params *app, struct app_link_params *cp)
{
- uint32_t n_swq, i;
+ if (cp->tcp_syn_local_q != 0) {
+ int status = app_link_filter_tcp_syn_add(cp);
+
+ APP_LOG(app, LOW, "%s (%u): Adding TCP SYN filter (queue = %u)",
+ cp->name, cp->pmd_id, cp->tcp_syn_local_q);
+
+ if (status)
+ rte_panic("%s (%u): Error adding TCP SYN filter (queue = %u) (%d)\n",
+ cp->name, cp->pmd_id, cp->tcp_syn_local_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 (%u): Adding IP filter "
+ "(queue= %u, IP = 0x%08x)",
+ p->name, p->pmd_id, p->ip_local_q, cp->ip);
+
+ if (status)
+ rte_panic("%s (%u): Error adding IP filter "
+ "(queue= %u, IP = 0x%08x) (%d)\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 (%u): Adding TCP filter "
+ "(queue = %u, IP = 0x%08x)",
+ p->name, p->pmd_id, p->tcp_local_q, cp->ip);
+
+ if (status)
+ rte_panic("%s (%u): Error adding TCP filter "
+ "(queue = %u, IP = 0x%08x) (%d)\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 (%u): Adding UDP filter "
+ "(queue = %u, IP = 0x%08x)",
+ p->name, p->pmd_id, p->udp_local_q, cp->ip);
+
+ if (status)
+ rte_panic("%s (%u): Error adding UDP filter "
+ "(queue = %u, IP = 0x%08x) (%d)\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 (%u): Adding SCTP filter "
+ "(queue = %u, IP = 0x%08x)",
+ p->name, p->pmd_id, p->sctp_local_q, cp->ip);
+
+ if (status)
+ rte_panic("%s (%u): Error adding SCTP filter "
+ "(queue = %u, IP = 0x%08x) (%d)\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);
+ if (status < 0)
+ rte_panic("%s (%u): PMD set up error %d\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;
- n_swq = app_get_n_swq_in();
- RTE_LOG(INFO, USER1, "Initializing %u SW rings ...\n", n_swq);
+ /* PMD link down */
+ rte_eth_dev_set_link_down(cp->pmd_id);
- app.rings = rte_malloc_socket(NULL, n_swq * sizeof(struct rte_ring *),
- RTE_CACHE_LINE_SIZE, rte_socket_id());
- if (app.rings == NULL)
- rte_panic("Cannot allocate memory to store ring pointers\n");
+ /* Mark link as DOWN */
+ cp->state = 0;
- for (i = 0; i < n_swq; i++) {
- struct rte_ring *ring;
- char name[32];
+ /* Return if current link IP is not valid */
+ if (cp->ip == 0)
+ return;
- snprintf(name, sizeof(name), "app_ring_%u", i);
+ /* 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];
- ring = rte_ring_create(
- name,
- app.rsz_swq,
- rte_socket_id(),
- RING_F_SP_ENQ | RING_F_SC_DEQ);
+ /* IP */
+ if (p->ip_local_q != 0) {
+ int status = app_link_filter_ip_del(p, cp);
- if (ring == NULL)
- rte_panic("Cannot create ring %u\n", i);
+ APP_LOG(app, LOW, "%s (%u): Deleting IP filter "
+ "(queue = %u, IP = 0x%x)",
+ p->name, p->pmd_id, p->ip_local_q, cp->ip);
- app.rings[i] = ring;
+ if (status)
+ rte_panic("%s (%u): Error deleting IP filter "
+ "(queue = %u, IP = 0x%x) (%d)\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 (%u): Deleting TCP filter "
+ "(queue = %u, IP = 0x%x)",
+ p->name, p->pmd_id, p->tcp_local_q, cp->ip);
+
+ if (status)
+ rte_panic("%s (%u): Error deleting TCP filter "
+ "(queue = %u, IP = 0x%x) (%d)\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 (%u): Deleting UDP filter "
+ "(queue = %u, IP = 0x%x)",
+ p->name, p->pmd_id, p->udp_local_q, cp->ip);
+
+ if (status)
+ rte_panic("%s (%u): Error deleting UDP filter "
+ "(queue = %u, IP = 0x%x) (%d)\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 (%u): Deleting SCTP filter "
+ "(queue = %u, IP = 0x%x)",
+ p->name, p->pmd_id, p->sctp_local_q, cp->ip);
+
+ if (status)
+ rte_panic("%s (%u): Error deleting SCTP filter "
+ "(queue = %u, IP = 0x%x) (%d)\n",
+ p->name, p->pmd_id, p->sctp_local_q, cp->ip, status);
+ }
}
}
static void
-app_ports_check_link(void)
+app_check_link(struct app_params *app)
{
- uint32_t all_ports_up, i;
+ uint32_t all_links_up, i;
- all_ports_up = 1;
+ all_links_up = 1;
- for (i = 0; i < app.n_ports; i++) {
- struct rte_eth_link link;
- uint32_t port;
+ for (i = 0; i < app->n_links; i++) {
+ struct app_link_params *p = &app->link_params[i];
+ struct rte_eth_link link_params;
- port = app.ports[i];
- memset(&link, 0, sizeof(link));
- rte_eth_link_get_nowait(port, &link);
- RTE_LOG(INFO, USER1, "Port %u (%u Gbps) %s\n",
- port,
- link.link_speed / 1000,
- link.link_status ? "UP" : "DOWN");
+ memset(&link_params, 0, sizeof(link_params));
+ rte_eth_link_get(p->pmd_id, &link_params);
- if (link.link_status == 0)
- all_ports_up = 0;
+ APP_LOG(app, HIGH, "%s (%u) (%u Gbps) %s",
+ p->name,
+ p->pmd_id,
+ link_params.link_speed / 1000,
+ link_params.link_status ? "UP" : "DOWN");
+
+ if (link_params.link_status == 0)
+ all_links_up = 0;
}
- if (all_ports_up == 0)
- rte_panic("Some NIC ports are DOWN\n");
+ if (all_links_up == 0)
+ rte_panic("Some links are DOWN\n");
}
static void
-app_init_ports(void)
+app_init_link(struct app_params *app)
{
uint32_t i;
- /* Init NIC ports, then start the ports */
- for (i = 0; i < app.n_ports; i++) {
- uint32_t port;
- int ret;
-
- port = app.ports[i];
- RTE_LOG(INFO, USER1, "Initializing NIC port %u ...\n", port);
-
- /* Init port */
- ret = rte_eth_dev_configure(
- port,
- 1,
- 1,
- &app.port_conf);
- if (ret < 0)
- rte_panic("Cannot init NIC port %u (%d)\n", port, ret);
- rte_eth_promiscuous_enable(port);
-
- /* Init RX queues */
- ret = rte_eth_rx_queue_setup(
- port,
- 0,
- app.rsz_hwq_rx,
- rte_eth_dev_socket_id(port),
- &app.rx_conf,
- app.pool);
- if (ret < 0)
- rte_panic("Cannot init RX for port %u (%d)\n",
- (uint32_t) port, ret);
-
- /* Init TX queues */
- ret = rte_eth_tx_queue_setup(
- port,
- 0,
- app.rsz_hwq_tx,
- rte_eth_dev_socket_id(port),
- &app.tx_conf);
- if (ret < 0)
- rte_panic("Cannot init TX for port %u (%d)\n", port,
- ret);
-
- /* Start port */
- ret = rte_eth_dev_start(port);
- if (ret < 0)
- rte_panic("Cannot start port %u (%d)\n", port, ret);
- }
-
- app_ports_check_link();
-}
-
-#define APP_PING_TIMEOUT_SEC 5
+ for (i = 0; i < app->n_links; i++) {
+ struct app_link_params *p_link = &app->link_params[i];
+ uint32_t link_id, n_hwq_in ,n_hwq_out, j;
+ int status;
-void
-app_ping(void)
+ sscanf(p_link->name, "LINK%u", &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_LOG(app, HIGH, "Initializing %s (%u) (%u RXQ, %u TXQ) ...",
+ p_link->name,
+ p_link->pmd_id,
+ n_hwq_in,
+ n_hwq_out);
+
+ /* LINK */
+ status = rte_eth_dev_configure(
+ p_link->pmd_id,
+ n_hwq_in,
+ n_hwq_out,
+ &p_link->conf);
+ if (status < 0)
+ rte_panic("%s (%d): init error (%d)\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;
+
+ sscanf(p_rxq->name, "RXQ%u.%u",
+ &rxq_link_id, &rxq_queue_id);
+ if (rxq_link_id != link_id)
+ continue;
+
+ status = rte_eth_rx_queue_setup(
+ p_link->pmd_id,
+ rxq_queue_id,
+ p_rxq->size,
+ rte_eth_dev_socket_id(p_link->pmd_id),
+ &p_rxq->conf,
+ app->mempool[p_rxq->mempool_id]);
+ if (status < 0)
+ rte_panic("%s (%u): %s init error (%d)\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;
+
+ sscanf(p_txq->name, "TXQ%u.%u",
+ &txq_link_id, &txq_queue_id);
+ if (txq_link_id != link_id)
+ continue;
+
+ status = rte_eth_tx_queue_setup(
+ p_link->pmd_id,
+ txq_queue_id,
+ p_txq->size,
+ rte_eth_dev_socket_id(p_link->pmd_id),
+ &p_txq->conf);
+ if (status < 0)
+ rte_panic("%s (%u): %s init error (%d)\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 %d)\n",
+ p_link->name, status);
+
+ /* LINK UP */
+ app_link_set_arp_filter(app, p_link);
+ app_link_set_tcp_syn_filter(app, p_link);
+ app_link_up_internal(app, p_link);
+ }
+
+ app_check_link(app);
+}
+
+static void
+app_init_swq(struct app_params *app)
{
- unsigned i;
- uint64_t timestamp, diff_tsc;
+ uint32_t i;
- const uint64_t timeout = rte_get_tsc_hz() * APP_PING_TIMEOUT_SEC;
+ for (i = 0; i < app->n_pktq_swq; i++) {
+ struct app_pktq_swq_params *p = &app->swq_params[i];
- for (i = 0; i < RTE_MAX_LCORE; i++) {
- struct app_core_params *p = &app.cores[i];
- struct rte_ring *ring_req, *ring_resp;
- void *msg;
- struct app_msg_req *req;
+ APP_LOG(app, HIGH, "Initializing %s...", p->name);
+ app->swq[i] = rte_ring_create(
+ p->name,
+ p->size,
+ p->cpu_socket_id,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+
+ 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;
- if ((p->core_type != APP_CORE_FC) &&
- (p->core_type != APP_CORE_FW) &&
- (p->core_type != APP_CORE_RT) &&
- (p->core_type != APP_CORE_RX))
- continue;
+ 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 = rte_eth_dev_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 %u init error (%d)\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 %u pipe %u "
+ "(profile %d) init error (%d)\n",
+ p_tm->name, subport_id, pipe_id, profile_id, status);
+ }
+ }
+ }
+}
+
+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);
+ }
+}
+
+static void app_pipeline_params_get(struct app_params *app,
+ struct app_pipeline_params *p_in,
+ struct pipeline_params *p_out)
+{
+ uint32_t i;
+
+ strcpy(p_out->name, p_in->name);
- ring_req = app_get_ring_req(p->core_id);
- ring_resp = app_get_ring_resp(p->core_id);
+ p_out->socket_id = (int) p_in->socket_id;
- /* Fill request message */
- msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
+ p_out->log_level = app->log_level;
- req = (struct app_msg_req *)
- rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- req->type = APP_MSG_REQ_PING;
+ /* 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];
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
+ 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;
- /* Wait for response */
- timestamp = rte_rdtsc();
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- diff_tsc = rte_rdtsc() - timestamp;
+ sscanf(p_hwq_in->name, "RXQ%u.%u", &rxq_link_id, &rxq_queue_id);
- if (unlikely(diff_tsc > timeout))
- rte_panic("Core %u of type %d does not respond "
- "to requests\n", p->core_id,
- p->core_type);
- } while (status != 0);
+ 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:
+ 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;
+ /* What about frag and ras ports? */
+ 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;
+ case APP_PKTQ_IN_SOURCE:
+ out->type = PIPELINE_PORT_IN_SOURCE;
+ out->params.source.mempool = app->mempool[in->id];
+ out->burst_size = app->source_params[in->id].burst;
+ break;
+ default:
+ break;
+ }
+ }
- /* Free message buffer */
- rte_ctrlmbuf_free(msg);
+ /* 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%u.%u", &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:
+ 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;
+ }
+ /* What about frag and ras ports? */
+ 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;
+ }
+ case APP_PKTQ_OUT_SINK:
+ out->type = PIPELINE_PORT_OUT_SINK;
+ 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_etc(void)
+app_init_pipelines(struct app_params *app)
{
- if ((app_get_first_core_id(APP_CORE_IPV4_FRAG) != RTE_MAX_LCORE) ||
- (app_get_first_core_id(APP_CORE_IPV4_RAS) != RTE_MAX_LCORE)) {
- RTE_LOG(INFO, USER1,
- "Activating the Ethernet header pop/push ...\n");
- app.ether_hdr_pop_push = 1;
+ 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->timer_period = (rte_get_tsc_hz() * params->timer_period) / 1000;
}
}
-void
-app_init(void)
+static void
+app_init_threads(struct app_params *app)
{
- if ((sizeof(struct app_pkt_metadata) % RTE_CACHE_LINE_SIZE) != 0)
- rte_panic("Application pkt meta-data size mismatch\n");
+ 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%uc%u%s\n",
+ params->socket_id,
+ params->core_id,
+ (params->hyper_th_id)? "h" : "");
+
+ t = &app->thread_data[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->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;
+
+ 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_msgq(app);
+
+ app_init_pipelines(app);
+ app_init_threads(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;
- app_check_core_params();
+ /* Check for available slots in the application commands array */
+ if (n_cmds > APP_MAX_CMDS - app->n_cmds)
+ return -ENOMEM;
- app_init_mbuf_pools();
- app_init_rings();
- app_init_ports();
- app_init_etc();
+ /* Push pipeline commands into the application */
+ memcpy(&app->cmds[app->n_cmds],
+ cmds,
+ n_cmds * sizeof(cmdline_parse_ctx_t *));
- RTE_LOG(INFO, USER1, "Initialization completed\n");
+ 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/main.c b/examples/ip_pipeline/main.c
index 612eea9..ef68c86 100644
--- a/examples/ip_pipeline/main.c
+++ b/examples/ip_pipeline/main.c
@@ -49,5 +49,8 @@ main(int argc, char **argv)
app_config_check(&app);
+ /* Init */
+ app_init(&app);
+
return 0;
}
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 04/11] ip_pipeline: moved pipelines to separate folder
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
` (2 preceding siblings ...)
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 03/11] ip_pipeline: modified init to match new params struct Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 05/11] ip_pipeline: added master pipeline Maciej Gajdzica
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
Moved pipelines to separate folder, removed not needed pipelines and
modified Makefile to match that change.
Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
---
examples/ip_pipeline/Makefile | 9 +-
examples/ip_pipeline/pipeline/pipeline_common_be.c | 204 ++++
examples/ip_pipeline/pipeline/pipeline_common_be.h | 161 +++
examples/ip_pipeline/pipeline/pipeline_common_fe.c | 1283 ++++++++++++++++++++
examples/ip_pipeline/pipeline/pipeline_common_fe.h | 248 ++++
examples/ip_pipeline/pipeline/pipeline_firewall.c | 313 +++++
.../pipeline/pipeline_flow_classification.c | 306 +++++
examples/ip_pipeline/pipeline/pipeline_master.c | 47 +
examples/ip_pipeline/pipeline/pipeline_master.h | 41 +
examples/ip_pipeline/pipeline/pipeline_master_be.c | 146 +++
examples/ip_pipeline/pipeline/pipeline_master_be.h | 41 +
.../ip_pipeline/pipeline/pipeline_passthrough.c | 213 ++++
examples/ip_pipeline/pipeline/pipeline_routing.c | 474 ++++++++
examples/ip_pipeline/pipeline_firewall.c | 313 -----
.../ip_pipeline/pipeline_flow_classification.c | 306 -----
examples/ip_pipeline/pipeline_ipv4_frag.c | 184 ---
examples/ip_pipeline/pipeline_ipv4_ras.c | 181 ---
examples/ip_pipeline/pipeline_passthrough.c | 213 ----
examples/ip_pipeline/pipeline_routing.c | 474 --------
examples/ip_pipeline/pipeline_rx.c | 385 ------
examples/ip_pipeline/pipeline_tx.c | 283 -----
21 files changed, 3485 insertions(+), 2340 deletions(-)
create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_be.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_fe.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_fe.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_master.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_master.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_master_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_master_be.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_routing.c
delete mode 100644 examples/ip_pipeline/pipeline_firewall.c
delete mode 100644 examples/ip_pipeline/pipeline_flow_classification.c
delete mode 100644 examples/ip_pipeline/pipeline_ipv4_frag.c
delete mode 100644 examples/ip_pipeline/pipeline_ipv4_ras.c
delete mode 100644 examples/ip_pipeline/pipeline_passthrough.c
delete mode 100644 examples/ip_pipeline/pipeline_routing.c
delete mode 100644 examples/ip_pipeline/pipeline_rx.c
delete mode 100644 examples/ip_pipeline/pipeline_tx.c
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index 59bea5b..213e879 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -36,11 +36,17 @@ endif
# Default target, can be overridden by command line or environment
RTE_TARGET ?= x86_64-native-linuxapp-gcc
+DIRS-(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline
+
include $(RTE_SDK)/mk/rte.vars.mk
# binary name
APP = ip_pipeline
+VPATH += $(SRCDIR)/pipeline
+
+INC += $(wildcard *.h) $(wildcard pipeline/*.h)
+
# all source are stored in SRCS-y
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c
@@ -49,7 +55,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c
+CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline
CFLAGS += -O3
-CFLAGS += $(WERROR_FLAGS)
+CFLAGS += $(WERROR_FLAGS) -Wno-error=unused-function -Wno-error=unused-variable
include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_be.c b/examples/ip_pipeline/pipeline/pipeline_common_be.c
new file mode 100644
index 0000000..1cb107a
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_common_be.c
@@ -0,0 +1,204 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#include <rte_common.h>
+#include <rte_ring.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
new file mode 100644
index 0000000..4340ab5
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_common_be.h
@@ -0,0 +1,161 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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;
+};
+
+#define PLOG_HIGH 1
+
+#define PLOG_LOW 2
+
+#define PLOG(p, level, fmt, ...) \
+do { \
+ if (p->log_level >= PLOG_ ## 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
new file mode 100644
index 0000000..4a9f8ef
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c
@@ -0,0 +1,1283 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#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 <cmdline_parse_ipaddr.h>
+#include <cmdline_parse_etheraddr.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+
+#include "pipeline_common_fe.h"
+
+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_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%u 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 = (~0) << (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", p->name);
+ return -1;
+ }
+ }
+
+ if ((depth == 0) || (depth > 32)) {
+ APP_LOG(app, HIGH, "Illegal value for depth parameter (%u)", 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;
+
+ /* 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%u is not a valid link", link_id);
+ return -1;
+ }
+
+ /* 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);
+
+ return 0;
+}
+
+int
+app_link_down(struct app_params *app,
+ uint32_t link_id)
+{
+ struct app_link_params *p;
+
+ /* 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%u is not a valid link", link_id);
+ return -1;
+ }
+
+ /* 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);
+
+ 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");
+}
+
+cmdline_parse_token_string_t cmd_ping_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_ping_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_ping_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ping_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_ping_ping_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping_string, "ping");
+
+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 %u - stats for input port %u:\n"
+ "\tPkts in: %lu\n"
+ "\tPkts dropped by AH: %lu\n"
+ "\tPkts dropped by other: %lu\n",
+ params->pipeline_id,
+ params->port_in_id,
+ stats.stats.n_pkts_in,
+ stats.n_pkts_dropped_by_ah,
+ stats.stats.n_pkts_drop);
+}
+
+cmdline_parse_token_string_t cmd_stats_port_in_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_stats_port_in_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_stats_port_in_stats_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, stats_string, "stats");
+
+cmdline_parse_token_string_t cmd_stats_port_in_port_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, port_string, "port");
+
+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);
+
+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 %u - stats for output port %u:\n"
+ "\tPkts in: %lu\n"
+ "\tPkts dropped by AH: %lu\n"
+ "\tPkts dropped by other: %lu\n",
+ params->pipeline_id,
+ params->port_out_id,
+ stats.stats.n_pkts_in,
+ stats.n_pkts_dropped_by_ah,
+ stats.stats.n_pkts_drop);
+}
+
+cmdline_parse_token_string_t cmd_stats_port_out_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, p_string,
+ "p");
+
+cmdline_parse_token_num_t cmd_stats_port_out_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_stats_port_out_stats_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, stats_string, "stats");
+
+cmdline_parse_token_string_t cmd_stats_port_out_port_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, port_string, "port");
+
+cmdline_parse_token_string_t cmd_stats_port_out_out_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, out_string, "out");
+
+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);
+
+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 %u - stats for table %u:\n"
+ "\tPkts in: %lu\n"
+ "\tPkts in with lookup miss: %lu\n"
+ "\tPkts in with lookup hit dropped by AH: %lu\n"
+ "\tPkts in with lookup hit dropped by others: %lu\n"
+ "\tPkts in with lookup miss dropped by AH: %lu\n"
+ "\tPkts in with lookup miss dropped by others: %lu\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);
+}
+
+cmdline_parse_token_string_t cmd_stats_table_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_stats_table_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_stats_table_stats_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, stats_string, "stats");
+
+cmdline_parse_token_string_t cmd_stats_table_table_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, table_string, "table");
+
+cmdline_parse_token_num_t cmd_stats_table_table_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, table_id, UINT32);
+
+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");
+}
+
+cmdline_parse_token_string_t cmd_port_in_enable_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_port_in_enable_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_port_in_enable_port_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, port_string,
+ "port");
+
+cmdline_parse_token_string_t cmd_port_in_enable_in_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, in_string, "in");
+
+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);
+
+cmdline_parse_token_string_t cmd_port_in_enable_enable_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, enable_string, "enable");
+
+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");
+}
+
+cmdline_parse_token_string_t cmd_port_in_disable_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_port_in_disable_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_port_in_disable_port_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, port_string, "port");
+
+cmdline_parse_token_string_t cmd_port_in_disable_in_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, in_string, "in");
+
+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);
+
+cmdline_parse_token_string_t cmd_port_in_disable_disable_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, disable_string, "disable");
+
+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 =(~0) << (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;
+
+ printf("%s: flags=<%s>\n",
+ p->name,
+ (p->state)? "UP" : "DOWN");
+
+ if (p->ip)
+ printf("\tinet %u.%u.%u.%u netmask %u.%u.%u.%u broadcast %u.%u.%u.%u\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 %02x:%02x:%02x:%02x:%02x:%02x\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 mcast %" PRIu64
+ " fdirmatch %" PRIu64
+ " fdirmiss %" PRIu64
+ " lb-packets %" PRIu64
+ " lb-bytes %" PRIu64
+ " xon %" PRIu64
+ " xoff %" PRIu64 "\n",
+ stats.imcasts,
+ stats.fdirmatch,
+ stats.fdirmiss,
+ stats.ilbpackets,
+ stats.ilbbytes,
+ stats.rx_pause_xon,
+ stats.rx_pause_xoff);
+
+ printf("\tRX errors %" PRIu64
+ " missed %" PRIu64
+ " badcrc %" PRIu64
+ " badlen %" PRIu64
+ " no-mbuf %" PRIu64
+ "\n",
+ stats.ierrors,
+ stats.imissed,
+ stats.ibadcrc,
+ stats.ibadlen,
+ stats.rx_nombuf);
+
+ printf("\tTX packets %" PRIu64
+ " bytes %" PRIu64 "\n",
+ stats.opackets,
+ stats.obytes);
+
+ printf("\tTX lb-packets %" PRIu64
+ " lb-bytes %" PRIu64
+ " xon %" PRIu64
+ " xoff %" PRIu64
+ "\n",
+ stats.olbpackets,
+ stats.olbbytes,
+ stats.tx_pause_xon,
+ stats.tx_pause_xoff);
+
+ printf("\tTX errors %" PRIu64
+ "\n",
+ stats.oerrors);
+
+ printf("\n");
+}
+
+struct cmd_link_config_result {
+ cmdline_fixed_string_t link_string;
+ uint32_t link_id;
+ cmdline_fixed_string_t config_string;
+ cmdline_ipaddr_t ip;
+ uint32_t depth;
+};
+
+static void
+cmd_link_config_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_link_config_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ uint32_t link_id = params->link_id;
+ uint32_t ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr);
+ uint32_t depth = params->depth;
+
+ status = app_link_config(app, link_id, ip, depth);
+ if(status)
+ printf("Command failed\n");
+ else {
+ struct app_link_params *p;
+
+ APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
+ print_link_info(p);
+ }
+}
+
+cmdline_parse_token_string_t cmd_link_config_link_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, link_string, "link");
+
+cmdline_parse_token_num_t cmd_link_config_link_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, link_id, UINT32);
+
+cmdline_parse_token_string_t cmd_link_config_config_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, config_string, "config");
+
+cmdline_parse_token_ipaddr_t cmd_link_config_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_link_config_result, ip);
+
+cmdline_parse_token_num_t cmd_link_config_depth =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, depth, UINT32);
+
+cmdline_parse_inst_t cmd_link_config = {
+ .f = cmd_link_config_parsed,
+ .data = NULL,
+ .help_str = "Link configuration",
+ .tokens = {
+ (void *)&cmd_link_config_link_string,
+ (void *)&cmd_link_config_link_id,
+ (void *)&cmd_link_config_config_string,
+ (void *)&cmd_link_config_ip,
+ (void *)&cmd_link_config_depth,
+ NULL,
+ },
+};
+
+/*
+ * link up
+ */
+
+struct cmd_link_up_result {
+ cmdline_fixed_string_t link_string;
+ uint32_t link_id;
+ cmdline_fixed_string_t up_string;
+};
+
+static void
+cmd_link_up_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_link_up_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ status = app_link_up(app, params->link_id);
+ if(status != 0)
+ printf("Command failed\n");
+ else {
+ struct app_link_params *p;
+
+ APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id, p);
+ print_link_info(p);
+ }
+}
+
+cmdline_parse_token_string_t cmd_link_up_link_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, link_string, "link");
+
+cmdline_parse_token_num_t cmd_link_up_link_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_up_result, link_id, UINT32);
+
+cmdline_parse_token_string_t cmd_link_up_up_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, up_string, "up");
+
+cmdline_parse_inst_t cmd_link_up = {
+ .f = cmd_link_up_parsed,
+ .data = NULL,
+ .help_str = "Link UP",
+ .tokens = {
+ (void *)&cmd_link_up_link_string,
+ (void *)&cmd_link_up_link_id,
+ (void *)&cmd_link_up_up_string,
+ NULL,
+ },
+};
+
+/*
+ * link down
+ */
+
+struct cmd_link_down_result {
+ cmdline_fixed_string_t link_string;
+ uint32_t link_id;
+ cmdline_fixed_string_t down_string;
+};
+
+static void
+cmd_link_down_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_link_down_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ status = app_link_down(app, params->link_id);
+ if(status != 0)
+ printf("Command failed\n");
+ else {
+ struct app_link_params *p;
+
+ APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id, p);
+ print_link_info(p);
+ }
+}
+
+cmdline_parse_token_string_t cmd_link_down_link_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, link_string, "link");
+
+cmdline_parse_token_num_t cmd_link_down_link_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_down_result, link_id, UINT32);
+
+cmdline_parse_token_string_t cmd_link_down_down_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, down_string, "down");
+
+cmdline_parse_inst_t cmd_link_down = {
+ .f = cmd_link_down_parsed,
+ .data = NULL,
+ .help_str = "Link DOWN",
+ .tokens = {
+ (void *) &cmd_link_down_link_string,
+ (void *) &cmd_link_down_link_id,
+ (void *) &cmd_link_down_down_string,
+ NULL,
+ },
+};
+
+/*
+ * link ls
+ */
+
+struct cmd_link_ls_result {
+ cmdline_fixed_string_t link_string;
+ cmdline_fixed_string_t ls_string;
+};
+
+static void
+cmd_link_ls_parsed(
+ __attribute__((unused)) void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct app_params *app = data;
+ uint32_t link_id;
+
+ 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);
+ }
+}
+
+cmdline_parse_token_string_t cmd_link_ls_link_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, link_string, "link");
+
+cmdline_parse_token_string_t cmd_link_ls_ls_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, ls_string, "ls");
+
+cmdline_parse_inst_t cmd_link_ls = {
+ .f = cmd_link_ls_parsed,
+ .data = NULL,
+ .help_str = "Link list",
+ .tokens = {
+ (void *)&cmd_link_ls_link_string,
+ (void *)&cmd_link_ls_ls_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
+ */
+
+static void
+app_run_file(
+ cmdline_parse_ctx_t *ctx,
+ const char *file_name)
+{
+ struct cmdline *file_cl;
+
+ int 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_file_result {
+ cmdline_fixed_string_t run_string;
+ char file_name[APP_FILE_NAME_SIZE];
+};
+
+static void
+cmd_run_parsed(
+ void *parsed_result,
+ struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_run_file_result *params = parsed_result;
+
+ app_run_file(cl->ctx, params->file_name);
+}
+
+cmdline_parse_token_string_t cmd_run_run_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string, "run");
+
+cmdline_parse_token_string_t cmd_run_file_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, file_name, NULL);
+
+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_file_name,
+ 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_config,
+ (cmdline_parse_inst_t *) &cmd_link_up,
+ (cmdline_parse_inst_t *) &cmd_link_down,
+ (cmdline_parse_inst_t *) &cmd_link_ls,
+
+ (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
new file mode 100644
index 0000000..76757ff
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.h
@@ -0,0 +1,248 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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_CHECK(app != NULL, "BUG: %s(): app == NULL", __func__);
+
+ APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", id, params);
+
+ if (params == NULL) {
+ printf("Pipeline %" PRIu32 " not found\n", id);
+ 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 app_pipeline_data *pipeline_data;
+
+ pipeline_data = app_pipeline_data(app, id);
+
+ if (pipeline_data == NULL)
+ return NULL;
+
+ return pipeline_data->fe;
+}
+
+static inline struct rte_ring *
+app_pipeline_msgq_in_get(struct app_params *app,
+ uint32_t pipeline_id)
+{
+ char msgq_name[APP_PARAM_NAME_SIZE];
+ struct app_pipeline_params *p = &app->pipeline_params[pipeline_id];
+ uint32_t i;
+
+ sprintf(msgq_name, "MSGQ-REQ-PIPELINE%u", pipeline_id);
+
+ for (i = 0; i < p->n_msgq_in; i++){
+ uint32_t msgq_id = p->msgq_in[i];
+ struct app_msgq_params *p_msgq = &app->msgq_params[msgq_id];
+ struct rte_ring *r = app->msgq[msgq_id];
+
+ if (strcmp(p_msgq->name, msgq_name) == 0)
+ return r;
+ }
+
+ APP_CHECK(1, "%s not found\n", msgq_name);
+ return NULL;
+}
+
+static inline struct rte_ring *
+app_pipeline_msgq_out_get(struct app_params *app,
+ uint32_t pipeline_id)
+{
+ char msgq_name[APP_PARAM_NAME_SIZE];
+ struct app_pipeline_params *p = &app->pipeline_params[pipeline_id];
+ uint32_t i;
+
+ sprintf(msgq_name, "MSGQ-RSP-PIPELINE%u", pipeline_id);
+
+ for (i = 0; i < p->n_msgq_out; i++){
+ uint32_t msgq_id = p->msgq_out[i];
+ struct app_msgq_params *p_msgq = &app->msgq_params[msgq_id];
+ struct rte_ring *r = app->msgq[msgq_id];
+
+ if (strcmp(p_msgq->name, msgq_name) == 0)
+ return r;
+ }
+
+ APP_CHECK(1, "%s not found\n", msgq_name);
+ return NULL;
+}
+
+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;
+}
+
+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_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);
+
+#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c
new file mode 100644
index 0000000..b70260e
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c
@@ -0,0 +1,313 @@
+/*-
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <rte_malloc.h>
+#include <rte_log.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_byteorder.h>
+
+#include <rte_port_ring.h>
+#include <rte_table_acl.h>
+#include <rte_pipeline.h>
+
+#include "main.h"
+
+struct app_core_firewall_message_handle_params {
+ struct rte_ring *ring_req;
+ struct rte_ring *ring_resp;
+
+ struct rte_pipeline *p;
+ uint32_t *port_out_id;
+ uint32_t table_id;
+};
+
+static void
+app_message_handle(struct app_core_firewall_message_handle_params *params);
+
+enum {
+ PROTO_FIELD_IPV4,
+ SRC_FIELD_IPV4,
+ DST_FIELD_IPV4,
+ SRCP_FIELD_IPV4,
+ DSTP_FIELD_IPV4,
+ NUM_FIELDS_IPV4
+};
+
+struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = {
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = PROTO_FIELD_IPV4,
+ .input_index = PROTO_FIELD_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, next_proto_id),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC_FIELD_IPV4,
+ .input_index = SRC_FIELD_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, src_addr),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST_FIELD_IPV4,
+ .input_index = DST_FIELD_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, dst_addr),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = SRCP_FIELD_IPV4,
+ .input_index = SRCP_FIELD_IPV4,
+ .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = DSTP_FIELD_IPV4,
+ .input_index = SRCP_FIELD_IPV4,
+ .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
+ sizeof(uint16_t),
+ },
+};
+
+void
+app_main_loop_pipeline_firewall(void) {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = rte_socket_id(),
+ };
+
+ struct rte_pipeline *p;
+ uint32_t port_in_id[APP_MAX_PORTS];
+ uint32_t port_out_id[APP_MAX_PORTS];
+ uint32_t table_id;
+ uint32_t i;
+
+ uint32_t core_id = rte_lcore_id();
+ struct app_core_params *core_params = app_get_core_params(core_id);
+ struct app_core_firewall_message_handle_params mh_params;
+
+ if ((core_params == NULL) || (core_params->core_type != APP_CORE_FW))
+ rte_panic("Core %u misconfiguration\n", core_id);
+
+ RTE_LOG(INFO, USER1, "Core %u is doing firewall\n", core_id);
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL)
+ rte_panic("Unable to configure the pipeline\n");
+
+ /* Input port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = app.rings[core_params->swq_in[i]],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ .burst_size = app.bsz_swq_rd,
+ };
+
+ if (rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]))
+ rte_panic("Unable to configure input port for "
+ "ring %d\n", i);
+ }
+
+ /* Output port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = app.rings[core_params->swq_out[i]],
+ .tx_burst_sz = app.bsz_swq_wr,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .f_action_bulk = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i]))
+ rte_panic("Unable to configure output port for "
+ "ring %d\n", i);
+ }
+
+ /* Table configuration */
+ {
+ struct rte_table_acl_params table_acl_params = {
+ .name = "test", /* unique identifier for acl contexts */
+ .n_rules = app.max_firewall_rules,
+ .n_rule_fields = DIM(ipv4_field_formats),
+ };
+
+ 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 = 0,
+ };
+
+ memcpy(table_acl_params.field_format, ipv4_field_formats,
+ sizeof(ipv4_field_formats));
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the ACL table\n");
+ }
+
+ /* Interconnecting ports and tables */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id))
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n", port_in_id[i], table_id);
+
+ /* Enable input ports */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0)
+ rte_panic("Pipeline consistency check failed\n");
+
+ /* Message handling */
+ mh_params.ring_req = app_get_ring_req(
+ app_get_first_core_id(APP_CORE_FW));
+ mh_params.ring_resp = app_get_ring_resp(
+ app_get_first_core_id(APP_CORE_FW));
+ mh_params.p = p;
+ mh_params.port_out_id = port_out_id;
+ mh_params.table_id = table_id;
+
+ /* Run-time */
+ for (i = 0; ; i++) {
+ rte_pipeline_run(p);
+
+ if ((i & APP_FLUSH) == 0) {
+ rte_pipeline_flush(p);
+ app_message_handle(&mh_params);
+ }
+ }
+}
+
+void
+app_message_handle(struct app_core_firewall_message_handle_params *params)
+{
+ struct rte_ring *ring_req = params->ring_req;
+ struct rte_ring *ring_resp;
+ struct rte_mbuf *msg;
+ struct app_msg_req *req;
+ struct app_msg_resp *resp;
+ struct rte_pipeline *p;
+ uint32_t *port_out_id;
+ uint32_t table_id;
+ int result;
+
+ /* Read request message */
+ result = rte_ring_sc_dequeue(ring_req, (void **) &msg);
+ if (result != 0)
+ return;
+
+ ring_resp = params->ring_resp;
+ p = params->p;
+ port_out_id = params->port_out_id;
+ table_id = params->table_id;
+
+ /* Handle request */
+ req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
+ switch (req->type) {
+ case APP_MSG_REQ_PING:
+ {
+ result = 0;
+ break;
+ }
+
+ case APP_MSG_REQ_FW_ADD:
+ {
+ struct rte_pipeline_table_entry entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[req->firewall_add.port]},
+ };
+
+ struct rte_pipeline_table_entry *entry_ptr;
+
+ int key_found;
+
+ result = rte_pipeline_table_entry_add(p, table_id,
+ &req->firewall_add.add_params, &entry, &key_found,
+ &entry_ptr);
+ break;
+ }
+
+ case APP_MSG_REQ_FW_DEL:
+ {
+ int key_found;
+
+ result = rte_pipeline_table_entry_delete(p, table_id,
+ &req->firewall_del.delete_params, &key_found, NULL);
+ break;
+ }
+
+ default:
+ rte_panic("FW unrecognized message type (%u)\n", req->type);
+ }
+
+ /* Fill in response message */
+ resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
+ resp->result = result;
+
+ /* Send response */
+ do {
+ result = rte_ring_sp_enqueue(ring_resp, (void *) msg);
+ } while (result == -ENOBUFS);
+}
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c
new file mode 100644
index 0000000..cc0cbf1
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c
@@ -0,0 +1,306 @@
+/*-
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <rte_malloc.h>
+#include <rte_log.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_byteorder.h>
+
+#include <rte_port_ring.h>
+#include <rte_table_hash.h>
+#include <rte_pipeline.h>
+
+#include "main.h"
+
+struct app_core_fc_message_handle_params {
+ struct rte_ring *ring_req;
+ struct rte_ring *ring_resp;
+
+ struct rte_pipeline *p;
+ uint32_t *port_out_id;
+ uint32_t table_id;
+};
+
+static void
+app_message_handle(struct app_core_fc_message_handle_params *params);
+
+static int app_flow_classification_table_init(
+ struct rte_pipeline *p,
+ uint32_t *port_out_id,
+ uint32_t table_id)
+{
+ struct app_flow_key flow_key;
+ uint32_t i;
+
+ /* Add entries to tables */
+ for (i = 0; i < (1 << 24); i++) {
+ struct rte_pipeline_table_entry entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[i & (app.n_ports - 1)]},
+ };
+ struct rte_pipeline_table_entry *entry_ptr;
+ int key_found, status;
+
+ flow_key.ttl = 0;
+ flow_key.proto = 6; /* TCP */
+ flow_key.header_checksum = 0;
+ flow_key.ip_src = 0;
+ flow_key.ip_dst = rte_bswap32(i);
+ flow_key.port_src = 0;
+ flow_key.port_dst = 0;
+
+ status = rte_pipeline_table_entry_add(p, table_id,
+ (void *) &flow_key, &entry, &key_found, &entry_ptr);
+ if (status < 0)
+ rte_panic("Unable to add entry to table %u (%d)\n",
+ table_id, status);
+ }
+
+ return 0;
+}
+
+void
+app_main_loop_pipeline_flow_classification(void) {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = rte_socket_id(),
+ };
+
+ struct rte_pipeline *p;
+ uint32_t port_in_id[APP_MAX_PORTS];
+ uint32_t port_out_id[APP_MAX_PORTS];
+ uint32_t table_id;
+ uint32_t i;
+
+ uint32_t core_id = rte_lcore_id();
+ struct app_core_params *core_params = app_get_core_params(core_id);
+ struct app_core_fc_message_handle_params mh_params;
+
+ if ((core_params == NULL) || (core_params->core_type != APP_CORE_FC))
+ rte_panic("Core %u misconfiguration\n", core_id);
+
+ RTE_LOG(INFO, USER1, "Core %u is doing flow classification "
+ "(pipeline with hash table, 16-byte key, LRU)\n", core_id);
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL)
+ rte_panic("Unable to configure the pipeline\n");
+
+ /* Input port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = app.rings[core_params->swq_in[i]],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ .burst_size = app.bsz_swq_rd,
+ };
+
+ if (rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]))
+ rte_panic("Unable to configure input port for "
+ "ring %d\n", i);
+ }
+
+ /* Output port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = app.rings[core_params->swq_out[i]],
+ .tx_burst_sz = app.bsz_swq_wr,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .f_action_bulk = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i]))
+ rte_panic("Unable to configure output port for "
+ "ring %d\n", i);
+ }
+
+ /* Table configuration */
+ {
+ struct rte_table_hash_key16_lru_params table_hash_params = {
+ .n_entries = 1 << 24,
+ .signature_offset = __builtin_offsetof(
+ struct app_pkt_metadata, signature),
+ .key_offset = __builtin_offsetof(
+ struct app_pkt_metadata, flow_key),
+ .f_hash = test_hash,
+ .seed = 0,
+ };
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_key16_lru_ops,
+ .arg_create = &table_hash_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table\n");
+ }
+
+ /* Interconnecting ports and tables */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id))
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n", port_in_id[i], table_id);
+
+ /* Enable input ports */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0)
+ rte_panic("Pipeline consistency check failed\n");
+
+ /* Message handling */
+ mh_params.ring_req = app_get_ring_req(
+ app_get_first_core_id(APP_CORE_FC));
+ mh_params.ring_resp = app_get_ring_resp(
+ app_get_first_core_id(APP_CORE_FC));
+ mh_params.p = p;
+ mh_params.port_out_id = port_out_id;
+ mh_params.table_id = table_id;
+
+ /* Run-time */
+ for (i = 0; ; i++) {
+ rte_pipeline_run(p);
+
+ if ((i & APP_FLUSH) == 0) {
+ rte_pipeline_flush(p);
+ app_message_handle(&mh_params);
+ }
+ }
+}
+
+void
+app_message_handle(struct app_core_fc_message_handle_params *params)
+{
+ struct rte_ring *ring_req = params->ring_req;
+ struct rte_ring *ring_resp;
+ void *msg;
+ struct app_msg_req *req;
+ struct app_msg_resp *resp;
+ struct rte_pipeline *p;
+ uint32_t *port_out_id;
+ uint32_t table_id;
+ int result;
+
+ /* Read request message */
+ result = rte_ring_sc_dequeue(ring_req, &msg);
+ if (result != 0)
+ return;
+
+ ring_resp = params->ring_resp;
+ p = params->p;
+ port_out_id = params->port_out_id;
+ table_id = params->table_id;
+
+ /* Handle request */
+ req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
+ switch (req->type) {
+ case APP_MSG_REQ_PING:
+ {
+ result = 0;
+ break;
+ }
+
+ case APP_MSG_REQ_FC_ADD_ALL:
+ {
+ result = app_flow_classification_table_init(p, port_out_id,
+ table_id);
+ break;
+ }
+
+ case APP_MSG_REQ_FC_ADD:
+ {
+ struct rte_pipeline_table_entry entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[req->flow_classif_add.port]},
+ };
+
+ struct rte_pipeline_table_entry *entry_ptr;
+
+ int key_found;
+
+ result = rte_pipeline_table_entry_add(p, table_id,
+ req->flow_classif_add.key_raw, &entry, &key_found,
+ &entry_ptr);
+ break;
+ }
+
+ case APP_MSG_REQ_FC_DEL:
+ {
+ int key_found;
+
+ result = rte_pipeline_table_entry_delete(p, table_id,
+ req->flow_classif_add.key_raw, &key_found, NULL);
+ break;
+ }
+
+ default:
+ rte_panic("FC Unrecognized message type (%u)\n", req->type);
+ }
+
+ /* Fill in response message */
+ resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
+ resp->result = result;
+
+ /* Send response */
+ do {
+ result = rte_ring_sp_enqueue(ring_resp, msg);
+ } while (result == -ENOBUFS);
+}
diff --git a/examples/ip_pipeline/pipeline/pipeline_master.c b/examples/ip_pipeline/pipeline/pipeline_master.c
new file mode 100644
index 0000000..1ccdad1
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_master.c
@@ -0,0 +1,47 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#include "pipeline_master.h"
+#include "pipeline_master_be.h"
+
+static struct pipeline_fe_ops pipeline_master_fe_ops = {
+ .f_init = NULL,
+ .f_free = 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
new file mode 100644
index 0000000..3fe3030
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_master.h
@@ -0,0 +1,41 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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
new file mode 100644
index 0000000..a8b084a
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_master_be.c
@@ -0,0 +1,146 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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 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->script_file_done = 0;
+ if (strlen(app->script_file) == 0)
+ 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;
+ int status;
+
+ 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 {
+ printf("Running CLI script file \"%s\" ...\n", app->script_file);
+ struct cmdline *file_cl = cmdline_new(p->cl->ctx, "", fd, 1);
+ cmdline_interact(file_cl);
+ close(fd);
+ }
+
+ p->script_file_done = 1;
+ }
+
+ status = cmdline_poll(p->cl);
+ if (status < 0)
+ rte_panic("CLI poll error (%d)\n", status);
+ else if(status == RDLINE_EXITED) {
+ cmdline_stdin_exit(p->cl);
+ rte_exit(0, "Bye!\n");
+ }
+
+ 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,
+ .f_track = NULL,
+};
diff --git a/examples/ip_pipeline/pipeline/pipeline_master_be.h b/examples/ip_pipeline/pipeline/pipeline_master_be.h
new file mode 100644
index 0000000..00b71fe
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_master_be.h
@@ -0,0 +1,41 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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
new file mode 100644
index 0000000..948b2c1
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough.c
@@ -0,0 +1,213 @@
+/*-
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <rte_malloc.h>
+#include <rte_log.h>
+
+#include <rte_port_ring.h>
+#include <rte_table_stub.h>
+#include <rte_pipeline.h>
+
+#include "main.h"
+
+void
+app_main_loop_pipeline_passthrough(void) {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = rte_socket_id(),
+ };
+
+ struct rte_pipeline *p;
+ uint32_t port_in_id[APP_MAX_PORTS];
+ uint32_t port_out_id[APP_MAX_PORTS];
+ uint32_t table_id[APP_MAX_PORTS];
+ uint32_t i;
+
+ uint32_t core_id = rte_lcore_id();
+ struct app_core_params *core_params = app_get_core_params(core_id);
+
+ if ((core_params == NULL) || (core_params->core_type != APP_CORE_PT))
+ rte_panic("Core %u misconfiguration\n", core_id);
+
+ RTE_LOG(INFO, USER1, "Core %u is doing pass-through\n", core_id);
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL)
+ rte_panic("%s: Unable to configure the pipeline\n", __func__);
+
+ /* Input port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = app.rings[core_params->swq_in[i]],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ .burst_size = app.bsz_swq_rd,
+ };
+
+ if (rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i])) {
+ rte_panic("%s: Unable to configure input port for "
+ "ring %d\n", __func__, i);
+ }
+ }
+
+ /* Output port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = app.rings[core_params->swq_out[i]],
+ .tx_burst_sz = app.bsz_swq_wr,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .f_action_bulk = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i])) {
+ rte_panic("%s: Unable to configure output port for "
+ "ring %d\n", __func__, i);
+ }
+ }
+
+ /* Table configuration */
+ for (i = 0; i < app.n_ports; 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,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id[i]))
+ rte_panic("%s: Unable to configure table %u\n",
+ __func__, i);
+ }
+
+ /* Interconnecting ports and tables */
+ for (i = 0; i < app.n_ports; i++) {
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id[i])) {
+ rte_panic("%s: Unable to connect input port %u to "
+ "table %u\n", __func__, port_in_id[i],
+ table_id[i]);
+ }
+ }
+
+ /* Add entries to tables */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_pipeline_table_entry default_entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[i]},
+ };
+
+ struct rte_pipeline_table_entry *default_entry_ptr;
+
+ if (rte_pipeline_table_default_entry_add(p, table_id[i],
+ &default_entry, &default_entry_ptr))
+ rte_panic("%s: Unable to add default entry to "
+ "table %u\n", __func__, table_id[i]);
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0)
+ rte_panic("%s: Pipeline consistency check failed\n", __func__);
+
+ /* Run-time */
+ for (i = 0; ; i++) {
+ rte_pipeline_run(p);
+
+ if ((i & APP_FLUSH) == 0)
+ rte_pipeline_flush(p);
+ }
+}
+
+void
+app_main_loop_passthrough(void) {
+ struct app_mbuf_array *m;
+ uint32_t i;
+
+ uint32_t core_id = rte_lcore_id();
+ struct app_core_params *core_params = app_get_core_params(core_id);
+
+ if ((core_params == NULL) || (core_params->core_type != APP_CORE_PT))
+ rte_panic("Core %u misconfiguration\n", core_id);
+
+ RTE_LOG(INFO, USER1, "Core %u is doing pass-through (no pipeline)\n",
+ core_id);
+
+ m = rte_malloc_socket(NULL, sizeof(struct app_mbuf_array),
+ RTE_CACHE_LINE_SIZE, rte_socket_id());
+ if (m == NULL)
+ rte_panic("%s: cannot allocate buffer space\n", __func__);
+
+ for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
+ int ret;
+
+ ret = rte_ring_sc_dequeue_bulk(
+ app.rings[core_params->swq_in[i]],
+ (void **) m->array,
+ app.bsz_swq_rd);
+
+ if (ret == -ENOENT)
+ continue;
+
+ do {
+ ret = rte_ring_sp_enqueue_bulk(
+ app.rings[core_params->swq_out[i]],
+ (void **) m->array,
+ app.bsz_swq_wr);
+ } while (ret < 0);
+ }
+}
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.c b/examples/ip_pipeline/pipeline/pipeline_routing.c
new file mode 100644
index 0000000..b1ce624
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_routing.c
@@ -0,0 +1,474 @@
+/*-
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <rte_malloc.h>
+#include <rte_log.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_byteorder.h>
+
+#include <rte_port_ring.h>
+#include <rte_table_lpm.h>
+#include <rte_table_hash.h>
+#include <rte_pipeline.h>
+
+#include "main.h"
+
+#include <unistd.h>
+
+struct app_routing_table_entry {
+ struct rte_pipeline_table_entry head;
+ uint32_t nh_ip;
+ uint32_t nh_iface;
+};
+
+struct app_arp_table_entry {
+ struct rte_pipeline_table_entry head;
+ struct ether_addr nh_arp;
+};
+
+static inline void
+app_routing_table_write_metadata(
+ struct rte_mbuf *pkt,
+ struct app_routing_table_entry *entry)
+{
+ struct app_pkt_metadata *c =
+ (struct app_pkt_metadata *) RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
+
+ c->arp_key.nh_ip = entry->nh_ip;
+ c->arp_key.nh_iface = entry->nh_iface;
+}
+
+static int
+app_routing_table_ah(
+ struct rte_mbuf **pkts,
+ uint64_t *pkts_mask,
+ struct rte_pipeline_table_entry **entries,
+ __attribute__((unused)) void *arg)
+{
+ uint64_t pkts_in_mask = *pkts_mask;
+
+ 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; i++) {
+ struct rte_mbuf *m = pkts[i];
+ struct app_routing_table_entry *a =
+ (struct app_routing_table_entry *) entries[i];
+
+ app_routing_table_write_metadata(m, a);
+ }
+ } else
+ for ( ; pkts_in_mask; ) {
+ struct rte_mbuf *m;
+ struct app_routing_table_entry *a;
+ uint64_t pkt_mask;
+ uint32_t packet_index;
+
+ packet_index = __builtin_ctzll(pkts_in_mask);
+ pkt_mask = 1LLU << packet_index;
+ pkts_in_mask &= ~pkt_mask;
+
+ m = pkts[packet_index];
+ a = (struct app_routing_table_entry *)
+ entries[packet_index];
+ app_routing_table_write_metadata(m, a);
+ }
+
+ return 0;
+}
+
+static inline void
+app_arp_table_write_metadata(
+ struct rte_mbuf *pkt,
+ struct app_arp_table_entry *entry)
+{
+ struct app_pkt_metadata *c =
+ (struct app_pkt_metadata *) RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
+ ether_addr_copy(&entry->nh_arp, &c->nh_arp);
+}
+
+static int
+app_arp_table_ah(
+ struct rte_mbuf **pkts,
+ uint64_t *pkts_mask,
+ struct rte_pipeline_table_entry **entries,
+ __attribute__((unused)) void *arg)
+{
+ uint64_t pkts_in_mask = *pkts_mask;
+
+ 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; i++) {
+ struct rte_mbuf *m = pkts[i];
+ struct app_arp_table_entry *a =
+ (struct app_arp_table_entry *) entries[i];
+
+ app_arp_table_write_metadata(m, a);
+ }
+ } else {
+ for ( ; pkts_in_mask; ) {
+ struct rte_mbuf *m;
+ struct app_arp_table_entry *a;
+ uint64_t pkt_mask;
+ uint32_t packet_index;
+
+ packet_index = __builtin_ctzll(pkts_in_mask);
+ pkt_mask = 1LLU << packet_index;
+ pkts_in_mask &= ~pkt_mask;
+
+ m = pkts[packet_index];
+ a = (struct app_arp_table_entry *)
+ entries[packet_index];
+ app_arp_table_write_metadata(m, a);
+ }
+ }
+
+ return 0;
+}
+
+static uint64_t app_arp_table_hash(
+ void *key,
+ __attribute__((unused)) uint32_t key_size,
+ __attribute__((unused)) uint64_t seed)
+{
+ uint32_t *k = (uint32_t *) key;
+
+ return k[1];
+}
+
+struct app_core_routing_message_handle_params {
+ struct rte_ring *ring_req;
+ struct rte_ring *ring_resp;
+ struct rte_pipeline *p;
+ uint32_t *port_out_id;
+ uint32_t routing_table_id;
+ uint32_t arp_table_id;
+};
+
+static void
+app_message_handle(struct app_core_routing_message_handle_params *params);
+
+void
+app_main_loop_pipeline_routing(void) {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = rte_socket_id(),
+ };
+
+ struct rte_pipeline *p;
+ uint32_t port_in_id[APP_MAX_PORTS];
+ uint32_t port_out_id[APP_MAX_PORTS];
+ uint32_t routing_table_id, arp_table_id;
+ uint32_t i;
+
+ uint32_t core_id = rte_lcore_id();
+ struct app_core_params *core_params = app_get_core_params(core_id);
+ struct app_core_routing_message_handle_params mh_params;
+
+ if ((core_params == NULL) || (core_params->core_type != APP_CORE_RT))
+ rte_panic("Core %u misconfiguration\n", core_id);
+
+ RTE_LOG(INFO, USER1, "Core %u is doing routing\n", core_id);
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL)
+ rte_panic("Unable to configure the pipeline\n");
+
+ /* Input port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = app.rings[core_params->swq_in[i]],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ .burst_size = app.bsz_swq_rd,
+ };
+
+ if (rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]))
+ rte_panic("Unable to configure input port for "
+ "ring %d\n", i);
+ }
+
+ /* Output port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = app.rings[core_params->swq_out[i]],
+ .tx_burst_sz = app.bsz_swq_wr,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .f_action_bulk = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i]))
+ rte_panic("Unable to configure output port for "
+ "ring %d\n", i);
+ }
+
+ /* Routing table configuration */
+ {
+ struct rte_table_lpm_params table_lpm_params = {
+ .n_rules = app.max_routing_rules,
+ .entry_unique_size =
+ sizeof(struct app_routing_table_entry),
+ .offset = __builtin_offsetof(struct app_pkt_metadata,
+ flow_key.ip_dst),
+ };
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_lpm_ops,
+ .arg_create = &table_lpm_params,
+ .f_action_hit = app_routing_table_ah,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size =
+ sizeof(struct app_routing_table_entry) -
+ sizeof(struct rte_pipeline_table_entry),
+ };
+
+ if (rte_pipeline_table_create(p, &table_params,
+ &routing_table_id))
+ rte_panic("Unable to configure the LPM table\n");
+ }
+
+ /* ARP table configuration */
+ {
+ struct rte_table_hash_key8_lru_params table_arp_params = {
+ .n_entries = app.max_arp_rules,
+ .f_hash = app_arp_table_hash,
+ .seed = 0,
+ .signature_offset = 0, /* Unused */
+ .key_offset = __builtin_offsetof(
+ struct app_pkt_metadata, arp_key),
+ };
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_key8_lru_dosig_ops,
+ .arg_create = &table_arp_params,
+ .f_action_hit = app_arp_table_ah,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = sizeof(struct app_arp_table_entry) -
+ sizeof(struct rte_pipeline_table_entry),
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &arp_table_id))
+ rte_panic("Unable to configure the ARP table\n");
+ }
+
+ /* Interconnecting ports and tables */
+ for (i = 0; i < app.n_ports; i++) {
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ routing_table_id))
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n", port_in_id[i], routing_table_id);
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0)
+ rte_panic("Pipeline consistency check failed\n");
+
+ /* Message handling */
+ mh_params.ring_req =
+ app_get_ring_req(app_get_first_core_id(APP_CORE_RT));
+ mh_params.ring_resp =
+ app_get_ring_resp(app_get_first_core_id(APP_CORE_RT));
+ mh_params.p = p;
+ mh_params.port_out_id = port_out_id;
+ mh_params.routing_table_id = routing_table_id;
+ mh_params.arp_table_id = arp_table_id;
+
+ /* Run-time */
+ for (i = 0; ; i++) {
+ rte_pipeline_run(p);
+
+ if ((i & APP_FLUSH) == 0) {
+ rte_pipeline_flush(p);
+ app_message_handle(&mh_params);
+ }
+ }
+}
+
+void
+app_message_handle(struct app_core_routing_message_handle_params *params)
+{
+ struct rte_ring *ring_req = params->ring_req;
+ struct rte_ring *ring_resp;
+ void *msg;
+ struct app_msg_req *req;
+ struct app_msg_resp *resp;
+ struct rte_pipeline *p;
+ uint32_t *port_out_id;
+ uint32_t routing_table_id, arp_table_id;
+ int result;
+
+ /* Read request message */
+ result = rte_ring_sc_dequeue(ring_req, &msg);
+ if (result != 0)
+ return;
+
+ ring_resp = params->ring_resp;
+ p = params->p;
+ port_out_id = params->port_out_id;
+ routing_table_id = params->routing_table_id;
+ arp_table_id = params->arp_table_id;
+
+ /* Handle request */
+ req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
+ switch (req->type) {
+ case APP_MSG_REQ_PING:
+ {
+ result = 0;
+ break;
+ }
+
+ case APP_MSG_REQ_RT_ADD:
+ {
+ struct app_routing_table_entry entry = {
+ .head = {
+ .action = RTE_PIPELINE_ACTION_TABLE,
+ {.table_id = arp_table_id},
+ },
+ .nh_ip = req->routing_add.nh_ip,
+ .nh_iface = port_out_id[req->routing_add.port],
+ };
+
+ struct rte_table_lpm_key key = {
+ .ip = req->routing_add.ip,
+ .depth = req->routing_add.depth,
+ };
+
+ struct rte_pipeline_table_entry *entry_ptr;
+
+ int key_found;
+
+ result = rte_pipeline_table_entry_add(p, routing_table_id, &key,
+ (struct rte_pipeline_table_entry *) &entry, &key_found,
+ &entry_ptr);
+ break;
+ }
+
+ case APP_MSG_REQ_RT_DEL:
+ {
+ struct rte_table_lpm_key key = {
+ .ip = req->routing_del.ip,
+ .depth = req->routing_del.depth,
+ };
+
+ int key_found;
+
+ result = rte_pipeline_table_entry_delete(p, routing_table_id,
+ &key, &key_found, NULL);
+ break;
+ }
+
+ case APP_MSG_REQ_ARP_ADD:
+ {
+
+ struct app_arp_table_entry entry = {
+ .head = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id =
+ port_out_id[req->arp_add.out_iface]},
+ },
+ .nh_arp = req->arp_add.nh_arp,
+ };
+
+ struct app_arp_key arp_key = {
+ .nh_ip = req->arp_add.nh_ip,
+ .nh_iface = port_out_id[req->arp_add.out_iface],
+ };
+
+ struct rte_pipeline_table_entry *entry_ptr;
+
+ int key_found;
+
+ result = rte_pipeline_table_entry_add(p, arp_table_id, &arp_key,
+ (struct rte_pipeline_table_entry *) &entry, &key_found,
+ &entry_ptr);
+ break;
+ }
+
+ case APP_MSG_REQ_ARP_DEL:
+ {
+ struct app_arp_key arp_key = {
+ .nh_ip = req->arp_del.nh_ip,
+ .nh_iface = port_out_id[req->arp_del.out_iface],
+ };
+
+ int key_found;
+
+ result = rte_pipeline_table_entry_delete(p, arp_table_id,
+ &arp_key, &key_found, NULL);
+ break;
+ }
+
+ default:
+ rte_panic("RT Unrecognized message type (%u)\n", req->type);
+ }
+
+ /* Fill in response message */
+ resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
+ resp->result = result;
+
+ /* Send response */
+ do {
+ result = rte_ring_sp_enqueue(ring_resp, msg);
+ } while (result == -ENOBUFS);
+}
diff --git a/examples/ip_pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline_firewall.c
deleted file mode 100644
index b70260e..0000000
--- a/examples/ip_pipeline/pipeline_firewall.c
+++ /dev/null
@@ -1,313 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include <rte_malloc.h>
-#include <rte_log.h>
-#include <rte_ethdev.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-#include <rte_byteorder.h>
-
-#include <rte_port_ring.h>
-#include <rte_table_acl.h>
-#include <rte_pipeline.h>
-
-#include "main.h"
-
-struct app_core_firewall_message_handle_params {
- struct rte_ring *ring_req;
- struct rte_ring *ring_resp;
-
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t table_id;
-};
-
-static void
-app_message_handle(struct app_core_firewall_message_handle_params *params);
-
-enum {
- PROTO_FIELD_IPV4,
- SRC_FIELD_IPV4,
- DST_FIELD_IPV4,
- SRCP_FIELD_IPV4,
- DSTP_FIELD_IPV4,
- NUM_FIELDS_IPV4
-};
-
-struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = {
- {
- .type = RTE_ACL_FIELD_TYPE_BITMASK,
- .size = sizeof(uint8_t),
- .field_index = PROTO_FIELD_IPV4,
- .input_index = PROTO_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) +
- offsetof(struct ipv4_hdr, next_proto_id),
- },
- {
- .type = RTE_ACL_FIELD_TYPE_MASK,
- .size = sizeof(uint32_t),
- .field_index = SRC_FIELD_IPV4,
- .input_index = SRC_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) +
- offsetof(struct ipv4_hdr, src_addr),
- },
- {
- .type = RTE_ACL_FIELD_TYPE_MASK,
- .size = sizeof(uint32_t),
- .field_index = DST_FIELD_IPV4,
- .input_index = DST_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) +
- offsetof(struct ipv4_hdr, dst_addr),
- },
- {
- .type = RTE_ACL_FIELD_TYPE_RANGE,
- .size = sizeof(uint16_t),
- .field_index = SRCP_FIELD_IPV4,
- .input_index = SRCP_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr),
- },
- {
- .type = RTE_ACL_FIELD_TYPE_RANGE,
- .size = sizeof(uint16_t),
- .field_index = DSTP_FIELD_IPV4,
- .input_index = SRCP_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
- sizeof(uint16_t),
- },
-};
-
-void
-app_main_loop_pipeline_firewall(void) {
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id;
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
- struct app_core_firewall_message_handle_params mh_params;
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_FW))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing firewall\n", core_id);
-
- /* Pipeline configuration */
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("Unable to configure the pipeline\n");
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i]))
- rte_panic("Unable to configure input port for "
- "ring %d\n", i);
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i]))
- rte_panic("Unable to configure output port for "
- "ring %d\n", i);
- }
-
- /* Table configuration */
- {
- struct rte_table_acl_params table_acl_params = {
- .name = "test", /* unique identifier for acl contexts */
- .n_rules = app.max_firewall_rules,
- .n_rule_fields = DIM(ipv4_field_formats),
- };
-
- 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 = 0,
- };
-
- memcpy(table_acl_params.field_format, ipv4_field_formats,
- sizeof(ipv4_field_formats));
-
- if (rte_pipeline_table_create(p, &table_params, &table_id))
- rte_panic("Unable to configure the ACL table\n");
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id))
- rte_panic("Unable to connect input port %u to "
- "table %u\n", port_in_id[i], table_id);
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("Pipeline consistency check failed\n");
-
- /* Message handling */
- mh_params.ring_req = app_get_ring_req(
- app_get_first_core_id(APP_CORE_FW));
- mh_params.ring_resp = app_get_ring_resp(
- app_get_first_core_id(APP_CORE_FW));
- mh_params.p = p;
- mh_params.port_out_id = port_out_id;
- mh_params.table_id = table_id;
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0) {
- rte_pipeline_flush(p);
- app_message_handle(&mh_params);
- }
- }
-}
-
-void
-app_message_handle(struct app_core_firewall_message_handle_params *params)
-{
- struct rte_ring *ring_req = params->ring_req;
- struct rte_ring *ring_resp;
- struct rte_mbuf *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t table_id;
- int result;
-
- /* Read request message */
- result = rte_ring_sc_dequeue(ring_req, (void **) &msg);
- if (result != 0)
- return;
-
- ring_resp = params->ring_resp;
- p = params->p;
- port_out_id = params->port_out_id;
- table_id = params->table_id;
-
- /* Handle request */
- req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
- switch (req->type) {
- case APP_MSG_REQ_PING:
- {
- result = 0;
- break;
- }
-
- case APP_MSG_REQ_FW_ADD:
- {
- struct rte_pipeline_table_entry entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[req->firewall_add.port]},
- };
-
- struct rte_pipeline_table_entry *entry_ptr;
-
- int key_found;
-
- result = rte_pipeline_table_entry_add(p, table_id,
- &req->firewall_add.add_params, &entry, &key_found,
- &entry_ptr);
- break;
- }
-
- case APP_MSG_REQ_FW_DEL:
- {
- int key_found;
-
- result = rte_pipeline_table_entry_delete(p, table_id,
- &req->firewall_del.delete_params, &key_found, NULL);
- break;
- }
-
- default:
- rte_panic("FW unrecognized message type (%u)\n", req->type);
- }
-
- /* Fill in response message */
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
- resp->result = result;
-
- /* Send response */
- do {
- result = rte_ring_sp_enqueue(ring_resp, (void *) msg);
- } while (result == -ENOBUFS);
-}
diff --git a/examples/ip_pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline_flow_classification.c
deleted file mode 100644
index cc0cbf1..0000000
--- a/examples/ip_pipeline/pipeline_flow_classification.c
+++ /dev/null
@@ -1,306 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include <rte_malloc.h>
-#include <rte_log.h>
-#include <rte_ethdev.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-#include <rte_byteorder.h>
-
-#include <rte_port_ring.h>
-#include <rte_table_hash.h>
-#include <rte_pipeline.h>
-
-#include "main.h"
-
-struct app_core_fc_message_handle_params {
- struct rte_ring *ring_req;
- struct rte_ring *ring_resp;
-
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t table_id;
-};
-
-static void
-app_message_handle(struct app_core_fc_message_handle_params *params);
-
-static int app_flow_classification_table_init(
- struct rte_pipeline *p,
- uint32_t *port_out_id,
- uint32_t table_id)
-{
- struct app_flow_key flow_key;
- uint32_t i;
-
- /* Add entries to tables */
- for (i = 0; i < (1 << 24); i++) {
- struct rte_pipeline_table_entry entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[i & (app.n_ports - 1)]},
- };
- struct rte_pipeline_table_entry *entry_ptr;
- int key_found, status;
-
- flow_key.ttl = 0;
- flow_key.proto = 6; /* TCP */
- flow_key.header_checksum = 0;
- flow_key.ip_src = 0;
- flow_key.ip_dst = rte_bswap32(i);
- flow_key.port_src = 0;
- flow_key.port_dst = 0;
-
- status = rte_pipeline_table_entry_add(p, table_id,
- (void *) &flow_key, &entry, &key_found, &entry_ptr);
- if (status < 0)
- rte_panic("Unable to add entry to table %u (%d)\n",
- table_id, status);
- }
-
- return 0;
-}
-
-void
-app_main_loop_pipeline_flow_classification(void) {
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id;
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
- struct app_core_fc_message_handle_params mh_params;
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_FC))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing flow classification "
- "(pipeline with hash table, 16-byte key, LRU)\n", core_id);
-
- /* Pipeline configuration */
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("Unable to configure the pipeline\n");
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i]))
- rte_panic("Unable to configure input port for "
- "ring %d\n", i);
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i]))
- rte_panic("Unable to configure output port for "
- "ring %d\n", i);
- }
-
- /* Table configuration */
- {
- struct rte_table_hash_key16_lru_params table_hash_params = {
- .n_entries = 1 << 24,
- .signature_offset = __builtin_offsetof(
- struct app_pkt_metadata, signature),
- .key_offset = __builtin_offsetof(
- struct app_pkt_metadata, flow_key),
- .f_hash = test_hash,
- .seed = 0,
- };
-
- struct rte_pipeline_table_params table_params = {
- .ops = &rte_table_hash_key16_lru_ops,
- .arg_create = &table_hash_params,
- .f_action_hit = NULL,
- .f_action_miss = NULL,
- .arg_ah = NULL,
- .action_data_size = 0,
- };
-
- if (rte_pipeline_table_create(p, &table_params, &table_id))
- rte_panic("Unable to configure the hash table\n");
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id))
- rte_panic("Unable to connect input port %u to "
- "table %u\n", port_in_id[i], table_id);
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("Pipeline consistency check failed\n");
-
- /* Message handling */
- mh_params.ring_req = app_get_ring_req(
- app_get_first_core_id(APP_CORE_FC));
- mh_params.ring_resp = app_get_ring_resp(
- app_get_first_core_id(APP_CORE_FC));
- mh_params.p = p;
- mh_params.port_out_id = port_out_id;
- mh_params.table_id = table_id;
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0) {
- rte_pipeline_flush(p);
- app_message_handle(&mh_params);
- }
- }
-}
-
-void
-app_message_handle(struct app_core_fc_message_handle_params *params)
-{
- struct rte_ring *ring_req = params->ring_req;
- struct rte_ring *ring_resp;
- void *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t table_id;
- int result;
-
- /* Read request message */
- result = rte_ring_sc_dequeue(ring_req, &msg);
- if (result != 0)
- return;
-
- ring_resp = params->ring_resp;
- p = params->p;
- port_out_id = params->port_out_id;
- table_id = params->table_id;
-
- /* Handle request */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- switch (req->type) {
- case APP_MSG_REQ_PING:
- {
- result = 0;
- break;
- }
-
- case APP_MSG_REQ_FC_ADD_ALL:
- {
- result = app_flow_classification_table_init(p, port_out_id,
- table_id);
- break;
- }
-
- case APP_MSG_REQ_FC_ADD:
- {
- struct rte_pipeline_table_entry entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[req->flow_classif_add.port]},
- };
-
- struct rte_pipeline_table_entry *entry_ptr;
-
- int key_found;
-
- result = rte_pipeline_table_entry_add(p, table_id,
- req->flow_classif_add.key_raw, &entry, &key_found,
- &entry_ptr);
- break;
- }
-
- case APP_MSG_REQ_FC_DEL:
- {
- int key_found;
-
- result = rte_pipeline_table_entry_delete(p, table_id,
- req->flow_classif_add.key_raw, &key_found, NULL);
- break;
- }
-
- default:
- rte_panic("FC Unrecognized message type (%u)\n", req->type);
- }
-
- /* Fill in response message */
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- resp->result = result;
-
- /* Send response */
- do {
- result = rte_ring_sp_enqueue(ring_resp, msg);
- } while (result == -ENOBUFS);
-}
diff --git a/examples/ip_pipeline/pipeline_ipv4_frag.c b/examples/ip_pipeline/pipeline_ipv4_frag.c
deleted file mode 100644
index e799206..0000000
--- a/examples/ip_pipeline/pipeline_ipv4_frag.c
+++ /dev/null
@@ -1,184 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_log.h>
-#include <rte_malloc.h>
-#include <rte_ethdev.h>
-#include <rte_mbuf.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-
-#include <rte_port_ethdev.h>
-#include <rte_port_ring.h>
-#include <rte_port_frag.h>
-#include <rte_table_stub.h>
-#include <rte_pipeline.h>
-
-#include "main.h"
-
-void
-app_main_loop_pipeline_ipv4_frag(void) {
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id[APP_MAX_PORTS];
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
-
- if ((core_params == NULL) ||
- (core_params->core_type != APP_CORE_IPV4_FRAG))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing IPv4 fragmentation\n", core_id);
-
- /* Pipeline configuration */
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("%s: Unable to configure the pipeline\n", __func__);
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_ipv4_frag_params
- port_frag_params = {
- .ring = app.rings[core_params->swq_in[i]],
- .mtu = 1500,
- .metadata_size = sizeof(struct app_pkt_metadata),
- .pool_direct = app.pool,
- .pool_indirect = app.indirect_pool,
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ipv4_frag_ops,
- .arg_create = (void *) &port_frag_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i]))
- rte_panic("%s: Unable to configure input port %i\n",
- __func__, i);
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i]))
- rte_panic("%s: Unable to configure output port %i\n",
- __func__, i);
- }
-
- /* Table configuration */
- for (i = 0; i < app.n_ports; 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,
- };
-
- if (rte_pipeline_table_create(p, &table_params, &table_id[i]))
- rte_panic("%s: Unable to configure table %u\n",
- __func__, table_id[i]);
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id[i]))
- rte_panic("%s: Unable to connect input port %u to "
- "table %u\n", __func__, port_in_id[i],
- table_id[i]);
-
- /* Add entries to tables */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_pipeline_table_entry default_entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[i]},
- };
-
- struct rte_pipeline_table_entry *default_entry_ptr;
-
- if (rte_pipeline_table_default_entry_add(p, table_id[i],
- &default_entry, &default_entry_ptr))
- rte_panic("%s: Unable to add default entry to "
- "table %u\n", __func__, table_id[i]);
- }
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("%s: Pipeline consistency check failed\n", __func__);
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0)
- rte_pipeline_flush(p);
- }
-}
diff --git a/examples/ip_pipeline/pipeline_ipv4_ras.c b/examples/ip_pipeline/pipeline_ipv4_ras.c
deleted file mode 100644
index 2d6611c..0000000
--- a/examples/ip_pipeline/pipeline_ipv4_ras.c
+++ /dev/null
@@ -1,181 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_log.h>
-#include <rte_malloc.h>
-#include <rte_ethdev.h>
-#include <rte_mbuf.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-
-#include <rte_port_ethdev.h>
-#include <rte_port_ring.h>
-#include <rte_port_ras.h>
-#include <rte_table_stub.h>
-#include <rte_pipeline.h>
-
-#include "main.h"
-
-void
-app_main_loop_pipeline_ipv4_ras(void) {
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id[APP_MAX_PORTS];
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
-
- if ((core_params == NULL) ||
- (core_params->core_type != APP_CORE_IPV4_RAS)) {
- rte_panic("Core %u misconfiguration\n", core_id);
- }
-
- RTE_LOG(INFO, USER1, "Core %u is doing IPv4 reassembly\n", core_id);
-
- /* Pipeline configuration */
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("%s: Unable to configure the pipeline\n", __func__);
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i]))
- rte_panic("%s: Unable to configure input port %i\n",
- __func__, i);
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_ipv4_ras_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ipv4_ras_ops,
- .arg_create = (void *) &port_ring_ipv4_ras_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i]))
- rte_panic("%s: Unable to configure output port %i\n",
- __func__, i);
- }
-
- /* Table configuration */
- for (i = 0; i < app.n_ports; 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,
- };
-
- if (rte_pipeline_table_create(p, &table_params, &table_id[i]))
- rte_panic("%s: Unable to configure table %u\n",
- __func__, table_id[i]);
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id[i]))
- rte_panic("%s: Unable to connect input port %u to "
- "table %u\n", __func__, port_in_id[i],
- table_id[i]);
-
- /* Add entries to tables */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_pipeline_table_entry default_entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[i]},
- };
-
- struct rte_pipeline_table_entry *default_entry_ptr;
-
- if (rte_pipeline_table_default_entry_add(p, table_id[i],
- &default_entry,
- &default_entry_ptr))
- rte_panic("%s: Unable to add default entry to "
- "table %u\n", __func__, table_id[i]);
- }
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("%s: Pipeline consistency check failed\n", __func__);
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0)
- rte_pipeline_flush(p);
- }
-}
diff --git a/examples/ip_pipeline/pipeline_passthrough.c b/examples/ip_pipeline/pipeline_passthrough.c
deleted file mode 100644
index 948b2c1..0000000
--- a/examples/ip_pipeline/pipeline_passthrough.c
+++ /dev/null
@@ -1,213 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include <rte_malloc.h>
-#include <rte_log.h>
-
-#include <rte_port_ring.h>
-#include <rte_table_stub.h>
-#include <rte_pipeline.h>
-
-#include "main.h"
-
-void
-app_main_loop_pipeline_passthrough(void) {
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id[APP_MAX_PORTS];
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_PT))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing pass-through\n", core_id);
-
- /* Pipeline configuration */
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("%s: Unable to configure the pipeline\n", __func__);
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i])) {
- rte_panic("%s: Unable to configure input port for "
- "ring %d\n", __func__, i);
- }
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i])) {
- rte_panic("%s: Unable to configure output port for "
- "ring %d\n", __func__, i);
- }
- }
-
- /* Table configuration */
- for (i = 0; i < app.n_ports; 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,
- };
-
- if (rte_pipeline_table_create(p, &table_params, &table_id[i]))
- rte_panic("%s: Unable to configure table %u\n",
- __func__, i);
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++) {
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id[i])) {
- rte_panic("%s: Unable to connect input port %u to "
- "table %u\n", __func__, port_in_id[i],
- table_id[i]);
- }
- }
-
- /* Add entries to tables */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_pipeline_table_entry default_entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[i]},
- };
-
- struct rte_pipeline_table_entry *default_entry_ptr;
-
- if (rte_pipeline_table_default_entry_add(p, table_id[i],
- &default_entry, &default_entry_ptr))
- rte_panic("%s: Unable to add default entry to "
- "table %u\n", __func__, table_id[i]);
- }
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("%s: Pipeline consistency check failed\n", __func__);
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0)
- rte_pipeline_flush(p);
- }
-}
-
-void
-app_main_loop_passthrough(void) {
- struct app_mbuf_array *m;
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_PT))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing pass-through (no pipeline)\n",
- core_id);
-
- m = rte_malloc_socket(NULL, sizeof(struct app_mbuf_array),
- RTE_CACHE_LINE_SIZE, rte_socket_id());
- if (m == NULL)
- rte_panic("%s: cannot allocate buffer space\n", __func__);
-
- for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
- int ret;
-
- ret = rte_ring_sc_dequeue_bulk(
- app.rings[core_params->swq_in[i]],
- (void **) m->array,
- app.bsz_swq_rd);
-
- if (ret == -ENOENT)
- continue;
-
- do {
- ret = rte_ring_sp_enqueue_bulk(
- app.rings[core_params->swq_out[i]],
- (void **) m->array,
- app.bsz_swq_wr);
- } while (ret < 0);
- }
-}
diff --git a/examples/ip_pipeline/pipeline_routing.c b/examples/ip_pipeline/pipeline_routing.c
deleted file mode 100644
index b1ce624..0000000
--- a/examples/ip_pipeline/pipeline_routing.c
+++ /dev/null
@@ -1,474 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include <rte_malloc.h>
-#include <rte_log.h>
-#include <rte_ethdev.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-#include <rte_byteorder.h>
-
-#include <rte_port_ring.h>
-#include <rte_table_lpm.h>
-#include <rte_table_hash.h>
-#include <rte_pipeline.h>
-
-#include "main.h"
-
-#include <unistd.h>
-
-struct app_routing_table_entry {
- struct rte_pipeline_table_entry head;
- uint32_t nh_ip;
- uint32_t nh_iface;
-};
-
-struct app_arp_table_entry {
- struct rte_pipeline_table_entry head;
- struct ether_addr nh_arp;
-};
-
-static inline void
-app_routing_table_write_metadata(
- struct rte_mbuf *pkt,
- struct app_routing_table_entry *entry)
-{
- struct app_pkt_metadata *c =
- (struct app_pkt_metadata *) RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
-
- c->arp_key.nh_ip = entry->nh_ip;
- c->arp_key.nh_iface = entry->nh_iface;
-}
-
-static int
-app_routing_table_ah(
- struct rte_mbuf **pkts,
- uint64_t *pkts_mask,
- struct rte_pipeline_table_entry **entries,
- __attribute__((unused)) void *arg)
-{
- uint64_t pkts_in_mask = *pkts_mask;
-
- 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; i++) {
- struct rte_mbuf *m = pkts[i];
- struct app_routing_table_entry *a =
- (struct app_routing_table_entry *) entries[i];
-
- app_routing_table_write_metadata(m, a);
- }
- } else
- for ( ; pkts_in_mask; ) {
- struct rte_mbuf *m;
- struct app_routing_table_entry *a;
- uint64_t pkt_mask;
- uint32_t packet_index;
-
- packet_index = __builtin_ctzll(pkts_in_mask);
- pkt_mask = 1LLU << packet_index;
- pkts_in_mask &= ~pkt_mask;
-
- m = pkts[packet_index];
- a = (struct app_routing_table_entry *)
- entries[packet_index];
- app_routing_table_write_metadata(m, a);
- }
-
- return 0;
-}
-
-static inline void
-app_arp_table_write_metadata(
- struct rte_mbuf *pkt,
- struct app_arp_table_entry *entry)
-{
- struct app_pkt_metadata *c =
- (struct app_pkt_metadata *) RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
- ether_addr_copy(&entry->nh_arp, &c->nh_arp);
-}
-
-static int
-app_arp_table_ah(
- struct rte_mbuf **pkts,
- uint64_t *pkts_mask,
- struct rte_pipeline_table_entry **entries,
- __attribute__((unused)) void *arg)
-{
- uint64_t pkts_in_mask = *pkts_mask;
-
- 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; i++) {
- struct rte_mbuf *m = pkts[i];
- struct app_arp_table_entry *a =
- (struct app_arp_table_entry *) entries[i];
-
- app_arp_table_write_metadata(m, a);
- }
- } else {
- for ( ; pkts_in_mask; ) {
- struct rte_mbuf *m;
- struct app_arp_table_entry *a;
- uint64_t pkt_mask;
- uint32_t packet_index;
-
- packet_index = __builtin_ctzll(pkts_in_mask);
- pkt_mask = 1LLU << packet_index;
- pkts_in_mask &= ~pkt_mask;
-
- m = pkts[packet_index];
- a = (struct app_arp_table_entry *)
- entries[packet_index];
- app_arp_table_write_metadata(m, a);
- }
- }
-
- return 0;
-}
-
-static uint64_t app_arp_table_hash(
- void *key,
- __attribute__((unused)) uint32_t key_size,
- __attribute__((unused)) uint64_t seed)
-{
- uint32_t *k = (uint32_t *) key;
-
- return k[1];
-}
-
-struct app_core_routing_message_handle_params {
- struct rte_ring *ring_req;
- struct rte_ring *ring_resp;
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t routing_table_id;
- uint32_t arp_table_id;
-};
-
-static void
-app_message_handle(struct app_core_routing_message_handle_params *params);
-
-void
-app_main_loop_pipeline_routing(void) {
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t routing_table_id, arp_table_id;
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
- struct app_core_routing_message_handle_params mh_params;
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_RT))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing routing\n", core_id);
-
- /* Pipeline configuration */
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("Unable to configure the pipeline\n");
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i]))
- rte_panic("Unable to configure input port for "
- "ring %d\n", i);
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i]))
- rte_panic("Unable to configure output port for "
- "ring %d\n", i);
- }
-
- /* Routing table configuration */
- {
- struct rte_table_lpm_params table_lpm_params = {
- .n_rules = app.max_routing_rules,
- .entry_unique_size =
- sizeof(struct app_routing_table_entry),
- .offset = __builtin_offsetof(struct app_pkt_metadata,
- flow_key.ip_dst),
- };
-
- struct rte_pipeline_table_params table_params = {
- .ops = &rte_table_lpm_ops,
- .arg_create = &table_lpm_params,
- .f_action_hit = app_routing_table_ah,
- .f_action_miss = NULL,
- .arg_ah = NULL,
- .action_data_size =
- sizeof(struct app_routing_table_entry) -
- sizeof(struct rte_pipeline_table_entry),
- };
-
- if (rte_pipeline_table_create(p, &table_params,
- &routing_table_id))
- rte_panic("Unable to configure the LPM table\n");
- }
-
- /* ARP table configuration */
- {
- struct rte_table_hash_key8_lru_params table_arp_params = {
- .n_entries = app.max_arp_rules,
- .f_hash = app_arp_table_hash,
- .seed = 0,
- .signature_offset = 0, /* Unused */
- .key_offset = __builtin_offsetof(
- struct app_pkt_metadata, arp_key),
- };
-
- struct rte_pipeline_table_params table_params = {
- .ops = &rte_table_hash_key8_lru_dosig_ops,
- .arg_create = &table_arp_params,
- .f_action_hit = app_arp_table_ah,
- .f_action_miss = NULL,
- .arg_ah = NULL,
- .action_data_size = sizeof(struct app_arp_table_entry) -
- sizeof(struct rte_pipeline_table_entry),
- };
-
- if (rte_pipeline_table_create(p, &table_params, &arp_table_id))
- rte_panic("Unable to configure the ARP table\n");
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++) {
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- routing_table_id))
- rte_panic("Unable to connect input port %u to "
- "table %u\n", port_in_id[i], routing_table_id);
- }
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("Pipeline consistency check failed\n");
-
- /* Message handling */
- mh_params.ring_req =
- app_get_ring_req(app_get_first_core_id(APP_CORE_RT));
- mh_params.ring_resp =
- app_get_ring_resp(app_get_first_core_id(APP_CORE_RT));
- mh_params.p = p;
- mh_params.port_out_id = port_out_id;
- mh_params.routing_table_id = routing_table_id;
- mh_params.arp_table_id = arp_table_id;
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0) {
- rte_pipeline_flush(p);
- app_message_handle(&mh_params);
- }
- }
-}
-
-void
-app_message_handle(struct app_core_routing_message_handle_params *params)
-{
- struct rte_ring *ring_req = params->ring_req;
- struct rte_ring *ring_resp;
- void *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t routing_table_id, arp_table_id;
- int result;
-
- /* Read request message */
- result = rte_ring_sc_dequeue(ring_req, &msg);
- if (result != 0)
- return;
-
- ring_resp = params->ring_resp;
- p = params->p;
- port_out_id = params->port_out_id;
- routing_table_id = params->routing_table_id;
- arp_table_id = params->arp_table_id;
-
- /* Handle request */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- switch (req->type) {
- case APP_MSG_REQ_PING:
- {
- result = 0;
- break;
- }
-
- case APP_MSG_REQ_RT_ADD:
- {
- struct app_routing_table_entry entry = {
- .head = {
- .action = RTE_PIPELINE_ACTION_TABLE,
- {.table_id = arp_table_id},
- },
- .nh_ip = req->routing_add.nh_ip,
- .nh_iface = port_out_id[req->routing_add.port],
- };
-
- struct rte_table_lpm_key key = {
- .ip = req->routing_add.ip,
- .depth = req->routing_add.depth,
- };
-
- struct rte_pipeline_table_entry *entry_ptr;
-
- int key_found;
-
- result = rte_pipeline_table_entry_add(p, routing_table_id, &key,
- (struct rte_pipeline_table_entry *) &entry, &key_found,
- &entry_ptr);
- break;
- }
-
- case APP_MSG_REQ_RT_DEL:
- {
- struct rte_table_lpm_key key = {
- .ip = req->routing_del.ip,
- .depth = req->routing_del.depth,
- };
-
- int key_found;
-
- result = rte_pipeline_table_entry_delete(p, routing_table_id,
- &key, &key_found, NULL);
- break;
- }
-
- case APP_MSG_REQ_ARP_ADD:
- {
-
- struct app_arp_table_entry entry = {
- .head = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id =
- port_out_id[req->arp_add.out_iface]},
- },
- .nh_arp = req->arp_add.nh_arp,
- };
-
- struct app_arp_key arp_key = {
- .nh_ip = req->arp_add.nh_ip,
- .nh_iface = port_out_id[req->arp_add.out_iface],
- };
-
- struct rte_pipeline_table_entry *entry_ptr;
-
- int key_found;
-
- result = rte_pipeline_table_entry_add(p, arp_table_id, &arp_key,
- (struct rte_pipeline_table_entry *) &entry, &key_found,
- &entry_ptr);
- break;
- }
-
- case APP_MSG_REQ_ARP_DEL:
- {
- struct app_arp_key arp_key = {
- .nh_ip = req->arp_del.nh_ip,
- .nh_iface = port_out_id[req->arp_del.out_iface],
- };
-
- int key_found;
-
- result = rte_pipeline_table_entry_delete(p, arp_table_id,
- &arp_key, &key_found, NULL);
- break;
- }
-
- default:
- rte_panic("RT Unrecognized message type (%u)\n", req->type);
- }
-
- /* Fill in response message */
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- resp->result = result;
-
- /* Send response */
- do {
- result = rte_ring_sp_enqueue(ring_resp, msg);
- } while (result == -ENOBUFS);
-}
diff --git a/examples/ip_pipeline/pipeline_rx.c b/examples/ip_pipeline/pipeline_rx.c
deleted file mode 100644
index 383f1a9..0000000
--- a/examples/ip_pipeline/pipeline_rx.c
+++ /dev/null
@@ -1,385 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_log.h>
-#include <rte_malloc.h>
-#include <rte_ethdev.h>
-#include <rte_mbuf.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-#include <rte_jhash.h>
-
-#include <rte_port_ethdev.h>
-#include <rte_port_ring.h>
-#include <rte_table_stub.h>
-#include <rte_pipeline.h>
-
-
-#include "main.h"
-
-struct app_core_rx_message_handle_params {
- struct rte_ring *ring_req;
- struct rte_ring *ring_resp;
-
- struct rte_pipeline *p;
- uint32_t *port_in_id;
-};
-
-static void
-app_message_handle(struct app_core_rx_message_handle_params *params);
-
-static int
-app_pipeline_rx_port_in_action_handler(struct rte_mbuf **pkts, uint32_t n,
- uint64_t *pkts_mask, void *arg);
-
-void
-app_main_loop_pipeline_rx(void) {
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id[APP_MAX_PORTS];
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
- struct app_core_rx_message_handle_params mh_params;
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_RX))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing RX\n", core_id);
-
- /* Pipeline configuration */
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("%s: Unable to configure the pipeline\n", __func__);
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ethdev_reader_params port_ethdev_params = {
- .port_id = app.ports[i],
- .queue_id = 0,
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ethdev_reader_ops,
- .arg_create = (void *) &port_ethdev_params,
- .f_action = app_pipeline_rx_port_in_action_handler,
- .arg_ah = NULL,
- .burst_size = app.bsz_hwq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i]))
- rte_panic("%s: Unable to configure input port for "
- "port %d\n", __func__, app.ports[i]);
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i]))
- rte_panic("%s: Unable to configure output port for "
- "ring RX %i\n", __func__, i);
- }
-
- /* Table configuration */
- for (i = 0; i < app.n_ports; 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,
- };
-
- if (rte_pipeline_table_create(p, &table_params, &table_id[i]))
- rte_panic("%s: Unable to configure table %u\n",
- __func__, table_id[i]);
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id[i]))
- rte_panic("%s: Unable to connect input port %u to "
- "table %u\n", __func__, port_in_id[i],
- table_id[i]);
-
- /* Add entries to tables */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_pipeline_table_entry default_entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[i]},
- };
-
- struct rte_pipeline_table_entry *default_entry_ptr;
-
- if (rte_pipeline_table_default_entry_add(p, table_id[i],
- &default_entry, &default_entry_ptr))
- rte_panic("%s: Unable to add default entry to "
- "table %u\n", __func__, table_id[i]);
- }
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("%s: Pipeline consistency check failed\n", __func__);
-
- /* Message handling */
- mh_params.ring_req =
- app_get_ring_req(app_get_first_core_id(APP_CORE_RX));
- mh_params.ring_resp =
- app_get_ring_resp(app_get_first_core_id(APP_CORE_RX));
- mh_params.p = p;
- mh_params.port_in_id = port_in_id;
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0) {
- rte_pipeline_flush(p);
- app_message_handle(&mh_params);
- }
- }
-}
-
-uint64_t test_hash(
- void *key,
- __attribute__((unused)) uint32_t key_size,
- __attribute__((unused)) uint64_t seed)
-{
- struct app_flow_key *flow_key = (struct app_flow_key *) key;
- uint32_t ip_dst = rte_be_to_cpu_32(flow_key->ip_dst);
- uint64_t signature = (ip_dst & 0x00FFFFFFLLU) >> 2;
-
- return signature;
-}
-
-uint32_t
-rte_jhash2_16(uint32_t *k, uint32_t initval)
-{
- uint32_t a, b, c;
-
- a = b = RTE_JHASH_GOLDEN_RATIO;
- c = initval;
-
- a += k[0];
- b += k[1];
- c += k[2];
- __rte_jhash_mix(a, b, c);
-
- c += 16; /* length in bytes */
- a += k[3]; /* Remaining word */
-
- __rte_jhash_mix(a, b, c);
-
- return c;
-}
-
-static inline void
-app_pkt_metadata_fill(struct rte_mbuf *m)
-{
- uint8_t *m_data = rte_pktmbuf_mtod(m, uint8_t *);
- struct app_pkt_metadata *c =
- (struct app_pkt_metadata *) RTE_MBUF_METADATA_UINT8_PTR(m, 0);
- struct ipv4_hdr *ip_hdr =
- (struct ipv4_hdr *) &m_data[sizeof(struct ether_hdr)];
- uint64_t *ipv4_hdr_slab = (uint64_t *) ip_hdr;
-
- /* TTL and Header Checksum are set to 0 */
- c->flow_key.slab0 = ipv4_hdr_slab[1] & 0xFFFFFFFF0000FF00LLU;
- c->flow_key.slab1 = ipv4_hdr_slab[2];
- c->signature = test_hash((void *) &c->flow_key, 0, 0);
-
- /* Pop Ethernet header */
- if (app.ether_hdr_pop_push) {
- rte_pktmbuf_adj(m, (uint16_t)sizeof(struct ether_hdr));
- m->l2_len = 0;
- m->l3_len = sizeof(struct ipv4_hdr);
- }
-}
-
-int
-app_pipeline_rx_port_in_action_handler(
- struct rte_mbuf **pkts,
- uint32_t n,
- uint64_t *pkts_mask,
- __rte_unused void *arg)
-{
- uint32_t i;
-
- for (i = 0; i < n; i++) {
- struct rte_mbuf *m = pkts[i];
-
- app_pkt_metadata_fill(m);
- }
-
- *pkts_mask = (~0LLU) >> (64 - n);
-
- return 0;
-}
-
-void
-app_main_loop_rx(void) {
- struct app_mbuf_array *ma;
- uint32_t i, j;
- int ret;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_RX))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing RX (no pipeline)\n", core_id);
-
- ma = rte_malloc_socket(NULL, sizeof(struct app_mbuf_array),
- RTE_CACHE_LINE_SIZE, rte_socket_id());
- if (ma == NULL)
- rte_panic("%s: cannot allocate buffer space\n", __func__);
-
- for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
- uint32_t n_mbufs;
-
- n_mbufs = rte_eth_rx_burst(
- app.ports[i],
- 0,
- ma->array,
- app.bsz_hwq_rd);
-
- if (n_mbufs == 0)
- continue;
-
- for (j = 0; j < n_mbufs; j++) {
- struct rte_mbuf *m = ma->array[j];
-
- app_pkt_metadata_fill(m);
- }
-
- do {
- ret = rte_ring_sp_enqueue_bulk(
- app.rings[core_params->swq_out[i]],
- (void **) ma->array,
- n_mbufs);
- } while (ret < 0);
- }
-}
-
-void
-app_message_handle(struct app_core_rx_message_handle_params *params)
-{
- struct rte_ring *ring_req = params->ring_req;
- struct rte_ring *ring_resp;
- void *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- struct rte_pipeline *p;
- uint32_t *port_in_id;
- int result;
-
- /* Read request message */
- result = rte_ring_sc_dequeue(ring_req, &msg);
- if (result != 0)
- return;
-
- ring_resp = params->ring_resp;
- p = params->p;
- port_in_id = params->port_in_id;
-
- /* Handle request */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- switch (req->type) {
- case APP_MSG_REQ_PING:
- {
- result = 0;
- break;
- }
-
- case APP_MSG_REQ_RX_PORT_ENABLE:
- {
- result = rte_pipeline_port_in_enable(p,
- port_in_id[req->rx_up.port]);
- break;
- }
-
- case APP_MSG_REQ_RX_PORT_DISABLE:
- {
- result = rte_pipeline_port_in_disable(p,
- port_in_id[req->rx_down.port]);
- break;
- }
-
- default:
- rte_panic("RX Unrecognized message type (%u)\n", req->type);
- }
-
- /* Fill in response message */
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- resp->result = result;
-
- /* Send response */
- do {
- result = rte_ring_sp_enqueue(ring_resp, msg);
- } while (result == -ENOBUFS);
-}
diff --git a/examples/ip_pipeline/pipeline_tx.c b/examples/ip_pipeline/pipeline_tx.c
deleted file mode 100644
index 0077c12..0000000
--- a/examples/ip_pipeline/pipeline_tx.c
+++ /dev/null
@@ -1,283 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_log.h>
-#include <rte_malloc.h>
-#include <rte_ethdev.h>
-#include <rte_mbuf.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-
-#include <rte_port_ethdev.h>
-#include <rte_port_ring.h>
-#include <rte_table_stub.h>
-#include <rte_pipeline.h>
-
-#include "main.h"
-
-static struct ether_addr local_ether_addr = {
- .addr_bytes = {0, 1, 2, 3, 4, 5},
-};
-
-static inline void
-app_pkt_metadata_flush(struct rte_mbuf *pkt)
-{
- struct app_pkt_metadata *pkt_meta = (struct app_pkt_metadata *)
- RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
- struct ether_hdr *ether_hdr = (struct ether_hdr *)
- rte_pktmbuf_prepend(pkt, (uint16_t) sizeof(struct ether_hdr));
-
- ether_addr_copy(&pkt_meta->nh_arp, ðer_hdr->d_addr);
- ether_addr_copy(&local_ether_addr, ðer_hdr->s_addr);
- ether_hdr->ether_type = rte_bswap16(ETHER_TYPE_IPv4);
- pkt->l2_len = sizeof(struct ether_hdr);
-}
-
-static int
-app_pipeline_tx_port_in_action_handler(
- struct rte_mbuf **pkts,
- uint32_t n,
- uint64_t *pkts_mask,
- __rte_unused void *arg)
-{
- uint32_t i;
-
- for (i = 0; i < n; i++) {
- struct rte_mbuf *m = pkts[i];
-
- app_pkt_metadata_flush(m);
- }
-
- *pkts_mask = (~0LLU) >> (64 - n);
-
- return 0;
-}
-
-void
-app_main_loop_pipeline_tx(void) {
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id[APP_MAX_PORTS];
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_TX))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing TX\n", core_id);
-
- /* Pipeline configuration */
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("%s: Unable to configure the pipeline\n", __func__);
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = (app.ether_hdr_pop_push) ?
- app_pipeline_tx_port_in_action_handler : NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i])) {
- rte_panic("%s: Unable to configure input port for "
- "ring TX %i\n", __func__, i);
- }
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ethdev_writer_params port_ethdev_params = {
- .port_id = app.ports[i],
- .queue_id = 0,
- .tx_burst_sz = app.bsz_hwq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ethdev_writer_ops,
- .arg_create = (void *) &port_ethdev_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i])) {
- rte_panic("%s: Unable to configure output port for "
- "port %d\n", __func__, app.ports[i]);
- }
- }
-
- /* Table configuration */
- for (i = 0; i < app.n_ports; 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,
- };
-
- if (rte_pipeline_table_create(p, &table_params, &table_id[i])) {
- rte_panic("%s: Unable to configure table %u\n",
- __func__, table_id[i]);
- }
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id[i]))
- rte_panic("%s: Unable to connect input port %u to "
- "table %u\n", __func__, port_in_id[i],
- table_id[i]);
-
- /* Add entries to tables */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_pipeline_table_entry default_entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[i]},
- };
-
- struct rte_pipeline_table_entry *default_entry_ptr;
-
- if (rte_pipeline_table_default_entry_add(p, table_id[i],
- &default_entry, &default_entry_ptr))
- rte_panic("%s: Unable to add default entry to "
- "table %u\n", __func__, table_id[i]);
- }
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("%s: Pipeline consistency check failed\n", __func__);
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0)
- rte_pipeline_flush(p);
- }
-}
-
-void
-app_main_loop_tx(void) {
- struct app_mbuf_array *m[APP_MAX_PORTS];
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_TX))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing TX (no pipeline)\n", core_id);
-
- for (i = 0; i < APP_MAX_PORTS; i++) {
- m[i] = rte_malloc_socket(NULL, sizeof(struct app_mbuf_array),
- RTE_CACHE_LINE_SIZE, rte_socket_id());
- if (m[i] == NULL)
- rte_panic("%s: Cannot allocate buffer space\n",
- __func__);
- }
-
- for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
- uint32_t n_mbufs, n_pkts;
- int ret;
-
- n_mbufs = m[i]->n_mbufs;
-
- ret = rte_ring_sc_dequeue_bulk(
- app.rings[core_params->swq_in[i]],
- (void **) &m[i]->array[n_mbufs],
- app.bsz_swq_rd);
-
- if (ret == -ENOENT)
- continue;
-
- n_mbufs += app.bsz_swq_rd;
-
- if (n_mbufs < app.bsz_hwq_wr) {
- m[i]->n_mbufs = n_mbufs;
- continue;
- }
-
- n_pkts = rte_eth_tx_burst(
- app.ports[i],
- 0,
- m[i]->array,
- n_mbufs);
-
- if (n_pkts < n_mbufs) {
- uint32_t k;
-
- for (k = n_pkts; k < n_mbufs; k++) {
- struct rte_mbuf *pkt_to_free;
-
- pkt_to_free = m[i]->array[k];
- rte_pktmbuf_free(pkt_to_free);
- }
- }
-
- m[i]->n_mbufs = 0;
- }
-}
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 05/11] ip_pipeline: added master pipeline
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
` (3 preceding siblings ...)
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 04/11] ip_pipeline: moved pipelines to separate folder Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 06/11] ip_pipeline: added application thread Maciej Gajdzica
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
From: Jasvinder Singh <jasvinder.singh@intel.com>
Master pipeline is responsible for command line handling and
communicationg with all other pipelines via message queues. Removed
cmdline.c file, as its functionality will be split over multiple
pipeline files.
Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
---
examples/ip_pipeline/Makefile | 5 +
examples/ip_pipeline/cmdline.c | 1976 ----------------------------------------
examples/ip_pipeline/init.c | 5 +
3 files changed, 10 insertions(+), 1976 deletions(-)
delete mode 100644 examples/ip_pipeline/cmdline.c
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index 213e879..9ce80a8 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -55,6 +55,11 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_fe.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master.c
+
CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS) -Wno-error=unused-function -Wno-error=unused-variable
diff --git a/examples/ip_pipeline/cmdline.c b/examples/ip_pipeline/cmdline.c
deleted file mode 100644
index 3173fd0..0000000
--- a/examples/ip_pipeline/cmdline.c
+++ /dev/null
@@ -1,1976 +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.
- */
-
-#include <stdio.h>
-#include <termios.h>
-#include <inttypes.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <rte_ether.h>
-#include <rte_byteorder.h>
-#include <rte_ring.h>
-#include <rte_mbuf.h>
-#include <rte_malloc.h>
-#include <rte_string_fns.h>
-#include <cmdline_rdline.h>
-#include <cmdline_parse.h>
-#include <cmdline_parse_num.h>
-#include <cmdline_parse_string.h>
-#include <cmdline_parse_ipaddr.h>
-#include <cmdline_parse_etheraddr.h>
-#include <cmdline_socket.h>
-#include <cmdline.h>
-
-#include "main.h"
-
-#define IS_RULE_PRESENT(res, rule_key, table, type) \
-do { \
- struct app_rule *it; \
- \
- (res) = NULL; \
- TAILQ_FOREACH(it, &table, entries) { \
- if (memcmp(&rule_key, &it->type.key, sizeof(rule_key)) == 0) {\
- (res) = it; \
- break; \
- } \
- } \
-} while (0)
-
-/* Rules */
-static void
-app_init_rule_tables(void);
-
-TAILQ_HEAD(linked_list, app_rule) arp_table, routing_table, firewall_table,
- flow_table;
-
-uint32_t n_arp_rules;
-uint32_t n_routing_rules;
-uint32_t n_firewall_rules;
-uint32_t n_flow_rules;
-
-struct app_arp_rule {
- struct {
- uint8_t out_iface;
- uint32_t nh_ip;
- } key;
-
- struct ether_addr nh_arp;
-};
-
-struct app_routing_rule {
- struct {
- uint32_t ip;
- uint8_t depth;
- } key;
-
- uint8_t port;
- uint32_t nh_ip;
-};
-
-struct app_firewall_rule {
- struct {
- 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;
- } key;
-
- int32_t priority;
- uint8_t port;
-};
-
-struct app_flow_rule {
- struct {
- uint32_t src_ip;
- uint32_t dst_ip;
- uint16_t src_port;
- uint16_t dst_port;
- uint8_t proto;
- } key;
-
- uint8_t port;
-};
-
-struct app_rule {
- union {
- struct app_arp_rule arp;
- struct app_routing_rule routing;
- struct app_firewall_rule firewall;
- struct app_flow_rule flow;
- };
-
- TAILQ_ENTRY(app_rule) entries;
-};
-
-/* Initialization */
-static void
-app_init_rule_tables(void)
-{
- TAILQ_INIT(&arp_table);
- TAILQ_INIT(&routing_table);
- TAILQ_INIT(&firewall_table);
- TAILQ_INIT(&flow_table);
-
- n_arp_rules = 0;
- n_routing_rules = 0;
- n_firewall_rules = 0;
- n_flow_rules = 0;
-}
-
-/* Printing */
-static void
-print_arp_rule(struct app_arp_rule rule)
-{
- printf("(Iface = %u, Address = %u.%u.%u.%u) => "
- "HWaddress = %02x:%02x:%02x:%02x:%02x:%02x\n",
- rule.key.out_iface,
- (rule.key.nh_ip >> 24) & 0xFF,
- (rule.key.nh_ip >> 16) & 0xFF,
- (rule.key.nh_ip >> 8) & 0xFF,
- rule.key.nh_ip & 0xFF,
-
- rule.nh_arp.addr_bytes[0],
- rule.nh_arp.addr_bytes[1],
- rule.nh_arp.addr_bytes[2],
- rule.nh_arp.addr_bytes[3],
- rule.nh_arp.addr_bytes[4],
- rule.nh_arp.addr_bytes[5]);
-}
-
-static void
-print_routing_rule(struct app_routing_rule rule)
-{
- printf("IP Prefix = %u.%u.%u.%u/%u => "
- "(Iface = %u, Gateway = %u.%u.%u.%u)\n",
- (rule.key.ip >> 24) & 0xFF,
- (rule.key.ip >> 16) & 0xFF,
- (rule.key.ip >> 8) & 0xFF,
- rule.key.ip & 0xFF,
-
- rule.key.depth,
- rule.port,
-
- (rule.nh_ip >> 24) & 0xFF,
- (rule.nh_ip >> 16) & 0xFF,
- (rule.nh_ip >> 8) & 0xFF,
- rule.nh_ip & 0xFF);
-}
-
-#ifdef RTE_LIBRTE_ACL
-
-static void
-print_firewall_rule(struct app_firewall_rule rule)
-{
- printf("Priority %d: (IP Src = %u.%u.%u.%u/%u, "
- "IP Dst = %u.%u.%u.%u/%u, "
- "Port Src = %u-%u, Port Dst = %u-%u, Proto = %u (%u)) => "
- "Port = %u\n",
- rule.priority,
-
- (rule.key.src_ip >> 24) & 0xFF,
- (rule.key.src_ip >> 16) & 0xFF,
- (rule.key.src_ip >> 8) & 0xFF,
- rule.key.src_ip & 0xFF,
- rule.key.src_ip_mask,
-
- (rule.key.dst_ip >> 24) & 0xFF,
- (rule.key.dst_ip >> 16) & 0xFF,
- (rule.key.dst_ip >> 8) & 0xFF,
- rule.key.dst_ip & 0xFF,
- rule.key.dst_ip_mask,
-
- rule.key.src_port_from,
- rule.key.src_port_to,
- rule.key.dst_port_from,
- rule.key.dst_port_to,
- rule.key.proto,
- rule.key.proto_mask,
- rule.port);
-}
-
-#endif
-
-static void
-print_flow_rule(struct app_flow_rule rule)
-{
- printf("(IP Src = %u.%u.%u.%u, IP Dst = %u.%u.%u.%u, Port Src = %u, "
- "Port Dst = %u, Proto = %u) => Port = %u\n",
- (rule.key.src_ip >> 24) & 0xFF,
- (rule.key.src_ip >> 16) & 0xFF,
- (rule.key.src_ip >> 8) & 0xFF,
- rule.key.src_ip & 0xFF,
-
- (rule.key.dst_ip >> 24) & 0xFF,
- (rule.key.dst_ip >> 16) & 0xFF,
- (rule.key.dst_ip >> 8) & 0xFF,
- rule.key.dst_ip & 0xFF,
-
- rule.key.src_port,
- rule.key.dst_port,
- (uint32_t) rule.key.proto,
- rule.port);
-}
-
-/* Commands */
-
-/* *** Run file (script) *** */
-struct cmd_run_file_result {
- cmdline_fixed_string_t run_string;
- char file_path[100];
-};
-
-static void
-cmd_run_file_parsed(
- void *parsed_result,
- struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_run_file_result *params = parsed_result;
- struct cmdline *file_cl;
- int fd;
-
- fd = open(params->file_path, O_RDONLY, 0);
- if (fd < 0) {
- printf("Illegal value for file path (%s)\n", params->file_path);
- return;
- }
-
- file_cl = cmdline_new(cl->ctx, "", fd, 1);
- cmdline_interact(file_cl);
- close(fd);
-}
-
-cmdline_parse_token_string_t cmd_run_file_run_string =
- TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string, "run");
-
-cmdline_parse_token_string_t cmd_run_file_file_path =
- TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, file_path, NULL);
-
-cmdline_parse_inst_t cmd_run_file = {
- .f = cmd_run_file_parsed,
- .data = NULL,
- .help_str = "Run commands from file",
- .tokens = {
- (void *)&cmd_run_file_run_string,
- (void *)&cmd_run_file_file_path,
- NULL,
- },
-};
-
-/* *** Link - Enable *** */
-struct cmd_link_enable_result {
- cmdline_fixed_string_t link_string;
- uint8_t port;
- cmdline_fixed_string_t up_string;
-};
-
-static void
-cmd_link_enable_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_link_enable_result *params = parsed_result;
- void *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_RX);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("RX core not preformed by any CPU core\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Check params */
- if (params->port >= app.n_ports) {
- printf("Illegal value for port parameter (%u)\n", params->port);
- return;
- }
-
- printf("Enabling port %d\n", params->port);
-
- /* Allocate message buffer */
- msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- req->type = APP_MSG_REQ_RX_PORT_ENABLE;
- req->rx_up.port = params->port;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- /* Check response */
- if (resp->result != 0)
- printf("Request LINK_UP failed (%u)\n", resp->result);
-
- /* Free message buffer */
- rte_ctrlmbuf_free(msg);
-}
-
-cmdline_parse_token_string_t cmd_link_enable_link_string =
- TOKEN_STRING_INITIALIZER(struct cmd_link_enable_result, link_string,
- "link");
-
-cmdline_parse_token_num_t cmd_link_enable_port =
- TOKEN_NUM_INITIALIZER(struct cmd_link_enable_result, port, UINT8);
-
-cmdline_parse_token_string_t cmd_link_enable_up_string =
- TOKEN_STRING_INITIALIZER(struct cmd_link_enable_result, up_string,
- "up");
-
-cmdline_parse_inst_t cmd_link_enable = {
- .f = cmd_link_enable_parsed,
- .data = NULL,
- .help_str = "Link down",
- .tokens = {
- (void *)&cmd_link_enable_link_string,
- (void *)&cmd_link_enable_port,
- (void *)&cmd_link_enable_up_string,
- NULL,
- },
-};
-
-/* *** Link - Disable *** */
-struct cmd_link_disable_result {
- cmdline_fixed_string_t link_string;
- uint8_t port;
- cmdline_fixed_string_t down_string;
-};
-
-static void
-cmd_link_disable_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_link_disable_result *params = parsed_result;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- void *msg;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_RX);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("RX not performed by any CPU core\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Check params */
- if (params->port >= app.n_ports) {
- printf("Illegal value for port parameter (%u)\n", params->port);
- return;
- }
-
- printf("Disabling port %d\n", params->port);
-
- /* Allocate message buffer */
- msg = rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- req->type = APP_MSG_REQ_RX_PORT_DISABLE;
- req->rx_down.port = params->port;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request LINK_DOWN failed (%u)\n", resp->result);
-
- /* Free message buffer */
- rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_link_disable_link_string =
- TOKEN_STRING_INITIALIZER(struct cmd_link_disable_result, link_string,
- "link");
-
-cmdline_parse_token_num_t cmd_link_disable_port =
- TOKEN_NUM_INITIALIZER(struct cmd_link_disable_result, port, UINT8);
-
-cmdline_parse_token_string_t cmd_link_disable_down_string =
- TOKEN_STRING_INITIALIZER(struct cmd_link_disable_result, down_string,
- "down");
-
-cmdline_parse_inst_t cmd_link_disable = {
- .f = cmd_link_disable_parsed,
- .data = NULL,
- .help_str = "Link up",
- .tokens = {
- (void *)&cmd_link_disable_link_string,
- (void *)&cmd_link_disable_port,
- (void *)&cmd_link_disable_down_string,
- NULL,
- },
-};
-
-
-/* *** ARP - Add *** */
-struct cmd_arp_add_result {
- cmdline_fixed_string_t arp_string;
- cmdline_fixed_string_t add_string;
- uint8_t out_iface;
- cmdline_ipaddr_t nh_ip;
- struct ether_addr nh_arp;
-
-};
-
-static void
-cmd_arp_add_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_arp_add_result *params = parsed_result;
- struct app_rule rule, *old_rule;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- void *msg;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("ARP not performed by any CPU core\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Check params */
- if (params->out_iface >= app.n_ports) {
- printf("Illegal value for output interface parameter (%u)\n",
- params->out_iface);
- return;
- }
-
- /* Create rule */
- memset(&rule, 0, sizeof(rule));
- rule.arp.key.out_iface = params->out_iface;
- rule.arp.key.nh_ip =
- rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
- rule.arp.nh_arp = params->nh_arp;
-
- /* Check rule existence */
- IS_RULE_PRESENT(old_rule, rule.arp.key, arp_table, arp);
- if ((old_rule == NULL) && (n_arp_rules == app.max_arp_rules)) {
- printf("ARP table is full.\n");
- return;
- }
-
- printf("Adding ARP entry: ");
- print_arp_rule(rule.arp);
-
- /* Allocate message buffer */
- msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- req->type = APP_MSG_REQ_ARP_ADD;
- req->arp_add.out_iface = rule.arp.key.out_iface;
- req->arp_add.nh_ip = rule.arp.key.nh_ip;
- req->arp_add.nh_arp = rule.arp.nh_arp;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request ARP_ADD failed (%u)\n", resp->result);
- else {
- if (old_rule == NULL) {
- struct app_rule *new_rule = (struct app_rule *)
- rte_zmalloc_socket("CLI",
- sizeof(struct app_rule),
- RTE_CACHE_LINE_SIZE,
- rte_socket_id());
-
- if (new_rule == NULL)
- rte_panic("Unable to allocate new rule\n");
-
- memcpy(new_rule, &rule, sizeof(rule));
- TAILQ_INSERT_TAIL(&arp_table, new_rule, entries);
- n_arp_rules++;
- } else
- old_rule->arp.nh_arp = rule.arp.nh_arp;
- }
-
- /* Free message buffer */
- rte_ctrlmbuf_free((struct rte_mbuf *) msg);
-}
-
-cmdline_parse_token_string_t cmd_arp_add_arp_string =
- TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, arp_string, "arp");
-
-cmdline_parse_token_string_t cmd_arp_add_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, add_string, "add");
-
-cmdline_parse_token_num_t cmd_arp_add_out_iface =
- TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, out_iface, UINT8);
-
-cmdline_parse_token_ipaddr_t cmd_arp_add_nh_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_arp_add_result, nh_ip);
-
-cmdline_parse_token_etheraddr_t cmd_arp_add_nh_arp =
- TOKEN_ETHERADDR_INITIALIZER(struct cmd_arp_add_result, nh_arp);
-
-cmdline_parse_inst_t cmd_arp_add = {
- .f = cmd_arp_add_parsed,
- .data = NULL,
- .help_str = "ARP add",
- .tokens = {
- (void *)&cmd_arp_add_arp_string,
- (void *)&cmd_arp_add_add_string,
- (void *)&cmd_arp_add_out_iface,
- (void *)&cmd_arp_add_nh_ip,
- (void *)&cmd_arp_add_nh_arp,
- NULL,
- },
- };
-
-/* *** ARP - Del *** */
-struct cmd_arp_del_result {
- cmdline_fixed_string_t arp_string;
- cmdline_fixed_string_t del_string;
- uint8_t out_iface;
- cmdline_ipaddr_t nh_ip;
-};
-
-static void
-cmd_arp_del_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_arp_del_result *params = parsed_result;
- struct app_rule rule, *old_rule;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- void *msg;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("ARP not performed by any CPU core\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Check params */
- if (params->out_iface > app.n_ports) {
- printf("Illegal value for output interface parameter (%u)\n",
- params->out_iface);
- return;
- }
-
- /* Create rule */
- memset(&rule, 0, sizeof(rule));
- rule.arp.key.out_iface = params->out_iface;
- rule.arp.key.nh_ip =
- rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
-
- /* Check rule existence */
- IS_RULE_PRESENT(old_rule, rule.arp.key, arp_table, arp);
- if (old_rule == NULL)
- return;
-
- printf("Deleting ARP entry: ");
- print_arp_rule(old_rule->arp);
-
- /* Allocate message buffer */
- msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- req->type = APP_MSG_REQ_ARP_DEL;
- req->arp_del.out_iface = rule.arp.key.out_iface;
- req->arp_del.nh_ip = rule.arp.key.nh_ip;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request ARP_DEL failed (%u)\n", resp->result);
- else {
- TAILQ_REMOVE(&arp_table, old_rule, entries);
- n_arp_rules--;
- rte_free(old_rule);
- }
-
- /* Free message buffer */
- rte_ctrlmbuf_free((struct rte_mbuf *) msg);
-}
-
-cmdline_parse_token_string_t cmd_arp_del_arp_string =
- TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "arp");
-
-cmdline_parse_token_string_t cmd_arp_del_del_string =
- TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, del_string, "del");
-
-cmdline_parse_token_num_t cmd_arp_del_out_iface =
- TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, out_iface, UINT8);
-
-cmdline_parse_token_ipaddr_t cmd_arp_del_nh_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_arp_del_result, nh_ip);
-
-cmdline_parse_inst_t cmd_arp_del = {
- .f = cmd_arp_del_parsed,
- .data = NULL,
- .help_str = "ARP delete",
- .tokens = {
- (void *)&cmd_arp_del_arp_string,
- (void *)&cmd_arp_del_del_string,
- (void *)&cmd_arp_del_out_iface,
- (void *)&cmd_arp_del_nh_ip,
- NULL,
- },
-};
-
-/* *** ARP - Print *** */
-struct cmd_arp_print_result {
- cmdline_fixed_string_t arp_string;
- cmdline_fixed_string_t print_string;
-};
-
-static void
-cmd_arp_print_parsed(
- __attribute__((unused)) void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct app_rule *it;
-
- TAILQ_FOREACH(it, &arp_table, entries) {
- print_arp_rule(it->arp);
- }
-}
-
-cmdline_parse_token_string_t cmd_arp_print_arp_string =
- TOKEN_STRING_INITIALIZER(struct cmd_arp_print_result, arp_string,
- "arp");
-
-cmdline_parse_token_string_t cmd_arp_print_print_string =
- TOKEN_STRING_INITIALIZER(struct cmd_arp_print_result, print_string,
- "ls");
-
-cmdline_parse_inst_t cmd_arp_print = {
- .f = cmd_arp_print_parsed,
- .data = NULL,
- .help_str = "ARP list",
- .tokens = {
- (void *)&cmd_arp_print_arp_string,
- (void *)&cmd_arp_print_print_string,
- NULL,
- },
-};
-
-/* *** Routing - Add *** */
-struct cmd_route_add_result {
- cmdline_fixed_string_t route_string;
- cmdline_fixed_string_t add_string;
- cmdline_ipaddr_t ip;
- uint8_t depth;
- uint8_t port;
- cmdline_ipaddr_t nh_ip;
-};
-
-static void
-cmd_route_add_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_route_add_result *params = parsed_result;
- struct app_rule rule, *old_rule;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- void *msg;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("Routing not performed by any CPU core\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Check params */
- if ((params->depth == 0) || (params->depth > 32)) {
- printf("Illegal value for depth parameter (%u)\n",
- params->depth);
- return;
- }
-
- if (params->port >= app.n_ports) {
- printf("Illegal value for port parameter (%u)\n", params->port);
- return;
- }
-
- /* Create rule */
- memset(&rule, 0, sizeof(rule));
- rule.routing.key.ip = rte_bswap32((uint32_t)
- params->ip.addr.ipv4.s_addr);
- rule.routing.key.depth = params->depth;
- rule.routing.port = params->port;
- rule.routing.nh_ip =
- rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
-
- /* Check rule existence */
- IS_RULE_PRESENT(old_rule, rule.routing.key, routing_table, routing);
- if ((old_rule == NULL) && (n_routing_rules == app.max_routing_rules)) {
- printf("Routing table is full.\n");
- return;
- }
-
- printf("Adding route: ");
- print_routing_rule(rule.routing);
-
- /* Allocate message buffer */
- msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- req->type = APP_MSG_REQ_RT_ADD;
- req->routing_add.ip = rule.routing.key.ip;
- req->routing_add.depth = rule.routing.key.depth;
- req->routing_add.port = rule.routing.port;
- req->routing_add.nh_ip = rule.routing.nh_ip;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request ROUTE_ADD failed (%u)\n", resp->result);
- else {
- if (old_rule == NULL) {
- struct app_rule *new_rule = (struct app_rule *)
- rte_zmalloc_socket("CLI",
- sizeof(struct app_rule),
- RTE_CACHE_LINE_SIZE,
- rte_socket_id());
-
- if (new_rule == NULL)
- rte_panic("Unable to allocate new rule\n");
-
- memcpy(new_rule, &rule, sizeof(rule));
- TAILQ_INSERT_TAIL(&routing_table, new_rule, entries);
- n_routing_rules++;
- } else {
- old_rule->routing.port = rule.routing.port;
- old_rule->routing.nh_ip = rule.routing.nh_ip;
- }
- }
-
- /* Free message buffer */
- rte_ctrlmbuf_free((struct rte_mbuf *) msg);
-}
-
-cmdline_parse_token_string_t cmd_route_add_route_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, route_string,
- "route");
-
-cmdline_parse_token_string_t cmd_route_add_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, add_string,
- "add");
-
-cmdline_parse_token_ipaddr_t cmd_route_add_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_route_add_result, ip);
-
-cmdline_parse_token_num_t cmd_route_add_depth =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, depth, UINT8);
-
-cmdline_parse_token_num_t cmd_route_add_port =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, port, UINT8);
-
-cmdline_parse_token_ipaddr_t cmd_route_add_nh_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_route_add_result, nh_ip);
-
-cmdline_parse_inst_t cmd_route_add = {
- .f = cmd_route_add_parsed,
- .data = NULL,
- .help_str = "Route add",
- .tokens = {
- (void *)&cmd_route_add_route_string,
- (void *)&cmd_route_add_add_string,
- (void *)&cmd_route_add_ip,
- (void *)&cmd_route_add_depth,
- (void *)&cmd_route_add_port,
- (void *)&cmd_route_add_nh_ip,
- NULL,
- },
-};
-
-/* *** Routing - Del *** */
-struct cmd_route_del_result {
- cmdline_fixed_string_t route_string;
- cmdline_fixed_string_t del_string;
- cmdline_ipaddr_t ip;
- uint8_t depth;
-};
-
-static void
-cmd_route_del_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_route_del_result *params = parsed_result;
- struct app_rule rule, *old_rule;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- void *msg;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("Routing not performed by any CPU core\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Check params */
- if ((params->depth == 0) || (params->depth > 32)) {
- printf("Illegal value for depth parameter (%u)\n",
- params->depth);
- return;
- }
-
- /* Create rule */
- memset(&rule, 0, sizeof(rule));
- rule.routing.key.ip = rte_bswap32((uint32_t)
- params->ip.addr.ipv4.s_addr);
- rule.routing.key.depth = params->depth;
-
- /* Check rule existence */
- IS_RULE_PRESENT(old_rule, rule.routing.key, routing_table, routing);
- if (old_rule == NULL)
- return;
-
- printf("Deleting route: ");
- print_routing_rule(old_rule->routing);
-
- /* Allocate message buffer */
- msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- req->type = APP_MSG_REQ_RT_DEL;
- req->routing_del.ip = rule.routing.key.ip;
- req->routing_del.depth = rule.routing.key.depth;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request ROUTE_DEL failed %u)\n", resp->result);
- else {
- TAILQ_REMOVE(&routing_table, old_rule, entries);
- rte_free(old_rule);
- n_routing_rules--;
- }
-
- /* Free message buffer */
- rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_route_del_route_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, route_string,
- "route");
-
-cmdline_parse_token_string_t cmd_route_del_del_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, del_string,
- "del");
-
-cmdline_parse_token_ipaddr_t cmd_route_del_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_route_del_result, ip);
-
-cmdline_parse_token_num_t cmd_route_del_depth =
- TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, depth, UINT8);
-
-cmdline_parse_inst_t cmd_route_del = {
- .f = cmd_route_del_parsed,
- .data = NULL,
- .help_str = "Route delete",
- .tokens = {
- (void *)&cmd_route_del_route_string,
- (void *)&cmd_route_del_del_string,
- (void *)&cmd_route_del_ip,
- (void *)&cmd_route_del_depth,
- NULL,
- },
-};
-
-/* *** Routing - Print *** */
-struct cmd_routing_print_result {
- cmdline_fixed_string_t routing_string;
- cmdline_fixed_string_t print_string;
-};
-
-static void
-cmd_routing_print_parsed(
- __attribute__((unused)) void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct app_rule *it;
-
- TAILQ_FOREACH(it, &routing_table, entries) {
- print_routing_rule(it->routing);
- }
-}
-
-cmdline_parse_token_string_t cmd_routing_print_routing_string =
- TOKEN_STRING_INITIALIZER(struct cmd_routing_print_result,
- routing_string, "route");
-
-cmdline_parse_token_string_t cmd_routing_print_print_string =
- TOKEN_STRING_INITIALIZER(struct cmd_routing_print_result, print_string,
- "ls");
-
-cmdline_parse_inst_t cmd_routing_print = {
- .f = cmd_routing_print_parsed,
- .data = NULL,
- .help_str = "Route list",
- .tokens = {
- (void *)&cmd_routing_print_routing_string,
- (void *)&cmd_routing_print_print_string,
- NULL,
- },
-};
-
-#ifdef RTE_LIBRTE_ACL
-
-/* *** Firewall - Add *** */
-struct cmd_firewall_add_result {
- cmdline_fixed_string_t firewall_string;
- cmdline_fixed_string_t add_string;
- int32_t priority;
- cmdline_ipaddr_t src_ip;
- uint32_t src_ip_mask;
- cmdline_ipaddr_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;
- uint8_t port;
-};
-
-static void
-cmd_firewall_add_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_firewall_add_result *params = parsed_result;
- struct app_rule rule, *old_rule, *new_rule = NULL;
- struct rte_mbuf *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_FW);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("Firewall not performed by any CPU core\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Check params */
- if (params->port >= app.n_ports) {
- printf("Illegal value for port parameter (%u)\n", params->port);
- return;
- }
-
- /* Create rule */
- memset(&rule, 0, sizeof(rule));
- rule.firewall.priority = params->priority;
- rule.firewall.key.src_ip =
- rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
- rule.firewall.key.src_ip_mask = params->src_ip_mask;
- rule.firewall.key.dst_ip =
- rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
- rule.firewall.key.dst_ip_mask = params->dst_ip_mask;
- rule.firewall.key.src_port_from = params->src_port_from;
- rule.firewall.key.src_port_to = params->src_port_to;
- rule.firewall.key.dst_port_from = params->dst_port_from;
- rule.firewall.key.dst_port_to = params->dst_port_to;
- rule.firewall.key.proto = params->proto;
- rule.firewall.key.proto_mask = params->proto_mask;
- rule.firewall.port = params->port;
-
- /* Check rule existence */
- IS_RULE_PRESENT(old_rule, rule.firewall.key, firewall_table, firewall);
- if ((old_rule == NULL) &&
- (n_firewall_rules == app.max_firewall_rules)) {
- printf("Firewall table is full.\n");
- return;
- }
-
- printf("Adding firewall rule: ");
- print_firewall_rule(rule.firewall);
-
- /* Allocate message buffer */
- msg = rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* if we need a new rule structure, allocate it before we go further */
- if (old_rule == NULL) {
- new_rule = rte_zmalloc_socket("CLI", sizeof(struct app_rule),
- RTE_CACHE_LINE_SIZE, rte_socket_id());
- if (new_rule == NULL) {
- printf("Cannot allocate memory for new rule\n");
- rte_ctrlmbuf_free(msg);
- return;
- }
- }
-
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
- req->type = APP_MSG_REQ_FW_ADD;
- req->firewall_add.add_params.priority = rule.firewall.priority;
- req->firewall_add.add_params.field_value[1].value.u32 =
- rule.firewall.key.src_ip;
- req->firewall_add.add_params.field_value[1].mask_range.u32 =
- rule.firewall.key.src_ip_mask;
- req->firewall_add.add_params.field_value[2].value.u32 =
- rule.firewall.key.dst_ip;
- req->firewall_add.add_params.field_value[2].mask_range.u32 =
- rule.firewall.key.dst_ip_mask;
- req->firewall_add.add_params.field_value[3].value.u16 =
- rule.firewall.key.src_port_from;
- req->firewall_add.add_params.field_value[3].mask_range.u16 =
- rule.firewall.key.src_port_to;
- req->firewall_add.add_params.field_value[4].value.u16 =
- rule.firewall.key.dst_port_from;
- req->firewall_add.add_params.field_value[4].mask_range.u16 =
- rule.firewall.key.dst_port_to;
- req->firewall_add.add_params.field_value[0].value.u8 =
- rule.firewall.key.proto;
- req->firewall_add.add_params.field_value[0].mask_range.u8 =
- rule.firewall.key.proto_mask;
- req->firewall_add.port = rule.firewall.port;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, (void *) msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, (void **) &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request FIREWALL_ADD failed (%u)\n", resp->result);
- else {
- if (old_rule == NULL) {
- memcpy(new_rule, &rule, sizeof(rule));
- TAILQ_INSERT_TAIL(&firewall_table, new_rule, entries);
- n_firewall_rules++;
- } else {
- old_rule->firewall.priority = rule.firewall.priority;
- old_rule->firewall.port = rule.firewall.port;
- }
- }
-
- /* Free message buffer */
- rte_ctrlmbuf_free(msg);
-}
-
-cmdline_parse_token_string_t cmd_firewall_add_firewall_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_result,
- firewall_string, "firewall");
-
-cmdline_parse_token_string_t cmd_firewall_add_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_result, add_string,
- "add");
-
-cmdline_parse_token_num_t cmd_firewall_add_priority =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, priority, INT32);
-
-cmdline_parse_token_ipaddr_t cmd_firewall_add_src_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_result, src_ip);
-cmdline_parse_token_num_t cmd_firewall_add_src_ip_mask =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_ip_mask,
- UINT32);
-
-cmdline_parse_token_ipaddr_t cmd_firewall_add_dst_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_result, dst_ip);
-cmdline_parse_token_num_t cmd_firewall_add_dst_ip_mask =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_ip_mask,
- UINT32);
-
-cmdline_parse_token_num_t cmd_firewall_add_src_port_from =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_port_from,
- UINT16);
-cmdline_parse_token_num_t cmd_firewall_add_src_port_to =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_port_to,
- UINT16);
-
-cmdline_parse_token_num_t cmd_firewall_add_dst_port_from =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_port_from,
- UINT16);
-cmdline_parse_token_num_t cmd_firewall_add_dst_port_to =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_port_to,
- UINT16);
-
-cmdline_parse_token_num_t cmd_firewall_add_proto =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, proto, UINT8);
-cmdline_parse_token_num_t cmd_firewall_add_proto_mask =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, proto_mask,
- UINT8);
-cmdline_parse_token_num_t cmd_firewall_add_port =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, port, UINT8);
-
-cmdline_parse_inst_t cmd_firewall_add = {
- .f = cmd_firewall_add_parsed,
- .data = NULL,
- .help_str = "Firewall rule add",
- .tokens = {
- (void *)&cmd_firewall_add_firewall_string,
- (void *)&cmd_firewall_add_add_string,
- (void *)&cmd_firewall_add_priority,
- (void *)&cmd_firewall_add_src_ip,
- (void *)&cmd_firewall_add_src_ip_mask,
- (void *)&cmd_firewall_add_dst_ip,
- (void *)&cmd_firewall_add_dst_ip_mask,
- (void *)&cmd_firewall_add_src_port_from,
- (void *)&cmd_firewall_add_src_port_to,
- (void *)&cmd_firewall_add_dst_port_from,
- (void *)&cmd_firewall_add_dst_port_to,
- (void *)&cmd_firewall_add_proto,
- (void *)&cmd_firewall_add_proto_mask,
- (void *)&cmd_firewall_add_port,
- NULL,
- },
-};
-
-/* *** firewall - Del *** */
-struct cmd_firewall_del_result {
- cmdline_fixed_string_t firewall_string;
- cmdline_fixed_string_t del_string;
- cmdline_ipaddr_t src_ip;
- uint32_t src_ip_mask;
- cmdline_ipaddr_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;
-};
-
-static void
-cmd_firewall_del_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_firewall_del_result *params = parsed_result;
- struct app_rule rule, *old_rule;
- struct rte_mbuf *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_FW);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("Firewall not performed by any CPU core\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Check params */
-
- /* Create rule */
- memset(&rule, 0, sizeof(rule));
- rule.firewall.key.src_ip =
- rte_bswap32((uint32_t) params->src_ip.addr.ipv4.s_addr);
- rule.firewall.key.src_ip_mask = params->src_ip_mask;
- rule.firewall.key.dst_ip =
- rte_bswap32((uint32_t) params->dst_ip.addr.ipv4.s_addr);
- rule.firewall.key.dst_ip_mask = params->dst_ip_mask;
- rule.firewall.key.src_port_from = params->src_port_from;
- rule.firewall.key.src_port_to = params->src_port_to;
- rule.firewall.key.dst_port_from = params->dst_port_from;
- rule.firewall.key.dst_port_to = params->dst_port_to;
- rule.firewall.key.proto = params->proto;
- rule.firewall.key.proto_mask = params->proto_mask;
-
- /* Check rule existence */
- IS_RULE_PRESENT(old_rule, rule.firewall.key, firewall_table, firewall);
- if (old_rule == NULL)
- return;
-
- printf("Deleting firewall rule: ");
- print_firewall_rule(old_rule->firewall);
-
- /* Allocate message buffer */
- msg = rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
- memset(&req->firewall_del, 0, sizeof(req->firewall_del));
- req->type = APP_MSG_REQ_FW_DEL;
- req->firewall_del.delete_params.field_value[1].value.u32 =
- rule.firewall.key.src_ip;
- req->firewall_del.delete_params.field_value[1].mask_range.u32 =
- rule.firewall.key.src_ip_mask;
- req->firewall_del.delete_params.field_value[2].value.u32 =
- rule.firewall.key.dst_ip;
- req->firewall_del.delete_params.field_value[2].mask_range.u32 =
- rule.firewall.key.dst_ip_mask;
- req->firewall_del.delete_params.field_value[3].value.u16 =
- rule.firewall.key.src_port_from;
- req->firewall_del.delete_params.field_value[3].mask_range.u16 =
- rule.firewall.key.src_port_to;
- req->firewall_del.delete_params.field_value[4].value.u16 =
- rule.firewall.key.dst_port_from;
- req->firewall_del.delete_params.field_value[4].mask_range.u16 =
- rule.firewall.key.dst_port_to;
- req->firewall_del.delete_params.field_value[0].value.u8 =
- rule.firewall.key.proto;
- req->firewall_del.delete_params.field_value[0].mask_range.u8 =
- rule.firewall.key.proto_mask;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, (void *) msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, (void **) &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request FIREWALL_DEL failed %u)\n", resp->result);
- else {
- TAILQ_REMOVE(&firewall_table, old_rule, entries);
- rte_free(old_rule);
- n_firewall_rules--;
- }
-
- /* Free message buffer */
- rte_ctrlmbuf_free(msg);
-}
-
-cmdline_parse_token_string_t cmd_firewall_del_firewall_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_result,
- firewall_string, "firewall");
-
-cmdline_parse_token_string_t cmd_firewall_del_del_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_result, del_string,
- "del");
-
-cmdline_parse_token_ipaddr_t cmd_firewall_del_src_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_result, src_ip);
-cmdline_parse_token_num_t cmd_firewall_del_src_ip_mask =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_ip_mask,
- UINT32);
-
-cmdline_parse_token_ipaddr_t cmd_firewall_del_dst_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_result, dst_ip);
-cmdline_parse_token_num_t cmd_firewall_del_dst_ip_mask =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_ip_mask,
- UINT32);
-
-cmdline_parse_token_num_t cmd_firewall_del_src_port_from =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_port_from,
- UINT16);
-cmdline_parse_token_num_t cmd_firewall_del_src_port_to =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_port_to,
- UINT16);
-
-cmdline_parse_token_num_t cmd_firewall_del_dst_port_from =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_port_from,
- UINT16);
-cmdline_parse_token_num_t cmd_firewall_del_dst_port_to =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_port_to,
- UINT16);
-
-cmdline_parse_token_num_t cmd_firewall_del_proto =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, proto, UINT8);
-cmdline_parse_token_num_t cmd_firewall_del_proto_mask =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, proto_mask,
- UINT8);
-
-cmdline_parse_inst_t cmd_firewall_del = {
- .f = cmd_firewall_del_parsed,
- .data = NULL,
- .help_str = "Firewall rule delete",
- .tokens = {
- (void *)&cmd_firewall_del_firewall_string,
- (void *)&cmd_firewall_del_del_string,
- (void *)&cmd_firewall_del_src_ip,
- (void *)&cmd_firewall_del_src_ip_mask,
- (void *)&cmd_firewall_del_dst_ip,
- (void *)&cmd_firewall_del_dst_ip_mask,
- (void *)&cmd_firewall_del_src_port_from,
- (void *)&cmd_firewall_del_src_port_to,
- (void *)&cmd_firewall_del_dst_port_from,
- (void *)&cmd_firewall_del_dst_port_to,
- (void *)&cmd_firewall_del_proto,
- (void *)&cmd_firewall_del_proto_mask,
- NULL,
- },
-};
-
-/* *** Firewall - Print *** */
-struct cmd_firewall_print_result {
- cmdline_fixed_string_t firewall_string;
- cmdline_fixed_string_t print_string;
-};
-
-static void
-cmd_firewall_print_parsed(
- __attribute__((unused)) void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct app_rule *it;
-
- TAILQ_FOREACH(it, &firewall_table, entries) {
- print_firewall_rule(it->firewall);
- }
-}
-
-cmdline_parse_token_string_t cmd_firewall_print_firewall_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_print_result,
- firewall_string, "firewall");
-
-cmdline_parse_token_string_t cmd_firewall_print_print_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_print_result, print_string,
- "ls");
-
-cmdline_parse_inst_t cmd_firewall_print = {
- .f = cmd_firewall_print_parsed,
- .data = NULL,
- .help_str = "Firewall rules list",
- .tokens = {
- (void *)&cmd_firewall_print_firewall_string,
- (void *)&cmd_firewall_print_print_string,
- NULL,
- },
-};
-
-#endif
-
-/* *** Flow Classification - Add All *** */
-struct cmd_flow_add_all_result {
- cmdline_fixed_string_t flow_string;
- cmdline_fixed_string_t add_string;
- cmdline_fixed_string_t all_string;
-};
-
-static void
-cmd_flow_add_all_parsed(
- __attribute__((unused)) void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- void *msg;
- int status;
-
- struct rte_ring *ring_req =
- app_get_ring_req(app_get_first_core_id(APP_CORE_FC));
- struct rte_ring *ring_resp =
- app_get_ring_resp(app_get_first_core_id(APP_CORE_FC));
-
- /* Allocate message buffer */
- msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- memset(req, 0, sizeof(struct app_msg_req));
-
- req->type = APP_MSG_REQ_FC_ADD_ALL;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request FLOW_ADD_ALL failed (%u)\n", resp->result);
-
- /* Free message buffer */
- rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_flow_add_all_flow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, flow_string,
- "flow");
-
-cmdline_parse_token_string_t cmd_flow_add_all_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, add_string,
- "add");
-
-cmdline_parse_token_string_t cmd_flow_add_all_all_string =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, all_string,
- "all");
-
-cmdline_parse_inst_t cmd_flow_add_all = {
- .f = cmd_flow_add_all_parsed,
- .data = NULL,
- .help_str = "Flow table initialization based on hard-coded rule",
- .tokens = {
- (void *)&cmd_flow_add_all_flow_string,
- (void *)&cmd_flow_add_all_add_string,
- (void *)&cmd_flow_add_all_all_string,
- NULL,
- },
-};
-
-/* *** Flow Classification - Add *** */
-struct cmd_flow_add_result {
- cmdline_fixed_string_t flow_string;
- cmdline_fixed_string_t add_string;
- cmdline_ipaddr_t src_ip;
- cmdline_ipaddr_t dst_ip;
- uint16_t src_port;
- uint16_t dst_port;
- uint8_t proto;
- uint8_t port;
-};
-
-static void
-cmd_flow_add_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_flow_add_result *params = parsed_result;
- struct app_rule rule, *old_rule;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- void *msg;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_FC);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("Flow classification not performed by any CPU core\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Check params */
- if (params->port >= app.n_ports) {
- printf("Illegal value for port parameter (%u)\n", params->port);
- return;
- }
-
- /* Create rule */
- memset(&rule, 0, sizeof(rule));
- rule.flow.key.src_ip =
- rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
- rule.flow.key.dst_ip =
- rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
- rule.flow.key.src_port = params->src_port;
- rule.flow.key.dst_port = params->dst_port;
- rule.flow.key.proto = params->proto;
- rule.flow.port = params->port;
-
- /* Check rule existence */
- IS_RULE_PRESENT(old_rule, rule.flow.key, flow_table, flow);
- if ((old_rule == NULL) && (n_flow_rules == app.max_flow_rules)) {
- printf("Flow table is full.\n");
- return;
- }
-
- printf("Adding flow: ");
- print_flow_rule(rule.flow);
-
- /* Allocate message buffer */
- msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- memset(req, 0, sizeof(struct app_msg_req));
-
- req->type = APP_MSG_REQ_FC_ADD;
- req->flow_classif_add.key.ip_src = rte_bswap32(rule.flow.key.src_ip);
- req->flow_classif_add.key.ip_dst = rte_bswap32(rule.flow.key.dst_ip);
- req->flow_classif_add.key.port_src =
- rte_bswap16(rule.flow.key.src_port);
- req->flow_classif_add.key.port_dst =
- rte_bswap16(rule.flow.key.dst_port);
- req->flow_classif_add.key.proto = rule.flow.key.proto;
- req->flow_classif_add.port = rule.flow.port;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request FLOW_ADD failed (%u)\n", resp->result);
- else {
- if (old_rule == NULL) {
- struct app_rule *new_rule = (struct app_rule *)
- rte_zmalloc_socket("CLI",
- sizeof(struct app_rule),
- RTE_CACHE_LINE_SIZE,
- rte_socket_id());
-
- if (new_rule == NULL)
- rte_panic("Unable to allocate new rule\n");
-
- memcpy(new_rule, &rule, sizeof(rule));
- TAILQ_INSERT_TAIL(&flow_table, new_rule, entries);
- n_flow_rules++;
- } else
- old_rule->flow.port = rule.flow.port;
- }
-
- /* Free message buffer */
- rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_flow_add_flow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_add_result, flow_string,
- "flow");
-
-cmdline_parse_token_string_t cmd_flow_add_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_add_result, add_string, "add");
-
-cmdline_parse_token_ipaddr_t cmd_flow_add_src_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_flow_add_result, src_ip);
-
-cmdline_parse_token_ipaddr_t cmd_flow_add_dst_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_flow_add_result, dst_ip);
-
-cmdline_parse_token_num_t cmd_flow_add_src_port =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, src_port, UINT16);
-
-cmdline_parse_token_num_t cmd_flow_add_dst_port =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, dst_port, UINT16);
-
-cmdline_parse_token_num_t cmd_flow_add_proto =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, proto, UINT8);
-
-cmdline_parse_token_num_t cmd_flow_add_port =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, port, UINT8);
-
-cmdline_parse_inst_t cmd_flow_add = {
- .f = cmd_flow_add_parsed,
- .data = NULL,
- .help_str = "Flow add",
- .tokens = {
- (void *)&cmd_flow_add_flow_string,
- (void *)&cmd_flow_add_add_string,
- (void *)&cmd_flow_add_src_ip,
- (void *)&cmd_flow_add_dst_ip,
- (void *)&cmd_flow_add_src_port,
- (void *)&cmd_flow_add_dst_port,
- (void *)&cmd_flow_add_proto,
- (void *)&cmd_flow_add_port,
- NULL,
- },
-};
-
-/* *** Flow Classification - Del *** */
-struct cmd_flow_del_result {
- cmdline_fixed_string_t flow_string;
- cmdline_fixed_string_t del_string;
- cmdline_ipaddr_t src_ip;
- cmdline_ipaddr_t dst_ip;
- uint16_t src_port;
- uint16_t dst_port;
- uint8_t proto;
-};
-
-static void
-cmd_flow_del_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_flow_del_result *params = parsed_result;
- struct app_rule rule, *old_rule;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- void *msg;
- int status;
-
- uint32_t core_id = app_get_first_core_id(APP_CORE_FC);
-
- if (core_id == RTE_MAX_LCORE) {
- printf("Flow classification not performed by any CPU core.\n");
- return;
- }
-
- struct rte_ring *ring_req = app_get_ring_req(core_id);
- struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
- /* Create rule */
- memset(&rule, 0, sizeof(rule));
- rule.flow.key.src_ip =
- rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
- rule.flow.key.dst_ip =
- rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
- rule.flow.key.src_port = params->src_port;
- rule.flow.key.dst_port = params->dst_port;
- rule.flow.key.proto = params->proto;
-
- /* Check rule existence */
- IS_RULE_PRESENT(old_rule, rule.flow.key, flow_table, flow);
- if (old_rule == NULL)
- return;
-
- printf("Deleting flow: ");
- print_flow_rule(old_rule->flow);
-
- /* Allocate message buffer */
- msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
- if (msg == NULL)
- rte_panic("Unable to allocate new message\n");
-
- /* Fill request message */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- memset(req, 0, sizeof(struct app_msg_req));
-
- req->type = APP_MSG_REQ_FC_DEL;
- req->flow_classif_del.key.ip_src = rte_bswap32(rule.flow.key.src_ip);
- req->flow_classif_del.key.ip_dst = rte_bswap32(rule.flow.key.dst_ip);
- req->flow_classif_del.key.port_src =
- rte_bswap32(rule.flow.key.src_port);
- req->flow_classif_del.key.port_dst =
- rte_bswap32(rule.flow.key.dst_port);
- req->flow_classif_del.key.proto = rule.flow.key.proto;
-
- /* Send request */
- do {
- status = rte_ring_sp_enqueue(ring_req, msg);
- } while (status == -ENOBUFS);
-
- /* Wait for response */
- do {
- status = rte_ring_sc_dequeue(ring_resp, &msg);
- } while (status != 0);
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
- /* Check response */
- if (resp->result != 0)
- printf("Request FLOW_DEL failed (%u)\n", resp->result);
- else {
- TAILQ_REMOVE(&flow_table, old_rule, entries);
- rte_free(old_rule);
- n_flow_rules--;
- }
-
- /* Free message buffer */
- rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_flow_del_flow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_del_result, flow_string,
- "flow");
-
-cmdline_parse_token_string_t cmd_flow_del_del_string =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_del_result, del_string, "del");
-
-cmdline_parse_token_ipaddr_t cmd_flow_del_src_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_flow_del_result, src_ip);
-
-cmdline_parse_token_ipaddr_t cmd_flow_del_dst_ip =
- TOKEN_IPADDR_INITIALIZER(struct cmd_flow_del_result, dst_ip);
-
-cmdline_parse_token_num_t cmd_flow_del_src_port =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, src_port, UINT16);
-
-cmdline_parse_token_num_t cmd_flow_del_dst_port =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, dst_port, UINT16);
-
-cmdline_parse_token_num_t cmd_flow_del_proto =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, proto, UINT8);
-
-cmdline_parse_inst_t cmd_flow_del = {
- .f = cmd_flow_del_parsed,
- .data = NULL,
- .help_str = "Flow delete",
- .tokens = {
- (void *)&cmd_flow_del_flow_string,
- (void *)&cmd_flow_del_del_string,
- (void *)&cmd_flow_del_src_ip,
- (void *)&cmd_flow_del_dst_ip,
- (void *)&cmd_flow_del_src_port,
- (void *)&cmd_flow_del_dst_port,
- (void *)&cmd_flow_del_proto,
- NULL,
- },
-};
-
-/* *** Flow Classification - Print *** */
-struct cmd_flow_print_result {
- cmdline_fixed_string_t flow_string;
- cmdline_fixed_string_t print_string;
-};
-
-static void
-cmd_flow_print_parsed(
- __attribute__((unused)) void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct app_rule *it;
-
- TAILQ_FOREACH(it, &flow_table, entries) {
- print_flow_rule(it->flow);
- }
-}
-
-cmdline_parse_token_string_t cmd_flow_print_flow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_print_result, flow_string,
- "flow");
-
-cmdline_parse_token_string_t cmd_flow_print_print_string =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_print_result, print_string,
- "ls");
-
-cmdline_parse_inst_t cmd_flow_print = {
- .f = cmd_flow_print_parsed,
- .data = NULL,
- .help_str = "Flow list",
- .tokens = {
- (void *)&cmd_flow_print_flow_string,
- (void *)&cmd_flow_print_print_string,
- NULL,
- },
-};
-
-/* *** QUIT *** */
-struct cmd_quit_result {
- cmdline_fixed_string_t quit;
-};
-
-static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
- struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- cmdline_quit(cl);
-}
-
-cmdline_parse_token_string_t cmd_quit_quit =
- TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
-
-cmdline_parse_inst_t cmd_quit = {
- .f = cmd_quit_parsed,
- .data = NULL,
- .help_str = "Exit application",
- .tokens = {
- (void *)&cmd_quit_quit,
- NULL,
- },
-};
-
-/* List of commands */
-cmdline_parse_ctx_t main_ctx[] = {
- (cmdline_parse_inst_t *)&cmd_flow_add,
- (cmdline_parse_inst_t *)&cmd_flow_del,
- (cmdline_parse_inst_t *)&cmd_flow_add_all,
- (cmdline_parse_inst_t *)&cmd_flow_print,
-#ifdef RTE_LIBRTE_ACL
- (cmdline_parse_inst_t *)&cmd_firewall_add,
- (cmdline_parse_inst_t *)&cmd_firewall_del,
- (cmdline_parse_inst_t *)&cmd_firewall_print,
-#endif
- (cmdline_parse_inst_t *)&cmd_route_add,
- (cmdline_parse_inst_t *)&cmd_route_del,
- (cmdline_parse_inst_t *)&cmd_routing_print,
- (cmdline_parse_inst_t *)&cmd_arp_add,
- (cmdline_parse_inst_t *)&cmd_arp_del,
- (cmdline_parse_inst_t *)&cmd_arp_print,
- (cmdline_parse_inst_t *)&cmd_run_file,
- (cmdline_parse_inst_t *)&cmd_link_enable,
- (cmdline_parse_inst_t *)&cmd_link_disable,
- (cmdline_parse_inst_t *)&cmd_quit,
- NULL,
-};
-
-/* Main loop */
-void
-app_main_loop_cmdline(void)
-{
- struct cmdline *cl;
- uint32_t core_id = rte_lcore_id();
-
- RTE_LOG(INFO, USER1, "Core %u is running the command line interface\n",
- core_id);
-
- n_arp_rules = 0;
- n_routing_rules = 0;
- n_firewall_rules = 0;
- n_flow_rules = 0;
-
- app_init_rule_tables();
-
- cl = cmdline_stdin_new(main_ctx, "pipeline> ");
- if (cl == NULL)
- return;
- cmdline_interact(cl);
- cmdline_stdin_exit(cl);
-}
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index d6b1768..b362af0 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -43,6 +43,8 @@
#include "app.h"
#include "pipeline.h"
+#include "pipeline_common_fe.h"
+#include "pipeline_master.h"
#define APP_NAME_SIZE 32
@@ -1185,6 +1187,9 @@ int app_init(struct app_params *app)
app_init_tm(app);
app_init_msgq(app);
+ app_pipeline_common_cmd_push(app);
+ app_pipeline_type_register(app, &pipeline_master);
+
app_init_pipelines(app);
app_init_threads(app);
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 06/11] ip_pipeline: added application thread
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
` (4 preceding siblings ...)
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 05/11] ip_pipeline: added master pipeline Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 07/11] ip_pipeline: moved config files to separate folder Maciej Gajdzica
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
Application thread runs pipelines on assigned cores.
Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
---
examples/ip_pipeline/Makefile | 1 +
examples/ip_pipeline/main.c | 6 +++
examples/ip_pipeline/thread.c | 105 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 112 insertions(+)
create mode 100644 examples/ip_pipeline/thread.c
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index 9ce80a8..f255338 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -53,6 +53,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += thread.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_be.c
diff --git a/examples/ip_pipeline/main.c b/examples/ip_pipeline/main.c
index ef68c86..862e2f2 100644
--- a/examples/ip_pipeline/main.c
+++ b/examples/ip_pipeline/main.c
@@ -52,5 +52,11 @@ main(int argc, char **argv)
/* Init */
app_init(&app);
+ /* Run-time */
+ rte_eal_mp_remote_launch(
+ app_thread,
+ (void *) &app,
+ CALL_MASTER);
+
return 0;
}
diff --git a/examples/ip_pipeline/thread.c b/examples/ip_pipeline/thread.c
new file mode 100644
index 0000000..66b2a2b
--- /dev/null
+++ b/examples/ip_pipeline/thread.c
@@ -0,0 +1,105 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#include <rte_cycles.h>
+#include <rte_pipeline.h>
+
+#include "pipeline_common_be.h"
+#include "app.h"
+
+int app_thread(void *arg)
+{
+ 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];
+
+ for (i = 0; ; i++) {
+ /* Run regular pipelines */
+ for (j = 0; j < t->n_regular; j++){
+ struct app_thread_pipeline_data *data = &t->regular[j];
+ struct pipeline *p = data->be;
+
+ rte_pipeline_run(p->p);
+ }
+
+ /* Run custom pipelines */
+ for (j = 0; j < t->n_custom; j++){
+ struct app_thread_pipeline_data *data = &t->custom[j];
+
+ data->f_run(data->be);
+ }
+
+ /* Timer */
+ if ((i & 0xF) == 0) {
+ uint64_t time = rte_get_tsc_cycles();
+ uint64_t t_deadline = UINT64_MAX;
+
+ if (time < t->deadline)
+ continue;
+
+ /* Timer for regular pipelines */
+ for (j = 0; j < t->n_regular; j++){
+ struct app_thread_pipeline_data *data = &t->regular[j];
+ uint64_t p_deadline = data->deadline;
+
+ if (p_deadline <= time) {
+ data->f_timer(data->be);
+ p_deadline = time + data->timer_period;
+ data->deadline = p_deadline;
+ }
+
+ if (p_deadline < t_deadline)
+ t_deadline = p_deadline;
+ }
+
+ /* Timer for custom pipelines */
+ for (j = 0; j < t->n_custom; j++){
+ struct app_thread_pipeline_data *data = &t->custom[j];
+ uint64_t p_deadline = data->deadline;
+
+ if (p_deadline <= time) {
+ data->f_timer(data->be);
+ p_deadline = time + data->timer_period;
+ data->deadline = p_deadline;
+ }
+
+ if (p_deadline < t_deadline)
+ t_deadline = p_deadline;
+ }
+
+ t->deadline = t_deadline;
+ }
+ }
+
+ return 0;
+}
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 07/11] ip_pipeline: moved config files to separate folder
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
` (5 preceding siblings ...)
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 06/11] ip_pipeline: added application thread Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 08/11] ip_pipeline: added new implementation of passthrough pipeline Maciej Gajdzica
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
Created new folder for config(.cfg) and script(.sh) files.
Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
---
examples/ip_pipeline/config/ip_pipeline.cfg | 9 ++
examples/ip_pipeline/config/ip_pipeline.sh | 5 +
examples/ip_pipeline/config/test.cfg | 164 +++++++++++++++++++++++++++
examples/ip_pipeline/config/test.sh | 6 +
examples/ip_pipeline/config/tm_profile.cfg | 105 +++++++++++++++++
examples/ip_pipeline/ip_pipeline.cfg | 56 ---------
examples/ip_pipeline/ip_pipeline.sh | 18 ---
7 files changed, 289 insertions(+), 74 deletions(-)
create mode 100644 examples/ip_pipeline/config/ip_pipeline.cfg
create mode 100644 examples/ip_pipeline/config/ip_pipeline.sh
create mode 100644 examples/ip_pipeline/config/test.cfg
create mode 100644 examples/ip_pipeline/config/test.sh
create mode 100644 examples/ip_pipeline/config/tm_profile.cfg
delete mode 100644 examples/ip_pipeline/ip_pipeline.cfg
delete mode 100644 examples/ip_pipeline/ip_pipeline.sh
diff --git a/examples/ip_pipeline/config/ip_pipeline.cfg b/examples/ip_pipeline/config/ip_pipeline.cfg
new file mode 100644
index 0000000..095ed25
--- /dev/null
+++ b/examples/ip_pipeline/config/ip_pipeline.cfg
@@ -0,0 +1,9 @@
+[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
new file mode 100644
index 0000000..4fca259
--- /dev/null
+++ b/examples/ip_pipeline/config/ip_pipeline.sh
@@ -0,0 +1,5 @@
+#
+#run config/ip_pipeline.sh
+#
+
+p 1 ping
diff --git a/examples/ip_pipeline/config/test.cfg b/examples/ip_pipeline/config/test.cfg
new file mode 100644
index 0000000..99a21dd
--- /dev/null
+++ b/examples/ip_pipeline/config/test.cfg
@@ -0,0 +1,164 @@
+; #define OFFSET_QINQ 142
+; #define OFFSET_IP_DA 166
+; #define OFFSET_HASH 128
+; #define OFFSET_FLOW_ID 132
+; #define OFFSET_COLOR 136
+
+; TBD - need to think about
+;[EAL]
+; c = not allowed
+;n = 2 ;
+;m = 2048
+
+
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = PASS-THROUGH; Packet RX
+core = s0c1
+pktq_in = RXQ0.0 RXQ1.0 SWQ1
+pktq_out = SWQ0 SWQ1
+msgq_in = MSGQ0
+msgq_out = MSGQ1
+pkt_type=qinq_ipv4
+key_type=qinq
+key_offset=OFFSET_QINQ
+hash_offset=OFFSET_HASH
+timer_period = 2
+
+[PIPELINE2]
+type = FIREWALL
+core = s1c2
+pktq_in = SWQ0 SWQ5
+pktq_out = SWQ2 SINK0
+msgq_in = MSGQ1
+msgq_out = MSGQ0
+n_rules=4K
+pkt_type=qinq_ipv4
+
+[PIPELINE3]
+type = FLOW_CLASSIF
+core = s0c3
+pktq_in = SWQ2
+pktq_out = SWQ3 SINK1
+time_period = 100
+n_flows=16M
+key_size=8
+key_offset=$OFFSET_QINQ
+hash_offset=$OFFSET_HASH
+flow_id_offset=$OFFSET_FLOW_ID
+
+[PIPELINE4]
+type = FLOW_ACTIONS
+core = c4h
+pktq_in = SWQ3
+pktq_out = SWQ4
+n_flows=16M
+flow_id_offset=$OFFSET_FLOW_ID
+color_offset=$OFFSET_COLOR
+
+[PIPELINE5]
+type = ROUTING
+core = s1c5h
+pktq_in = SWQ4
+pktq_out = TXQ0.0 TXQ1.0 SINK2
+n_routes=1M
+next_hop_type=ipv4_mpls
+ip_da_offset=$OFFSET_IP_DA
+color_offset=$OFFSET_COLOR
+
+[MEMPOOL1]
+pool_size=2k
+cache_size=64
+
+[LINK0]
+ip_local_q=0
+udp_local_q =0
+arp_q=0
+tcp_local_q=0
+
+[LINK1]
+ip_local_q=0
+udp_local_q =0
+arp_q=0
+tcp_local_q=0
+
+[RXQ0.0]
+mempool=MEMPOOL0
+burst=16
+size=128
+
+[RXQ1.0]
+mempool=MEMPOOL0
+burst=16
+size=128
+
+[TXQ0.0]
+burst=16
+size=128
+dropless=yes
+
+[TXQ1.0]
+burst=16
+size=128
+dropless=no
+
+[SWQ0]
+size=64
+
+[SWQ1]
+dropless=yes
+
+[SWQ2]
+cpu=0
+
+[SWQ3]
+dropless=yes
+
+[SWQ4]
+dropless=yes
+
+[TM1]
+cfg=config/tm_profile.cfg
+
+[SOURCE1]
+mempool=MEMPOOL3
+burst=64
+
+[MSGQ-REQ-PIPELINE1]
+size=16
+
+[MSGQ-RSP-PIPELINE1]
+size=16
+
+[MSGQ-REQ-PIPELINE2]
+size=16
+
+[MSGQ-RSP-PIPELINE2]
+size=16
+
+[MSGQ-REQ-PIPELINE3]
+size=16
+
+[MSGQ-RSP-PIPELINE3]
+size=16
+
+[MSGQ-REQ-PIPELINE4]
+size=16
+
+[MSGQ-RSP-PIPELINE4]
+size=16
+
+[MSGQ-REQ-PIPELINE5]
+size=16
+
+[MSGQ-RSP-PIPELINE5]
+size=16
+
+;[MSGQ-REQ-CORE-s1c5h]
+;size = 32
+
+;[MSGQ-RSP-CORE-s1c5h]
+;size = 32
diff --git a/examples/ip_pipeline/config/test.sh b/examples/ip_pipeline/config/test.sh
new file mode 100644
index 0000000..ca78a4a
--- /dev/null
+++ b/examples/ip_pipeline/config/test.sh
@@ -0,0 +1,6 @@
+p 1 ping
+p 1 stats port in 0
+p 1 stats table 0
+p 1 stats port out 1
+p 1 port in 0 disable
+p 1 port in 0 enable
diff --git a/examples/ip_pipeline/config/tm_profile.cfg b/examples/ip_pipeline/config/tm_profile.cfg
new file mode 100644
index 0000000..53edb67
--- /dev/null
+++ b/examples/ip_pipeline/config/tm_profile.cfg
@@ -0,0 +1,105 @@
+; 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 Intel Data Plane Development Kit (Intel 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/ip_pipeline.cfg b/examples/ip_pipeline/ip_pipeline.cfg
deleted file mode 100644
index 428830d..0000000
--- a/examples/ip_pipeline/ip_pipeline.cfg
+++ /dev/null
@@ -1,56 +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.
-
-; Core configuration
-[core 0]
-type = MASTER
-queues in = 15 16 17 -1 -1 -1 -1 -1
-queues out = 12 13 14 -1 -1 -1 -1 -1
-
-[core 1]
-type = RX
-queues in = -1 -1 -1 -1 -1 -1 -1 12
-queues out = 0 1 2 3 -1 -1 -1 15
-
-[core 2]
-type = FC
-queues in = 0 1 2 3 -1 -1 -1 13
-queues out = 4 5 6 7 -1 -1 -1 16
-
-[core 3]
-type = RT
-queues in = 4 5 6 7 -1 -1 -1 14
-queues out = 8 9 10 11 -1 -1 -1 17
-
-[core 4]
-type = TX
-queues in = 8 9 10 11 -1 -1 -1 -1
-queues out = -1 -1 -1 -1 -1 -1 -1 -1
diff --git a/examples/ip_pipeline/ip_pipeline.sh b/examples/ip_pipeline/ip_pipeline.sh
deleted file mode 100644
index c3419ca..0000000
--- a/examples/ip_pipeline/ip_pipeline.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#Address Resolution Protocol (ARP) Table
-#arp add iface ipaddr macaddr
-arp add 0 0.0.0.1 0a:0b:0c:0d:0e:0f
-arp add 1 0.128.0.1 1a:1b:1c:1d:1e:1f
-
-#Routing Table
-#route add ipaddr prefixlen iface gateway
-route add 0.0.0.0 9 0 0.0.0.1
-route add 0.128.0.0 9 1 0.128.0.1
-
-#Flow Table
-flow add all
-#flow add 0.0.0.0 1.2.3.4 0 0 6 0
-#flow add 10.11.12.13 0.0.0.0 0 0 6 1
-
-#Firewall
-#firewall add 1 0.0.0.0 0 0.0.0.0 9 0 65535 0 65535 6 0xf 0
-#firewall add 1 0.0.0.0 0 0.128.0.0 9 0 65535 0 65535 6 0xf 1
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 08/11] ip_pipeline: added new implementation of passthrough pipeline
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
` (6 preceding siblings ...)
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 07/11] ip_pipeline: moved config files to separate folder Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 09/11] ip_pipeline: added new implementation of firewall pipeline Maciej Gajdzica
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
From: Jasvinder Singh <jasvinder.singh@intel.com>
Passthrough pipeline implementation is split to two files.
pipeline_passthrough.c file handles front-end functions (cli commands
parsing) pipeline_passthrough_ops.c contains implementation of functions
done by pipeline (back-end).
Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
---
examples/ip_pipeline/Makefile | 2 +
examples/ip_pipeline/config/pt1.cfg | 9 +
examples/ip_pipeline/config/pt2.cfg | 15 +
examples/ip_pipeline/config/pt3.cfg | 21 +
examples/ip_pipeline/init.c | 2 +
examples/ip_pipeline/pipeline/hash_func.h | 351 ++++++++++
.../ip_pipeline/pipeline/pipeline_actions_common.h | 119 ++++
.../ip_pipeline/pipeline/pipeline_passthrough.c | 192 +----
.../ip_pipeline/pipeline/pipeline_passthrough.h | 41 ++
.../ip_pipeline/pipeline/pipeline_passthrough_be.c | 741 ++++++++++++++++++++
.../ip_pipeline/pipeline/pipeline_passthrough_be.h | 41 ++
11 files changed, 1355 insertions(+), 179 deletions(-)
create mode 100644 examples/ip_pipeline/config/pt1.cfg
create mode 100644 examples/ip_pipeline/config/pt2.cfg
create mode 100644 examples/ip_pipeline/config/pt3.cfg
create mode 100644 examples/ip_pipeline/pipeline/hash_func.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_actions_common.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough_be.h
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index f255338..930dc61 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -60,6 +60,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_be.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_fe.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master_be.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough.c
CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline
CFLAGS += -O3
diff --git a/examples/ip_pipeline/config/pt1.cfg b/examples/ip_pipeline/config/pt1.cfg
new file mode 100644
index 0000000..c9cdc78
--- /dev/null
+++ b/examples/ip_pipeline/config/pt1.cfg
@@ -0,0 +1,9 @@
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = PASS-THROUGH
+core = s0c1
+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/pt2.cfg b/examples/ip_pipeline/config/pt2.cfg
new file mode 100644
index 0000000..860cab6
--- /dev/null
+++ b/examples/ip_pipeline/config/pt2.cfg
@@ -0,0 +1,15 @@
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = PASS-THROUGH
+core = s0c1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = SWQ0 SWQ1 SWQ2 SWQ3
+
+[PIPELINE2]
+type = PASS-THROUGH
+core = s0c2
+pktq_in = SWQ0 SWQ1 SWQ2 SWQ3
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0
diff --git a/examples/ip_pipeline/config/pt3.cfg b/examples/ip_pipeline/config/pt3.cfg
new file mode 100644
index 0000000..e6159d0
--- /dev/null
+++ b/examples/ip_pipeline/config/pt3.cfg
@@ -0,0 +1,21 @@
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = PASS-THROUGH
+core = s0c1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = SWQ0 SWQ1 SWQ2 SWQ3
+
+[PIPELINE2]
+type = PASS-THROUGH
+core = s0c2
+pktq_in = SWQ0 SWQ1 SWQ2 SWQ3
+pktq_out = SWQ4 SWQ5 SWQ6 SWQ7
+
+[PIPELINE3]
+type = PASS-THROUGH
+core = s0c3
+pktq_in = SWQ4 SWQ5 SWQ6 SWQ7
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index b362af0..711c243 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -45,6 +45,7 @@
#include "pipeline.h"
#include "pipeline_common_fe.h"
#include "pipeline_master.h"
+#include "pipeline_passthrough.h"
#define APP_NAME_SIZE 32
@@ -1189,6 +1190,7 @@ int app_init(struct app_params *app)
app_pipeline_common_cmd_push(app);
app_pipeline_type_register(app, &pipeline_master);
+ app_pipeline_type_register(app, &pipeline_passthrough);
app_init_pipelines(app);
app_init_threads(app);
diff --git a/examples/ip_pipeline/pipeline/hash_func.h b/examples/ip_pipeline/pipeline/hash_func.h
new file mode 100644
index 0000000..0d9c019
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/hash_func.h
@@ -0,0 +1,351 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+#ifndef __INCLUDE_HASH_FUNC_H__
+#define __INCLUDE_HASH_FUNC_H__
+
+static inline uint64_t
+hash_xor_key8(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t xor0;
+
+ xor0 = seed ^ k[0];
+
+ return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key16(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t xor0;
+
+ xor0 = (k[0] ^ seed) ^ k[1];
+
+ return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key24(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t xor0;
+
+ xor0 = (k[0] ^ seed) ^ k[1];
+
+ xor0 ^= k[2];
+
+ return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key32(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t xor0, xor1;
+
+ xor0 = (k[0] ^ seed) ^ k[1];
+ xor1 = k[2] ^ k[3];
+
+ xor0 ^= xor1;
+
+ return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key40(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t xor0, xor1;
+
+ xor0 = (k[0] ^ seed) ^ k[1];
+ xor1 = k[2] ^ k[3];
+
+ xor0 ^= xor1;
+
+ xor0 ^= k[4];
+
+ return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key48(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t xor0, xor1, xor2;
+
+ xor0 = (k[0] ^ seed) ^ k[1];
+ xor1 = k[2] ^ k[3];
+ xor2 = k[4] ^ k[5];
+
+ xor0 ^= xor1;
+
+ xor0 ^= xor2;
+
+ return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key56(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t xor0, xor1, xor2;
+
+ xor0 = (k[0] ^ seed) ^ k[1];
+ xor1 = k[2] ^ k[3];
+ xor2 = k[4] ^ k[5];
+
+ xor0 ^= xor1;
+ xor2 ^= k[6];
+
+ xor0 ^= xor2;
+
+ return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key64(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t xor0, xor1, xor2, xor3;
+
+ xor0 = (k[0] ^ seed) ^ k[1];
+ xor1 = k[2] ^ k[3];
+ xor2 = k[4] ^ k[5];
+ xor3 = k[6] ^ k[7];
+
+ xor0 ^= xor1;
+ xor2 ^= xor3;
+
+ xor0 ^= xor2;
+
+ return (xor0 >> 32) ^ xor0;
+}
+
+#if defined(__x86_64__)
+
+#include <x86intrin.h>
+
+static inline uint64_t
+hash_crc_key8(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t crc0;
+
+ crc0 = _mm_crc32_u64(seed, k[0]);
+
+ return crc0;
+}
+
+static inline uint64_t
+hash_crc_key16(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t k0, crc0, crc1;
+
+ k0 = k[0];
+
+ crc0 = _mm_crc32_u64(k0, seed);
+ crc1 = _mm_crc32_u64(k0 >> 32, k[1]);
+
+ crc0 ^= crc1;
+
+ return crc0;
+}
+
+static inline uint64_t
+hash_crc_key24(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t k0, k2, crc0, crc1;
+
+ k0 = k[0];
+ k2 = k[2];
+
+ crc0 = _mm_crc32_u64(k0, seed);
+ crc1 = _mm_crc32_u64(k0 >> 32, k[1]);
+
+ crc0 = _mm_crc32_u64(crc0, k2);
+
+ crc0 ^= crc1;
+
+ return crc0;
+}
+
+static inline uint64_t
+hash_crc_key32(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t k0, k2, crc0, crc1, crc2, crc3;
+
+ k0 = k[0];
+ k2 = k[2];
+
+ crc0 = _mm_crc32_u64(k0, seed);
+ crc1 = _mm_crc32_u64(k0 >> 32, k[1]);
+
+ crc2 = _mm_crc32_u64(k2, k[3]);
+ crc3 = k2 >> 32;
+
+ crc0 = _mm_crc32_u64(crc0, crc1);
+ crc1 = _mm_crc32_u64(crc2, crc3);
+
+ crc0 ^= crc1;
+
+ return crc0;
+}
+
+static inline uint64_t
+hash_crc_key40(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t k0, k2, crc0, crc1, crc2, crc3;
+
+ k0 = k[0];
+ k2 = k[2];
+
+ crc0 = _mm_crc32_u64(k0, seed);
+ crc1 = _mm_crc32_u64(k0 >> 32, k[1]);
+
+ crc2 = _mm_crc32_u64(k2, k[3]);
+ crc3 = _mm_crc32_u64(k2 >> 32, k[4]);
+
+ crc0 = _mm_crc32_u64(crc0, crc1);
+ crc1 = _mm_crc32_u64(crc2, crc3);
+
+ crc0 ^= crc1;
+
+ return crc0;
+}
+
+static inline uint64_t
+hash_crc_key48(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t k0, k2, k5, crc0, crc1, crc2, crc3;
+
+ k0 = k[0];
+ k2 = k[2];
+ k5 = k[5];
+
+ crc0 = _mm_crc32_u64(k0, seed);
+ crc1 = _mm_crc32_u64(k0 >> 32, k[1]);
+
+ crc2 = _mm_crc32_u64(k2, k[3]);
+ crc3 = _mm_crc32_u64(k2 >> 32, k[4]);
+
+ crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2);
+ crc1 = _mm_crc32_u64(crc3, k5);
+
+ crc0 ^= crc1;
+
+ return crc0;
+}
+
+static inline uint64_t
+hash_crc_key56(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t k0, k2, k5, crc0, crc1, crc2, crc3, crc4, crc5;
+
+ k0 = k[0];
+ k2 = k[2];
+ k5 = k[5];
+
+ crc0 = _mm_crc32_u64(k0, seed);
+ crc1 = _mm_crc32_u64(k0 >> 32, k[1]);
+
+ crc2 = _mm_crc32_u64(k2, k[3]);
+ crc3 = _mm_crc32_u64(k2 >> 32, k[4]);
+
+ crc4 = _mm_crc32_u64(k5, k[6]);
+ crc5 = k5 >> 32;
+
+ crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2);
+ crc1 = _mm_crc32_u64(crc3, (crc4 << 32) ^ crc5);
+
+ crc0 ^= crc1;
+
+ return crc0;
+}
+
+static inline uint64_t
+hash_crc_key64(void *key, __rte_unused uint32_t key_size, uint64_t seed)
+{
+ uint64_t *k = key;
+ uint64_t k0, k2, k5, crc0, crc1, crc2, crc3, crc4, crc5;
+
+ k0 = k[0];
+ k2 = k[2];
+ k5 = k[5];
+
+ crc0 = _mm_crc32_u64(k0, seed);
+ crc1 = _mm_crc32_u64(k0 >> 32, k[1]);
+
+ crc2 = _mm_crc32_u64(k2, k[3]);
+ crc3 = _mm_crc32_u64(k2 >> 32, k[4]);
+
+ crc4 = _mm_crc32_u64(k5, k[6]);
+ crc5 = _mm_crc32_u64(k5 >> 32, k[7]);
+
+ crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2);
+ crc1 = _mm_crc32_u64(crc3, (crc4 << 32) ^ crc5);
+
+ crc0 ^= crc1;
+
+ return crc0;
+}
+
+#define hash_default_key8 hash_crc_key8
+#define hash_default_key16 hash_crc_key16
+#define hash_default_key24 hash_crc_key24
+#define hash_default_key32 hash_crc_key32
+#define hash_default_key40 hash_crc_key40
+#define hash_default_key48 hash_crc_key48
+#define hash_default_key56 hash_crc_key56
+#define hash_default_key64 hash_crc_key64
+
+#else
+
+#define hash_default_key8 hash_xor_key8
+#define hash_default_key16 hash_xor_key16
+#define hash_default_key24 hash_xor_key24
+#define hash_default_key32 hash_xor_key32
+#define hash_default_key40 hash_xor_key40
+#define hash_default_key48 hash_xor_key48
+#define hash_default_key56 hash_xor_key56
+#define hash_default_key64 hash_xor_key64
+
+#endif
+
+#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_actions_common.h b/examples/ip_pipeline/pipeline/pipeline_actions_common.h
new file mode 100644
index 0000000..3389ced
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_actions_common.h
@@ -0,0 +1,119 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+#ifndef __INCLUDE_PIPELINE_ACTIONS_COMMON_H__
+#define __INCLUDE_PIPELINE_ACTIONS_COMMON_H__
+
+#define PIPELINE_PORT_IN_AH(f_ah, f_pkt_work, f_pkt4_work) \
+static int \
+f_ah( \
+ struct rte_mbuf **pkts, \
+ uint32_t n_pkts, \
+ uint64_t *pkts_mask, \
+ 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); \
+ \
+ *pkts_mask = (~0LLU) >> (64 - n_pkts); \
+ \
+ return 0; \
+}
+
+#define PIPELINE_TABLE_AH_HIT(f_ah, f_pkt_work, f_pkt4_work) \
+static int \
+f_ah( \
+ struct rte_mbuf **pkts, \
+ uint64_t *pkts_mask, \
+ struct rte_pipeline_table_entry **entries, \
+ void *arg) \
+{ \
+ uint64_t pkts_in_mask = *pkts_mask; \
+ \
+ 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( \
+ struct rte_mbuf **pkts, \
+ uint64_t *pkts_mask, \
+ struct rte_pipeline_table_entry *entry, \
+ void *arg) \
+{ \
+ uint64_t pkts_in_mask = *pkts_mask; \
+ \
+ 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; \
+}
+
+#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough.c b/examples/ip_pipeline/pipeline/pipeline_passthrough.c
index 948b2c1..fc2cae5 100644
--- a/examples/ip_pipeline/pipeline/pipeline_passthrough.c
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,183 +31,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
+#include "pipeline_passthrough.h"
+#include "pipeline_passthrough_be.h"
-#include <rte_malloc.h>
-#include <rte_log.h>
+static struct pipeline_fe_ops pipeline_passthrough_fe_ops = {
+ .f_init = NULL,
+ .f_free = NULL,
+ .cmds = NULL,
+};
-#include <rte_port_ring.h>
-#include <rte_table_stub.h>
-#include <rte_pipeline.h>
-
-#include "main.h"
-
-void
-app_main_loop_pipeline_passthrough(void) {
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id[APP_MAX_PORTS];
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_PT))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing pass-through\n", core_id);
-
- /* Pipeline configuration */
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("%s: Unable to configure the pipeline\n", __func__);
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i])) {
- rte_panic("%s: Unable to configure input port for "
- "ring %d\n", __func__, i);
- }
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i])) {
- rte_panic("%s: Unable to configure output port for "
- "ring %d\n", __func__, i);
- }
- }
-
- /* Table configuration */
- for (i = 0; i < app.n_ports; 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,
- };
-
- if (rte_pipeline_table_create(p, &table_params, &table_id[i]))
- rte_panic("%s: Unable to configure table %u\n",
- __func__, i);
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++) {
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id[i])) {
- rte_panic("%s: Unable to connect input port %u to "
- "table %u\n", __func__, port_in_id[i],
- table_id[i]);
- }
- }
-
- /* Add entries to tables */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_pipeline_table_entry default_entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[i]},
- };
-
- struct rte_pipeline_table_entry *default_entry_ptr;
-
- if (rte_pipeline_table_default_entry_add(p, table_id[i],
- &default_entry, &default_entry_ptr))
- rte_panic("%s: Unable to add default entry to "
- "table %u\n", __func__, table_id[i]);
- }
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("%s: Pipeline consistency check failed\n", __func__);
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0)
- rte_pipeline_flush(p);
- }
-}
-
-void
-app_main_loop_passthrough(void) {
- struct app_mbuf_array *m;
- uint32_t i;
-
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
-
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_PT))
- rte_panic("Core %u misconfiguration\n", core_id);
-
- RTE_LOG(INFO, USER1, "Core %u is doing pass-through (no pipeline)\n",
- core_id);
-
- m = rte_malloc_socket(NULL, sizeof(struct app_mbuf_array),
- RTE_CACHE_LINE_SIZE, rte_socket_id());
- if (m == NULL)
- rte_panic("%s: cannot allocate buffer space\n", __func__);
-
- for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
- int ret;
-
- ret = rte_ring_sc_dequeue_bulk(
- app.rings[core_params->swq_in[i]],
- (void **) m->array,
- app.bsz_swq_rd);
-
- if (ret == -ENOENT)
- continue;
-
- do {
- ret = rte_ring_sp_enqueue_bulk(
- app.rings[core_params->swq_out[i]],
- (void **) m->array,
- app.bsz_swq_wr);
- } while (ret < 0);
- }
-}
+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
new file mode 100644
index 0000000..420a876
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough.h
@@ -0,0 +1,41 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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
new file mode 100644
index 0000000..3edf7ac
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
@@ -0,0 +1,741 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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 "hash_func.h"
+
+enum flow_key_type {
+ FLOW_KEY_QINQ,
+ FLOW_KEY_IPV4_5TUPLE,
+ FLOW_KEY_IPV6_5TUPLE,
+};
+
+struct pipeline_passthrough {
+ struct pipeline p;
+
+ uint32_t key_type_valid;
+ enum flow_key_type key_type;
+ uint32_t key_offset_rd;
+ uint32_t key_offset_wr;
+ uint32_t hash_offset;
+
+ rte_table_hash_op_hash f_hash;
+ rte_pipeline_port_in_action_handler f_port_in_ah;
+} __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 inline void
+pkt_work_key_qinq(
+ struct rte_mbuf *pkt,
+ void *arg)
+{
+ struct pipeline_passthrough *p_pt = arg;
+ uint64_t *key_rd = RTE_MBUF_METADATA_UINT64_PTR(pkt, p_pt->key_offset_rd);
+ uint64_t *key_wr = RTE_MBUF_METADATA_UINT64_PTR(pkt, p_pt->key_offset_wr);
+ uint32_t *hash = RTE_MBUF_METADATA_UINT32_PTR(pkt, p_pt->hash_offset);
+
+ /* Read */
+ uint64_t key_qinq = *key_rd & rte_bswap64(0x00000FFF00000FFFLLU);
+
+ /* Compute */
+ uint32_t hash_qinq = p_pt->f_hash(&key_qinq, 8, 0);
+
+ /* Write */
+ *key_wr = key_qinq;
+ *hash = hash_qinq;
+}
+
+static inline void
+pkt4_work_key_qinq(
+ struct rte_mbuf **pkt,
+ void *arg)
+{
+ struct pipeline_passthrough *p_pt = arg;
+
+ uint64_t *key_rd0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], p_pt->key_offset_rd);
+ uint64_t *key_wr0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], p_pt->key_offset_wr);
+ uint32_t *hash0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0], p_pt->hash_offset);
+
+ uint64_t *key_rd1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], p_pt->key_offset_rd);
+ uint64_t *key_wr1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], p_pt->key_offset_wr);
+ uint32_t *hash1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1], p_pt->hash_offset);
+
+ uint64_t *key_rd2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], p_pt->key_offset_rd);
+ uint64_t *key_wr2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], p_pt->key_offset_wr);
+ uint32_t *hash2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2], p_pt->hash_offset);
+
+ uint64_t *key_rd3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], p_pt->key_offset_rd);
+ uint64_t *key_wr3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], p_pt->key_offset_wr);
+ uint32_t *hash3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3], p_pt->hash_offset);
+
+ /* Read */
+ uint64_t key_qinq0 = *key_rd0 & rte_bswap64(0x00000FFF00000FFFLLU);
+ uint64_t key_qinq1 = *key_rd1 & rte_bswap64(0x00000FFF00000FFFLLU);
+ uint64_t key_qinq2 = *key_rd2 & rte_bswap64(0x00000FFF00000FFFLLU);
+ uint64_t key_qinq3 = *key_rd3 & rte_bswap64(0x00000FFF00000FFFLLU);
+
+ /* Compute */
+ uint32_t hash_qinq0 = p_pt->f_hash(&key_qinq0, 8, 0);
+ uint32_t hash_qinq1 = p_pt->f_hash(&key_qinq1, 8, 0);
+ uint32_t hash_qinq2 = p_pt->f_hash(&key_qinq2, 8, 0);
+ uint32_t hash_qinq3 = p_pt->f_hash(&key_qinq3, 8, 0);
+
+ /* Write */
+ *key_wr0 = key_qinq0;
+ *key_wr1 = key_qinq1;
+ *key_wr2 = key_qinq2;
+ *key_wr3 = key_qinq3;
+
+ *hash0 = hash_qinq0;
+ *hash1 = hash_qinq1;
+ *hash2 = hash_qinq2;
+ *hash3 = hash_qinq3;
+}
+
+PIPELINE_PORT_IN_AH(port_in_ah_key_qinq, pkt_work_key_qinq, pkt4_work_key_qinq);
+
+static inline void
+pkt_work_key_ipv4(
+ struct rte_mbuf *pkt,
+ void *arg)
+{
+ struct pipeline_passthrough *p_pt = arg;
+ uint64_t *key_rd = RTE_MBUF_METADATA_UINT64_PTR(pkt, p_pt->key_offset_rd);
+ uint64_t *key_wr = RTE_MBUF_METADATA_UINT64_PTR(pkt, p_pt->key_offset_wr);
+ uint32_t *hash = RTE_MBUF_METADATA_UINT32_PTR(pkt, p_pt->hash_offset);
+ uint64_t key_ipv4[2];
+ uint32_t hash_ipv4;
+
+ /* Read */
+ key_ipv4[0] = key_rd[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU);
+ key_ipv4[1] = key_rd[1];
+
+ /* Compute */
+ hash_ipv4 = p_pt->f_hash(key_ipv4, 16, 0);
+
+ /* Write */
+ key_wr[0] = key_ipv4[0];
+ key_wr[1] = key_ipv4[1];
+ *hash = hash_ipv4;
+}
+
+static inline void
+pkt4_work_key_ipv4(
+ struct rte_mbuf **pkt,
+ void *arg)
+{
+ struct pipeline_passthrough *p_pt = arg;
+
+ uint64_t *key_rd0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], p_pt->key_offset_rd);
+ uint64_t *key_wr0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], p_pt->key_offset_wr);
+ uint32_t *hash0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0], p_pt->hash_offset);
+
+ uint64_t *key_rd1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], p_pt->key_offset_rd);
+ uint64_t *key_wr1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], p_pt->key_offset_wr);
+ uint32_t *hash1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1], p_pt->hash_offset);
+
+ uint64_t *key_rd2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], p_pt->key_offset_rd);
+ uint64_t *key_wr2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], p_pt->key_offset_wr);
+ uint32_t *hash2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2], p_pt->hash_offset);
+
+ uint64_t *key_rd3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], p_pt->key_offset_rd);
+ uint64_t *key_wr3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], p_pt->key_offset_wr);
+ uint32_t *hash3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3], p_pt->hash_offset);
+
+ uint64_t key_ipv4_0[2];
+ uint64_t key_ipv4_1[2];
+ uint64_t key_ipv4_2[2];
+ uint64_t key_ipv4_3[2];
+
+ uint32_t hash_ipv4_0;
+ uint32_t hash_ipv4_1;
+ uint32_t hash_ipv4_2;
+ uint32_t hash_ipv4_3;
+
+ /* Read */
+ key_ipv4_0[0] = key_rd0[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU);
+ key_ipv4_1[0] = key_rd1[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU);
+ key_ipv4_2[0] = key_rd2[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU);
+ key_ipv4_3[0] = key_rd3[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU);
+
+ key_ipv4_0[1] = key_rd0[1];
+ key_ipv4_1[1] = key_rd1[1];
+ key_ipv4_2[1] = key_rd2[1];
+ key_ipv4_3[1] = key_rd3[1];
+
+ /* Compute */
+ hash_ipv4_0 = p_pt->f_hash(key_ipv4_0, 16, 0);
+ hash_ipv4_1 = p_pt->f_hash(key_ipv4_1, 16, 0);
+ hash_ipv4_2 = p_pt->f_hash(key_ipv4_2, 16, 0);
+ hash_ipv4_3 = p_pt->f_hash(key_ipv4_3, 16, 0);
+
+ /* Write */
+ key_wr0[0] = key_ipv4_0[0];
+ key_wr1[0] = key_ipv4_1[0];
+ key_wr2[0] = key_ipv4_2[0];
+ key_wr3[0] = key_ipv4_3[0];
+
+ key_wr0[1] = key_ipv4_0[1];
+ key_wr1[1] = key_ipv4_1[1];
+ key_wr2[1] = key_ipv4_2[1];
+ key_wr3[1] = key_ipv4_3[1];
+
+ *hash0 = hash_ipv4_0;
+ *hash1 = hash_ipv4_1;
+ *hash2 = hash_ipv4_2;
+ *hash3 = hash_ipv4_3;
+}
+
+PIPELINE_PORT_IN_AH(port_in_ah_key_ipv4, pkt_work_key_ipv4, pkt4_work_key_ipv4);
+
+static inline void
+pkt_work_key_ipv6(
+ struct rte_mbuf *pkt,
+ void *arg)
+{
+ struct pipeline_passthrough *p_pt = arg;
+ uint64_t *key_rd = RTE_MBUF_METADATA_UINT64_PTR(pkt, p_pt->key_offset_rd);
+ uint64_t *key_wr = RTE_MBUF_METADATA_UINT64_PTR(pkt, p_pt->key_offset_wr);
+ uint32_t *hash = RTE_MBUF_METADATA_UINT32_PTR(pkt, p_pt->hash_offset);
+ uint64_t key_ipv6[8];
+ uint32_t hash_ipv6;
+
+ /* Read */
+ key_ipv6[0] = key_rd[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU);
+ key_ipv6[1] = key_rd[1];
+ key_ipv6[2] = key_rd[2];
+ key_ipv6[3] = key_rd[3];
+ key_ipv6[4] = key_rd[4];
+ key_ipv6[5] = 0;
+ key_ipv6[6] = 0;
+ key_ipv6[7] = 0;
+
+ /* Compute */
+ hash_ipv6 = p_pt->f_hash(key_ipv6, 64, 0);
+
+ /* Write */
+ key_wr[0] = key_ipv6[0];
+ key_wr[1] = key_ipv6[1];
+ key_wr[2] = key_ipv6[2];
+ key_wr[3] = key_ipv6[3];
+ key_wr[4] = key_ipv6[4];
+ key_wr[5] = 0;
+ key_wr[6] = 0;
+ key_wr[7] = 0;
+ *hash = hash_ipv6;
+}
+
+static inline void
+pkt4_work_key_ipv6(
+ struct rte_mbuf **pkt,
+ void *arg)
+{
+ struct pipeline_passthrough *p_pt = arg;
+
+ uint64_t *key_rd0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], p_pt->key_offset_rd);
+ uint64_t *key_wr0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], p_pt->key_offset_wr);
+ uint32_t *hash0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0], p_pt->hash_offset);
+
+ uint64_t *key_rd1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], p_pt->key_offset_rd);
+ uint64_t *key_wr1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], p_pt->key_offset_wr);
+ uint32_t *hash1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1], p_pt->hash_offset);
+
+ uint64_t *key_rd2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], p_pt->key_offset_rd);
+ uint64_t *key_wr2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], p_pt->key_offset_wr);
+ uint32_t *hash2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2], p_pt->hash_offset);
+
+ uint64_t *key_rd3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], p_pt->key_offset_rd);
+ uint64_t *key_wr3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], p_pt->key_offset_wr);
+ uint32_t *hash3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3], p_pt->hash_offset);
+
+ uint64_t key_ipv6_0[8];
+ uint64_t key_ipv6_1[8];
+ uint64_t key_ipv6_2[8];
+ uint64_t key_ipv6_3[8];
+
+ uint32_t hash_ipv6_0;
+ uint32_t hash_ipv6_1;
+ uint32_t hash_ipv6_2;
+ uint32_t hash_ipv6_3;
+
+ /* Read */
+ key_ipv6_0[0] = key_rd0[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU);
+ key_ipv6_1[0] = key_rd1[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU);
+ key_ipv6_2[0] = key_rd2[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU);
+ key_ipv6_3[0] = key_rd3[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU);
+
+ key_ipv6_0[1] = key_rd0[1];
+ key_ipv6_1[1] = key_rd1[1];
+ key_ipv6_2[1] = key_rd2[1];
+ key_ipv6_3[1] = key_rd3[1];
+
+ key_ipv6_0[2] = key_rd0[2];
+ key_ipv6_1[2] = key_rd1[2];
+ key_ipv6_2[2] = key_rd2[2];
+ key_ipv6_3[2] = key_rd3[2];
+
+ key_ipv6_0[3] = key_rd0[3];
+ key_ipv6_1[3] = key_rd1[3];
+ key_ipv6_2[3] = key_rd2[3];
+ key_ipv6_3[3] = key_rd3[3];
+
+ key_ipv6_0[4] = key_rd0[4];
+ key_ipv6_1[4] = key_rd1[4];
+ key_ipv6_2[4] = key_rd2[4];
+ key_ipv6_3[4] = key_rd3[4];
+
+ key_ipv6_0[5] = 0;
+ key_ipv6_1[5] = 0;
+ key_ipv6_2[5] = 0;
+ key_ipv6_3[5] = 0;
+
+ key_ipv6_0[6] = 0;
+ key_ipv6_1[6] = 0;
+ key_ipv6_2[6] = 0;
+ key_ipv6_3[6] = 0;
+
+ key_ipv6_0[7] = 0;
+ key_ipv6_1[7] = 0;
+ key_ipv6_2[7] = 0;
+ key_ipv6_3[7] = 0;
+
+ /* Compute */
+ hash_ipv6_0 = p_pt->f_hash(key_ipv6_0, 64, 0);
+ hash_ipv6_1 = p_pt->f_hash(key_ipv6_1, 64, 0);
+ hash_ipv6_2 = p_pt->f_hash(key_ipv6_2, 64, 0);
+ hash_ipv6_3 = p_pt->f_hash(key_ipv6_3, 64, 0);
+
+ /* Write */
+ key_wr0[0] = key_ipv6_0[0];
+ key_wr1[0] = key_ipv6_1[0];
+ key_wr2[0] = key_ipv6_2[0];
+ key_wr3[0] = key_ipv6_3[0];
+
+ key_wr0[1] = key_ipv6_0[1];
+ key_wr1[1] = key_ipv6_1[1];
+ key_wr2[1] = key_ipv6_2[1];
+ key_wr3[1] = key_ipv6_3[1];
+
+ key_wr0[2] = key_ipv6_0[2];
+ key_wr1[2] = key_ipv6_1[2];
+ key_wr2[2] = key_ipv6_2[2];
+ key_wr3[2] = key_ipv6_3[2];
+
+ key_wr0[3] = key_ipv6_0[3];
+ key_wr1[3] = key_ipv6_1[3];
+ key_wr2[3] = key_ipv6_2[3];
+ key_wr3[3] = key_ipv6_3[3];
+
+ key_wr0[4] = key_ipv6_0[4];
+ key_wr1[4] = key_ipv6_1[4];
+ key_wr2[4] = key_ipv6_2[4];
+ key_wr3[4] = key_ipv6_3[4];
+
+ key_wr0[5] = 0;
+ key_wr0[5] = 0;
+ key_wr0[5] = 0;
+ key_wr0[5] = 0;
+
+ key_wr0[6] = 0;
+ key_wr0[6] = 0;
+ key_wr0[6] = 0;
+ key_wr0[6] = 0;
+
+ key_wr0[7] = 0;
+ key_wr0[7] = 0;
+ key_wr0[7] = 0;
+ key_wr0[7] = 0;
+
+ *hash0 = hash_ipv6_0;
+ *hash1 = hash_ipv6_1;
+ *hash2 = hash_ipv6_2;
+ *hash3 = hash_ipv6_3;
+}
+
+PIPELINE_PORT_IN_AH(port_in_ah_key_ipv6, pkt_work_key_ipv6, pkt4_work_key_ipv6);
+
+static int
+pipeline_passthrough_parse_args(struct pipeline_passthrough *p,
+ struct pipeline_params *params)
+{
+ uint32_t key_type_present = 0;
+ uint32_t key_offset_rd_present = 0;
+ uint32_t key_offset_wr_present = 0;
+ uint32_t hash_offset_present = 0;
+ uint32_t i;
+
+ for (i = 0; i < params->n_args; i++) {
+ char *arg_name = params->args_name[i];
+ char *arg_value = params->args_value[i];
+
+ /* key_type */
+ if (strcmp(arg_name, "key_type") == 0) {
+ if (key_type_present)
+ return -1;
+ key_type_present = 1;
+
+ if ((strcmp(arg_value, "q-in-q") == 0) ||
+ (strcmp(arg_value, "qinq") == 0))
+ p->key_type = FLOW_KEY_QINQ;
+ else if (strcmp(arg_value, "ipv4_5tuple") == 0)
+ p->key_type = FLOW_KEY_IPV4_5TUPLE;
+ else if (strcmp(arg_value, "ipv6_5tuple") == 0)
+ p->key_type = FLOW_KEY_IPV6_5TUPLE;
+ else
+ return -1;
+
+ p->key_type_valid = 1;
+
+ continue;
+ }
+
+ /* key_offset_rd */
+ if (strcmp(arg_name, "key_offset_rd") == 0) {
+ if (key_offset_rd_present)
+ return -1;
+ key_offset_rd_present = 1;
+
+ p->key_offset_rd = atoi(arg_value);
+
+ continue;
+ }
+
+ /* key_offset_wr */
+ if (strcmp(arg_name, "key_offset_wr") == 0) {
+ if (key_offset_wr_present)
+ return -1;
+ key_offset_wr_present = 1;
+
+ p->key_offset_wr = atoi(arg_value);
+
+ continue;
+ }
+
+ /* hash_offset */
+ if (strcmp(arg_name, "hash_offset") == 0) {
+ if (hash_offset_present)
+ return -1;
+ hash_offset_present = 1;
+
+ p->hash_offset = atoi(arg_value);
+
+ continue;
+ }
+
+ /* any other */
+ return -1;
+ }
+
+ /* Check that mandatory arguments are present */
+ if ((key_offset_rd_present != key_type_present) ||
+ (key_offset_wr_present != key_type_present) ||
+ (hash_offset_present != key_type_present))
+ return -1;
+
+ 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) ||
+ (params->n_ports_in < params->n_ports_out) ||
+ (params->n_ports_in % params->n_ports_out))
+ 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))
+ return NULL;
+
+ if (p_pt->key_type_valid == 0) {
+ p_pt->f_hash = NULL;
+ p_pt->f_port_in_ah = NULL;
+ } else
+ switch (p_pt->key_type) {
+ case FLOW_KEY_QINQ:
+ p_pt->f_hash = hash_default_key8;
+ p_pt->f_port_in_ah = port_in_ah_key_qinq;
+ break;
+
+ case FLOW_KEY_IPV4_5TUPLE:
+ p_pt->f_hash = hash_default_key16;
+ p_pt->f_port_in_ah = port_in_ah_key_ipv4;
+ break;
+
+ case FLOW_KEY_IPV6_5TUPLE:
+ p_pt->f_hash = hash_default_key64;
+ p_pt->f_port_in_ah = port_in_ah_key_ipv6;
+ break;
+
+ default:
+ p_pt->f_hash = NULL;
+ p_pt->f_port_in_ah = NULL;
+ }
+
+ /* 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;
+ }
+ }
+
+ /* 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 = p_pt->f_port_in_ah,
+ .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 */
+ 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,
+ .f_action_bulk = 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 = p->n_ports_in;
+ 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++) {
+ struct rte_pipeline_table_entry default_entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = p->port_out_id[i / (p->n_ports_in / p->n_ports_out)]},
+ };
+
+
+ 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;
+}
+
+static int
+pipeline_passthrough_track(void *pipeline, uint32_t port_in, uint32_t *port_out)
+{
+ struct pipeline *p = (struct pipeline *) pipeline;
+
+ /* Check input arguments */
+ if ((p == NULL) ||
+ (port_in >= p->n_ports_in) ||
+ (port_out == NULL))
+ return -1;
+
+ *port_out = port_in / p->n_ports_in;
+ 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,
+ .f_track = pipeline_passthrough_track,
+};
diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h
new file mode 100644
index 0000000..9d5e3db
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h
@@ -0,0 +1,41 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#ifndef __INCLUDE_PIPELINE_PASSTHROUGH_BE_H__
+#define __INCLUDE_PIPELINE_PASSTHROUGH_BE_H__
+
+#include "pipeline_common_be.h"
+
+extern struct pipeline_be_ops pipeline_passthrough_be_ops;
+
+#endif
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 09/11] ip_pipeline: added new implementation of firewall pipeline
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
` (7 preceding siblings ...)
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 08/11] ip_pipeline: added new implementation of passthrough pipeline Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 10/11] ip_pipeline: added new implementation of routing pipeline Maciej Gajdzica
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
From: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
Firewall pipeline implementation is split to two files.
pipeline_firewall.c file handles front-end functions (cli commands
parsing) pipeline_firewall_ops.c contains implementation of functions
done by pipeline (back-end).
Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
---
examples/ip_pipeline/Makefile | 2 +
examples/ip_pipeline/config/fw.cfg | 11 +
examples/ip_pipeline/config/fw.sh | 13 +
examples/ip_pipeline/init.c | 2 +
examples/ip_pipeline/pipeline/pipeline_firewall.c | 1125 +++++++++++++++-----
examples/ip_pipeline/pipeline/pipeline_firewall.h | 63 ++
.../ip_pipeline/pipeline/pipeline_firewall_be.c | 701 ++++++++++++
.../ip_pipeline/pipeline/pipeline_firewall_be.h | 138 +++
8 files changed, 1816 insertions(+), 239 deletions(-)
create mode 100644 examples/ip_pipeline/config/fw.cfg
create mode 100644 examples/ip_pipeline/config/fw.sh
create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.h
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index 930dc61..382fee6 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -62,6 +62,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master_be.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough_be.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c
CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline
CFLAGS += -O3
diff --git a/examples/ip_pipeline/config/fw.cfg b/examples/ip_pipeline/config/fw.cfg
new file mode 100644
index 0000000..fba324b
--- /dev/null
+++ b/examples/ip_pipeline/config/fw.cfg
@@ -0,0 +1,11 @@
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = FIREWALL
+core = s0c1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0
+n_rules = 4096
+pkt_type = ipv4
diff --git a/examples/ip_pipeline/config/fw.sh b/examples/ip_pipeline/config/fw.sh
new file mode 100644
index 0000000..59e1213
--- /dev/null
+++ b/examples/ip_pipeline/config/fw.sh
@@ -0,0 +1,13 @@
+#Firewall
+
+p 1 firewall add ipv4 1 0.0.0.0 0 0.0.0.0 10 0 65535 0 65535 6 0xf 0
+p 1 firewall add ipv4 1 0.0.0.0 0 0.64.0.0 10 0 65535 0 65535 6 0xf 1
+p 1 firewall add ipv4 1 0.0.0.0 0 0.128.0.0 10 0 65535 0 65535 6 0xf 2
+p 1 firewall add ipv4 1 0.0.0.0 0 0.192.0.0 10 0 65535 0 65535 6 0xf 3
+
+p 1 firewall ls
+
+#p 1 firewall del ipv4 0.0.0.0 0 0.0.0.0 10 0 65535 0 65535 6 0xf
+#p 1 firewall del ipv4 0.0.0.0 0 0.64.0.0 10 0 65535 0 65535 6 0xf
+#p 1 firewall del ipv4 0.0.0.0 0 0.128.0.0 10 0 65535 0 65535 6 0xf
+#p 1 firewall del ipv4 0.0.0.0 0 0.192.0.0 10 0 65535 0 65535 6 0xf
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index 711c243..3583672 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -46,6 +46,7 @@
#include "pipeline_common_fe.h"
#include "pipeline_master.h"
#include "pipeline_passthrough.h"
+#include "pipeline_firewall.h"
#define APP_NAME_SIZE 32
@@ -1191,6 +1192,7 @@ int app_init(struct app_params *app)
app_pipeline_common_cmd_push(app);
app_pipeline_type_register(app, &pipeline_master);
app_pipeline_type_register(app, &pipeline_passthrough);
+ app_pipeline_type_register(app, &pipeline_firewall);
app_init_pipelines(app);
app_init_threads(app);
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c
index b70260e..9796fe2 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall.c
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,282 +32,929 @@
*/
#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+#include <rte_common.h>
+#include <rte_hexdump.h>
#include <rte_malloc.h>
-#include <rte_log.h>
-#include <rte_ethdev.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-#include <rte_byteorder.h>
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_ipaddr.h>
+#include <cmdline_parse_etheraddr.h>
+#include <cmdline_socket.h>
+
+#include "app.h"
+#include "pipeline_common_fe.h"
+#include "pipeline_firewall.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;
+};
-#include <rte_port_ring.h>
-#include <rte_table_acl.h>
-#include <rte_pipeline.h>
+static void
+print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule)
+{
+ printf("Prio = %d (SA = %u.%u.%u.%u/%u, "
+ "DA = %u.%u.%u.%u/%u, "
+ "SP = %u-%u, "
+ "DP = %u-%u, "
+ "Proto = %u / 0x%x) => "
+ "Port = %u (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);
+}
-#include "main.h"
+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;
-struct app_core_firewall_message_handle_params {
- struct rte_ring *ring_req;
- struct rte_ring *ring_resp;
+ TAILQ_FOREACH(r, &p->rules, node)
+ if (memcmp(key, &r->key, sizeof(struct pipeline_firewall_key)) == 0)
+ return r;
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t table_id;
-};
+ return NULL;
+}
static void
-app_message_handle(struct app_core_firewall_message_handle_params *params);
-
-enum {
- PROTO_FIELD_IPV4,
- SRC_FIELD_IPV4,
- DST_FIELD_IPV4,
- SRCP_FIELD_IPV4,
- DSTP_FIELD_IPV4,
- NUM_FIELDS_IPV4
-};
+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;
-struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = {
- {
- .type = RTE_ACL_FIELD_TYPE_BITMASK,
- .size = sizeof(uint8_t),
- .field_index = PROTO_FIELD_IPV4,
- .input_index = PROTO_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) +
- offsetof(struct ipv4_hdr, next_proto_id),
- },
- {
- .type = RTE_ACL_FIELD_TYPE_MASK,
- .size = sizeof(uint32_t),
- .field_index = SRC_FIELD_IPV4,
- .input_index = SRC_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) +
- offsetof(struct ipv4_hdr, src_addr),
- },
- {
- .type = RTE_ACL_FIELD_TYPE_MASK,
- .size = sizeof(uint32_t),
- .field_index = DST_FIELD_IPV4,
- .input_index = DST_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) +
- offsetof(struct ipv4_hdr, dst_addr),
- },
- {
- .type = RTE_ACL_FIELD_TYPE_RANGE,
- .size = sizeof(uint16_t),
- .field_index = SRCP_FIELD_IPV4,
- .input_index = SRCP_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr),
- },
- {
- .type = RTE_ACL_FIELD_TYPE_RANGE,
- .size = sizeof(uint16_t),
- .field_index = DSTP_FIELD_IPV4,
- .input_index = SRCP_FIELD_IPV4,
- .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
- sizeof(uint16_t),
- },
-};
+ /* Check input arguments */
+ if (app == NULL)
+ return;
-void
-app_main_loop_pipeline_firewall(void) {
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
+ p = app_pipeline_data_fe(app, pipeline_id);
+ if (p == NULL)
+ return;
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id;
- uint32_t i;
+ 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 %u (entry ptr = %p)\n",
+ p->default_rule_port_id,
+ p->default_rule_entry_ptr);
+ else
+ printf("Default rule: DROP\n");
+
+ printf("\n");
+}
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
- struct app_core_firewall_message_handle_params mh_params;
+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;
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_FW))
- rte_panic("Core %u misconfiguration\n", core_id);
+ /* Initialization */
+ p->n_ports_in = params->n_ports_in;
+ p->n_ports_out = params->n_ports_out;
- RTE_LOG(INFO, USER1, "Core %u is doing firewall\n", core_id);
+ 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;
- /* Pipeline configuration */
- p = rte_pipeline_create(&pipeline_params);
+ return (void *) p;
+}
+
+static int
+app_pipeline_firewall_free(void *pipeline)
+{
+ struct app_pipeline_firewall *p = pipeline;
+
+ /* Check input arguments */
if (p == NULL)
- rte_panic("Unable to configure the pipeline\n");
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i]))
- rte_panic("Unable to configure input port for "
- "ring %d\n", i);
+ 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.src_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 = (~0) << (32 - src_ip_depth);
+
+ if (dst_ip_depth)
+ dst_ip_netmask = ((~0) << (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_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);
+ if (p == NULL)
+ return -1;
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i]))
- rte_panic("Unable to configure output port for "
- "ring %d\n", i);
+ 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;
}
- /* Table configuration */
- {
- struct rte_table_acl_params table_acl_params = {
- .name = "test", /* unique identifier for acl contexts */
- .n_rules = app.max_firewall_rules,
- .n_rule_fields = DIM(ipv4_field_formats),
- };
-
- 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 = 0,
- };
-
- memcpy(table_acl_params.field_format, ipv4_field_formats,
- sizeof(ipv4_field_formats));
-
- if (rte_pipeline_table_create(p, &table_params, &table_id))
- rte_panic("Unable to configure the ACL table\n");
+ /* Allocate and write request */
+ req = app_msg_alloc(app);
+ if (req == NULL) {
+ if (new_rule)
+ rte_free(rule);
+ return -1;
}
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id))
- rte_panic("Unable to connect input port %u to "
- "table %u\n", port_in_id[i], table_id);
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("Pipeline consistency check failed\n");
-
- /* Message handling */
- mh_params.ring_req = app_get_ring_req(
- app_get_first_core_id(APP_CORE_FW));
- mh_params.ring_resp = app_get_ring_resp(
- app_get_first_core_id(APP_CORE_FW));
- mh_params.p = p;
- mh_params.port_out_id = port_out_id;
- mh_params.table_id = table_id;
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0) {
- rte_pipeline_flush(p);
- app_message_handle(&mh_params);
- }
+ 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;
}
-void
-app_message_handle(struct app_core_firewall_message_handle_params *params)
+int
+app_pipeline_firewall_delete_rule(struct app_params *app,
+ uint32_t pipeline_id,
+ struct pipeline_firewall_key *key)
{
- struct rte_ring *ring_req = params->ring_req;
- struct rte_ring *ring_resp;
- struct rte_mbuf *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t table_id;
- int result;
-
- /* Read request message */
- result = rte_ring_sc_dequeue(ring_req, (void **) &msg);
- if (result != 0)
- return;
+ 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);
+ 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_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);
+ 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);
+ 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;
+}
- ring_resp = params->ring_resp;
- p = params->p;
- port_out_id = params->port_out_id;
- table_id = params->table_id;
-
- /* Handle request */
- req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
- switch (req->type) {
- case APP_MSG_REQ_PING:
- {
- result = 0;
- break;
+/*
+ * p firewall add ipv4
+ */
+
+struct cmd_firewall_add_ipv4_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t firewall_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t ipv4_string;
+ int32_t priority;
+ cmdline_ipaddr_t src_ip;
+ uint32_t src_ip_mask;
+ cmdline_ipaddr_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;
+ uint8_t port_id;
+};
+
+static void
+cmd_firewall_add_ipv4_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_firewall_add_ipv4_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_firewall_key key;
+ int status;
+
+ key.type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.src_ip = rte_bswap32((uint32_t) params->src_ip.addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask;
+ key.key.ipv4_5tuple.dst_ip = rte_bswap32((uint32_t) params->dst_ip.addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask;
+ key.key.ipv4_5tuple.src_port_from = params->src_port_from;
+ key.key.ipv4_5tuple.src_port_to = params->src_port_to;
+ key.key.ipv4_5tuple.dst_port_from = params->dst_port_from;
+ key.key.ipv4_5tuple.dst_port_to = params->dst_port_to;
+ key.key.ipv4_5tuple.proto = params->proto;
+ key.key.ipv4_5tuple.proto_mask = params->proto_mask;
+
+ status = app_pipeline_firewall_add_rule(app,
+ params->pipeline_id,
+ &key,
+ params->priority,
+ params->port_id);
+
+ if(status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
+
+cmdline_parse_token_string_t cmd_firewall_add_ipv4_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_add_ipv4_firewall_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_add_ipv4_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, add_string, "add");
- case APP_MSG_REQ_FW_ADD:
- {
- struct rte_pipeline_table_entry entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[req->firewall_add.port]},
- };
+cmdline_parse_token_string_t cmd_firewall_add_ipv4_ipv4_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, ipv4_string, "ipv4");
- struct rte_pipeline_table_entry *entry_ptr;
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_priority =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, priority, INT32);
- int key_found;
+cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_src_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip);
- result = rte_pipeline_table_entry_add(p, table_id,
- &req->firewall_add.add_params, &entry, &key_found,
- &entry_ptr);
- break;
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_ip_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip_mask, UINT32);
+
+cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_dst_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_ip_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip_mask, UINT32);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_from =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_to =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_port_to, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_from =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_to =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_port_to, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, proto, UINT8);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, proto_mask, UINT8);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, port_id, UINT8);
+
+cmdline_parse_inst_t cmd_firewall_add_ipv4 = {
+ .f = cmd_firewall_add_ipv4_parsed,
+ .data = NULL,
+ .help_str = "Firewall rule add",
+ .tokens = {
+ (void *) &cmd_firewall_add_ipv4_p_string,
+ (void *) &cmd_firewall_add_ipv4_pipeline_id,
+ (void *) &cmd_firewall_add_ipv4_firewall_string,
+ (void *) &cmd_firewall_add_ipv4_add_string,
+ (void *) &cmd_firewall_add_ipv4_ipv4_string,
+ (void *) &cmd_firewall_add_ipv4_priority,
+ (void *) &cmd_firewall_add_ipv4_src_ip,
+ (void *) &cmd_firewall_add_ipv4_src_ip_mask,
+ (void *) &cmd_firewall_add_ipv4_dst_ip,
+ (void *) &cmd_firewall_add_ipv4_dst_ip_mask,
+ (void *) &cmd_firewall_add_ipv4_src_port_from,
+ (void *) &cmd_firewall_add_ipv4_src_port_to,
+ (void *) &cmd_firewall_add_ipv4_dst_port_from,
+ (void *) &cmd_firewall_add_ipv4_dst_port_to,
+ (void *) &cmd_firewall_add_ipv4_proto,
+ (void *) &cmd_firewall_add_ipv4_proto_mask,
+ (void *) &cmd_firewall_add_ipv4_port_id,
+ NULL,
+ },
+};
+
+/*
+ * p firewall del ipv4
+ */
+
+struct cmd_firewall_del_ipv4_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t firewall_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_fixed_string_t ipv4_string;
+ cmdline_ipaddr_t src_ip;
+ uint32_t src_ip_mask;
+ cmdline_ipaddr_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;
+};
+
+static void
+cmd_firewall_del_ipv4_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_firewall_del_ipv4_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_firewall_key key;
+ int status;
+
+ key.type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.src_ip = rte_bswap32((uint32_t) params->src_ip.addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask;
+ key.key.ipv4_5tuple.dst_ip = rte_bswap32((uint32_t) params->dst_ip.addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask;
+ key.key.ipv4_5tuple.src_port_from = params->src_port_from;
+ key.key.ipv4_5tuple.src_port_to = params->src_port_to;
+ key.key.ipv4_5tuple.dst_port_from = params->dst_port_from;
+ key.key.ipv4_5tuple.dst_port_to = params->dst_port_to;
+ key.key.ipv4_5tuple.proto = params->proto;
+ key.key.ipv4_5tuple.proto_mask = params->proto_mask;
+
+ status = app_pipeline_firewall_delete_rule(app,
+ params->pipeline_id,
+ &key);
+
+ if(status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
+
+cmdline_parse_token_string_t cmd_firewall_del_ipv4_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_del_ipv4_firewall_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_del_ipv4_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, del_string, "del");
+
+cmdline_parse_token_string_t cmd_firewall_del_ipv4_ipv4_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, ipv4_string, "ipv4");
+
+cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_src_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_ip_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip_mask, UINT32);
+
+cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_dst_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_ip_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip_mask, UINT32);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_from =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_to =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_port_to, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_from =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_port_from, UINT16);
- case APP_MSG_REQ_FW_DEL:
- {
- int key_found;
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_to =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_port_to, UINT16);
- result = rte_pipeline_table_entry_delete(p, table_id,
- &req->firewall_del.delete_params, &key_found, NULL);
- break;
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, proto, UINT8);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, proto_mask, UINT8);
+
+cmdline_parse_inst_t cmd_firewall_del_ipv4 = {
+ .f = cmd_firewall_del_ipv4_parsed,
+ .data = NULL,
+ .help_str = "Firewall rule delete",
+ .tokens = {
+ (void *) &cmd_firewall_del_ipv4_p_string,
+ (void *) &cmd_firewall_del_ipv4_pipeline_id,
+ (void *) &cmd_firewall_del_ipv4_firewall_string,
+ (void *) &cmd_firewall_del_ipv4_del_string,
+ (void *) &cmd_firewall_del_ipv4_ipv4_string,
+ (void *) &cmd_firewall_del_ipv4_src_ip,
+ (void *) &cmd_firewall_del_ipv4_src_ip_mask,
+ (void *) &cmd_firewall_del_ipv4_dst_ip,
+ (void *) &cmd_firewall_del_ipv4_dst_ip_mask,
+ (void *) &cmd_firewall_del_ipv4_src_port_from,
+ (void *) &cmd_firewall_del_ipv4_src_port_to,
+ (void *) &cmd_firewall_del_ipv4_dst_port_from,
+ (void *) &cmd_firewall_del_ipv4_dst_port_to,
+ (void *) &cmd_firewall_del_ipv4_proto,
+ (void *) &cmd_firewall_del_ipv4_proto_mask,
+ NULL,
+ },
+};
+
+/*
+ * p firewall add default
+ */
+struct cmd_firewall_add_default_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t firewall_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t default_string;
+ uint8_t port_id;
+};
+
+static void
+cmd_firewall_add_default_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_firewall_add_default_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ status = app_pipeline_firewall_add_default_rule(app,
+ params->pipeline_id,
+ params->port_id);
+
+ if(status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
+
+cmdline_parse_token_string_t cmd_firewall_add_default_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_firewall_add_default_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_add_default_firewall_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result,
+ firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_add_default_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, add_string,
+ "add");
+
+cmdline_parse_token_string_t cmd_firewall_add_default_default_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, default_string,
+ "default");
+
+cmdline_parse_token_num_t cmd_firewall_add_default_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, port_id, UINT8);
+
+cmdline_parse_inst_t cmd_firewall_add_default = {
+ .f = cmd_firewall_add_default_parsed,
+ .data = NULL,
+ .help_str = "Firewall default rule add",
+ .tokens = {
+ (void *) &cmd_firewall_add_default_p_string,
+ (void *) &cmd_firewall_add_default_pipeline_id,
+ (void *) &cmd_firewall_add_default_firewall_string,
+ (void *) &cmd_firewall_add_default_add_string,
+ (void *) &cmd_firewall_add_default_default_string,
+ (void *) &cmd_firewall_add_default_port_id,
+ NULL,
+ },
+};
+
+/*
+ * p firewall del default
+ */
+struct cmd_firewall_del_default_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t firewall_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_fixed_string_t default_string;
+};
+
+static void
+cmd_firewall_del_default_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_firewall_del_default_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ status = app_pipeline_firewall_delete_default_rule(app,
+ params->pipeline_id);
- default:
- rte_panic("FW unrecognized message type (%u)\n", req->type);
+ if(status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
+
+cmdline_parse_token_string_t cmd_firewall_del_default_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_firewall_del_default_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_default_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_del_default_firewall_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result,
+ firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_del_default_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, del_string,
+ "del");
+
+cmdline_parse_token_string_t cmd_firewall_del_default_default_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, default_string,
+ "default");
+
+cmdline_parse_inst_t cmd_firewall_del_default = {
+ .f = cmd_firewall_del_default_parsed,
+ .data = NULL,
+ .help_str = "Firewall default rule delete",
+ .tokens = {
+ (void *) &cmd_firewall_del_default_p_string,
+ (void *) &cmd_firewall_del_default_pipeline_id,
+ (void *) &cmd_firewall_del_default_firewall_string,
+ (void *) &cmd_firewall_del_default_del_string,
+ (void *) &cmd_firewall_del_default_default_string,
+ NULL,
+ },
+};
+
+/*
+ * p firewall ls
+ */
+
+struct cmd_firewall_ls_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t firewall_string;
+ cmdline_fixed_string_t ls_string;
+};
- /* Fill in response message */
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
- resp->result = result;
+static void
+cmd_firewall_ls_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_firewall_ls_result *params = parsed_result;
+ struct app_params *app = data;
- /* Send response */
- do {
- result = rte_ring_sp_enqueue(ring_resp, (void *) msg);
- } while (result == -ENOBUFS);
+ app_pipeline_firewall_ls(app, params->pipeline_id);
}
+
+cmdline_parse_token_string_t cmd_firewall_ls_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_firewall_ls_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_ls_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_ls_firewall_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result,
+ firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_ls_ls_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, ls_string,
+ "ls");
+
+cmdline_parse_inst_t cmd_firewall_ls = {
+ .f = cmd_firewall_ls_parsed,
+ .data = NULL,
+ .help_str = "Firewall rule list",
+ .tokens = {
+ (void *) &cmd_firewall_ls_p_string,
+ (void *) &cmd_firewall_ls_pipeline_id,
+ (void *) &cmd_firewall_ls_firewall_string,
+ (void *) &cmd_firewall_ls_ls_string,
+ NULL,
+ },
+};
+
+static cmdline_parse_ctx_t pipeline_cmds[] = {
+ (cmdline_parse_inst_t *) &cmd_firewall_add_ipv4,
+ (cmdline_parse_inst_t *) &cmd_firewall_del_ipv4,
+ (cmdline_parse_inst_t *) &cmd_firewall_add_default,
+ (cmdline_parse_inst_t *) &cmd_firewall_del_default,
+ (cmdline_parse_inst_t *) &cmd_firewall_ls,
+ NULL,
+};
+
+static struct pipeline_fe_ops pipeline_firewall_fe_ops = {
+ .f_init = app_pipeline_firewall_init,
+ .f_free = app_pipeline_firewall_free,
+ .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
new file mode 100644
index 0000000..82e905d
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.h
@@ -0,0 +1,63 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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_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);
+
+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
new file mode 100644
index 0000000..a364d63
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
@@ -0,0 +1,701 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_log.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"
+
+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_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_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 = 4,
+ .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 = 4,
+ .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 = 4,
+ .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) {
+ if (n_rules_present)
+ return -1;
+ n_rules_present = 1;
+
+ p->n_rules = atoi(arg_value);
+ continue;
+ }
+
+ if (strcmp(arg_name, "pkt_type") == 0){
+ if (pkt_type_present)
+ return -1;
+ 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 */
+ return -1;
+ }
+
+ /* other */
+ return -1;
+ }
+
+ 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,
+ .f_action_bulk = 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_track(void *pipeline,
+ __rte_unused uint32_t port_in,
+ uint32_t *port_out)
+{
+ struct pipeline *p = (struct pipeline *) pipeline;
+
+ /* Check input arguments */
+ if ((p == NULL) ||
+ (port_in >= p->n_ports_in) ||
+ (port_out == NULL))
+ return -1;
+
+ if (p->n_ports_in == 1) {
+ *port_out = 0;
+ return 0;
+ }
+
+ return -1;
+}
+
+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;
+}
+
+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,
+ .f_track = pipeline_firewall_track,
+};
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.h b/examples/ip_pipeline/pipeline/pipeline_firewall_be.h
new file mode 100644
index 0000000..8e1fd69
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.h
@@ -0,0 +1,138 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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_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 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
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 10/11] ip_pipeline: added new implementation of routing pipeline
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
` (8 preceding siblings ...)
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 09/11] ip_pipeline: added new implementation of firewall pipeline Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 11/11] ip_pipeline: added new implementation of flow classification pipeline Maciej Gajdzica
2015-06-25 12:19 ` [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Dumitrescu, Cristian
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
From: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Routing pipeline implementation is split to two files.
pipeline_routing.c file handles front-end functions (cli commands
parsing) pipeline_routing_ops.c contains implementation of functions
done by pipeline (back-end).
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
---
examples/ip_pipeline/Makefile | 2 +
examples/ip_pipeline/config/rt.cfg | 13 +
examples/ip_pipeline/config/rt.sh | 18 +
examples/ip_pipeline/init.c | 2 +
examples/ip_pipeline/pipeline/pipeline_routing.c | 1777 ++++++++++++++++----
examples/ip_pipeline/pipeline/pipeline_routing.h | 99 ++
.../ip_pipeline/pipeline/pipeline_routing_be.c | 836 +++++++++
.../ip_pipeline/pipeline/pipeline_routing_be.h | 230 +++
8 files changed, 2620 insertions(+), 357 deletions(-)
create mode 100644 examples/ip_pipeline/config/rt.cfg
create mode 100644 examples/ip_pipeline/config/rt.sh
create mode 100644 examples/ip_pipeline/pipeline/pipeline_routing.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_routing_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_routing_be.h
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index 382fee6..a2881a6 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -64,6 +64,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough_be.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall_be.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing.c
CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline
CFLAGS += -O3
diff --git a/examples/ip_pipeline/config/rt.cfg b/examples/ip_pipeline/config/rt.cfg
new file mode 100644
index 0000000..e2c614f
--- /dev/null
+++ b/examples/ip_pipeline/config/rt.cfg
@@ -0,0 +1,13 @@
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = ROUTING
+core = s0c1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0
+n_routes = 4096
+n_arp_entries = 1024
+ip_da_offset = 158; ip_da_offset = headroom (128) + ethernet header (14) + ip header offset (16)
+arp_key_offset = 128; arp_key_offset = headroom (128)
diff --git a/examples/ip_pipeline/config/rt.sh b/examples/ip_pipeline/config/rt.sh
new file mode 100644
index 0000000..3cf2877
--- /dev/null
+++ b/examples/ip_pipeline/config/rt.sh
@@ -0,0 +1,18 @@
+#run config/routing.sh
+
+p 1 ping
+
+p 1 arp add default 2
+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 route add default 3
+p 1 route add 0.0.0.0 10 0 10.0.0.1
+p 1 route add 0.64.0.0 10 1 11.0.0.1
+p 1 route add 0.128.0.0 10 2 12.0.0.1
+p 1 route add 0.192.0.0 10 3 13.0.0.1
+
+p 1 route ls
+p 1 arp ls
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index 3583672..840bc60 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -47,6 +47,7 @@
#include "pipeline_master.h"
#include "pipeline_passthrough.h"
#include "pipeline_firewall.h"
+#include "pipeline_routing.h"
#define APP_NAME_SIZE 32
@@ -1193,6 +1194,7 @@ int app_init(struct app_params *app)
app_pipeline_type_register(app, &pipeline_master);
app_pipeline_type_register(app, &pipeline_passthrough);
app_pipeline_type_register(app, &pipeline_firewall);
+ app_pipeline_type_register(app, &pipeline_routing);
app_init_pipelines(app);
app_init_threads(app);
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.c b/examples/ip_pipeline/pipeline/pipeline_routing.c
index b1ce624..3a42bc9 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing.c
+++ b/examples/ip_pipeline/pipeline/pipeline_routing.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,444 +31,1507 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_ipaddr.h>
+#include <cmdline_parse_etheraddr.h>
-#include <rte_malloc.h>
-#include <rte_log.h>
-#include <rte_ethdev.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-#include <rte_byteorder.h>
+#include "app.h"
+#include "pipeline_common_fe.h"
+#include "pipeline_routing.h"
-#include <rte_port_ring.h>
-#include <rte_table_lpm.h>
-#include <rte_table_hash.h>
-#include <rte_pipeline.h>
+struct app_pipeline_routing_route {
+ struct pipeline_routing_route_key key;
+ struct app_pipeline_routing_route_params params;
+ void *entry_ptr;
-#include "main.h"
+ TAILQ_ENTRY(app_pipeline_routing_route) node;
+};
-#include <unistd.h>
+struct app_pipeline_routing_arp_entry {
+ struct pipeline_routing_arp_key key;
+ struct ether_addr macaddr;
+ void *entry_ptr;
-struct app_routing_table_entry {
- struct rte_pipeline_table_entry head;
- uint32_t nh_ip;
- uint32_t nh_iface;
+ TAILQ_ENTRY(app_pipeline_routing_arp_entry) node;
};
-struct app_arp_table_entry {
- struct rte_pipeline_table_entry head;
- struct ether_addr nh_arp;
+struct pipeline_routing {
+ /* Parameters */
+ uint32_t n_ports_in;
+ uint32_t n_ports_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 inline void
-app_routing_table_write_metadata(
- struct rte_mbuf *pkt,
- struct app_routing_table_entry *entry)
+static void *
+pipeline_routing_init(struct pipeline_params *params,
+ __rte_unused void *arg)
{
- struct app_pkt_metadata *c =
- (struct app_pkt_metadata *) RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
+ struct pipeline_routing *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 pipeline_routing));
+ p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+ if (p == NULL)
+ return NULL;
- c->arp_key.nh_ip = entry->nh_ip;
- c->arp_key.nh_iface = entry->nh_iface;
+ /* Initialization */
+ p->n_ports_in = params->n_ports_in;
+ p->n_ports_out = params->n_ports_out;
+
+ TAILQ_INIT(&p->routes);
+ p->n_routes = 0;
+
+ TAILQ_INIT(&p->arp_entries);
+ p->n_arp_entries = 0;
+
+ return p;
}
static int
-app_routing_table_ah(
- struct rte_mbuf **pkts,
- uint64_t *pkts_mask,
- struct rte_pipeline_table_entry **entries,
- __attribute__((unused)) void *arg)
+app_pipeline_routing_free(void *pipeline)
{
- uint64_t pkts_in_mask = *pkts_mask;
+ struct pipeline_routing *p = pipeline;
- if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) {
- uint64_t n_pkts = __builtin_popcountll(pkts_in_mask);
- uint32_t i;
+ /* Check input arguments */
+ if (p == NULL)
+ return -1;
- for (i = 0; i < n_pkts; i++) {
- struct rte_mbuf *m = pkts[i];
- struct app_routing_table_entry *a =
- (struct app_routing_table_entry *) entries[i];
+ /* Free resources */
+ while (!TAILQ_EMPTY(&p->routes)) {
+ struct app_pipeline_routing_route *route;
- app_routing_table_write_metadata(m, a);
+ 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;
}
- } else
- for ( ; pkts_in_mask; ) {
- struct rte_mbuf *m;
- struct app_routing_table_entry *a;
- uint64_t pkt_mask;
- uint32_t packet_index;
-
- packet_index = __builtin_ctzll(pkts_in_mask);
- pkt_mask = 1LLU << packet_index;
- pkts_in_mask &= ~pkt_mask;
-
- m = pkts[packet_index];
- a = (struct app_routing_table_entry *)
- entries[packet_index];
- app_routing_table_write_metadata(m, a);
+ }
+
+ 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 = %u.%u.%u.%u/%u => "
+ "(Port = %u, Next Hop IP = %u.%u.%u.%u)\n",
+ (key->ip >> 24) & 0xFF,
+ (key->ip >> 16) & 0xFF,
+ (key->ip >> 8) & 0xFF,
+ key->ip & 0xFF,
+
+ key->depth,
+ route->params.port_id,
+
+ (route->params.ip >> 24) & 0xFF,
+ (route->params.ip >> 16) & 0xFF,
+ (route->params.ip >> 8) & 0xFF,
+ route->params.ip & 0xFF);
+ }
+}
+
+static void
+print_arp_entry(const struct app_pipeline_routing_arp_entry *entry)
+{
+ printf("(Port = %u, IP = %u.%u.%u.%u) => "
+ "HWaddress = %02x:%02x:%02x:%02x:%02x:%02x\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);
+ if (p == NULL)
+ return -EINVAL;
+
+ TAILQ_FOREACH(it, &p->routes, node)
+ print_route(it);
+
+ if (p->default_route_present)
+ printf("Default route: port %u (entry ptr = %p)\n",
+ p->default_route_port_id,
+ p->default_route_entry_ptr);
+ else
+ printf("Default: DROP\n");
return 0;
}
-static inline void
-app_arp_table_write_metadata(
- struct rte_mbuf *pkt,
- struct app_arp_table_entry *entry)
+int
+app_pipeline_routing_add_route(struct app_params *app,
+ uint32_t pipeline_id,
+ struct pipeline_routing_route_key *key,
+ struct app_pipeline_routing_route_params *route_params)
{
- struct app_pkt_metadata *c =
- (struct app_pkt_metadata *) RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
- ether_addr_copy(&entry->nh_arp, &c->nh_arp);
+ 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) ||
+ (route_params == NULL))
+ return -1;
+
+ p = app_pipeline_data_fe(app, pipeline_id);
+ 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 = (~0) << (32 - depth);
+ key->key.ipv4.ip &= netmask;
+
+ /* route params */
+ if (route_params->port_id >= p->n_ports_out)
+ 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));
+ req->flags = route_params->flags;
+ req->port_id = route_params->port_id;
+ req->ip = route_params->ip;
+
+ 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->params, route_params, sizeof(*route_params));
+ entry->entry_ptr = rsp->entry_ptr;
+
+ /* Commit entry */
+ if (new_entry) {
+ TAILQ_INSERT_TAIL(&p->routes, entry, node);
+ p->n_routes++;
+ }
+
+ print_route(entry);
+
+ /* 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);
+ 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 = (~0) << (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);
+ 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);
+ 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_arp_table_ah(
- struct rte_mbuf **pkts,
- uint64_t *pkts_mask,
- struct rte_pipeline_table_entry **entries,
- __attribute__((unused)) void *arg)
+app_pipeline_routing_arp_ls(struct app_params *app, uint32_t pipeline_id)
{
- uint64_t pkts_in_mask = *pkts_mask;
+ struct pipeline_routing *p;
+ struct app_pipeline_routing_arp_entry *it;
- if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) {
- uint64_t n_pkts = __builtin_popcountll(pkts_in_mask);
- uint32_t i;
+ p = app_pipeline_data_fe(app, pipeline_id);
+ if (p == NULL)
+ return -EINVAL;
- for (i = 0; i < n_pkts; i++) {
- struct rte_mbuf *m = pkts[i];
- struct app_arp_table_entry *a =
- (struct app_arp_table_entry *) entries[i];
+ TAILQ_FOREACH(it, &p->arp_entries, node)
+ print_arp_entry(it);
- app_arp_table_write_metadata(m, a);
+ if (p->default_arp_entry_present)
+ printf("Default entry: port %u (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);
+ 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;
}
- } else {
- for ( ; pkts_in_mask; ) {
- struct rte_mbuf *m;
- struct app_arp_table_entry *a;
- uint64_t pkt_mask;
- uint32_t packet_index;
-
- packet_index = __builtin_ctzll(pkts_in_mask);
- pkt_mask = 1LLU << packet_index;
- pkts_in_mask &= ~pkt_mask;
-
- m = pkts[packet_index];
- a = (struct app_arp_table_entry *)
- entries[packet_index];
- app_arp_table_write_metadata(m, a);
+ 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++;
+ }
+
+ print_arp_entry(entry);
+
+ /* 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);
+ 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);
+ 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;
}
-static uint64_t app_arp_table_hash(
- void *key,
- __attribute__((unused)) uint32_t key_size,
- __attribute__((unused)) uint64_t seed)
+int
+app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
+ uint32_t pipeline_id)
{
- uint32_t *k = (uint32_t *) key;
+ 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);
+ 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 k[1];
+ return 0;
}
-struct app_core_routing_message_handle_params {
- struct rte_ring *ring_req;
- struct rte_ring *ring_resp;
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t routing_table_id;
- uint32_t arp_table_id;
+/*
+ * route add
+ */
+
+struct cmd_route_add_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t route_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_ipaddr_t ip;
+ uint32_t depth;
+ uint32_t port;
+ cmdline_ipaddr_t nh_ip;
};
static void
-app_message_handle(struct app_core_routing_message_handle_params *params);
+cmd_route_add_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_route_add_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_routing_route_key key;
+ struct app_pipeline_routing_route_params rt_params;
+ int status;
-void
-app_main_loop_pipeline_routing(void) {
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
+ /* Create route */
+ key.type = PIPELINE_ROUTING_ROUTE_IPV4;
+ key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr);
+ key.key.ipv4.depth = params->depth;
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t routing_table_id, arp_table_id;
- uint32_t i;
+ rt_params.flags = 0; /* remote route */
+ rt_params.port_id = params->port;
+ rt_params.ip = rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
- struct app_core_routing_message_handle_params mh_params;
+ status = app_pipeline_routing_add_route(app, params->p, &key, &rt_params);
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_RT))
- rte_panic("Core %u misconfiguration\n", core_id);
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
- RTE_LOG(INFO, USER1, "Core %u is doing routing\n", core_id);
+static cmdline_parse_token_string_t cmd_route_add_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_route_add_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_route_add_route_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, route_string,
+ "route");
+
+static cmdline_parse_token_string_t cmd_route_add_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, add_string,
+ "add");
+
+static cmdline_parse_token_ipaddr_t cmd_route_add_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_route_add_result, ip);
+
+static cmdline_parse_token_num_t cmd_route_add_depth =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, depth, UINT32);
+
+static cmdline_parse_token_num_t cmd_route_add_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, port, UINT32);
+
+static cmdline_parse_token_ipaddr_t cmd_route_add_nh_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_route_add_result, nh_ip);
+
+static cmdline_parse_inst_t cmd_route_add = {
+ .f = cmd_route_add_parsed,
+ .data = NULL,
+ .help_str = "Route add",
+ .tokens = {
+ (void *)&cmd_route_add_p_string,
+ (void *)&cmd_route_add_p,
+ (void *)&cmd_route_add_route_string,
+ (void *)&cmd_route_add_add_string,
+ (void *)&cmd_route_add_ip,
+ (void *)&cmd_route_add_depth,
+ (void *)&cmd_route_add_port,
+ (void *)&cmd_route_add_nh_ip,
+ NULL,
+ },
+};
- /* Pipeline configuration */
- p = rte_pipeline_create(&pipeline_params);
- if (p == NULL)
- rte_panic("Unable to configure the pipeline\n");
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i]))
- rte_panic("Unable to configure input port for "
- "ring %d\n", i);
- }
-
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i]))
- rte_panic("Unable to configure output port for "
- "ring %d\n", i);
- }
-
- /* Routing table configuration */
- {
- struct rte_table_lpm_params table_lpm_params = {
- .n_rules = app.max_routing_rules,
- .entry_unique_size =
- sizeof(struct app_routing_table_entry),
- .offset = __builtin_offsetof(struct app_pkt_metadata,
- flow_key.ip_dst),
- };
-
- struct rte_pipeline_table_params table_params = {
- .ops = &rte_table_lpm_ops,
- .arg_create = &table_lpm_params,
- .f_action_hit = app_routing_table_ah,
- .f_action_miss = NULL,
- .arg_ah = NULL,
- .action_data_size =
- sizeof(struct app_routing_table_entry) -
- sizeof(struct rte_pipeline_table_entry),
- };
-
- if (rte_pipeline_table_create(p, &table_params,
- &routing_table_id))
- rte_panic("Unable to configure the LPM table\n");
- }
-
- /* ARP table configuration */
- {
- struct rte_table_hash_key8_lru_params table_arp_params = {
- .n_entries = app.max_arp_rules,
- .f_hash = app_arp_table_hash,
- .seed = 0,
- .signature_offset = 0, /* Unused */
- .key_offset = __builtin_offsetof(
- struct app_pkt_metadata, arp_key),
- };
-
- struct rte_pipeline_table_params table_params = {
- .ops = &rte_table_hash_key8_lru_dosig_ops,
- .arg_create = &table_arp_params,
- .f_action_hit = app_arp_table_ah,
- .f_action_miss = NULL,
- .arg_ah = NULL,
- .action_data_size = sizeof(struct app_arp_table_entry) -
- sizeof(struct rte_pipeline_table_entry),
- };
-
- if (rte_pipeline_table_create(p, &table_params, &arp_table_id))
- rte_panic("Unable to configure the ARP table\n");
- }
-
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++) {
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- routing_table_id))
- rte_panic("Unable to connect input port %u to "
- "table %u\n", port_in_id[i], routing_table_id);
- }
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("Pipeline consistency check failed\n");
-
- /* Message handling */
- mh_params.ring_req =
- app_get_ring_req(app_get_first_core_id(APP_CORE_RT));
- mh_params.ring_resp =
- app_get_ring_resp(app_get_first_core_id(APP_CORE_RT));
- mh_params.p = p;
- mh_params.port_out_id = port_out_id;
- mh_params.routing_table_id = routing_table_id;
- mh_params.arp_table_id = arp_table_id;
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0) {
- rte_pipeline_flush(p);
- app_message_handle(&mh_params);
- }
+/*
+ * route del
+ */
+
+struct cmd_route_del_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t route_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_ipaddr_t ip;
+ uint32_t depth;
+};
+
+static void
+cmd_route_del_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_route_del_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_routing_route_key key;
+
+ int status;
+
+ /* Create route */
+ key.type = PIPELINE_ROUTING_ROUTE_IPV4;
+ key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr);
+ key.key.ipv4.depth = params->depth;
+
+ status = app_pipeline_routing_delete_route(app, params->p, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
}
}
-void
-app_message_handle(struct app_core_routing_message_handle_params *params)
+static cmdline_parse_token_string_t cmd_route_del_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_route_del_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_route_del_route_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, route_string,
+ "route");
+
+static cmdline_parse_token_string_t cmd_route_del_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, del_string,
+ "del");
+
+static cmdline_parse_token_ipaddr_t cmd_route_del_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_route_del_result, ip);
+
+static cmdline_parse_token_num_t cmd_route_del_depth =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, depth, UINT32);
+
+static cmdline_parse_inst_t cmd_route_del = {
+ .f = cmd_route_del_parsed,
+ .data = NULL,
+ .help_str = "Route delete",
+ .tokens = {
+ (void *)&cmd_route_del_p_string,
+ (void *)&cmd_route_del_p,
+ (void *)&cmd_route_del_route_string,
+ (void *)&cmd_route_del_del_string,
+ (void *)&cmd_route_del_ip,
+ (void *)&cmd_route_del_depth,
+ NULL,
+ },
+};
+
+/*
+ * route add default
+ */
+
+struct cmd_route_add_default_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t route_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t default_string;
+ uint32_t port;
+};
+
+static void
+cmd_route_add_default_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
{
- struct rte_ring *ring_req = params->ring_req;
- struct rte_ring *ring_resp;
- void *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t routing_table_id, arp_table_id;
- int result;
-
- /* Read request message */
- result = rte_ring_sc_dequeue(ring_req, &msg);
- if (result != 0)
+ struct cmd_route_add_default_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ status = app_pipeline_routing_add_default_route(app, params->p,
+ params->port);
+
+ if (status != 0) {
+ printf("Command failed\n");
return;
+ }
+}
- ring_resp = params->ring_resp;
- p = params->p;
- port_out_id = params->port_out_id;
- routing_table_id = params->routing_table_id;
- arp_table_id = params->arp_table_id;
-
- /* Handle request */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- switch (req->type) {
- case APP_MSG_REQ_PING:
- {
- result = 0;
- break;
+static cmdline_parse_token_string_t cmd_route_add_default_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_route_add_default_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_add_default_result, p, UINT32);
+
+cmdline_parse_token_string_t cmd_route_add_default_route_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, route_string,
+ "route");
+
+cmdline_parse_token_string_t cmd_route_add_default_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, add_string,
+ "add");
+
+cmdline_parse_token_string_t cmd_route_add_default_default_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result,
+ default_string, "default");
+
+cmdline_parse_token_num_t cmd_route_add_default_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_add_default_result, port, UINT32);
+
+cmdline_parse_inst_t cmd_route_add_default = {
+ .f = cmd_route_add_default_parsed,
+ .data = NULL,
+ .help_str = "Route default set",
+ .tokens = {
+ (void *)&cmd_route_add_default_p_string,
+ (void *)&cmd_route_add_default_p,
+ (void *)&cmd_route_add_default_route_string,
+ (void *)&cmd_route_add_default_add_string,
+ (void *)&cmd_route_add_default_default_string,
+ (void *)&cmd_route_add_default_port,
+ NULL,
+ },
+};
+
+/*
+ * route del default
+ */
+
+struct cmd_route_del_default_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t route_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_fixed_string_t default_string;
+};
+
+static void
+cmd_route_del_default_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_route_del_default_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ status = app_pipeline_routing_delete_default_route(app, params->p);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
- case APP_MSG_REQ_RT_ADD:
- {
- struct app_routing_table_entry entry = {
- .head = {
- .action = RTE_PIPELINE_ACTION_TABLE,
- {.table_id = arp_table_id},
- },
- .nh_ip = req->routing_add.nh_ip,
- .nh_iface = port_out_id[req->routing_add.port],
- };
+static cmdline_parse_token_string_t cmd_route_del_default_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_route_del_default_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_del_default_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_route_del_default_route_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, route_string,
+ "route");
+
+static cmdline_parse_token_string_t cmd_route_del_default_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, del_string,
+ "del");
+
+static cmdline_parse_token_string_t cmd_route_del_default_default_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result,
+ default_string, "default");
+
+
+static cmdline_parse_inst_t cmd_route_del_default = {
+ .f = cmd_route_del_default_parsed,
+ .data = NULL,
+ .help_str = "Route default clear",
+ .tokens = {
+ (void *)&cmd_route_del_default_p_string,
+ (void *)&cmd_route_del_default_p,
+ (void *)&cmd_route_del_default_route_string,
+ (void *)&cmd_route_del_default_del_string,
+ (void *)&cmd_route_del_default_default_string,
+ NULL,
+ },
+};
- struct rte_table_lpm_key key = {
- .ip = req->routing_add.ip,
- .depth = req->routing_add.depth,
- };
+/*
+ * route ls
+ */
- struct rte_pipeline_table_entry *entry_ptr;
+struct cmd_route_ls_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t route_string;
+ cmdline_fixed_string_t ls_string;
+};
- int key_found;
+static void
+cmd_route_ls_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_route_ls_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
- result = rte_pipeline_table_entry_add(p, routing_table_id, &key,
- (struct rte_pipeline_table_entry *) &entry, &key_found,
- &entry_ptr);
- break;
+ status = app_pipeline_routing_route_ls(app, params->p);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
+
+static cmdline_parse_token_string_t cmd_route_ls_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_ls_result, p_string, "p");
+
+static cmdline_parse_token_num_t cmd_route_ls_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_ls_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_route_ls_route_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_ls_result,
+ route_string, "route");
+
+static cmdline_parse_token_string_t cmd_route_ls_ls_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_ls_result, ls_string,
+ "ls");
+
+static cmdline_parse_inst_t cmd_route_ls = {
+ .f = cmd_route_ls_parsed,
+ .data = NULL,
+ .help_str = "Route list",
+ .tokens = {
+ (void *)&cmd_route_ls_p_string,
+ (void *)&cmd_route_ls_p,
+ (void *)&cmd_route_ls_route_string,
+ (void *)&cmd_route_ls_ls_string,
+ NULL,
+ },
+};
- case APP_MSG_REQ_RT_DEL:
- {
- struct rte_table_lpm_key key = {
- .ip = req->routing_del.ip,
- .depth = req->routing_del.depth,
- };
+/*
+ * arp add
+ */
- int key_found;
+struct cmd_arp_add_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t arp_string;
+ cmdline_fixed_string_t add_string;
+ uint32_t port_id;
+ cmdline_ipaddr_t ip;
+ struct ether_addr macaddr;
- result = rte_pipeline_table_entry_delete(p, routing_table_id,
- &key, &key_found, NULL);
- break;
+};
+
+static void
+cmd_arp_add_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_arp_add_result *params = parsed_result;
+ struct app_params *app = data;
+
+ struct pipeline_routing_arp_key key;
+ int status;
+
+ key.type = PIPELINE_ROUTING_ARP_IPV4;
+ key.key.ipv4.port_id = params->port_id;
+ key.key.ipv4.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr);
+
+ status = app_pipeline_routing_add_arp_entry(app,
+ params->p,
+ &key,
+ ¶ms->macaddr);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
- case APP_MSG_REQ_ARP_ADD:
- {
+static cmdline_parse_token_string_t cmd_arp_add_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_arp_add_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_arp_add_arp_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, arp_string, "arp");
+
+static cmdline_parse_token_string_t cmd_arp_add_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, add_string, "add");
+
+static cmdline_parse_token_num_t cmd_arp_add_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, port_id, UINT32);
+
+static cmdline_parse_token_ipaddr_t cmd_arp_add_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_arp_add_result, ip);
+
+static cmdline_parse_token_etheraddr_t cmd_arp_add_macaddr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_arp_add_result, macaddr);
+
+static cmdline_parse_inst_t cmd_arp_add = {
+ .f = cmd_arp_add_parsed,
+ .data = NULL,
+ .help_str = "ARP add",
+ .tokens = {
+ (void *)&cmd_arp_add_p_string,
+ (void *)&cmd_arp_add_p,
+ (void *)&cmd_arp_add_arp_string,
+ (void *)&cmd_arp_add_add_string,
+ (void *)&cmd_arp_add_port_id,
+ (void *)&cmd_arp_add_ip,
+ (void *)&cmd_arp_add_macaddr,
+ NULL,
+ },
+};
- struct app_arp_table_entry entry = {
- .head = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id =
- port_out_id[req->arp_add.out_iface]},
- },
- .nh_arp = req->arp_add.nh_arp,
- };
+/*
+ * arp del
+ */
- struct app_arp_key arp_key = {
- .nh_ip = req->arp_add.nh_ip,
- .nh_iface = port_out_id[req->arp_add.out_iface],
- };
+struct cmd_arp_del_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t arp_string;
+ cmdline_fixed_string_t del_string;
+ uint32_t port_id;
+ cmdline_ipaddr_t ip;
+};
- struct rte_pipeline_table_entry *entry_ptr;
+static void
+cmd_arp_del_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_arp_del_result *params = parsed_result;
+ struct app_params *app = data;
- int key_found;
+ struct pipeline_routing_arp_key key;
+ int status;
- result = rte_pipeline_table_entry_add(p, arp_table_id, &arp_key,
- (struct rte_pipeline_table_entry *) &entry, &key_found,
- &entry_ptr);
- break;
+ key.type = PIPELINE_ROUTING_ARP_IPV4;
+ key.key.ipv4.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr);
+ key.key.ipv4.port_id = params->port_id;
+
+ status = app_pipeline_routing_delete_arp_entry(app, params->p, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
- case APP_MSG_REQ_ARP_DEL:
- {
- struct app_arp_key arp_key = {
- .nh_ip = req->arp_del.nh_ip,
- .nh_iface = port_out_id[req->arp_del.out_iface],
- };
+static cmdline_parse_token_string_t cmd_arp_del_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_arp_del_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_arp_del_arp_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "arp");
+
+static cmdline_parse_token_string_t cmd_arp_del_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, del_string, "del");
+
+static cmdline_parse_token_num_t cmd_arp_del_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, port_id, UINT32);
+
+static cmdline_parse_token_ipaddr_t cmd_arp_del_ip =
+ TOKEN_IPV4_INITIALIZER(struct cmd_arp_del_result, ip);
+
+static cmdline_parse_inst_t cmd_arp_del = {
+ .f = cmd_arp_del_parsed,
+ .data = NULL,
+ .help_str = "ARP delete",
+ .tokens = {
+ (void *)&cmd_arp_del_p_string,
+ (void *)&cmd_arp_del_p,
+ (void *)&cmd_arp_del_arp_string,
+ (void *)&cmd_arp_del_del_string,
+ (void *)&cmd_arp_del_port_id,
+ (void *)&cmd_arp_del_ip,
+ NULL,
+ },
+};
- int key_found;
+/*
+ * arp add default
+ */
- result = rte_pipeline_table_entry_delete(p, arp_table_id,
- &arp_key, &key_found, NULL);
- break;
+struct cmd_arp_add_default_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t arp_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t default_string;
+ uint32_t port_id;
+};
+
+static void
+cmd_arp_add_default_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_arp_add_default_result *params = parsed_result;
+ struct app_params *app = data;
+
+ int status;
+
+ status = app_pipeline_routing_add_default_arp_entry(app,
+ params->p,
+ params->port_id);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
+
+static cmdline_parse_token_string_t cmd_arp_add_default_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_arp_add_default_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_add_default_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_arp_add_default_arp_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, arp_string,
+ "arp");
+
+static cmdline_parse_token_string_t cmd_arp_add_default_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, add_string,
+ "add");
+
+static cmdline_parse_token_string_t cmd_arp_add_default_default_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, default_string,
+ "default");
+
+static cmdline_parse_token_num_t cmd_arp_add_default_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_add_default_result, port_id,
+ UINT32);
+
+static cmdline_parse_inst_t cmd_arp_add_default = {
+ .f = cmd_arp_add_default_parsed,
+ .data = NULL,
+ .help_str = "ARP add default",
+ .tokens = {
+ (void *)&cmd_arp_add_default_p_string,
+ (void *)&cmd_arp_add_default_p,
+ (void *)&cmd_arp_add_default_arp_string,
+ (void *)&cmd_arp_add_default_add_string,
+ (void *)&cmd_arp_add_default_default_string,
+ (void *)&cmd_arp_add_default_port_id,
+ NULL,
+ },
+};
- default:
- rte_panic("RT Unrecognized message type (%u)\n", req->type);
+/*
+ * arp del default
+ */
+
+struct cmd_arp_del_default_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t arp_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_fixed_string_t default_string;
+};
+
+static void
+cmd_arp_del_default_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_arp_del_default_result *params = parsed_result;
+ struct app_params *app = data;
+
+ int status;
+
+ status = app_pipeline_routing_delete_default_arp_entry(app, params->p);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
}
+}
+
+static cmdline_parse_token_string_t cmd_arp_del_default_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_arp_del_default_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_del_default_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_arp_del_default_arp_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, arp_string,
+ "arp");
+
+static cmdline_parse_token_string_t cmd_arp_del_default_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, del_string,
+ "del");
+
+static cmdline_parse_token_string_t cmd_arp_del_default_default_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, default_string,
+ "default");
+
+static cmdline_parse_inst_t cmd_arp_del_default = {
+ .f = cmd_arp_del_default_parsed,
+ .data = NULL,
+ .help_str = "ARP delete default",
+ .tokens = {
+ (void *)&cmd_arp_del_default_p_string,
+ (void *)&cmd_arp_del_default_p,
+ (void *)&cmd_arp_del_default_arp_string,
+ (void *)&cmd_arp_del_default_del_string,
+ (void *)&cmd_arp_del_default_default_string,
+ NULL,
+ },
+};
+
+/*
+ * arp ls
+ */
+
+struct cmd_arp_ls_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t arp_string;
+ cmdline_fixed_string_t ls_string;
+};
+
+static void
+cmd_arp_ls_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_arp_ls_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_routing *p;
- /* Fill in response message */
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- resp->result = result;
+ p = app_pipeline_data_fe(app, params->p);
+ if (p == NULL)
+ return;
- /* Send response */
- do {
- result = rte_ring_sp_enqueue(ring_resp, msg);
- } while (result == -ENOBUFS);
+ app_pipeline_routing_arp_ls(app, params->p);
}
+
+static cmdline_parse_token_string_t cmd_arp_ls_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_arp_ls_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_ls_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_arp_ls_arp_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, arp_string,
+ "arp");
+
+static cmdline_parse_token_string_t cmd_arp_ls_ls_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, ls_string,
+ "ls");
+
+static cmdline_parse_inst_t cmd_arp_ls = {
+ .f = cmd_arp_ls_parsed,
+ .data = NULL,
+ .help_str = "ARP list",
+ .tokens = {
+ (void *)&cmd_arp_ls_p_string,
+ (void *)&cmd_arp_ls_p,
+ (void *)&cmd_arp_ls_arp_string,
+ (void *)&cmd_arp_ls_ls_string,
+ NULL,
+ },
+};
+
+static cmdline_parse_ctx_t pipeline_cmds[] = {
+ (cmdline_parse_inst_t *)&cmd_route_add,
+ (cmdline_parse_inst_t *)&cmd_route_del,
+ (cmdline_parse_inst_t *)&cmd_route_add_default,
+ (cmdline_parse_inst_t *)&cmd_route_del_default,
+ (cmdline_parse_inst_t *)&cmd_route_ls,
+ (cmdline_parse_inst_t *)&cmd_arp_add,
+ (cmdline_parse_inst_t *)&cmd_arp_del,
+ (cmdline_parse_inst_t *)&cmd_arp_add_default,
+ (cmdline_parse_inst_t *)&cmd_arp_del_default,
+ (cmdline_parse_inst_t *)&cmd_arp_ls,
+ NULL,
+};
+
+static struct pipeline_fe_ops pipeline_routing_fe_ops = {
+ .f_init = pipeline_routing_init,
+ .f_free = app_pipeline_routing_free,
+ .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
new file mode 100644
index 0000000..851cddd
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_routing.h
@@ -0,0 +1,99 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#ifndef __INCLUDE_PIPELINE_ROUTING_H__
+#define __INCLUDE_PIPELINE_ROUTING_H__
+
+#include "pipeline.h"
+#include "pipeline_routing_be.h"
+
+/*
+ * Route
+ */
+
+struct app_pipeline_routing_route_params {
+ enum pipeline_routing_route_flags flags;
+ uint32_t port_id; /* Output port ID */
+ uint32_t ip; /* IP address for the next hop (only for remote routes) */
+};
+
+int
+app_pipeline_routing_add_route(struct app_params *app,
+ uint32_t pipeline_id,
+ struct pipeline_routing_route_key *key,
+ struct app_pipeline_routing_route_params *route_params);
+
+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);
+
+/*
+ * 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
new file mode 100644
index 0000000..44c106a
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.c
@@ -0,0 +1,836 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_log.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 "hash_func.h"
+
+struct pipeline_routing {
+ struct pipeline p;
+ pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS];
+
+ uint32_t n_routes;
+ uint32_t n_arp_entries;
+ uint32_t ip_da_offset;
+ uint32_t arp_key_offset;
+} __rte_cache_aligned;
+
+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 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,
+};
+
+/*
+ * Routing table
+ */
+struct routing_table_entry {
+ struct rte_pipeline_table_entry head;
+ enum pipeline_routing_route_flags flags;
+ uint32_t port_id; /* Output port ID */
+ uint32_t ip; /* IP address for the next hop (only valid for remote routes) */
+};
+
+static inline void
+pkt_work_routing(
+ struct rte_mbuf *pkt,
+ struct rte_pipeline_table_entry *table_entry,
+ void *arg)
+{
+ struct routing_table_entry *entry =
+ (struct routing_table_entry *) table_entry;
+ struct pipeline_routing *p_rt = arg;
+
+ struct pipeline_routing_arp_key_ipv4 *arp_key =
+ (struct pipeline_routing_arp_key_ipv4 *) RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->arp_key_offset);
+ uint32_t ip = RTE_MBUF_METADATA_UINT32(pkt, p_rt->ip_da_offset);
+
+ arp_key->port_id = entry->port_id;
+ arp_key->ip = entry->ip;
+ if (entry->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
+ arp_key->ip = ip;
+}
+
+static inline void
+pkt4_work_routing(
+ struct rte_mbuf **pkts,
+ struct rte_pipeline_table_entry **table_entries,
+ void *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 pipeline_routing *p_rt = arg;
+
+ struct pipeline_routing_arp_key_ipv4 *arp_key0 =
+ (struct pipeline_routing_arp_key_ipv4 *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkts[0], p_rt->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->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->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->arp_key_offset);
+
+ uint32_t ip0 = RTE_MBUF_METADATA_UINT32(pkts[0], p_rt->ip_da_offset);
+ uint32_t ip1 = RTE_MBUF_METADATA_UINT32(pkts[1], p_rt->ip_da_offset);
+ uint32_t ip2 = RTE_MBUF_METADATA_UINT32(pkts[2], p_rt->ip_da_offset);
+ uint32_t ip3 = RTE_MBUF_METADATA_UINT32(pkts[3], p_rt->ip_da_offset);
+
+ arp_key0->port_id = entry0->port_id;
+ arp_key1->port_id = entry1->port_id;
+ arp_key2->port_id = entry2->port_id;
+ arp_key3->port_id = entry3->port_id;
+
+ arp_key0->ip = entry0->ip;
+ if (entry0->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
+ arp_key0->ip = ip0;
+
+ arp_key1->ip = entry1->ip;
+ if (entry1->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
+ arp_key1->ip = ip1;
+
+ arp_key2->ip = entry2->ip;
+ if (entry2->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
+ arp_key2->ip = ip2;
+
+ arp_key3->ip = entry3->ip;
+ if (entry3->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
+ arp_key3->ip = ip3;
+}
+
+PIPELINE_TABLE_AH_HIT(routing_table_ah_hit, pkt_work_routing, pkt4_work_routing);
+
+/*
+ * ARP table
+ */
+struct arp_table_entry {
+ struct rte_pipeline_table_entry head;
+ uint64_t macaddr;
+};
+
+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: pkt buffer - mbuf */
+ uint8_t *raw = rte_pktmbuf_mtod(pkt, uint8_t *);
+
+ /* Read: table entry */
+ uint64_t mac_addr_dst = entry->macaddr;
+ uint64_t mac_addr_src = 0;
+
+ /* Compute: Ethernet header */
+ uint64_t slab0 = mac_addr_dst | (mac_addr_src << 48);
+ uint32_t slab1 = mac_addr_src >> 16;
+
+ /* Write: pkt buffer - pkt headers */
+ *((uint64_t *) raw) = slab0;
+ *((uint32_t *) (raw + 8)) = slab1;
+}
+
+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: pkt buffer - mbuf */
+ uint8_t *raw0 = rte_pktmbuf_mtod(pkts[0], uint8_t *);
+ uint8_t *raw1 = rte_pktmbuf_mtod(pkts[1], uint8_t *);
+ uint8_t *raw2 = rte_pktmbuf_mtod(pkts[2], uint8_t *);
+ uint8_t *raw3 = rte_pktmbuf_mtod(pkts[3], uint8_t *);
+
+ /* Read: table entry */
+ uint64_t mac_addr_dst0 = entry0->macaddr;
+ uint64_t mac_addr_dst1 = entry1->macaddr;
+ uint64_t mac_addr_dst2 = entry2->macaddr;
+ uint64_t mac_addr_dst3 = entry3->macaddr;
+
+ uint64_t mac_addr_src0 = 0;
+ uint64_t mac_addr_src1 = 0;
+ uint64_t mac_addr_src2 = 0;
+ uint64_t mac_addr_src3 = 0;
+
+ /* Compute: Ethernet header */
+ uint64_t pkt0_slab0 = mac_addr_dst0 | (mac_addr_src0 << 48);
+ uint64_t pkt1_slab0 = mac_addr_dst1 | (mac_addr_src1 << 48);
+ uint64_t pkt2_slab0 = mac_addr_dst2 | (mac_addr_src2 << 48);
+ uint64_t pkt3_slab0 = mac_addr_dst3 | (mac_addr_src3 << 48);
+
+ uint32_t pkt0_slab1 = mac_addr_src0 >> 16;
+ uint32_t pkt1_slab1 = mac_addr_src1 >> 16;
+ uint32_t pkt2_slab1 = mac_addr_src2 >> 16;
+ uint32_t pkt3_slab1 = mac_addr_src3 >> 16;
+
+ /* Write: pkt buffer - pkt headers */
+ *((uint64_t *) raw0) = pkt0_slab0;
+ *((uint32_t *) (raw0 + 8)) = pkt0_slab1;
+ *((uint64_t *) raw1) = pkt1_slab0;
+ *((uint32_t *) (raw1 + 8)) = pkt1_slab1;
+ *((uint64_t *) raw2) = pkt2_slab0;
+ *((uint32_t *) (raw2 + 8)) = pkt2_slab1;
+ *((uint64_t *) raw3) = pkt3_slab0;
+ *((uint32_t *) (raw3 + 8)) = pkt3_slab1;
+}
+
+PIPELINE_TABLE_AH_HIT(arp_table_ah_hit, pkt_work_arp, pkt4_work_arp);
+
+static int
+pipeline_routing_parse_args(struct pipeline_routing *p,
+ struct pipeline_params *params)
+{
+ uint32_t n_routes_present = 0;
+ uint32_t n_arp_entries_present = 0;
+ uint32_t ip_da_offset_present = 0;
+ uint32_t arp_key_offset_present = 0;
+ uint32_t i;
+
+ 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) {
+ if (n_routes_present)
+ return -1;
+ n_routes_present = 1;
+
+ p->n_routes = atoi(arg_value);
+ if (p->n_routes == 0)
+ return -1;
+
+ continue;
+ }
+
+ /* n_arp_entries */
+ if (strcmp(arg_name, "n_arp_entries") == 0) {
+ if (n_arp_entries_present)
+ return -1;
+ n_arp_entries_present = 1;
+
+ p->n_arp_entries = atoi(arg_value);
+ if (p->n_arp_entries == 0)
+ return -1;
+
+ continue;
+ }
+
+ /* ip_da_offset */
+ if (strcmp(arg_name, "ip_da_offset") == 0) {
+ if (ip_da_offset_present)
+ return -1;
+ ip_da_offset_present = 1;
+
+ p->ip_da_offset = atoi(arg_value);
+
+ continue;
+ }
+
+ /* arp_key_offset */
+ if (strcmp(arg_name, "arp_key_offset") == 0) {
+ if (arp_key_offset_present)
+ return -1;
+ arp_key_offset_present = 1;
+
+ p->arp_key_offset = atoi(arg_value);
+
+ continue;
+ }
+
+ /* any other */
+ return -1;
+ }
+
+ /* Check that mandatory arguments are present */
+ if ((n_routes_present == 0) ||
+ (n_arp_entries_present == 0) ||
+ (ip_da_offset_present == 0) ||
+ (n_arp_entries_present && (arp_key_offset_present == 0)))
+ return -1;
+
+ 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))
+ 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,
+ .f_action_bulk = 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 = {
+ .n_rules = p_rt->n_routes,
+ .entry_unique_size = sizeof(struct routing_table_entry),
+ .offset = p_rt->ip_da_offset,
+ };
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_lpm_ops,
+ .arg_create = &table_lpm_params,
+ .f_action_hit = routing_table_ah_hit,
+ .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->n_arp_entries) {
+ struct rte_table_hash_key8_ext_params table_arp_params = {
+ .n_entries = p_rt->n_arp_entries,
+ .n_entries_ext = p_rt->n_arp_entries,
+ .f_hash = hash_default_key8,
+ .seed = 0,
+ .signature_offset = 0, /* Unused */
+ .key_offset = p_rt->arp_key_offset,
+ };
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_key8_ext_dosig_ops,
+ .arg_create = &table_arp_params,
+ .f_action_hit = arp_table_ah_hit,
+ .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_track(void *pipeline,
+ __rte_unused uint32_t port_in,
+ uint32_t *port_out)
+{
+ struct pipeline *p = (struct pipeline *) pipeline;
+
+ /* Check input arguments */
+ if ((p == NULL) ||
+ (port_in >= p->n_ports_in) ||
+ (port_out == NULL))
+ return -1;
+
+ if (p->n_ports_in == 1) {
+ *port_out = 0;
+ return 0;
+ }
+
+ return -1;
+}
+
+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_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 = {
+ .head = {
+ .action = RTE_PIPELINE_ACTION_TABLE,
+ {.table_id = p->table_id[1]},
+ },
+
+ .flags = req->flags,
+ .port_id = req->port_id,
+ .ip = rte_bswap32(req->ip),
+ };
+
+ if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) {
+ rsp->status = -1;
+ return rsp;
+ }
+
+ rsp->status = rte_pipeline_table_entry_add(p->p,
+ p->table_id[0],
+ &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_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;
+ }
+
+ *((struct ether_addr *) &entry.macaddr) = req->macaddr;
+
+ 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;
+}
+
+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,
+ .f_track = pipeline_routing_track,
+};
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.h b/examples/ip_pipeline/pipeline/pipeline_routing_be.h
new file mode 100644
index 0000000..db34db5
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.h
@@ -0,0 +1,230 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#ifndef __INCLUDE_PIPELINE_ROUTING_BE_H__
+#define __INCLUDE_PIPELINE_ROUTING_BE_H__
+
+#include <rte_ether.h>
+
+#include "pipeline_common_be.h"
+
+/*
+ * 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 */
+};
+
+/*
+ * 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_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 */
+ enum pipeline_routing_route_flags flags;
+ uint32_t port_id; /* Output port ID */
+ uint32_t ip; /* IP address for the next hop (only valid for remote routes) */
+};
+
+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;
+};
+
+extern struct pipeline_be_ops pipeline_routing_be_ops;
+
+#endif
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 11/11] ip_pipeline: added new implementation of flow classification pipeline
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
` (9 preceding siblings ...)
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 10/11] ip_pipeline: added new implementation of routing pipeline Maciej Gajdzica
@ 2015-06-25 11:15 ` Maciej Gajdzica
2015-06-25 12:19 ` [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Dumitrescu, Cristian
11 siblings, 0 replies; 13+ messages in thread
From: Maciej Gajdzica @ 2015-06-25 11:15 UTC (permalink / raw)
To: dev
Flow classification pipeline implementation is split to two files.
pipeline_flow_classification.c file handles front-end functions (cli
commands parsing) pipeline_flow_classification_ops.c contains
implementation of functions done by pipeline (back-end).
Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
---
examples/ip_pipeline/Makefile | 2 +
examples/ip_pipeline/config/fc_ipv4_5tuple.cfg | 23 +
examples/ip_pipeline/config/fc_ipv4_5tuple.sh | 9 +
examples/ip_pipeline/config/fc_ipv6_5tuple.cfg | 23 +
examples/ip_pipeline/config/fc_ipv6_5tuple.sh | 8 +
examples/ip_pipeline/config/fc_qinq.cfg | 23 +
examples/ip_pipeline/config/fc_qinq.sh | 8 +
examples/ip_pipeline/init.c | 2 +
.../pipeline/pipeline_flow_classification.c | 2063 +++++++++++++++++---
.../pipeline/pipeline_flow_classification.h | 106 +
.../pipeline/pipeline_flow_classification_be.c | 569 ++++++
.../pipeline/pipeline_flow_classification_be.h | 140 ++
12 files changed, 2755 insertions(+), 221 deletions(-)
create mode 100644 examples/ip_pipeline/config/fc_ipv4_5tuple.cfg
create mode 100644 examples/ip_pipeline/config/fc_ipv4_5tuple.sh
create mode 100644 examples/ip_pipeline/config/fc_ipv6_5tuple.cfg
create mode 100644 examples/ip_pipeline/config/fc_ipv6_5tuple.sh
create mode 100644 examples/ip_pipeline/config/fc_qinq.cfg
create mode 100644 examples/ip_pipeline/config/fc_qinq.sh
create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification.h
create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index a2881a6..f3ff1ec 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -64,6 +64,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough_be.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall_be.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing_be.c
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing.c
diff --git a/examples/ip_pipeline/config/fc_ipv4_5tuple.cfg b/examples/ip_pipeline/config/fc_ipv4_5tuple.cfg
new file mode 100644
index 0000000..246df5f
--- /dev/null
+++ b/examples/ip_pipeline/config/fc_ipv4_5tuple.cfg
@@ -0,0 +1,23 @@
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = PASS-THROUGH
+core = s0c1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = SWQ0 SWQ1 SWQ2 SWQ3
+key_type = ipv4_5tuple
+key_offset_rd = 150; key_offset_rd = headroom (128) + ethernet (14) + ttl offset (8)
+key_offset_wr = 64
+hash_offset = 80
+
+[PIPELINE2]
+type = FLOW_CLASSIFICATION
+core = s0c2
+pktq_in = SWQ0 SWQ1 SWQ2 SWQ3
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0
+n_flows = 16777216
+key_offset = 64
+key_size = 16
+hash_offset = 80
diff --git a/examples/ip_pipeline/config/fc_ipv4_5tuple.sh b/examples/ip_pipeline/config/fc_ipv4_5tuple.sh
new file mode 100644
index 0000000..29c77f9
--- /dev/null
+++ b/examples/ip_pipeline/config/fc_ipv4_5tuple.sh
@@ -0,0 +1,9 @@
+#run config/fc_ipv4_5tuple.sh
+
+p 1 ping
+p 2 ping
+
+p 2 flow add default 3
+p 2 flow add ipv4_5tuple 1.2.3.4 5.6.7.8 256 257 6 2
+p 2 flow ls
+
diff --git a/examples/ip_pipeline/config/fc_ipv6_5tuple.cfg b/examples/ip_pipeline/config/fc_ipv6_5tuple.cfg
new file mode 100644
index 0000000..4b2b0da
--- /dev/null
+++ b/examples/ip_pipeline/config/fc_ipv6_5tuple.cfg
@@ -0,0 +1,23 @@
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = PASS-THROUGH
+core = s0c1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = SWQ0 SWQ1 SWQ2 SWQ3
+key_type = ipv6_5tuple; key_size = 64
+key_offset_rd = 146; key_offset_rd = headroom (128) + ethernet (14) + payload length offset (4)
+key_offset_wr = 0
+hash_offset = 64
+
+[PIPELINE2]
+type = FLOW_CLASSIFICATION
+core = s0c2
+pktq_in = SWQ0 SWQ1 SWQ2 SWQ3
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0
+n_flows = 16777216
+key_offset = 0
+key_size = 64
+hash_offset = 64
diff --git a/examples/ip_pipeline/config/fc_ipv6_5tuple.sh b/examples/ip_pipeline/config/fc_ipv6_5tuple.sh
new file mode 100644
index 0000000..b3724ee
--- /dev/null
+++ b/examples/ip_pipeline/config/fc_ipv6_5tuple.sh
@@ -0,0 +1,8 @@
+#run config/fc_ipv6_5tuple.sh
+
+p 1 ping
+p 2 ping
+
+p 2 flow add default 3
+p 2 flow add ipv6_5tuple 0001:0203:0405:0607:0809:0a0b:0c0d:0e0f 1011:1213:1415:1617:1819:1a1b:1c1d:1e1f 256 257 6 2
+p 2 flow ls
diff --git a/examples/ip_pipeline/config/fc_qinq.cfg b/examples/ip_pipeline/config/fc_qinq.cfg
new file mode 100644
index 0000000..a502d7a
--- /dev/null
+++ b/examples/ip_pipeline/config/fc_qinq.cfg
@@ -0,0 +1,23 @@
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = PASS-THROUGH
+core = s0c1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = SWQ0 SWQ1 SWQ2 SWQ3
+key_type = qinq
+key_offset_rd = 140; key_offset_rd = headroom (128) + 1st ethertype offset (12)
+key_offset_wr = 64
+hash_offset = 72
+
+[PIPELINE2]
+type = FLOW_CLASSIFICATION
+core = s0c2
+pktq_in = SWQ0 SWQ1 SWQ2 SWQ3
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0
+n_flows = 16777216
+key_offset = 64
+key_size = 8
+hash_offset = 72
diff --git a/examples/ip_pipeline/config/fc_qinq.sh b/examples/ip_pipeline/config/fc_qinq.sh
new file mode 100644
index 0000000..71dc350
--- /dev/null
+++ b/examples/ip_pipeline/config/fc_qinq.sh
@@ -0,0 +1,8 @@
+#run config/fc_qinq.sh
+
+p 1 ping
+p 2 ping
+
+p 2 flow add default 3
+p 2 flow add qinq 256 257 2
+p 2 flow ls
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index 840bc60..c4edae8 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -47,6 +47,7 @@
#include "pipeline_master.h"
#include "pipeline_passthrough.h"
#include "pipeline_firewall.h"
+#include "pipeline_flow_classification.h"
#include "pipeline_routing.h"
#define APP_NAME_SIZE 32
@@ -1193,6 +1194,7 @@ int app_init(struct app_params *app)
app_pipeline_common_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_firewall);
app_pipeline_type_register(app, &pipeline_routing);
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c
index cc0cbf1..f578f54 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,275 +32,1896 @@
*/
#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+#include <rte_common.h>
+#include <rte_hexdump.h>
#include <rte_malloc.h>
-#include <rte_log.h>
-#include <rte_ethdev.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-#include <rte_byteorder.h>
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_ipaddr.h>
+#include <cmdline_parse_etheraddr.h>
-#include <rte_port_ring.h>
-#include <rte_table_hash.h>
-#include <rte_pipeline.h>
+#include "app.h"
+#include "pipeline_common_fe.h"
+#include "pipeline_flow_classification.h"
+#include "hash_func.h"
-#include "main.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];
+ void *key_buffer = (key_out)? key_out : buffer;
+
+ switch (key_in->type) {
+ case FLOW_KEY_QINQ:
+ {
+ struct pkt_key_qinq *qinq = key_buffer;
-struct app_core_fc_message_handle_params {
- struct rte_ring *ring_req;
- struct rte_ring *ring_resp;
+ qinq->ethertype_svlan = 0;
+ qinq->svlan = rte_bswap16(key_in->key.qinq.svlan);
+ qinq->ethertype_cvlan = 0;
+ qinq->cvlan = rte_bswap16(key_in->key.qinq.cvlan);
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t table_id;
+ if (signature)
+ *signature = (uint32_t) hash_default_key8(qinq, 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_bswap32(key_in->key.ipv4_5tuple.ip_src);
+ ipv4->ip_dst = rte_bswap32(key_in->key.ipv4_5tuple.ip_dst);
+ ipv4->port_src = rte_bswap16(key_in->key.ipv4_5tuple.port_src);
+ ipv4->port_dst = rte_bswap16(key_in->key.ipv4_5tuple.port_dst);
+
+ if (signature)
+ *signature = (uint32_t) hash_default_key16(ipv4, 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_bswap16(key_in->key.ipv6_5tuple.port_src);
+ ipv6->port_dst = rte_bswap16(key_in->key.ipv6_5tuple.port_dst);
+
+ if (signature)
+ *signature = (uint32_t) hash_default_key64(ipv6, 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 signature;
+ void *entry_ptr;
+
+ TAILQ_ENTRY(app_pipeline_fc_flow) node;
};
-static void
-app_message_handle(struct app_core_fc_message_handle_params *params);
+#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_flow_classification_table_init(
- struct rte_pipeline *p,
- uint32_t *port_out_id,
- uint32_t table_id)
+static int
+app_pipeline_fc_free(void *pipeline)
{
- struct app_flow_key flow_key;
+ struct app_pipeline_fc *p = pipeline;
uint32_t i;
- /* Add entries to tables */
- for (i = 0; i < (1 << 24); i++) {
- struct rte_pipeline_table_entry entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[i & (app.n_ports - 1)]},
- };
- struct rte_pipeline_table_entry *entry_ptr;
- int key_found, status;
-
- flow_key.ttl = 0;
- flow_key.proto = 6; /* TCP */
- flow_key.header_checksum = 0;
- flow_key.ip_src = 0;
- flow_key.ip_dst = rte_bswap32(i);
- flow_key.port_src = 0;
- flow_key.port_dst = 0;
-
- status = rte_pipeline_table_entry_add(p, table_id,
- (void *) &flow_key, &entry, &key_found, &entry_ptr);
- if (status < 0)
- rte_panic("Unable to add entry to table %u (%d)\n",
- table_id, status);
+ /* 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_add(struct app_params *app,
+ uint32_t pipeline_id,
+ struct pipeline_fc_key *key,
+ uint32_t port_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);
+ if (p == NULL)
+ return -1;
+
+ if (port_id >= p->n_ports_in)
+ 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;
+
+ /* 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->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;
}
-void
-app_main_loop_pipeline_flow_classification(void) {
- struct rte_pipeline_params pipeline_params = {
- .name = "pipeline",
- .socket_id = rte_socket_id(),
- };
-
- struct rte_pipeline *p;
- uint32_t port_in_id[APP_MAX_PORTS];
- uint32_t port_out_id[APP_MAX_PORTS];
- uint32_t table_id;
- uint32_t i;
+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 n_keys)
+{
+ struct app_pipeline_fc *p;
+ struct pipeline_fc_add_bulk_msg_req *req;
+ struct pipeline_fc_add_bulk_msg_rsp *rsp;
- uint32_t core_id = rte_lcore_id();
- struct app_core_params *core_params = app_get_core_params(core_id);
- struct app_core_fc_message_handle_params mh_params;
+ 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;
- if ((core_params == NULL) || (core_params->core_type != APP_CORE_FC))
- rte_panic("Core %u misconfiguration\n", core_id);
+ uint32_t i;
+ int status;
- RTE_LOG(INFO, USER1, "Core %u is doing flow classification "
- "(pipeline with hash table, 16-byte key, LRU)\n", core_id);
+ /* Check input arguments */
+ if ((app == NULL) ||
+ (key == NULL) ||
+ (port_id == NULL) ||
+ (n_keys == 0))
+ return -1;
- /* Pipeline configuration */
- p = rte_pipeline_create(&pipeline_params);
+ p = app_pipeline_data_fe(app, pipeline_id);
if (p == NULL)
- rte_panic("Unable to configure the pipeline\n");
-
- /* Input port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_reader_params port_ring_params = {
- .ring = app.rings[core_params->swq_in[i]],
- };
-
- struct rte_pipeline_port_in_params port_params = {
- .ops = &rte_port_ring_reader_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .arg_ah = NULL,
- .burst_size = app.bsz_swq_rd,
- };
-
- if (rte_pipeline_port_in_create(p, &port_params,
- &port_in_id[i]))
- rte_panic("Unable to configure input port for "
- "ring %d\n", i);
+ return -1;
+
+ for (i = 0; i < n_keys; i++)
+ if (port_id[i] >= p->n_ports_in)
+ 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;
}
- /* Output port configuration */
- for (i = 0; i < app.n_ports; i++) {
- struct rte_port_ring_writer_params port_ring_params = {
- .ring = app.rings[core_params->swq_out[i]],
- .tx_burst_sz = app.bsz_swq_wr,
- };
-
- struct rte_pipeline_port_out_params port_params = {
- .ops = &rte_port_ring_writer_ops,
- .arg_create = (void *) &port_ring_params,
- .f_action = NULL,
- .f_action_bulk = NULL,
- .arg_ah = NULL,
- };
-
- if (rte_pipeline_port_out_create(p, &port_params,
- &port_out_id[i]))
- rte_panic("Unable to configure output port for "
- "ring %d\n", i);
+ 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;
}
- /* Table configuration */
- {
- struct rte_table_hash_key16_lru_params table_hash_params = {
- .n_entries = 1 << 24,
- .signature_offset = __builtin_offsetof(
- struct app_pkt_metadata, signature),
- .key_offset = __builtin_offsetof(
- struct app_pkt_metadata, flow_key),
- .f_hash = test_hash,
- .seed = 0,
- };
-
- struct rte_pipeline_table_params table_params = {
- .ops = &rte_table_hash_key16_lru_ops,
- .arg_create = &table_hash_params,
- .f_action_hit = NULL,
- .f_action_miss = NULL,
- .arg_ah = NULL,
- .action_data_size = 0,
- };
-
- if (rte_pipeline_table_create(p, &table_params, &table_id))
- rte_panic("Unable to configure the hash table\n");
+ 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;
}
- /* Interconnecting ports and tables */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
- table_id))
- rte_panic("Unable to connect input port %u to "
- "table %u\n", port_in_id[i], table_id);
-
- /* Enable input ports */
- for (i = 0; i < app.n_ports; i++)
- if (rte_pipeline_port_in_enable(p, port_in_id[i]))
- rte_panic("Unable to enable input port %u\n",
- port_in_id[i]);
-
- /* Check pipeline consistency */
- if (rte_pipeline_check(p) < 0)
- rte_panic("Pipeline consistency check failed\n");
-
- /* Message handling */
- mh_params.ring_req = app_get_ring_req(
- app_get_first_core_id(APP_CORE_FC));
- mh_params.ring_resp = app_get_ring_resp(
- app_get_first_core_id(APP_CORE_FC));
- mh_params.p = p;
- mh_params.port_out_id = port_out_id;
- mh_params.table_id = table_id;
-
- /* Run-time */
- for (i = 0; ; i++) {
- rte_pipeline_run(p);
-
- if ((i & APP_FLUSH) == 0) {
- rte_pipeline_flush(p);
- app_message_handle(&mh_params);
+ flow_rsp = rte_malloc(NULL, n_keys * sizeof(struct pipeline_fc_add_bulk_flow_rsp), RTE_CACHE_LINE_SIZE);
+ if (flow_req == 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];
+ }
+
+ 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]->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 */
+ app_msg_free(app, rsp);
+
+ for (i = rsp->n_keys; 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 status;
}
-void
-app_message_handle(struct app_core_fc_message_handle_params *params)
+int
+app_pipeline_fc_del(struct app_params *app,
+ uint32_t pipeline_id,
+ struct pipeline_fc_key *key)
{
- struct rte_ring *ring_req = params->ring_req;
- struct rte_ring *ring_resp;
- void *msg;
- struct app_msg_req *req;
- struct app_msg_resp *resp;
- struct rte_pipeline *p;
- uint32_t *port_out_id;
- uint32_t table_id;
- int result;
-
- /* Read request message */
- result = rte_ring_sc_dequeue(ring_req, &msg);
- if (result != 0)
- return;
+ struct app_pipeline_fc *p;
+ struct app_pipeline_fc_flow *flow;
- ring_resp = params->ring_resp;
- p = params->p;
- port_out_id = params->port_out_id;
- table_id = params->table_id;
+ struct pipeline_fc_del_msg_req *req;
+ struct pipeline_fc_del_msg_rsp *rsp;
- /* Handle request */
- req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- switch (req->type) {
- case APP_MSG_REQ_PING:
- {
- result = 0;
- break;
+ uint32_t signature, bucket_id;
+
+ /* Check input arguments */
+ if ((app == NULL) ||
+ (key == NULL))
+ return -1;
+
+ p = app_pipeline_data_fe(app, pipeline_id);
+ 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;
}
- case APP_MSG_REQ_FC_ADD_ALL:
- {
- result = app_flow_classification_table_init(p, port_out_id,
- table_id);
- break;
+ /* 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);
+ if (p == NULL)
+ return -1;
+
+ if (port_id >= p->n_ports_in)
+ 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;
}
- case APP_MSG_REQ_FC_ADD:
- {
- struct rte_pipeline_table_entry entry = {
- .action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = port_out_id[req->flow_classif_add.port]},
- };
+ p->default_flow_port_id = port_id;
+ p->default_flow_entry_ptr = rsp->entry_ptr;
- struct rte_pipeline_table_entry *entry_ptr;
+ /* Commit route */
+ p->default_flow_present = 1;
- int key_found;
+ /* Free response */
+ app_msg_free(app, rsp);
- result = rte_pipeline_table_entry_add(p, table_id,
- req->flow_classif_add.key_raw, &entry, &key_found,
- &entry_ptr);
- break;
+ 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);
+ 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;
}
- case APP_MSG_REQ_FC_DEL:
- {
- int key_found;
+ /* 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 = %u, "
+ "CVLAN = %u) => "
+ "Port = %u "
+ "(signature = 0x%08x, "
+ "entry_ptr = %p)\n",
+
+ flow->key.key.qinq.svlan,
+ flow->key.key.qinq.cvlan,
+ flow->port_id,
+ flow->signature,
+ flow->entry_ptr);
+}
+
+static void
+print_fc_ipv4_5tuple_flow(struct app_pipeline_fc_flow *flow)
+{
+ printf("(SA = %u.%u.%u.%u, "
+ "DA = %u.%u.%u.%u, "
+ "SP = %u, "
+ "DP = %u, "
+ "Proto = %u) => "
+ "Port = %u "
+ "(signature = 0x%08x, "
+ "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->signature,
+ flow->entry_ptr);
+}
+
+static void
+print_fc_ipv6_5tuple_flow(struct app_pipeline_fc_flow *flow)
+{
+ printf("(SA = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x, "
+ "DA = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x, "
+ "SP = %u, "
+ "DP = %u "
+ "Proto = %u "
+ "=> Port = %u "
+ "(signature = 0x%08x, "
+ "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],
- result = rte_pipeline_table_entry_delete(p, table_id,
- req->flow_classif_add.key_raw, &key_found, NULL);
+ 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->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;
}
+}
- default:
- rte_panic("FC Unrecognized message type (%u)\n", req->type);
+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);
+ 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 %u (entry ptr = %p)\n",
+ p->default_flow_port_id,
+ p->default_flow_entry_ptr);
+ else
+ printf("Default: DROP\n");
+
+ return 0;
+}
+
+/*
+ * flow add qinq
+ */
+
+struct cmd_fc_add_qinq_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t qinq_string;
+ uint16_t svlan;
+ uint16_t cvlan;
+ uint32_t port;
+};
+
+static void
+cmd_fc_add_qinq_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_add_qinq_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_fc_key key;
+ int status;
+
+ memset(&key, 0, sizeof(key));
+ key.type = FLOW_KEY_QINQ;
+ key.key.qinq.svlan = params->svlan;
+ key.key.qinq.cvlan = params->cvlan;
+
+ status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port);
+ if(status != 0)
+ printf("Command failed\n");
+}
+
+cmdline_parse_token_string_t cmd_fc_add_qinq_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_add_qinq_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_add_qinq_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_add_qinq_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, add_string, "add");
+
+cmdline_parse_token_string_t cmd_fc_add_qinq_qinq_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, qinq_string, "qinq");
+
+cmdline_parse_token_num_t cmd_fc_add_qinq_svlan =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, svlan, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_add_qinq_cvlan =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, cvlan, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_add_qinq_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, port, UINT32);
+
+cmdline_parse_inst_t cmd_fc_add_qinq = {
+ .f = cmd_fc_add_qinq_parsed,
+ .data = NULL,
+ .help_str = "Flow add (Q-in-Q)",
+ .tokens = {
+ (void *) &cmd_fc_add_qinq_p_string,
+ (void *) &cmd_fc_add_qinq_pipeline_id,
+ (void *) &cmd_fc_add_qinq_flow_string,
+ (void *) &cmd_fc_add_qinq_add_string,
+ (void *) &cmd_fc_add_qinq_qinq_string,
+ (void *) &cmd_fc_add_qinq_svlan,
+ (void *) &cmd_fc_add_qinq_cvlan,
+ (void *) &cmd_fc_add_qinq_port,
+ NULL,
+ },
+};
+
+/*
+ * flow add qinq all
+ */
+
+struct cmd_fc_add_qinq_all_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t qinq_string;
+ cmdline_fixed_string_t all_string;
+ uint32_t n_flows;
+ uint32_t n_ports;
+};
+
+#ifndef N_FLOWS_BULK
+#define N_FLOWS_BULK 4096
+#endif
+
+static void
+cmd_fc_add_qinq_all_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_add_qinq_all_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_fc_key *key;
+ uint32_t *port_id;
+ uint32_t flow_id;
+
+ key = rte_zmalloc(NULL, N_FLOWS_BULK * sizeof(*key), RTE_CACHE_LINE_SIZE);
+ if (key == NULL) {
+ printf("Memory allocation failed\n");
+ return;
}
- /* Fill in response message */
- resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
- resp->result = result;
+ port_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*port_id), RTE_CACHE_LINE_SIZE);
+ if (port_id == NULL) {
+ rte_free(key);
+ printf("Memory allocation failed\n");
+ return;
+ }
- /* Send response */
- do {
- result = rte_ring_sp_enqueue(ring_resp, msg);
- } while (result == -ENOBUFS);
+ for (flow_id = 0; flow_id < params->n_flows; flow_id++) {
+ uint32_t pos = flow_id & (N_FLOWS_BULK - 1);
+
+ key[pos].type = FLOW_KEY_QINQ;
+ key[pos].key.qinq.svlan = flow_id >> 12;
+ key[pos].key.qinq.cvlan = flow_id & 0xFFF;
+
+ port_id[pos] = flow_id % params->n_ports;
+
+ if ((pos == N_FLOWS_BULK - 1) ||
+ (flow_id == params->n_flows - 1)) {
+ int status;
+
+ status = app_pipeline_fc_add_bulk(app,
+ params->pipeline_id,
+ key,
+ port_id,
+ pos + 1);
+
+ if(status != 0) {
+ printf("Command failed\n");
+
+ break;
+ }
+ }
+ }
+
+ rte_free(port_id);
+ rte_free(key);
+}
+
+cmdline_parse_token_string_t cmd_fc_add_qinq_all_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_add_qinq_all_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_add_qinq_all_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_add_qinq_all_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, add_string, "add");
+
+cmdline_parse_token_string_t cmd_fc_add_qinq_all_qinq_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, qinq_string, "qinq");
+
+cmdline_parse_token_string_t cmd_fc_add_qinq_all_all_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, all_string, "all");
+
+cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_flows =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_flows, UINT32);
+
+cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_ports =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_ports, UINT32);
+
+cmdline_parse_inst_t cmd_fc_add_qinq_all = {
+ .f = cmd_fc_add_qinq_all_parsed,
+ .data = NULL,
+ .help_str = "Flow add all (Q-in-Q)",
+ .tokens = {
+ (void *) &cmd_fc_add_qinq_all_p_string,
+ (void *) &cmd_fc_add_qinq_all_pipeline_id,
+ (void *) &cmd_fc_add_qinq_all_flow_string,
+ (void *) &cmd_fc_add_qinq_all_add_string,
+ (void *) &cmd_fc_add_qinq_all_qinq_string,
+ (void *) &cmd_fc_add_qinq_all_all_string,
+ (void *) &cmd_fc_add_qinq_all_n_flows,
+ (void *) &cmd_fc_add_qinq_all_n_ports,
+ NULL,
+ },
+};
+
+/*
+ * flow add ipv4_5tuple
+ */
+
+struct cmd_fc_add_ipv4_5tuple_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t ipv4_5tuple_string;
+ cmdline_ipaddr_t ip_src;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+ uint32_t proto;
+ uint32_t port;
+};
+
+static void
+cmd_fc_add_ipv4_5tuple_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_add_ipv4_5tuple_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_fc_key key;
+ int status;
+
+ memset(&key, 0, sizeof(key));
+ key.type = FLOW_KEY_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.ip_src = rte_bswap32(params->ip_src.addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.ip_dst = rte_bswap32(params->ip_dst.addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.port_src = params->port_src;
+ key.key.ipv4_5tuple.port_dst = params->port_dst;
+ key.key.ipv4_5tuple.proto = params->proto;
+
+ status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port);
+ if(status != 0)
+ printf("Command failed\n");
+}
+
+cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, add_string, "add");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple");
+
+cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_src =
+ TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_src);
+
+cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_dst =
+ TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_dst);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_src =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_src, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_dst =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_dst, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_proto =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, proto, UINT32);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port, UINT32);
+
+cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple = {
+ .f = cmd_fc_add_ipv4_5tuple_parsed,
+ .data = NULL,
+ .help_str = "Flow add (IPv4 5-tuple)",
+ .tokens = {
+ (void *) &cmd_fc_add_ipv4_5tuple_p_string,
+ (void *) &cmd_fc_add_ipv4_5tuple_pipeline_id,
+ (void *) &cmd_fc_add_ipv4_5tuple_flow_string,
+ (void *) &cmd_fc_add_ipv4_5tuple_add_string,
+ (void *) &cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string,
+ (void *) &cmd_fc_add_ipv4_5tuple_ip_src,
+ (void *) &cmd_fc_add_ipv4_5tuple_ip_dst,
+ (void *) &cmd_fc_add_ipv4_5tuple_port_src,
+ (void *) &cmd_fc_add_ipv4_5tuple_port_dst,
+ (void *) &cmd_fc_add_ipv4_5tuple_proto,
+ (void *) &cmd_fc_add_ipv4_5tuple_port,
+ NULL,
+ },
+};
+
+/*
+ * flow add ipv4_5tuple all
+ */
+
+struct cmd_fc_add_ipv4_5tuple_all_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t ipv4_5tuple_string;
+ cmdline_fixed_string_t all_string;
+ uint32_t n_flows;
+ uint32_t n_ports;
+};
+
+static void
+cmd_fc_add_ipv4_5tuple_all_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_add_ipv4_5tuple_all_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_fc_key *key;
+ uint32_t *port_id;
+ uint32_t flow_id;
+
+ key = rte_zmalloc(NULL, N_FLOWS_BULK * sizeof(*key), RTE_CACHE_LINE_SIZE);
+ if (key == NULL) {
+ printf("Memory allocation failed\n");
+ return;
+ }
+
+ port_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*port_id), RTE_CACHE_LINE_SIZE);
+ if (port_id == NULL) {
+ rte_free(key);
+ printf("Memory allocation failed\n");
+ return;
+ }
+
+ for (flow_id = 0; flow_id < params->n_flows; flow_id++) {
+ uint32_t pos = flow_id & (N_FLOWS_BULK - 1);
+
+ key[pos].type = FLOW_KEY_IPV4_5TUPLE;
+ key[pos].key.ipv4_5tuple.ip_src = 0;
+ key[pos].key.ipv4_5tuple.ip_dst = flow_id;
+ key[pos].key.ipv4_5tuple.port_src = 0;
+ key[pos].key.ipv4_5tuple.port_dst = 0;
+ key[pos].key.ipv4_5tuple.proto = 6;
+
+ port_id[pos] = flow_id % params->n_ports;
+
+ if ((pos == N_FLOWS_BULK - 1) ||
+ (flow_id == params->n_flows - 1)) {
+ int status;
+
+ status = app_pipeline_fc_add_bulk(app,
+ params->pipeline_id,
+ key,
+ port_id,
+ pos + 1);
+
+ if(status != 0) {
+ printf("Command failed\n");
+
+ break;
+ }
+ }
+ }
+
+ rte_free(port_id);
+ rte_free(key);
+}
+
+cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, add_string, "add");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, ipv4_5tuple_string, "ipv4_5tuple");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_all_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, all_string, "all");
+
+cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_flows =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, n_flows, UINT32);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_ports =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, n_ports, UINT32);
+
+cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple_all = {
+ .f = cmd_fc_add_ipv4_5tuple_all_parsed,
+ .data = NULL,
+ .help_str = "Flow add all (IPv4 5-tuple)",
+ .tokens = {
+ (void *) &cmd_fc_add_ipv4_5tuple_all_p_string,
+ (void *) &cmd_fc_add_ipv4_5tuple_all_pipeline_id,
+ (void *) &cmd_fc_add_ipv4_5tuple_all_flow_string,
+ (void *) &cmd_fc_add_ipv4_5tuple_all_add_string,
+ (void *) &cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string,
+ (void *) &cmd_fc_add_ipv4_5tuple_all_all_string,
+ (void *) &cmd_fc_add_ipv4_5tuple_all_n_flows,
+ (void *) &cmd_fc_add_ipv4_5tuple_all_n_ports,
+ NULL,
+ },
+};
+
+/*
+ * flow add ipv6_5tuple
+ */
+
+struct cmd_fc_add_ipv6_5tuple_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t ipv6_5tuple_string;
+ cmdline_ipaddr_t ip_src;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+ uint32_t proto;
+ uint32_t port;
+};
+
+static void
+cmd_fc_add_ipv6_5tuple_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_add_ipv6_5tuple_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_fc_key key;
+ int status;
+
+ memset(&key, 0, sizeof(key));
+ key.type = FLOW_KEY_IPV6_5TUPLE;
+ memcpy(key.key.ipv6_5tuple.ip_src, params->ip_src.addr.ipv6.s6_addr, 16);
+ memcpy(key.key.ipv6_5tuple.ip_dst, params->ip_dst.addr.ipv6.s6_addr, 16);
+ key.key.ipv6_5tuple.port_src = params->port_src;
+ key.key.ipv6_5tuple.port_dst = params->port_dst;
+ key.key.ipv6_5tuple.proto = params->proto;
+
+ status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port);
+ if(status != 0)
+ printf("Command failed\n");
+}
+
+cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, add_string, "add");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple");
+
+cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_src =
+ TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_src);
+
+cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_dst =
+ TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_dst);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_src =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_src, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_dst =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_dst, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_proto =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, proto, UINT32);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port, UINT32);
+
+cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple = {
+ .f = cmd_fc_add_ipv6_5tuple_parsed,
+ .data = NULL,
+ .help_str = "Flow add (IPv6 5-tuple)",
+ .tokens = {
+ (void *) &cmd_fc_add_ipv6_5tuple_p_string,
+ (void *) &cmd_fc_add_ipv6_5tuple_pipeline_id,
+ (void *) &cmd_fc_add_ipv6_5tuple_flow_string,
+ (void *) &cmd_fc_add_ipv6_5tuple_add_string,
+ (void *) &cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string,
+ (void *) &cmd_fc_add_ipv6_5tuple_ip_src,
+ (void *) &cmd_fc_add_ipv6_5tuple_ip_dst,
+ (void *) &cmd_fc_add_ipv6_5tuple_port_src,
+ (void *) &cmd_fc_add_ipv6_5tuple_port_dst,
+ (void *) &cmd_fc_add_ipv6_5tuple_proto,
+ (void *) &cmd_fc_add_ipv6_5tuple_port,
+ NULL,
+ },
+};
+
+/*
+ * flow add ipv6_5tuple all
+ */
+
+struct cmd_fc_add_ipv6_5tuple_all_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t ipv6_5tuple_string;
+ cmdline_fixed_string_t all_string;
+ uint32_t n_flows;
+ uint32_t n_ports;
+};
+
+static void
+cmd_fc_add_ipv6_5tuple_all_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_add_ipv6_5tuple_all_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_fc_key *key;
+ uint32_t *port_id;
+ uint32_t flow_id;
+
+ key = rte_zmalloc(NULL, N_FLOWS_BULK * sizeof(*key), RTE_CACHE_LINE_SIZE);
+ if (key == NULL) {
+ printf("Memory allocation failed\n");
+ return;
+ }
+
+ port_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*port_id), RTE_CACHE_LINE_SIZE);
+ if (port_id == NULL) {
+ rte_free(key);
+ printf("Memory allocation failed\n");
+ return;
+ }
+
+ for (flow_id = 0; flow_id < params->n_flows; flow_id++) {
+ uint32_t pos = flow_id & (N_FLOWS_BULK - 1);
+ uint32_t *x;
+
+ key[pos].type = FLOW_KEY_IPV6_5TUPLE;
+ x = (uint32_t *) key[pos].key.ipv6_5tuple.ip_dst;
+ *x = rte_bswap32(flow_id);
+ key[pos].key.ipv6_5tuple.proto = 6;
+
+ port_id[pos] = flow_id % params->n_ports;
+
+ if ((pos == N_FLOWS_BULK - 1) ||
+ (flow_id == params->n_flows - 1)) {
+ int status;
+
+ status = app_pipeline_fc_add_bulk(app,
+ params->pipeline_id,
+ key,
+ port_id,
+ pos + 1);
+
+ if(status != 0) {
+ printf("Command failed\n");
+
+ break;
+ }
+ }
+ }
+
+ rte_free(port_id);
+ rte_free(key);
}
+
+cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, add_string, "add");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, ipv6_5tuple_string, "ipv6_5tuple");
+
+cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_all_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, all_string, "all");
+
+cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_flows =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, n_flows, UINT32);
+
+cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_ports =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, n_ports, UINT32);
+
+cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple_all = {
+ .f = cmd_fc_add_ipv6_5tuple_all_parsed,
+ .data = NULL,
+ .help_str = "Flow add all (ipv6 5-tuple)",
+ .tokens = {
+ (void *) &cmd_fc_add_ipv6_5tuple_all_p_string,
+ (void *) &cmd_fc_add_ipv6_5tuple_all_pipeline_id,
+ (void *) &cmd_fc_add_ipv6_5tuple_all_flow_string,
+ (void *) &cmd_fc_add_ipv6_5tuple_all_add_string,
+ (void *) &cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string,
+ (void *) &cmd_fc_add_ipv6_5tuple_all_all_string,
+ (void *) &cmd_fc_add_ipv6_5tuple_all_n_flows,
+ (void *) &cmd_fc_add_ipv6_5tuple_all_n_ports,
+ NULL,
+ },
+};
+
+/*
+ * flow del qinq
+ */
+struct cmd_fc_del_qinq_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_fixed_string_t qinq_string;
+ uint16_t svlan;
+ uint16_t cvlan;
+};
+
+static void
+cmd_fc_del_qinq_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_del_qinq_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_fc_key key;
+ int status;
+
+ memset(&key, 0, sizeof(key));
+ key.type = FLOW_KEY_QINQ;
+ key.key.qinq.svlan = params->svlan;
+ key.key.qinq.cvlan = params->cvlan;
+ status = app_pipeline_fc_del(app, params->pipeline_id, &key);
+
+ if(status != 0)
+ printf("Command failed\n");
+}
+
+cmdline_parse_token_string_t cmd_fc_del_qinq_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_del_qinq_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_del_qinq_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_del_qinq_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, del_string, "del");
+
+cmdline_parse_token_string_t cmd_fc_del_qinq_qinq_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, qinq_string, "qinq");
+
+cmdline_parse_token_num_t cmd_fc_del_qinq_svlan =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, svlan, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_del_qinq_cvlan =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, cvlan, UINT16);
+
+cmdline_parse_inst_t cmd_fc_del_qinq = {
+ .f = cmd_fc_del_qinq_parsed,
+ .data = NULL,
+ .help_str = "Flow delete (Q-in-Q)",
+ .tokens = {
+ (void *) &cmd_fc_del_qinq_p_string,
+ (void *) &cmd_fc_del_qinq_pipeline_id,
+ (void *) &cmd_fc_del_qinq_flow_string,
+ (void *) &cmd_fc_del_qinq_del_string,
+ (void *) &cmd_fc_del_qinq_qinq_string,
+ (void *) &cmd_fc_del_qinq_svlan,
+ (void *) &cmd_fc_del_qinq_cvlan,
+ NULL,
+ },
+};
+
+/*
+ * flow del ipv4_5tuple
+ */
+
+struct cmd_fc_del_ipv4_5tuple_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_fixed_string_t ipv4_5tuple_string;
+ cmdline_ipaddr_t ip_src;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+ uint32_t proto;
+};
+
+static void
+cmd_fc_del_ipv4_5tuple_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_del_ipv4_5tuple_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_fc_key key;
+ int status;
+
+ memset(&key, 0, sizeof(key));
+ key.type = FLOW_KEY_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.ip_src = rte_bswap32(params->ip_src.addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.ip_dst = rte_bswap32(params->ip_dst.addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.port_src = params->port_src;
+ key.key.ipv4_5tuple.port_dst = params->port_dst;
+ key.key.ipv4_5tuple.proto = params->proto;
+
+ status = app_pipeline_fc_del(app, params->pipeline_id, &key);
+ if(status != 0)
+ printf("Command failed\n");
+}
+
+cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, del_string, "del");
+
+cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple");
+
+cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_src =
+ TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_src);
+
+cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_dst =
+ TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_dst);
+
+cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_src =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, port_src, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_dst =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, port_dst, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_proto =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, proto, UINT32);
+
+cmdline_parse_inst_t cmd_fc_del_ipv4_5tuple = {
+ .f = cmd_fc_del_ipv4_5tuple_parsed,
+ .data = NULL,
+ .help_str = "Flow delete (IPv4 5-tuple)",
+ .tokens = {
+ (void *) &cmd_fc_del_ipv4_5tuple_p_string,
+ (void *) &cmd_fc_del_ipv4_5tuple_pipeline_id,
+ (void *) &cmd_fc_del_ipv4_5tuple_flow_string,
+ (void *) &cmd_fc_del_ipv4_5tuple_del_string,
+ (void *) &cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string,
+ (void *) &cmd_fc_del_ipv4_5tuple_ip_src,
+ (void *) &cmd_fc_del_ipv4_5tuple_ip_dst,
+ (void *) &cmd_fc_del_ipv4_5tuple_port_src,
+ (void *) &cmd_fc_del_ipv4_5tuple_port_dst,
+ (void *) &cmd_fc_del_ipv4_5tuple_proto,
+ NULL,
+ },
+};
+
+/*
+ * flow del ipv6_5tuple
+ */
+
+struct cmd_fc_del_ipv6_5tuple_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_fixed_string_t ipv6_5tuple_string;
+ cmdline_ipaddr_t ip_src;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+ uint32_t proto;
+};
+
+static void
+cmd_fc_del_ipv6_5tuple_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_del_ipv6_5tuple_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_fc_key key;
+ int status;
+
+ memset(&key, 0, sizeof(key));
+ key.type = FLOW_KEY_IPV6_5TUPLE;
+ memcpy(key.key.ipv6_5tuple.ip_src, params->ip_src.addr.ipv6.s6_addr, 16);
+ memcpy(key.key.ipv6_5tuple.ip_dst, params->ip_dst.addr.ipv6.s6_addr, 16);
+ key.key.ipv6_5tuple.port_src = params->port_src;
+ key.key.ipv6_5tuple.port_dst = params->port_dst;
+ key.key.ipv6_5tuple.proto = params->proto;
+
+ status = app_pipeline_fc_del(app, params->pipeline_id, &key);
+ if(status != 0)
+ printf("Command failed\n");
+}
+
+cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, del_string, "del");
+
+cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple");
+
+cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_src =
+ TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_src);
+
+cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_dst =
+ TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_dst);
+
+cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_src =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_src, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_dst =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_dst, UINT16);
+
+cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_proto =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, proto, UINT32);
+
+cmdline_parse_inst_t cmd_fc_del_ipv6_5tuple = {
+ .f = cmd_fc_del_ipv6_5tuple_parsed,
+ .data = NULL,
+ .help_str = "Flow delete (IPv6 5-tuple)",
+ .tokens = {
+ (void *) &cmd_fc_del_ipv6_5tuple_p_string,
+ (void *) &cmd_fc_del_ipv6_5tuple_pipeline_id,
+ (void *) &cmd_fc_del_ipv6_5tuple_flow_string,
+ (void *) &cmd_fc_del_ipv6_5tuple_del_string,
+ (void *) &cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string,
+ (void *) &cmd_fc_del_ipv6_5tuple_ip_src,
+ (void *) &cmd_fc_del_ipv6_5tuple_ip_dst,
+ (void *) &cmd_fc_del_ipv6_5tuple_port_src,
+ (void *) &cmd_fc_del_ipv6_5tuple_port_dst,
+ (void *) &cmd_fc_del_ipv6_5tuple_proto,
+ NULL,
+ },
+};
+
+/*
+ * flow add default
+ */
+
+struct cmd_fc_add_default_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t add_string;
+ cmdline_fixed_string_t default_string;
+ uint32_t port;
+};
+
+static void
+cmd_fc_add_default_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_add_default_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ status = app_pipeline_fc_add_default(app, params->pipeline_id,
+ params->port);
+
+ if(status != 0)
+ printf("Command failed\n");
+}
+
+cmdline_parse_token_string_t cmd_fc_add_default_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_add_default_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_add_default_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_add_default_add_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, add_string, "add");
+
+cmdline_parse_token_string_t cmd_fc_add_default_default_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, default_string, "default");
+
+cmdline_parse_token_num_t cmd_fc_add_default_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, port, UINT32);
+
+cmdline_parse_inst_t cmd_fc_add_default = {
+ .f = cmd_fc_add_default_parsed,
+ .data = NULL,
+ .help_str = "Flow add default",
+ .tokens = {
+ (void *) &cmd_fc_add_default_p_string,
+ (void *) &cmd_fc_add_default_pipeline_id,
+ (void *) &cmd_fc_add_default_flow_string,
+ (void *) &cmd_fc_add_default_add_string,
+ (void *) &cmd_fc_add_default_default_string,
+ (void *) &cmd_fc_add_default_port,
+ NULL,
+ },
+};
+
+/*
+ * flow del default
+ */
+
+struct cmd_fc_del_default_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_fixed_string_t default_string;
+};
+
+static void
+cmd_fc_del_default_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_del_default_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ status = app_pipeline_fc_del_default(app, params->pipeline_id);
+ if(status != 0)
+ printf("Command failed\n");
+}
+
+cmdline_parse_token_string_t cmd_fc_del_default_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_del_default_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_del_default_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_del_default_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_del_default_del_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, del_string, "del");
+
+cmdline_parse_token_string_t cmd_fc_del_default_default_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, default_string, "default");
+
+cmdline_parse_inst_t cmd_fc_del_default = {
+ .f = cmd_fc_del_default_parsed,
+ .data = NULL,
+ .help_str = "Flow delete default",
+ .tokens = {
+ (void *) &cmd_fc_del_default_p_string,
+ (void *) &cmd_fc_del_default_pipeline_id,
+ (void *) &cmd_fc_del_default_flow_string,
+ (void *) &cmd_fc_del_default_del_string,
+ (void *) &cmd_fc_del_default_default_string,
+ NULL,
+ },
+};
+
+/*
+ * flow ls
+ */
+
+struct cmd_fc_ls_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t pipeline_id;
+ cmdline_fixed_string_t flow_string;
+ cmdline_fixed_string_t ls_string;
+};
+
+static void
+cmd_fc_ls_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_fc_ls_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+
+ status = app_pipeline_fc_ls(app, params->pipeline_id);
+ if(status != 0)
+ printf("Command failed\n");
+}
+
+cmdline_parse_token_string_t cmd_fc_ls_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_fc_ls_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_fc_ls_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_fc_ls_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result,
+ flow_string, "flow");
+
+cmdline_parse_token_string_t cmd_fc_ls_ls_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, ls_string,
+ "ls");
+
+cmdline_parse_inst_t cmd_fc_ls = {
+ .f = cmd_fc_ls_parsed,
+ .data = NULL,
+ .help_str = "Flow list",
+ .tokens = {
+ (void *) &cmd_fc_ls_p_string,
+ (void *) &cmd_fc_ls_pipeline_id,
+ (void *) &cmd_fc_ls_flow_string,
+ (void *) &cmd_fc_ls_ls_string,
+ NULL,
+ },
+};
+
+static cmdline_parse_ctx_t pipeline_cmds[] = {
+ (cmdline_parse_inst_t *) &cmd_fc_add_qinq,
+ (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple,
+ (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple,
+
+ (cmdline_parse_inst_t *) &cmd_fc_del_qinq,
+ (cmdline_parse_inst_t *) &cmd_fc_del_ipv4_5tuple,
+ (cmdline_parse_inst_t *) &cmd_fc_del_ipv6_5tuple,
+
+ (cmdline_parse_inst_t *) &cmd_fc_add_default,
+ (cmdline_parse_inst_t *) &cmd_fc_del_default,
+
+ (cmdline_parse_inst_t *) &cmd_fc_add_qinq_all,
+ (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple_all,
+ (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple_all,
+
+ (cmdline_parse_inst_t *) &cmd_fc_ls,
+ NULL,
+};
+
+static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = {
+ .f_init = app_pipeline_fc_init,
+ .f_free = app_pipeline_fc_free,
+ .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
new file mode 100644
index 0000000..dd67755
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.h
@@ -0,0 +1,106 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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);
+
+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 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);
+
+
+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
new file mode 100644
index 0000000..25ae694
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
@@ -0,0 +1,569 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_table_hash.h>
+#include <rte_byteorder.h>
+
+#include "pipeline_flow_classification_be.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_offset;
+ uint32_t key_size;
+ uint32_t hash_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;
+};
+
+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
+};
+
+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 i;
+
+ 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) {
+ if (n_flows_present)
+ return -1;
+ n_flows_present = 1;
+
+ p->n_flows = atoi(arg_value);
+ if (p->n_flows == 0)
+ return -1;
+
+ continue;
+ }
+
+ /* key_offset */
+ if (strcmp(arg_name, "key_offset") == 0) {
+ if (key_offset_present)
+ return -1;
+ key_offset_present = 1;
+
+ p->key_offset = atoi(arg_value);
+
+ continue;
+ }
+
+ /* key_size */
+ if (strcmp(arg_name, "key_size") == 0) {
+ if (key_size_present)
+ return -1;
+ key_size_present = 1;
+
+ p->key_size = atoi(arg_value);
+ if ((p->key_size == 0) ||
+ (p->key_size > PIPELINE_FC_FLOW_KEY_MAX_SIZE) ||
+ (p->key_size % 8))
+ return -1;
+
+ continue;
+ }
+
+ /* hash_offset */
+ if (strcmp(arg_name, "hash_offset") == 0) {
+ if (hash_offset_present)
+ return -1;
+ hash_offset_present = 1;
+
+ p->hash_offset = atoi(arg_value);
+
+ continue;
+ }
+
+ /* Unknown argument */
+ return -1;
+ }
+
+ /* Check that mandatory arguments are present */
+ if ((n_flows_present == 0) ||
+ (key_offset_present == 0) ||
+ (key_size_present == 0) ||
+ (hash_offset_present == 0))
+ return -1;
+
+ 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,
+ .f_action_bulk = 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_key8_ext_params table_hash_key8_params = {
+ .n_entries = p_fc->n_flows,
+ .n_entries_ext = p_fc->n_flows,
+ .signature_offset = p_fc->hash_offset,
+ .key_offset = p_fc->key_offset,
+ .f_hash = hash_func[(p_fc->key_size / 8) - 1],
+ .seed = 0,
+ };
+
+ struct rte_table_hash_key16_ext_params table_hash_key16_params = {
+ .n_entries = p_fc->n_flows,
+ .n_entries_ext = p_fc->n_flows,
+ .signature_offset = p_fc->hash_offset,
+ .key_offset = p_fc->key_offset,
+ .f_hash = hash_func[(p_fc->key_size / 8) - 1],
+ .seed = 0,
+ };
+
+ struct rte_table_hash_ext_params table_hash_params = {
+ .key_size = p_fc->key_size,
+ .n_keys = p_fc->n_flows,
+ .n_buckets = p_fc->n_flows / 4,
+ .n_buckets_ext = p_fc->n_flows / 4,
+ .f_hash = hash_func[(p_fc->key_size / 8) - 1],
+ .seed = 0,
+ .signature_offset = p_fc->hash_offset,
+ .key_offset = p_fc->key_offset,
+ };
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = NULL, /* set below */
+ .arg_create = NULL, /* set below */
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .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_lru_ops;
+ table_params.arg_create = &table_hash_key8_params;
+ break;
+
+ case 16:
+ table_params.ops = &rte_table_hash_key16_ext_ops;
+ table_params.arg_create = &table_hash_key16_params;
+ 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_track(void *pipeline,
+ __rte_unused uint32_t port_in,
+ uint32_t *port_out)
+{
+ struct pipeline *p = (struct pipeline *) pipeline;
+
+ /* Check input arguments */
+ if ((p == NULL) ||
+ (port_in >= p->n_ports_in) ||
+ (port_out == NULL))
+ return -1;
+
+ if (p->n_ports_in == 1) {
+ *port_out = 0;
+ return 0;
+ }
+
+ return -1;
+}
+
+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]},
+ },
+ };
+
+ 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]},
+ },
+ };
+
+ 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]},
+ },
+ };
+
+ 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,
+ .f_track = pipeline_fc_track,
+};
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h
new file mode 100644
index 0000000..46403d5
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h
@@ -0,0 +1,140 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-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.
+ */
+
+#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;
+};
+
+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;
+};
+
+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
--
1.7.9.5
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
` (10 preceding siblings ...)
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 11/11] ip_pipeline: added new implementation of flow classification pipeline Maciej Gajdzica
@ 2015-06-25 12:19 ` Dumitrescu, Cristian
11 siblings, 0 replies; 13+ messages in thread
From: Dumitrescu, Cristian @ 2015-06-25 12:19 UTC (permalink / raw)
To: Gajdzica, MaciejX T, dev
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Maciej Gajdzica
> Sent: Thursday, June 25, 2015 12:15 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application
> enhancements
>
> This patchset enhances functionality of ip_pipeline application. New config
> file syntax is introduced, so parser is changed. Changed structure of the
> application. Now every global variable is stored in app_struct in app.h.
> Syntax of pipeline cli commands was changed. Implementation of cli
> commands
> for every pipeline is moved to the separate file.
>
> Changes in v2:
> - renamed some files
> - added more config files
> - reworked flow classification pipeline implementation
> - fixed some bugs
>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2015-06-25 12:21 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-25 11:15 [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 01/11] ip_pipeline: add parsing for config files with new syntax Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 02/11] ip_pipeline: added config checks Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 03/11] ip_pipeline: modified init to match new params struct Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 04/11] ip_pipeline: moved pipelines to separate folder Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 05/11] ip_pipeline: added master pipeline Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 06/11] ip_pipeline: added application thread Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 07/11] ip_pipeline: moved config files to separate folder Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 08/11] ip_pipeline: added new implementation of passthrough pipeline Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 09/11] ip_pipeline: added new implementation of firewall pipeline Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 10/11] ip_pipeline: added new implementation of routing pipeline Maciej Gajdzica
2015-06-25 11:15 ` [dpdk-dev] [PATCH v2 11/11] ip_pipeline: added new implementation of flow classification pipeline Maciej Gajdzica
2015-06-25 12:19 ` [dpdk-dev] [PATCH v2 00/11] ip_pipeline: ip_pipeline application enhancements Dumitrescu, Cristian
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).