aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile3
-rw-r--r--examples/distributor/main.c36
-rw-r--r--examples/dpdk_qat/main.c2
-rw-r--r--examples/ethtool/ethtool-app/ethapp.c1
-rw-r--r--examples/ethtool/lib/Makefile4
-rw-r--r--examples/ethtool/lib/rte_ethtool.c12
-rw-r--r--examples/exception_path/main.c3
-rw-r--r--examples/ip_fragmentation/main.c6
-rw-r--r--examples/ip_pipeline/Makefile1
-rw-r--r--examples/ip_pipeline/app.h403
-rw-r--r--examples/ip_pipeline/config/action.cfg68
-rw-r--r--examples/ip_pipeline/config/action.sh119
-rw-r--r--examples/ip_pipeline/config/action.txt8
-rw-r--r--examples/ip_pipeline/config/edge_router_downstream.cfg30
-rw-r--r--examples/ip_pipeline/config/edge_router_downstream.sh7
-rw-r--r--examples/ip_pipeline/config/edge_router_upstream.cfg36
-rw-r--r--examples/ip_pipeline/config/edge_router_upstream.sh37
-rw-r--r--examples/ip_pipeline/config/firewall.cfg68
-rw-r--r--examples/ip_pipeline/config/firewall.sh13
-rw-r--r--examples/ip_pipeline/config/firewall.txt9
-rw-r--r--examples/ip_pipeline/config/flow.cfg72
-rw-r--r--examples/ip_pipeline/config/flow.sh25
-rw-r--r--examples/ip_pipeline/config/flow.txt17
-rw-r--r--examples/ip_pipeline/config/kni.cfg67
-rw-r--r--examples/ip_pipeline/config/l2fwd.cfg5
-rw-r--r--examples/ip_pipeline/config/l3fwd.cfg9
-rw-r--r--examples/ip_pipeline/config/l3fwd.sh32
-rw-r--r--examples/ip_pipeline/config/l3fwd_arp.cfg70
-rw-r--r--examples/ip_pipeline/config/l3fwd_arp.sh43
-rw-r--r--examples/ip_pipeline/config/network_layers.cfg223
-rw-r--r--examples/ip_pipeline/config/network_layers.sh79
-rwxr-xr-xexamples/ip_pipeline/config/pipeline-to-core-mapping.py936
-rw-r--r--examples/ip_pipeline/config_check.c58
-rw-r--r--examples/ip_pipeline/config_parse.c1448
-rw-r--r--examples/ip_pipeline/init.c302
-rw-r--r--examples/ip_pipeline/parser.c745
-rw-r--r--examples/ip_pipeline/parser.h54
-rw-r--r--examples/ip_pipeline/pipeline.h11
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_common_fe.c640
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_common_fe.h26
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_firewall.c1463
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_firewall.h12
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_firewall_be.c28
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_flow_actions.c1507
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_flow_actions.h11
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c22
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_flow_classification.c2084
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_flow_classification.h28
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c22
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_master.c2
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_master_be.c22
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_passthrough.c27
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_passthrough_be.c39
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_routing.c1845
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_routing.h7
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_routing_be.c102
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_routing_be.h16
-rw-r--r--examples/ip_pipeline/pipeline_be.h51
-rw-r--r--examples/ip_pipeline/thread_fe.c39
-rw-r--r--examples/ip_reassembly/main.c6
-rw-r--r--examples/ipsec-secgw/Makefile8
-rw-r--r--examples/ipsec-secgw/esp.c248
-rw-r--r--examples/ipsec-secgw/esp.h9
-rw-r--r--examples/ipsec-secgw/ipip.h149
-rw-r--r--examples/ipsec-secgw/ipsec-secgw.c338
-rw-r--r--examples/ipsec-secgw/ipsec.c60
-rw-r--r--examples/ipsec-secgw/ipsec.h75
-rw-r--r--examples/ipsec-secgw/rt.c229
-rw-r--r--examples/ipsec-secgw/sa.c466
-rw-r--r--examples/ipsec-secgw/sp4.c (renamed from examples/ipsec-secgw/sp.c)171
-rw-r--r--examples/ipsec-secgw/sp6.c448
-rw-r--r--examples/ipv4_multicast/main.c4
-rw-r--r--examples/kni/main.c5
-rw-r--r--examples/l2fwd-crypto/main.c25
-rw-r--r--examples/l2fwd-ivshmem/host/host.c3
-rw-r--r--examples/l2fwd-jobstats/main.c5
-rw-r--r--examples/l2fwd-keepalive/Makefile5
-rw-r--r--examples/l2fwd-keepalive/ka-agent/Makefile49
-rw-r--r--examples/l2fwd-keepalive/ka-agent/main.c150
-rw-r--r--examples/l2fwd-keepalive/main.c25
-rw-r--r--examples/l2fwd-keepalive/shm.c131
-rw-r--r--examples/l2fwd-keepalive/shm.h89
-rw-r--r--examples/l2fwd/main.c26
-rw-r--r--examples/l3fwd-acl/main.c5
-rw-r--r--examples/l3fwd-power/main.c3
-rw-r--r--examples/l3fwd-vf/main.c2
-rw-r--r--examples/l3fwd/l3fwd_em.c2
-rw-r--r--examples/l3fwd/l3fwd_em_hlm_sse.h4
-rw-r--r--examples/l3fwd/main.c2
-rw-r--r--examples/link_status_interrupt/main.c3
-rw-r--r--examples/multi_process/l2fwd_fork/main.c6
-rw-r--r--examples/netmap_compat/lib/compat_netmap.c3
-rw-r--r--examples/packet_ordering/main.c18
-rw-r--r--examples/performance-thread/common/lthread.c2
-rw-r--r--examples/performance-thread/common/lthread_int.h12
-rw-r--r--examples/performance-thread/common/lthread_mutex.c3
-rw-r--r--examples/performance-thread/common/lthread_pool.h4
-rw-r--r--examples/performance-thread/common/lthread_queue.h2
-rw-r--r--examples/performance-thread/common/lthread_sched.c2
-rw-r--r--examples/performance-thread/common/lthread_tls.c4
-rw-r--r--examples/performance-thread/l3fwd-thread/main.c55
-rw-r--r--examples/qos_meter/main.c16
-rw-r--r--examples/qos_meter/main.h2
-rw-r--r--examples/qos_sched/args.c14
-rw-r--r--examples/qos_sched/main.c2
-rw-r--r--examples/qos_sched/main.h5
-rw-r--r--examples/quota_watermark/qw/init.c2
-rw-r--r--examples/quota_watermark/qwctl/qwctl.c2
-rw-r--r--examples/tep_termination/main.c112
-rw-r--r--examples/tep_termination/main.h13
-rw-r--r--examples/tep_termination/vxlan_setup.c20
-rw-r--r--examples/tep_termination/vxlan_setup.h6
-rw-r--r--examples/vhost/main.c2370
-rw-r--r--examples/vhost/main.h70
-rw-r--r--examples/vhost_xen/main.c66
-rw-r--r--examples/vhost_xen/main.h11
-rw-r--r--examples/vm_power_manager/channel_manager.c1
-rw-r--r--examples/vmdq/main.c2
-rw-r--r--examples/vmdq_dcb/main.c2
119 files changed, 9995 insertions, 8632 deletions
diff --git a/examples/Makefile b/examples/Makefile
index b28b30e7..f650d3ec 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,6 +1,6 @@
# BSD LICENSE
#
-# Copyright(c) 2014 6WIND S.A.
+# Copyright(c) 2016 6WIND S.A.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -64,6 +64,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += l2fwd-crypto
DIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += l2fwd-ivshmem
DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += l2fwd-jobstats
DIRS-y += l2fwd-keepalive
+DIRS-y += l2fwd-keepalive/ka-agent
DIRS-$(CONFIG_RTE_LIBRTE_LPM) += l3fwd
DIRS-$(CONFIG_RTE_LIBRTE_ACL) += l3fwd-acl
ifeq ($(CONFIG_RTE_LIBRTE_LPM),y)
diff --git a/examples/distributor/main.c b/examples/distributor/main.c
index c0201a9e..24857f2d 100644
--- a/examples/distributor/main.c
+++ b/examples/distributor/main.c
@@ -52,19 +52,6 @@
#define BURST_SIZE 32
#define RTE_RING_SZ 1024
-/* uncommnet below line to enable debug logs */
-/* #define DEBUG */
-
-#ifdef DEBUG
-#define LOG_LEVEL RTE_LOG_DEBUG
-#define LOG_DEBUG(log_type, fmt, args...) do { \
- RTE_LOG(DEBUG, log_type, fmt, ##args); \
-} while (0)
-#else
-#define LOG_LEVEL RTE_LOG_INFO
-#define LOG_DEBUG(log_type, fmt, args...) do {} while (0)
-#endif
-
#define RTE_LOGTYPE_DISTRAPP RTE_LOGTYPE_USER1
/* mask of enabled ports */
@@ -178,19 +165,25 @@ struct lcore_params {
struct rte_mempool *mem_pool;
};
-static void
+static int
quit_workers(struct rte_distributor *d, struct rte_mempool *p)
{
const unsigned num_workers = rte_lcore_count() - 2;
unsigned i;
struct rte_mbuf *bufs[num_workers];
- rte_mempool_get_bulk(p, (void *)bufs, num_workers);
+
+ if (rte_mempool_get_bulk(p, (void *)bufs, num_workers) != 0) {
+ printf("line %d: Error getting mbufs from pool\n", __LINE__);
+ return -1;
+ }
for (i = 0; i < num_workers; i++)
bufs[i]->hash.rss = i << 1;
rte_distributor_process(d, bufs, num_workers);
rte_mempool_put_bulk(p, (void *)bufs, num_workers);
+
+ return 0;
}
static int
@@ -240,7 +233,8 @@ lcore_rx(struct lcore_params *p)
uint16_t sent = rte_ring_enqueue_burst(r, (void *)bufs, nb_ret);
app_stats.rx.enqueued_pkts += sent;
if (unlikely(sent < nb_ret)) {
- LOG_DEBUG(DISTRAPP, "%s:Packet loss due to full ring\n", __func__);
+ RTE_LOG(DEBUG, DISTRAPP,
+ "%s:Packet loss due to full ring\n", __func__);
while (sent < nb_ret)
rte_pktmbuf_free(bufs[sent++]);
}
@@ -258,7 +252,8 @@ lcore_rx(struct lcore_params *p)
* get packets till quit_signal is actually been
* received and they gracefully shutdown
*/
- quit_workers(d, mem_pool);
+ if (quit_workers(d, mem_pool) != 0)
+ return -1;
/* rx thread should quit at last */
return 0;
}
@@ -271,7 +266,8 @@ flush_one_port(struct output_buffer *outbuf, uint8_t outp)
app_stats.tx.tx_pkts += nb_tx;
if (unlikely(nb_tx < outbuf->count)) {
- LOG_DEBUG(DISTRAPP, "%s:Packet loss with tx_burst\n", __func__);
+ RTE_LOG(DEBUG, DISTRAPP,
+ "%s:Packet loss with tx_burst\n", __func__);
do {
rte_pktmbuf_free(outbuf->mbufs[nb_tx]);
} while (++nb_tx < outbuf->count);
@@ -588,7 +584,9 @@ main(int argc, char *argv[])
}
/* call lcore_main on master core only */
struct lcore_params p = { 0, d, output_ring, mbuf_pool};
- lcore_rx(&p);
+
+ if (lcore_rx(&p) != 0)
+ return -1;
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
if (rte_eal_wait_lcore(lcore_id) < 0)
diff --git a/examples/dpdk_qat/main.c b/examples/dpdk_qat/main.c
index dc68989a..3c6112d7 100644
--- a/examples/dpdk_qat/main.c
+++ b/examples/dpdk_qat/main.c
@@ -661,8 +661,6 @@ main(int argc, char **argv)
return -1;
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
if (check_port_config(nb_ports) < 0)
rte_panic("check_port_config failed\n");
diff --git a/examples/ethtool/ethtool-app/ethapp.c b/examples/ethtool/ethtool-app/ethapp.c
index 2ed4796d..38e466c0 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -535,7 +535,6 @@ static void pcmd_portstats_callback(__rte_unused void *ptr_params,
}
stat = rte_ethtool_net_get_stats64(params->port, &stat_info);
if (stat == 0) {
- /* Most of rte_eth_stats is deprecated.. */
printf("Port %i stats\n", params->port);
printf(" In: %" PRIu64 " (%" PRIu64 " bytes)\n"
" Out: %"PRIu64" (%"PRIu64 " bytes)\n"
diff --git a/examples/ethtool/lib/Makefile b/examples/ethtool/lib/Makefile
index d7ee9555..5b4991e2 100644
--- a/examples/ethtool/lib/Makefile
+++ b/examples/ethtool/lib/Makefile
@@ -54,4 +54,8 @@ SRCS-y := rte_ethtool.c
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
+# internal dependencies
+DEPDIRS-y += lib/librte_eal
+DEPDIRS-y += lib/librte_ether
+
include $(RTE_SDK)/mk/rte.extlib.mk
diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c
index 42e05f1f..54391f21 100644
--- a/examples/ethtool/lib/rte_ethtool.c
+++ b/examples/ethtool/lib/rte_ethtool.c
@@ -51,8 +51,7 @@ rte_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo)
if (drvinfo == NULL)
return -EINVAL;
- if (!rte_eth_dev_is_valid_port(port_id))
- return -ENODEV;
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(port_id, &dev_info);
@@ -120,8 +119,7 @@ rte_ethtool_get_link(uint8_t port_id)
{
struct rte_eth_link link;
- if (!rte_eth_dev_is_valid_port(port_id))
- return -ENODEV;
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
rte_eth_link_get(port_id, &link);
return link.link_status;
}
@@ -267,8 +265,7 @@ rte_ethtool_net_open(uint8_t port_id)
int
rte_ethtool_net_stop(uint8_t port_id)
{
- if (!rte_eth_dev_is_valid_port(port_id))
- return -ENODEV;
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
rte_eth_dev_stop(port_id);
return 0;
@@ -277,8 +274,7 @@ rte_ethtool_net_stop(uint8_t port_id)
int
rte_ethtool_net_get_mac_addr(uint8_t port_id, struct ether_addr *addr)
{
- if (!rte_eth_dev_is_valid_port(port_id))
- return -ENODEV;
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
if (addr == NULL)
return -EINVAL;
rte_eth_macaddr_get(port_id, addr);
diff --git a/examples/exception_path/main.c b/examples/exception_path/main.c
index bec98040..e5eedcc1 100644
--- a/examples/exception_path/main.c
+++ b/examples/exception_path/main.c
@@ -350,8 +350,7 @@ setup_port_lcore_affinities(void)
}
port_ids[i] = rx_port++;
- }
- else if (output_cores_mask & (1ULL << i)) {
+ } else if (output_cores_mask & (1ULL << (i & 0x3f))) {
/* Skip ports that are not enabled */
while ((ports_mask & (1 << tx_port)) == 0) {
tx_port++;
diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c
index 81a49187..2f452648 100644
--- a/examples/ip_fragmentation/main.c
+++ b/examples/ip_fragmentation/main.c
@@ -785,7 +785,7 @@ init_mem(void)
RTE_LOG(INFO, IP_FRAG, "Creating LPM6 table on socket %i\n", socket);
snprintf(buf, sizeof(buf), "IP_FRAG_LPM_%i", socket);
- lpm6 = rte_lpm6_create("IP_FRAG_LPM6", socket, &lpm6_config);
+ lpm6 = rte_lpm6_create(buf, socket, &lpm6_config);
if (lpm6 == NULL) {
RTE_LOG(ERR, IP_FRAG, "Cannot create LPM table\n");
return -1;
@@ -824,9 +824,7 @@ main(int argc, char **argv)
rte_exit(EXIT_FAILURE, "Invalid arguments");
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
- else if (nb_ports == 0)
+ if (nb_ports == 0)
rte_exit(EXIT_FAILURE, "No ports found!\n");
nb_lcores = rte_lcore_count();
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index 10fe1ba9..58271173 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -50,6 +50,7 @@ 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
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += parser.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
diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h
index 55a98417..6a6fdd97 100644
--- a/examples/ip_pipeline/app.h
+++ b/examples/ip_pipeline/app.h
@@ -44,12 +44,24 @@
#include <cmdline_parse.h>
#include <rte_ethdev.h>
+#ifdef RTE_LIBRTE_KNI
+#include <rte_kni.h>
+#endif
#include "cpu_core_map.h"
#include "pipeline.h"
#define APP_PARAM_NAME_SIZE PIPELINE_NAME_SIZE
#define APP_LINK_PCI_BDF_SIZE 16
+
+#ifndef APP_LINK_MAX_HWQ_IN
+#define APP_LINK_MAX_HWQ_IN 128
+#endif
+
+#ifndef APP_LINK_MAX_HWQ_OUT
+#define APP_LINK_MAX_HWQ_OUT 128
+#endif
+
struct app_mempool_params {
char *name;
uint32_t parsed;
@@ -69,6 +81,12 @@ struct app_link_params {
uint32_t tcp_local_q; /* 0 = Disabled (pkts go to default queue 0) */
uint32_t udp_local_q; /* 0 = Disabled (pkts go to default queue 0) */
uint32_t sctp_local_q; /* 0 = Disabled (pkts go to default queue 0) */
+ uint32_t rss_qs[APP_LINK_MAX_HWQ_IN];
+ uint32_t n_rss_qs;
+ uint64_t rss_proto_ipv4;
+ uint64_t rss_proto_ipv6;
+ uint64_t rss_proto_l2;
+ uint32_t promisc;
uint32_t state; /* DOWN = 0, UP = 1 */
uint32_t ip; /* 0 = Invalid */
uint32_t depth; /* Valid only when IP is valid */
@@ -76,7 +94,6 @@ struct app_link_params {
char pci_bdf[APP_LINK_PCI_BDF_SIZE];
struct rte_eth_conf conf;
- uint8_t promisc;
};
struct app_pktq_hwq_in_params {
@@ -118,6 +135,22 @@ struct app_pktq_swq_params {
uint32_t mempool_indirect_id;
};
+struct app_pktq_kni_params {
+ char *name;
+ uint32_t parsed;
+
+ uint32_t socket_id;
+ uint32_t core_id;
+ uint32_t hyper_th_id;
+ uint32_t force_bind;
+
+ uint32_t mempool_id; /* Position in the app->mempool_params */
+ uint32_t burst_read;
+ uint32_t burst_write;
+ uint32_t dropless;
+ uint64_t n_retries;
+};
+
#ifndef APP_FILE_NAME_SIZE
#define APP_FILE_NAME_SIZE 256
#endif
@@ -171,6 +204,7 @@ enum app_pktq_in_type {
APP_PKTQ_IN_HWQ,
APP_PKTQ_IN_SWQ,
APP_PKTQ_IN_TM,
+ APP_PKTQ_IN_KNI,
APP_PKTQ_IN_SOURCE,
};
@@ -183,6 +217,7 @@ enum app_pktq_out_type {
APP_PKTQ_OUT_HWQ,
APP_PKTQ_OUT_SWQ,
APP_PKTQ_OUT_TM,
+ APP_PKTQ_OUT_KNI,
APP_PKTQ_OUT_SINK,
};
@@ -191,9 +226,7 @@ struct app_pktq_out_params {
uint32_t id; /* Position in the appropriate app array */
};
-#ifndef APP_PIPELINE_TYPE_SIZE
-#define APP_PIPELINE_TYPE_SIZE 64
-#endif
+#define APP_PIPELINE_TYPE_SIZE PIPELINE_TYPE_SIZE
#define APP_MAX_PIPELINE_PKTQ_IN PIPELINE_MAX_PORT_IN
#define APP_MAX_PIPELINE_PKTQ_OUT PIPELINE_MAX_PORT_OUT
@@ -229,6 +262,22 @@ struct app_pipeline_params {
uint32_t n_args;
};
+struct app_params;
+
+typedef void (*app_link_op)(struct app_params *app,
+ uint32_t link_id,
+ uint32_t up,
+ void *arg);
+
+#ifndef APP_MAX_PIPELINES
+#define APP_MAX_PIPELINES 64
+#endif
+
+struct app_link_data {
+ app_link_op f_link[APP_MAX_PIPELINES];
+ void *arg[APP_MAX_PIPELINES];
+};
+
struct app_pipeline_data {
void *be;
void *fe;
@@ -247,7 +296,7 @@ struct app_thread_pipeline_data {
};
#ifndef APP_MAX_THREAD_PIPELINES
-#define APP_MAX_THREAD_PIPELINES 16
+#define APP_MAX_THREAD_PIPELINES 64
#endif
#ifndef APP_THREAD_TIMER_PERIOD
@@ -272,7 +321,7 @@ struct app_thread_data {
uint64_t headroom_time;
uint64_t headroom_cycles;
double headroom_ratio;
-};
+} __rte_cache_aligned;
#ifndef APP_MAX_LINKS
#define APP_MAX_LINKS 16
@@ -370,6 +419,8 @@ struct app_eal_params {
/* Support running on Xen dom0 without hugetlbfs */
uint32_t xen_dom0_present;
int xen_dom0;
+
+ uint32_t parsed;
};
#ifndef APP_APPNAME_SIZE
@@ -380,17 +431,9 @@ struct app_eal_params {
#define APP_MAX_MEMPOOLS 8
#endif
-#ifndef APP_LINK_MAX_HWQ_IN
-#define APP_LINK_MAX_HWQ_IN 64
-#endif
+#define APP_MAX_HWQ_IN (APP_MAX_LINKS * APP_LINK_MAX_HWQ_IN)
-#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)
+#define APP_MAX_HWQ_OUT (APP_MAX_LINKS * APP_LINK_MAX_HWQ_OUT)
#ifndef APP_MAX_PKTQ_SWQ
#define APP_MAX_PKTQ_SWQ 256
@@ -398,24 +441,22 @@ struct app_eal_params {
#define APP_MAX_PKTQ_TM APP_MAX_LINKS
+#define APP_MAX_PKTQ_KNI APP_MAX_LINKS
+
#ifndef APP_MAX_PKTQ_SOURCE
-#define APP_MAX_PKTQ_SOURCE 16
+#define APP_MAX_PKTQ_SOURCE 64
#endif
#ifndef APP_MAX_PKTQ_SINK
-#define APP_MAX_PKTQ_SINK 16
+#define APP_MAX_PKTQ_SINK 64
#endif
#ifndef APP_MAX_MSGQ
-#define APP_MAX_MSGQ 64
-#endif
-
-#ifndef APP_MAX_PIPELINES
-#define APP_MAX_PIPELINES 64
+#define APP_MAX_MSGQ 256
#endif
#ifndef APP_EAL_ARGC
-#define APP_EAL_ARGC 32
+#define APP_EAL_ARGC 64
#endif
#ifndef APP_MAX_PIPELINE_TYPES
@@ -453,6 +494,7 @@ struct app_params {
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_kni_params kni_params[APP_MAX_PKTQ_KNI];
struct app_pktq_source_params source_params[APP_MAX_PKTQ_SOURCE];
struct app_pktq_sink_params sink_params[APP_MAX_PKTQ_SINK];
struct app_msgq_params msgq_params[APP_MAX_MSGQ];
@@ -464,6 +506,7 @@ struct app_params {
uint32_t n_pktq_hwq_out;
uint32_t n_pktq_swq;
uint32_t n_pktq_tm;
+ uint32_t n_pktq_kni;
uint32_t n_pktq_source;
uint32_t n_pktq_sink;
uint32_t n_msgq;
@@ -474,8 +517,12 @@ struct app_params {
struct cpu_core_map *core_map;
uint64_t core_mask;
struct rte_mempool *mempool[APP_MAX_MEMPOOLS];
+ struct app_link_data link_data[APP_MAX_LINKS];
struct rte_ring *swq[APP_MAX_PKTQ_SWQ];
struct rte_sched_port *tm[APP_MAX_PKTQ_TM];
+#ifdef RTE_LIBRTE_KNI
+ struct rte_kni *kni[APP_MAX_PKTQ_KNI];
+#endif /* RTE_LIBRTE_KNI */
struct rte_ring *msgq[APP_MAX_MSGQ];
struct pipeline_type pipeline_type[APP_MAX_PIPELINE_TYPES];
struct app_pipeline_data pipeline_data[APP_MAX_PIPELINES];
@@ -529,28 +576,6 @@ do \
sscanf(obj->name, prefix "%" SCNu32, &id); \
while (0) \
-#define APP_PARAM_ADD(obj_array, obj_name) \
-({ \
- ssize_t obj_idx; \
- 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) { \
- (obj_array)[obj_idx].name = strdup(obj_name); \
- if ((obj_array)[obj_idx].name == NULL) \
- obj_idx = -EINVAL; \
- } else \
- obj_idx = -ENOMEM; \
- } \
- obj_idx; \
-})
-
#define APP_CHECK(exp, fmt, ...) \
do { \
if (!(exp)) { \
@@ -665,6 +690,41 @@ app_swq_get_readers(struct app_params *app, struct app_pktq_swq_params *swq)
return n_readers;
}
+static inline struct app_pipeline_params *
+app_swq_get_reader(struct app_params *app,
+ struct app_pktq_swq_params *swq,
+ uint32_t *pktq_in_id)
+{
+ struct app_pipeline_params *reader = NULL;
+ uint32_t pos = swq - app->swq_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_readers = 0, id = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_in; j++) {
+ struct app_pktq_in_params *pktq = &p->pktq_in[j];
+
+ if ((pktq->type == APP_PKTQ_IN_SWQ) &&
+ (pktq->id == pos)) {
+ n_readers++;
+ reader = p;
+ id = j;
+ }
+ }
+ }
+
+ if (n_readers != 1)
+ return NULL;
+
+ *pktq_in_id = id;
+ return reader;
+}
+
static inline uint32_t
app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm)
{
@@ -690,6 +750,101 @@ app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm)
return n_readers;
}
+static inline struct app_pipeline_params *
+app_tm_get_reader(struct app_params *app,
+ struct app_pktq_tm_params *tm,
+ uint32_t *pktq_in_id)
+{
+ struct app_pipeline_params *reader = NULL;
+ uint32_t pos = tm - app->tm_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_readers = 0, id = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_in; j++) {
+ struct app_pktq_in_params *pktq = &p->pktq_in[j];
+
+ if ((pktq->type == APP_PKTQ_IN_TM) &&
+ (pktq->id == pos)) {
+ n_readers++;
+ reader = p;
+ id = j;
+ }
+ }
+ }
+
+ if (n_readers != 1)
+ return NULL;
+
+ *pktq_in_id = id;
+ return reader;
+}
+
+static inline uint32_t
+app_kni_get_readers(struct app_params *app, struct app_pktq_kni_params *kni)
+{
+ uint32_t pos = kni - app->kni_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_readers = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_in; j++) {
+ struct app_pktq_in_params *pktq = &p->pktq_in[j];
+
+ if ((pktq->type == APP_PKTQ_IN_KNI) &&
+ (pktq->id == pos))
+ n_readers++;
+ }
+ }
+
+ return n_readers;
+}
+
+static inline struct app_pipeline_params *
+app_kni_get_reader(struct app_params *app,
+ struct app_pktq_kni_params *kni,
+ uint32_t *pktq_in_id)
+{
+ struct app_pipeline_params *reader = NULL;
+ uint32_t pos = kni - app->kni_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_readers = 0, id = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_in; j++) {
+ struct app_pktq_in_params *pktq = &p->pktq_in[j];
+
+ if ((pktq->type == APP_PKTQ_IN_KNI) &&
+ (pktq->id == pos)) {
+ n_readers++;
+ reader = p;
+ id = j;
+ }
+ }
+ }
+
+ if (n_readers != 1)
+ return NULL;
+
+ *pktq_in_id = id;
+ return reader;
+}
+
static inline uint32_t
app_source_get_readers(struct app_params *app,
struct app_pktq_source_params *source)
@@ -789,6 +944,42 @@ app_swq_get_writers(struct app_params *app, struct app_pktq_swq_params *swq)
return n_writers;
}
+static inline struct app_pipeline_params *
+app_swq_get_writer(struct app_params *app,
+ struct app_pktq_swq_params *swq,
+ uint32_t *pktq_out_id)
+{
+ struct app_pipeline_params *writer = NULL;
+ uint32_t pos = swq - app->swq_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_writers = 0, id = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
+ RTE_DIM(p->pktq_out));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_out; j++) {
+ struct app_pktq_out_params *pktq = &p->pktq_out[j];
+
+ if ((pktq->type == APP_PKTQ_OUT_SWQ) &&
+ (pktq->id == pos)) {
+ n_writers++;
+ writer = p;
+ id = j;
+ }
+ }
+ }
+
+ if (n_writers != 1)
+ return NULL;
+
+ *pktq_out_id = id;
+ return writer;
+}
+
static inline uint32_t
app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm)
{
@@ -815,6 +1006,104 @@ app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm)
return n_writers;
}
+static inline struct app_pipeline_params *
+app_tm_get_writer(struct app_params *app,
+ struct app_pktq_tm_params *tm,
+ uint32_t *pktq_out_id)
+{
+ struct app_pipeline_params *writer = NULL;
+ uint32_t pos = tm - app->tm_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_writers = 0, id = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
+ RTE_DIM(p->pktq_out));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_out; j++) {
+ struct app_pktq_out_params *pktq = &p->pktq_out[j];
+
+ if ((pktq->type == APP_PKTQ_OUT_TM) &&
+ (pktq->id == pos)) {
+ n_writers++;
+ writer = p;
+ id = j;
+ }
+ }
+ }
+
+ if (n_writers != 1)
+ return NULL;
+
+ *pktq_out_id = id;
+ return writer;
+}
+
+static inline uint32_t
+app_kni_get_writers(struct app_params *app, struct app_pktq_kni_params *kni)
+{
+ uint32_t pos = kni - app->kni_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_writers = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
+ RTE_DIM(p->pktq_out));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_out; j++) {
+ struct app_pktq_out_params *pktq = &p->pktq_out[j];
+
+ if ((pktq->type == APP_PKTQ_OUT_KNI) &&
+ (pktq->id == pos))
+ n_writers++;
+ }
+ }
+
+ return n_writers;
+}
+
+static inline struct app_pipeline_params *
+app_kni_get_writer(struct app_params *app,
+ struct app_pktq_kni_params *kni,
+ uint32_t *pktq_out_id)
+{
+ struct app_pipeline_params *writer = NULL;
+ uint32_t pos = kni - app->kni_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_writers = 0, id = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
+ RTE_DIM(p->pktq_out));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_out; j++) {
+ struct app_pktq_out_params *pktq = &p->pktq_out[j];
+
+ if ((pktq->type == APP_PKTQ_OUT_KNI) &&
+ (pktq->id == pos)) {
+ n_writers++;
+ writer = p;
+ id = j;
+ }
+ }
+ }
+
+ if (n_writers != 1)
+ return NULL;
+
+ *pktq_out_id = id;
+ return writer;
+}
+
static inline uint32_t
app_sink_get_writers(struct app_params *app, struct app_pktq_sink_params *sink)
{
@@ -913,6 +1202,26 @@ app_get_link_for_tm(struct app_params *app, struct app_pktq_tm_params *p_tm)
return &app->link_params[link_param_idx];
}
+static inline struct app_link_params *
+app_get_link_for_kni(struct app_params *app, struct app_pktq_kni_params *p_kni)
+{
+ char link_name[APP_PARAM_NAME_SIZE];
+ uint32_t link_id;
+ ssize_t link_param_idx;
+
+ sscanf(p_kni->name, "KNI%" PRIu32, &link_id);
+ sprintf(link_name, "LINK%" PRIu32, link_id);
+ link_param_idx = APP_PARAM_FIND(app->link_params, link_name);
+ APP_CHECK((link_param_idx >= 0),
+ "Cannot find %s for %s", link_name, p_kni->name);
+
+ return &app->link_params[link_param_idx];
+}
+
+void app_pipeline_params_get(struct app_params *app,
+ struct app_pipeline_params *p_in,
+ struct pipeline_params *p_out);
+
int app_config_init(struct app_params *app);
int app_config_args(struct app_params *app,
@@ -932,6 +1241,8 @@ int app_config_check(struct app_params *app);
int app_init(struct app_params *app);
+int app_post_init(struct app_params *app);
+
int app_thread(void *arg);
int app_pipeline_type_register(struct app_params *app,
diff --git a/examples/ip_pipeline/config/action.cfg b/examples/ip_pipeline/config/action.cfg
new file mode 100644
index 00000000..994ae94a
--- /dev/null
+++ b/examples/ip_pipeline/config/action.cfg
@@ -0,0 +1,68 @@
+; BSD LICENSE
+;
+; Copyright(c) 2016 Intel Corporation. All rights reserved.
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+; ________________
+; RXQ0.0 --->| |---> TXQ0.0
+; | |
+; RXQ1.0 --->| |---> TXQ1.0
+; | Flow |
+; RXQ2.0 --->| Actions |---> TXQ2.0
+; | |
+; RXQ3.0 --->| |---> TXQ3.0
+; |________________|
+;
+;
+; Input packet: Ethernet/IPv4
+;
+; Packet buffer layout:
+; # Field Name Offset (Bytes) Size (Bytes)
+; 0 Mbuf 0 128
+; 1 Headroom 128 128
+; 2 Ethernet header 256 14
+; 3 IPv4 header 270 20
+
+[EAL]
+log_level = 0
+
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = FLOW_ACTIONS
+core = 1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0
+n_flows = 65536
+n_meters_per_flow = 4
+flow_id_offset = 286; ipdaddr
+ip_hdr_offset = 270
+color_offset = 128
diff --git a/examples/ip_pipeline/config/action.sh b/examples/ip_pipeline/config/action.sh
new file mode 100644
index 00000000..2986ae60
--- /dev/null
+++ b/examples/ip_pipeline/config/action.sh
@@ -0,0 +1,119 @@
+#
+# run ./config/action.sh
+#
+
+p 1 action flow 0 meter 0 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 0 policer 0 g G y Y r R
+p 1 action flow 0 meter 1 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 0 policer 1 g G y Y r R
+p 1 action flow 0 meter 2 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 0 policer 2 g G y Y r R
+p 1 action flow 0 meter 3 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 0 policer 3 g G y Y r R
+p 1 action flow 0 port 0
+
+p 1 action flow 1 meter 0 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 1 policer 0 g G y Y r R
+p 1 action flow 1 meter 1 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 1 policer 1 g G y Y r R
+p 1 action flow 1 meter 2 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 1 policer 2 g G y Y r R
+p 1 action flow 1 meter 3 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 1 policer 3 g G y Y r R
+p 1 action flow 1 port 1
+
+p 1 action flow 2 meter 0 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 2 policer 0 g G y Y r R
+p 1 action flow 2 meter 1 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 2 policer 1 g G y Y r R
+p 1 action flow 2 meter 2 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 2 policer 2 g G y Y r R
+p 1 action flow 2 meter 3 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 2 policer 3 g G y Y r R
+p 1 action flow 2 port 2
+
+p 1 action flow 3 meter 0 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 3 policer 0 g G y Y r R
+p 1 action flow 3 meter 1 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 3 policer 1 g G y Y r R
+p 1 action flow 3 meter 2 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 3 policer 2 g G y Y r R
+p 1 action flow 3 meter 3 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 3 policer 3 g G y Y r R
+p 1 action flow 3 port 3
+
+#p 1 action flow bulk ./config/action.txt
+
+#p 1 action flow ls
+
+p 1 action flow 0 stats
+p 1 action flow 1 stats
+p 1 action flow 2 stats
+p 1 action flow 3 stats
+
+p 1 action dscp 0 class 0 color G
+p 1 action dscp 1 class 1 color G
+p 1 action dscp 2 class 2 color G
+p 1 action dscp 3 class 3 color G
+p 1 action dscp 4 class 0 color G
+p 1 action dscp 5 class 1 color G
+p 1 action dscp 6 class 2 color G
+p 1 action dscp 7 class 3 color G
+p 1 action dscp 8 class 0 color G
+p 1 action dscp 9 class 1 color G
+p 1 action dscp 10 class 2 color G
+p 1 action dscp 11 class 3 color G
+p 1 action dscp 12 class 0 color G
+p 1 action dscp 13 class 1 color G
+p 1 action dscp 14 class 2 color G
+p 1 action dscp 15 class 3 color G
+p 1 action dscp 16 class 0 color G
+p 1 action dscp 17 class 1 color G
+p 1 action dscp 18 class 2 color G
+p 1 action dscp 19 class 3 color G
+p 1 action dscp 20 class 0 color G
+p 1 action dscp 21 class 1 color G
+p 1 action dscp 22 class 2 color G
+p 1 action dscp 23 class 3 color G
+p 1 action dscp 24 class 0 color G
+p 1 action dscp 25 class 1 color G
+p 1 action dscp 26 class 2 color G
+p 1 action dscp 27 class 3 color G
+p 1 action dscp 27 class 0 color G
+p 1 action dscp 29 class 1 color G
+p 1 action dscp 30 class 2 color G
+p 1 action dscp 31 class 3 color G
+p 1 action dscp 32 class 0 color G
+p 1 action dscp 33 class 1 color G
+p 1 action dscp 34 class 2 color G
+p 1 action dscp 35 class 3 color G
+p 1 action dscp 36 class 0 color G
+p 1 action dscp 37 class 1 color G
+p 1 action dscp 38 class 2 color G
+p 1 action dscp 39 class 3 color G
+p 1 action dscp 40 class 0 color G
+p 1 action dscp 41 class 1 color G
+p 1 action dscp 42 class 2 color G
+p 1 action dscp 43 class 3 color G
+p 1 action dscp 44 class 0 color G
+p 1 action dscp 45 class 1 color G
+p 1 action dscp 46 class 2 color G
+p 1 action dscp 47 class 3 color G
+p 1 action dscp 48 class 0 color G
+p 1 action dscp 49 class 1 color G
+p 1 action dscp 50 class 2 color G
+p 1 action dscp 51 class 3 color G
+p 1 action dscp 52 class 0 color G
+p 1 action dscp 53 class 1 color G
+p 1 action dscp 54 class 2 color G
+p 1 action dscp 55 class 3 color G
+p 1 action dscp 56 class 0 color G
+p 1 action dscp 57 class 1 color G
+p 1 action dscp 58 class 2 color G
+p 1 action dscp 59 class 3 color G
+p 1 action dscp 60 class 0 color G
+p 1 action dscp 61 class 1 color G
+p 1 action dscp 62 class 2 color G
+p 1 action dscp 63 class 3 color G
+
+p 1 action dscp ls
diff --git a/examples/ip_pipeline/config/action.txt b/examples/ip_pipeline/config/action.txt
new file mode 100644
index 00000000..f14207b9
--- /dev/null
+++ b/examples/ip_pipeline/config/action.txt
@@ -0,0 +1,8 @@
+#
+# p <pipelineid> action flow bulk ./config/action.txt
+#
+
+flow 0 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 0
+flow 1 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 1
+flow 2 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 2
+flow 3 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 3
diff --git a/examples/ip_pipeline/config/edge_router_downstream.cfg b/examples/ip_pipeline/config/edge_router_downstream.cfg
index 85bbab8f..c6b4e1f2 100644
--- a/examples/ip_pipeline/config/edge_router_downstream.cfg
+++ b/examples/ip_pipeline/config/edge_router_downstream.cfg
@@ -1,6 +1,6 @@
; BSD LICENSE
;
-; Copyright(c) 2015 Intel Corporation. All rights reserved.
+; Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
@@ -36,9 +36,9 @@
; network) contains the following functional blocks: Packet RX & Routing,
; Traffic management and Packet TX. The input packets are assumed to be
; IPv4, while the output packets are Q-in-Q IPv4.
-
+;
; A simple implementation for this functional pipeline is presented below.
-
+;
; Packet Rx & Traffic Management Packet Tx
; Routing (Pass-Through) (Pass-Through)
; _____________________ SWQ0 ______________________ SWQ4 _____________________
@@ -50,11 +50,23 @@
; | | SWQ3 | | SWQ7 | |
; RXQ3.0 --->| |----->| |----->| |---> TXQ3.0
; |_____________________| |______________________| |_____________________|
-; | _|_ ^ _|_ ^ _|_ ^ _|_ ^
-; | |___|||___|||___|||___||
-; +--> SINK0 |___|||___|||___|||___||
-; (route miss) |__| |__| |__| |__|
-; TM0 TM1 TM2 TM3
+; | | ^ | ^ | ^ | ^
+; | |__| |__| |__| |__|
+; +--> SINK0 TM0 TM1 TM2 TM3
+; (Default)
+;
+; Input packet: Ethernet/IPv4
+; Output packet: Ethernet/QinQ/IPv4
+;
+; Packet buffer layout:
+; # Field Name Offset (Bytes) Size (Bytes)
+; 0 Mbuf 0 128
+; 1 Headroom 128 128
+; 2 Ethernet header 256 14
+; 3 IPv4 header 270 20
+
+[EAL]
+log_level = 0
[PIPELINE0]
type = MASTER
@@ -67,7 +79,7 @@ pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
pktq_out = SWQ0 SWQ1 SWQ2 SWQ3 SINK0
encap = ethernet_qinq
qinq_sched = test
-ip_hdr_offset = 270; mbuf (128) + headroom (128) + ethernet header (14) = 270
+ip_hdr_offset = 270
[PIPELINE2]
type = PASS-THROUGH
diff --git a/examples/ip_pipeline/config/edge_router_downstream.sh b/examples/ip_pipeline/config/edge_router_downstream.sh
index ce46beb5..67c3a0d1 100644
--- a/examples/ip_pipeline/config/edge_router_downstream.sh
+++ b/examples/ip_pipeline/config/edge_router_downstream.sh
@@ -1,3 +1,7 @@
+#
+# run ./config/edge_router_downstream.sh
+#
+
################################################################################
# Routing: Ether QinQ, ARP off
################################################################################
@@ -6,5 +10,4 @@ p 1 route add 0.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 qinq 256 257
p 1 route add 0.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 qinq 258 259
p 1 route add 0.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 qinq 260 261
p 1 route add 0.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 qinq 262 263
-
-p 1 route ls
+#p 1 route ls
diff --git a/examples/ip_pipeline/config/edge_router_upstream.cfg b/examples/ip_pipeline/config/edge_router_upstream.cfg
index a08c5cce..dea42b95 100644
--- a/examples/ip_pipeline/config/edge_router_upstream.cfg
+++ b/examples/ip_pipeline/config/edge_router_upstream.cfg
@@ -1,6 +1,6 @@
; BSD LICENSE
;
-; Copyright(c) 2015 Intel Corporation. All rights reserved.
+; Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
; An edge router typically sits between two networks such as the provider
; core network and the provider access network. A typical packet processing
; pipeline for the upstream traffic (i.e. traffic from access to core
@@ -36,10 +37,10 @@
; Flow classification, Metering, Routing and Packet TX. The input packets
; are assumed to be Q-in-Q IPv4, while the output packets are MPLS IPv4
; (with variable number of labels per route).
-
+;
; A simple implementation for this functional pipeline is presented below.
-
-; Packet Rx & Pass-Through Flow-Classification Flow-Actions Routing
+;
+; Packet RX & Pass-Through Flow Classification Flow Actions Routing
: Firewall
; __________ SWQ0 __________ SWQ4 __________ SWQ8 __________ SWQ12 __________
; RXQ0.0 --->| |------>| |------>| |------>| |------>| |------> TXQ0.0
@@ -51,8 +52,21 @@
; RXQ3.0 --->| |------>| |------>| |------>| |------>| |------> TXQ3.0
; |__________| |__________| |__________| |__________| |__________|
; | | |
-; +--> SINK0 (Default) +--> SINK1 (Default) +--> SINK2 (Route Miss)
+; +--> SINK0 (Default) +--> SINK1 (Default) +--> SINK2 (Default)
+;
+; Input packet: Ethernet/QinQ/IPv4
+; Output packet: Ethernet/MPLS/IPv4
+;
+; Packet buffer layout:
+; # Field Name Offset (Bytes) Size (Bytes)
+; 0 Mbuf 0 128
+; 1 Headroom 128 128
+; 2 Ethernet header 256 14
+; 3 QinQ header 270 8
+; 4 IPv4 header 278 20
+[EAL]
+log_level = 0
[PIPELINE0]
type = MASTER
@@ -72,10 +86,10 @@ core = 2
pktq_in = SWQ0 SWQ1 SWQ2 SWQ3
pktq_out = SWQ4 SWQ5 SWQ6 SWQ7
dma_size = 8
-dma_dst_offset = 128; mbuf (128)
-dma_src_offset = 268; mbuf (128) + headroom (128) + 1st ethertype offset (12) = 268
+dma_dst_offset = 128
+dma_src_offset = 268; 1st Ethertype offset
dma_src_mask = 00000FFF00000FFF; qinq
-dma_hash_offset = 136; dma_dst_offset + dma_size = 136
+dma_hash_offset = 136; dma_dst_offset + dma_size
[PIPELINE3]
type = FLOW_CLASSIFICATION
@@ -86,7 +100,7 @@ n_flows = 65536
key_size = 8; dma_size
key_offset = 128; dma_dst_offset
hash_offset = 136; dma_hash_offset
-flowid_offset = 192; mbuf (128) + 64
+flowid_offset = 192
[PIPELINE4]
type = FLOW_ACTIONS
@@ -96,7 +110,7 @@ pktq_out = SWQ12 SWQ13 SWQ14 SWQ15
n_flows = 65536
n_meters_per_flow = 1
flow_id_offset = 192; flowid_offset
-ip_hdr_offset = 278; mbuf (128) + headroom (128) + ethernet (14) + qinq (8) = 278
+ip_hdr_offset = 278
color_offset = 196; flowid_offset + sizeof(flow_id)
[PIPELINE5]
@@ -106,5 +120,5 @@ pktq_in = SWQ12 SWQ13 SWQ14 SWQ15
pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK2
encap = ethernet_mpls
mpls_color_mark = yes
-ip_hdr_offset = 278; mbuf (128) + headroom (128) + ethernet (14) + qinq (8) = 278
+ip_hdr_offset = 278
color_offset = 196; flowid_offset + sizeof(flow_id)
diff --git a/examples/ip_pipeline/config/edge_router_upstream.sh b/examples/ip_pipeline/config/edge_router_upstream.sh
index eeba600c..5d574c1a 100644
--- a/examples/ip_pipeline/config/edge_router_upstream.sh
+++ b/examples/ip_pipeline/config/edge_router_upstream.sh
@@ -1,24 +1,26 @@
-################################################
-# Firewall Rules:4 for 4 ports
-################################################
-p 1 firewall add ipv4 1 0.0.0.0 8 0.0.0.0 10 0 0 0 0 6 1 0
-p 1 firewall add ipv4 1 0.0.0.0 8 0.64.0.0 10 0 0 0 0 6 1 1
-p 1 firewall add ipv4 1 0.0.0.0 8 0.128.0.0 10 0 0 0 0 6 1 2
-p 1 firewall add ipv4 1 0.0.0.0 8 0.192.0.0 10 0 0 0 0 6 1 3
-p 1 firewall add default 4 #SINK0
+#
+# run ./config/edge_router_upstream.sh
+#
+################################################################################
+# Firewall
+################################################################################
+p 1 firewall add default 4 #SINK0
+p 1 firewall add bulk ./config/edge_router_upstream_firewall.txt
+#p 1 firewall ls
################################################################################
-# Flow classification
+# Flow Classification
################################################################################
p 3 flow add default 4 #SINK1
-p 3 flow add qinq all 65536 4
+p 3 flow add qinq bulk ./config/edge_router_upstream_flow.txt
+#p 3 flow ls
################################################################################
-# Flow Actions - Metering
+# Flow Actions - Metering and Policing
################################################################################
-p 4 flows 65536 meter 0 trtcm 1250000000 1250000000 100000000 100000000
-p 4 flows 65536 ports 4
+p 4 action flow bulk ./config/edge_router_upstream_action.txt
+#p 4 action flow ls
################################################################################
# Routing: Ether MPLS, ARP off
@@ -28,11 +30,4 @@ p 5 route add 0.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 mpls 0:1
p 5 route add 0.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 mpls 10:11
p 5 route add 0.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 mpls 20:21
p 5 route add 0.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 mpls 30:31
-
-################################################################################
-# List all configurations
-################################################################################
-p 1 firewall ls
-#p 3 flow ls
-#p 4 flow actions ls
-p 5 route ls
+#p 5 route ls
diff --git a/examples/ip_pipeline/config/firewall.cfg b/examples/ip_pipeline/config/firewall.cfg
new file mode 100644
index 00000000..2f5dd9f6
--- /dev/null
+++ b/examples/ip_pipeline/config/firewall.cfg
@@ -0,0 +1,68 @@
+; BSD LICENSE
+;
+; Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+; _______________
+; RXQ0.0 --->| |---> TXQ0.0
+; | |
+; RXQ1.0 --->| |---> TXQ1.0
+; | Firewall |
+; RXQ2.0 --->| |---> TXQ2.0
+; | |
+; RXQ3.0 --->| |---> TXQ3.0
+; |_______________|
+; |
+; +-----------> SINK0 (default rule)
+;
+; Input packet: Ethernet/IPv4
+;
+; Packet buffer layout:
+; # Field Name Offset (Bytes) Size (Bytes)
+; 0 Mbuf 0 128
+; 1 Headroom 128 128
+; 2 Ethernet header 256 14
+; 3 IPv4 header 270 20
+
+[EAL]
+log_level = 0
+
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = FIREWALL
+core = 1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0
+n_rules = 4096
+pkt_type = ipv4
+;pkt_type = vlan_ipv4
+;pkt_type = qinq_ipv4
diff --git a/examples/ip_pipeline/config/firewall.sh b/examples/ip_pipeline/config/firewall.sh
new file mode 100644
index 00000000..c83857ee
--- /dev/null
+++ b/examples/ip_pipeline/config/firewall.sh
@@ -0,0 +1,13 @@
+#
+# run ./config/firewall.sh
+#
+
+p 1 firewall add default 4 #SINK0
+p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.0.0.0 10 0 65535 0 65535 6 0xF port 0
+p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.64.0.0 10 0 65535 0 65535 6 0xF port 1
+p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.128.0.0 10 0 65535 0 65535 6 0xF port 2
+p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.192.0.0 10 0 65535 0 65535 6 0xF port 3
+
+#p 1 firewall add bulk ./config/firewall.txt
+
+p 1 firewall ls
diff --git a/examples/ip_pipeline/config/firewall.txt b/examples/ip_pipeline/config/firewall.txt
new file mode 100644
index 00000000..54cfffda
--- /dev/null
+++ b/examples/ip_pipeline/config/firewall.txt
@@ -0,0 +1,9 @@
+#
+# p <pipelineid> firewall add bulk ./config/firewall.txt
+# p <pipelineid> firewall del bulk ./config/firewall.txt
+#
+
+priority 1 ipv4 0.0.0.0 0 100.0.0.0 10 0 65535 0 65535 6 0xF port 0
+priority 1 ipv4 0.0.0.0 0 100.64.0.0 10 0 65535 0 65535 6 0xF port 1
+priority 1 ipv4 0.0.0.0 0 100.128.0.0 10 0 65535 0 65535 6 0xF port 2
+priority 1 ipv4 0.0.0.0 0 100.192.0.0 10 0 65535 0 65535 6 0xF port 3
diff --git a/examples/ip_pipeline/config/flow.cfg b/examples/ip_pipeline/config/flow.cfg
new file mode 100644
index 00000000..6895d393
--- /dev/null
+++ b/examples/ip_pipeline/config/flow.cfg
@@ -0,0 +1,72 @@
+; BSD LICENSE
+;
+; Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+; ________________
+; RXQ0.0 --->| |---> TXQ0.0
+; | |
+; RXQ1.0 --->| |---> TXQ1.0
+; | Flow |
+; RXQ2.0 --->| Classification |---> TXQ2.0
+; | |
+; RXQ3.0 --->| |---> TXQ3.0
+; |________________|
+; |
+; +-----------> SINK0 (flow lookup miss)
+;
+; Input packet: Ethernet/IPv4
+;
+; Packet buffer layout:
+; # Field Name Offset (Bytes) Size (Bytes)
+; 0 Mbuf 0 128
+; 1 Headroom 128 128
+; 2 Ethernet header 256 14
+; 3 QinQ/IPv4/IPv6 header 270 8/20/40
+
+[EAL]
+log_level = 0
+
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = FLOW_CLASSIFICATION
+core = 1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0
+n_flows = 65536
+;key_size = 8 ; QinQ key size
+;key_offset = 270 ; QinQ key offset
+;key_mask = 0000FFF00000FFF0 ; QinQ key mask
+key_size = 16 ; IPv4 5-tuple key size
+key_offset = 278 ; IPv4 5-tuple key offset
+key_mask = 00FF0000FFFFFFFFFFFFFFFFFFFFFFFF ; IPv4 5-tuple key mask
+flowid_offset = 128
diff --git a/examples/ip_pipeline/config/flow.sh b/examples/ip_pipeline/config/flow.sh
new file mode 100644
index 00000000..489c7079
--- /dev/null
+++ b/examples/ip_pipeline/config/flow.sh
@@ -0,0 +1,25 @@
+#
+# run ./config/flow.sh
+#
+
+################################################################################
+# Flow classification (QinQ)
+################################################################################
+#p 1 flow add default 4 #SINK0
+#p 1 flow add qinq 100 200 port 0 id 0
+#p 1 flow add qinq 101 201 port 1 id 1
+#p 1 flow add qinq 102 202 port 2 id 2
+#p 1 flow add qinq 103 203 port 3 id 3
+
+#p 1 flow add qinq bulk ./config/flow.txt
+
+################################################################################
+# Flow classification (IPv4 5-tuple)
+################################################################################
+p 1 flow add default 4 #SINK0
+p 1 flow add ipv4 100.0.0.10 200.0.0.10 100 200 6 port 0 id 0
+p 1 flow add ipv4 100.0.0.11 200.0.0.11 101 201 6 port 1 id 1
+p 1 flow add ipv4 100.0.0.12 200.0.0.12 102 202 6 port 2 id 2
+p 1 flow add ipv4 100.0.0.13 200.0.0.13 103 203 6 port 3 id 3
+
+#p 1 flow add ipv4 bulk ./config/flow.txt
diff --git a/examples/ip_pipeline/config/flow.txt b/examples/ip_pipeline/config/flow.txt
new file mode 100644
index 00000000..c1a141dd
--- /dev/null
+++ b/examples/ip_pipeline/config/flow.txt
@@ -0,0 +1,17 @@
+#
+# p <pipelineid> flow add qinq bulk ./config/flow.txt
+#
+
+#qinq 100 200 port 0 id 0
+#qinq 101 201 port 1 id 1
+#qinq 102 202 port 2 id 2
+#qinq 103 203 port 3 id 3
+
+#
+# p <pipelineid> flow add ipv4 bulk ./config/flow.txt
+#
+
+ipv4 100.0.0.10 200.0.0.10 100 200 6 port 0 id 0
+ipv4 100.0.0.11 200.0.0.11 101 201 6 port 1 id 1
+ipv4 100.0.0.12 200.0.0.12 102 202 6 port 2 id 2
+ipv4 100.0.0.13 200.0.0.13 103 203 6 port 3 id 3
diff --git a/examples/ip_pipeline/config/kni.cfg b/examples/ip_pipeline/config/kni.cfg
new file mode 100644
index 00000000..cea208b4
--- /dev/null
+++ b/examples/ip_pipeline/config/kni.cfg
@@ -0,0 +1,67 @@
+; BSD LICENSE
+;
+; Copyright(c) 2016 Intel Corporation.
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+; ______________ ______________________
+; | | KNI0 | |
+; RXQ0.0 --->| |------->|--+ |
+; | | KNI1 | | br0 |
+; TXQ1.0 <---| |<-------|<-+ |
+; | Pass-through | | Linux Kernel |
+; | (P1) | | Network Stack |
+; | | KNI1 | |
+; RXQ1.0 --->| |------->|--+ |
+; | | KNI0 | | br0 |
+; TXQ0.0 <---| |<-------|<-+ |
+; |______________| |______________________|
+;
+; Insert Linux kernel KNI module:
+; [Linux]$ insmod rte_kni.ko
+;
+; Configure Linux kernel bridge between KNI0 and KNI1 interfaces:
+; [Linux]$ ifconfig KNI0 up
+; [Linux]$ ifconfig KNI1 up
+; [Linux]$ brctl addbr "br0"
+; [Linux]$ brctl addif br0 KNI0
+; [Linux]$ brctl addif br0 KNI1
+; [Linux]$ ifconfig br0 up
+
+[EAL]
+log_level = 0
+
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = PASS-THROUGH
+core = 1
+pktq_in = RXQ0.0 KNI1 RXQ1.0 KNI0
+pktq_out = KNI0 TXQ1.0 KNI1 TXQ0.0
diff --git a/examples/ip_pipeline/config/l2fwd.cfg b/examples/ip_pipeline/config/l2fwd.cfg
index c743a143..a1df9e6a 100644
--- a/examples/ip_pipeline/config/l2fwd.cfg
+++ b/examples/ip_pipeline/config/l2fwd.cfg
@@ -1,6 +1,6 @@
; BSD LICENSE
;
-; Copyright(c) 2015 Intel Corporation. All rights reserved.
+; Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
@@ -44,6 +44,9 @@
; |________________|
;
+[EAL]
+log_level = 0
+
[PIPELINE0]
type = MASTER
core = 0
diff --git a/examples/ip_pipeline/config/l3fwd.cfg b/examples/ip_pipeline/config/l3fwd.cfg
index 5449dc32..02c8f36f 100644
--- a/examples/ip_pipeline/config/l3fwd.cfg
+++ b/examples/ip_pipeline/config/l3fwd.cfg
@@ -1,6 +1,6 @@
; BSD LICENSE
;
-; Copyright(c) 2015 Intel Corporation. All rights reserved.
+; Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,9 @@
; 2 Ethernet header 256 14
; 3 IPv4 header 270 20
+[EAL]
+log_level = 0
+
[PIPELINE0]
type = MASTER
core = 0
@@ -59,5 +62,7 @@ type = ROUTING
core = 1
pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0
-encap = ethernet; encap = ethernet / ethernet_qinq / ethernet_mpls
+encap = ethernet
+;encap = ethernet_qinq
+;encap = ethernet_mpls
ip_hdr_offset = 270
diff --git a/examples/ip_pipeline/config/l3fwd.sh b/examples/ip_pipeline/config/l3fwd.sh
index 27740103..47406aa4 100644
--- a/examples/ip_pipeline/config/l3fwd.sh
+++ b/examples/ip_pipeline/config/l3fwd.sh
@@ -1,9 +1,33 @@
+#
+# run ./config/l3fwd.sh
+#
+
################################################################################
# Routing: encap = ethernet, arp = off
################################################################################
p 1 route add default 4 #SINK0
-p 1 route add 0.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0
-p 1 route add 0.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1
-p 1 route add 0.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2
-p 1 route add 0.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3
+p 1 route add 100.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0
+p 1 route add 100.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1
+p 1 route add 100.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2
+p 1 route add 100.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3
p 1 route ls
+
+################################################################################
+# Routing: encap = ethernet_qinq, arp = off
+################################################################################
+#p 1 route add default 4 #SINK0
+#p 1 route add 100.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 qinq 1000 2000
+#p 1 route add 100.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 qinq 1001 2001
+#p 1 route add 100.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 qinq 1002 2002
+#p 1 route add 100.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 qinq 1003 2003
+#p 1 route ls
+
+################################################################################
+# Routing: encap = ethernet_mpls, arp = off
+################################################################################
+#p 1 route add default 4 #SINK0
+#p 1 route add 100.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 mpls 1000:2000
+#p 1 route add 100.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 mpls 1001:2001
+#p 1 route add 100.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 mpls 1002:2002
+#p 1 route add 100.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 mpls 1003:2003
+#p 1 route ls
diff --git a/examples/ip_pipeline/config/l3fwd_arp.cfg b/examples/ip_pipeline/config/l3fwd_arp.cfg
new file mode 100644
index 00000000..2c63c8fd
--- /dev/null
+++ b/examples/ip_pipeline/config/l3fwd_arp.cfg
@@ -0,0 +1,70 @@
+; BSD LICENSE
+;
+; Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+; _______________
+; RXQ0.0 --->| |---> TXQ0.0
+; | |
+; RXQ1.0 --->| |---> TXQ1.0
+; | Routing |
+; RXQ2.0 --->| |---> TXQ2.0
+; | |
+; RXQ3.0 --->| |---> TXQ3.0
+; |_______________|
+; |
+; +-----------> SINK0 (route miss)
+;
+; Input packet: Ethernet/IPv4
+;
+; Packet buffer layout:
+; # Field Name Offset (Bytes) Size (Bytes)
+; 0 Mbuf 0 128
+; 1 Headroom 128 128
+; 2 Ethernet header 256 14
+; 3 IPv4 header 270 20
+
+[EAL]
+log_level = 0
+
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = ROUTING
+core = 1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0
+encap = ethernet
+;encap = ethernet_qinq
+;encap = ethernet_mpls
+n_arp_entries = 1024
+ip_hdr_offset = 270
+arp_key_offset = 128
diff --git a/examples/ip_pipeline/config/l3fwd_arp.sh b/examples/ip_pipeline/config/l3fwd_arp.sh
new file mode 100644
index 00000000..20bea582
--- /dev/null
+++ b/examples/ip_pipeline/config/l3fwd_arp.sh
@@ -0,0 +1,43 @@
+#
+# run ./config/l3fwd_arp.sh
+#
+
+################################################################################
+# ARP
+################################################################################
+p 1 arp add default 4 #SINK0
+p 1 arp add 0 10.0.0.1 a0:b0:c0:d0:e0:f0
+p 1 arp add 1 11.0.0.1 a1:b1:c1:d1:e1:f1
+p 1 arp add 2 12.0.0.1 a2:b2:c2:d2:e2:f2
+p 1 arp add 3 13.0.0.1 a3:b3:c3:d3:e3:f3
+p 1 arp ls
+
+################################################################################
+# Routing: encap = ethernet, arp = on
+################################################################################
+p 1 route add default 4 #SINK0
+p 1 route add 100.0.0.0 10 port 0 ether 10.0.0.1
+p 1 route add 100.64.0.0 10 port 1 ether 11.0.0.1
+p 1 route add 100.128.0.0 10 port 2 ether 12.0.0.1
+p 1 route add 100.192.0.0 10 port 3 ether 13.0.0.1
+p 1 route ls
+
+################################################################################
+# Routing: encap = ethernet_qinq, arp = on
+################################################################################
+#p 1 route add default 4 #SINK0
+#p 1 route add 100.0.0.0 10 port 0 ether 10.0.0.1 qinq 1000 2000
+#p 1 route add 100.64.0.0 10 port 1 ether 11.0.0.1 qinq 1001 2001
+#p 1 route add 100.128.0.0 10 port 2 ether 12.0.0.1 qinq 1002 2002
+#p 1 route add 100.192.0.0 10 port 3 ether 13.0.0.1 qinq 1003 2003
+#p 1 route ls
+
+################################################################################
+# Routing: encap = ethernet_mpls, arp = on
+################################################################################
+#p 1 route add default 4 #SINK0
+#p 1 route add 100.0.0.0 10 port 0 ether 10.0.0.1 mpls 1000:2000
+#p 1 route add 100.64.0.0 10 port 1 ether 11.0.0.1 mpls 1001:2001
+#p 1 route add 100.128.0.0 10 port 2 ether 12.0.0.1 mpls 1002:2002
+#p 1 route add 100.192.0.0 10 port 3 ether 13.0.0.1 mpls 1003:2003
+#p 1 route ls
diff --git a/examples/ip_pipeline/config/network_layers.cfg b/examples/ip_pipeline/config/network_layers.cfg
new file mode 100644
index 00000000..8054d9fe
--- /dev/null
+++ b/examples/ip_pipeline/config/network_layers.cfg
@@ -0,0 +1,223 @@
+; BSD LICENSE
+;
+; Copyright(c) 2016 Intel Corporation. All rights reserved.
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+; The diagram below shows how additional protocol components can be plugged into
+; the IP layer implemented by the ip_pipeline application. Pick your favorite
+; open source components for dynamic ARP, ICMP, UDP or TCP termination, etc and
+; connect them through SWQs to the IP infrastructure.
+;
+; The input packets with local destination are sent to the UDP/TCP applications
+; while the input packets with remote destination are routed back to the
+; network. Additional features can easily be added to this setup:
+; * IP Reassembly: add SWQs with IP reassembly enabled (typically required for
+; the input traffic with local destination);
+; * IP Fragmentation: add SWQs with IP fragmentation enabled (typically
+; required to enforce the MTU for the routed output traffic);
+; * Traffic Metering: add Flow Action pipeline instances (e.g. for metering the
+; TCP connections or ICMP input traffic);
+; * Traffic Management: add TMs for the required output LINKs;
+; * Protocol encapsulations (QinQ, MPLS) for the output packets: part of the
+; routing pipeline configuration.
+;
+; _________ _________
+; | | | |
+; | UDP | | TCP |
+; | App | | App |
+; |_________| |_________|
+; ^ | ^ |
+; __|___V__ __|___V__
+; | | SWQ0 (UDP TX) | | SWQ1 (TCP TX)
+; | UDP |-------+ | TCP |------------+
+; | | | | | |
+; |_________| | |_________| |
+; ^ | ^ |
+; | SWQ2 | | SWQ3 |
+; | (UDP RX) | | (TCP RX) |
+; ____|____ | ____|____ |
+; | | | | | |
+; RXQ<0..3>.1 ------>|Firewall +--->| | +------>| Flow +--->| |
+; (UDP local dest) | (P2) | SINK0 | | | (P3) | SINK1 |
+; |_________| (Deny)| | |_________| (RST) |
+; RXQ<0..3>.2 -------------------------|-----+ |
+; (TCP local dest) | |
+; | +------------------------------+
+; | |
+; _V_____V_
+; | |
+; | Routing | TXQ<0..3>.0
+; RXQ<0..3>.0 ---------------------->| & ARP +----------------------------->
+; (IP remote dest) | (P1) |
+; |_________|
+; | ^ |
+; SWQ4 +-------------+ | | SWQ5 (ARP miss)
+; (Route miss) | | +------------+
+; | +-------------+ |
+; ___V__|__ SWQ6 ____V____
+; | | (ICMP TX) | | TXQ<0..3>.1
+; RXQ<0..3>.3 ------>| ICMP | +------>| Dyn ARP +------------->
+; (IP local dest) | | | | |
+; |_________| | |_________|
+; RXQ<0..3>.4 -------------------------------+
+; (ARP)
+;
+; This configuration file implements the diagram presented below, where the
+; dynamic ARP, ICMP, UDP and TCP components have been stubbed out and replaced
+; with loop-back and packet drop devices.
+;
+; _________ _________
+; | | SWQ0 (UDP TX) | | SWQ1 (TCP TX)
+; |Loobpack |-------+ |Loopback |------------+
+; | (P4) | | | (P5) | |
+; |_________| | |_________| |
+; ^ | ^ |
+; | SWQ2 | | SWQ3 |
+; | (UDP RX) | | (TCP RX) |
+; ____|____ | ____|____ |
+; | | | | | |
+; RXQ<0..3>.1 ------>|Firewall +--->| | +------>| Flow +--->| |
+; (UDP local dest) | (P2) | SINK0 | | | (P3) | SINK1 |
+; |_________| (Deny)| | |_________| (RST) |
+; RXQ<0..3>.2 -------------------------|-----+ |
+; (TCP local dest) | |
+; | +------------------------------+
+; | |
+; _V_____V_
+; | |
+; | Routing | TXQ<0..3>.0
+; RXQ<0..3>.0 ---------------------->| & ARP +----------------------------->
+; (IP remote dest) | (P1) |
+; |_________|
+; | |
+; SINK2 |<---+ +--->| SINK3
+; (Route miss) (ARP miss)
+;
+; _________ _________
+; | | | |
+; RXQ<0..3>.3 ------>| Drop +--->| SINK<4..7> +------>| Drop +--->| SINK<8..11>
+; (IP local dest) | (P6) | (IP local dest) | | (P7) | (ARP)
+; |_________| | |_________|
+; RXQ<0..3>.4 ------------------------------------+
+; (ARP)
+;
+;
+; Input packet: Ethernet/IPv4 or Ethernet/ARP
+; Output packet: Ethernet/IPv4 or Ethernet/ARP
+;
+; Packet buffer layout (for input IPv4 packets):
+; # Field Name Offset (Bytes) Size (Bytes)
+; 0 Mbuf 0 128
+; 1 Headroom 128 128
+; 2 Ethernet header 256 14
+; 3 IPv4 header 270 20
+; 4 ICMP/UDP/TCP header 290 8/8/20
+
+[EAL]
+log_level = 0
+
+[LINK0]
+udp_local_q = 1
+tcp_local_q = 2
+ip_local_q = 3
+arp_q = 4
+
+[LINK1]
+udp_local_q = 1
+tcp_local_q = 2
+ip_local_q = 3
+arp_q = 4
+
+[LINK2]
+udp_local_q = 1
+tcp_local_q = 2
+ip_local_q = 3
+arp_q = 4
+
+[LINK3]
+udp_local_q = 1
+tcp_local_q = 2
+ip_local_q = 3
+arp_q = 4
+
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = ROUTING
+core = 1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 SWQ0 SWQ1
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK2 SINK3
+port_local_dest = 4 ; SINK2 (Drop)
+n_arp_entries = 1000
+ip_hdr_offset = 270
+arp_key_offset = 128
+
+[PIPELINE2]
+type = FIREWALL
+core = 1
+pktq_in = RXQ0.1 RXQ1.1 RXQ2.1 RXQ3.1
+pktq_out = SWQ2 SINK0
+n_rules = 4096
+
+[PIPELINE3]
+type = FLOW_CLASSIFICATION
+core = 1
+pktq_in = RXQ0.2 RXQ1.2 RXQ2.2 RXQ3.2
+pktq_out = SWQ3 SINK1
+n_flows = 65536
+key_size = 16 ; IPv4 5-tuple key size
+key_offset = 278 ; IPv4 5-tuple key offset
+key_mask = 00FF0000FFFFFFFFFFFFFFFFFFFFFFFF ; IPv4 5-tuple key mask
+flowid_offset = 128 ; Flow ID effectively acts as TCP socket ID
+
+[PIPELINE4]
+type = PASS-THROUGH ; Loop-back (UDP place-holder)
+core = 1
+pktq_in = SWQ2
+pktq_out = SWQ0
+
+[PIPELINE5]
+type = PASS-THROUGH ; Loop-back (TCP place-holder)
+core = 1
+pktq_in = SWQ3
+pktq_out = SWQ1
+
+[PIPELINE6]
+type = PASS-THROUGH ; Drop (ICMP place-holder)
+core = 1
+pktq_in = RXQ0.3 RXQ1.3 RXQ2.3 RXQ3.3
+pktq_out = SINK4 SINK5 SINK6 SINK7
+
+[PIPELINE7]
+type = PASS-THROUGH ; Drop (Dynamic ARP place-holder)
+core = 1
+pktq_in = RXQ0.4 RXQ1.4 RXQ2.4 RXQ3.4
+pktq_out = SINK8 SINK9 SINK10 SINK11
diff --git a/examples/ip_pipeline/config/network_layers.sh b/examples/ip_pipeline/config/network_layers.sh
new file mode 100644
index 00000000..3b86bebd
--- /dev/null
+++ b/examples/ip_pipeline/config/network_layers.sh
@@ -0,0 +1,79 @@
+#
+# run ./config/network_layers.sh
+#
+
+################################################################################
+# Link configuration
+################################################################################
+# Routes added implicitly when links are brought UP:
+# IP Prefix = 10.0.0.1/16 => (Port 0, Local)
+# IP Prefix = 10.0.0.1/32 => (Port 4, Local)
+# IP Prefix = 10.1.0.1/16 => (Port 1, Local)
+# IP Prefix = 10.1.0.1/32 => (Port 4, Local)
+# IP Prefix = 10.2.0.1/16 => (Port 2, Local)
+# IP Prefix = 10.2.0.1/32 => (Port 4, Local)
+# IP Prefix = 10.3.0.1/16 => (Port 3, Local)
+# IP Prefix = 10.3.0.1/32 => (Port 4, Local)
+link 0 down
+link 1 down
+link 2 down
+link 3 down
+link 0 config 10.0.0.1 16
+link 1 config 10.1.0.1 16
+link 2 config 10.2.0.1 16
+link 3 config 10.3.0.1 16
+link 0 up
+link 1 up
+link 2 up
+link 3 up
+#link ls
+
+################################################################################
+# Static ARP
+################################################################################
+p 1 arp add default 5 #SINK3
+p 1 arp add 0 10.0.0.2 a0:b0:c0:d0:e0:f0
+p 1 arp add 1 10.1.0.2 a1:b1:c1:d1:e1:f1
+p 1 arp add 2 10.2.0.2 a2:b2:c2:d2:e2:f2
+p 1 arp add 3 10.3.0.2 a3:b3:c3:d3:e3:f3
+#p 1 arp ls
+
+################################################################################
+# Routes
+################################################################################
+p 1 route add default 4 #SINK2
+p 1 route add 100.0.0.0 16 port 0 ether 10.0.0.2
+p 1 route add 100.1.0.0 16 port 1 ether 10.1.0.2
+p 1 route add 100.2.0.0 16 port 2 ether 10.2.0.2
+p 1 route add 100.3.0.0 16 port 3 ether 10.3.0.2
+#p 1 route ls
+
+################################################################################
+# Local destination UDP traffic
+################################################################################
+# Prio = Lowest: [SA = ANY, DA = ANY, SP = ANY, DP = ANY, PROTO = ANY] => Drop
+# Prio = 1 (High): [SA = ANY, DA = 10.0.0.1, SP = ANY, DP = 1000, PROTO = UDP] => Allow
+# Prio = 1 (High): [SA = ANY, DA = 10.1.0.1, SP = ANY, DP = 1001, PROTO = UDP] => Allow
+# Prio = 1 (High): [SA = ANY, DA = 10.2.0.1, SP = ANY, DP = 1002, PROTO = UDP] => Allow
+# Prio = 1 (High): [SA = ANY, DA = 10.3.0.1, SP = ANY, DP = 1003, PROTO = UDP] => Allow
+p 1 firewall add default 1 #SINK0
+p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.0.0.1 32 0 65535 1000 1000 17 0xF port 0
+p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.1.0.1 32 0 65535 1001 1001 17 0xF port 0
+p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.2.0.1 32 0 65535 1002 1002 17 0xF port 0
+p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.3.0.1 32 0 65535 1003 1003 17 0xF port 0
+#p 2 firewall ls
+
+################################################################################
+# Local destination TCP traffic
+################################################################################
+# Unknown connection => Drop
+# TCP [SA = 100.0.0.10, DA = 10.0.0.1, SP = 1000, DP = 80] => socket ID = 0
+# TCP [SA = 100.1.0.10, DA = 10.1.0.1, SP = 1001, DP = 80] => socket ID = 1
+# TCP [SA = 100.2.0.10, DA = 10.2.0.1, SP = 1002, DP = 80] => socket ID = 2
+# TCP [SA = 100.3.0.10, DA = 10.3.0.1, SP = 1003, DP = 80] => socket ID = 3
+p 3 flow add default 1 #SINK1
+p 3 flow add ipv4 100.0.0.10 10.0.0.1 1000 80 6 port 1 id 0
+p 3 flow add ipv4 100.1.0.10 10.1.0.1 1001 80 6 port 1 id 1
+p 3 flow add ipv4 100.2.0.10 10.2.0.1 1002 80 6 port 1 id 2
+p 3 flow add ipv4 100.3.0.10 10.3.0.1 1003 80 6 port 1 id 3
+#p 3 flow ls
diff --git a/examples/ip_pipeline/config/pipeline-to-core-mapping.py b/examples/ip_pipeline/config/pipeline-to-core-mapping.py
new file mode 100755
index 00000000..37b131c6
--- /dev/null
+++ b/examples/ip_pipeline/config/pipeline-to-core-mapping.py
@@ -0,0 +1,936 @@
+#! /usr/bin/python2
+
+# BSD LICENSE
+#
+# Copyright(c) 2016 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# This script maps the set of pipelines identified (MASTER pipelines are
+# ignored) from the input configuration file to the set of cores
+# provided as input argument and creates configuration files for each of
+# the mapping combinations.
+#
+
+from __future__ import print_function
+import sys
+import errno
+import os
+import re
+import array
+import itertools
+import re
+import argparse
+from collections import namedtuple
+
+# default values
+enable_stage0_traceout = 1
+enable_stage1_traceout = 1
+enable_stage2_traceout = 1
+
+enable_stage1_fileout = 1
+enable_stage2_fileout = 1
+
+Constants = namedtuple('Constants', ['MAX_CORES', 'MAX_PIPELINES'])
+constants = Constants(16, 64)
+
+# pattern for physical core
+pattern_phycore = '^(s|S)\d(c|C)[1-9][0-9]*$'
+reg_phycore = re.compile(pattern_phycore)
+
+
+def popcount(mask):
+ return bin(mask).count("1")
+
+
+def len2mask(length):
+ if (length == 0):
+ return 0
+
+ if (length > 64):
+ sys.exit('error: len2mask - length %i > 64. exiting' % length)
+
+ return int('1' * length, 2)
+
+
+def bitstring_write(n, n_bits):
+ tmpstr = ""
+ if (n_bits > 64):
+ return
+
+ i = n_bits - 1
+ while (i >= 0):
+ cond = (n & (1 << i))
+ if (cond):
+ print('1', end='')
+ tmpstr += '1'
+ else:
+ print('0', end='')
+ tmpstr += '0'
+ i -= 1
+ return tmpstr
+
+
+class Cores0:
+
+ def __init__(self):
+ self.n_pipelines = 0
+
+
+class Cores1:
+
+ def __init__(self):
+ self.pipelines = 0
+ self.n_pipelines = 0
+
+
+class Cores2:
+
+ def __init__(self):
+ self.pipelines = 0
+ self.n_pipelines = 0
+ self.counter = 0
+ self.counter_max = 0
+ self.bitpos = array.array(
+ "L", itertools.repeat(0, constants.MAX_PIPELINES))
+
+
+class Context0:
+
+ def __init__(self):
+ self.cores = [Cores0() for i in range(0, constants.MAX_CORES)]
+ self.n_cores = 0
+ self.n_pipelines = 0
+ self.n_pipelines0 = 0
+ self.pos = 0
+ self.file_comment = ""
+ self.ctx1 = None
+ self.ctx2 = None
+
+ def stage0_print(self):
+ print('printing Context0 obj')
+ print('c0.cores(n_pipelines) = [ ', end='')
+ for cores_count in range(0, constants.MAX_CORES):
+ print(self.cores[cores_count].n_pipelines, end=' ')
+ print(']')
+ print('c0.n_cores = %d' % self.n_cores)
+ print('c0.n_pipelines = %d' % self.n_pipelines)
+ print('c0.n_pipelines0 = %d' % self.n_pipelines0)
+ print('c0.pos = %d' % self.pos)
+ print('c0.file_comment = %s' % self.file_comment)
+ if (self.ctx1 is not None):
+ print('c0.ctx1 = ', end='')
+ print(repr(self.ctx1))
+ else:
+ print('c0.ctx1 = None')
+
+ if (self.ctx2 is not None):
+ print('c0.ctx2 = ', end='')
+ print(repr(self.ctx2))
+ else:
+ print('c0.ctx2 = None')
+
+ def stage0_init(self, num_cores, num_pipelines, ctx1, ctx2):
+ self.n_cores = num_cores
+ self.n_pipelines = num_pipelines
+ self.ctx1 = ctx1
+ self.ctx2 = ctx2
+
+ def stage0_process(self):
+ # stage0 init
+ self.cores[0].n_pipelines = self.n_pipelines
+ self.n_pipelines0 = 0
+ self.pos = 1
+
+ while True:
+ # go forward
+ while True:
+ if ((self.pos < self.n_cores) and (self.n_pipelines0 > 0)):
+ self.cores[self.pos].n_pipelines = min(
+ self.cores[self.pos - 1].n_pipelines,
+ self.n_pipelines0)
+ self.n_pipelines0 -= self.cores[self.pos].n_pipelines
+ self.pos += 1
+ else:
+ break
+
+ # check solution
+ if (self.n_pipelines0 == 0):
+ self.stage0_log()
+ self.ctx1.stage1_init(self, self.ctx2) # self is object c0
+ self.ctx1.stage1_process()
+
+ # go backward
+ while True:
+ if (self.pos == 0):
+ return
+
+ self.pos -= 1
+ if ((self.cores[self.pos].n_pipelines > 1) and
+ (self.pos != (self.n_cores - 1))):
+ break
+
+ self.n_pipelines0 += self.cores[self.pos].n_pipelines
+ self.cores[self.pos].n_pipelines = 0
+
+ # rearm
+ self.cores[self.pos].n_pipelines -= 1
+ self.n_pipelines0 += 1
+ self.pos += 1
+
+ def stage0_log(self):
+ tmp_file_comment = ""
+ if(enable_stage0_traceout != 1):
+ return
+
+ print('STAGE0: ', end='')
+ tmp_file_comment += 'STAGE0: '
+ for cores_count in range(0, self.n_cores):
+ print('C%d = %d\t'
+ % (cores_count,
+ self.cores[cores_count].n_pipelines), end='')
+ tmp_file_comment += "C{} = {}\t".format(
+ cores_count, self.cores[cores_count].n_pipelines)
+ # end for
+ print('')
+ self.ctx1.stage0_file_comment = tmp_file_comment
+ self.ctx2.stage0_file_comment = tmp_file_comment
+
+
+class Context1:
+ _fileTrace = None
+
+ def __init__(self):
+ self.cores = [Cores1() for i in range(constants.MAX_CORES)]
+ self.n_cores = 0
+ self.n_pipelines = 0
+ self.pos = 0
+ self.stage0_file_comment = ""
+ self.stage1_file_comment = ""
+
+ self.ctx2 = None
+ self.arr_pipelines2cores = []
+
+ def stage1_reset(self):
+ for i in range(constants.MAX_CORES):
+ self.cores[i].pipelines = 0
+ self.cores[i].n_pipelines = 0
+
+ self.n_cores = 0
+ self.n_pipelines = 0
+ self.pos = 0
+ self.ctx2 = None
+ # clear list
+ del self.arr_pipelines2cores[:]
+
+ def stage1_print(self):
+ print('printing Context1 obj')
+ print('ctx1.cores(pipelines,n_pipelines) = [ ', end='')
+ for cores_count in range(0, constants.MAX_CORES):
+ print('(%d,%d)' % (self.cores[cores_count].pipelines,
+ self.cores[cores_count].n_pipelines), end=' ')
+ print(']')
+ print('ctx1.n_cores = %d' % self.n_cores)
+ print('ctx1.n_pipelines = %d' % self.n_pipelines)
+ print('ctx1.pos = %d' % self.pos)
+ print('ctx1.stage0_file_comment = %s' % self.stage0_file_comment)
+ print('ctx1.stage1_file_comment = %s' % self.stage1_file_comment)
+ if (self.ctx2 is not None):
+ print('ctx1.ctx2 = ', end='')
+ print(self.ctx2)
+ else:
+ print('ctx1.ctx2 = None')
+
+ def stage1_init(self, c0, ctx2):
+ self.stage1_reset()
+ self.n_cores = 0
+ while (c0.cores[self.n_cores].n_pipelines > 0):
+ self.n_cores += 1
+
+ self.n_pipelines = c0.n_pipelines
+ self.ctx2 = ctx2
+
+ self.arr_pipelines2cores = [0] * self.n_pipelines
+
+ i = 0
+ while (i < self.n_cores):
+ self.cores[i].n_pipelines = c0.cores[i].n_pipelines
+ i += 1
+
+ def stage1_process(self):
+ pipelines_max = len2mask(self.n_pipelines)
+ while True:
+ pos = 0
+ overlap = 0
+
+ if (self.cores[self.pos].pipelines == pipelines_max):
+ if (self.pos == 0):
+ return
+
+ self.cores[self.pos].pipelines = 0
+ self.pos -= 1
+ continue
+
+ self.cores[self.pos].pipelines += 1
+ if (popcount(self.cores[self.pos].pipelines) !=
+ self.cores[self.pos].n_pipelines):
+ continue
+
+ overlap = 0
+ pos = 0
+ while (pos < self.pos):
+ if ((self.cores[self.pos].pipelines) &
+ (self.cores[pos].pipelines)):
+ overlap = 1
+ break
+ pos += 1
+
+ if (overlap):
+ continue
+
+ if ((self.pos > 0) and
+ ((self.cores[self.pos].n_pipelines) ==
+ (self.cores[self.pos - 1].n_pipelines)) and
+ ((self.cores[self.pos].pipelines) <
+ (self.cores[self.pos - 1].pipelines))):
+ continue
+
+ if (self.pos == self.n_cores - 1):
+ self.stage1_log()
+ self.ctx2.stage2_init(self)
+ self.ctx2.stage2_process()
+
+ if (self.pos == 0):
+ return
+
+ self.cores[self.pos].pipelines = 0
+ self.pos -= 1
+ continue
+
+ self.pos += 1
+
+ def stage1_log(self):
+ tmp_file_comment = ""
+ if(enable_stage1_traceout == 1):
+ print('STAGE1: ', end='')
+ tmp_file_comment += 'STAGE1: '
+ i = 0
+ while (i < self.n_cores):
+ print('C%d = [' % i, end='')
+ tmp_file_comment += "C{} = [".format(i)
+
+ j = self.n_pipelines - 1
+ while (j >= 0):
+ cond = ((self.cores[i].pipelines) & (1 << j))
+ if (cond):
+ print('1', end='')
+ tmp_file_comment += '1'
+ else:
+ print('0', end='')
+ tmp_file_comment += '0'
+ j -= 1
+
+ print(']\t', end='')
+ tmp_file_comment += ']\t'
+ i += 1
+
+ print('\n', end='')
+ self.stage1_file_comment = tmp_file_comment
+ self.ctx2.stage1_file_comment = tmp_file_comment
+
+ # check if file traceing is enabled
+ if(enable_stage1_fileout != 1):
+ return
+
+ # spit out the combination to file
+ self.stage1_process_file()
+
+ def stage1_updateCoresInBuf(self, nPipeline, sCore):
+ rePipeline = self._fileTrace.arr_pipelines[nPipeline]
+ rePipeline = rePipeline.replace("[", "\[").replace("]", "\]")
+ reCore = 'core\s*=\s*((\d*)|(((s|S)\d)?(c|C)[1-9][0-9]*)).*\n'
+ sSubs = 'core = ' + sCore + '\n'
+
+ reg_pipeline = re.compile(rePipeline)
+ search_match = reg_pipeline.search(self._fileTrace.in_buf)
+
+ if(search_match):
+ pos = search_match.start()
+ substr1 = self._fileTrace.in_buf[:pos]
+ substr2 = self._fileTrace.in_buf[pos:]
+ substr2 = re.sub(reCore, sSubs, substr2, 1)
+ self._fileTrace.in_buf = substr1 + substr2
+
+ def stage1_process_file(self):
+ outFileName = os.path.join(self._fileTrace.out_path,
+ self._fileTrace.prefix_outfile)
+ outFileName += "_{}CoReS".format(self.n_cores)
+
+ i = 0 # represents core number
+ while (i < self.n_cores):
+ j = self.n_pipelines - 1
+ pipeline_idx = 0
+ while(j >= 0):
+ cond = ((self.cores[i].pipelines) & (1 << j))
+ if (cond):
+ # update the pipelines array to match the core
+ # only in case of cond match
+ self.arr_pipelines2cores[
+ pipeline_idx] = fileTrace.in_physical_cores[i]
+
+ j -= 1
+ pipeline_idx += 1
+
+ i += 1
+
+ # update the in_buf as per the arr_pipelines2cores
+ for pipeline_idx in range(len(self.arr_pipelines2cores)):
+ outFileName += "_{}".format(self.arr_pipelines2cores[pipeline_idx])
+ self.stage1_updateCoresInBuf(
+ pipeline_idx, self.arr_pipelines2cores[pipeline_idx])
+
+ # by now the in_buf is all set to be written to file
+ outFileName += self._fileTrace.suffix_outfile
+ outputFile = open(outFileName, "w")
+
+ # write out the comments
+ strTruncated = ("", "(Truncated)")[self._fileTrace.ncores_truncated]
+ outputFile.write(
+ "; =============== Pipeline-to-Core Mapping ================\n"
+ "; Generated from file {}\n"
+ "; Input pipelines = {}\n"
+ "; Input cores = {}\n"
+ "; N_PIPELINES = {} N_CORES = {} {} hyper_thread = {}\n"
+ .format(
+ self._fileTrace.in_file_namepath,
+ fileTrace.arr_pipelines,
+ fileTrace.in_physical_cores,
+ self._fileTrace.n_pipelines,
+ self._fileTrace.n_cores,
+ strTruncated,
+ self._fileTrace.hyper_thread))
+
+ outputFile.write(
+ "; {stg0cmt}\n"
+ "; {stg1cmt}\n"
+ "; ========================================================\n"
+ "; \n"
+ .format(
+ stg0cmt=self.stage0_file_comment,
+ stg1cmt=self.stage1_file_comment))
+
+ # write buffer contents
+ outputFile.write(self._fileTrace.in_buf)
+ outputFile.flush()
+ outputFile.close()
+
+
+class Context2:
+ _fileTrace = None
+
+ def __init__(self):
+ self.cores = [Cores2() for i in range(constants.MAX_CORES)]
+ self.n_cores = 0
+ self.n_pipelines = 0
+ self.pos = 0
+ self.stage0_file_comment = ""
+ self.stage1_file_comment = ""
+ self.stage2_file_comment = ""
+
+ # each array entry is a pipeline mapped to core stored as string
+ # pipeline ranging from 1 to n, however stored in zero based array
+ self.arr2_pipelines2cores = []
+
+ def stage2_print(self):
+ print('printing Context2 obj')
+ print('ctx2.cores(pipelines, n_pipelines, counter, counter_max) =')
+ for cores_count in range(0, constants.MAX_CORES):
+ print('core[%d] = (%d,%d,%d,%d)' % (
+ cores_count,
+ self.cores[cores_count].pipelines,
+ self.cores[cores_count].n_pipelines,
+ self.cores[cores_count].counter,
+ self.cores[cores_count].counter_max))
+
+ print('ctx2.n_cores = %d' % self.n_cores, end='')
+ print('ctx2.n_pipelines = %d' % self.n_pipelines, end='')
+ print('ctx2.pos = %d' % self.pos)
+ print('ctx2.stage0_file_comment = %s' %
+ self.self.stage0_file_comment)
+ print('ctx2.stage1_file_comment = %s' %
+ self.self.stage1_file_comment)
+ print('ctx2.stage2_file_comment = %s' %
+ self.self.stage2_file_comment)
+
+ def stage2_reset(self):
+ for i in range(0, constants.MAX_CORES):
+ self.cores[i].pipelines = 0
+ self.cores[i].n_pipelines = 0
+ self.cores[i].counter = 0
+ self.cores[i].counter_max = 0
+
+ for idx in range(0, constants.MAX_PIPELINES):
+ self.cores[i].bitpos[idx] = 0
+
+ self.n_cores = 0
+ self.n_pipelines = 0
+ self.pos = 0
+ # clear list
+ del self.arr2_pipelines2cores[:]
+
+ def bitpos_load(self, coreidx):
+ i = j = 0
+ while (i < self.n_pipelines):
+ if ((self.cores[coreidx].pipelines) &
+ (1 << i)):
+ self.cores[coreidx].bitpos[j] = i
+ j += 1
+ i += 1
+ self.cores[coreidx].n_pipelines = j
+
+ def bitpos_apply(self, in_buf, pos, n_pos):
+ out = 0
+ for i in range(0, n_pos):
+ out |= (in_buf & (1 << i)) << (pos[i] - i)
+
+ return out
+
+ def stage2_init(self, ctx1):
+ self.stage2_reset()
+ self.n_cores = ctx1.n_cores
+ self.n_pipelines = ctx1.n_pipelines
+
+ self.arr2_pipelines2cores = [''] * self.n_pipelines
+
+ core_idx = 0
+ while (core_idx < self.n_cores):
+ self.cores[core_idx].pipelines = ctx1.cores[core_idx].pipelines
+
+ self.bitpos_load(core_idx)
+ core_idx += 1
+
+ def stage2_log(self):
+ tmp_file_comment = ""
+ if(enable_stage2_traceout == 1):
+ print('STAGE2: ', end='')
+ tmp_file_comment += 'STAGE2: '
+
+ for i in range(0, self.n_cores):
+ mask = len2mask(self.cores[i].n_pipelines)
+ pipelines_ht0 = self.bitpos_apply(
+ (~self.cores[i].counter) & mask,
+ self.cores[i].bitpos,
+ self.cores[i].n_pipelines)
+
+ pipelines_ht1 = self.bitpos_apply(
+ self.cores[i].counter,
+ self.cores[i].bitpos,
+ self.cores[i].n_pipelines)
+
+ print('C%dHT0 = [' % i, end='')
+ tmp_file_comment += "C{}HT0 = [".format(i)
+ tmp_file_comment += bitstring_write(
+ pipelines_ht0, self.n_pipelines)
+
+ print(']\tC%dHT1 = [' % i, end='')
+ tmp_file_comment += "]\tC{}HT1 = [".format(i)
+ tmp_file_comment += bitstring_write(
+ pipelines_ht1, self.n_pipelines)
+ print(']\t', end='')
+ tmp_file_comment += ']\t'
+
+ print('')
+ self.stage2_file_comment = tmp_file_comment
+
+ # check if file traceing is enabled
+ if(enable_stage2_fileout != 1):
+ return
+ # spit out the combination to file
+ self.stage2_process_file()
+
+ def stage2_updateCoresInBuf(self, nPipeline, sCore):
+ rePipeline = self._fileTrace.arr_pipelines[nPipeline]
+ rePipeline = rePipeline.replace("[", "\[").replace("]", "\]")
+ reCore = 'core\s*=\s*((\d*)|(((s|S)\d)?(c|C)[1-9][0-9]*)).*\n'
+ sSubs = 'core = ' + sCore + '\n'
+
+ reg_pipeline = re.compile(rePipeline)
+ search_match = reg_pipeline.search(self._fileTrace.in_buf)
+
+ if(search_match):
+ pos = search_match.start()
+ substr1 = self._fileTrace.in_buf[:pos]
+ substr2 = self._fileTrace.in_buf[pos:]
+ substr2 = re.sub(reCore, sSubs, substr2, 1)
+ self._fileTrace.in_buf = substr1 + substr2
+
+ def pipelines2cores(self, n, n_bits, nCore, bHT):
+ if (n_bits > 64):
+ return
+
+ i = n_bits - 1
+ pipeline_idx = 0
+ while (i >= 0):
+ cond = (n & (1 << i))
+ if (cond):
+ # update the pipelines array to match the core
+ # only in case of cond match
+ # PIPELINE0 and core 0 are reserved
+ if(bHT):
+ tmpCore = fileTrace.in_physical_cores[nCore] + 'h'
+ self.arr2_pipelines2cores[pipeline_idx] = tmpCore
+ else:
+ self.arr2_pipelines2cores[pipeline_idx] = \
+ fileTrace.in_physical_cores[nCore]
+
+ i -= 1
+ pipeline_idx += 1
+
+ def stage2_process_file(self):
+ outFileName = os.path.join(self._fileTrace.out_path,
+ self._fileTrace.prefix_outfile)
+ outFileName += "_{}CoReS".format(self.n_cores)
+
+ for i in range(0, self.n_cores):
+ mask = len2mask(self.cores[i].n_pipelines)
+ pipelines_ht0 = self.bitpos_apply((~self.cores[i].counter) & mask,
+ self.cores[i].bitpos,
+ self.cores[i].n_pipelines)
+
+ pipelines_ht1 = self.bitpos_apply(self.cores[i].counter,
+ self.cores[i].bitpos,
+ self.cores[i].n_pipelines)
+
+ # update pipelines to core mapping
+ self.pipelines2cores(pipelines_ht0, self.n_pipelines, i, False)
+ self.pipelines2cores(pipelines_ht1, self.n_pipelines, i, True)
+
+ # update the in_buf as per the arr_pipelines2cores
+ for pipeline_idx in range(len(self.arr2_pipelines2cores)):
+ outFileName += "_{}".format(
+ self.arr2_pipelines2cores[pipeline_idx])
+ self.stage2_updateCoresInBuf(
+ pipeline_idx, self.arr2_pipelines2cores[pipeline_idx])
+
+ # by now the in_buf is all set to be written to file
+ outFileName += self._fileTrace.suffix_outfile
+ outputFile = open(outFileName, "w")
+
+ # write the file comments
+ strTruncated = ("", "(Truncated)")[self._fileTrace.ncores_truncated]
+ outputFile.write(
+ "; =============== Pipeline-to-Core Mapping ================\n"
+ "; Generated from file {}\n"
+ "; Input pipelines = {}\n"
+ "; Input cores = {}\n"
+ "; N_PIPELINES = {} N_CORES = {} {} hyper_thread = {} \n"
+ .format(
+ self._fileTrace.in_file_namepath,
+ fileTrace.arr_pipelines,
+ fileTrace.in_physical_cores,
+ self._fileTrace.n_pipelines,
+ self._fileTrace.n_cores,
+ strTruncated,
+ self._fileTrace.hyper_thread))
+
+ outputFile.write(
+ "; {stg0cmt}\n"
+ "; {stg1cmt}\n"
+ "; {stg2cmt}\n"
+ "; ========================================================\n"
+ "; \n"
+ .format(
+ stg0cmt=self.stage0_file_comment,
+ stg1cmt=self.stage1_file_comment,
+ stg2cmt=self.stage2_file_comment))
+
+ # write the buffer contents
+ outputFile.write(self._fileTrace.in_buf)
+ outputFile.flush()
+ outputFile.close()
+
+ def stage2_process(self):
+ i = 0
+ while(i < self.n_cores):
+ self.cores[i].counter_max = len2mask(
+ self.cores[i].n_pipelines - 1)
+ i += 1
+
+ self.pos = self.n_cores - 1
+ while True:
+ if (self.pos == self.n_cores - 1):
+ self.stage2_log()
+
+ if (self.cores[self.pos].counter ==
+ self.cores[self.pos].counter_max):
+ if (self.pos == 0):
+ return
+
+ self.cores[self.pos].counter = 0
+ self.pos -= 1
+ continue
+
+ self.cores[self.pos].counter += 1
+ if(self.pos < self.n_cores - 1):
+ self.pos += 1
+
+
+class FileTrace:
+
+ def __init__(self, filenamepath):
+ self.in_file_namepath = os.path.abspath(filenamepath)
+ self.in_filename = os.path.basename(self.in_file_namepath)
+ self.in_path = os.path.dirname(self.in_file_namepath)
+
+ filenamesplit = self.in_filename.split('.')
+ self.prefix_outfile = filenamesplit[0]
+ self.suffix_outfile = ".cfg"
+
+ # output folder: in the same folder as input file
+ # create new folder in the name of input file
+ self.out_path = os.path.join(
+ os.path.abspath(os.path.dirname(__file__)),
+ self.prefix_outfile)
+
+ try:
+ os.makedirs(self.out_path)
+ except OSError as excep:
+ if excep.errno == errno.EEXIST and os.path.isdir(self.out_path):
+ pass
+ else:
+ raise
+
+ self.in_buf = None
+ self.arr_pipelines = [] # holds the positions of search
+
+ self.max_cores = 15
+ self.max_pipelines = 15
+
+ self.in_physical_cores = None
+ self.hyper_thread = None
+
+ # save the num of pipelines determined from input file
+ self.n_pipelines = 0
+ # save the num of cores input (or the truncated value)
+ self.n_cores = 0
+ self.ncores_truncated = False
+
+ def print_TraceFile(self):
+ print("self.in_file_namepath = ", self.in_file_namepath)
+ print("self.in_filename = ", self.in_filename)
+ print("self.in_path = ", self.in_path)
+ print("self.out_path = ", self.out_path)
+ print("self.prefix_outfile = ", self.prefix_outfile)
+ print("self.suffix_outfile = ", self.suffix_outfile)
+ print("self.in_buf = ", self.in_buf)
+ print("self.arr_pipelines =", self.arr_pipelines)
+ print("self.in_physical_cores", self.in_physical_cores)
+ print("self.hyper_thread", self.hyper_thread)
+
+
+def process(n_cores, n_pipelines, fileTrace):
+ '''process and map pipelines, cores.'''
+ if (n_cores == 0):
+ sys.exit('N_CORES is 0, exiting')
+
+ if (n_pipelines == 0):
+ sys.exit('N_PIPELINES is 0, exiting')
+
+ if (n_cores > n_pipelines):
+ print('\nToo many cores, truncating N_CORES to N_PIPELINES')
+ n_cores = n_pipelines
+ fileTrace.ncores_truncated = True
+
+ fileTrace.n_pipelines = n_pipelines
+ fileTrace.n_cores = n_cores
+
+ strTruncated = ("", "(Truncated)")[fileTrace.ncores_truncated]
+ print("N_PIPELINES = {}, N_CORES = {} {}"
+ .format(n_pipelines, n_cores, strTruncated))
+ print("---------------------------------------------------------------")
+
+ ctx0_inst = Context0()
+ ctx1_inst = Context1()
+ ctx2_inst = Context2()
+
+ # initialize the class variables
+ ctx1_inst._fileTrace = fileTrace
+ ctx2_inst._fileTrace = fileTrace
+
+ ctx0_inst.stage0_init(n_cores, n_pipelines, ctx1_inst, ctx2_inst)
+ ctx0_inst.stage0_process()
+
+
+def validate_core(core):
+ match = reg_phycore.match(core)
+ if(match):
+ return True
+ else:
+ return False
+
+
+def validate_phycores(phy_cores):
+ '''validate physical cores, check if unique.'''
+ # eat up whitespaces
+ phy_cores = phy_cores.strip().split(',')
+
+ # check if the core list is unique
+ if(len(phy_cores) != len(set(phy_cores))):
+ print('list of physical cores has duplicates')
+ return None
+
+ for core in phy_cores:
+ if not validate_core(core):
+ print('invalid physical core specified.')
+ return None
+ return phy_cores
+
+
+def scanconfigfile(fileTrace):
+ '''scan input file for pipelines, validate then process.'''
+ # open file
+ filetoscan = open(fileTrace.in_file_namepath, 'r')
+ fileTrace.in_buf = filetoscan.read()
+
+ # reset iterator on open file
+ filetoscan.seek(0)
+
+ # scan input file for pipelines
+ # master pipelines to be ignored
+ pattern_pipeline = r'\[PIPELINE\d*\]'
+ pattern_mastertype = r'type\s*=\s*MASTER'
+
+ pending_pipeline = False
+ for line in filetoscan:
+ match_pipeline = re.search(pattern_pipeline, line)
+ match_type = re.search('type\s*=', line)
+ match_mastertype = re.search(pattern_mastertype, line)
+
+ if(match_pipeline):
+ sPipeline = line[match_pipeline.start():match_pipeline.end()]
+ pending_pipeline = True
+ elif(match_type):
+ # found a type definition...
+ if(match_mastertype is None):
+ # and this is not a master pipeline...
+ if(pending_pipeline):
+ # add it to the list of pipelines to be mapped
+ fileTrace.arr_pipelines.append(sPipeline)
+ pending_pipeline = False
+ else:
+ # and this is a master pipeline...
+ # ignore the current and move on to next
+ sPipeline = ""
+ pending_pipeline = False
+ filetoscan.close()
+
+ # validate if pipelines are unique
+ if(len(fileTrace.arr_pipelines) != len(set(fileTrace.arr_pipelines))):
+ sys.exit('Error: duplicate pipelines in input file')
+
+ num_pipelines = len(fileTrace.arr_pipelines)
+ num_cores = len(fileTrace.in_physical_cores)
+
+ print("-------------------Pipeline-to-core mapping--------------------")
+ print("Input pipelines = {}\nInput cores = {}"
+ .format(fileTrace.arr_pipelines, fileTrace.in_physical_cores))
+
+ # input configuration file validations goes here
+ if (num_cores > fileTrace.max_cores):
+ sys.exit('Error: number of cores specified > max_cores (%d)' %
+ fileTrace.max_cores)
+
+ if (num_pipelines > fileTrace.max_pipelines):
+ sys.exit('Error: number of pipelines in input \
+ cfg file > max_pipelines (%d)' % fileTrace.max_pipelines)
+
+ # call process to generate pipeline-to-core mapping, trace and log
+ process(num_cores, num_pipelines, fileTrace)
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description='mappipelines')
+
+ reqNamedGrp = parser.add_argument_group('required named args')
+ reqNamedGrp.add_argument(
+ '-i',
+ '--input-file',
+ type=argparse.FileType('r'),
+ help='Input config file',
+ required=True)
+
+ reqNamedGrp.add_argument(
+ '-pc',
+ '--physical-cores',
+ type=validate_phycores,
+ help='''Enter available CPU cores in
+ format:\"<core>,<core>,...\"
+ where each core format: \"s<SOCKETID>c<COREID>\"
+ where SOCKETID={0..9}, COREID={1-99}''',
+ required=True)
+
+ # add optional arguments
+ parser.add_argument(
+ '-ht',
+ '--hyper-thread',
+ help='enable/disable hyper threading. default is ON',
+ default='ON',
+ choices=['ON', 'OFF'])
+
+ parser.add_argument(
+ '-nO',
+ '--no-output-file',
+ help='''disable output config file generation.
+ Output file generation is enabled by default''',
+ action="store_true")
+
+ args = parser.parse_args()
+
+ if(args.physical_cores is None):
+ parser.error("invalid physical_cores specified")
+
+ # create object of FileTrace and initialise
+ fileTrace = FileTrace(args.input_file.name)
+ fileTrace.in_physical_cores = args.physical_cores
+ fileTrace.hyper_thread = args.hyper_thread
+
+ if(fileTrace.hyper_thread == 'OFF'):
+ print("!!!!disabling stage2 HT!!!!")
+ enable_stage2_traceout = 0
+ enable_stage2_fileout = 0
+ elif(fileTrace.hyper_thread == 'ON'):
+ print("!!!!HT enabled. disabling stage1 file generation.!!!!")
+ enable_stage1_fileout = 0
+
+ if(args.no_output_file is True):
+ print("!!!!disabling stage1 and stage2 fileout!!!!")
+ enable_stage1_fileout = 0
+ enable_stage2_fileout = 0
+
+ scanconfigfile(fileTrace)
diff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c
index fd9ff495..af1b6284 100644
--- a/examples/ip_pipeline/config_check.c
+++ b/examples/ip_pipeline/config_check.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,6 +56,26 @@ check_mempools(struct app_params *app)
}
}
+static inline uint32_t
+link_rxq_used(struct app_link_params *link, uint32_t q_id)
+{
+ uint32_t i;
+
+ if ((link->arp_q == q_id) ||
+ (link->tcp_syn_q == q_id) ||
+ (link->ip_local_q == q_id) ||
+ (link->tcp_local_q == q_id) ||
+ (link->udp_local_q == q_id) ||
+ (link->sctp_local_q == q_id))
+ return 1;
+
+ for (i = 0; i < link->n_rss_qs; i++)
+ if (link->rss_qs[i] == q_id)
+ return 1;
+
+ return 0;
+}
+
static void
check_links(struct app_params *app)
{
@@ -90,14 +110,12 @@ check_links(struct app_params *app)
rxq_max = link->udp_local_q;
if (link->sctp_local_q > rxq_max)
rxq_max = link->sctp_local_q;
+ for (i = 0; i < link->n_rss_qs; i++)
+ if (link->rss_qs[i] > rxq_max)
+ rxq_max = link->rss_qs[i];
for (i = 1; i <= rxq_max; i++)
- APP_CHECK(((link->arp_q == i) ||
- (link->tcp_syn_q == i) ||
- (link->ip_local_q == i) ||
- (link->tcp_local_q == i) ||
- (link->udp_local_q == i) ||
- (link->sctp_local_q == i)),
+ APP_CHECK((link_rxq_used(link, i)),
"%s RXQs are not contiguous (A)\n", link->name);
n_rxq = app_link_get_n_rxq(app, link);
@@ -118,7 +136,7 @@ check_links(struct app_params *app)
"%s RXQs are not contiguous (C)\n", link->name);
}
- /* Check that link RXQs are contiguous */
+ /* Check that link TXQs are contiguous */
n_txq = app_link_get_n_txq(app, link);
APP_CHECK((n_txq), "%s does not have any TXQ\n", link->name);
@@ -298,6 +316,29 @@ check_tms(struct app_params *app)
}
static void
+check_knis(struct app_params *app) {
+ uint32_t i;
+
+ for (i = 0; i < app->n_pktq_kni; i++) {
+ struct app_pktq_kni_params *p = &app->kni_params[i];
+ uint32_t n_readers = app_kni_get_readers(app, p);
+ uint32_t n_writers = app_kni_get_writers(app, p);
+
+ APP_CHECK((n_readers != 0),
+ "%s has no reader\n", p->name);
+
+ APP_CHECK((n_readers == 1),
+ "%s has more than one reader\n", p->name);
+
+ APP_CHECK((n_writers != 0),
+ "%s has no writer\n", p->name);
+
+ APP_CHECK((n_writers == 1),
+ "%s has more than one writer\n", p->name);
+ }
+}
+
+static void
check_sources(struct app_params *app)
{
uint32_t i;
@@ -435,6 +476,7 @@ app_config_check(struct app_params *app)
check_txqs(app);
check_swqs(app);
check_tms(app);
+ check_knis(app);
check_sources(app);
check_sinks(app);
check_msgqs(app);
diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c
index e5efd03e..0adca98f 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -1,4 +1,4 @@
-/*-
+/*-
* BSD LICENSE
*
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
@@ -30,6 +30,7 @@
* (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>
@@ -80,6 +81,11 @@ static const struct app_link_params link_params_default = {
.tcp_local_q = 0,
.udp_local_q = 0,
.sctp_local_q = 0,
+ .rss_qs = {0},
+ .n_rss_qs = 0,
+ .rss_proto_ipv4 = ETH_RSS_IPV4,
+ .rss_proto_ipv6 = ETH_RSS_IPV6,
+ .rss_proto_l2 = 0,
.state = 0,
.ip = 0,
.depth = 0,
@@ -103,6 +109,13 @@ static const struct app_link_params link_params_default = {
.max_rx_pkt_len = 9000, /* Jumbo frame max packet len */
.split_hdr_size = 0, /* Header split buffer size */
},
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_key_len = 40,
+ .rss_hf = 0,
+ },
+ },
.txmode = {
.mq_mode = ETH_MQ_TX_NONE,
},
@@ -176,6 +189,20 @@ struct app_pktq_tm_params default_tm_params = {
.burst_write = 32,
};
+struct app_pktq_kni_params default_kni_params = {
+ .parsed = 0,
+ .socket_id = 0,
+ .core_id = 0,
+ .hyper_th_id = 0,
+ .force_bind = 0,
+
+ .mempool_id = 0,
+ .burst_read = 32,
+ .burst_write = 32,
+ .dropless = 0,
+ .n_retries = 0,
+};
+
struct app_pktq_source_params default_source_params = {
.parsed = 0,
.mempool_id = 0,
@@ -229,306 +256,136 @@ app_print_usage(char *prgname)
rte_exit(0, app_usage, prgname, app_params_default.config_file);
}
-#define skip_white_spaces(pos) \
-({ \
- __typeof__(pos) _p = (pos); \
- for ( ; isspace(*_p); _p++); \
- _p; \
+#define APP_PARAM_ADD(set, key) \
+({ \
+ ssize_t pos = APP_PARAM_FIND(set, key); \
+ ssize_t size = RTE_DIM(set); \
+ \
+ if (pos < 0) { \
+ for (pos = 0; pos < size; pos++) { \
+ if (!APP_PARAM_VALID(&((set)[pos]))) \
+ break; \
+ } \
+ \
+ APP_CHECK((pos < size), \
+ "Parse error: size of %s is limited to %u elements",\
+ #set, (uint32_t) size); \
+ \
+ (set)[pos].name = strdup(key); \
+ APP_CHECK(((set)[pos].name), \
+ "Parse error: no free memory"); \
+ } \
+ pos; \
})
-#define PARSER_PARAM_ADD_CHECK(result, params_array, section_name) \
-do { \
- APP_CHECK((result != -EINVAL), \
- "Parse error: no free memory"); \
- APP_CHECK((result != -ENOMEM), \
- "Parse error: too many \"%s\" sections", section_name); \
- APP_CHECK(((result >= 0) && (params_array)[result].parsed == 0),\
- "Parse error: duplicate \"%s\" section", section_name); \
- APP_CHECK((result >= 0), \
- "Parse error in section \"%s\"", section_name); \
-} while (0)
-
-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;
- }
+#define APP_PARAM_ADD_LINK_FOR_RXQ(app, rxq_name) \
+({ \
+ char link_name[APP_PARAM_NAME_SIZE]; \
+ ssize_t link_param_pos; \
+ uint32_t link_id, queue_id; \
+ \
+ sscanf((rxq_name), "RXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\
+ sprintf(link_name, "LINK%" PRIu32, link_id); \
+ link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \
+ link_param_pos; \
+})
- if (((p[0] == 'n') && (p[1] == 'o')) ||
- ((p[0] == 'N') && (p[1] == 'O'))) {
- p += 2;
- result = 0;
- }
+#define APP_PARAM_ADD_LINK_FOR_TXQ(app, txq_name) \
+({ \
+ char link_name[APP_PARAM_NAME_SIZE]; \
+ ssize_t link_param_pos; \
+ uint32_t link_id, queue_id; \
+ \
+ sscanf((txq_name), "TXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\
+ sprintf(link_name, "LINK%" PRIu32, link_id); \
+ link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \
+ link_param_pos; \
+})
- if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
- ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
- p += 3;
- result = 0;
- }
+#define APP_PARAM_ADD_LINK_FOR_TM(app, tm_name) \
+({ \
+ char link_name[APP_PARAM_NAME_SIZE]; \
+ ssize_t link_param_pos; \
+ uint32_t link_id; \
+ \
+ sscanf((tm_name), "TM%" SCNu32, &link_id); \
+ sprintf(link_name, "LINK%" PRIu32, link_id); \
+ link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \
+ link_param_pos; \
+})
- p = skip_white_spaces(p);
+#define APP_PARAM_ADD_LINK_FOR_KNI(app, kni_name) \
+({ \
+ char link_name[APP_PARAM_NAME_SIZE]; \
+ ssize_t link_param_pos; \
+ uint32_t link_id; \
+ \
+ sscanf((kni_name), "KNI%" SCNu32, &link_id); \
+ sprintf(link_name, "LINK%" PRIu32, link_id); \
+ link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \
+ link_param_pos; \
+})
- if (p[0] != '\0')
- return -EINVAL;
+#define PARSE_CHECK_DUPLICATE_SECTION(obj) \
+do { \
+ APP_CHECK(((obj)->parsed == 0), \
+ "Parse error: duplicate \"%s\" section", (obj)->name); \
+ (obj)->parsed++; \
+} while (0)
- return result;
-}
+#define PARSE_CHECK_DUPLICATE_SECTION_EAL(obj) \
+do { \
+ APP_CHECK(((obj)->parsed == 0), \
+ "Parse error: duplicate \"%s\" section", "EAL"); \
+ (obj)->parsed++; \
+} while (0)
#define PARSE_ERROR(exp, section, entry) \
-APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"\n", section, entry)
+APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"", section, entry)
#define PARSE_ERROR_MESSAGE(exp, section, entry, message) \
-APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": %s\n", \
+APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": %s", \
section, entry, message)
+#define PARSE_ERROR_NO_ELEMENTS(exp, section, entry) \
+APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \
+ "no elements detected", \
+ section, entry)
+
+#define PARSE_ERROR_TOO_MANY_ELEMENTS(exp, section, entry, max) \
+APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \
+ "maximum number of elements allowed is %u", \
+ section, entry, max)
+
+#define PARSE_ERROR_INVALID_ELEMENT(exp, section, entry, value) \
+APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \
+ "Invalid element value \"%s\"", \
+ section, entry, value)
#define PARSE_ERROR_MALLOC(exp) \
-APP_CHECK(exp, "Parse error: no free memory\n")
+APP_CHECK(exp, "Parse error: no free memory")
#define PARSE_ERROR_SECTION(exp, section) \
APP_CHECK(exp, "Parse error in section \"%s\"", section)
#define PARSE_ERROR_SECTION_NO_ENTRIES(exp, section) \
-APP_CHECK(exp, "Parse error in section \"%s\": no entries\n", section)
+APP_CHECK(exp, "Parse error in section \"%s\": no entries", section)
#define PARSE_WARNING_IGNORED(exp, section, entry) \
do \
if (!(exp)) \
fprintf(stderr, "Parse warning in section \"%s\": " \
- "entry \"%s\" is ignored\n", section, entry); \
+ "entry \"%s\" is ignored", section, entry); \
while (0)
#define PARSE_ERROR_INVALID(exp, section, entry) \
-APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"\n",\
+APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"",\
section, entry)
#define PARSE_ERROR_DUPLICATE(exp, section, entry) \
-APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"\n",\
+APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"", \
section, entry)
-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 through */
- case 'G':
- val *= 1024ULL;
- /* fall through */
- case 'M':
- val *= 1024ULL;
- /* fall through */
- case 'k':
- case 'K':
- val *= 1024ULL;
- p++;
- break;
- }
-
- p = skip_white_spaces(p);
- if (*p != '\0')
- return -EINVAL;
-
- *value = val;
- return 0;
-}
-
-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;
-
- if (val > UINT32_MAX)
- return -ERANGE;
-
- *value = val;
- return 0;
-}
-
-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 || c_parsed || h_parsed)
- return -EINVAL;
- s_parsed = 1;
- next++;
- break;
- case 'c':
- case 'C':
- if (c_parsed || h_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' && type != 'H')
- return -EINVAL;
-
- if (num_len != 0 && (type == 'h' || 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;
- break;
- case 'h':
- case 'H':
- h = 1;
- break;
- }
- }
-
- *socket = s;
- *core = c;
- *ht = h;
- return 0;
-}
-
-static uint32_t
-get_hex_val(char c)
-{
- switch (c) {
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- return c - '0';
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- return c - 'A' + 10;
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- return c - 'a' + 10;
- default:
- return 0;
- }
-}
-
-int
-parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
-{
- char *c;
- uint32_t len, i;
-
- /* Check input parameters */
- if ((src == NULL) ||
- (dst == NULL) ||
- (size == NULL) ||
- (*size == 0))
- return -1;
-
- len = strlen(src);
- if (((len & 3) != 0) ||
- (len > (*size) * 2))
- return -1;
- *size = len / 2;
-
- for (c = src; *c != 0; c++) {
- if ((((*c) >= '0') && ((*c) <= '9')) ||
- (((*c) >= 'A') && ((*c) <= 'F')) ||
- (((*c) >= 'a') && ((*c) <= 'f')))
- continue;
-
- return -1;
- }
-
- /* Convert chars to bytes */
- for (i = 0; i < *size; i++)
- dst[i] = get_hex_val(src[2 * i]) * 16 +
- get_hex_val(src[2 * i + 1]);
-
- 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)
{
@@ -584,6 +441,8 @@ parse_eal(struct app_params *app,
rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
+ PARSE_CHECK_DUPLICATE_SECTION_EAL(p);
+
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *entry = &entries[i];
@@ -963,413 +822,162 @@ parse_eal(struct app_params *app,
free(entries);
}
-static int
-parse_pipeline_pcap_source(struct app_params *app,
- struct app_pipeline_params *p,
- const char *file_name, const char *cp_size)
-{
- const char *next = NULL;
- char *end;
- uint32_t i;
- int parse_file = 0;
-
- if (file_name && !cp_size) {
- next = file_name;
- parse_file = 1; /* parse file path */
- } else if (cp_size && !file_name) {
- next = cp_size;
- parse_file = 0; /* parse copy size */
- } else
- return -EINVAL;
-
- char name[APP_PARAM_NAME_SIZE];
- size_t name_len;
-
- if (p->n_pktq_in == 0)
- return -EINVAL;
-
- i = 0;
- while (*next != '\0') {
- uint32_t id;
-
- if (i >= p->n_pktq_in)
- return -EINVAL;
-
- id = p->pktq_in[i].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 (parse_file) {
- app->source_params[id].file_name = strdup(name);
- if (app->source_params[id].file_name == NULL)
- return -ENOMEM;
- } else {
- if (parser_read_uint32(
- &app->source_params[id].n_bytes_per_pkt,
- name) != 0) {
- if (app->source_params[id].
- file_name != NULL)
- free(app->source_params[id].
- file_name);
- return -EINVAL;
- }
- }
-
- i++;
-
- if (i == p->n_pktq_in)
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int
-parse_pipeline_pcap_sink(struct app_params *app,
- struct app_pipeline_params *p,
- const char *file_name, const char *n_pkts_to_dump)
-{
- const char *next = NULL;
- char *end;
- uint32_t i;
- int parse_file = 0;
-
- if (file_name && !n_pkts_to_dump) {
- next = file_name;
- parse_file = 1; /* parse file path */
- } else if (n_pkts_to_dump && !file_name) {
- next = n_pkts_to_dump;
- parse_file = 0; /* parse copy size */
- } else
- return -EINVAL;
-
- char name[APP_PARAM_NAME_SIZE];
- size_t name_len;
-
- if (p->n_pktq_out == 0)
- return -EINVAL;
-
- i = 0;
- while (*next != '\0') {
- uint32_t id;
-
- if (i >= p->n_pktq_out)
- return -EINVAL;
-
- id = p->pktq_out[i].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 (parse_file) {
- app->sink_params[id].file_name = strdup(name);
- if (app->sink_params[id].file_name == NULL)
- return -ENOMEM;
- } else {
- if (parser_read_uint32(
- &app->sink_params[id].n_pkts_to_dump,
- name) != 0) {
- if (app->sink_params[id].file_name !=
- NULL)
- free(app->sink_params[id].
- file_name);
- return -EINVAL;
- }
- }
-
- i++;
-
- if (i == p->n_pktq_out)
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int
+static void
parse_pipeline_pktq_in(struct app_params *app,
struct app_pipeline_params *p,
- const char *value)
+ char *value)
{
- const char *next = value;
- char *end;
- char name[APP_PARAM_NAME_SIZE];
- size_t name_len;
+ p->n_pktq_in = 0;
- while (*next != '\0') {
+ while (1) {
enum app_pktq_in_type type;
int id;
- char *end_space;
- char *end_tab;
+ char *name = strtok_r(value, PARSE_DELIMITER, &value);
- next = skip_white_spaces(next);
- if (!next)
+ if (name == NULL)
break;
- end_space = strchr(next, ' ');
- end_tab = strchr(next, ' ');
-
- if (end_space && (!end_tab))
- end = end_space;
- else if ((!end_space) && end_tab)
- end = end_tab;
- else if (end_space && end_tab)
- end = RTE_MIN(end_space, end_tab);
- else
- end = NULL;
-
- 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++;
+ PARSE_ERROR_TOO_MANY_ELEMENTS(
+ (p->n_pktq_in < RTE_DIM(p->pktq_in)),
+ p->name, "pktq_in", (uint32_t)RTE_DIM(p->pktq_in));
if (validate_name(name, "RXQ", 2) == 0) {
type = APP_PKTQ_IN_HWQ;
id = APP_PARAM_ADD(app->hwq_in_params, name);
+ APP_PARAM_ADD_LINK_FOR_RXQ(app, name);
} else if (validate_name(name, "SWQ", 1) == 0) {
type = APP_PKTQ_IN_SWQ;
id = APP_PARAM_ADD(app->swq_params, name);
} else if (validate_name(name, "TM", 1) == 0) {
type = APP_PKTQ_IN_TM;
id = APP_PARAM_ADD(app->tm_params, name);
+ APP_PARAM_ADD_LINK_FOR_TM(app, name);
+ } else if (validate_name(name, "KNI", 1) == 0) {
+ type = APP_PKTQ_IN_KNI;
+ id = APP_PARAM_ADD(app->kni_params, name);
+ APP_PARAM_ADD_LINK_FOR_KNI(app, name);
} else if (validate_name(name, "SOURCE", 1) == 0) {
type = APP_PKTQ_IN_SOURCE;
id = APP_PARAM_ADD(app->source_params, name);
} else
- return -EINVAL;
-
- if (id < 0)
- return id;
+ PARSE_ERROR_INVALID_ELEMENT(0,
+ p->name, "pktq_in", name);
p->pktq_in[p->n_pktq_in].type = type;
p->pktq_in[p->n_pktq_in].id = (uint32_t) id;
p->n_pktq_in++;
}
- return 0;
+ PARSE_ERROR_NO_ELEMENTS((p->n_pktq_in > 0), p->name, "pktq_in");
}
-static int
+static void
parse_pipeline_pktq_out(struct app_params *app,
struct app_pipeline_params *p,
- const char *value)
+ char *value)
{
- const char *next = value;
- char *end;
- char name[APP_PARAM_NAME_SIZE];
- size_t name_len;
+ p->n_pktq_out = 0;
- while (*next != '\0') {
+ while (1) {
enum app_pktq_out_type type;
int id;
- char *end_space;
- char *end_tab;
+ char *name = strtok_r(value, PARSE_DELIMITER, &value);
- next = skip_white_spaces(next);
- if (!next)
+ if (name == NULL)
break;
- end_space = strchr(next, ' ');
- end_tab = strchr(next, ' ');
+ PARSE_ERROR_TOO_MANY_ELEMENTS(
+ (p->n_pktq_out < RTE_DIM(p->pktq_out)),
+ p->name, "pktq_out", (uint32_t)RTE_DIM(p->pktq_out));
- if (end_space && (!end_tab))
- end = end_space;
- else if ((!end_space) && end_tab)
- end = end_tab;
- else if (end_space && end_tab)
- end = RTE_MIN(end_space, end_tab);
- else
- end = NULL;
-
- 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);
+ APP_PARAM_ADD_LINK_FOR_TXQ(app, name);
} else if (validate_name(name, "SWQ", 1) == 0) {
type = APP_PKTQ_OUT_SWQ;
id = APP_PARAM_ADD(app->swq_params, name);
} else if (validate_name(name, "TM", 1) == 0) {
type = APP_PKTQ_OUT_TM;
id = APP_PARAM_ADD(app->tm_params, name);
+ APP_PARAM_ADD_LINK_FOR_TM(app, name);
+ } else if (validate_name(name, "KNI", 1) == 0) {
+ type = APP_PKTQ_OUT_KNI;
+ id = APP_PARAM_ADD(app->kni_params, name);
+ APP_PARAM_ADD_LINK_FOR_KNI(app, name);
} else if (validate_name(name, "SINK", 1) == 0) {
type = APP_PKTQ_OUT_SINK;
id = APP_PARAM_ADD(app->sink_params, name);
} else
- return -EINVAL;
-
- if (id < 0)
- return id;
+ PARSE_ERROR_INVALID_ELEMENT(0,
+ p->name, "pktq_out", name);
p->pktq_out[p->n_pktq_out].type = type;
p->pktq_out[p->n_pktq_out].id = id;
p->n_pktq_out++;
}
- return 0;
+ PARSE_ERROR_NO_ELEMENTS((p->n_pktq_out > 0), p->name, "pktq_out");
}
-static int
+static void
parse_pipeline_msgq_in(struct app_params *app,
struct app_pipeline_params *p,
- const char *value)
+ char *value)
{
- const char *next = value;
- char *end;
- char name[APP_PARAM_NAME_SIZE];
- size_t name_len;
- ssize_t idx;
-
- while (*next != '\0') {
- char *end_space;
- char *end_tab;
-
- next = skip_white_spaces(next);
- if (!next)
- break;
-
- end_space = strchr(next, ' ');
- end_tab = strchr(next, ' ');
+ p->n_msgq_in = 0;
- if (end_space && (!end_tab))
- end = end_space;
- else if ((!end_space) && end_tab)
- end = end_tab;
- else if (end_space && end_tab)
- end = RTE_MIN(end_space, end_tab);
- else
- end = NULL;
+ while (1) {
+ int idx;
+ char *name = strtok_r(value, PARSE_DELIMITER, &value);
- if (!end)
- name_len = strlen(next);
- else
- name_len = end - next;
+ if (name == NULL)
+ break;
- if (name_len == 0 || name_len == sizeof(name))
- return -EINVAL;
+ PARSE_ERROR_TOO_MANY_ELEMENTS(
+ (p->n_msgq_in < RTE_DIM(p->msgq_in)),
+ p->name, "msgq_in", (uint32_t)(RTE_DIM(p->msgq_in)));
- strncpy(name, next, name_len);
- name[name_len] = '\0';
- next += name_len;
- if (*next != '\0')
- next++;
-
- if (validate_name(name, "MSGQ", 1) != 0)
- return -EINVAL;
+ PARSE_ERROR_INVALID_ELEMENT(
+ (validate_name(name, "MSGQ", 1) == 0),
+ p->name, "msgq_in", name);
idx = APP_PARAM_ADD(app->msgq_params, name);
- if (idx < 0)
- return idx;
-
p->msgq_in[p->n_msgq_in] = idx;
p->n_msgq_in++;
}
- return 0;
+ PARSE_ERROR_NO_ELEMENTS((p->n_msgq_in > 0), p->name, "msgq_in");
}
-static int
+static void
parse_pipeline_msgq_out(struct app_params *app,
struct app_pipeline_params *p,
- const char *value)
+ char *value)
{
- const char *next = value;
- char *end;
- char name[APP_PARAM_NAME_SIZE];
- size_t name_len;
- ssize_t idx;
-
- while (*next != '\0') {
- char *end_space;
- char *end_tab;
-
- next = skip_white_spaces(next);
- if (!next)
- break;
-
- end_space = strchr(next, ' ');
- end_tab = strchr(next, ' ');
-
- if (end_space && (!end_tab))
- end = end_space;
- else if ((!end_space) && end_tab)
- end = end_tab;
- else if (end_space && end_tab)
- end = RTE_MIN(end_space, end_tab);
- else
- end = NULL;
+ p->n_msgq_out = 0;
- if (!end)
- name_len = strlen(next);
- else
- name_len = end - next;
+ while (1) {
+ int idx;
+ char *name = strtok_r(value, PARSE_DELIMITER, &value);
- if (name_len == 0 || name_len == sizeof(name))
- return -EINVAL;
+ if (name == NULL)
+ break;
- strncpy(name, next, name_len);
- name[name_len] = '\0';
- next += name_len;
- if (*next != '\0')
- next++;
+ PARSE_ERROR_TOO_MANY_ELEMENTS(
+ (p->n_msgq_out < RTE_DIM(p->msgq_out)),
+ p->name, "msgq_out", (uint32_t)RTE_DIM(p->msgq_out));
- if (validate_name(name, "MSGQ", 1) != 0)
- return -EINVAL;
+ PARSE_ERROR_INVALID_ELEMENT(
+ (validate_name(name, "MSGQ", 1) == 0),
+ p->name, "msgq_out", name);
idx = APP_PARAM_ADD(app->msgq_params, name);
- if (idx < 0)
- return idx;
-
p->msgq_out[p->n_msgq_out] = idx;
p->n_msgq_out++;
}
- return 0;
+ PARSE_ERROR_NO_ELEMENTS((p->n_msgq_out > 0), p->name, "msgq_out");
}
static void
@@ -1392,9 +1000,8 @@ parse_pipeline(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -1421,38 +1028,26 @@ parse_pipeline(struct app_params *app,
}
if (strcmp(ent->name, "pktq_in") == 0) {
- int status = parse_pipeline_pktq_in(app, param,
- ent->value);
+ parse_pipeline_pktq_in(app, param, ent->value);
- PARSE_ERROR((status == 0), section_name,
- ent->name);
continue;
}
if (strcmp(ent->name, "pktq_out") == 0) {
- int status = parse_pipeline_pktq_out(app, param,
- ent->value);
+ parse_pipeline_pktq_out(app, param, ent->value);
- PARSE_ERROR((status == 0), section_name,
- ent->name);
continue;
}
if (strcmp(ent->name, "msgq_in") == 0) {
- int status = parse_pipeline_msgq_in(app, param,
- ent->value);
+ parse_pipeline_msgq_in(app, param, ent->value);
- PARSE_ERROR((status == 0), section_name,
- ent->name);
continue;
}
if (strcmp(ent->name, "msgq_out") == 0) {
- int status = parse_pipeline_msgq_out(app, param,
- ent->value);
+ parse_pipeline_msgq_out(app, param, ent->value);
- PARSE_ERROR((status == 0), section_name,
- ent->name);
continue;
}
@@ -1466,66 +1061,6 @@ parse_pipeline(struct app_params *app,
continue;
}
- if (strcmp(ent->name, "pcap_file_rd") == 0) {
- int status;
-
-#ifndef RTE_PORT_PCAP
- PARSE_ERROR_INVALID(0, section_name, ent->name);
-#endif
-
- status = parse_pipeline_pcap_source(app,
- param, ent->value, NULL);
-
- PARSE_ERROR((status == 0), section_name,
- ent->name);
- continue;
- }
-
- if (strcmp(ent->name, "pcap_bytes_rd_per_pkt") == 0) {
- int status;
-
-#ifndef RTE_PORT_PCAP
- PARSE_ERROR_INVALID(0, section_name, ent->name);
-#endif
-
- status = parse_pipeline_pcap_source(app,
- param, NULL, ent->value);
-
- PARSE_ERROR((status == 0), section_name,
- ent->name);
- continue;
- }
-
- if (strcmp(ent->name, "pcap_file_wr") == 0) {
- int status;
-
-#ifndef RTE_PORT_PCAP
- PARSE_ERROR_INVALID(0, section_name, ent->name);
-#endif
-
- status = parse_pipeline_pcap_sink(app, param,
- ent->value, NULL);
-
- PARSE_ERROR((status == 0), section_name,
- ent->name);
- continue;
- }
-
- if (strcmp(ent->name, "pcap_n_pkt_wr") == 0) {
- int status;
-
-#ifndef RTE_PORT_PCAP
- PARSE_ERROR_INVALID(0, section_name, ent->name);
-#endif
-
- status = parse_pipeline_pcap_sink(app, param,
- NULL, ent->value);
-
- PARSE_ERROR((status == 0), section_name,
- ent->name);
- continue;
- }
-
/* pipeline type specific items */
APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS),
"Parse error in section \"%s\": too many "
@@ -1541,17 +1076,13 @@ parse_pipeline(struct app_params *app,
param->n_args++;
}
- param->parsed = 1;
-
snprintf(name, sizeof(name), "MSGQ-REQ-%s", section_name);
param_idx = APP_PARAM_ADD(app->msgq_params, name);
- PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name);
app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
param->msgq_in[param->n_msgq_in++] = param_idx;
snprintf(name, sizeof(name), "MSGQ-RSP-%s", section_name);
param_idx = APP_PARAM_ADD(app->msgq_params, name);
- PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name);
app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
param->msgq_out[param->n_msgq_out++] = param_idx;
@@ -1560,7 +1091,6 @@ parse_pipeline(struct app_params *app,
param->core_id,
(param->hyper_th_id) ? "h" : "");
param_idx = APP_PARAM_ADD(app->msgq_params, name);
- PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name);
app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
snprintf(name, sizeof(name), "MSGQ-RSP-CORE-s%" PRIu32 "c%" PRIu32 "%s",
@@ -1568,7 +1098,6 @@ parse_pipeline(struct app_params *app,
param->core_id,
(param->hyper_th_id) ? "h" : "");
param_idx = APP_PARAM_ADD(app->msgq_params, name);
- PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name);
app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
free(entries);
@@ -1593,9 +1122,8 @@ parse_mempool(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -1640,11 +1168,152 @@ parse_mempool(struct app_params *app,
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- param->parsed = 1;
-
free(entries);
}
+static int
+parse_link_rss_qs(struct app_link_params *p,
+ char *value)
+{
+ p->n_rss_qs = 0;
+
+ while (1) {
+ char *token = strtok_r(value, PARSE_DELIMITER, &value);
+
+ if (token == NULL)
+ break;
+
+ if (p->n_rss_qs == RTE_DIM(p->rss_qs))
+ return -ENOMEM;
+
+ if (parser_read_uint32(&p->rss_qs[p->n_rss_qs++], token))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+parse_link_rss_proto_ipv4(struct app_link_params *p,
+ char *value)
+{
+ uint64_t mask = 0;
+
+ while (1) {
+ char *token = strtok_r(value, PARSE_DELIMITER, &value);
+
+ if (token == NULL)
+ break;
+
+ if (strcmp(token, "IP") == 0) {
+ mask |= ETH_RSS_IPV4;
+ continue;
+ }
+ if (strcmp(token, "FRAG") == 0) {
+ mask |= ETH_RSS_FRAG_IPV4;
+ continue;
+ }
+ if (strcmp(token, "TCP") == 0) {
+ mask |= ETH_RSS_NONFRAG_IPV4_TCP;
+ continue;
+ }
+ if (strcmp(token, "UDP") == 0) {
+ mask |= ETH_RSS_NONFRAG_IPV4_UDP;
+ continue;
+ }
+ if (strcmp(token, "SCTP") == 0) {
+ mask |= ETH_RSS_NONFRAG_IPV4_SCTP;
+ continue;
+ }
+ if (strcmp(token, "OTHER") == 0) {
+ mask |= ETH_RSS_NONFRAG_IPV4_OTHER;
+ continue;
+ }
+ return -EINVAL;
+ }
+
+ p->rss_proto_ipv4 = mask;
+ return 0;
+}
+
+static int
+parse_link_rss_proto_ipv6(struct app_link_params *p,
+ char *value)
+{
+ uint64_t mask = 0;
+
+ while (1) {
+ char *token = strtok_r(value, PARSE_DELIMITER, &value);
+
+ if (token == NULL)
+ break;
+
+ if (strcmp(token, "IP") == 0) {
+ mask |= ETH_RSS_IPV6;
+ continue;
+ }
+ if (strcmp(token, "FRAG") == 0) {
+ mask |= ETH_RSS_FRAG_IPV6;
+ continue;
+ }
+ if (strcmp(token, "TCP") == 0) {
+ mask |= ETH_RSS_NONFRAG_IPV6_TCP;
+ continue;
+ }
+ if (strcmp(token, "UDP") == 0) {
+ mask |= ETH_RSS_NONFRAG_IPV6_UDP;
+ continue;
+ }
+ if (strcmp(token, "SCTP") == 0) {
+ mask |= ETH_RSS_NONFRAG_IPV6_SCTP;
+ continue;
+ }
+ if (strcmp(token, "OTHER") == 0) {
+ mask |= ETH_RSS_NONFRAG_IPV6_OTHER;
+ continue;
+ }
+ if (strcmp(token, "IP_EX") == 0) {
+ mask |= ETH_RSS_IPV6_EX;
+ continue;
+ }
+ if (strcmp(token, "TCP_EX") == 0) {
+ mask |= ETH_RSS_IPV6_TCP_EX;
+ continue;
+ }
+ if (strcmp(token, "UDP_EX") == 0) {
+ mask |= ETH_RSS_IPV6_UDP_EX;
+ continue;
+ }
+ return -EINVAL;
+ }
+
+ p->rss_proto_ipv6 = mask;
+ return 0;
+}
+
+static int
+parse_link_rss_proto_l2(struct app_link_params *p,
+ char *value)
+{
+ uint64_t mask = 0;
+
+ while (1) {
+ char *token = strtok_r(value, PARSE_DELIMITER, &value);
+
+ if (token == NULL)
+ break;
+
+ if (strcmp(token, "L2") == 0) {
+ mask |= ETH_RSS_L2_PAYLOAD;
+ continue;
+ }
+ return -EINVAL;
+ }
+
+ p->rss_proto_l2 = mask;
+ return 0;
+}
+
static void
parse_link(struct app_params *app,
const char *section_name,
@@ -1653,6 +1322,10 @@ parse_link(struct app_params *app,
struct app_link_params *param;
struct rte_cfgfile_entry *entries;
int n_entries, i;
+ int rss_qs_present = 0;
+ int rss_proto_ipv4_present = 0;
+ int rss_proto_ipv6_present = 0;
+ int rss_proto_l2_present = 0;
int pci_bdf_present = 0;
ssize_t param_idx;
@@ -1665,9 +1338,8 @@ parse_link(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -1707,7 +1379,6 @@ parse_link(struct app_params *app,
continue;
}
-
if (strcmp(ent->name, "tcp_local_q") == 0) {
int status = parser_read_uint32(
&param->tcp_local_q, ent->value);
@@ -1735,6 +1406,44 @@ parse_link(struct app_params *app,
continue;
}
+ if (strcmp(ent->name, "rss_qs") == 0) {
+ int status = parse_link_rss_qs(param, ent->value);
+
+ PARSE_ERROR((status == 0), section_name,
+ ent->name);
+ rss_qs_present = 1;
+ continue;
+ }
+
+ if (strcmp(ent->name, "rss_proto_ipv4") == 0) {
+ int status =
+ parse_link_rss_proto_ipv4(param, ent->value);
+
+ PARSE_ERROR((status != -EINVAL), section_name,
+ ent->name);
+ rss_proto_ipv4_present = 1;
+ continue;
+ }
+
+ if (strcmp(ent->name, "rss_proto_ipv6") == 0) {
+ int status =
+ parse_link_rss_proto_ipv6(param, ent->value);
+
+ PARSE_ERROR((status != -EINVAL), section_name,
+ ent->name);
+ rss_proto_ipv6_present = 1;
+ continue;
+ }
+
+ if (strcmp(ent->name, "rss_proto_l2") == 0) {
+ int status = parse_link_rss_proto_l2(param, ent->value);
+
+ PARSE_ERROR((status != -EINVAL), section_name,
+ ent->name);
+ rss_proto_l2_present = 1;
+ continue;
+ }
+
if (strcmp(ent->name, "pci_bdf") == 0) {
PARSE_ERROR_DUPLICATE((pci_bdf_present == 0),
section_name, ent->name);
@@ -1760,7 +1469,28 @@ parse_link(struct app_params *app,
"this entry is mandatory (port_mask is not "
"provided)");
- param->parsed = 1;
+ if (rss_proto_ipv4_present)
+ PARSE_ERROR_MESSAGE((rss_qs_present),
+ section_name, "rss_proto_ipv4",
+ "entry not allowed (rss_qs entry is not provided)");
+ if (rss_proto_ipv6_present)
+ PARSE_ERROR_MESSAGE((rss_qs_present),
+ section_name, "rss_proto_ipv6",
+ "entry not allowed (rss_qs entry is not provided)");
+ if (rss_proto_l2_present)
+ PARSE_ERROR_MESSAGE((rss_qs_present),
+ section_name, "rss_proto_l2",
+ "entry not allowed (rss_qs entry is not provided)");
+ if (rss_proto_ipv4_present |
+ rss_proto_ipv6_present |
+ rss_proto_l2_present){
+ if (rss_proto_ipv4_present == 0)
+ param->rss_proto_ipv4 = 0;
+ if (rss_proto_ipv6_present == 0)
+ param->rss_proto_ipv6 = 0;
+ if (rss_proto_l2_present == 0)
+ param->rss_proto_l2 = 0;
+ }
free(entries);
}
@@ -1784,9 +1514,10 @@ parse_rxq(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
+
+ APP_PARAM_ADD_LINK_FOR_RXQ(app, section_name);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -1798,10 +1529,8 @@ parse_rxq(struct app_params *app,
PARSE_ERROR((status == 0), section_name,
ent->name);
- idx = APP_PARAM_ADD(app->mempool_params,
- ent->value);
- PARSER_PARAM_ADD_CHECK(idx, app->mempool_params,
- section_name);
+
+ idx = APP_PARAM_ADD(app->mempool_params, ent->value);
param->mempool_id = idx;
continue;
}
@@ -1828,8 +1557,6 @@ parse_rxq(struct app_params *app,
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- param->parsed = 1;
-
free(entries);
}
@@ -1852,9 +1579,10 @@ parse_txq(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
+
+ APP_PARAM_ADD_LINK_FOR_TXQ(app, section_name);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -1887,12 +1615,19 @@ parse_txq(struct app_params *app,
continue;
}
+ if (strcmp(ent->name, "n_retries") == 0) {
+ int status = parser_read_uint64(&param->n_retries,
+ ent->value);
+
+ PARSE_ERROR((status == 0), section_name,
+ ent->name);
+ continue;
+ }
+
/* unrecognized */
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- param->parsed = 1;
-
free(entries);
}
@@ -1920,9 +1655,8 @@ parse_swq(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -2050,11 +1784,9 @@ parse_swq(struct app_params *app,
PARSE_ERROR((status == 0), section_name,
ent->name);
- idx = APP_PARAM_ADD(app->mempool_params,
- ent->value);
- PARSER_PARAM_ADD_CHECK(idx, app->mempool_params,
- section_name);
+ idx = APP_PARAM_ADD(app->mempool_params, ent->value);
param->mempool_direct_id = idx;
+
mempool_direct_present = 1;
continue;
}
@@ -2066,11 +1798,10 @@ parse_swq(struct app_params *app,
PARSE_ERROR((status == 0), section_name,
ent->name);
- idx = APP_PARAM_ADD(app->mempool_params,
- ent->value);
- PARSER_PARAM_ADD_CHECK(idx, app->mempool_params,
- section_name);
+
+ idx = APP_PARAM_ADD(app->mempool_params, ent->value);
param->mempool_indirect_id = idx;
+
mempool_indirect_present = 1;
continue;
}
@@ -2079,32 +1810,30 @@ parse_swq(struct app_params *app,
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- APP_CHECK(((mtu_present) &&
+ APP_CHECK(((mtu_present == 0) ||
((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),
"Parse error in section \"%s\": IPv4/IPv6 fragmentation "
"is off, therefore entry \"mtu\" is not allowed",
section_name);
- APP_CHECK(((metadata_size_present) &&
+ APP_CHECK(((metadata_size_present == 0) ||
((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),
"Parse error in section \"%s\": IPv4/IPv6 fragmentation "
"is off, therefore entry \"metadata_size\" is "
"not allowed", section_name);
- APP_CHECK(((mempool_direct_present) &&
+ APP_CHECK(((mempool_direct_present == 0) ||
((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),
"Parse error in section \"%s\": IPv4/IPv6 fragmentation "
"is off, therefore entry \"mempool_direct\" is "
"not allowed", section_name);
- APP_CHECK(((mempool_indirect_present) &&
+ APP_CHECK(((mempool_indirect_present == 0) ||
((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),
"Parse error in section \"%s\": IPv4/IPv6 fragmentation "
"is off, therefore entry \"mempool_indirect\" is "
"not allowed", section_name);
- param->parsed = 1;
-
free(entries);
}
@@ -2127,9 +1856,10 @@ parse_tm(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
+
+ APP_PARAM_ADD_LINK_FOR_TM(app, section_name);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -2162,7 +1892,101 @@ parse_tm(struct app_params *app,
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- param->parsed = 1;
+ free(entries);
+}
+
+static void
+parse_kni(struct app_params *app,
+ const char *section_name,
+ struct rte_cfgfile *cfg)
+{
+ struct app_pktq_kni_params *param;
+ struct rte_cfgfile_entry *entries;
+ int n_entries, i;
+ ssize_t param_idx;
+
+ n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
+ PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
+
+ entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
+ PARSE_ERROR_MALLOC(entries != NULL);
+
+ rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
+
+ param_idx = APP_PARAM_ADD(app->kni_params, section_name);
+ param = &app->kni_params[param_idx];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
+
+ APP_PARAM_ADD_LINK_FOR_KNI(app, section_name);
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ if (strcmp(ent->name, "core") == 0) {
+ int status = parse_pipeline_core(
+ &param->socket_id,
+ &param->core_id,
+ &param->hyper_th_id,
+ ent->value);
+
+ PARSE_ERROR((status == 0), section_name,
+ ent->name);
+ param->force_bind = 1;
+ continue;
+ }
+
+ if (strcmp(ent->name, "mempool") == 0) {
+ int status = validate_name(ent->value,
+ "MEMPOOL", 1);
+ ssize_t idx;
+
+ PARSE_ERROR((status == 0), section_name,
+ ent->name);
+
+ idx = APP_PARAM_ADD(app->mempool_params, ent->value);
+ param->mempool_id = idx;
+ continue;
+ }
+
+ if (strcmp(ent->name, "burst_read") == 0) {
+ int status = parser_read_uint32(&param->burst_read,
+ ent->value);
+
+ PARSE_ERROR((status == 0), section_name,
+ ent->name);
+ continue;
+ }
+
+ if (strcmp(ent->name, "burst_write") == 0) {
+ int status = parser_read_uint32(&param->burst_write,
+ ent->value);
+
+ PARSE_ERROR((status == 0), section_name,
+ ent->name);
+ continue;
+ }
+
+ if (strcmp(ent->name, "dropless") == 0) {
+ int status = parser_read_arg_bool(ent->value);
+
+ PARSE_ERROR((status != -EINVAL), section_name,
+ ent->name);
+ param->dropless = status;
+ continue;
+ }
+
+ if (strcmp(ent->name, "n_retries") == 0) {
+ int status = parser_read_uint64(&param->n_retries,
+ ent->value);
+
+ PARSE_ERROR((status == 0), section_name,
+ ent->name);
+ continue;
+ }
+
+ /* unrecognized */
+ PARSE_ERROR_INVALID(0, section_name, ent->name);
+ }
free(entries);
}
@@ -2188,9 +2012,8 @@ parse_source(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -2202,10 +2025,8 @@ parse_source(struct app_params *app,
PARSE_ERROR((status == 0), section_name,
ent->name);
- idx = APP_PARAM_ADD(app->mempool_params,
- ent->value);
- PARSER_PARAM_ADD_CHECK(idx, app->mempool_params,
- section_name);
+
+ idx = APP_PARAM_ADD(app->mempool_params, ent->value);
param->mempool_id = idx;
continue;
}
@@ -2219,7 +2040,7 @@ parse_source(struct app_params *app,
continue;
}
- if (strcmp(ent->name, "pcap_file_rd")) {
+ if (strcmp(ent->name, "pcap_file_rd") == 0) {
PARSE_ERROR_DUPLICATE((pcap_file_present == 0),
section_name, ent->name);
@@ -2251,8 +2072,6 @@ parse_source(struct app_params *app,
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- param->parsed = 1;
-
free(entries);
}
@@ -2277,14 +2096,13 @@ parse_sink(struct app_params *app,
rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
param_idx = APP_PARAM_ADD(app->sink_params, section_name);
- PARSER_PARAM_ADD_CHECK(param_idx, app->sink_params, section_name);
-
param = &app->sink_params[param_idx];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
- if (strcmp(ent->name, "pcap_file_wr")) {
+ if (strcmp(ent->name, "pcap_file_wr") == 0) {
PARSE_ERROR_DUPLICATE((pcap_file_present == 0),
section_name, ent->name);
@@ -2295,7 +2113,7 @@ parse_sink(struct app_params *app,
continue;
}
- if (strcmp(ent->name, "pcap_n_pkt_wr")) {
+ if (strcmp(ent->name, "pcap_n_pkt_wr") == 0) {
int status;
PARSE_ERROR_DUPLICATE((pcap_n_pkt_present == 0),
@@ -2314,8 +2132,6 @@ parse_sink(struct app_params *app,
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- param->parsed = 1;
-
free(entries);
}
@@ -2338,9 +2154,8 @@ parse_msgq_req_pipeline(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -2358,7 +2173,6 @@ parse_msgq_req_pipeline(struct app_params *app,
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- param->parsed = 1;
free(entries);
}
@@ -2381,9 +2195,8 @@ parse_msgq_rsp_pipeline(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -2401,8 +2214,6 @@ parse_msgq_rsp_pipeline(struct app_params *app,
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- param->parsed = 1;
-
free(entries);
}
@@ -2425,9 +2236,8 @@ parse_msgq(struct app_params *app,
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];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
@@ -2454,8 +2264,6 @@ parse_msgq(struct app_params *app,
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
- param->parsed = 1;
-
free(entries);
}
@@ -2478,6 +2286,7 @@ static const struct config_section cfg_file_scheme[] = {
{"TXQ", 2, parse_txq},
{"SWQ", 1, parse_swq},
{"TM", 1, parse_tm},
+ {"KNI", 1, parse_kni},
{"SOURCE", 1, parse_source},
{"SINK", 1, parse_sink},
{"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline},
@@ -2488,10 +2297,7 @@ static const struct config_section cfg_file_scheme[] = {
static void
create_implicit_mempools(struct app_params *app)
{
- ssize_t idx;
-
- idx = APP_PARAM_ADD(app->mempool_params, "MEMPOOL0");
- PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, "start-up");
+ APP_PARAM_ADD(app->mempool_params, "MEMPOOL0");
}
static void
@@ -2510,7 +2316,6 @@ create_implicit_links_from_port_mask(struct app_params *app,
snprintf(name, sizeof(name), "LINK%" PRIu32, link_id);
idx = APP_PARAM_ADD(app->link_params, name);
- PARSER_PARAM_ADD_CHECK(idx, app->link_params, name);
app->link_params[idx].pmd_id = pmd_id;
link_id++;
@@ -2525,6 +2330,11 @@ assign_link_pmd_id_from_pci_bdf(struct app_params *app)
for (i = 0; i < app->n_links; i++) {
struct app_link_params *link = &app->link_params[i];
+ APP_CHECK((strlen(link->pci_bdf)),
+ "Parse error: %s pci_bdf is not configured "
+ "(port_mask is not provided)",
+ link->name);
+
link->pmd_id = i;
}
}
@@ -2615,28 +2425,12 @@ app_config_parse(struct app_params *app, const char *file_name)
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->kni_params, app->n_pktq_kni);
APP_PARAM_COUNT(app->source_params, app->n_pktq_source);
APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink);
APP_PARAM_COUNT(app->msgq_params, app->n_msgq);
APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines);
-#ifdef RTE_PORT_PCAP
- for (i = 0; i < (int)app->n_pktq_source; i++) {
- struct app_pktq_source_params *p = &app->source_params[i];
-
- APP_CHECK((p->file_name), "Parse error: missing "
- "mandatory field \"pcap_file_rd\" for \"%s\"",
- p->name);
- }
-#else
- for (i = 0; i < (int)app->n_pktq_source; i++) {
- struct app_pktq_source_params *p = &app->source_params[i];
-
- APP_CHECK((!p->file_name), "Parse error: invalid field "
- "\"pcap_file_rd\" for \"%s\"", p->name);
- }
-#endif
-
if (app->port_mask == 0)
assign_link_pmd_id_from_pci_bdf(app);
@@ -2803,6 +2597,84 @@ save_links_params(struct app_params *app, FILE *f)
fprintf(f, "%s = %" PRIu32 "\n", "sctp_local_q",
p->sctp_local_q);
+ if (p->n_rss_qs) {
+ uint32_t j;
+
+ /* rss_qs */
+ fprintf(f, "rss_qs = ");
+ for (j = 0; j < p->n_rss_qs; j++)
+ fprintf(f, "%" PRIu32 " ", p->rss_qs[j]);
+ fputc('\n', f);
+
+ /* rss_proto_ipv4 */
+ if (p->rss_proto_ipv4) {
+ fprintf(f, "rss_proto_ipv4 = ");
+ if (p->rss_proto_ipv4 & ETH_RSS_IPV4)
+ fprintf(f, "IP ");
+ if (p->rss_proto_ipv4 & ETH_RSS_FRAG_IPV4)
+ fprintf(f, "FRAG ");
+ if (p->rss_proto_ipv4 &
+ ETH_RSS_NONFRAG_IPV4_TCP)
+ fprintf(f, "TCP ");
+ if (p->rss_proto_ipv4 &
+ ETH_RSS_NONFRAG_IPV4_UDP)
+ fprintf(f, "UDP ");
+ if (p->rss_proto_ipv4 &
+ ETH_RSS_NONFRAG_IPV4_SCTP)
+ fprintf(f, "SCTP ");
+ if (p->rss_proto_ipv4 &
+ ETH_RSS_NONFRAG_IPV4_OTHER)
+ fprintf(f, "OTHER ");
+ fprintf(f, "\n");
+ } else
+ fprintf(f, "; rss_proto_ipv4 = <NONE>\n");
+
+ /* rss_proto_ipv6 */
+ if (p->rss_proto_ipv6) {
+ fprintf(f, "rss_proto_ipv6 = ");
+ if (p->rss_proto_ipv6 & ETH_RSS_IPV6)
+ fprintf(f, "IP ");
+ if (p->rss_proto_ipv6 & ETH_RSS_FRAG_IPV6)
+ fprintf(f, "FRAG ");
+ if (p->rss_proto_ipv6 &
+ ETH_RSS_NONFRAG_IPV6_TCP)
+ fprintf(f, "TCP ");
+ if (p->rss_proto_ipv6 &
+ ETH_RSS_NONFRAG_IPV6_UDP)
+ fprintf(f, "UDP ");
+ if (p->rss_proto_ipv6 &
+ ETH_RSS_NONFRAG_IPV6_SCTP)
+ fprintf(f, "SCTP ");
+ if (p->rss_proto_ipv6 &
+ ETH_RSS_NONFRAG_IPV6_OTHER)
+ fprintf(f, "OTHER ");
+ if (p->rss_proto_ipv6 & ETH_RSS_IPV6_EX)
+ fprintf(f, "IP_EX ");
+ if (p->rss_proto_ipv6 &
+ ETH_RSS_IPV6_TCP_EX)
+ fprintf(f, "TCP_EX ");
+ if (p->rss_proto_ipv6 &
+ ETH_RSS_IPV6_UDP_EX)
+ fprintf(f, "UDP_EX ");
+ fprintf(f, "\n");
+ } else
+ fprintf(f, "; rss_proto_ipv6 = <NONE>\n");
+
+ /* rss_proto_l2 */
+ if (p->rss_proto_l2) {
+ fprintf(f, "rss_proto_l2 = ");
+ if (p->rss_proto_l2 & ETH_RSS_L2_PAYLOAD)
+ fprintf(f, "L2 ");
+ fprintf(f, "\n");
+ } else
+ fprintf(f, "; rss_proto_l2 = <NONE>\n");
+ } else {
+ fprintf(f, "; rss_qs = <NONE>\n");
+ fprintf(f, "; rss_proto_ipv4 = <NONE>\n");
+ fprintf(f, "; rss_proto_ipv6 = <NONE>\n");
+ fprintf(f, "; rss_proto_l2 = <NONE>\n");
+ }
+
if (strlen(p->pci_bdf))
fprintf(f, "%s = %s\n", "pci_bdf", p->pci_bdf);
@@ -2851,6 +2723,7 @@ save_txq_params(struct app_params *app, FILE *f)
fprintf(f, "%s = %s\n",
"dropless",
p->dropless ? "yes" : "no");
+ fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
fputc('\n', f);
}
@@ -2916,6 +2789,53 @@ save_tm_params(struct app_params *app, FILE *f)
}
static void
+save_kni_params(struct app_params *app, FILE *f)
+{
+ struct app_pktq_kni_params *p;
+ size_t i, count;
+
+ count = RTE_DIM(app->kni_params);
+ for (i = 0; i < count; i++) {
+ p = &app->kni_params[i];
+ if (!APP_PARAM_VALID(p))
+ continue;
+
+ /* section name */
+ fprintf(f, "[%s]\n", p->name);
+
+ /* core */
+ if (p->force_bind) {
+ fprintf(f, "; force_bind = 1\n");
+ fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n",
+ p->socket_id,
+ p->core_id,
+ (p->hyper_th_id) ? "h" : "");
+ } else
+ fprintf(f, "; force_bind = 0\n");
+
+ /* mempool */
+ fprintf(f, "%s = %s\n", "mempool",
+ app->mempool_params[p->mempool_id].name);
+
+ /* burst_read */
+ fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read);
+
+ /* burst_write */
+ fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write);
+
+ /* dropless */
+ fprintf(f, "%s = %s\n",
+ "dropless",
+ p->dropless ? "yes" : "no");
+
+ /* n_retries */
+ fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
+
+ fputc('\n', f);
+ }
+}
+
+static void
save_source_params(struct app_params *app, FILE *f)
{
struct app_pktq_source_params *p;
@@ -3022,6 +2942,9 @@ save_pipeline_params(struct app_params *app, FILE *f)
case APP_PKTQ_IN_TM:
name = app->tm_params[pp->id].name;
break;
+ case APP_PKTQ_IN_KNI:
+ name = app->kni_params[pp->id].name;
+ break;
case APP_PKTQ_IN_SOURCE:
name = app->source_params[pp->id].name;
break;
@@ -3056,6 +2979,9 @@ save_pipeline_params(struct app_params *app, FILE *f)
case APP_PKTQ_OUT_TM:
name = app->tm_params[pp->id].name;
break;
+ case APP_PKTQ_OUT_KNI:
+ name = app->kni_params[pp->id].name;
+ break;
case APP_PKTQ_OUT_SINK:
name = app->sink_params[pp->id].name;
break;
@@ -3141,6 +3067,7 @@ app_config_save(struct app_params *app, const char *file_name)
save_txq_params(app, file);
save_swq_params(app, file);
save_tm_params(app, file);
+ save_kni_params(app, file);
save_source_params(app, file);
save_sink_params(app, file);
save_msgq_params(app, file);
@@ -3156,6 +3083,10 @@ app_config_init(struct app_params *app)
memcpy(app, &app_params_default, sizeof(struct app_params));
+ /* configure default_source_params */
+ default_source_params.file_name = strdup("./config/packets.pcap");
+ PARSE_ERROR_MALLOC(default_source_params.file_name != NULL);
+
for (i = 0; i < RTE_DIM(app->mempool_params); i++)
memcpy(&app->mempool_params[i],
&mempool_params_default,
@@ -3186,6 +3117,11 @@ app_config_init(struct app_params *app)
&default_tm_params,
sizeof(default_tm_params));
+ for (i = 0; i < RTE_DIM(app->kni_params); i++)
+ memcpy(&app->kni_params[i],
+ &default_kni_params,
+ sizeof(default_kni_params));
+
for (i = 0; i < RTE_DIM(app->source_params); i++)
memcpy(&app->source_params[i],
&default_source_params,
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index 83422e88..cd167f61 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -55,6 +55,8 @@
#define APP_NAME_SIZE 32
+#define APP_RETA_SIZE_MAX (ETH_RSS_RETA_SIZE_512 / RTE_RETA_GROUP_SIZE)
+
static void
app_init_core_map(struct app_params *app)
{
@@ -902,6 +904,67 @@ app_get_cpu_socket_id(uint32_t pmd_id)
return (status != SOCKET_ID_ANY) ? status : 0;
}
+static inline int
+app_link_rss_enabled(struct app_link_params *cp)
+{
+ return (cp->n_rss_qs) ? 1 : 0;
+}
+
+static void
+app_link_rss_setup(struct app_link_params *cp)
+{
+ struct rte_eth_dev_info dev_info;
+ struct rte_eth_rss_reta_entry64 reta_conf[APP_RETA_SIZE_MAX];
+ uint32_t i;
+ int status;
+
+ /* Get RETA size */
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(cp->pmd_id, &dev_info);
+
+ if (dev_info.reta_size == 0)
+ rte_panic("%s (%u): RSS setup error (null RETA size)\n",
+ cp->name, cp->pmd_id);
+
+ if (dev_info.reta_size > ETH_RSS_RETA_SIZE_512)
+ rte_panic("%s (%u): RSS setup error (RETA size too big)\n",
+ cp->name, cp->pmd_id);
+
+ /* Setup RETA contents */
+ memset(reta_conf, 0, sizeof(reta_conf));
+
+ for (i = 0; i < dev_info.reta_size; i++)
+ reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX;
+
+ for (i = 0; i < dev_info.reta_size; i++) {
+ uint32_t reta_id = i / RTE_RETA_GROUP_SIZE;
+ uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE;
+ uint32_t rss_qs_pos = i % cp->n_rss_qs;
+
+ reta_conf[reta_id].reta[reta_pos] =
+ (uint16_t) cp->rss_qs[rss_qs_pos];
+ }
+
+ /* RETA update */
+ status = rte_eth_dev_rss_reta_update(cp->pmd_id,
+ reta_conf,
+ dev_info.reta_size);
+ if (status != 0)
+ rte_panic("%s (%u): RSS setup error (RETA update failed)\n",
+ cp->name, cp->pmd_id);
+}
+
+static void
+app_init_link_set_config(struct app_link_params *p)
+{
+ if (p->n_rss_qs) {
+ p->conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
+ p->conf.rx_adv_conf.rss_conf.rss_hf = p->rss_proto_ipv4 |
+ p->rss_proto_ipv6 |
+ p->rss_proto_l2;
+ }
+}
+
static void
app_init_link(struct app_params *app)
{
@@ -917,6 +980,7 @@ app_init_link(struct app_params *app)
sscanf(p_link->name, "LINK%" PRIu32, &link_id);
n_hwq_in = app_link_get_n_rxq(app, p_link);
n_hwq_out = app_link_get_n_txq(app, p_link);
+ app_init_link_set_config(p_link);
APP_LOG(app, HIGH, "Initializing %s (%" PRIu32") "
"(%" PRIu32 " RXQ, %" PRIu32 " TXQ) ...",
@@ -1001,9 +1065,13 @@ app_init_link(struct app_params *app)
rte_panic("Cannot start %s (error %" PRId32 ")\n",
p_link->name, status);
- /* LINK UP */
+ /* LINK FILTERS */
app_link_set_arp_filter(app, p_link);
app_link_set_tcp_syn_filter(app, p_link);
+ if (app_link_rss_enabled(p_link))
+ app_link_rss_setup(p_link);
+
+ /* LINK UP */
app_link_up_internal(app, p_link);
}
@@ -1108,6 +1176,111 @@ app_init_tm(struct app_params *app)
}
}
+#ifdef RTE_LIBRTE_KNI
+static int
+kni_config_network_interface(uint8_t port_id, uint8_t if_up) {
+ int ret = 0;
+
+ if (port_id >= rte_eth_dev_count())
+ return -EINVAL;
+
+ ret = (if_up) ?
+ rte_eth_dev_set_link_up(port_id) :
+ rte_eth_dev_set_link_down(port_id);
+
+ return ret;
+}
+
+static int
+kni_change_mtu(uint8_t port_id, unsigned new_mtu) {
+ int ret;
+
+ if (port_id >= rte_eth_dev_count())
+ return -EINVAL;
+
+ if (new_mtu > ETHER_MAX_LEN)
+ return -EINVAL;
+
+ /* Set new MTU */
+ ret = rte_eth_dev_set_mtu(port_id, new_mtu);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+#endif /* RTE_LIBRTE_KNI */
+
+#ifndef RTE_LIBRTE_KNI
+static void
+app_init_kni(struct app_params *app) {
+ if (app->n_pktq_kni == 0)
+ return;
+
+ rte_panic("Can not init KNI without librte_kni support.\n");
+}
+#else
+static void
+app_init_kni(struct app_params *app) {
+ uint32_t i;
+
+ if (app->n_pktq_kni == 0)
+ return;
+
+ rte_kni_init(app->n_pktq_kni);
+
+ for (i = 0; i < app->n_pktq_kni; i++) {
+ struct app_pktq_kni_params *p_kni = &app->kni_params[i];
+ struct app_link_params *p_link;
+ struct rte_eth_dev_info dev_info;
+ struct app_mempool_params *mempool_params;
+ struct rte_mempool *mempool;
+ struct rte_kni_conf conf;
+ struct rte_kni_ops ops;
+
+ /* LINK */
+ p_link = app_get_link_for_kni(app, p_kni);
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(p_link->pmd_id, &dev_info);
+
+ /* MEMPOOL */
+ mempool_params = &app->mempool_params[p_kni->mempool_id];
+ mempool = app->mempool[p_kni->mempool_id];
+
+ /* KNI */
+ memset(&conf, 0, sizeof(conf));
+ snprintf(conf.name, RTE_KNI_NAMESIZE, "%s", p_kni->name);
+ conf.force_bind = p_kni->force_bind;
+ if (conf.force_bind) {
+ int lcore_id;
+
+ lcore_id = cpu_core_map_get_lcore_id(app->core_map,
+ p_kni->socket_id,
+ p_kni->core_id,
+ p_kni->hyper_th_id);
+
+ if (lcore_id < 0)
+ rte_panic("%s invalid CPU core\n", p_kni->name);
+
+ conf.core_id = (uint32_t) lcore_id;
+ }
+ conf.group_id = p_link->pmd_id;
+ conf.mbuf_size = mempool_params->buffer_size;
+ conf.addr = dev_info.pci_dev->addr;
+ conf.id = dev_info.pci_dev->id;
+
+ memset(&ops, 0, sizeof(ops));
+ ops.port_id = (uint8_t) p_link->pmd_id;
+ ops.change_mtu = kni_change_mtu;
+ ops.config_network_if = kni_config_network_interface;
+
+ APP_LOG(app, HIGH, "Initializing %s ...", p_kni->name);
+ app->kni[i] = rte_kni_alloc(mempool, &conf, &ops);
+ if (!app->kni[i])
+ rte_panic("%s init error\n", p_kni->name);
+ }
+}
+#endif /* RTE_LIBRTE_KNI */
+
static void
app_init_msgq(struct app_params *app)
{
@@ -1128,15 +1301,16 @@ app_init_msgq(struct app_params *app)
}
}
-static void app_pipeline_params_get(struct app_params *app,
+void app_pipeline_params_get(struct app_params *app,
struct app_pipeline_params *p_in,
struct pipeline_params *p_out)
{
uint32_t i;
- uint32_t mempool_id;
snprintf(p_out->name, PIPELINE_NAME_SIZE, "%s", p_in->name);
+ snprintf(p_out->type, PIPELINE_TYPE_SIZE, "%s", p_in->type);
+
p_out->socket_id = (int) p_in->socket_id;
p_out->log_level = app->log_level;
@@ -1212,34 +1386,35 @@ static void app_pipeline_params_get(struct app_params *app,
break;
}
case APP_PKTQ_IN_TM:
+ {
out->type = PIPELINE_PORT_IN_SCHED_READER;
out->params.sched.sched = app->tm[in->id];
out->burst_size = app->tm_params[in->id].burst_read;
break;
+ }
+#ifdef RTE_LIBRTE_KNI
+ case APP_PKTQ_IN_KNI:
+ {
+ out->type = PIPELINE_PORT_IN_KNI_READER;
+ out->params.kni.kni = app->kni[in->id];
+ out->burst_size = app->kni_params[in->id].burst_read;
+ break;
+ }
+#endif /* RTE_LIBRTE_KNI */
case APP_PKTQ_IN_SOURCE:
- mempool_id = app->source_params[in->id].mempool_id;
+ {
+ uint32_t mempool_id =
+ app->source_params[in->id].mempool_id;
+
out->type = PIPELINE_PORT_IN_SOURCE;
out->params.source.mempool = app->mempool[mempool_id];
out->burst_size = app->source_params[in->id].burst;
-
-#ifdef RTE_NEXT_ABI
- if (app->source_params[in->id].file_name
- != NULL) {
- out->params.source.file_name = strdup(
- app->source_params[in->id].
- file_name);
- if (out->params.source.file_name == NULL) {
- out->params.source.
- n_bytes_per_pkt = 0;
- break;
- }
- out->params.source.n_bytes_per_pkt =
- app->source_params[in->id].
- n_bytes_per_pkt;
- }
-#endif
-
+ out->params.source.file_name =
+ app->source_params[in->id].file_name;
+ out->params.source.n_bytes_per_pkt =
+ app->source_params[in->id].n_bytes_per_pkt;
break;
+ }
default:
break;
}
@@ -1350,7 +1525,8 @@ static void app_pipeline_params_get(struct app_params *app,
}
break;
}
- case APP_PKTQ_OUT_TM: {
+ case APP_PKTQ_OUT_TM:
+ {
struct rte_port_sched_writer_params *params =
&out->params.sched;
@@ -1360,24 +1536,45 @@ static void app_pipeline_params_get(struct app_params *app,
app->tm_params[in->id].burst_write;
break;
}
- case APP_PKTQ_OUT_SINK:
- out->type = PIPELINE_PORT_OUT_SINK;
- if (app->sink_params[in->id].file_name != NULL) {
- out->params.sink.file_name = strdup(
- app->sink_params[in->id].
- file_name);
- if (out->params.sink.file_name == NULL) {
- out->params.sink.max_n_pkts = 0;
- break;
- }
- out->params.sink.max_n_pkts =
- app->sink_params[in->id].
- n_pkts_to_dump;
+#ifdef RTE_LIBRTE_KNI
+ case APP_PKTQ_OUT_KNI:
+ {
+ struct app_pktq_kni_params *p_kni =
+ &app->kni_params[in->id];
+
+ if (p_kni->dropless == 0) {
+ struct rte_port_kni_writer_params *params =
+ &out->params.kni;
+
+ out->type = PIPELINE_PORT_OUT_KNI_WRITER;
+ params->kni = app->kni[in->id];
+ params->tx_burst_sz =
+ app->kni_params[in->id].burst_write;
} else {
- out->params.sink.file_name = NULL;
- out->params.sink.max_n_pkts = 0;
+ struct rte_port_kni_writer_nodrop_params
+ *params = &out->params.kni_nodrop;
+
+ out->type = PIPELINE_PORT_OUT_KNI_WRITER_NODROP;
+ params->kni = app->kni[in->id];
+ params->tx_burst_sz =
+ app->kni_params[in->id].burst_write;
+ params->n_retries =
+ app->kni_params[in->id].n_retries;
}
break;
+ }
+#endif /* RTE_LIBRTE_KNI */
+ case APP_PKTQ_OUT_SINK:
+ {
+ out->type = PIPELINE_PORT_OUT_SINK;
+ out->params.sink.file_name =
+ app->sink_params[in->id].file_name;
+ out->params.sink.max_n_pkts =
+ app->sink_params[in->id].
+ n_pkts_to_dump;
+
+ break;
+ }
default:
break;
}
@@ -1449,6 +1646,27 @@ app_init_pipelines(struct app_params *app)
}
static void
+app_post_init_pipelines(struct app_params *app)
+{
+ uint32_t p_id;
+
+ for (p_id = 0; p_id < app->n_pipelines; p_id++) {
+ struct app_pipeline_params *params =
+ &app->pipeline_params[p_id];
+ struct app_pipeline_data *data = &app->pipeline_data[p_id];
+ int status;
+
+ if (data->ptype->fe_ops->f_post_init == NULL)
+ continue;
+
+ status = data->ptype->fe_ops->f_post_init(data->fe);
+ if (status)
+ rte_panic("Pipeline instance \"%s\" front-end "
+ "post-init error\n", params->name);
+ }
+}
+
+static void
app_init_threads(struct app_params *app)
{
uint64_t time = rte_get_tsc_cycles();
@@ -1534,6 +1752,7 @@ int app_init(struct app_params *app)
app_init_link(app);
app_init_swq(app);
app_init_tm(app);
+ app_init_kni(app);
app_init_msgq(app);
app_pipeline_common_cmd_push(app);
@@ -1551,6 +1770,13 @@ int app_init(struct app_params *app)
return 0;
}
+int app_post_init(struct app_params *app)
+{
+ app_post_init_pipelines(app);
+
+ return 0;
+}
+
static int
app_pipeline_type_cmd_push(struct app_params *app,
struct pipeline_type *ptype)
diff --git a/examples/ip_pipeline/parser.c b/examples/ip_pipeline/parser.c
new file mode 100644
index 00000000..689e2065
--- /dev/null
+++ b/examples/ip_pipeline/parser.c
@@ -0,0 +1,745 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For my_ether_aton() function:
+ *
+ * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
+ * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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.
+ */
+
+/*
+ * For inet_pton4() and inet_pton6() functions:
+ *
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <rte_errno.h>
+#include <rte_cfgfile.h>
+#include <rte_string_fns.h>
+
+#include "app.h"
+#include "parser.h"
+
+static uint32_t
+get_hex_val(char c)
+{
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ return c - '0';
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ return c - 'A' + 10;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ return c - 'a' + 10;
+ default:
+ return 0;
+ }
+}
+
+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;
+}
+
+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 through */
+ case 'G':
+ val *= 1024ULL;
+ /* fall through */
+ case 'M':
+ val *= 1024ULL;
+ /* fall through */
+ case 'k':
+ case 'K':
+ val *= 1024ULL;
+ p++;
+ break;
+ }
+
+ p = skip_white_spaces(p);
+ if (*p != '\0')
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint64_hex(uint64_t *value, const char *p)
+{
+ char *next;
+ uint64_t val;
+
+ p = skip_white_spaces(p);
+
+ val = strtoul(p, &next, 16);
+ if (p == next)
+ return -EINVAL;
+
+ p = skip_white_spaces(next);
+ if (*p != '\0')
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+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;
+
+ if (val > UINT32_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint32_hex(uint32_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64_hex(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT32_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint16(uint16_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT16_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint16_hex(uint16_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64_hex(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT16_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint8(uint8_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT8_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64_hex(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT8_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
+{
+ uint32_t i;
+
+ if ((string == NULL) ||
+ (tokens == NULL) ||
+ (*n_tokens < 1))
+ return -EINVAL;
+
+ for (i = 0; i < *n_tokens; i++) {
+ tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
+ if (tokens[i] == NULL)
+ break;
+ }
+
+ if ((i == *n_tokens) &&
+ (NULL != strtok_r(string, PARSE_DELIMITER, &string)))
+ return -E2BIG;
+
+ *n_tokens = i;
+ return 0;
+}
+
+int
+parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
+{
+ char *c;
+ uint32_t len, i;
+
+ /* Check input parameters */
+ if ((src == NULL) ||
+ (dst == NULL) ||
+ (size == NULL) ||
+ (*size == 0))
+ return -1;
+
+ len = strlen(src);
+ if (((len & 3) != 0) ||
+ (len > (*size) * 2))
+ return -1;
+ *size = len / 2;
+
+ for (c = src; *c != 0; c++) {
+ if ((((*c) >= '0') && ((*c) <= '9')) ||
+ (((*c) >= 'A') && ((*c) <= 'F')) ||
+ (((*c) >= 'a') && ((*c) <= 'f')))
+ continue;
+
+ return -1;
+ }
+
+ /* Convert chars to bytes */
+ for (i = 0; i < *size; i++)
+ dst[i] = get_hex_val(src[2 * i]) * 16 +
+ get_hex_val(src[2 * i + 1]);
+
+ return 0;
+}
+
+int
+parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
+{
+ uint32_t n_max_labels = *n_labels, count = 0;
+
+ /* Check for void list of labels */
+ if (strcmp(string, "<void>") == 0) {
+ *n_labels = 0;
+ return 0;
+ }
+
+ /* At least one label should be present */
+ for ( ; (*string != '\0'); ) {
+ char *next;
+ int value;
+
+ if (count >= n_max_labels)
+ return -1;
+
+ if (count > 0) {
+ if (string[0] != ':')
+ return -1;
+
+ string++;
+ }
+
+ value = strtol(string, &next, 10);
+ if (next == string)
+ return -1;
+ string = next;
+
+ labels[count++] = (uint32_t) value;
+ }
+
+ *n_labels = count;
+ return 0;
+}
+
+#define INADDRSZ 4
+#define IN6ADDRSZ 16
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ unsigned int new = *tp * 10 + (pch - digits);
+
+ if (new > 255)
+ return 0;
+ if (!saw_digit) {
+ if (++octets > 4)
+ return 0;
+ saw_digit = 1;
+ }
+ *tp = (unsigned char)new;
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return 0;
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return 0;
+ }
+ if (octets < 4)
+ return 0;
+
+ memcpy(dst, tmp, INADDRSZ);
+ return 1;
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, unsigned char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
+ const char *xdigits = 0, *curtok = 0;
+ int ch = 0, saw_xdigit = 0, count_xdigit = 0;
+ unsigned int val = 0;
+ unsigned dbloct_count = 0;
+
+ memset((tp = tmp), '\0', IN6ADDRSZ);
+ endp = tp + IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return 0;
+ curtok = src;
+ saw_xdigit = count_xdigit = 0;
+ val = 0;
+
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr((xdigits = xdigits_l), ch);
+ if (pch == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ if (count_xdigit >= 4)
+ return 0;
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return 0;
+ saw_xdigit = 1;
+ count_xdigit++;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return 0;
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return 0;
+ }
+ if (tp + sizeof(int16_t) > endp)
+ return 0;
+ *tp++ = (unsigned char) ((val >> 8) & 0xff);
+ *tp++ = (unsigned char) (val & 0xff);
+ saw_xdigit = 0;
+ count_xdigit = 0;
+ val = 0;
+ dbloct_count++;
+ continue;
+ }
+ if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += INADDRSZ;
+ saw_xdigit = 0;
+ dbloct_count += 2;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return 0;
+ }
+ if (saw_xdigit) {
+ if (tp + sizeof(int16_t) > endp)
+ return 0;
+ *tp++ = (unsigned char) ((val >> 8) & 0xff);
+ *tp++ = (unsigned char) (val & 0xff);
+ dbloct_count++;
+ }
+ if (colonp != NULL) {
+ /* if we already have 8 double octets, having a colon means error */
+ if (dbloct_count == 8)
+ return 0;
+
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ for (i = 1; i <= n; i++) {
+ endp[-i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return 0;
+ memcpy(dst, tmp, IN6ADDRSZ);
+ return 1;
+}
+
+static struct ether_addr *
+my_ether_aton(const char *a)
+{
+ int i;
+ char *end;
+ unsigned long o[ETHER_ADDR_LEN];
+ static struct ether_addr ether_addr;
+
+ i = 0;
+ do {
+ errno = 0;
+ o[i] = strtoul(a, &end, 16);
+ if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
+ return NULL;
+ a = end + 1;
+ } while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0);
+
+ /* Junk at the end of line */
+ if (end[0] != 0)
+ return NULL;
+
+ /* Support the format XX:XX:XX:XX:XX:XX */
+ if (i == ETHER_ADDR_LEN) {
+ while (i-- != 0) {
+ if (o[i] > UINT8_MAX)
+ return NULL;
+ ether_addr.addr_bytes[i] = (uint8_t)o[i];
+ }
+ /* Support the format XXXX:XXXX:XXXX */
+ } else if (i == ETHER_ADDR_LEN / 2) {
+ while (i-- != 0) {
+ if (o[i] > UINT16_MAX)
+ return NULL;
+ ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
+ ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
+ }
+ /* unknown format */
+ } else
+ return NULL;
+
+ return (struct ether_addr *)&ether_addr;
+}
+
+int
+parse_ipv4_addr(const char *token, struct in_addr *ipv4)
+{
+ if (strlen(token) >= INET_ADDRSTRLEN)
+ return -EINVAL;
+
+ if (inet_pton4(token, (unsigned char *)ipv4) != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+int
+parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
+{
+ if (strlen(token) >= INET6_ADDRSTRLEN)
+ return -EINVAL;
+
+ if (inet_pton6(token, (unsigned char *)ipv6) != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+int
+parse_mac_addr(const char *token, struct ether_addr *addr)
+{
+ struct ether_addr *tmp;
+
+ tmp = my_ether_aton(token);
+ if (tmp == NULL)
+ return -1;
+
+ memcpy(addr, tmp, sizeof(struct ether_addr));
+ return 0;
+}
+
+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 || c_parsed || h_parsed)
+ return -EINVAL;
+ s_parsed = 1;
+ next++;
+ break;
+ case 'c':
+ case 'C':
+ if (c_parsed || h_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' && type != 'H')
+ return -EINVAL;
+
+ if (num_len != 0 && (type == 'h' || 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;
+ break;
+ case 'h':
+ case 'H':
+ h = 1;
+ break;
+ }
+ }
+
+ *socket = s;
+ *core = c;
+ *ht = h;
+ return 0;
+}
diff --git a/examples/ip_pipeline/parser.h b/examples/ip_pipeline/parser.h
index 58b59daf..9bd36af3 100644
--- a/examples/ip_pipeline/parser.h
+++ b/examples/ip_pipeline/parser.h
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,17 +34,51 @@
#ifndef __INCLUDE_PARSER_H__
#define __INCLUDE_PARSER_H__
-int
-parser_read_arg_bool(const char *p);
+#include <stdint.h>
-int
-parser_read_uint64(uint64_t *value, const char *p);
+#include <rte_ip.h>
+#include <rte_ether.h>
-int
-parser_read_uint32(uint32_t *value, const char *p);
+#define PARSE_DELIMITER " \f\n\r\t\v"
-int
-parse_hex_string(char *src, uint8_t *dst, uint32_t *size);
+#define skip_white_spaces(pos) \
+({ \
+ __typeof__(pos) _p = (pos); \
+ for ( ; isspace(*_p); _p++) \
+ ; \
+ _p; \
+})
-#endif
+static inline size_t
+skip_digits(const char *src)
+{
+ size_t i;
+
+ for (i = 0; isdigit(src[i]); i++)
+ ;
+
+ return i;
+}
+
+int parser_read_arg_bool(const char *p);
+
+int parser_read_uint64(uint64_t *value, const char *p);
+int parser_read_uint32(uint32_t *value, const char *p);
+int parser_read_uint16(uint16_t *value, const char *p);
+int parser_read_uint8(uint8_t *value, const char *p);
+int parser_read_uint64_hex(uint64_t *value, const char *p);
+int parser_read_uint32_hex(uint32_t *value, const char *p);
+int parser_read_uint16_hex(uint16_t *value, const char *p);
+int parser_read_uint8_hex(uint8_t *value, const char *p);
+
+int parse_hex_string(char *src, uint8_t *dst, uint32_t *size);
+
+int parse_ipv4_addr(const char *token, struct in_addr *ipv4);
+int parse_ipv6_addr(const char *token, struct in6_addr *ipv6);
+int parse_mac_addr(const char *token, struct ether_addr *addr);
+int parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels);
+
+int parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens);
+
+#endif
diff --git a/examples/ip_pipeline/pipeline.h b/examples/ip_pipeline/pipeline.h
index dab9c36d..14a551db 100644
--- a/examples/ip_pipeline/pipeline.h
+++ b/examples/ip_pipeline/pipeline.h
@@ -42,13 +42,22 @@
* Pipeline type front-end operations
*/
-typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params, void *arg);
+typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params,
+ void *arg);
+
+typedef int (*pipeline_fe_op_post_init)(void *pipeline);
typedef int (*pipeline_fe_op_free)(void *pipeline);
+typedef int (*pipeline_fe_op_track)(struct pipeline_params *params,
+ uint32_t port_in,
+ uint32_t *port_out);
+
struct pipeline_fe_ops {
pipeline_fe_op_init f_init;
+ pipeline_fe_op_post_init f_post_init;
pipeline_fe_op_free f_free;
+ pipeline_fe_op_track f_track;
cmdline_parse_ctx_t *cmds;
};
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c
index a691d422..cd1d082a 100644
--- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c
+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,12 +42,146 @@
#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"
+#include "parser.h"
+
+struct app_link_params *
+app_pipeline_track_pktq_out_to_link(struct app_params *app,
+ uint32_t pipeline_id,
+ uint32_t pktq_out_id)
+{
+ struct app_pipeline_params *p;
+
+ /* Check input arguments */
+ if (app == NULL)
+ return NULL;
+
+ APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
+ if (p == NULL)
+ return NULL;
+
+ for ( ; ; ) {
+ struct app_pktq_out_params *pktq_out =
+ &p->pktq_out[pktq_out_id];
+
+ switch (pktq_out->type) {
+ case APP_PKTQ_OUT_HWQ:
+ {
+ struct app_pktq_hwq_out_params *hwq_out;
+
+ hwq_out = &app->hwq_out_params[pktq_out->id];
+
+ return app_get_link_for_txq(app, hwq_out);
+ }
+
+ case APP_PKTQ_OUT_SWQ:
+ {
+ struct pipeline_params pp;
+ struct pipeline_type *ptype;
+ struct app_pktq_swq_params *swq;
+ uint32_t pktq_in_id;
+ int status;
+
+ swq = &app->swq_params[pktq_out->id];
+ p = app_swq_get_reader(app, swq, &pktq_in_id);
+ if (p == NULL)
+ return NULL;
+
+ ptype = app_pipeline_type_find(app, p->type);
+ if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL))
+ return NULL;
+
+ app_pipeline_params_get(app, p, &pp);
+ status = ptype->fe_ops->f_track(&pp,
+ pktq_in_id,
+ &pktq_out_id);
+ if (status)
+ return NULL;
+
+ break;
+ }
+
+ case APP_PKTQ_OUT_TM:
+ {
+ struct pipeline_params pp;
+ struct pipeline_type *ptype;
+ struct app_pktq_tm_params *tm;
+ uint32_t pktq_in_id;
+ int status;
+
+ tm = &app->tm_params[pktq_out->id];
+ p = app_tm_get_reader(app, tm, &pktq_in_id);
+ if (p == NULL)
+ return NULL;
+
+ ptype = app_pipeline_type_find(app, p->type);
+ if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL))
+ return NULL;
+
+ app_pipeline_params_get(app, p, &pp);
+ status = ptype->fe_ops->f_track(&pp,
+ pktq_in_id,
+ &pktq_out_id);
+ if (status)
+ return NULL;
+
+ break;
+ }
+
+ case APP_PKTQ_OUT_KNI:
+ {
+ struct pipeline_params pp;
+ struct pipeline_type *ptype;
+ struct app_pktq_kni_params *kni;
+ uint32_t pktq_in_id;
+ int status;
+
+ kni = &app->kni_params[pktq_out->id];
+ p = app_kni_get_reader(app, kni, &pktq_in_id);
+ if (p == NULL)
+ return NULL;
+
+ ptype = app_pipeline_type_find(app, p->type);
+ if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL))
+ return NULL;
+
+ app_pipeline_params_get(app, p, &pp);
+ status = ptype->fe_ops->f_track(&pp,
+ pktq_in_id,
+ &pktq_out_id);
+ if (status)
+ return NULL;
+
+ break;
+ }
+
+ case APP_PKTQ_OUT_SINK:
+ default:
+ return NULL;
+ }
+ }
+}
+
+int
+app_pipeline_track_default(struct pipeline_params *p,
+ uint32_t port_in,
+ uint32_t *port_out)
+{
+ /* Check input arguments */
+ if ((p == NULL) ||
+ (port_in >= p->n_ports_in) ||
+ (port_out == NULL))
+ return -1;
+
+ if (p->n_ports_out == 1) {
+ *port_out = 0;
+ return 0;
+ }
+
+ return -1;
+}
int
app_pipeline_ping(struct app_params *app,
@@ -312,6 +446,40 @@ app_pipeline_port_in_disable(struct app_params *app,
}
int
+app_link_set_op(struct app_params *app,
+ uint32_t link_id,
+ uint32_t pipeline_id,
+ app_link_op op,
+ void *arg)
+{
+ struct app_pipeline_params *pp;
+ struct app_link_params *lp;
+ struct app_link_data *ld;
+ uint32_t ppos, lpos;
+
+ /* Check input arguments */
+ if ((app == NULL) ||
+ (op == NULL))
+ return -1;
+
+ APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, lp);
+ if (lp == NULL)
+ return -1;
+ lpos = lp - app->link_params;
+ ld = &app->link_data[lpos];
+
+ APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, pp);
+ if (pp == NULL)
+ return -1;
+ ppos = pp - app->pipeline_params;
+
+ ld->f_link[ppos] = op;
+ ld->arg[ppos] = arg;
+
+ return 0;
+}
+
+int
app_link_config(struct app_params *app,
uint32_t link_id,
uint32_t ip,
@@ -382,6 +550,8 @@ app_link_up(struct app_params *app,
uint32_t link_id)
{
struct app_link_params *p;
+ struct app_link_data *d;
+ int i;
/* Check input arguments */
if (app == NULL)
@@ -394,6 +564,8 @@ app_link_up(struct app_params *app,
return -1;
}
+ d = &app->link_data[p - app->link_params];
+
/* Check link state */
if (p->state) {
APP_LOG(app, HIGH, "%s is already UP", p->name);
@@ -408,6 +580,11 @@ app_link_up(struct app_params *app,
app_link_up_internal(app, p);
+ /* Callbacks */
+ for (i = 0; i < APP_MAX_PIPELINES; i++)
+ if (d->f_link[i])
+ d->f_link[i](app, link_id, 1, d->arg[i]);
+
return 0;
}
@@ -416,6 +593,8 @@ app_link_down(struct app_params *app,
uint32_t link_id)
{
struct app_link_params *p;
+ struct app_link_data *d;
+ uint32_t i;
/* Check input arguments */
if (app == NULL)
@@ -428,6 +607,8 @@ app_link_down(struct app_params *app,
return -1;
}
+ d = &app->link_data[p - app->link_params];
+
/* Check link state */
if (p->state == 0) {
APP_LOG(app, HIGH, "%s is already DOWN", p->name);
@@ -436,6 +617,11 @@ app_link_down(struct app_params *app,
app_link_down_internal(app, p);
+ /* Callbacks */
+ for (i = 0; i < APP_MAX_PIPELINES; i++)
+ if (d->f_link[i])
+ d->f_link[i](app, link_id, 0, d->arg[i]);
+
return 0;
}
@@ -464,16 +650,16 @@ cmd_ping_parsed(
printf("Command failed\n");
}
-cmdline_parse_token_string_t cmd_ping_p_string =
+static 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 =
+static 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 =
+static 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 = {
+static cmdline_parse_inst_t cmd_ping = {
.f = cmd_ping_parsed,
.data = NULL,
.help_str = "Pipeline ping",
@@ -498,6 +684,7 @@ struct cmd_stats_port_in_result {
uint32_t port_in_id;
};
+
static void
cmd_stats_port_in_parsed(
void *parsed_result,
@@ -531,23 +718,23 @@ cmd_stats_port_in_parsed(
stats.stats.n_pkts_drop);
}
-cmdline_parse_token_string_t cmd_stats_port_in_p_string =
+static 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 =
+static 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 =
+static 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 =
+static 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 =
+static cmdline_parse_token_string_t cmd_stats_port_in_in_string =
TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, in_string,
"in");
@@ -555,7 +742,7 @@ cmdline_parse_token_string_t cmd_stats_port_in_in_string =
TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, port_in_id,
UINT32);
-cmdline_parse_inst_t cmd_stats_port_in = {
+static cmdline_parse_inst_t cmd_stats_port_in = {
.f = cmd_stats_port_in_parsed,
.data = NULL,
.help_str = "Pipeline input port stats",
@@ -617,31 +804,31 @@ cmd_stats_port_out_parsed(
stats.stats.n_pkts_drop);
}
-cmdline_parse_token_string_t cmd_stats_port_out_p_string =
+static 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 =
+static 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 =
+static 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 =
+static 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 =
+static 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 =
+static cmdline_parse_token_num_t cmd_stats_port_out_port_out_id =
TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, port_out_id,
UINT32);
-cmdline_parse_inst_t cmd_stats_port_out = {
+static cmdline_parse_inst_t cmd_stats_port_out = {
.f = cmd_stats_port_out_parsed,
.data = NULL,
.help_str = "Pipeline output port stats",
@@ -707,26 +894,26 @@ cmd_stats_table_parsed(
stats.n_pkts_dropped_lkp_miss);
}
-cmdline_parse_token_string_t cmd_stats_table_p_string =
+static 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 =
+static 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 =
+static 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 =
+static 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 =
+static 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 = {
+static cmdline_parse_inst_t cmd_stats_table = {
.f = cmd_stats_table_parsed,
.data = NULL,
.help_str = "Pipeline table stats",
@@ -771,31 +958,31 @@ cmd_port_in_enable_parsed(
printf("Command failed\n");
}
-cmdline_parse_token_string_t cmd_port_in_enable_p_string =
+static 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 =
+static 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 =
+static 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 =
+static 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 =
+static cmdline_parse_token_num_t cmd_port_in_enable_port_in_id =
TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, port_in_id,
UINT32);
-cmdline_parse_token_string_t cmd_port_in_enable_enable_string =
+static 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 = {
+static cmdline_parse_inst_t cmd_port_in_enable = {
.f = cmd_port_in_enable_parsed,
.data = NULL,
.help_str = "Pipeline input port enable",
@@ -841,31 +1028,31 @@ cmd_port_in_disable_parsed(
printf("Command failed\n");
}
-cmdline_parse_token_string_t cmd_port_in_disable_p_string =
+static 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 =
+static 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 =
+static 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 =
+static 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 =
+static cmdline_parse_token_num_t cmd_port_in_disable_port_in_id =
TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, port_in_id,
UINT32);
-cmdline_parse_token_string_t cmd_port_in_disable_disable_string =
+static 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 = {
+static cmdline_parse_inst_t cmd_port_in_disable = {
.f = cmd_port_in_disable_parsed,
.data = NULL,
.help_str = "Pipeline input port disable",
@@ -963,219 +1150,144 @@ print_link_info(struct app_link_params *p)
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
+ * link
+ *
+ * link config:
+ * link <linkid> config <ipaddr> <depth>
+ *
+ * link up:
+ * link <linkid> up
+ *
+ * link down:
+ * link <linkid> down
+ *
+ * link ls:
+ * link ls
*/
-struct cmd_link_up_result {
+struct cmd_link_result {
cmdline_fixed_string_t link_string;
- uint32_t link_id;
- cmdline_fixed_string_t up_string;
+ cmdline_multi_string_t multi_string;
};
static void
-cmd_link_up_parsed(
+cmd_link_parsed(
void *parsed_result,
__attribute__((unused)) struct cmdline *cl,
- void *data)
+ void *data)
{
- struct cmd_link_up_result *params = parsed_result;
+ struct cmd_link_result *params = parsed_result;
struct app_params *app = data;
+
+ char *tokens[16];
+ uint32_t n_tokens = RTE_DIM(tokens);
int status;
- status = app_link_up(app, params->link_id);
- if (status != 0)
- printf("Command failed\n");
- else {
- struct app_link_params *p;
+ uint32_t link_id;
- APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id,
- p);
- print_link_info(p);
+ status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
+ if (status != 0) {
+ printf(CMD_MSG_TOO_MANY_ARGS, "link");
+ return;
}
-}
-
-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);
+ /* link ls */
+ if ((n_tokens == 1) && (strcmp(tokens[0], "ls") == 0)) {
+ for (link_id = 0; link_id < app->n_links; link_id++) {
+ struct app_link_params *p;
-cmdline_parse_token_string_t cmd_link_up_up_string =
- TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, up_string, "up");
+ APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
+ print_link_info(p);
+ }
+ return;
+ } /* link ls */
-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,
- },
-};
+ if (n_tokens < 2) {
+ printf(CMD_MSG_MISMATCH_ARGS, "link");
+ return;
+ }
-/*
- * link down
- */
+ if (parser_read_uint32(&link_id, tokens[0])) {
+ printf(CMD_MSG_INVALID_ARG, "linkid");
+ return;
+ }
-struct cmd_link_down_result {
- cmdline_fixed_string_t link_string;
- uint32_t link_id;
- cmdline_fixed_string_t down_string;
-};
+ /* link config */
+ if (strcmp(tokens[1], "config") == 0) {
+ struct in_addr ipaddr_ipv4;
+ uint32_t depth;
-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;
+ if (n_tokens != 4) {
+ printf(CMD_MSG_MISMATCH_ARGS, "link config");
+ return;
+ }
- status = app_link_down(app, params->link_id);
- if (status != 0)
- printf("Command failed\n");
- else {
- struct app_link_params *p;
+ if (parse_ipv4_addr(tokens[2], &ipaddr_ipv4)) {
+ printf(CMD_MSG_INVALID_ARG, "ipaddr");
+ return;
+ }
- APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id,
- p);
- print_link_info(p);
- }
-}
+ if (parser_read_uint32(&depth, tokens[3])) {
+ printf(CMD_MSG_INVALID_ARG, "depth");
+ return;
+ }
-cmdline_parse_token_string_t cmd_link_down_link_string =
- TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, link_string,
- "link");
+ status = app_link_config(app,
+ link_id,
+ rte_be_to_cpu_32(ipaddr_ipv4.s_addr),
+ depth);
+ if (status)
+ printf(CMD_MSG_FAIL, "link config");
-cmdline_parse_token_num_t cmd_link_down_link_id =
- TOKEN_NUM_INITIALIZER(struct cmd_link_down_result, link_id, UINT32);
+ return;
+ } /* link config */
-cmdline_parse_token_string_t cmd_link_down_down_string =
- TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, down_string,
- "down");
+ /* link up */
+ if (strcmp(tokens[1], "up") == 0) {
+ if (n_tokens != 2) {
+ printf(CMD_MSG_MISMATCH_ARGS, "link up");
+ return;
+ }
-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,
- },
-};
+ status = app_link_up(app, link_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "link up");
-/*
- * link ls
- */
+ return;
+ } /* link up */
-struct cmd_link_ls_result {
- cmdline_fixed_string_t link_string;
- cmdline_fixed_string_t ls_string;
-};
+ /* link down */
+ if (strcmp(tokens[1], "down") == 0) {
+ if (n_tokens != 2) {
+ printf(CMD_MSG_MISMATCH_ARGS, "link down");
+ return;
+ }
-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;
+ status = app_link_down(app, link_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "link down");
- for (link_id = 0; link_id < app->n_links; link_id++) {
- struct app_link_params *p;
+ return;
+ } /* link down */
- APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
- print_link_info(p);
- }
+ printf(CMD_MSG_MISMATCH_ARGS, "link");
}
-cmdline_parse_token_string_t cmd_link_ls_link_string =
- TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, link_string,
- "link");
+static cmdline_parse_token_string_t cmd_link_link_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_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");
+static cmdline_parse_token_string_t cmd_link_multi_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_result, multi_string,
+ TOKEN_STRING_MULTI);
-cmdline_parse_inst_t cmd_link_ls = {
- .f = cmd_link_ls_parsed,
+static cmdline_parse_inst_t cmd_link = {
+ .f = cmd_link_parsed,
.data = NULL,
- .help_str = "Link list",
+ .help_str = "link config / up / down / ls",
.tokens = {
- (void *)&cmd_link_ls_link_string,
- (void *)&cmd_link_ls_ls_string,
+ (void *) &cmd_link_link_string,
+ (void *) &cmd_link_multi_string,
NULL,
},
};
@@ -1212,6 +1324,11 @@ static cmdline_parse_inst_t cmd_quit = {
/*
* run
+ *
+ * run <file>
+ * run <file> [<count> [<interval>]]
+ <count> default is 1
+ * <interval> is measured in milliseconds, default is 1 second
*/
static void
@@ -1233,9 +1350,9 @@ app_run_file(
close(fd);
}
-struct cmd_run_file_result {
+struct cmd_run_result {
cmdline_fixed_string_t run_string;
- char file_name[APP_FILE_NAME_SIZE];
+ cmdline_multi_string_t multi_string;
};
static void
@@ -1244,25 +1361,87 @@ cmd_run_parsed(
struct cmdline *cl,
__attribute__((unused)) void *data)
{
- struct cmd_run_file_result *params = parsed_result;
+ struct cmd_run_result *params = parsed_result;
+
+ char *tokens[16];
+ uint32_t n_tokens = RTE_DIM(tokens);
+ int status;
+
+ char *file_name;
+ uint32_t count, interval, i;
- app_run_file(cl->ctx, params->file_name);
+ status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
+ if (status) {
+ printf(CMD_MSG_TOO_MANY_ARGS, "run");
+ return;
+ }
+
+ switch (n_tokens) {
+ case 0:
+ printf(CMD_MSG_NOT_ENOUGH_ARGS, "run");
+ return;
+
+ case 1:
+ file_name = tokens[0];
+ count = 1;
+ interval = 1000;
+ break;
+
+ case 2:
+ file_name = tokens[0];
+
+ if (parser_read_uint32(&count, tokens[1]) ||
+ (count == 0)) {
+ printf(CMD_MSG_INVALID_ARG, "count");
+ return;
+ }
+
+ interval = 1000;
+ break;
+
+ case 3:
+ file_name = tokens[0];
+
+ if (parser_read_uint32(&count, tokens[1]) ||
+ (count == 0)) {
+ printf(CMD_MSG_INVALID_ARG, "count");
+ return;
+ }
+
+ if (parser_read_uint32(&interval, tokens[2]) ||
+ (interval == 0)) {
+ printf(CMD_MSG_INVALID_ARG, "interval");
+ return;
+ }
+ break;
+
+ default:
+ printf(CMD_MSG_MISMATCH_ARGS, "run");
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ app_run_file(cl->ctx, file_name);
+ if (interval)
+ usleep(interval * 1000);
+ }
}
-cmdline_parse_token_string_t cmd_run_run_string =
- TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string,
- "run");
+static cmdline_parse_token_string_t cmd_run_run_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_run_result, run_string, "run");
+
+static cmdline_parse_token_string_t cmd_run_multi_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_run_result, multi_string,
+ TOKEN_STRING_MULTI);
-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 = {
+static cmdline_parse_inst_t cmd_run = {
.f = cmd_run_parsed,
.data = NULL,
.help_str = "Run CLI script file",
.tokens = {
(void *) &cmd_run_run_string,
- (void *) &cmd_run_file_name,
+ (void *) &cmd_run_multi_string,
NULL,
},
};
@@ -1270,12 +1449,7 @@ cmdline_parse_inst_t cmd_run = {
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_link,
(cmdline_parse_inst_t *) &cmd_ping,
(cmdline_parse_inst_t *) &cmd_stats_port_in,
(cmdline_parse_inst_t *) &cmd_stats_port_out,
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.h b/examples/ip_pipeline/pipeline/pipeline_common_fe.h
index cfad963d..ce0bf13e 100644
--- a/examples/ip_pipeline/pipeline/pipeline_common_fe.h
+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.h
@@ -182,6 +182,16 @@ app_msg_send_recv(struct app_params *app,
return msg_recv;
}
+struct app_link_params *
+app_pipeline_track_pktq_out_to_link(struct app_params *app,
+ uint32_t pipeline_id,
+ uint32_t pktq_out_id);
+
+int
+app_pipeline_track_default(struct pipeline_params *params,
+ uint32_t port_in,
+ uint32_t *port_out);
+
int
app_pipeline_ping(struct app_params *app,
uint32_t pipeline_id);
@@ -215,6 +225,13 @@ app_pipeline_port_in_disable(struct app_params *app,
uint32_t port_id);
int
+app_link_set_op(struct app_params *app,
+ uint32_t link_id,
+ uint32_t pipeline_id,
+ app_link_op op,
+ void *arg);
+
+int
app_link_config(struct app_params *app,
uint32_t link_id,
uint32_t ip,
@@ -231,4 +248,13 @@ app_link_down(struct app_params *app,
int
app_pipeline_common_cmd_push(struct app_params *app);
+#define CMD_MSG_OUT_OF_MEMORY "Not enough memory\n"
+#define CMD_MSG_NOT_ENOUGH_ARGS "Not enough arguments for command \"%s\"\n"
+#define CMD_MSG_TOO_MANY_ARGS "Too many arguments for command \"%s\"\n"
+#define CMD_MSG_MISMATCH_ARGS "Incorrect set of arguments for command \"%s\"\n"
+#define CMD_MSG_INVALID_ARG "Invalid value for argument \"%s\"\n"
+#define CMD_MSG_ARG_NOT_FOUND "Syntax error: \"%s\" not found\n"
+#define CMD_MSG_FILE_ERR "Error in file \"%s\" at line %u\n"
+#define CMD_MSG_FAIL "Command \"%s\" failed\n"
+
#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c
index fd897d5c..a82e552d 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall.c
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c
@@ -30,9 +30,11 @@
* (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 <errno.h>
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <sys/queue.h>
#include <netinet/in.h>
@@ -43,15 +45,11 @@
#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"
-
-#define BUF_SIZE 1024
+#include "parser.h"
struct app_pipeline_firewall_rule {
struct pipeline_firewall_key key;
@@ -75,18 +73,6 @@ struct app_pipeline_firewall {
void *default_rule_entry_ptr;
};
-struct app_pipeline_add_bulk_params {
- struct pipeline_firewall_key *keys;
- uint32_t n_keys;
- uint32_t *priorities;
- uint32_t *port_ids;
-};
-
-struct app_pipeline_del_bulk_params {
- struct pipeline_firewall_key *keys;
- uint32_t n_keys;
-};
-
static void
print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule)
{
@@ -272,356 +258,118 @@ app_pipeline_firewall_key_check_and_normalize(struct pipeline_firewall_key *key)
}
}
-static int
-app_pipeline_add_bulk_parse_file(char *filename,
- struct app_pipeline_add_bulk_params *params)
+int
+app_pipeline_firewall_load_file(char *filename,
+ struct pipeline_firewall_key *keys,
+ uint32_t *priorities,
+ uint32_t *port_ids,
+ uint32_t *n_keys,
+ uint32_t *line)
{
- FILE *f;
- char file_buf[BUF_SIZE];
- uint32_t i;
- int status = 0;
+ FILE *f = NULL;
+ char file_buf[1024];
+ uint32_t i, l;
- f = fopen(filename, "r");
- if (f == NULL)
+ /* Check input arguments */
+ if ((filename == NULL) ||
+ (keys == NULL) ||
+ (priorities == NULL) ||
+ (port_ids == NULL) ||
+ (n_keys == NULL) ||
+ (*n_keys == 0) ||
+ (line == NULL)) {
+ if (line)
+ *line = 0;
return -1;
-
- params->n_keys = 0;
- while (fgets(file_buf, BUF_SIZE, f) != NULL)
- params->n_keys++;
- rewind(f);
-
- if (params->n_keys == 0) {
- status = -1;
- goto end;
- }
-
- params->keys = rte_malloc(NULL,
- params->n_keys * sizeof(struct pipeline_firewall_key),
- RTE_CACHE_LINE_SIZE);
- if (params->keys == NULL) {
- status = -1;
- goto end;
- }
-
- params->priorities = rte_malloc(NULL,
- params->n_keys * sizeof(uint32_t),
- RTE_CACHE_LINE_SIZE);
- if (params->priorities == NULL) {
- status = -1;
- goto end;
- }
-
- params->port_ids = rte_malloc(NULL,
- params->n_keys * sizeof(uint32_t),
- RTE_CACHE_LINE_SIZE);
- if (params->port_ids == NULL) {
- status = -1;
- goto end;
- }
-
- i = 0;
- while (fgets(file_buf, BUF_SIZE, f) != NULL) {
- char *str;
-
- str = strtok(file_buf, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->priorities[i] = atoi(str);
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_ip = atoi(str)<<24;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<16;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<8;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
}
- params->keys[i].key.ipv4_5tuple.src_ip_mask = atoi(str);
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip = atoi(str)<<24;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<16;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<8;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip_mask = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_port_from = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_port_to = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_port_from = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_port_to = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.proto = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- /* Need to add 2 to str to skip leading 0x */
- params->keys[i].key.ipv4_5tuple.proto_mask = strtol(str+2, NULL, 16);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->port_ids[i] = atoi(str);
- params->keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE;
-
- i++;
- }
-
-end:
- fclose(f);
- return status;
-}
-
-static int
-app_pipeline_del_bulk_parse_file(char *filename,
- struct app_pipeline_del_bulk_params *params)
-{
- FILE *f;
- char file_buf[BUF_SIZE];
- uint32_t i;
- int status = 0;
+ /* Open input file */
f = fopen(filename, "r");
- if (f == NULL)
+ if (f == NULL) {
+ *line = 0;
return -1;
-
- params->n_keys = 0;
- while (fgets(file_buf, BUF_SIZE, f) != NULL)
- params->n_keys++;
- rewind(f);
-
- if (params->n_keys == 0) {
- status = -1;
- goto end;
- }
-
- params->keys = rte_malloc(NULL,
- params->n_keys * sizeof(struct pipeline_firewall_key),
- RTE_CACHE_LINE_SIZE);
- if (params->keys == NULL) {
- status = -1;
- goto end;
}
- i = 0;
- while (fgets(file_buf, BUF_SIZE, f) != NULL) {
- char *str;
-
- str = strtok(file_buf, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_ip = atoi(str)<<24;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<16;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<8;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_ip_mask = atoi(str);
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip = atoi(str)<<24;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<16;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<8;
-
- str = strtok(NULL, " .");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_ip_mask = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_port_from = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.src_port_to = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_port_from = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.dst_port_to = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- params->keys[i].key.ipv4_5tuple.proto = atoi(str);
-
- str = strtok(NULL, " ");
- if (str == NULL) {
- status = -1;
- goto end;
- }
- /* Need to add 2 to str to skip leading 0x */
- params->keys[i].key.ipv4_5tuple.proto_mask = strtol(str+2, NULL, 16);
-
- params->keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+ /* Read file */
+ for (i = 0, l = 1; i < *n_keys; l++) {
+ char *tokens[32];
+ uint32_t n_tokens = RTE_DIM(tokens);
+
+ uint32_t priority = 0;
+ struct in_addr sipaddr;
+ uint32_t sipdepth = 0;
+ struct in_addr dipaddr;
+ uint32_t dipdepth = 0;
+ uint16_t sport0 = 0;
+ uint16_t sport1 = 0;
+ uint16_t dport0 = 0;
+ uint16_t dport1 = 0;
+ uint8_t proto = 0;
+ uint8_t protomask = 0;
+ uint32_t port_id = 0;
+
+ int status;
+
+ if (fgets(file_buf, sizeof(file_buf), f) == NULL)
+ break;
+
+ status = parse_tokenize_string(file_buf, tokens, &n_tokens);
+ if (status)
+ goto error1;
+
+ if ((n_tokens == 0) || (tokens[0][0] == '#'))
+ continue;
+
+ if ((n_tokens != 15) ||
+ strcmp(tokens[0], "priority") ||
+ parser_read_uint32(&priority, tokens[1]) ||
+ strcmp(tokens[2], "ipv4") ||
+ parse_ipv4_addr(tokens[3], &sipaddr) ||
+ parser_read_uint32(&sipdepth, tokens[4]) ||
+ parse_ipv4_addr(tokens[5], &dipaddr) ||
+ parser_read_uint32(&dipdepth, tokens[6]) ||
+ parser_read_uint16(&sport0, tokens[7]) ||
+ parser_read_uint16(&sport1, tokens[8]) ||
+ parser_read_uint16(&dport0, tokens[9]) ||
+ parser_read_uint16(&dport1, tokens[10]) ||
+ parser_read_uint8(&proto, tokens[11]) ||
+ parser_read_uint8_hex(&protomask, tokens[12]) ||
+ strcmp(tokens[13], "port") ||
+ parser_read_uint32(&port_id, tokens[14]))
+ goto error1;
+
+ keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+ keys[i].key.ipv4_5tuple.src_ip =
+ rte_be_to_cpu_32(sipaddr.s_addr);
+ keys[i].key.ipv4_5tuple.src_ip_mask = sipdepth;
+ keys[i].key.ipv4_5tuple.dst_ip =
+ rte_be_to_cpu_32(dipaddr.s_addr);
+ keys[i].key.ipv4_5tuple.dst_ip_mask = dipdepth;
+ keys[i].key.ipv4_5tuple.src_port_from = sport0;
+ keys[i].key.ipv4_5tuple.src_port_to = sport1;
+ keys[i].key.ipv4_5tuple.dst_port_from = dport0;
+ keys[i].key.ipv4_5tuple.dst_port_to = dport1;
+ keys[i].key.ipv4_5tuple.proto = proto;
+ keys[i].key.ipv4_5tuple.proto_mask = protomask;
+
+ port_ids[i] = port_id;
+ priorities[i] = priority;
+
+ if (app_pipeline_firewall_key_check_and_normalize(&keys[i]))
+ goto error1;
i++;
}
- for (i = 0; i < params->n_keys; i++) {
- if (app_pipeline_firewall_key_check_and_normalize(&params->keys[i]) != 0) {
- status = -1;
- goto end;
- }
- }
+ /* Close file */
+ *n_keys = i;
+ fclose(f);
+ return 0;
-end:
+error1:
+ *line = l;
fclose(f);
- return status;
+ return -1;
}
int
@@ -804,14 +552,14 @@ app_pipeline_firewall_add_bulk(struct app_params *app,
return -1;
rules = rte_malloc(NULL,
- n_keys * sizeof(struct app_pipeline_firewall_rule *),
- RTE_CACHE_LINE_SIZE);
+ n_keys * sizeof(struct app_pipeline_firewall_rule *),
+ RTE_CACHE_LINE_SIZE);
if (rules == NULL)
return -1;
new_rules = rte_malloc(NULL,
- n_keys * sizeof(int),
- RTE_CACHE_LINE_SIZE);
+ n_keys * sizeof(int),
+ RTE_CACHE_LINE_SIZE);
if (new_rules == NULL) {
rte_free(rules);
return -1;
@@ -834,8 +582,9 @@ app_pipeline_firewall_add_bulk(struct app_params *app,
rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]);
new_rules[i] = (rules[i] == NULL);
if (rules[i] == NULL) {
- rules[i] = rte_malloc(NULL, sizeof(*rules[i]),
- RTE_CACHE_LINE_SIZE);
+ rules[i] = rte_malloc(NULL,
+ sizeof(*rules[i]),
+ RTE_CACHE_LINE_SIZE);
if (rules[i] == NULL) {
uint32_t j;
@@ -852,8 +601,8 @@ app_pipeline_firewall_add_bulk(struct app_params *app,
}
keys_found = rte_malloc(NULL,
- n_keys * sizeof(int),
- RTE_CACHE_LINE_SIZE);
+ n_keys * sizeof(int),
+ RTE_CACHE_LINE_SIZE);
if (keys_found == NULL) {
uint32_t j;
@@ -867,8 +616,8 @@ app_pipeline_firewall_add_bulk(struct app_params *app,
}
entries_ptr = rte_malloc(NULL,
- n_keys * sizeof(struct rte_pipeline_table_entry *),
- RTE_CACHE_LINE_SIZE);
+ n_keys * sizeof(struct rte_pipeline_table_entry *),
+ RTE_CACHE_LINE_SIZE);
if (entries_ptr == NULL) {
uint32_t j;
@@ -883,8 +632,8 @@ app_pipeline_firewall_add_bulk(struct app_params *app,
}
for (i = 0; i < n_keys; i++) {
entries_ptr[i] = rte_malloc(NULL,
- sizeof(struct rte_pipeline_table_entry),
- RTE_CACHE_LINE_SIZE);
+ sizeof(struct rte_pipeline_table_entry),
+ RTE_CACHE_LINE_SIZE);
if (entries_ptr[i] == NULL) {
uint32_t j;
@@ -1030,8 +779,8 @@ app_pipeline_firewall_delete_bulk(struct app_params *app,
return -1;
rules = rte_malloc(NULL,
- n_keys * sizeof(struct app_pipeline_firewall_rule *),
- RTE_CACHE_LINE_SIZE);
+ n_keys * sizeof(struct app_pipeline_firewall_rule *),
+ RTE_CACHE_LINE_SIZE);
if (rules == NULL)
return -1;
@@ -1044,8 +793,8 @@ app_pipeline_firewall_delete_bulk(struct app_params *app,
}
keys_found = rte_malloc(NULL,
- n_keys * sizeof(int),
- RTE_CACHE_LINE_SIZE);
+ n_keys * sizeof(int),
+ RTE_CACHE_LINE_SIZE);
if (keys_found == NULL) {
rte_free(rules);
return -1;
@@ -1197,668 +946,500 @@ app_pipeline_firewall_delete_default_rule(struct app_params *app,
}
/*
- * p firewall add ipv4
+ * firewall
+ *
+ * firewall add:
+ * p <pipelineid> firewall add priority <priority>
+ * ipv4 <sipaddr> <sipdepth> <dipaddr> <dipdepth>
+ * <sport0> <sport1> <dport0> <dport1> <proto> <protomask>
+ * port <portid>
+ * Note: <protomask> is a hex value
+ *
+ * p <pipelineid> firewall add bulk <file>
+ *
+ * firewall add default:
+ * p <pipelineid> firewall add default <port ID>
+ *
+ * firewall del:
+ * p <pipelineid> firewall del
+ * ipv4 <sipaddr> <sipdepth> <dipaddr> <dipdepth>
+ * <sport0> <sport1> <dport0> <dport1> <proto> <protomask>
+ *
+ * p <pipelineid> firewall del bulk <file>
+ *
+ * firewall del default:
+ * p <pipelineid> firewall del default
+ *
+ * firewall ls:
+ * p <pipelineid> firewall ls
*/
-struct cmd_firewall_add_ipv4_result {
+struct cmd_firewall_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;
+ cmdline_multi_string_t multi_string;
};
-static void
-cmd_firewall_add_ipv4_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
+static void cmd_firewall_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
void *data)
{
- struct cmd_firewall_add_ipv4_result *params = parsed_result;
+ struct cmd_firewall_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");
-
-cmdline_parse_token_string_t cmd_firewall_add_ipv4_ipv4_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result,
- ipv4_string, "ipv4");
-
-cmdline_parse_token_num_t cmd_firewall_add_ipv4_priority =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, priority,
- INT32);
-
-cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_src_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip);
+ char *tokens[17];
+ uint32_t n_tokens = RTE_DIM(tokens);
-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");
+ status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
+ if (status) {
+ printf(CMD_MSG_TOO_MANY_ARGS, "firewall");
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);
+ /* firewall add */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "priority") == 0)) {
+ struct pipeline_firewall_key key;
+ uint32_t priority;
+ struct in_addr sipaddr;
+ uint32_t sipdepth;
+ struct in_addr dipaddr;
+ uint32_t dipdepth;
+ uint16_t sport0;
+ uint16_t sport1;
+ uint16_t dport0;
+ uint16_t dport1;
+ uint8_t proto;
+ uint8_t protomask;
+ uint32_t port_id;
+
+ memset(&key, 0, sizeof(key));
+
+ if (n_tokens != 16) {
+ printf(CMD_MSG_MISMATCH_ARGS, "firewall add");
+ return;
+ }
-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);
+ if (parser_read_uint32(&priority, tokens[2])) {
+ printf(CMD_MSG_INVALID_ARG, "priority");
+ return;
+ }
-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);
+ if (strcmp(tokens[3], "ipv4")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "ipv4");
+ return;
+ }
-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);
+ if (parse_ipv4_addr(tokens[4], &sipaddr)) {
+ printf(CMD_MSG_INVALID_ARG, "sipaddr");
+ return;
+ }
-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);
+ if (parser_read_uint32(&sipdepth, tokens[5])) {
+ printf(CMD_MSG_INVALID_ARG, "sipdepth");
+ return;
+ }
-cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result,
- proto, UINT8);
+ if (parse_ipv4_addr(tokens[6], &dipaddr)) {
+ printf(CMD_MSG_INVALID_ARG, "dipaddr");
+ return;
+ }
-cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto_mask =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, proto_mask,
- UINT8);
+ if (parser_read_uint32(&dipdepth, tokens[7])) {
+ printf(CMD_MSG_INVALID_ARG, "dipdepth");
+ return;
+ }
-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,
- },
-};
+ if (parser_read_uint16(&sport0, tokens[8])) {
+ printf(CMD_MSG_INVALID_ARG, "sport0");
+ return;
+ }
-/*
- * p firewall add bulk
- */
+ if (parser_read_uint16(&sport1, tokens[9])) {
+ printf(CMD_MSG_INVALID_ARG, "sport1");
+ return;
+ }
-struct cmd_firewall_add_bulk_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 bulk_string;
- cmdline_fixed_string_t file_path;
-};
+ if (parser_read_uint16(&dport0, tokens[10])) {
+ printf(CMD_MSG_INVALID_ARG, "dport0");
+ return;
+ }
-static void
-cmd_firewall_add_bulk_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- void *data)
-{
- struct cmd_firewall_add_bulk_result *params = parsed_result;
- struct app_params *app = data;
- int status;
+ if (parser_read_uint16(&dport1, tokens[11])) {
+ printf(CMD_MSG_INVALID_ARG, "dport1");
+ return;
+ }
- struct app_pipeline_add_bulk_params add_bulk_params;
+ if (parser_read_uint8(&proto, tokens[12])) {
+ printf(CMD_MSG_INVALID_ARG, "proto");
+ return;
+ }
- status = app_pipeline_add_bulk_parse_file(params->file_path, &add_bulk_params);
- if (status != 0) {
- printf("Command failed\n");
- goto end;
- }
+ if (parser_read_uint8_hex(&protomask, tokens[13])) {
+ printf(CMD_MSG_INVALID_ARG, "protomask");
+ return;
+ }
- status = app_pipeline_firewall_add_bulk(app, params->pipeline_id, add_bulk_params.keys,
- add_bulk_params.n_keys, add_bulk_params.priorities, add_bulk_params.port_ids);
- if (status != 0) {
- printf("Command failed\n");
- goto end;
- }
+ if (strcmp(tokens[14], "port")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
-end:
- rte_free(add_bulk_params.keys);
- rte_free(add_bulk_params.priorities);
- rte_free(add_bulk_params.port_ids);
-}
+ if (parser_read_uint32(&port_id, tokens[15])) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_add_bulk_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, p_string,
- "p");
+ key.type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.src_ip = rte_be_to_cpu_32(sipaddr.s_addr);
+ key.key.ipv4_5tuple.src_ip_mask = sipdepth;
+ key.key.ipv4_5tuple.dst_ip = rte_be_to_cpu_32(dipaddr.s_addr);
+ key.key.ipv4_5tuple.dst_ip_mask = dipdepth;
+ key.key.ipv4_5tuple.src_port_from = sport0;
+ key.key.ipv4_5tuple.src_port_to = sport1;
+ key.key.ipv4_5tuple.dst_port_from = dport0;
+ key.key.ipv4_5tuple.dst_port_to = dport1;
+ key.key.ipv4_5tuple.proto = proto;
+ key.key.ipv4_5tuple.proto_mask = protomask;
+
+ status = app_pipeline_firewall_add_rule(app,
+ params->pipeline_id,
+ &key,
+ priority,
+ port_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "firewall add");
-cmdline_parse_token_num_t cmd_firewall_add_bulk_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_bulk_result, pipeline_id,
- UINT32);
+ return;
+ } /* firewall add */
+
+ /* firewall add bulk */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "bulk") == 0)) {
+ struct pipeline_firewall_key *keys;
+ uint32_t *priorities, *port_ids, n_keys, line;
+ char *filename;
+
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "firewall add bulk");
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_add_bulk_firewall_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result,
- firewall_string, "firewall");
+ filename = tokens[2];
-cmdline_parse_token_string_t cmd_firewall_add_bulk_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result,
- add_string, "add");
+ n_keys = APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE;
+ keys = malloc(n_keys * sizeof(struct pipeline_firewall_key));
+ if (keys == NULL) {
+ printf(CMD_MSG_OUT_OF_MEMORY);
+ return;
+ }
+ memset(keys, 0, n_keys * sizeof(struct pipeline_firewall_key));
-cmdline_parse_token_string_t cmd_firewall_add_bulk_bulk_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result,
- bulk_string, "bulk");
+ priorities = malloc(n_keys * sizeof(uint32_t));
+ if (priorities == NULL) {
+ printf(CMD_MSG_OUT_OF_MEMORY);
+ free(keys);
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_add_bulk_file_path_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result,
- file_path, NULL);
+ port_ids = malloc(n_keys * sizeof(uint32_t));
+ if (port_ids == NULL) {
+ printf(CMD_MSG_OUT_OF_MEMORY);
+ free(priorities);
+ free(keys);
+ return;
+ }
-cmdline_parse_inst_t cmd_firewall_add_bulk = {
- .f = cmd_firewall_add_bulk_parsed,
- .data = NULL,
- .help_str = "Firewall rule add bulk",
- .tokens = {
- (void *) &cmd_firewall_add_bulk_p_string,
- (void *) &cmd_firewall_add_bulk_pipeline_id,
- (void *) &cmd_firewall_add_bulk_firewall_string,
- (void *) &cmd_firewall_add_bulk_add_string,
- (void *) &cmd_firewall_add_bulk_bulk_string,
- (void *) &cmd_firewall_add_bulk_file_path_string,
- NULL,
- },
-};
+ status = app_pipeline_firewall_load_file(filename,
+ keys,
+ priorities,
+ port_ids,
+ &n_keys,
+ &line);
+ if (status != 0) {
+ printf(CMD_MSG_FILE_ERR, filename, line);
+ free(port_ids);
+ free(priorities);
+ free(keys);
+ return;
+ }
-/*
- * p firewall del bulk
- */
+ status = app_pipeline_firewall_add_bulk(app,
+ params->pipeline_id,
+ keys,
+ n_keys,
+ priorities,
+ port_ids);
+ if (status)
+ printf(CMD_MSG_FAIL, "firewall add bulk");
+
+ free(keys);
+ free(priorities);
+ free(port_ids);
+ return;
+ } /* firewall add bulk */
-struct cmd_firewall_del_bulk_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 bulk_string;
- cmdline_fixed_string_t file_path;
-};
+ /* firewall add default */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "default") == 0)) {
+ uint32_t port_id;
-static void
-cmd_firewall_del_bulk_parsed(
- void *parsed_result,
- __attribute__((unused)) struct cmdline *cl,
- void *data)
-{
- struct cmd_firewall_del_bulk_result *params = parsed_result;
- struct app_params *app = data;
- int status;
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "firewall add default");
+ return;
+ }
- struct app_pipeline_del_bulk_params del_bulk_params;
+ if (parser_read_uint32(&port_id, tokens[2])) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
- status = app_pipeline_del_bulk_parse_file(params->file_path, &del_bulk_params);
- if (status != 0) {
- printf("Command failed\n");
- goto end;
- }
+ status = app_pipeline_firewall_add_default_rule(app,
+ params->pipeline_id,
+ port_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "firewall add default");
- status = app_pipeline_firewall_delete_bulk(app, params->pipeline_id,
- del_bulk_params.keys, del_bulk_params.n_keys);
- if (status != 0) {
- printf("Command failed\n");
- goto end;
- }
+ return;
+ } /* firewall add default */
+
+ /* firewall del */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ (strcmp(tokens[1], "ipv4") == 0)) {
+ struct pipeline_firewall_key key;
+ struct in_addr sipaddr;
+ uint32_t sipdepth;
+ struct in_addr dipaddr;
+ uint32_t dipdepth;
+ uint16_t sport0;
+ uint16_t sport1;
+ uint16_t dport0;
+ uint16_t dport1;
+ uint8_t proto;
+ uint8_t protomask;
+
+ memset(&key, 0, sizeof(key));
+
+ if (n_tokens != 12) {
+ printf(CMD_MSG_MISMATCH_ARGS, "firewall del");
+ return;
+ }
-end:
- rte_free(del_bulk_params.keys);
-}
+ if (parse_ipv4_addr(tokens[2], &sipaddr)) {
+ printf(CMD_MSG_INVALID_ARG, "sipaddr");
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_del_bulk_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, p_string,
- "p");
+ if (parser_read_uint32(&sipdepth, tokens[3])) {
+ printf(CMD_MSG_INVALID_ARG, "sipdepth");
+ return;
+ }
-cmdline_parse_token_num_t cmd_firewall_del_bulk_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_bulk_result, pipeline_id,
- UINT32);
+ if (parse_ipv4_addr(tokens[4], &dipaddr)) {
+ printf(CMD_MSG_INVALID_ARG, "dipaddr");
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_del_bulk_firewall_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result,
- firewall_string, "firewall");
+ if (parser_read_uint32(&dipdepth, tokens[5])) {
+ printf(CMD_MSG_INVALID_ARG, "dipdepth");
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_del_bulk_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result,
- del_string, "del");
+ if (parser_read_uint16(&sport0, tokens[6])) {
+ printf(CMD_MSG_INVALID_ARG, "sport0");
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_del_bulk_bulk_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result,
- bulk_string, "bulk");
+ if (parser_read_uint16(&sport1, tokens[7])) {
+ printf(CMD_MSG_INVALID_ARG, "sport1");
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_del_bulk_file_path_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result,
- file_path, NULL);
+ if (parser_read_uint16(&dport0, tokens[8])) {
+ printf(CMD_MSG_INVALID_ARG, "dport0");
+ return;
+ }
-cmdline_parse_inst_t cmd_firewall_del_bulk = {
- .f = cmd_firewall_del_bulk_parsed,
- .data = NULL,
- .help_str = "Firewall rule del bulk",
- .tokens = {
- (void *) &cmd_firewall_del_bulk_p_string,
- (void *) &cmd_firewall_del_bulk_pipeline_id,
- (void *) &cmd_firewall_del_bulk_firewall_string,
- (void *) &cmd_firewall_del_bulk_add_string,
- (void *) &cmd_firewall_del_bulk_bulk_string,
- (void *) &cmd_firewall_del_bulk_file_path_string,
- NULL,
- },
-};
+ if (parser_read_uint16(&dport1, tokens[9])) {
+ printf(CMD_MSG_INVALID_ARG, "dport1");
+ return;
+ }
-/*
- * 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;
-};
+ if (parser_read_uint8(&proto, tokens[10])) {
+ printf(CMD_MSG_INVALID_ARG, "proto");
+ return;
+ }
-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;
+ if (parser_read_uint8_hex(&protomask, tokens[11])) {
+ printf(CMD_MSG_INVALID_ARG, "protomask");
+ return;
+ }
- status = app_pipeline_firewall_add_default_rule(app,
- params->pipeline_id,
- params->port_id);
+ key.type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.src_ip = rte_be_to_cpu_32(sipaddr.s_addr);
+ key.key.ipv4_5tuple.src_ip_mask = sipdepth;
+ key.key.ipv4_5tuple.dst_ip = rte_be_to_cpu_32(dipaddr.s_addr);
+ key.key.ipv4_5tuple.dst_ip_mask = dipdepth;
+ key.key.ipv4_5tuple.src_port_from = sport0;
+ key.key.ipv4_5tuple.src_port_to = sport1;
+ key.key.ipv4_5tuple.dst_port_from = dport0;
+ key.key.ipv4_5tuple.dst_port_to = dport1;
+ key.key.ipv4_5tuple.proto = proto;
+ key.key.ipv4_5tuple.proto_mask = protomask;
+
+ status = app_pipeline_firewall_delete_rule(app,
+ params->pipeline_id,
+ &key);
+ if (status)
+ printf(CMD_MSG_FAIL, "firewall del");
- 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");
+ } /* firewall del */
+
+ /* firewall del bulk */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ (strcmp(tokens[1], "bulk") == 0)) {
+ struct pipeline_firewall_key *keys;
+ uint32_t *priorities, *port_ids, n_keys, line;
+ char *filename;
+
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "firewall del bulk");
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_add_default_default_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result,
- default_string, "default");
+ filename = tokens[2];
-cmdline_parse_token_num_t cmd_firewall_add_default_port_id =
- TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, port_id,
- UINT8);
+ n_keys = APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE;
+ keys = malloc(n_keys * sizeof(struct pipeline_firewall_key));
+ if (keys == NULL) {
+ printf(CMD_MSG_OUT_OF_MEMORY);
+ return;
+ }
+ memset(keys, 0, n_keys * sizeof(struct pipeline_firewall_key));
-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,
- },
-};
+ priorities = malloc(n_keys * sizeof(uint32_t));
+ if (priorities == NULL) {
+ printf(CMD_MSG_OUT_OF_MEMORY);
+ free(keys);
+ return;
+ }
-/*
- * 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;
-};
+ port_ids = malloc(n_keys * sizeof(uint32_t));
+ if (port_ids == NULL) {
+ printf(CMD_MSG_OUT_OF_MEMORY);
+ free(priorities);
+ free(keys);
+ return;
+ }
-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_load_file(filename,
+ keys,
+ priorities,
+ port_ids,
+ &n_keys,
+ &line);
+ if (status != 0) {
+ printf(CMD_MSG_FILE_ERR, filename, line);
+ free(port_ids);
+ free(priorities);
+ free(keys);
+ return;
+ }
- status = app_pipeline_firewall_delete_default_rule(app,
- params->pipeline_id);
+ status = app_pipeline_firewall_delete_bulk(app,
+ params->pipeline_id,
+ keys,
+ n_keys);
+ if (status)
+ printf(CMD_MSG_FAIL, "firewall del bulk");
- if (status != 0) {
- printf("Command failed\n");
+ free(port_ids);
+ free(priorities);
+ free(keys);
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");
+ } /* firewall del bulk */
+
+ /* firewall del default */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ (strcmp(tokens[1], "default") == 0)) {
+ if (n_tokens != 2) {
+ printf(CMD_MSG_MISMATCH_ARGS, "firewall del default");
+ return;
+ }
-cmdline_parse_token_string_t cmd_firewall_del_default_default_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result,
- default_string, "default");
+ status = app_pipeline_firewall_delete_default_rule(app,
+ params->pipeline_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "firewall del 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,
- },
-};
+ return;
-/*
- * p firewall ls
- */
+ } /* firewall del default */
-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;
-};
-
-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;
- int status;
+ /* firewall ls */
+ if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
+ if (n_tokens != 1) {
+ printf(CMD_MSG_MISMATCH_ARGS, "firewall ls");
+ return;
+ }
- status = app_pipeline_firewall_ls(app, params->pipeline_id);
+ status = app_pipeline_firewall_ls(app, params->pipeline_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "firewall ls");
- if (status != 0) {
- printf("Command failed\n");
return;
- }
+ } /* firewall ls */
+
+ printf(CMD_MSG_MISMATCH_ARGS, "firewall");
}
-cmdline_parse_token_string_t cmd_firewall_ls_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, p_string,
- "p");
+static cmdline_parse_token_string_t cmd_firewall_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_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);
+static cmdline_parse_token_num_t cmd_firewall_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_firewall_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");
+static cmdline_parse_token_string_t cmd_firewall_firewall_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_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");
+static cmdline_parse_token_string_t cmd_firewall_multi_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, multi_string,
+ TOKEN_STRING_MULTI);
-cmdline_parse_inst_t cmd_firewall_ls = {
- .f = cmd_firewall_ls_parsed,
+static cmdline_parse_inst_t cmd_firewall = {
+ .f = cmd_firewall_parsed,
.data = NULL,
- .help_str = "Firewall rule list",
+ .help_str = "firewall add / add bulk / add default / del / del bulk"
+ " / del default / ls",
.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,
+ (void *) &cmd_firewall_p_string,
+ (void *) &cmd_firewall_pipeline_id,
+ (void *) &cmd_firewall_firewall_string,
+ (void *) &cmd_firewall_multi_string,
NULL,
},
};
static cmdline_parse_ctx_t pipeline_cmds[] = {
- (cmdline_parse_inst_t *) &cmd_firewall_add_ipv4,
- (cmdline_parse_inst_t *) &cmd_firewall_del_ipv4,
- (cmdline_parse_inst_t *) &cmd_firewall_add_bulk,
- (cmdline_parse_inst_t *) &cmd_firewall_del_bulk,
- (cmdline_parse_inst_t *) &cmd_firewall_add_default,
- (cmdline_parse_inst_t *) &cmd_firewall_del_default,
- (cmdline_parse_inst_t *) &cmd_firewall_ls,
+ (cmdline_parse_inst_t *) &cmd_firewall,
NULL,
};
static struct pipeline_fe_ops pipeline_firewall_fe_ops = {
.f_init = app_pipeline_firewall_init,
+ .f_post_init = NULL,
.f_free = app_pipeline_firewall_free,
+ .f_track = app_pipeline_track_default,
.cmds = pipeline_cmds,
};
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.h b/examples/ip_pipeline/pipeline/pipeline_firewall.h
index ccc4e64b..aa79a2a0 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall.h
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.h
@@ -72,6 +72,18 @@ int
app_pipeline_firewall_delete_default_rule(struct app_params *app,
uint32_t pipeline_id);
+#ifndef APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE
+#define APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE 65536
+#endif
+
+int
+app_pipeline_firewall_load_file(char *filename,
+ struct pipeline_firewall_key *keys,
+ uint32_t *priorities,
+ uint32_t *port_ids,
+ uint32_t *n_keys,
+ uint32_t *line);
+
extern struct pipeline_type pipeline_firewall;
#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
index e7a8a4c5..b61f3034 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
@@ -565,27 +565,6 @@ pipeline_firewall_free(void *pipeline)
}
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;
@@ -732,7 +711,7 @@ pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg)
n_keys = req->n_keys;
for (i = 0; i < n_keys; i++) {
- entries[i] = rte_malloc(NULL,
+ entries[i] = rte_zmalloc(NULL,
sizeof(struct firewall_table_entry),
RTE_CACHE_LINE_SIZE);
if (entries[i] == NULL) {
@@ -740,7 +719,7 @@ pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg)
return rsp;
}
- params[i] = rte_malloc(NULL,
+ params[i] = rte_zmalloc(NULL,
sizeof(struct rte_table_acl_rule_add_params),
RTE_CACHE_LINE_SIZE);
if (params[i] == NULL) {
@@ -814,7 +793,7 @@ pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg)
n_keys = req->n_keys;
for (i = 0; i < n_keys; i++) {
- params[i] = rte_malloc(NULL,
+ params[i] = rte_zmalloc(NULL,
sizeof(struct rte_table_acl_rule_delete_params),
RTE_CACHE_LINE_SIZE);
if (params[i] == NULL) {
@@ -903,5 +882,4 @@ struct pipeline_be_ops pipeline_firewall_be_ops = {
.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_flow_actions.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c
index 4012121f..bf12fd7b 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c
@@ -35,6 +35,7 @@
#include <string.h>
#include <sys/queue.h>
#include <netinet/in.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_hexdump.h>
@@ -43,13 +44,12 @@
#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 "app.h"
#include "pipeline_common_fe.h"
#include "pipeline_flow_actions.h"
#include "hash_func.h"
+#include "parser.h"
/*
* Flow actions pipeline
@@ -689,1121 +689,620 @@ app_pipeline_fa_dscp_ls(struct app_params *app,
return 0;
}
-/*
- * Flow meter configuration (single flow)
- *
- * p <pipeline ID> flow <flow ID> meter <meter ID> trtcm <trtcm params>
- */
-
-struct cmd_fa_meter_config_result {
- cmdline_fixed_string_t p_string;
- uint32_t pipeline_id;
- cmdline_fixed_string_t flow_string;
- uint32_t flow_id;
- cmdline_fixed_string_t meter_string;
- uint32_t meter_id;
- cmdline_fixed_string_t trtcm_string;
- uint64_t cir;
- uint64_t pir;
- uint64_t cbs;
- uint64_t pbs;
-};
-
-static void
-cmd_fa_meter_config_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_fa_meter_config_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_fa_flow_params flow_params;
- int status;
-
- if (params->meter_id >= PIPELINE_FA_N_TC_MAX) {
- printf("Command failed\n");
- return;
- }
-
- flow_params.m[params->meter_id].cir = params->cir;
- flow_params.m[params->meter_id].pir = params->pir;
- flow_params.m[params->meter_id].cbs = params->cbs;
- flow_params.m[params->meter_id].pbs = params->pbs;
-
- status = app_pipeline_fa_flow_config(app,
- params->pipeline_id,
- params->flow_id,
- 1 << params->meter_id,
- 0,
- 0,
- &flow_params);
-
- if (status != 0)
- printf("Command failed\n");
-}
-
-cmdline_parse_token_string_t cmd_fa_meter_config_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
- p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,
- pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_flow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
- flow_string, "flow");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_flow_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,
- flow_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_meter_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
- meter_string, "meter");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_meter_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,
- meter_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_trtcm_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
- trtcm_string, "trtcm");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_cir =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cir, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_pir =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pir, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_cbs =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cbs, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_pbs =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pbs, UINT64);
-
-cmdline_parse_inst_t cmd_fa_meter_config = {
- .f = cmd_fa_meter_config_parsed,
- .data = NULL,
- .help_str = "Flow meter configuration (single flow) ",
- .tokens = {
- (void *) &cmd_fa_meter_config_p_string,
- (void *) &cmd_fa_meter_config_pipeline_id,
- (void *) &cmd_fa_meter_config_flow_string,
- (void *) &cmd_fa_meter_config_flow_id,
- (void *) &cmd_fa_meter_config_meter_string,
- (void *) &cmd_fa_meter_config_meter_id,
- (void *) &cmd_fa_meter_config_trtcm_string,
- (void *) &cmd_fa_meter_config_cir,
- (void *) &cmd_fa_meter_config_pir,
- (void *) &cmd_fa_meter_config_cbs,
- (void *) &cmd_fa_meter_config_pbs,
- NULL,
- },
-};
-
-/*
- * Flow meter configuration (multiple flows)
- *
- * p <pipeline ID> flows <n_flows> meter <meter ID> trtcm <trtcm params>
- */
-
-struct cmd_fa_meter_config_bulk_result {
- cmdline_fixed_string_t p_string;
- uint32_t pipeline_id;
- cmdline_fixed_string_t flows_string;
- uint32_t n_flows;
- cmdline_fixed_string_t meter_string;
- uint32_t meter_id;
- cmdline_fixed_string_t trtcm_string;
- uint64_t cir;
- uint64_t pir;
- uint64_t cbs;
- uint64_t pbs;
-};
-
-static void
-cmd_fa_meter_config_bulk_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
+int
+app_pipeline_fa_load_file(char *filename,
+ uint32_t *flow_ids,
+ struct pipeline_fa_flow_params *p,
+ uint32_t *n_flows,
+ uint32_t *line)
{
- struct cmd_fa_meter_config_bulk_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_fa_flow_params flow_template, *flow_params;
- uint32_t *flow_id;
- uint32_t i;
+ FILE *f = NULL;
+ char file_buf[1024];
+ uint32_t i, l;
- if ((params->n_flows == 0) ||
- (params->meter_id >= PIPELINE_FA_N_TC_MAX)) {
- printf("Invalid arguments\n");
- return;
- }
-
- flow_id = (uint32_t *) rte_malloc(NULL,
- N_FLOWS_BULK * sizeof(uint32_t),
- RTE_CACHE_LINE_SIZE);
- if (flow_id == NULL) {
- printf("Memory allocation failed\n");
- return;
- }
+ /* Check input arguments */
+ if ((filename == NULL) ||
+ (flow_ids == NULL) ||
+ (p == NULL) ||
+ (n_flows == NULL) ||
+ (*n_flows == 0) ||
+ (line == NULL)) {
+ if (line)
+ *line = 0;
+ return -1;
+ }
- flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,
- N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),
- RTE_CACHE_LINE_SIZE);
- if (flow_params == NULL) {
- rte_free(flow_id);
- printf("Memory allocation failed\n");
- return;
+ /* Open input file */
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ *line = 0;
+ return -1;
}
- memset(&flow_template, 0, sizeof(flow_template));
- flow_template.m[params->meter_id].cir = params->cir;
- flow_template.m[params->meter_id].pir = params->pir;
- flow_template.m[params->meter_id].cbs = params->cbs;
- flow_template.m[params->meter_id].pbs = params->pbs;
+ /* Read file */
+ for (i = 0, l = 1; i < *n_flows; l++) {
+ char *tokens[64];
+ uint32_t n_tokens = RTE_DIM(tokens);
- for (i = 0; i < params->n_flows; i++) {
- uint32_t pos = i % N_FLOWS_BULK;
+ int status;
- flow_id[pos] = i;
- memcpy(&flow_params[pos],
- &flow_template,
- sizeof(flow_template));
+ if (fgets(file_buf, sizeof(file_buf), f) == NULL)
+ break;
- if ((pos == N_FLOWS_BULK - 1) ||
- (i == params->n_flows - 1)) {
- int status;
+ status = parse_tokenize_string(file_buf, tokens, &n_tokens);
+ if (status)
+ goto error1;
- status = app_pipeline_fa_flow_config_bulk(app,
- params->pipeline_id,
- flow_id,
- pos + 1,
- 1 << params->meter_id,
- 0,
- 0,
- flow_params);
+ if ((n_tokens == 0) || (tokens[0][0] == '#'))
+ continue;
- if (status != 0) {
- printf("Command failed\n");
- break;
- }
- }
+ if ((n_tokens != 64) ||
+ /* flow */
+ strcmp(tokens[0], "flow") ||
+ parser_read_uint32(&flow_ids[i], tokens[1]) ||
+
+ /* meter & policer 0 */
+ strcmp(tokens[2], "meter") ||
+ strcmp(tokens[3], "0") ||
+ strcmp(tokens[4], "trtcm") ||
+ parser_read_uint64(&p[i].m[0].cir, tokens[5]) ||
+ parser_read_uint64(&p[i].m[0].pir, tokens[6]) ||
+ parser_read_uint64(&p[i].m[0].cbs, tokens[7]) ||
+ parser_read_uint64(&p[i].m[0].pbs, tokens[8]) ||
+ strcmp(tokens[9], "policer") ||
+ strcmp(tokens[10], "0") ||
+ strcmp(tokens[11], "g") ||
+ string_to_policer_action(tokens[12],
+ &p[i].p[0].action[e_RTE_METER_GREEN]) ||
+ strcmp(tokens[13], "y") ||
+ string_to_policer_action(tokens[14],
+ &p[i].p[0].action[e_RTE_METER_YELLOW]) ||
+ strcmp(tokens[15], "r") ||
+ string_to_policer_action(tokens[16],
+ &p[i].p[0].action[e_RTE_METER_RED]) ||
+
+ /* meter & policer 1 */
+ strcmp(tokens[17], "meter") ||
+ strcmp(tokens[18], "1") ||
+ strcmp(tokens[19], "trtcm") ||
+ parser_read_uint64(&p[i].m[1].cir, tokens[20]) ||
+ parser_read_uint64(&p[i].m[1].pir, tokens[21]) ||
+ parser_read_uint64(&p[i].m[1].cbs, tokens[22]) ||
+ parser_read_uint64(&p[i].m[1].pbs, tokens[23]) ||
+ strcmp(tokens[24], "policer") ||
+ strcmp(tokens[25], "1") ||
+ strcmp(tokens[26], "g") ||
+ string_to_policer_action(tokens[27],
+ &p[i].p[1].action[e_RTE_METER_GREEN]) ||
+ strcmp(tokens[28], "y") ||
+ string_to_policer_action(tokens[29],
+ &p[i].p[1].action[e_RTE_METER_YELLOW]) ||
+ strcmp(tokens[30], "r") ||
+ string_to_policer_action(tokens[31],
+ &p[i].p[1].action[e_RTE_METER_RED]) ||
+
+ /* meter & policer 2 */
+ strcmp(tokens[32], "meter") ||
+ strcmp(tokens[33], "2") ||
+ strcmp(tokens[34], "trtcm") ||
+ parser_read_uint64(&p[i].m[2].cir, tokens[35]) ||
+ parser_read_uint64(&p[i].m[2].pir, tokens[36]) ||
+ parser_read_uint64(&p[i].m[2].cbs, tokens[37]) ||
+ parser_read_uint64(&p[i].m[2].pbs, tokens[38]) ||
+ strcmp(tokens[39], "policer") ||
+ strcmp(tokens[40], "2") ||
+ strcmp(tokens[41], "g") ||
+ string_to_policer_action(tokens[42],
+ &p[i].p[2].action[e_RTE_METER_GREEN]) ||
+ strcmp(tokens[43], "y") ||
+ string_to_policer_action(tokens[44],
+ &p[i].p[2].action[e_RTE_METER_YELLOW]) ||
+ strcmp(tokens[45], "r") ||
+ string_to_policer_action(tokens[46],
+ &p[i].p[2].action[e_RTE_METER_RED]) ||
+
+ /* meter & policer 3 */
+ strcmp(tokens[47], "meter") ||
+ strcmp(tokens[48], "3") ||
+ strcmp(tokens[49], "trtcm") ||
+ parser_read_uint64(&p[i].m[3].cir, tokens[50]) ||
+ parser_read_uint64(&p[i].m[3].pir, tokens[51]) ||
+ parser_read_uint64(&p[i].m[3].cbs, tokens[52]) ||
+ parser_read_uint64(&p[i].m[3].pbs, tokens[53]) ||
+ strcmp(tokens[54], "policer") ||
+ strcmp(tokens[55], "3") ||
+ strcmp(tokens[56], "g") ||
+ string_to_policer_action(tokens[57],
+ &p[i].p[3].action[e_RTE_METER_GREEN]) ||
+ strcmp(tokens[58], "y") ||
+ string_to_policer_action(tokens[59],
+ &p[i].p[3].action[e_RTE_METER_YELLOW]) ||
+ strcmp(tokens[60], "r") ||
+ string_to_policer_action(tokens[61],
+ &p[i].p[3].action[e_RTE_METER_RED]) ||
+
+ /* port */
+ strcmp(tokens[62], "port") ||
+ parser_read_uint32(&p[i].port_id, tokens[63]))
+ goto error1;
+
+ i++;
}
- rte_free(flow_params);
- rte_free(flow_id);
+ /* Close file */
+ *n_flows = i;
+ fclose(f);
+ return 0;
+error1:
+ *line = l;
+ fclose(f);
+ return -1;
}
-cmdline_parse_token_string_t cmd_fa_meter_config_bulk_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_bulk_flows_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- flows_string, "flows");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_n_flows =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- n_flows, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_bulk_meter_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- meter_string, "meter");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_meter_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- meter_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_bulk_trtcm_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- trtcm_string, "trtcm");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cir =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- cir, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pir =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- pir, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cbs =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- cbs, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pbs =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
- pbs, UINT64);
-
-cmdline_parse_inst_t cmd_fa_meter_config_bulk = {
- .f = cmd_fa_meter_config_bulk_parsed,
- .data = NULL,
- .help_str = "Flow meter configuration (multiple flows)",
- .tokens = {
- (void *) &cmd_fa_meter_config_bulk_p_string,
- (void *) &cmd_fa_meter_config_bulk_pipeline_id,
- (void *) &cmd_fa_meter_config_bulk_flows_string,
- (void *) &cmd_fa_meter_config_bulk_n_flows,
- (void *) &cmd_fa_meter_config_bulk_meter_string,
- (void *) &cmd_fa_meter_config_bulk_meter_id,
- (void *) &cmd_fa_meter_config_bulk_trtcm_string,
- (void *) &cmd_fa_meter_config_cir,
- (void *) &cmd_fa_meter_config_pir,
- (void *) &cmd_fa_meter_config_cbs,
- (void *) &cmd_fa_meter_config_pbs,
- NULL,
- },
-};
-
/*
- * Flow policer configuration (single flow)
+ * action
*
- * p <pipeline ID> flow <flow ID> policer <policer ID>
- * G <action> Y <action> R <action>
+ * flow meter, policer and output port configuration:
+ * p <pipelineid> action flow <flowid> meter <meterid> trtcm <cir> <pir> <cbs> <pbs>
*
- * <action> = G (green) | Y (yellow) | R (red) | D (drop)
- */
-
-struct cmd_fa_policer_config_result {
- cmdline_fixed_string_t p_string;
- uint32_t pipeline_id;
- cmdline_fixed_string_t flow_string;
- uint32_t flow_id;
- cmdline_fixed_string_t policer_string;
- uint32_t policer_id;
- cmdline_fixed_string_t green_string;
- cmdline_fixed_string_t g_action;
- cmdline_fixed_string_t yellow_string;
- cmdline_fixed_string_t y_action;
- cmdline_fixed_string_t red_string;
- cmdline_fixed_string_t r_action;
-};
-
-static void
-cmd_fa_policer_config_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_fa_policer_config_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_fa_flow_params flow_params;
- int status;
-
- if (params->policer_id >= PIPELINE_FA_N_TC_MAX) {
- printf("Command failed\n");
- return;
- }
-
- status = string_to_policer_action(params->g_action,
- &flow_params.p[params->policer_id].action[e_RTE_METER_GREEN]);
- if (status)
- printf("Invalid policer green action\n");
-
- status = string_to_policer_action(params->y_action,
- &flow_params.p[params->policer_id].action[e_RTE_METER_YELLOW]);
- if (status)
- printf("Invalid policer yellow action\n");
-
- status = string_to_policer_action(params->r_action,
- &flow_params.p[params->policer_id].action[e_RTE_METER_RED]);
- if (status)
- printf("Invalid policer red action\n");
-
- status = app_pipeline_fa_flow_config(app,
- params->pipeline_id,
- params->flow_id,
- 0,
- 1 << params->policer_id,
- 0,
- &flow_params);
-
- if (status != 0)
- printf("Command failed\n");
-
-}
-
-cmdline_parse_token_string_t cmd_fa_policer_config_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
- p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,
- pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_flow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
- flow_string, "flow");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_flow_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,
- flow_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_policer_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
- policer_string, "policer");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_policer_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,
- policer_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_green_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
- green_string, "G");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_g_action =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
- g_action, "R#Y#G#D");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_yellow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
- yellow_string, "Y");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_y_action =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
- y_action, "R#Y#G#D");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_red_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
- red_string, "R");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_r_action =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
- r_action, "R#Y#G#D");
-
-cmdline_parse_inst_t cmd_fa_policer_config = {
- .f = cmd_fa_policer_config_parsed,
- .data = NULL,
- .help_str = "Flow policer configuration (single flow)",
- .tokens = {
- (void *) &cmd_fa_policer_config_p_string,
- (void *) &cmd_fa_policer_config_pipeline_id,
- (void *) &cmd_fa_policer_config_flow_string,
- (void *) &cmd_fa_policer_config_flow_id,
- (void *) &cmd_fa_policer_config_policer_string,
- (void *) &cmd_fa_policer_config_policer_id,
- (void *) &cmd_fa_policer_config_green_string,
- (void *) &cmd_fa_policer_config_g_action,
- (void *) &cmd_fa_policer_config_yellow_string,
- (void *) &cmd_fa_policer_config_y_action,
- (void *) &cmd_fa_policer_config_red_string,
- (void *) &cmd_fa_policer_config_r_action,
- NULL,
- },
-};
-
-/*
- * Flow policer configuration (multiple flows)
+ * p <pipelineid> action flow <flowid> policer <policerid> g <gaction> y <yaction> r <raction>
+ * <action> is one of the following:
+ * G = recolor to green
+ * Y = recolor as yellow
+ * R = recolor as red
+ * D = drop
*
- * p <pipeline ID> flows <n_flows> policer <policer ID>
- * G <action> Y <action> R <action>
+ * p <pipelineid> action flow <flowid> port <port ID>
*
- * <action> = G (green) | Y (yellow) | R (red) | D (drop)
- */
+ * p <pipelineid> action flow bulk <file>
+ *
+ * flow policer stats read:
+ * p <pipelineid> action flow <flowid> stats
+ *
+ * flow ls:
+ * p <pipelineid> action flow ls
+ *
+ * dscp table configuration:
+ * p <pipelineid> action dscp <dscpid> class <class ID> color <color>
+ *
+ * dscp table ls:
+ * p <pipelineid> action dscp ls
+**/
-struct cmd_fa_policer_config_bulk_result {
+struct cmd_action_result {
cmdline_fixed_string_t p_string;
uint32_t pipeline_id;
- cmdline_fixed_string_t flows_string;
- uint32_t n_flows;
- cmdline_fixed_string_t policer_string;
- uint32_t policer_id;
- cmdline_fixed_string_t green_string;
- cmdline_fixed_string_t g_action;
- cmdline_fixed_string_t yellow_string;
- cmdline_fixed_string_t y_action;
- cmdline_fixed_string_t red_string;
- cmdline_fixed_string_t r_action;
+ cmdline_fixed_string_t action_string;
+ cmdline_multi_string_t multi_string;
};
static void
-cmd_fa_policer_config_bulk_parsed(
+cmd_action_parsed(
void *parsed_result,
__rte_unused struct cmdline *cl,
void *data)
{
- struct cmd_fa_policer_config_bulk_result *params = parsed_result;
+ struct cmd_action_result *params = parsed_result;
struct app_params *app = data;
- struct pipeline_fa_flow_params flow_template, *flow_params;
- uint32_t *flow_id, i;
- int status;
- if ((params->n_flows == 0) ||
- (params->policer_id >= PIPELINE_FA_N_TC_MAX)) {
- printf("Invalid arguments\n");
- return;
- }
-
- flow_id = (uint32_t *) rte_malloc(NULL,
- N_FLOWS_BULK * sizeof(uint32_t),
- RTE_CACHE_LINE_SIZE);
- if (flow_id == NULL) {
- printf("Memory allocation failed\n");
- return;
- }
+ char *tokens[16];
+ uint32_t n_tokens = RTE_DIM(tokens);
+ int status;
- flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,
- N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),
- RTE_CACHE_LINE_SIZE);
- if (flow_params == NULL) {
- rte_free(flow_id);
- printf("Memory allocation failed\n");
+ status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
+ if (status != 0) {
+ printf(CMD_MSG_TOO_MANY_ARGS, "action");
return;
}
- memset(&flow_template, 0, sizeof(flow_template));
-
- status = string_to_policer_action(params->g_action,
- &flow_template.p[params->policer_id].action[e_RTE_METER_GREEN]);
- if (status)
- printf("Invalid policer green action\n");
-
- status = string_to_policer_action(params->y_action,
- &flow_template.p[params->policer_id].action[e_RTE_METER_YELLOW]);
- if (status)
- printf("Invalid policer yellow action\n");
-
- status = string_to_policer_action(params->r_action,
- &flow_template.p[params->policer_id].action[e_RTE_METER_RED]);
- if (status)
- printf("Invalid policer red action\n");
-
- for (i = 0; i < params->n_flows; i++) {
- uint32_t pos = i % N_FLOWS_BULK;
-
- flow_id[pos] = i;
- memcpy(&flow_params[pos], &flow_template,
- sizeof(flow_template));
-
- if ((pos == N_FLOWS_BULK - 1) ||
- (i == params->n_flows - 1)) {
- int status;
-
- status = app_pipeline_fa_flow_config_bulk(app,
- params->pipeline_id,
- flow_id,
- pos + 1,
- 0,
- 1 << params->policer_id,
- 0,
- flow_params);
-
- if (status != 0) {
- printf("Command failed\n");
-
- break;
- }
+ /* action flow meter */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "flow") == 0) &&
+ strcmp(tokens[1], "bulk") &&
+ strcmp(tokens[1], "ls") &&
+ (strcmp(tokens[2], "meter") == 0)) {
+ struct pipeline_fa_flow_params flow_params;
+ uint32_t flow_id, meter_id;
+
+ if (n_tokens != 9) {
+ printf(CMD_MSG_MISMATCH_ARGS, "action flow meter");
+ return;
}
- }
-
- rte_free(flow_params);
- rte_free(flow_id);
-
-}
-
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_bulk_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_flows_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- flows_string, "flows");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_bulk_n_flows =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- n_flows, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_policer_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- policer_string, "policer");
-cmdline_parse_token_num_t cmd_fa_policer_config_bulk_policer_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- policer_id, UINT32);
+ memset(&flow_params, 0, sizeof(flow_params));
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_green_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- green_string, "G");
+ if (parser_read_uint32(&flow_id, tokens[1])) {
+ printf(CMD_MSG_INVALID_ARG, "flowid");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_g_action =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- g_action, "R#Y#G#D");
+ if (parser_read_uint32(&meter_id, tokens[3]) ||
+ (meter_id >= PIPELINE_FA_N_TC_MAX)) {
+ printf(CMD_MSG_INVALID_ARG, "meterid");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_yellow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- yellow_string, "Y");
+ if (strcmp(tokens[4], "trtcm")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "trtcm");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_y_action =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- y_action, "R#Y#G#D");
+ if (parser_read_uint64(&flow_params.m[meter_id].cir, tokens[5])) {
+ printf(CMD_MSG_INVALID_ARG, "cir");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_red_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- red_string, "R");
+ if (parser_read_uint64(&flow_params.m[meter_id].pir, tokens[6])) {
+ printf(CMD_MSG_INVALID_ARG, "pir");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_r_action =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
- r_action, "R#Y#G#D");
+ if (parser_read_uint64(&flow_params.m[meter_id].cbs, tokens[7])) {
+ printf(CMD_MSG_INVALID_ARG, "cbs");
+ return;
+ }
-cmdline_parse_inst_t cmd_fa_policer_config_bulk = {
- .f = cmd_fa_policer_config_bulk_parsed,
- .data = NULL,
- .help_str = "Flow policer configuration (multiple flows)",
- .tokens = {
- (void *) &cmd_fa_policer_config_bulk_p_string,
- (void *) &cmd_fa_policer_config_bulk_pipeline_id,
- (void *) &cmd_fa_policer_config_bulk_flows_string,
- (void *) &cmd_fa_policer_config_bulk_n_flows,
- (void *) &cmd_fa_policer_config_bulk_policer_string,
- (void *) &cmd_fa_policer_config_bulk_policer_id,
- (void *) &cmd_fa_policer_config_bulk_green_string,
- (void *) &cmd_fa_policer_config_bulk_g_action,
- (void *) &cmd_fa_policer_config_bulk_yellow_string,
- (void *) &cmd_fa_policer_config_bulk_y_action,
- (void *) &cmd_fa_policer_config_bulk_red_string,
- (void *) &cmd_fa_policer_config_bulk_r_action,
- NULL,
- },
-};
+ if (parser_read_uint64(&flow_params.m[meter_id].pbs, tokens[8])) {
+ printf(CMD_MSG_INVALID_ARG, "pbs");
+ return;
+ }
-/*
- * Flow output port configuration (single flow)
- *
- * p <pipeline ID> flow <flow ID> port <port ID>
- */
+ status = app_pipeline_fa_flow_config(app,
+ params->pipeline_id,
+ flow_id,
+ 1 << meter_id,
+ 0,
+ 0,
+ &flow_params);
+ if (status)
+ printf(CMD_MSG_FAIL, "action flow meter");
-struct cmd_fa_output_port_config_result {
- cmdline_fixed_string_t p_string;
- uint32_t pipeline_id;
- cmdline_fixed_string_t flow_string;
- uint32_t flow_id;
- cmdline_fixed_string_t port_string;
- uint32_t port_id;
-};
+ return;
+ } /* action flow meter */
+
+ /* action flow policer */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "flow") == 0) &&
+ strcmp(tokens[1], "bulk") &&
+ strcmp(tokens[1], "ls") &&
+ (strcmp(tokens[2], "policer") == 0)) {
+ struct pipeline_fa_flow_params flow_params;
+ uint32_t flow_id, policer_id;
+
+ if (n_tokens != 10) {
+ printf(CMD_MSG_MISMATCH_ARGS, "action flow policer");
+ return;
+ }
-static void
-cmd_fa_output_port_config_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_fa_output_port_config_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_fa_flow_params flow_params;
- int status;
+ memset(&flow_params, 0, sizeof(flow_params));
- flow_params.port_id = params->port_id;
+ if (parser_read_uint32(&flow_id, tokens[1])) {
+ printf(CMD_MSG_INVALID_ARG, "flowid");
+ return;
+ }
- status = app_pipeline_fa_flow_config(app,
- params->pipeline_id,
- params->flow_id,
- 0,
- 0,
- 1,
- &flow_params);
+ if (parser_read_uint32(&policer_id, tokens[3]) ||
+ (policer_id >= PIPELINE_FA_N_TC_MAX)) {
+ printf(CMD_MSG_INVALID_ARG, "policerid");
+ return;
+ }
- if (status != 0)
- printf("Command failed\n");
-}
+ if (strcmp(tokens[4], "g")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "g");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_output_port_config_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,
- p_string, "p");
+ if (string_to_policer_action(tokens[5],
+ &flow_params.p[policer_id].action[e_RTE_METER_GREEN])) {
+ printf(CMD_MSG_INVALID_ARG, "gaction");
+ return;
+ }
-cmdline_parse_token_num_t cmd_fa_output_port_config_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,
- pipeline_id, UINT32);
+ if (strcmp(tokens[6], "y")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "y");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_output_port_config_flow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,
- flow_string, "flow");
+ if (string_to_policer_action(tokens[7],
+ &flow_params.p[policer_id].action[e_RTE_METER_YELLOW])) {
+ printf(CMD_MSG_INVALID_ARG, "yaction");
+ return;
+ }
-cmdline_parse_token_num_t cmd_fa_output_port_config_flow_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,
- flow_id, UINT32);
+ if (strcmp(tokens[8], "r")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "r");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_output_port_config_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,
- port_string, "port");
+ if (string_to_policer_action(tokens[9],
+ &flow_params.p[policer_id].action[e_RTE_METER_RED])) {
+ printf(CMD_MSG_INVALID_ARG, "raction");
+ return;
+ }
-cmdline_parse_token_num_t cmd_fa_output_port_config_port_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,
- port_id, UINT32);
+ status = app_pipeline_fa_flow_config(app,
+ params->pipeline_id,
+ flow_id,
+ 0,
+ 1 << policer_id,
+ 0,
+ &flow_params);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "action flow policer");
-cmdline_parse_inst_t cmd_fa_output_port_config = {
- .f = cmd_fa_output_port_config_parsed,
- .data = NULL,
- .help_str = "Flow output port configuration (single flow)",
- .tokens = {
- (void *) &cmd_fa_output_port_config_p_string,
- (void *) &cmd_fa_output_port_config_pipeline_id,
- (void *) &cmd_fa_output_port_config_flow_string,
- (void *) &cmd_fa_output_port_config_flow_id,
- (void *) &cmd_fa_output_port_config_port_string,
- (void *) &cmd_fa_output_port_config_port_id,
- NULL,
- },
-};
+ return;
+ } /* action flow policer */
+
+ /* action flow port */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "flow") == 0) &&
+ strcmp(tokens[1], "bulk") &&
+ strcmp(tokens[1], "ls") &&
+ (strcmp(tokens[2], "port") == 0)) {
+ struct pipeline_fa_flow_params flow_params;
+ uint32_t flow_id, port_id;
+
+ if (n_tokens != 4) {
+ printf(CMD_MSG_MISMATCH_ARGS, "action flow port");
+ return;
+ }
-/*
- * Flow output port configuration (multiple flows)
- *
- * p <pipeline ID> flows <n_flows> ports <n_ports>
- */
+ memset(&flow_params, 0, sizeof(flow_params));
-struct cmd_fa_output_port_config_bulk_result {
- cmdline_fixed_string_t p_string;
- uint32_t pipeline_id;
- cmdline_fixed_string_t flows_string;
- uint32_t n_flows;
- cmdline_fixed_string_t ports_string;
- uint32_t n_ports;
-};
+ if (parser_read_uint32(&flow_id, tokens[1])) {
+ printf(CMD_MSG_INVALID_ARG, "flowid");
+ return;
+ }
-static void
-cmd_fa_output_port_config_bulk_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_fa_output_port_config_bulk_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_fa_flow_params *flow_params;
- uint32_t *flow_id;
- uint32_t i;
+ if (parser_read_uint32(&port_id, tokens[3])) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
- if (params->n_flows == 0) {
- printf("Invalid arguments\n");
- return;
- }
+ flow_params.port_id = port_id;
- flow_id = (uint32_t *) rte_malloc(NULL,
- N_FLOWS_BULK * sizeof(uint32_t),
- RTE_CACHE_LINE_SIZE);
- if (flow_id == NULL) {
- printf("Memory allocation failed\n");
- return;
- }
+ status = app_pipeline_fa_flow_config(app,
+ params->pipeline_id,
+ flow_id,
+ 0,
+ 0,
+ 1,
+ &flow_params);
+ if (status)
+ printf(CMD_MSG_FAIL, "action flow port");
- flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,
- N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),
- RTE_CACHE_LINE_SIZE);
- if (flow_params == NULL) {
- rte_free(flow_id);
- printf("Memory allocation failed\n");
return;
- }
-
- for (i = 0; i < params->n_flows; i++) {
- uint32_t pos = i % N_FLOWS_BULK;
- uint32_t port_id = i % params->n_ports;
-
- flow_id[pos] = i;
-
- memset(&flow_params[pos], 0, sizeof(flow_params[pos]));
- flow_params[pos].port_id = port_id;
+ } /* action flow port */
+
+ /* action flow stats */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "flow") == 0) &&
+ strcmp(tokens[1], "bulk") &&
+ strcmp(tokens[1], "ls") &&
+ (strcmp(tokens[2], "stats") == 0)) {
+ struct pipeline_fa_policer_stats stats;
+ uint32_t flow_id, policer_id;
+
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "action flow stats");
+ return;
+ }
- if ((pos == N_FLOWS_BULK - 1) ||
- (i == params->n_flows - 1)) {
- int status;
+ if (parser_read_uint32(&flow_id, tokens[1])) {
+ printf(CMD_MSG_INVALID_ARG, "flowid");
+ return;
+ }
- status = app_pipeline_fa_flow_config_bulk(app,
+ for (policer_id = 0;
+ policer_id < PIPELINE_FA_N_TC_MAX;
+ policer_id++) {
+ status = app_pipeline_fa_flow_policer_stats_read(app,
params->pipeline_id,
flow_id,
- pos + 1,
- 0,
- 0,
+ policer_id,
1,
- flow_params);
-
+ &stats);
if (status != 0) {
- printf("Command failed\n");
-
- break;
+ printf(CMD_MSG_FAIL, "action flow stats");
+ return;
}
- }
- }
-
- rte_free(flow_params);
- rte_free(flow_id);
-
-}
-
-cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
- p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
- pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_flows_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
- flows_string, "flows");
-
-cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_flows =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
- n_flows, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_ports_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
- ports_string, "ports");
-
-cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_ports =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
- n_ports, UINT32);
-
-cmdline_parse_inst_t cmd_fa_output_port_config_bulk = {
- .f = cmd_fa_output_port_config_bulk_parsed,
- .data = NULL,
- .help_str = "Flow output port configuration (multiple flows)",
- .tokens = {
- (void *) &cmd_fa_output_port_config_bulk_p_string,
- (void *) &cmd_fa_output_port_config_bulk_pipeline_id,
- (void *) &cmd_fa_output_port_config_bulk_flows_string,
- (void *) &cmd_fa_output_port_config_bulk_n_flows,
- (void *) &cmd_fa_output_port_config_bulk_ports_string,
- (void *) &cmd_fa_output_port_config_bulk_n_ports,
- NULL,
- },
-};
-
-/*
- * Flow DiffServ Code Point (DSCP) translation table configuration
- *
- * p <pipeline ID> dscp <DSCP ID> class <traffic class ID> color <color>
- *
- * <color> = G (green) | Y (yellow) | R (red)
-*/
-struct cmd_fa_dscp_config_result {
- cmdline_fixed_string_t p_string;
- uint32_t pipeline_id;
- cmdline_fixed_string_t dscp_string;
- uint32_t dscp_id;
- cmdline_fixed_string_t class_string;
- uint32_t traffic_class_id;
- cmdline_fixed_string_t color_string;
- cmdline_fixed_string_t color;
-
-};
-
-static void
-cmd_fa_dscp_config_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_fa_dscp_config_result *params = parsed_result;
- struct app_params *app = data;
- enum rte_meter_color color;
- int status;
+ /* Display stats */
+ printf("\tPolicer: %" PRIu32
+ "\tPkts G: %" PRIu64
+ "\tPkts Y: %" PRIu64
+ "\tPkts R: %" PRIu64
+ "\tPkts D: %" PRIu64 "\n",
+ policer_id,
+ stats.n_pkts[e_RTE_METER_GREEN],
+ stats.n_pkts[e_RTE_METER_YELLOW],
+ stats.n_pkts[e_RTE_METER_RED],
+ stats.n_pkts_drop);
+ }
- status = string_to_color(params->color, &color);
- if (status) {
- printf("Invalid color\n");
return;
- }
-
- status = app_pipeline_fa_dscp_config(app,
- params->pipeline_id,
- params->dscp_id,
- params->traffic_class_id,
- color);
-
- if (status != 0)
- printf("Command failed\n");
-}
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
- p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_dscp_config_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,
- pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_dscp_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
- dscp_string, "dscp");
-
-cmdline_parse_token_num_t cmd_fa_dscp_config_dscp_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,
- dscp_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_class_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
- class_string, "class");
-
-cmdline_parse_token_num_t cmd_fa_dscp_config_traffic_class_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,
- traffic_class_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_color_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
- color_string, "color");
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_color =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
- color, "G#Y#R");
+ } /* action flow stats */
+
+ /* action flow bulk */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "flow") == 0) &&
+ (strcmp(tokens[1], "bulk") == 0)) {
+ struct pipeline_fa_flow_params *flow_params;
+ uint32_t *flow_ids, n_flows, line;
+ char *filename;
+
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "action flow bulk");
+ return;
+ }
-cmdline_parse_inst_t cmd_fa_dscp_config = {
- .f = cmd_fa_dscp_config_parsed,
- .data = NULL,
- .help_str = "Flow DSCP translation table configuration",
- .tokens = {
- (void *) &cmd_fa_dscp_config_p_string,
- (void *) &cmd_fa_dscp_config_pipeline_id,
- (void *) &cmd_fa_dscp_config_dscp_string,
- (void *) &cmd_fa_dscp_config_dscp_id,
- (void *) &cmd_fa_dscp_config_class_string,
- (void *) &cmd_fa_dscp_config_traffic_class_id,
- (void *) &cmd_fa_dscp_config_color_string,
- (void *) &cmd_fa_dscp_config_color,
- NULL,
- },
-};
+ filename = tokens[2];
-/*
- * Flow policer stats read
- *
- * p <pipeline ID> flow <flow ID> policer <policer ID> stats
- */
+ n_flows = APP_PIPELINE_FA_MAX_RECORDS_IN_FILE;
+ flow_ids = malloc(n_flows * sizeof(uint32_t));
+ if (flow_ids == NULL) {
+ printf(CMD_MSG_OUT_OF_MEMORY);
+ return;
+ }
-struct cmd_fa_policer_stats_result {
- cmdline_fixed_string_t p_string;
- uint32_t pipeline_id;
- cmdline_fixed_string_t flow_string;
- uint32_t flow_id;
- cmdline_fixed_string_t policer_string;
- uint32_t policer_id;
- cmdline_fixed_string_t stats_string;
-};
+ flow_params = malloc(n_flows * sizeof(struct pipeline_fa_flow_params));
+ if (flow_params == NULL) {
+ printf(CMD_MSG_OUT_OF_MEMORY);
+ free(flow_ids);
+ return;
+ }
-static void
-cmd_fa_policer_stats_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_fa_policer_stats_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_fa_policer_stats stats;
- int status;
+ status = app_pipeline_fa_load_file(filename,
+ flow_ids,
+ flow_params,
+ &n_flows,
+ &line);
+ if (status) {
+ printf(CMD_MSG_FILE_ERR, filename, line);
+ free(flow_params);
+ free(flow_ids);
+ return;
+ }
- status = app_pipeline_fa_flow_policer_stats_read(app,
- params->pipeline_id,
- params->flow_id,
- params->policer_id,
- 1,
- &stats);
- if (status != 0) {
- printf("Command failed\n");
+ status = app_pipeline_fa_flow_config_bulk(app,
+ params->pipeline_id,
+ flow_ids,
+ n_flows,
+ 0xF,
+ 0xF,
+ 1,
+ flow_params);
+ if (status)
+ printf(CMD_MSG_FAIL, "action flow bulk");
+
+ free(flow_params);
+ free(flow_ids);
return;
- }
-
- /* Display stats */
- printf("\tPkts G: %" PRIu64
- "\tPkts Y: %" PRIu64
- "\tPkts R: %" PRIu64
- "\tPkts D: %" PRIu64 "\n",
- stats.n_pkts[e_RTE_METER_GREEN],
- stats.n_pkts[e_RTE_METER_YELLOW],
- stats.n_pkts[e_RTE_METER_RED],
- stats.n_pkts_drop);
-}
-
-cmdline_parse_token_string_t cmd_fa_policer_stats_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
- p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_policer_stats_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,
- pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_stats_flow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
- flow_string, "flow");
-
-cmdline_parse_token_num_t cmd_fa_policer_stats_flow_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,
- flow_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_stats_policer_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
- policer_string, "policer");
-
-cmdline_parse_token_num_t cmd_fa_policer_stats_policer_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,
- policer_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_stats_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
- stats_string, "stats");
-
-cmdline_parse_inst_t cmd_fa_policer_stats = {
- .f = cmd_fa_policer_stats_parsed,
- .data = NULL,
- .help_str = "Flow policer stats read",
- .tokens = {
- (void *) &cmd_fa_policer_stats_p_string,
- (void *) &cmd_fa_policer_stats_pipeline_id,
- (void *) &cmd_fa_policer_stats_flow_string,
- (void *) &cmd_fa_policer_stats_flow_id,
- (void *) &cmd_fa_policer_stats_policer_string,
- (void *) &cmd_fa_policer_stats_policer_id,
- (void *) &cmd_fa_policer_stats_string,
- NULL,
- },
-};
-
-/*
- * Flow list
- *
- * p <pipeline ID> flow ls
- */
+ } /* action flow bulk */
+
+ /* action flow ls */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "flow") == 0) &&
+ (strcmp(tokens[1], "ls") == 0)) {
+ if (n_tokens != 2) {
+ printf(CMD_MSG_MISMATCH_ARGS, "action flow ls");
+ return;
+ }
-struct cmd_fa_flow_ls_result {
- cmdline_fixed_string_t p_string;
- uint32_t pipeline_id;
- cmdline_fixed_string_t flow_string;
- cmdline_fixed_string_t actions_string;
- cmdline_fixed_string_t ls_string;
-};
+ status = app_pipeline_fa_flow_ls(app,
+ params->pipeline_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "action flow ls");
-static void
-cmd_fa_flow_ls_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_fa_flow_ls_result *params = parsed_result;
- struct app_params *app = data;
- int status;
-
- status = app_pipeline_fa_flow_ls(app, params->pipeline_id);
- if (status != 0)
- printf("Command failed\n");
-}
+ return;
+ } /* action flow ls */
+
+ /* action dscp */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "dscp") == 0) &&
+ strcmp(tokens[1], "ls")) {
+ uint32_t dscp_id, tc_id;
+ enum rte_meter_color color;
+
+ if (n_tokens != 6) {
+ printf(CMD_MSG_MISMATCH_ARGS, "action dscp");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_flow_ls_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
- p_string, "p");
+ if (parser_read_uint32(&dscp_id, tokens[1])) {
+ printf(CMD_MSG_INVALID_ARG, "dscpid");
+ return;
+ }
-cmdline_parse_token_num_t cmd_fa_flow_ls_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_flow_ls_result,
- pipeline_id, UINT32);
+ if (strcmp(tokens[2], "class")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "class");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_flow_ls_flow_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
- flow_string, "flow");
+ if (parser_read_uint32(&tc_id, tokens[3])) {
+ printf(CMD_MSG_INVALID_ARG, "classid");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_flow_ls_actions_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
- actions_string, "actions");
+ if (strcmp(tokens[4], "color")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "color");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fa_flow_ls_ls_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
- ls_string, "ls");
+ if (string_to_color(tokens[5], &color)) {
+ printf(CMD_MSG_INVALID_ARG, "colorid");
+ return;
+ }
-cmdline_parse_inst_t cmd_fa_flow_ls = {
- .f = cmd_fa_flow_ls_parsed,
- .data = NULL,
- .help_str = "Flow actions list",
- .tokens = {
- (void *) &cmd_fa_flow_ls_p_string,
- (void *) &cmd_fa_flow_ls_pipeline_id,
- (void *) &cmd_fa_flow_ls_flow_string,
- (void *) &cmd_fa_flow_ls_actions_string,
- (void *) &cmd_fa_flow_ls_ls_string,
- NULL,
- },
-};
+ status = app_pipeline_fa_dscp_config(app,
+ params->pipeline_id,
+ dscp_id,
+ tc_id,
+ color);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "action dscp");
-/*
- * Flow DiffServ Code Point (DSCP) translation table list
- *
- * p <pipeline ID> dscp ls
- */
+ return;
+ } /* action dscp */
+
+ /* action dscp ls */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "dscp") == 0) &&
+ (strcmp(tokens[1], "ls") == 0)) {
+ if (n_tokens != 2) {
+ printf(CMD_MSG_MISMATCH_ARGS, "action dscp ls");
+ return;
+ }
-struct cmd_fa_dscp_ls_result {
- cmdline_fixed_string_t p_string;
- uint32_t pipeline_id;
- cmdline_fixed_string_t dscp_string;
- cmdline_fixed_string_t ls_string;
-};
+ status = app_pipeline_fa_dscp_ls(app,
+ params->pipeline_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "action dscp ls");
-static void
-cmd_fa_dscp_ls_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_fa_dscp_ls_result *params = parsed_result;
- struct app_params *app = data;
- int status;
+ return;
+ } /* action dscp ls */
- status = app_pipeline_fa_dscp_ls(app, params->pipeline_id);
- if (status != 0)
- printf("Command failed\n");
+ printf(CMD_MSG_FAIL, "action");
}
-cmdline_parse_token_string_t cmd_fa_dscp_ls_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result,
- p_string, "p");
+static cmdline_parse_token_string_t cmd_action_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_action_result, p_string, "p");
-cmdline_parse_token_num_t cmd_fa_dscp_ls_pipeline_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_ls_result,
- pipeline_id, UINT32);
+static cmdline_parse_token_num_t cmd_action_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_action_result, pipeline_id, UINT32);
-cmdline_parse_token_string_t cmd_fa_dscp_ls_dscp_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result,
- dscp_string, "dscp");
+static cmdline_parse_token_string_t cmd_action_action_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_action_result, action_string, "action");
-cmdline_parse_token_string_t cmd_fa_dscp_ls_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result, ls_string,
- "ls");
+static cmdline_parse_token_string_t cmd_action_multi_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_action_result, multi_string,
+ TOKEN_STRING_MULTI);
-cmdline_parse_inst_t cmd_fa_dscp_ls = {
- .f = cmd_fa_dscp_ls_parsed,
+cmdline_parse_inst_t cmd_action = {
+ .f = cmd_action_parsed,
.data = NULL,
- .help_str = "Flow DSCP translaton table list",
+ .help_str = "flow actions (meter, policer, policer stats, dscp table)",
.tokens = {
- (void *) &cmd_fa_dscp_ls_p_string,
- (void *) &cmd_fa_dscp_ls_pipeline_id,
- (void *) &cmd_fa_dscp_ls_dscp_string,
- (void *) &cmd_fa_dscp_ls_string,
+ (void *) &cmd_action_p_string,
+ (void *) &cmd_action_pipeline_id,
+ (void *) &cmd_action_action_string,
+ (void *) &cmd_action_multi_string,
NULL,
},
};
static cmdline_parse_ctx_t pipeline_cmds[] = {
- (cmdline_parse_inst_t *) &cmd_fa_meter_config,
- (cmdline_parse_inst_t *) &cmd_fa_meter_config_bulk,
- (cmdline_parse_inst_t *) &cmd_fa_policer_config,
- (cmdline_parse_inst_t *) &cmd_fa_policer_config_bulk,
- (cmdline_parse_inst_t *) &cmd_fa_output_port_config,
- (cmdline_parse_inst_t *) &cmd_fa_output_port_config_bulk,
- (cmdline_parse_inst_t *) &cmd_fa_dscp_config,
- (cmdline_parse_inst_t *) &cmd_fa_policer_stats,
- (cmdline_parse_inst_t *) &cmd_fa_flow_ls,
- (cmdline_parse_inst_t *) &cmd_fa_dscp_ls,
+ (cmdline_parse_inst_t *) &cmd_action,
NULL,
};
static struct pipeline_fe_ops pipeline_flow_actions_fe_ops = {
.f_init = app_pipeline_fa_init,
+ .f_post_init = NULL,
.f_free = app_pipeline_fa_free,
+ .f_track = app_pipeline_track_default,
.cmds = pipeline_cmds,
};
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.h b/examples/ip_pipeline/pipeline/pipeline_flow_actions.h
index f2cd0cbb..9c609741 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.h
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.h
@@ -73,6 +73,17 @@ app_pipeline_fa_flow_policer_stats_read(struct app_params *app,
int clear,
struct pipeline_fa_policer_stats *stats);
+#ifndef APP_PIPELINE_FA_MAX_RECORDS_IN_FILE
+#define APP_PIPELINE_FA_MAX_RECORDS_IN_FILE 65536
+#endif
+
+int
+app_pipeline_fa_load_file(char *filename,
+ uint32_t *flow_ids,
+ struct pipeline_fa_flow_params *p,
+ uint32_t *n_flows,
+ uint32_t *line);
+
extern struct pipeline_type pipeline_flow_actions;
#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c
index 3ad3ee63..11fcbb76 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c
@@ -760,27 +760,6 @@ pipeline_fa_free(void *pipeline)
}
static int
-pipeline_fa_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_fa_timer(void *pipeline)
{
struct pipeline *p = (struct pipeline *) pipeline;
@@ -1007,5 +986,4 @@ struct pipeline_be_ops pipeline_flow_actions_be_ops = {
.f_free = pipeline_fa_free,
.f_run = NULL,
.f_timer = pipeline_fa_timer,
- .f_track = pipeline_fa_track,
};
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c
index 19215748..9ef50cc9 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-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
#include <string.h>
#include <sys/queue.h>
#include <netinet/in.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_hexdump.h>
@@ -43,13 +44,12 @@
#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 "app.h"
#include "pipeline_common_fe.h"
#include "pipeline_flow_classification.h"
#include "hash_func.h"
+#include "parser.h"
/*
* Key conversion
@@ -96,9 +96,9 @@ app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in,
struct pkt_key_qinq *qinq = key_buffer;
qinq->ethertype_svlan = 0;
- qinq->svlan = rte_bswap16(key_in->key.qinq.svlan);
+ qinq->svlan = rte_cpu_to_be_16(key_in->key.qinq.svlan);
qinq->ethertype_cvlan = 0;
- qinq->cvlan = rte_bswap16(key_in->key.qinq.cvlan);
+ qinq->cvlan = rte_cpu_to_be_16(key_in->key.qinq.cvlan);
if (signature)
*signature = (uint32_t) hash_default_key8(qinq, 8, 0);
@@ -112,10 +112,10 @@ app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in,
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);
+ ipv4->ip_src = rte_cpu_to_be_32(key_in->key.ipv4_5tuple.ip_src);
+ ipv4->ip_dst = rte_cpu_to_be_32(key_in->key.ipv4_5tuple.ip_dst);
+ ipv4->port_src = rte_cpu_to_be_16(key_in->key.ipv4_5tuple.port_src);
+ ipv4->port_dst = rte_cpu_to_be_16(key_in->key.ipv4_5tuple.port_dst);
if (signature)
*signature = (uint32_t) hash_default_key16(ipv4, 16, 0);
@@ -132,8 +132,8 @@ app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in,
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);
+ ipv6->port_src = rte_cpu_to_be_16(key_in->key.ipv6_5tuple.port_src);
+ ipv6->port_dst = rte_cpu_to_be_16(key_in->key.ipv6_5tuple.port_dst);
if (signature)
*signature = (uint32_t) hash_default_key64(ipv6, 64, 0);
@@ -278,6 +278,283 @@ app_pipeline_fc_key_check(struct pipeline_fc_key *key)
}
int
+app_pipeline_fc_load_file_qinq(char *filename,
+ struct pipeline_fc_key *keys,
+ uint32_t *port_ids,
+ uint32_t *flow_ids,
+ uint32_t *n_keys,
+ uint32_t *line)
+{
+ FILE *f = NULL;
+ char file_buf[1024];
+ uint32_t i, l;
+
+ /* Check input arguments */
+ if ((filename == NULL) ||
+ (keys == NULL) ||
+ (port_ids == NULL) ||
+ (flow_ids == NULL) ||
+ (n_keys == NULL) ||
+ (*n_keys == 0) ||
+ (line == NULL)) {
+ if (line)
+ *line = 0;
+ return -1;
+ }
+
+ /* Open input file */
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ *line = 0;
+ return -1;
+ }
+
+ /* Read file */
+ for (i = 0, l = 1; i < *n_keys; l++) {
+ char *tokens[32];
+ uint32_t n_tokens = RTE_DIM(tokens);
+
+ uint16_t svlan, cvlan;
+ uint32_t portid, flowid;
+ int status;
+
+ if (fgets(file_buf, sizeof(file_buf), f) == NULL)
+ break;
+
+ status = parse_tokenize_string(file_buf, tokens, &n_tokens);
+ if (status)
+ goto error1;
+
+ if ((n_tokens == 0) || (tokens[0][0] == '#'))
+ continue;
+
+ if ((n_tokens != 7) ||
+ strcmp(tokens[0], "qinq") ||
+ parser_read_uint16(&svlan, tokens[1]) ||
+ parser_read_uint16(&cvlan, tokens[2]) ||
+ strcmp(tokens[3], "port") ||
+ parser_read_uint32(&portid, tokens[4]) ||
+ strcmp(tokens[5], "id") ||
+ parser_read_uint32(&flowid, tokens[6]))
+ goto error1;
+
+ keys[i].type = FLOW_KEY_QINQ;
+ keys[i].key.qinq.svlan = svlan;
+ keys[i].key.qinq.cvlan = cvlan;
+
+ port_ids[i] = portid;
+ flow_ids[i] = flowid;
+
+ if (app_pipeline_fc_key_check(&keys[i]))
+ goto error1;
+
+ i++;
+ }
+
+ /* Close file */
+ *n_keys = i;
+ fclose(f);
+ return 0;
+
+error1:
+ *line = l;
+ fclose(f);
+ return -1;
+}
+
+int
+app_pipeline_fc_load_file_ipv4(char *filename,
+ struct pipeline_fc_key *keys,
+ uint32_t *port_ids,
+ uint32_t *flow_ids,
+ uint32_t *n_keys,
+ uint32_t *line)
+{
+ FILE *f = NULL;
+ char file_buf[1024];
+ uint32_t i, l;
+
+ /* Check input arguments */
+ if ((filename == NULL) ||
+ (keys == NULL) ||
+ (port_ids == NULL) ||
+ (flow_ids == NULL) ||
+ (n_keys == NULL) ||
+ (*n_keys == 0) ||
+ (line == NULL)) {
+ if (line)
+ *line = 0;
+ return -1;
+ }
+
+ /* Open input file */
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ *line = 0;
+ return -1;
+ }
+
+ /* Read file */
+ for (i = 0, l = 1; i < *n_keys; l++) {
+ char *tokens[32];
+ uint32_t n_tokens = RTE_DIM(tokens);
+
+ struct in_addr sipaddr, dipaddr;
+ uint16_t sport, dport;
+ uint8_t proto;
+ uint32_t portid, flowid;
+ int status;
+
+ if (fgets(file_buf, sizeof(file_buf), f) == NULL)
+ break;
+
+ status = parse_tokenize_string(file_buf, tokens, &n_tokens);
+ if (status)
+ goto error2;
+
+ if ((n_tokens == 0) || (tokens[0][0] == '#'))
+ continue;
+
+ if ((n_tokens != 10) ||
+ strcmp(tokens[0], "ipv4") ||
+ parse_ipv4_addr(tokens[1], &sipaddr) ||
+ parse_ipv4_addr(tokens[2], &dipaddr) ||
+ parser_read_uint16(&sport, tokens[3]) ||
+ parser_read_uint16(&dport, tokens[4]) ||
+ parser_read_uint8(&proto, tokens[5]) ||
+ strcmp(tokens[6], "port") ||
+ parser_read_uint32(&portid, tokens[7]) ||
+ strcmp(tokens[8], "id") ||
+ parser_read_uint32(&flowid, tokens[9]))
+ goto error2;
+
+ keys[i].type = FLOW_KEY_IPV4_5TUPLE;
+ keys[i].key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr);
+ keys[i].key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr);
+ keys[i].key.ipv4_5tuple.port_src = sport;
+ keys[i].key.ipv4_5tuple.port_dst = dport;
+ keys[i].key.ipv4_5tuple.proto = proto;
+
+ port_ids[i] = portid;
+ flow_ids[i] = flowid;
+
+ if (app_pipeline_fc_key_check(&keys[i]))
+ goto error2;
+
+ i++;
+ }
+
+ /* Close file */
+ *n_keys = i;
+ fclose(f);
+ return 0;
+
+error2:
+ *line = l;
+ fclose(f);
+ return -1;
+}
+
+int
+app_pipeline_fc_load_file_ipv6(char *filename,
+ struct pipeline_fc_key *keys,
+ uint32_t *port_ids,
+ uint32_t *flow_ids,
+ uint32_t *n_keys,
+ uint32_t *line)
+{
+ FILE *f = NULL;
+ char file_buf[1024];
+ uint32_t i, l;
+
+ /* Check input arguments */
+ if ((filename == NULL) ||
+ (keys == NULL) ||
+ (port_ids == NULL) ||
+ (flow_ids == NULL) ||
+ (n_keys == NULL) ||
+ (*n_keys == 0) ||
+ (line == NULL)) {
+ if (line)
+ *line = 0;
+ return -1;
+ }
+
+ /* Open input file */
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ *line = 0;
+ return -1;
+ }
+
+ /* Read file */
+ for (i = 0, l = 1; i < *n_keys; l++) {
+ char *tokens[32];
+ uint32_t n_tokens = RTE_DIM(tokens);
+
+ struct in6_addr sipaddr, dipaddr;
+ uint16_t sport, dport;
+ uint8_t proto;
+ uint32_t portid, flowid;
+ int status;
+
+ if (fgets(file_buf, sizeof(file_buf), f) == NULL)
+ break;
+
+ status = parse_tokenize_string(file_buf, tokens, &n_tokens);
+ if (status)
+ goto error3;
+
+ if ((n_tokens == 0) || (tokens[0][0] == '#'))
+ continue;
+
+ if ((n_tokens != 10) ||
+ strcmp(tokens[0], "ipv6") ||
+ parse_ipv6_addr(tokens[1], &sipaddr) ||
+ parse_ipv6_addr(tokens[2], &dipaddr) ||
+ parser_read_uint16(&sport, tokens[3]) ||
+ parser_read_uint16(&dport, tokens[4]) ||
+ parser_read_uint8(&proto, tokens[5]) ||
+ strcmp(tokens[6], "port") ||
+ parser_read_uint32(&portid, tokens[7]) ||
+ strcmp(tokens[8], "id") ||
+ parser_read_uint32(&flowid, tokens[9]))
+ goto error3;
+
+ keys[i].type = FLOW_KEY_IPV6_5TUPLE;
+ memcpy(keys[i].key.ipv6_5tuple.ip_src,
+ sipaddr.s6_addr,
+ sizeof(sipaddr.s6_addr));
+ memcpy(keys[i].key.ipv6_5tuple.ip_dst,
+ dipaddr.s6_addr,
+ sizeof(dipaddr.s6_addr));
+ keys[i].key.ipv6_5tuple.port_src = sport;
+ keys[i].key.ipv6_5tuple.port_dst = dport;
+ keys[i].key.ipv6_5tuple.proto = proto;
+
+ port_ids[i] = portid;
+ flow_ids[i] = flowid;
+
+ if (app_pipeline_fc_key_check(&keys[i]))
+ goto error3;
+
+ i++;
+ }
+
+ /* Close file */
+ *n_keys = i;
+ fclose(f);
+ return 0;
+
+error3:
+ *line = l;
+ fclose(f);
+ return -1;
+}
+
+
+
+int
app_pipeline_fc_add(struct app_params *app,
uint32_t pipeline_id,
struct pipeline_fc_key *key,
@@ -896,1315 +1173,728 @@ app_pipeline_fc_ls(struct app_params *app,
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;
- cmdline_fixed_string_t port_string;
- uint32_t port;
- cmdline_fixed_string_t flowid_string;
- uint32_t flow_id;
-};
-
-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,
- params->flow_id);
- 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_string_t cmd_fc_add_qinq_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, port_string,
- "port");
-
-cmdline_parse_token_num_t cmd_fc_add_qinq_port =
- TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, port, UINT32);
-
-cmdline_parse_token_string_t cmd_fc_add_qinq_flowid_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, flowid_string,
- "flowid");
-
-cmdline_parse_token_num_t cmd_fc_add_qinq_flow_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, flow_id, 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_string,
- (void *) &cmd_fc_add_qinq_port,
- (void *) &cmd_fc_add_qinq_flowid_string,
- (void *) &cmd_fc_add_qinq_flow_id,
- NULL,
- },
-};
-
-/*
- * flow add qinq all
+ * flow
+ *
+ * flow add:
+ * p <pipelineid> flow add qinq <svlan> <cvlan> port <portid> id <flowid>
+ * p <pipelineid> flow add qinq bulk <file>
+ * p <pipelineid> flow add ipv4 <sipaddr> <dipaddr> <sport> <dport> <proto> port <port ID> id <flowid>
+ * p <pipelineid> flow add ipv4 bulk <file>
+ * p <pipelineid> flow add ipv6 <sipaddr> <dipaddr> <sport> <dport> <proto> port <port ID> id <flowid>
+ * p <pipelineid> flow add ipv6 bulk <file>
+ *
+ * flow add default:
+ * p <pipelineid> flow add default <portid>
+ *
+ * flow del:
+ * p <pipelineid> flow del qinq <svlan> <cvlan>
+ * p <pipelineid> flow del ipv4 <sipaddr> <dipaddr> <sport> <dport> <proto>
+ * p <pipelineid> flow del ipv6 <sipaddr> <dipaddr> <sport> <dport> <proto>
+ *
+ * flow del default:
+ * p <pipelineid> flow del default
+ *
+ * flow ls:
+ * p <pipelineid> flow ls
*/
-struct cmd_fc_add_qinq_all_result {
+struct cmd_flow_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;
+ cmdline_multi_string_t multi_string;
};
-#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,
+cmd_flow_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
void *data)
{
- struct cmd_fc_add_qinq_all_result *params = parsed_result;
+ struct cmd_flow_result *results = parsed_result;
struct app_params *app = data;
- struct pipeline_fc_key *key;
- uint32_t *port_id;
- uint32_t *flow_id;
- uint32_t id;
-
- /* Check input arguments */
- if (params->n_flows == 0) {
- printf("Invalid number of flows\n");
- return;
- }
- if (params->n_ports == 0) {
- printf("Invalid number of output ports\n");
- return;
- }
-
- /* Memory allocation */
- 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;
- }
+ char *tokens[16];
+ uint32_t n_tokens = RTE_DIM(tokens);
+ int status;
- flow_id = rte_malloc(NULL,
- N_FLOWS_BULK * sizeof(*flow_id),
- RTE_CACHE_LINE_SIZE);
- if (flow_id == NULL) {
- rte_free(port_id);
- rte_free(key);
- printf("Memory allocation failed\n");
+ status = parse_tokenize_string(results->multi_string, tokens, &n_tokens);
+ if (status) {
+ printf(CMD_MSG_TOO_MANY_ARGS, "flow");
return;
}
- /* Flow add */
- for (id = 0; id < params->n_flows; id++) {
- uint32_t pos = id & (N_FLOWS_BULK - 1);
-
- key[pos].type = FLOW_KEY_QINQ;
- key[pos].key.qinq.svlan = id >> 12;
- key[pos].key.qinq.cvlan = id & 0xFFF;
-
- port_id[pos] = id % params->n_ports;
- flow_id[pos] = id;
-
- if ((pos == N_FLOWS_BULK - 1) ||
- (id == params->n_flows - 1)) {
- int status;
-
- status = app_pipeline_fc_add_bulk(app,
- params->pipeline_id,
- key,
- port_id,
- flow_id,
- pos + 1);
-
- if (status != 0) {
- printf("Command failed\n");
-
- break;
- }
+ /* flow add qinq */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "qinq") == 0) &&
+ strcmp(tokens[2], "bulk")) {
+ struct pipeline_fc_key key;
+ uint32_t svlan;
+ uint32_t cvlan;
+ uint32_t port_id;
+ uint32_t flow_id;
+
+ memset(&key, 0, sizeof(key));
+
+ if (n_tokens != 8) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow add qinq");
+ return;
}
- }
-
- /* Memory free */
- rte_free(flow_id);
- 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");
+ if (parser_read_uint32(&svlan, tokens[2]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "svlan");
+ return;
+ }
-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);
+ if (parser_read_uint32(&cvlan, tokens[3]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "cvlan");
+ return;
+ }
-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");
+ if (strcmp(tokens[4], "port") != 0) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
-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");
+ if (parser_read_uint32(&port_id, tokens[5]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
-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");
+ if (strcmp(tokens[6], "id") != 0) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "id");
+ return;
+ }
-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");
+ if (parser_read_uint32(&flow_id, tokens[7]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "flowid");
+ return;
+ }
-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);
+ key.type = FLOW_KEY_QINQ;
+ key.key.qinq.svlan = svlan;
+ key.key.qinq.cvlan = cvlan;
-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);
+ status = app_pipeline_fc_add(app,
+ results->pipeline_id,
+ &key,
+ port_id,
+ flow_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow add qinq");
-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,
- },
-};
+ return;
+ } /* flow add qinq */
+
+ /* flow add ipv4 */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "ipv4") == 0) &&
+ strcmp(tokens[2], "bulk")) {
+ struct pipeline_fc_key key;
+ struct in_addr sipaddr;
+ struct in_addr dipaddr;
+ uint32_t sport;
+ uint32_t dport;
+ uint32_t proto;
+ uint32_t port_id;
+ uint32_t flow_id;
+
+ memset(&key, 0, sizeof(key));
+
+ if (n_tokens != 11) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv4");
+ return;
+ }
-/*
- * flow add ipv4_5tuple
- */
+ if (parse_ipv4_addr(tokens[2], &sipaddr) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "sipv4addr");
+ return;
+ }
+ if (parse_ipv4_addr(tokens[3], &dipaddr) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "dipv4addr");
+ return;
+ }
-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;
- cmdline_fixed_string_t port_string;
- uint32_t port;
- cmdline_fixed_string_t flowid_string;
- uint32_t flow_id;
-};
+ if (parser_read_uint32(&sport, tokens[4]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "sport");
+ return;
+ }
-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;
+ if (parser_read_uint32(&dport, tokens[5]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "dport");
+ return;
+ }
- 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,
- params->flow_id);
- if (status != 0)
- printf("Command failed\n");
-}
+ if (parser_read_uint32(&proto, tokens[6]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "proto");
+ return;
+ }
-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");
+ if (strcmp(tokens[7], "port") != 0) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
-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);
+ if (parser_read_uint32(&port_id, tokens[8]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
-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");
+ if (strcmp(tokens[9], "id") != 0) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "id");
+ return;
+ }
-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");
+ if (parser_read_uint32(&flow_id, tokens[10]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "flowid");
+ return;
+ }
-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");
+ key.type = FLOW_KEY_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr);
+ key.key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr);
+ key.key.ipv4_5tuple.port_src = sport;
+ key.key.ipv4_5tuple.port_dst = dport;
+ key.key.ipv4_5tuple.proto = proto;
+
+ status = app_pipeline_fc_add(app,
+ results->pipeline_id,
+ &key,
+ port_id,
+ flow_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow add ipv4");
-cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_src =
- TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_src);
+ return;
+ } /* flow add ipv4 */
+
+ /* flow add ipv6 */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "ipv6") == 0) &&
+ strcmp(tokens[2], "bulk")) {
+ struct pipeline_fc_key key;
+ struct in6_addr sipaddr;
+ struct in6_addr dipaddr;
+ uint32_t sport;
+ uint32_t dport;
+ uint32_t proto;
+ uint32_t port_id;
+ uint32_t flow_id;
+
+ memset(&key, 0, sizeof(key));
+
+ if (n_tokens != 11) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv6");
+ return;
+ }
-cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_dst =
- TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_dst);
+ if (parse_ipv6_addr(tokens[2], &sipaddr) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "sipv6addr");
+ return;
+ }
+ if (parse_ipv6_addr(tokens[3], &dipaddr) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "dipv6addr");
+ return;
+ }
-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);
+ if (parser_read_uint32(&sport, tokens[4]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "sport");
+ return;
+ }
-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);
+ if (parser_read_uint32(&dport, tokens[5]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "dport");
+ return;
+ }
-cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_proto =
- TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, proto,
- UINT32);
+ if (parser_read_uint32(&proto, tokens[6]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "proto");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_string,
- "port");
+ if (strcmp(tokens[7], "port") != 0) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
-cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port =
- TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port,
- UINT32);
+ if (parser_read_uint32(&port_id, tokens[8]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_flowid_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result,
- flowid_string, "flowid");
+ if (strcmp(tokens[9], "id") != 0) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "id");
+ return;
+ }
-cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_flow_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, flow_id,
- UINT32);
+ if (parser_read_uint32(&flow_id, tokens[10]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "flowid");
+ return;
+ }
-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_string,
- (void *) &cmd_fc_add_ipv4_5tuple_port,
- (void *) &cmd_fc_add_ipv4_5tuple_flowid_string,
- (void *) &cmd_fc_add_ipv4_5tuple_flow_id,
- NULL,
- },
-};
+ key.type = FLOW_KEY_IPV6_5TUPLE;
+ memcpy(key.key.ipv6_5tuple.ip_src, (void *)&sipaddr, 16);
+ memcpy(key.key.ipv6_5tuple.ip_dst, (void *)&dipaddr, 16);
+ key.key.ipv6_5tuple.port_src = sport;
+ key.key.ipv6_5tuple.port_dst = dport;
+ key.key.ipv6_5tuple.proto = proto;
+
+ status = app_pipeline_fc_add(app,
+ results->pipeline_id,
+ &key,
+ port_id,
+ flow_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow add ipv6");
-/*
- * flow add ipv4_5tuple all
- */
+ return;
+ } /* flow add ipv6 */
+
+ /* flow add qinq bulk */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "qinq") == 0) &&
+ (strcmp(tokens[2], "bulk") == 0)) {
+ struct pipeline_fc_key *keys;
+ uint32_t *port_ids, *flow_ids, n_keys, line;
+ char *filename;
+
+ if (n_tokens != 4) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow add qinq bulk");
+ return;
+ }
-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;
-};
+ filename = tokens[3];
-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;
- uint32_t id;
-
- /* Check input parameters */
- if (params->n_flows == 0) {
- printf("Invalid number of flows\n");
- return;
- }
+ n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE;
+ keys = malloc(n_keys * sizeof(struct pipeline_fc_key));
+ if (keys == NULL)
+ return;
+ memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key));
- if (params->n_ports == 0) {
- printf("Invalid number of ports\n");
- return;
- }
+ port_ids = malloc(n_keys * sizeof(uint32_t));
+ if (port_ids == NULL) {
+ free(keys);
+ return;
+ }
- /* Memory allocation */
- key = rte_zmalloc(NULL,
- N_FLOWS_BULK * sizeof(*key),
- RTE_CACHE_LINE_SIZE);
- if (key == NULL) {
- printf("Memory allocation failed\n");
- return;
- }
+ flow_ids = malloc(n_keys * sizeof(uint32_t));
+ if (flow_ids == NULL) {
+ free(port_ids);
+ free(keys);
+ 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;
- }
+ status = app_pipeline_fc_load_file_qinq(filename,
+ keys,
+ port_ids,
+ flow_ids,
+ &n_keys,
+ &line);
+ if (status != 0) {
+ printf(CMD_MSG_FILE_ERR, filename, line);
+ free(flow_ids);
+ free(port_ids);
+ free(keys);
+ return;
+ }
- flow_id = rte_malloc(NULL,
- N_FLOWS_BULK * sizeof(*flow_id),
- RTE_CACHE_LINE_SIZE);
- if (flow_id == NULL) {
- rte_free(port_id);
- rte_free(key);
- printf("Memory allocation failed\n");
+ status = app_pipeline_fc_add_bulk(app,
+ results->pipeline_id,
+ keys,
+ port_ids,
+ flow_ids,
+ n_keys);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow add qinq bulk");
+
+ free(flow_ids);
+ free(port_ids);
+ free(keys);
return;
- }
-
- /* Flow add */
- for (id = 0; id < params->n_flows; id++) {
- uint32_t pos = id & (N_FLOWS_BULK - 1);
+ } /* flow add qinq bulk */
+
+ /* flow add ipv4 bulk */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "ipv4") == 0) &&
+ (strcmp(tokens[2], "bulk") == 0)) {
+ struct pipeline_fc_key *keys;
+ uint32_t *port_ids, *flow_ids, n_keys, line;
+ char *filename;
+
+ if (n_tokens != 4) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv4 bulk");
+ return;
+ }
- key[pos].type = FLOW_KEY_IPV4_5TUPLE;
- key[pos].key.ipv4_5tuple.ip_src = 0;
- key[pos].key.ipv4_5tuple.ip_dst = id;
- key[pos].key.ipv4_5tuple.port_src = 0;
- key[pos].key.ipv4_5tuple.port_dst = 0;
- key[pos].key.ipv4_5tuple.proto = 6;
+ filename = tokens[3];
- port_id[pos] = id % params->n_ports;
- flow_id[pos] = id;
+ n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE;
+ keys = malloc(n_keys * sizeof(struct pipeline_fc_key));
+ if (keys == NULL)
+ return;
+ memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key));
- if ((pos == N_FLOWS_BULK - 1) ||
- (id == params->n_flows - 1)) {
- int status;
+ port_ids = malloc(n_keys * sizeof(uint32_t));
+ if (port_ids == NULL) {
+ free(keys);
+ return;
+ }
- status = app_pipeline_fc_add_bulk(app,
- params->pipeline_id,
- key,
- port_id,
- flow_id,
- pos + 1);
+ flow_ids = malloc(n_keys * sizeof(uint32_t));
+ if (flow_ids == NULL) {
+ free(port_ids);
+ free(keys);
+ return;
+ }
- if (status != 0) {
- printf("Command failed\n");
+ status = app_pipeline_fc_load_file_ipv4(filename,
+ keys,
+ port_ids,
+ flow_ids,
+ &n_keys,
+ &line);
+ if (status != 0) {
+ printf(CMD_MSG_FILE_ERR, filename, line);
+ free(flow_ids);
+ free(port_ids);
+ free(keys);
+ return;
+ }
- break;
- }
+ status = app_pipeline_fc_add_bulk(app,
+ results->pipeline_id,
+ keys,
+ port_ids,
+ flow_ids,
+ n_keys);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow add ipv4 bulk");
+
+ free(flow_ids);
+ free(port_ids);
+ free(keys);
+ return;
+ } /* flow add ipv4 bulk */
+
+ /* flow add ipv6 bulk */
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "ipv6") == 0) &&
+ (strcmp(tokens[2], "bulk") == 0)) {
+ struct pipeline_fc_key *keys;
+ uint32_t *port_ids, *flow_ids, n_keys, line;
+ char *filename;
+
+ if (n_tokens != 4) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv6 bulk");
+ return;
}
- }
- /* Memory free */
- rte_free(flow_id);
- rte_free(port_id);
- rte_free(key);
-}
+ filename = tokens[3];
-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");
+ n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE;
+ keys = malloc(n_keys * sizeof(struct pipeline_fc_key));
+ if (keys == NULL)
+ return;
+ memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key));
-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);
+ port_ids = malloc(n_keys * sizeof(uint32_t));
+ if (port_ids == NULL) {
+ free(keys);
+ return;
+ }
-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");
+ flow_ids = malloc(n_keys * sizeof(uint32_t));
+ if (flow_ids == NULL) {
+ free(port_ids);
+ free(keys);
+ return;
+ }
-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");
+ status = app_pipeline_fc_load_file_ipv6(filename,
+ keys,
+ port_ids,
+ flow_ids,
+ &n_keys,
+ &line);
+ if (status != 0) {
+ printf(CMD_MSG_FILE_ERR, filename, line);
+ free(flow_ids);
+ free(port_ids);
+ free(keys);
+ return;
+ }
-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");
+ status = app_pipeline_fc_add_bulk(app,
+ results->pipeline_id,
+ keys,
+ port_ids,
+ flow_ids,
+ n_keys);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow add ipv6 bulk");
+
+ free(flow_ids);
+ free(port_ids);
+ free(keys);
+ return;
+ } /* flow add ipv6 bulk */
-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");
+ /* flow add default*/
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "default") == 0)) {
+ uint32_t port_id;
-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);
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow add default");
+ return;
+ }
-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);
+ if (parser_read_uint32(&port_id, tokens[2]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
-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,
- },
-};
+ status = app_pipeline_fc_add_default(app,
+ results->pipeline_id,
+ port_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow add default");
-/*
- * flow add ipv6_5tuple
- */
+ return;
+ } /* flow add default */
-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;
- cmdline_fixed_string_t port_string;
- uint32_t port;
- cmdline_fixed_string_t flowid_string;
- uint32_t flow_id;
-};
+ /* flow del qinq */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ (strcmp(tokens[1], "qinq") == 0)) {
+ struct pipeline_fc_key key;
+ uint32_t svlan;
+ uint32_t cvlan;
-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));
- 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,
- params->flow_id);
- if (status != 0)
- printf("Command failed\n");
-}
+ if (n_tokens != 4) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow del qinq");
+ return;
+ }
-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");
+ if (parser_read_uint32(&svlan, tokens[2]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "svlan");
+ return;
+ }
-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);
+ if (parser_read_uint32(&cvlan, tokens[3]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "cvlan");
+ return;
+ }
-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");
+ key.type = FLOW_KEY_QINQ;
+ key.key.qinq.svlan = svlan;
+ key.key.qinq.cvlan = cvlan;
-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");
+ status = app_pipeline_fc_del(app,
+ results->pipeline_id,
+ &key);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow del qinq");
-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");
+ return;
+ } /* flow del qinq */
+
+ /* flow del ipv4 */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ (strcmp(tokens[1], "ipv4") == 0)) {
+ struct pipeline_fc_key key;
+ struct in_addr sipaddr;
+ struct in_addr dipaddr;
+ uint32_t sport;
+ uint32_t dport;
+ uint32_t proto;
+
+ memset(&key, 0, sizeof(key));
+
+ if (n_tokens != 7) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow del ipv4");
+ return;
+ }
-cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_src =
- TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_src);
+ if (parse_ipv4_addr(tokens[2], &sipaddr) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "sipv4addr");
+ return;
+ }
+ if (parse_ipv4_addr(tokens[3], &dipaddr) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "dipv4addr");
+ return;
+ }
-cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_dst =
- TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_dst);
+ if (parser_read_uint32(&sport, tokens[4]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "sport");
+ return;
+ }
-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);
+ if (parser_read_uint32(&dport, tokens[5]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "dport");
+ return;
+ }
-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);
+ if (parser_read_uint32(&proto, tokens[6]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "proto");
+ return;
+ }
-cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_proto =
- TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, proto,
- UINT32);
+ key.type = FLOW_KEY_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr);
+ key.key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr);
+ key.key.ipv4_5tuple.port_src = sport;
+ key.key.ipv4_5tuple.port_dst = dport;
+ key.key.ipv4_5tuple.proto = proto;
-cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result,
- port_string, "port");
+ status = app_pipeline_fc_del(app,
+ results->pipeline_id,
+ &key);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow del ipv4");
-cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port =
- TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port,
- UINT32);
+ return;
+ } /* flow del ipv4 */
+
+ /* flow del ipv6 */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ (strcmp(tokens[1], "ipv6") == 0)) {
+ struct pipeline_fc_key key;
+ struct in6_addr sipaddr;
+ struct in6_addr dipaddr;
+ uint32_t sport;
+ uint32_t dport;
+ uint32_t proto;
+
+ memset(&key, 0, sizeof(key));
+
+ if (n_tokens != 7) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow del ipv6");
+ return;
+ }
-cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_flowid_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result,
- flowid_string, "flowid");
+ if (parse_ipv6_addr(tokens[2], &sipaddr) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "sipv6addr");
+ return;
+ }
-cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_flow_id =
- TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, flow_id,
- UINT32);
+ if (parse_ipv6_addr(tokens[3], &dipaddr) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "dipv6addr");
+ return;
+ }
-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_string,
- (void *) &cmd_fc_add_ipv6_5tuple_port,
- (void *) &cmd_fc_add_ipv6_5tuple_flowid_string,
- (void *) &cmd_fc_add_ipv6_5tuple_flow_id,
- NULL,
- },
-};
+ if (parser_read_uint32(&sport, tokens[4]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "sport");
+ return;
+ }
-/*
- * flow add ipv6_5tuple all
- */
+ if (parser_read_uint32(&dport, tokens[5]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "dport");
+ return;
+ }
-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;
-};
+ if (parser_read_uint32(&proto, tokens[6]) != 0) {
+ printf(CMD_MSG_INVALID_ARG, "proto");
+ return;
+ }
-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;
- uint32_t id;
-
- /* Check input parameters */
- if (params->n_flows == 0) {
- printf("Invalid number of flows\n");
- return;
- }
+ key.type = FLOW_KEY_IPV6_5TUPLE;
+ memcpy(key.key.ipv6_5tuple.ip_src, &sipaddr, 16);
+ memcpy(key.key.ipv6_5tuple.ip_dst, &dipaddr, 16);
+ key.key.ipv6_5tuple.port_src = sport;
+ key.key.ipv6_5tuple.port_dst = dport;
+ key.key.ipv6_5tuple.proto = proto;
- if (params->n_ports == 0) {
- printf("Invalid number of ports\n");
- return;
- }
+ status = app_pipeline_fc_del(app,
+ results->pipeline_id,
+ &key);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow del ipv6");
- /* Memory allocation */
- key = rte_zmalloc(NULL,
- N_FLOWS_BULK * sizeof(*key),
- RTE_CACHE_LINE_SIZE);
- if (key == NULL) {
- printf("Memory allocation failed\n");
return;
- }
+ } /* flow del ipv6 */
+
+ /* flow del default*/
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ (strcmp(tokens[1], "default") == 0)) {
+ if (n_tokens != 2) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow del default");
+ return;
+ }
- 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;
- }
+ status = app_pipeline_fc_del_default(app,
+ results->pipeline_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow del default");
- flow_id = rte_malloc(NULL,
- N_FLOWS_BULK * sizeof(*flow_id),
- RTE_CACHE_LINE_SIZE);
- if (flow_id == NULL) {
- rte_free(port_id);
- rte_free(key);
- printf("Memory allocation failed\n");
return;
- }
-
- /* Flow add */
- for (id = 0; id < params->n_flows; id++) {
- uint32_t pos = 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(id);
- key[pos].key.ipv6_5tuple.proto = 6;
-
- port_id[pos] = id % params->n_ports;
- flow_id[pos] = id;
+ } /* flow del default */
- if ((pos == N_FLOWS_BULK - 1) ||
- (id == params->n_flows - 1)) {
- int status;
-
- status = app_pipeline_fc_add_bulk(app,
- params->pipeline_id,
- key,
- port_id,
- flow_id,
- pos + 1);
-
- if (status != 0) {
- printf("Command failed\n");
-
- break;
- }
+ /* flow ls */
+ if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
+ if (n_tokens != 1) {
+ printf(CMD_MSG_MISMATCH_ARGS, "flow ls");
+ return;
}
- }
-
- /* Memory free */
- rte_free(flow_id);
- 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);
+ status = app_pipeline_fc_ls(app, results->pipeline_id);
+ if (status)
+ printf(CMD_MSG_FAIL, "flow ls");
-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;
+ return;
+ } /* flow ls */
- status = app_pipeline_fc_ls(app, params->pipeline_id);
- if (status != 0)
- printf("Command failed\n");
+ printf(CMD_MSG_MISMATCH_ARGS, "flow");
}
-cmdline_parse_token_string_t cmd_fc_ls_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, p_string, "p");
+static cmdline_parse_token_string_t cmd_flow_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_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);
+static cmdline_parse_token_num_t cmd_flow_pipeline_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_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");
+static cmdline_parse_token_string_t cmd_flow_flow_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_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");
+static cmdline_parse_token_string_t cmd_flow_multi_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_result, multi_string,
+ TOKEN_STRING_MULTI);
-cmdline_parse_inst_t cmd_fc_ls = {
- .f = cmd_fc_ls_parsed,
+static cmdline_parse_inst_t cmd_flow = {
+ .f = cmd_flow_parsed,
.data = NULL,
- .help_str = "Flow list",
+ .help_str = "flow add / add bulk / add default / del / del default / ls",
.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,
+ (void *) &cmd_flow_p_string,
+ (void *) &cmd_flow_pipeline_id,
+ (void *) &cmd_flow_flow_string,
+ (void *) &cmd_flow_multi_string,
NULL,
},
};
static cmdline_parse_ctx_t pipeline_cmds[] = {
- (cmdline_parse_inst_t *) &cmd_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,
+ (cmdline_parse_inst_t *) &cmd_flow,
NULL,
};
static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = {
.f_init = app_pipeline_fc_init,
+ .f_post_init = NULL,
.f_free = app_pipeline_fc_free,
+ .f_track = app_pipeline_track_default,
.cmds = pipeline_cmds,
};
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.h b/examples/ip_pipeline/pipeline/pipeline_flow_classification.h
index 9c775006..6c5ed384 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.h
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.h
@@ -102,6 +102,34 @@ int
app_pipeline_fc_del_default(struct app_params *app,
uint32_t pipeline_id);
+#ifndef APP_PIPELINE_FC_MAX_FLOWS_IN_FILE
+#define APP_PIPELINE_FC_MAX_FLOWS_IN_FILE (16 * 1024 * 1024)
+#endif
+
+int
+app_pipeline_fc_load_file_qinq(char *filename,
+ struct pipeline_fc_key *keys,
+ uint32_t *port_ids,
+ uint32_t *flow_ids,
+ uint32_t *n_keys,
+ uint32_t *line);
+
+int
+app_pipeline_fc_load_file_ipv4(char *filename,
+ struct pipeline_fc_key *keys,
+ uint32_t *port_ids,
+ uint32_t *flow_ids,
+ uint32_t *n_keys,
+ uint32_t *line);
+
+int
+app_pipeline_fc_load_file_ipv6(char *filename,
+ struct pipeline_fc_key *keys,
+ uint32_t *port_ids,
+ uint32_t *flow_ids,
+ uint32_t *n_keys,
+ uint32_t *line);
+
extern struct pipeline_type pipeline_flow_classification;
#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
index 70d976d5..8a762bc7 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
@@ -643,27 +643,6 @@ pipeline_fc_free(void *pipeline)
}
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;
@@ -807,5 +786,4 @@ struct pipeline_be_ops pipeline_flow_classification_be_ops = {
.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_master.c b/examples/ip_pipeline/pipeline/pipeline_master.c
index 1ccdad14..aab58a27 100644
--- a/examples/ip_pipeline/pipeline/pipeline_master.c
+++ b/examples/ip_pipeline/pipeline/pipeline_master.c
@@ -36,7 +36,9 @@
static struct pipeline_fe_ops pipeline_master_fe_ops = {
.f_init = NULL,
+ .f_post_init = NULL,
.f_free = NULL,
+ .f_track = NULL,
.cmds = NULL,
};
diff --git a/examples/ip_pipeline/pipeline/pipeline_master_be.c b/examples/ip_pipeline/pipeline/pipeline_master_be.c
index ac0cbbc5..9a7c8c13 100644
--- a/examples/ip_pipeline/pipeline/pipeline_master_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_master_be.c
@@ -48,6 +48,7 @@
struct pipeline_master {
struct app_params *app;
struct cmdline *cl;
+ int post_init_done;
int script_file_done;
} __rte_cache_aligned;
@@ -77,6 +78,7 @@ pipeline_init(__rte_unused struct pipeline_params *params, void *arg)
return NULL;
}
+ p->post_init_done = 0;
p->script_file_done = 0;
if (app->script_file == NULL)
p->script_file_done = 1;
@@ -102,8 +104,20 @@ static int
pipeline_run(void *pipeline)
{
struct pipeline_master *p = (struct pipeline_master *) pipeline;
+ struct app_params *app = p->app;
int status;
+#ifdef RTE_LIBRTE_KNI
+ uint32_t i;
+#endif /* RTE_LIBRTE_KNI */
+ /* Application post-init phase */
+ if (p->post_init_done == 0) {
+ app_post_init(app);
+
+ p->post_init_done = 1;
+ }
+
+ /* Run startup script file */
if (p->script_file_done == 0) {
struct app_params *app = p->app;
int fd = open(app->script_file, O_RDONLY);
@@ -124,6 +138,7 @@ pipeline_run(void *pipeline)
p->script_file_done = 1;
}
+ /* Command Line Interface (CLI) */
status = cmdline_poll(p->cl);
if (status < 0)
rte_panic("CLI poll error (%" PRId32 ")\n", status);
@@ -132,6 +147,12 @@ pipeline_run(void *pipeline)
rte_exit(0, "Bye!\n");
}
+#ifdef RTE_LIBRTE_KNI
+ /* Handle KNI requests from Linux kernel */
+ for (i = 0; i < app->n_pktq_kni; i++)
+ rte_kni_handle_request(app->kni[i]);
+#endif /* RTE_LIBRTE_KNI */
+
return 0;
}
@@ -146,5 +167,4 @@ struct pipeline_be_ops pipeline_master_be_ops = {
.f_free = pipeline_free,
.f_run = pipeline_run,
.f_timer = pipeline_timer,
- .f_track = NULL,
};
diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough.c b/examples/ip_pipeline/pipeline/pipeline_passthrough.c
index fc2cae5e..63ce1472 100644
--- a/examples/ip_pipeline/pipeline/pipeline_passthrough.c
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough.c
@@ -34,9 +34,36 @@
#include "pipeline_passthrough.h"
#include "pipeline_passthrough_be.h"
+static int
+app_pipeline_passthrough_track(struct pipeline_params *p,
+ uint32_t port_in,
+ uint32_t *port_out)
+{
+ struct pipeline_passthrough_params pp;
+ int status;
+
+ /* Check input arguments */
+ if ((p == NULL) ||
+ (port_in >= p->n_ports_in) ||
+ (port_out == NULL))
+ return -1;
+
+ status = pipeline_passthrough_parse_args(&pp, p);
+ if (status)
+ return -1;
+
+ if (pp.lb_hash_enabled)
+ return -1;
+
+ *port_out = port_in / (p->n_ports_in / p->n_ports_out);
+ return 0;
+}
+
static struct pipeline_fe_ops pipeline_passthrough_fe_ops = {
.f_init = NULL,
+ .f_post_init = NULL,
.f_free = NULL,
+ .f_track = app_pipeline_passthrough_track,
.cmds = NULL,
};
diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
index a0d11aea..6146a28f 100644
--- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
@@ -547,6 +547,18 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,
"dma_src_mask", dma_mask_str);
}
+ if (p->lb_hash_enabled)
+ PIPELINE_ARG_CHECK((params->n_ports_out > 1),
+ "Parse error in section \"%s\": entry \"lb\" not "
+ "allowed for single output port pipeline",
+ params->name);
+ else
+ PIPELINE_ARG_CHECK(((params->n_ports_in >= params->n_ports_out)
+ && ((params->n_ports_in % params->n_ports_out) == 0)),
+ "Parse error in section \"%s\": n_ports_in needs to be "
+ "a multiple of n_ports_out (lb mode disabled)",
+ params->name);
+
return 0;
}
@@ -579,9 +591,7 @@ pipeline_passthrough_init(struct pipeline_params *params,
/* 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))
+ (params->n_ports_out == 0))
return NULL;
/* Memory allocation */
@@ -702,10 +712,13 @@ pipeline_passthrough_init(struct pipeline_params *params,
/* Add entries to tables */
for (i = 0; i < p->n_ports_in; i++) {
+ uint32_t port_out_id = (p_pt->params.lb_hash_enabled == 0) ?
+ (i / (p->n_ports_in / p->n_ports_out)) :
+ 0;
+
struct rte_pipeline_table_entry default_entry = {
.action = RTE_PIPELINE_ACTION_PORT,
- {.port_id = p->port_out_id[
- i / (p->n_ports_in / p->n_ports_out)]},
+ {.port_id = p->port_out_id[port_out_id]},
};
struct rte_pipeline_table_entry *default_entry_ptr;
@@ -780,25 +793,9 @@ pipeline_passthrough_timer(void *pipeline)
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_routing.c b/examples/ip_pipeline/pipeline/pipeline_routing.c
index eab89f2e..3aadbf91 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-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,12 +34,11 @@
#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 "app.h"
#include "pipeline_common_fe.h"
#include "pipeline_routing.h"
+#include "parser.h"
struct app_pipeline_routing_route {
struct pipeline_routing_route_key key;
@@ -59,8 +58,14 @@ struct app_pipeline_routing_arp_entry {
struct pipeline_routing {
/* Parameters */
+ struct app_params *app;
+ uint32_t pipeline_id;
uint32_t n_ports_in;
uint32_t n_ports_out;
+ struct pipeline_routing_params rp;
+
+ /* Links */
+ uint32_t link_id[PIPELINE_MAX_PORT_OUT];
/* Routes */
TAILQ_HEAD(, app_pipeline_routing_route) routes;
@@ -79,12 +84,151 @@ struct pipeline_routing {
void *default_arp_entry_ptr;
};
+static int
+app_pipeline_routing_find_link(struct pipeline_routing *p,
+ uint32_t link_id,
+ uint32_t *port_id)
+{
+ uint32_t i;
+
+ for (i = 0; i < p->n_ports_out; i++)
+ if (p->link_id[i] == link_id) {
+ *port_id = i;
+ return 0;
+ }
+
+ return -1;
+}
+
+static void
+app_pipeline_routing_link_op(__rte_unused struct app_params *app,
+ uint32_t link_id,
+ uint32_t up,
+ void *arg)
+{
+ struct pipeline_routing_route_key key0, key1;
+ struct pipeline_routing *p = arg;
+ struct app_link_params *lp;
+ uint32_t port_id, netmask;
+ int status;
+
+ if (app == NULL)
+ return;
+
+ APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, lp);
+ if (lp == NULL)
+ return;
+
+ status = app_pipeline_routing_find_link(p,
+ link_id,
+ &port_id);
+ if (status)
+ return;
+
+ netmask = (~0U) << (32 - lp->depth);
+
+ /* Local network (directly attached network) */
+ key0.type = PIPELINE_ROUTING_ROUTE_IPV4;
+ key0.key.ipv4.ip = lp->ip & netmask;
+ key0.key.ipv4.depth = lp->depth;
+
+ /* Local termination */
+ key1.type = PIPELINE_ROUTING_ROUTE_IPV4;
+ key1.key.ipv4.ip = lp->ip;
+ key1.key.ipv4.depth = 32;
+
+ if (up) {
+ struct pipeline_routing_route_data data0, data1;
+
+ /* Local network (directly attached network) */
+ memset(&data0, 0, sizeof(data0));
+ data0.flags = PIPELINE_ROUTING_ROUTE_LOCAL |
+ PIPELINE_ROUTING_ROUTE_ARP;
+ if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ)
+ data0.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
+ if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) {
+ data0.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
+ data0.l2.mpls.n_labels = 1;
+ }
+ data0.port_id = port_id;
+
+ if (p->rp.n_arp_entries)
+ app_pipeline_routing_add_route(app,
+ p->pipeline_id,
+ &key0,
+ &data0);
+
+ /* Local termination */
+ memset(&data1, 0, sizeof(data1));
+ data1.flags = PIPELINE_ROUTING_ROUTE_LOCAL |
+ PIPELINE_ROUTING_ROUTE_ARP;
+ if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ)
+ data1.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
+ if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) {
+ data1.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
+ data1.l2.mpls.n_labels = 1;
+ }
+ data1.port_id = p->rp.port_local_dest;
+
+ app_pipeline_routing_add_route(app,
+ p->pipeline_id,
+ &key1,
+ &data1);
+ } else {
+ /* Local network (directly attached network) */
+ if (p->rp.n_arp_entries)
+ app_pipeline_routing_delete_route(app,
+ p->pipeline_id,
+ &key0);
+
+ /* Local termination */
+ app_pipeline_routing_delete_route(app,
+ p->pipeline_id,
+ &key1);
+ }
+}
+
+static int
+app_pipeline_routing_set_link_op(
+ struct app_params *app,
+ struct pipeline_routing *p)
+{
+ uint32_t port_id;
+
+ for (port_id = 0; port_id < p->n_ports_out; port_id++) {
+ struct app_link_params *link;
+ uint32_t link_id;
+ int status;
+
+ link = app_pipeline_track_pktq_out_to_link(app,
+ p->pipeline_id,
+ port_id);
+ if (link == NULL)
+ continue;
+
+ link_id = link - app->link_params;
+ p->link_id[port_id] = link_id;
+
+ status = app_link_set_op(app,
+ link_id,
+ p->pipeline_id,
+ app_pipeline_routing_link_op,
+ (void *) p);
+ if (status)
+ return status;
+ }
+
+ return 0;
+}
+
static void *
-pipeline_routing_init(struct pipeline_params *params,
- __rte_unused void *arg)
+app_pipeline_routing_init(struct pipeline_params *params,
+ void *arg)
{
+ struct app_params *app = (struct app_params *) arg;
struct pipeline_routing *p;
- uint32_t size;
+ uint32_t pipeline_id, size;
+ int status;
/* Check input arguments */
if ((params == NULL) ||
@@ -92,6 +236,8 @@ pipeline_routing_init(struct pipeline_params *params,
(params->n_ports_out == 0))
return NULL;
+ APP_PARAM_GET_ID(params, "PIPELINE", pipeline_id);
+
/* Memory allocation */
size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
@@ -99,19 +245,40 @@ pipeline_routing_init(struct pipeline_params *params,
return NULL;
/* Initialization */
+ p->app = app;
+ p->pipeline_id = pipeline_id;
p->n_ports_in = params->n_ports_in;
p->n_ports_out = params->n_ports_out;
+ status = pipeline_routing_parse_args(&p->rp, params);
+ if (status) {
+ rte_free(p);
+ return NULL;
+ }
TAILQ_INIT(&p->routes);
p->n_routes = 0;
TAILQ_INIT(&p->arp_entries);
p->n_arp_entries = 0;
+ app_pipeline_routing_set_link_op(app, p);
+
return p;
}
static int
+app_pipeline_routing_post_init(void *pipeline)
+{
+ struct pipeline_routing *p = pipeline;
+
+ /* Check input arguments */
+ if (p == NULL)
+ return -1;
+
+ return app_pipeline_routing_set_macaddr(p->app, p->pipeline_id);
+}
+
+static int
app_pipeline_routing_free(void *pipeline)
{
struct pipeline_routing *p = pipeline;
@@ -198,7 +365,9 @@ print_route(const struct app_pipeline_routing_route *route)
key->depth,
route->data.port_id);
- if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP)
+ if (route->data.flags & PIPELINE_ROUTING_ROUTE_LOCAL)
+ printf(", Local");
+ else if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP)
printf(
", Next Hop IP = %" PRIu32 ".%" PRIu32
".%" PRIu32 ".%" PRIu32,
@@ -383,8 +552,6 @@ app_pipeline_routing_add_route(struct app_params *app,
p->n_routes++;
}
- print_route(entry);
-
/* Message buffer free */
app_msg_free(app, rsp);
return 0;
@@ -677,8 +844,6 @@ app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id,
p->n_arp_entries++;
}
- print_arp_entry(entry);
-
/* Message buffer free */
app_msg_free(app, rsp);
return 0;
@@ -853,1382 +1018,600 @@ app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
return 0;
}
-static int
-parse_labels(char *string, uint32_t *labels, uint32_t *n_labels)
+int
+app_pipeline_routing_set_macaddr(struct app_params *app,
+ uint32_t pipeline_id)
{
- uint32_t n_max_labels = *n_labels, count = 0;
-
- /* Check for void list of labels */
- if (strcmp(string, "<void>") == 0) {
- *n_labels = 0;
- return 0;
- }
+ struct app_pipeline_params *p;
+ struct pipeline_routing_set_macaddr_msg_req *req;
+ struct pipeline_routing_set_macaddr_msg_rsp *rsp;
+ uint32_t port_id;
- /* At least one label should be present */
- for ( ; (*string != '\0'); ) {
- char *next;
- int value;
+ /* Check input arguments */
+ if (app == NULL)
+ return -EINVAL;
- if (count >= n_max_labels)
- return -1;
+ APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
+ if (p == NULL)
+ return -EINVAL;
- if (count > 0) {
- if (string[0] != ':')
- return -1;
+ /* Allocate and write request */
+ req = app_msg_alloc(app);
+ if (req == NULL)
+ return -ENOMEM;
- string++;
- }
+ req->type = PIPELINE_MSG_REQ_CUSTOM;
+ req->subtype = PIPELINE_ROUTING_MSG_REQ_SET_MACADDR;
- value = strtol(string, &next, 10);
- if (next == string)
- return -1;
- string = next;
+ memset(req->macaddr, 0, sizeof(req->macaddr));
+ for (port_id = 0; port_id < p->n_pktq_out; port_id++) {
+ struct app_link_params *link;
- labels[count++] = (uint32_t) value;
+ link = app_pipeline_track_pktq_out_to_link(app,
+ pipeline_id,
+ port_id);
+ if (link)
+ req->macaddr[port_id] = link->mac_addr;
}
- *n_labels = count;
- return 0;
-}
-
-/*
- * route add (mpls = no, qinq = no, arp = no)
- */
-
-struct cmd_route_add1_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;
- cmdline_fixed_string_t port_string;
- uint32_t port;
- cmdline_fixed_string_t ether_string;
- struct ether_addr macaddr;
-};
-
-static void
-cmd_route_add1_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_route_add1_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_routing_route_key key;
- struct pipeline_routing_route_data route_data;
- 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;
-
- route_data.flags = 0;
- route_data.port_id = params->port;
- route_data.ethernet.macaddr = params->macaddr;
-
- status = app_pipeline_routing_add_route(app,
- params->p,
- &key,
- &route_data);
+ /* Send request and wait for response */
+ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+ if (rsp == NULL)
+ return -ETIMEDOUT;
- if (status != 0) {
- printf("Command failed\n");
- return;
+ /* Read response and write entry */
+ if (rsp->status) {
+ app_msg_free(app, rsp);
+ return rsp->status;
}
-}
-
-static cmdline_parse_token_string_t cmd_route_add1_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, p_string,
- "p");
-
-static cmdline_parse_token_num_t cmd_route_add1_p =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add1_result, p, UINT32);
-static cmdline_parse_token_string_t cmd_route_add1_route_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, route_string,
- "route");
-
-static cmdline_parse_token_string_t cmd_route_add1_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, add_string,
- "add");
-
-static cmdline_parse_token_ipaddr_t cmd_route_add1_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_route_add1_result, ip);
-
-static cmdline_parse_token_num_t cmd_route_add1_depth =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add1_result, depth, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add1_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, port_string,
- "port");
-
-static cmdline_parse_token_num_t cmd_route_add1_port =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add1_result, port, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add1_ether_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, ether_string,
- "ether");
-
-static cmdline_parse_token_etheraddr_t cmd_route_add1_macaddr =
- TOKEN_ETHERADDR_INITIALIZER(struct cmd_route_add1_result, macaddr);
-
-static cmdline_parse_inst_t cmd_route_add1 = {
- .f = cmd_route_add1_parsed,
- .data = NULL,
- .help_str = "Route add (mpls = no, qinq = no, arp = no)",
- .tokens = {
- (void *)&cmd_route_add1_p_string,
- (void *)&cmd_route_add1_p,
- (void *)&cmd_route_add1_route_string,
- (void *)&cmd_route_add1_add_string,
- (void *)&cmd_route_add1_ip,
- (void *)&cmd_route_add1_depth,
- (void *)&cmd_route_add1_port_string,
- (void *)&cmd_route_add1_port,
- (void *)&cmd_route_add1_ether_string,
- (void *)&cmd_route_add1_macaddr,
- NULL,
- },
-};
-
-/*
- * route add (mpls = no, qinq = no, arp = yes)
- */
-
-struct cmd_route_add2_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;
- cmdline_fixed_string_t port_string;
- uint32_t port;
- cmdline_fixed_string_t ether_string;
- cmdline_ipaddr_t nh_ip;
-};
-
-static void
-cmd_route_add2_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_route_add2_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_routing_route_key key;
- struct pipeline_routing_route_data route_data;
- 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;
-
- route_data.flags = PIPELINE_ROUTING_ROUTE_ARP;
- route_data.port_id = params->port;
- route_data.ethernet.ip =
- rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
-
- status = app_pipeline_routing_add_route(app,
- params->p,
- &key,
- &route_data);
+ /* Free response */
+ app_msg_free(app, rsp);
- if (status != 0) {
- printf("Command failed\n");
- return;
- }
+ return 0;
}
-static cmdline_parse_token_string_t cmd_route_add2_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, p_string,
- "p");
-
-static cmdline_parse_token_num_t cmd_route_add2_p =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add2_result, p, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add2_route_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, route_string,
- "route");
-
-static cmdline_parse_token_string_t cmd_route_add2_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, add_string,
- "add");
-
-static cmdline_parse_token_ipaddr_t cmd_route_add2_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_route_add2_result, ip);
-
-static cmdline_parse_token_num_t cmd_route_add2_depth =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add2_result, depth, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add2_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, port_string,
- "port");
-
-static cmdline_parse_token_num_t cmd_route_add2_port =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add2_result, port, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add2_ether_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, ether_string,
- "ether");
-
-static cmdline_parse_token_ipaddr_t cmd_route_add2_nh_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_route_add2_result, nh_ip);
-
-static cmdline_parse_inst_t cmd_route_add2 = {
- .f = cmd_route_add2_parsed,
- .data = NULL,
- .help_str = "Route add (mpls = no, qinq = no, arp = yes)",
- .tokens = {
- (void *)&cmd_route_add2_p_string,
- (void *)&cmd_route_add2_p,
- (void *)&cmd_route_add2_route_string,
- (void *)&cmd_route_add2_add_string,
- (void *)&cmd_route_add2_ip,
- (void *)&cmd_route_add2_depth,
- (void *)&cmd_route_add2_port_string,
- (void *)&cmd_route_add2_port,
- (void *)&cmd_route_add2_ether_string,
- (void *)&cmd_route_add2_nh_ip,
- NULL,
- },
-};
-
/*
- * route add (mpls = no, qinq = yes, arp = no)
+ * route
+ *
+ * route add (ARP = ON/OFF, MPLS = ON/OFF, QINQ = ON/OFF):
+ * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr>
+ * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr>
+ * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> qinq <svlan> <cvlan>
+ * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> qinq <svlan> <cvlan>
+ * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> mpls <mpls labels>
+ * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> mpls <mpls labels>
+ *
+ * route add default:
+ * p <pipelineid> route add default <portid>
+ *
+ * route del:
+ * p <pipelineid> route del <ipaddr> <depth>
+ *
+ * route del default:
+ * p <pipelineid> route del default
+ *
+ * route ls:
+ * p <pipelineid> route ls
*/
-struct cmd_route_add3_result {
+struct cmd_route_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;
- cmdline_fixed_string_t port_string;
- uint32_t port;
- cmdline_fixed_string_t ether_string;
- struct ether_addr macaddr;
- cmdline_fixed_string_t qinq_string;
- uint32_t svlan;
- uint32_t cvlan;
+ cmdline_multi_string_t multi_string;
};
static void
-cmd_route_add3_parsed(
+cmd_route_parsed(
void *parsed_result,
__rte_unused struct cmdline *cl,
void *data)
{
- struct cmd_route_add3_result *params = parsed_result;
+ struct cmd_route_result *params = parsed_result;
struct app_params *app = data;
- struct pipeline_routing_route_key key;
- struct pipeline_routing_route_data route_data;
- 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;
-
- route_data.flags = PIPELINE_ROUTING_ROUTE_QINQ;
- route_data.port_id = params->port;
- route_data.ethernet.macaddr = params->macaddr;
- route_data.l2.qinq.svlan = params->svlan;
- route_data.l2.qinq.cvlan = params->cvlan;
-
- status = app_pipeline_routing_add_route(app,
- params->p,
- &key,
- &route_data);
-
- if (status != 0) {
- printf("Command failed\n");
- return;
- }
-}
-static cmdline_parse_token_string_t cmd_route_add3_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, p_string,
- "p");
-
-static cmdline_parse_token_num_t cmd_route_add3_p =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, p, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add3_route_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, route_string,
- "route");
-
-static cmdline_parse_token_string_t cmd_route_add3_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, add_string,
- "add");
-
-static cmdline_parse_token_ipaddr_t cmd_route_add3_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_route_add3_result, ip);
-
-static cmdline_parse_token_num_t cmd_route_add3_depth =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, depth, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add3_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, port_string,
- "port");
-
-static cmdline_parse_token_num_t cmd_route_add3_port =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, port, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add3_ether_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, ether_string,
- "ether");
-
-static cmdline_parse_token_etheraddr_t cmd_route_add3_macaddr =
- TOKEN_ETHERADDR_INITIALIZER(struct cmd_route_add3_result, macaddr);
-
-static cmdline_parse_token_string_t cmd_route_add3_qinq_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, qinq_string,
- "qinq");
-
-static cmdline_parse_token_num_t cmd_route_add3_svlan =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, svlan, UINT32);
-
-static cmdline_parse_token_num_t cmd_route_add3_cvlan =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, cvlan, UINT32);
-
-static cmdline_parse_inst_t cmd_route_add3 = {
- .f = cmd_route_add3_parsed,
- .data = NULL,
- .help_str = "Route add (qinq = yes, arp = no)",
- .tokens = {
- (void *)&cmd_route_add3_p_string,
- (void *)&cmd_route_add3_p,
- (void *)&cmd_route_add3_route_string,
- (void *)&cmd_route_add3_add_string,
- (void *)&cmd_route_add3_ip,
- (void *)&cmd_route_add3_depth,
- (void *)&cmd_route_add3_port_string,
- (void *)&cmd_route_add3_port,
- (void *)&cmd_route_add3_ether_string,
- (void *)&cmd_route_add3_macaddr,
- (void *)&cmd_route_add3_qinq_string,
- (void *)&cmd_route_add3_svlan,
- (void *)&cmd_route_add3_cvlan,
- NULL,
- },
-};
-
-/*
- * route add (mpls = no, qinq = yes, arp = yes)
- */
-
-struct cmd_route_add4_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;
- cmdline_fixed_string_t port_string;
- uint32_t port;
- cmdline_fixed_string_t ether_string;
- cmdline_ipaddr_t nh_ip;
- cmdline_fixed_string_t qinq_string;
- uint32_t svlan;
- uint32_t cvlan;
-};
-
-static void
-cmd_route_add4_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_route_add4_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_routing_route_key key;
- struct pipeline_routing_route_data route_data;
+ char *tokens[16];
+ uint32_t n_tokens = RTE_DIM(tokens);
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;
-
- route_data.flags = PIPELINE_ROUTING_ROUTE_QINQ |
- PIPELINE_ROUTING_ROUTE_ARP;
- route_data.port_id = params->port;
- route_data.ethernet.ip =
- rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
- route_data.l2.qinq.svlan = params->svlan;
- route_data.l2.qinq.cvlan = params->cvlan;
-
- status = app_pipeline_routing_add_route(app,
- params->p,
- &key,
- &route_data);
-
+ status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
if (status != 0) {
- printf("Command failed\n");
+ printf(CMD_MSG_TOO_MANY_ARGS, "route");
return;
}
-}
-
-static cmdline_parse_token_string_t cmd_route_add4_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, p_string,
- "p");
-
-static cmdline_parse_token_num_t cmd_route_add4_p =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, p, UINT32);
-static cmdline_parse_token_string_t cmd_route_add4_route_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, route_string,
- "route");
-
-static cmdline_parse_token_string_t cmd_route_add4_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, add_string,
- "add");
-
-static cmdline_parse_token_ipaddr_t cmd_route_add4_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_route_add4_result, ip);
+ /* route add */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ strcmp(tokens[1], "default")) {
+ struct pipeline_routing_route_key key;
+ struct pipeline_routing_route_data route_data;
+ struct in_addr ipv4, nh_ipv4;
+ struct ether_addr mac_addr;
+ uint32_t depth, port_id, svlan, cvlan, i;
+ uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX];
+ uint32_t n_labels = RTE_DIM(mpls_labels);
+
+ memset(&key, 0, sizeof(key));
+ memset(&route_data, 0, sizeof(route_data));
+
+ if (n_tokens < 7) {
+ printf(CMD_MSG_NOT_ENOUGH_ARGS, "route add");
+ return;
+ }
-static cmdline_parse_token_num_t cmd_route_add4_depth =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, depth, UINT32);
+ if (parse_ipv4_addr(tokens[1], &ipv4)) {
+ printf(CMD_MSG_INVALID_ARG, "ipaddr");
+ return;
+ }
-static cmdline_parse_token_string_t cmd_route_add4_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, port_string,
- "port");
+ if (parser_read_uint32(&depth, tokens[2])) {
+ printf(CMD_MSG_INVALID_ARG, "depth");
+ return;
+ }
-static cmdline_parse_token_num_t cmd_route_add4_port =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, port, UINT32);
+ if (strcmp(tokens[3], "port")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
-static cmdline_parse_token_string_t cmd_route_add4_ether_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, ether_string,
- "ether");
+ if (parser_read_uint32(&port_id, tokens[4])) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
-static cmdline_parse_token_ipaddr_t cmd_route_add4_nh_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_route_add4_result, nh_ip);
+ if (strcmp(tokens[5], "ether")) {
+ printf(CMD_MSG_ARG_NOT_FOUND, "ether");
+ return;
+ }
-static cmdline_parse_token_string_t cmd_route_add4_qinq_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, qinq_string,
- "qinq");
+ if (parse_mac_addr(tokens[6], &mac_addr)) {
+ if (parse_ipv4_addr(tokens[6], &nh_ipv4)) {
+ printf(CMD_MSG_INVALID_ARG, "nhmacaddr or nhipaddr");
+ return;
+ }
-static cmdline_parse_token_num_t cmd_route_add4_svlan =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, svlan, UINT32);
+ route_data.flags |= PIPELINE_ROUTING_ROUTE_ARP;
+ }
-static cmdline_parse_token_num_t cmd_route_add4_cvlan =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, cvlan, UINT32);
+ if (n_tokens > 7) {
+ if (strcmp(tokens[7], "mpls") == 0) {
+ if (n_tokens != 9) {
+ printf(CMD_MSG_MISMATCH_ARGS, "route add mpls");
+ return;
+ }
+
+ if (parse_mpls_labels(tokens[8], mpls_labels, &n_labels)) {
+ printf(CMD_MSG_INVALID_ARG, "mpls labels");
+ return;
+ }
+
+ route_data.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
+ } else if (strcmp(tokens[7], "qinq") == 0) {
+ if (n_tokens != 10) {
+ printf(CMD_MSG_MISMATCH_ARGS, "route add qinq");
+ return;
+ }
+
+ if (parser_read_uint32(&svlan, tokens[8])) {
+ printf(CMD_MSG_INVALID_ARG, "svlan");
+ return;
+ }
+ if (parser_read_uint32(&cvlan, tokens[9])) {
+ printf(CMD_MSG_INVALID_ARG, "cvlan");
+ return;
+ }
+
+ route_data.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
+ } else {
+ printf(CMD_MSG_ARG_NOT_FOUND, "mpls or qinq");
+ return;
+ }
+ }
-static cmdline_parse_inst_t cmd_route_add4 = {
- .f = cmd_route_add4_parsed,
- .data = NULL,
- .help_str = "Route add (qinq = yes, arp = yes)",
- .tokens = {
- (void *)&cmd_route_add4_p_string,
- (void *)&cmd_route_add4_p,
- (void *)&cmd_route_add4_route_string,
- (void *)&cmd_route_add4_add_string,
- (void *)&cmd_route_add4_ip,
- (void *)&cmd_route_add4_depth,
- (void *)&cmd_route_add4_port_string,
- (void *)&cmd_route_add4_port,
- (void *)&cmd_route_add4_ether_string,
- (void *)&cmd_route_add4_nh_ip,
- (void *)&cmd_route_add4_qinq_string,
- (void *)&cmd_route_add4_svlan,
- (void *)&cmd_route_add4_cvlan,
- NULL,
- },
-};
+ switch (route_data.flags) {
+ case 0:
+ route_data.port_id = port_id;
+ route_data.ethernet.macaddr = mac_addr;
+ break;
-/*
- * route add (mpls = yes, qinq = no, arp = no)
- */
+ case PIPELINE_ROUTING_ROUTE_ARP:
+ route_data.port_id = port_id;
+ route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
+ break;
-struct cmd_route_add5_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;
- cmdline_fixed_string_t port_string;
- uint32_t port;
- cmdline_fixed_string_t ether_string;
- struct ether_addr macaddr;
- cmdline_fixed_string_t mpls_string;
- cmdline_fixed_string_t mpls_labels;
-};
+ case PIPELINE_ROUTING_ROUTE_MPLS:
+ route_data.port_id = port_id;
+ route_data.ethernet.macaddr = mac_addr;
+ for (i = 0; i < n_labels; i++)
+ route_data.l2.mpls.labels[i] = mpls_labels[i];
+ route_data.l2.mpls.n_labels = n_labels;
+ break;
-static void
-cmd_route_add5_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_route_add5_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_routing_route_key key;
- struct pipeline_routing_route_data route_data;
- uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX];
- uint32_t n_labels = RTE_DIM(mpls_labels);
- uint32_t i;
- int status;
+ case PIPELINE_ROUTING_ROUTE_MPLS | PIPELINE_ROUTING_ROUTE_ARP:
+ route_data.port_id = port_id;
+ route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
+ for (i = 0; i < n_labels; i++)
+ route_data.l2.mpls.labels[i] = mpls_labels[i];
+ route_data.l2.mpls.n_labels = n_labels;
+ break;
- /* Parse MPLS labels */
- status = parse_labels(params->mpls_labels, mpls_labels, &n_labels);
- if (status) {
- printf("MPLS labels parse error\n");
- return;
- }
+ case PIPELINE_ROUTING_ROUTE_QINQ:
+ route_data.port_id = port_id;
+ route_data.ethernet.macaddr = mac_addr;
+ route_data.l2.qinq.svlan = svlan;
+ route_data.l2.qinq.cvlan = cvlan;
+ break;
- /* 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;
+ case PIPELINE_ROUTING_ROUTE_QINQ | PIPELINE_ROUTING_ROUTE_ARP:
+ default:
+ route_data.port_id = port_id;
+ route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
+ route_data.l2.qinq.svlan = svlan;
+ route_data.l2.qinq.cvlan = cvlan;
+ break;
+ }
- route_data.flags = PIPELINE_ROUTING_ROUTE_MPLS;
- route_data.port_id = params->port;
- route_data.ethernet.macaddr = params->macaddr;
- for (i = 0; i < n_labels; i++)
- route_data.l2.mpls.labels[i] = mpls_labels[i];
- route_data.l2.mpls.n_labels = n_labels;
+ key.type = PIPELINE_ROUTING_ROUTE_IPV4;
+ key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
+ key.key.ipv4.depth = depth;
- status = app_pipeline_routing_add_route(app,
- params->p,
- &key,
- &route_data);
+ status = app_pipeline_routing_add_route(app,
+ params->p,
+ &key,
+ &route_data);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "route add");
- if (status != 0) {
- printf("Command failed\n");
return;
- }
-}
-
-static cmdline_parse_token_string_t cmd_route_add5_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, p_string,
- "p");
-
-static cmdline_parse_token_num_t cmd_route_add5_p =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add5_result, p, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add5_route_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, route_string,
- "route");
-
-static cmdline_parse_token_string_t cmd_route_add5_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, add_string,
- "add");
-
-static cmdline_parse_token_ipaddr_t cmd_route_add5_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_route_add5_result, ip);
+ } /* route add */
-static cmdline_parse_token_num_t cmd_route_add5_depth =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add5_result, depth, UINT32);
+ /* route add default */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "default") == 0)) {
+ uint32_t port_id;
-static cmdline_parse_token_string_t cmd_route_add5_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, port_string,
- "port");
-
-static cmdline_parse_token_num_t cmd_route_add5_port =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add5_result, port, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add5_ether_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, ether_string,
- "ether");
-
-static cmdline_parse_token_etheraddr_t cmd_route_add5_macaddr =
- TOKEN_ETHERADDR_INITIALIZER(struct cmd_route_add5_result, macaddr);
-
-static cmdline_parse_token_string_t cmd_route_add5_mpls_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, mpls_string,
- "mpls");
-
-static cmdline_parse_token_string_t cmd_route_add5_mpls_labels =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, mpls_labels,
- NULL);
-
-static cmdline_parse_inst_t cmd_route_add5 = {
- .f = cmd_route_add5_parsed,
- .data = NULL,
- .help_str = "Route add (mpls = yes, arp = no)",
- .tokens = {
- (void *)&cmd_route_add5_p_string,
- (void *)&cmd_route_add5_p,
- (void *)&cmd_route_add5_route_string,
- (void *)&cmd_route_add5_add_string,
- (void *)&cmd_route_add5_ip,
- (void *)&cmd_route_add5_depth,
- (void *)&cmd_route_add5_port_string,
- (void *)&cmd_route_add5_port,
- (void *)&cmd_route_add5_ether_string,
- (void *)&cmd_route_add5_macaddr,
- (void *)&cmd_route_add5_mpls_string,
- (void *)&cmd_route_add5_mpls_labels,
- NULL,
- },
-};
-
-/*
- * route add (mpls = yes, qinq = no, arp = yes)
- */
-
-struct cmd_route_add6_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;
- cmdline_fixed_string_t port_string;
- uint32_t port;
- cmdline_fixed_string_t ether_string;
- cmdline_ipaddr_t nh_ip;
- cmdline_fixed_string_t mpls_string;
- cmdline_fixed_string_t mpls_labels;
-};
-
-static void
-cmd_route_add6_parsed(
- void *parsed_result,
- __rte_unused struct cmdline *cl,
- void *data)
-{
- struct cmd_route_add6_result *params = parsed_result;
- struct app_params *app = data;
- struct pipeline_routing_route_key key;
- struct pipeline_routing_route_data route_data;
- uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX];
- uint32_t n_labels = RTE_DIM(mpls_labels);
- uint32_t i;
- int status;
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "route add default");
+ return;
+ }
- /* Parse MPLS labels */
- status = parse_labels(params->mpls_labels, mpls_labels, &n_labels);
- if (status) {
- printf("MPLS labels parse error\n");
- return;
- }
+ if (parser_read_uint32(&port_id, tokens[2])) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
- /* 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;
-
- route_data.flags = PIPELINE_ROUTING_ROUTE_MPLS |
- PIPELINE_ROUTING_ROUTE_ARP;
- route_data.port_id = params->port;
- route_data.ethernet.ip =
- rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
- for (i = 0; i < n_labels; i++)
- route_data.l2.mpls.labels[i] = mpls_labels[i];
- route_data.l2.mpls.n_labels = n_labels;
-
- status = app_pipeline_routing_add_route(app,
- params->p,
- &key,
- &route_data);
+ status = app_pipeline_routing_add_default_route(app,
+ params->p,
+ port_id);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "route add default");
- if (status != 0) {
- printf("Command failed\n");
return;
- }
-}
-
-static cmdline_parse_token_string_t cmd_route_add6_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, p_string,
- "p");
-
-static cmdline_parse_token_num_t cmd_route_add6_p =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add6_result, p, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add6_route_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, route_string,
- "route");
-
-static cmdline_parse_token_string_t cmd_route_add6_add_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, add_string,
- "add");
-
-static cmdline_parse_token_ipaddr_t cmd_route_add6_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_route_add6_result, ip);
-
-static cmdline_parse_token_num_t cmd_route_add6_depth =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add6_result, depth, UINT32);
-
-static cmdline_parse_token_string_t cmd_route_add6_port_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, port_string,
- "port");
+ } /* route add default */
-static cmdline_parse_token_num_t cmd_route_add6_port =
- TOKEN_NUM_INITIALIZER(struct cmd_route_add6_result, port, UINT32);
+ /* route del*/
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ strcmp(tokens[1], "default")) {
+ struct pipeline_routing_route_key key;
+ struct in_addr ipv4;
+ uint32_t depth;
-static cmdline_parse_token_string_t cmd_route_add6_ether_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, ether_string,
- "ether");
-
-static cmdline_parse_token_ipaddr_t cmd_route_add6_nh_ip =
- TOKEN_IPV4_INITIALIZER(struct cmd_route_add6_result, nh_ip);
-
-static cmdline_parse_token_string_t cmd_route_add6_mpls_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, mpls_string,
- "mpls");
-
-static cmdline_parse_token_string_t cmd_route_add6_mpls_labels =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, mpls_labels,
- NULL);
-
-static cmdline_parse_inst_t cmd_route_add6 = {
- .f = cmd_route_add6_parsed,
- .data = NULL,
- .help_str = "Route add (mpls = yes, arp = yes)",
- .tokens = {
- (void *)&cmd_route_add6_p_string,
- (void *)&cmd_route_add6_p,
- (void *)&cmd_route_add6_route_string,
- (void *)&cmd_route_add6_add_string,
- (void *)&cmd_route_add6_ip,
- (void *)&cmd_route_add6_depth,
- (void *)&cmd_route_add6_port_string,
- (void *)&cmd_route_add6_port,
- (void *)&cmd_route_add6_ether_string,
- (void *)&cmd_route_add6_nh_ip,
- (void *)&cmd_route_add6_mpls_string,
- (void *)&cmd_route_add6_mpls_labels,
- NULL,
- },
-};
+ memset(&key, 0, sizeof(key));
-/*
- * 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;
-};
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "route del");
+ return;
+ }
-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;
+ if (parse_ipv4_addr(tokens[1], &ipv4)) {
+ printf(CMD_MSG_INVALID_ARG, "ipaddr");
+ return;
+ }
- int status;
+ if (parser_read_uint32(&depth, tokens[2])) {
+ printf(CMD_MSG_INVALID_ARG, "depth");
+ return;
+ }
- /* 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;
+ key.type = PIPELINE_ROUTING_ROUTE_IPV4;
+ key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
+ key.key.ipv4.depth = depth;
- status = app_pipeline_routing_delete_route(app, params->p, &key);
+ status = app_pipeline_routing_delete_route(app, params->p, &key);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "route del");
- if (status != 0) {
- printf("Command failed\n");
return;
- }
-}
-
-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 cmd_route_add_default_result *params = parsed_result;
- struct app_params *app = data;
- int status;
+ } /* route del */
+
+ /* route del default */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ (strcmp(tokens[1], "default") == 0)) {
+ if (n_tokens != 2) {
+ printf(CMD_MSG_MISMATCH_ARGS, "route del default");
+ return;
+ }
- status = app_pipeline_routing_add_default_route(app, params->p,
- params->port);
+ status = app_pipeline_routing_delete_default_route(app,
+ params->p);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "route del default");
- if (status != 0) {
- printf("Command failed\n");
return;
- }
-}
-
-static cmdline_parse_token_string_t cmd_route_add_default_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, p_string,
- "p");
+ } /* route del default */
-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;
+ /* route ls */
+ if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
+ if (n_tokens != 1) {
+ printf(CMD_MSG_MISMATCH_ARGS, "route ls");
+ return;
+ }
- status = app_pipeline_routing_delete_default_route(app, params->p);
+ status = app_pipeline_routing_route_ls(app, params->p);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "route ls");
- if (status != 0) {
- printf("Command failed\n");
return;
- }
-}
-
-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,
- },
-};
-
-/*
- * route ls
- */
-
-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;
-};
-
-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;
-
- status = app_pipeline_routing_route_ls(app, params->p);
+ } /* route ls */
- if (status != 0) {
- printf("Command failed\n");
- return;
- }
+ printf(CMD_MSG_MISMATCH_ARGS, "route");
}
-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_string_t cmd_route_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_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_num_t cmd_route_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_route_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_route_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_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_token_string_t cmd_route_multi_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_route_result, multi_string,
+ TOKEN_STRING_MULTI);
-static cmdline_parse_inst_t cmd_route_ls = {
- .f = cmd_route_ls_parsed,
+static cmdline_parse_inst_t cmd_route = {
+ .f = cmd_route_parsed,
.data = NULL,
- .help_str = "Route list",
+ .help_str = "route add / add default / del / del default / ls",
.tokens = {
- (void *)&cmd_route_ls_p_string,
- (void *)&cmd_route_ls_p,
- (void *)&cmd_route_ls_route_string,
- (void *)&cmd_route_ls_ls_string,
+ (void *)&cmd_route_p_string,
+ (void *)&cmd_route_p,
+ (void *)&cmd_route_route_string,
+ (void *)&cmd_route_multi_string,
NULL,
},
};
/*
- * arp add
+ * arp
+ *
+ * arp add:
+ * p <pipelineid> arp add <portid> <ipaddr> <macaddr>
+ *
+ * arp add default:
+ * p <pipelineid> arp add default <portid>
+ *
+ * arp del:
+ * p <pipelineid> arp del <portid> <ipaddr>
+ *
+ * arp del default:
+ * p <pipelineid> arp del default
+ *
+ * arp ls:
+ * p <pipelineid> arp ls
*/
-struct cmd_arp_add_result {
+struct cmd_arp_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;
-
+ cmdline_multi_string_t multi_string;
};
static void
-cmd_arp_add_parsed(
+cmd_arp_parsed(
void *parsed_result,
__rte_unused struct cmdline *cl,
void *data)
{
- struct cmd_arp_add_result *params = parsed_result;
+ struct cmd_arp_result *params = parsed_result;
struct app_params *app = data;
- struct pipeline_routing_arp_key key;
+ char *tokens[16];
+ uint32_t n_tokens = RTE_DIM(tokens);
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,
- &params->macaddr);
-
+ status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
if (status != 0) {
- printf("Command failed\n");
+ printf(CMD_MSG_TOO_MANY_ARGS, "arp");
return;
}
-}
-
-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");
+ /* arp add */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ strcmp(tokens[1], "default")) {
+ struct pipeline_routing_arp_key key;
+ struct in_addr ipv4;
+ struct ether_addr mac_addr;
+ uint32_t port_id;
-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,
- },
-};
+ memset(&key, 0, sizeof(key));
-/*
- * arp del
- */
+ if (n_tokens != 4) {
+ printf(CMD_MSG_MISMATCH_ARGS, "arp add");
+ return;
+ }
-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;
-};
+ if (parser_read_uint32(&port_id, tokens[1])) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
-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;
+ if (parse_ipv4_addr(tokens[2], &ipv4)) {
+ printf(CMD_MSG_INVALID_ARG, "ipaddr");
+ return;
+ }
- struct pipeline_routing_arp_key key;
- int status;
+ if (parse_mac_addr(tokens[3], &mac_addr)) {
+ printf(CMD_MSG_INVALID_ARG, "macaddr");
+ return;
+ }
- 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;
+ key.type = PIPELINE_ROUTING_ARP_IPV4;
+ key.key.ipv4.port_id = port_id;
+ key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
- status = app_pipeline_routing_delete_arp_entry(app, params->p, &key);
+ status = app_pipeline_routing_add_arp_entry(app,
+ params->p,
+ &key,
+ &mac_addr);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "arp add");
- if (status != 0) {
- printf("Command failed\n");
return;
- }
-}
-
-static cmdline_parse_token_string_t cmd_arp_del_p_string =
- TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, p_string,
- "p");
+ } /* arp add */
-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,
- },
-};
-
-/*
- * arp add default
- */
-
-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;
-};
+ /* arp add default */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "add") == 0) &&
+ (strcmp(tokens[1], "default") == 0)) {
+ 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;
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "arp add default");
+ return;
+ }
- int status;
+ if (parser_read_uint32(&port_id, tokens[2])) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
- status = app_pipeline_routing_add_default_arp_entry(app,
- params->p,
- params->port_id);
+ status = app_pipeline_routing_add_default_arp_entry(app,
+ params->p,
+ port_id);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "arp add default");
- 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");
+ } /* arp add default */
-static cmdline_parse_token_string_t cmd_arp_add_default_default_string =
- TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result,
- default_string, "default");
+ /* arp del*/
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ strcmp(tokens[1], "default")) {
+ struct pipeline_routing_arp_key key;
+ struct in_addr ipv4;
+ uint32_t port_id;
-static cmdline_parse_token_num_t cmd_arp_add_default_port_id =
- TOKEN_NUM_INITIALIZER(struct cmd_arp_add_default_result, port_id,
- UINT32);
+ memset(&key, 0, sizeof(key));
-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,
- },
-};
-
-/*
- * arp del default
- */
+ if (n_tokens != 3) {
+ printf(CMD_MSG_MISMATCH_ARGS, "arp del");
+ return;
+ }
-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;
-};
+ if (parser_read_uint32(&port_id, tokens[1])) {
+ printf(CMD_MSG_INVALID_ARG, "portid");
+ return;
+ }
-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;
+ if (parse_ipv4_addr(tokens[2], &ipv4)) {
+ printf(CMD_MSG_INVALID_ARG, "ipaddr");
+ return;
+ }
- int status;
+ key.type = PIPELINE_ROUTING_ARP_IPV4;
+ key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
+ key.key.ipv4.port_id = port_id;
- status = app_pipeline_routing_delete_default_arp_entry(app, params->p);
+ status = app_pipeline_routing_delete_arp_entry(app,
+ params->p,
+ &key);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "arp del");
- 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 del */
+
+ /* arp del default */
+ if ((n_tokens >= 2) &&
+ (strcmp(tokens[0], "del") == 0) &&
+ (strcmp(tokens[1], "default") == 0)) {
+ if (n_tokens != 2) {
+ printf(CMD_MSG_MISMATCH_ARGS, "arp del default");
+ return;
+ }
+
+ status = app_pipeline_routing_delete_default_arp_entry(app,
+ params->p);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "arp del default");
+
+ return;
+ } /* arp del default */
+
+ /* arp ls */
+ if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
+ if (n_tokens != 1) {
+ printf(CMD_MSG_MISMATCH_ARGS, "arp ls");
+ return;
+ }
-/*
- * arp ls
- */
+ status = app_pipeline_routing_arp_ls(app, params->p);
+ if (status != 0)
+ printf(CMD_MSG_FAIL, "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;
-
- p = app_pipeline_data_fe(app, params->p, &pipeline_routing);
- if (p == NULL)
return;
+ } /* arp ls */
- app_pipeline_routing_arp_ls(app, params->p);
+ printf(CMD_MSG_FAIL, "arp");
}
-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_string_t cmd_arp_p_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_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_num_t cmd_arp_p =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_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_arp_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_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_token_string_t cmd_arp_multi_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_result, multi_string,
+ TOKEN_STRING_MULTI);
-static cmdline_parse_inst_t cmd_arp_ls = {
- .f = cmd_arp_ls_parsed,
+static cmdline_parse_inst_t cmd_arp = {
+ .f = cmd_arp_parsed,
.data = NULL,
- .help_str = "ARP list",
+ .help_str = "arp add / add default / del / del default / ls",
.tokens = {
- (void *)&cmd_arp_ls_p_string,
- (void *)&cmd_arp_ls_p,
- (void *)&cmd_arp_ls_arp_string,
- (void *)&cmd_arp_ls_ls_string,
+ (void *)&cmd_arp_p_string,
+ (void *)&cmd_arp_p,
+ (void *)&cmd_arp_arp_string,
+ (void *)&cmd_arp_multi_string,
NULL,
},
};
static cmdline_parse_ctx_t pipeline_cmds[] = {
- (cmdline_parse_inst_t *)&cmd_route_add1,
- (cmdline_parse_inst_t *)&cmd_route_add2,
- (cmdline_parse_inst_t *)&cmd_route_add3,
- (cmdline_parse_inst_t *)&cmd_route_add4,
- (cmdline_parse_inst_t *)&cmd_route_add5,
- (cmdline_parse_inst_t *)&cmd_route_add6,
- (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,
+ (cmdline_parse_inst_t *)&cmd_route,
+ (cmdline_parse_inst_t *)&cmd_arp,
NULL,
};
static struct pipeline_fe_ops pipeline_routing_fe_ops = {
- .f_init = pipeline_routing_init,
+ .f_init = app_pipeline_routing_init,
+ .f_post_init = app_pipeline_routing_post_init,
.f_free = app_pipeline_routing_free,
+ .f_track = app_pipeline_track_default,
.cmds = pipeline_cmds,
};
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.h b/examples/ip_pipeline/pipeline/pipeline_routing.h
index fa41642b..0197449b 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing.h
+++ b/examples/ip_pipeline/pipeline/pipeline_routing.h
@@ -86,6 +86,13 @@ app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
uint32_t pipeline_id);
/*
+ * SETTINGS
+ */
+int
+app_pipeline_routing_set_macaddr(struct app_params *app,
+ uint32_t pipeline_id);
+
+/*
* Pipeline type
*/
extern struct pipeline_type pipeline_routing;
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.c b/examples/ip_pipeline/pipeline/pipeline_routing_be.c
index bc5bf7a5..21ac7888 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.c
@@ -65,7 +65,9 @@
((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32))
-#define MAC_SRC_DEFAULT 0x112233445566ULL
+/* Network Byte Order (NBO) */
+#define SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr, ethertype) \
+ (((uint64_t) macaddr) | (((uint64_t) rte_cpu_to_be_16(ethertype)) << 48))
#ifndef PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s
#define PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s 256
@@ -75,6 +77,7 @@ struct pipeline_routing {
struct pipeline p;
struct pipeline_routing_params params;
pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS];
+ uint64_t macaddr[PIPELINE_MAX_PORT_OUT];
} __rte_cache_aligned;
/*
@@ -132,6 +135,10 @@ static void *
pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p,
void *msg);
+static void *
+pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p,
+ void *msg);
+
static pipeline_msg_req_handler custom_handlers[] = {
[PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] =
pipeline_routing_msg_req_route_add_handler,
@@ -149,6 +156,8 @@ static pipeline_msg_req_handler custom_handlers[] = {
pipeline_routing_msg_req_arp_add_default_handler,
[PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] =
pipeline_routing_msg_req_arp_del_default_handler,
+ [PIPELINE_ROUTING_MSG_REQ_SET_MACADDR] =
+ pipeline_routing_msg_req_set_macaddr_handler,
};
/*
@@ -921,6 +930,7 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p,
struct pipeline_params *params)
{
uint32_t n_routes_present = 0;
+ uint32_t port_local_dest_present = 0;
uint32_t encap_present = 0;
uint32_t qinq_sched_present = 0;
uint32_t mpls_color_mark_present = 0;
@@ -933,6 +943,7 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p,
/* default values */
p->n_routes = PIPELINE_ROUTING_N_ROUTES_DEFAULT;
+ p->port_local_dest = params->n_ports_out - 1;
p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET;
p->qinq_sched = 0;
p->mpls_color_mark = 0;
@@ -962,6 +973,23 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p,
continue;
}
+ /* port_local_dest */
+ if (strcmp(arg_name, "port_local_dest") == 0) {
+ int status;
+
+ PIPELINE_PARSE_ERR_DUPLICATE(
+ port_local_dest_present == 0, params->name,
+ arg_name);
+ port_local_dest_present = 1;
+
+ status = parser_read_uint32(&p->port_local_dest,
+ arg_value);
+ PIPELINE_PARSE_ERR_INV_VAL(((status == 0) &&
+ (p->port_local_dest < params->n_ports_out)),
+ params->name, arg_name, arg_value);
+
+ continue;
+ }
/* encap */
if (strcmp(arg_name, "encap") == 0) {
@@ -1419,27 +1447,6 @@ pipeline_routing_free(void *pipeline)
}
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;
@@ -1534,7 +1541,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
/* Ether - ARP off */
if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
(p_rt->params.n_arp_entries == 0)) {
- uint64_t macaddr_src = MAC_SRC_DEFAULT;
+ uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
uint64_t macaddr_dst;
uint64_t ethertype = ETHER_TYPE_IPv4;
@@ -1542,7 +1549,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
macaddr_dst = rte_bswap64(macaddr_dst << 16);
entry_arp0.slab[0] =
- rte_bswap64((macaddr_src << 16) | ethertype);
+ SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype);
entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
entry_arp0.slab[1] = rte_bswap64(macaddr_dst);
@@ -1556,11 +1563,11 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
/* Ether - ARP on */
if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
p_rt->params.n_arp_entries) {
- uint64_t macaddr_src = MAC_SRC_DEFAULT;
+ uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
uint64_t ethertype = ETHER_TYPE_IPv4;
- entry_arp1.slab[0] = rte_bswap64((macaddr_src << 16) |
- ethertype);
+ entry_arp1.slab[0] =
+ SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype);
entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
entry_arp1.data_offset = entry_arp1.slab_offset[0] - 6
@@ -1571,7 +1578,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
/* Ether QinQ - ARP off */
if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
(p_rt->params.n_arp_entries == 0)) {
- uint64_t macaddr_src = MAC_SRC_DEFAULT;
+ uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
uint64_t macaddr_dst;
uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
uint64_t ethertype_vlan = 0x8100;
@@ -1588,8 +1595,8 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
ethertype_ipv4);
entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
- entry_arp0.slab[1] = rte_bswap64((macaddr_src << 16) |
- ethertype_qinq);
+ entry_arp0.slab[1] =
+ SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_qinq);
entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
entry_arp0.slab[2] = rte_bswap64(macaddr_dst);
@@ -1603,7 +1610,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
/* Ether QinQ - ARP on */
if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
p_rt->params.n_arp_entries) {
- uint64_t macaddr_src = MAC_SRC_DEFAULT;
+ uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
uint64_t ethertype_vlan = 0x8100;
uint64_t ethertype_qinq = 0x9100;
@@ -1616,8 +1623,8 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
ethertype_ipv4);
entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
- entry_arp1.slab[1] = rte_bswap64((macaddr_src << 16) |
- ethertype_qinq);
+ entry_arp1.slab[1] =
+ SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_qinq);
entry_arp1.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
entry_arp1.data_offset = entry_arp1.slab_offset[1] - 6
@@ -1628,7 +1635,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
/* Ether MPLS - ARP off */
if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
(p_rt->params.n_arp_entries == 0)) {
- uint64_t macaddr_src = MAC_SRC_DEFAULT;
+ uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
uint64_t macaddr_dst;
uint64_t ethertype_mpls = 0x8847;
@@ -1697,8 +1704,8 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
return rsp;
}
- entry_arp0.slab[2] = rte_bswap64((macaddr_src << 16) |
- ethertype_mpls);
+ entry_arp0.slab[2] =
+ SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_mpls);
entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset -
(n_labels * 4 + 8);
@@ -1714,7 +1721,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
/* Ether MPLS - ARP on */
if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
p_rt->params.n_arp_entries) {
- uint64_t macaddr_src = MAC_SRC_DEFAULT;
+ uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
uint64_t ethertype_mpls = 0x8847;
uint64_t label0 = req->data.l2.mpls.labels[0];
@@ -1779,8 +1786,8 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
return rsp;
}
- entry_arp1.slab[2] = rte_bswap64((macaddr_src << 16) |
- ethertype_mpls);
+ entry_arp1.slab[2] =
+ SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_mpls);
entry_arp1.slab_offset[2] = p_rt->params.ip_hdr_offset -
(n_labels * 4 + 8);
@@ -1961,10 +1968,25 @@ pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg)
return rsp;
}
+void *
+pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p, void *msg)
+{
+ struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
+ struct pipeline_routing_set_macaddr_msg_req *req = msg;
+ struct pipeline_routing_set_macaddr_msg_rsp *rsp = msg;
+ uint32_t port_id;
+
+ for (port_id = 0; port_id < p->n_ports_out; port_id++)
+ p_rt->macaddr[port_id] = req->macaddr[port_id];
+
+ rsp->status = 0;
+
+ return rsp;
+}
+
struct pipeline_be_ops pipeline_routing_be_ops = {
.f_init = pipeline_routing_init,
.f_free = pipeline_routing_free,
.f_run = NULL,
.f_timer = pipeline_routing_timer,
- .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
index ec767b24..12763427 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing_be.h
+++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.h
@@ -54,6 +54,7 @@ enum pipeline_routing_encap {
struct pipeline_routing_params {
/* routing */
uint32_t n_routes;
+ uint32_t port_local_dest;
/* routing packet encapsulation */
enum pipeline_routing_encap encap;
@@ -160,6 +161,7 @@ enum pipeline_routing_msg_req_type {
PIPELINE_ROUTING_MSG_REQ_ARP_DEL,
PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT,
PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT,
+ PIPELINE_ROUTING_MSG_REQ_SET_MACADDR,
PIPELINE_ROUTING_MSG_REQS
};
@@ -291,6 +293,20 @@ struct pipeline_routing_arp_delete_default_msg_rsp {
int status;
};
+/*
+ * MSG SET MACADDR
+ */
+struct pipeline_routing_set_macaddr_msg_req {
+ enum pipeline_msg_req_type type;
+ enum pipeline_routing_msg_req_type subtype;
+
+ uint64_t macaddr[PIPELINE_MAX_PORT_OUT];
+};
+
+struct pipeline_routing_set_macaddr_msg_rsp {
+ int status;
+};
+
extern struct pipeline_be_ops pipeline_routing_be_ops;
#endif
diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h
index f4ff262e..b562472b 100644
--- a/examples/ip_pipeline/pipeline_be.h
+++ b/examples/ip_pipeline/pipeline_be.h
@@ -40,6 +40,9 @@
#include <rte_port_ras.h>
#include <rte_port_sched.h>
#include <rte_port_source_sink.h>
+#ifdef RTE_LIBRTE_KNI
+#include <rte_port_kni.h>
+#endif
#include <rte_pipeline.h>
enum pipeline_port_in_type {
@@ -49,6 +52,7 @@ enum pipeline_port_in_type {
PIPELINE_PORT_IN_RING_READER_IPV4_FRAG,
PIPELINE_PORT_IN_RING_READER_IPV6_FRAG,
PIPELINE_PORT_IN_SCHED_READER,
+ PIPELINE_PORT_IN_KNI_READER,
PIPELINE_PORT_IN_SOURCE,
};
@@ -61,6 +65,9 @@ struct pipeline_port_in_params {
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;
+#ifdef RTE_LIBRTE_KNI
+ struct rte_port_kni_reader_params kni;
+#endif
struct rte_port_source_params source;
} params;
uint32_t burst_size;
@@ -82,6 +89,10 @@ pipeline_port_in_params_convert(struct pipeline_port_in_params *p)
return (void *) &p->params.ring_ipv6_frag;
case PIPELINE_PORT_IN_SCHED_READER:
return (void *) &p->params.sched;
+#ifdef RTE_LIBRTE_KNI
+ case PIPELINE_PORT_IN_KNI_READER:
+ return (void *) &p->params.kni;
+#endif
case PIPELINE_PORT_IN_SOURCE:
return (void *) &p->params.source;
default:
@@ -105,6 +116,10 @@ pipeline_port_in_params_get_ops(struct pipeline_port_in_params *p)
return &rte_port_ring_reader_ipv6_frag_ops;
case PIPELINE_PORT_IN_SCHED_READER:
return &rte_port_sched_reader_ops;
+#ifdef RTE_LIBRTE_KNI
+ case PIPELINE_PORT_IN_KNI_READER:
+ return &rte_port_kni_reader_ops;
+#endif
case PIPELINE_PORT_IN_SOURCE:
return &rte_port_source_ops;
default:
@@ -122,6 +137,8 @@ enum pipeline_port_out_type {
PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS,
PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS,
PIPELINE_PORT_OUT_SCHED_WRITER,
+ PIPELINE_PORT_OUT_KNI_WRITER,
+ PIPELINE_PORT_OUT_KNI_WRITER_NODROP,
PIPELINE_PORT_OUT_SINK,
};
@@ -137,6 +154,10 @@ struct pipeline_port_out_params {
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;
+#ifdef RTE_LIBRTE_KNI
+ struct rte_port_kni_writer_params kni;
+ struct rte_port_kni_writer_nodrop_params kni_nodrop;
+#endif
struct rte_port_sink_params sink;
} params;
};
@@ -163,6 +184,12 @@ pipeline_port_out_params_convert(struct pipeline_port_out_params *p)
return (void *) &p->params.ring_ipv6_ras;
case PIPELINE_PORT_OUT_SCHED_WRITER:
return (void *) &p->params.sched;
+#ifdef RTE_LIBRTE_KNI
+ case PIPELINE_PORT_OUT_KNI_WRITER:
+ return (void *) &p->params.kni;
+ case PIPELINE_PORT_OUT_KNI_WRITER_NODROP:
+ return (void *) &p->params.kni_nodrop;
+#endif
case PIPELINE_PORT_OUT_SINK:
return (void *) &p->params.sink;
default:
@@ -192,6 +219,12 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p)
return &rte_port_ring_writer_ipv6_ras_ops;
case PIPELINE_PORT_OUT_SCHED_WRITER:
return &rte_port_sched_writer_ops;
+#ifdef RTE_LIBRTE_KNI
+ case PIPELINE_PORT_OUT_KNI_WRITER:
+ return &rte_port_kni_writer_ops;
+ case PIPELINE_PORT_OUT_KNI_WRITER_NODROP:
+ return &rte_port_kni_writer_nodrop_ops;
+#endif
case PIPELINE_PORT_OUT_SINK:
return &rte_port_sink_ops;
default:
@@ -200,15 +233,19 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p)
}
#ifndef PIPELINE_NAME_SIZE
-#define PIPELINE_NAME_SIZE 32
+#define PIPELINE_NAME_SIZE 64
+#endif
+
+#ifndef PIPELINE_TYPE_SIZE
+#define PIPELINE_TYPE_SIZE 64
#endif
#ifndef PIPELINE_MAX_PORT_IN
-#define PIPELINE_MAX_PORT_IN 16
+#define PIPELINE_MAX_PORT_IN 64
#endif
#ifndef PIPELINE_MAX_PORT_OUT
-#define PIPELINE_MAX_PORT_OUT 16
+#define PIPELINE_MAX_PORT_OUT 64
#endif
#ifndef PIPELINE_MAX_TABLES
@@ -224,11 +261,12 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p)
#endif
#ifndef PIPELINE_MAX_ARGS
-#define PIPELINE_MAX_ARGS 32
+#define PIPELINE_MAX_ARGS 64
#endif
struct pipeline_params {
char name[PIPELINE_NAME_SIZE];
+ char type[PIPELINE_TYPE_SIZE];
struct pipeline_port_in_params port_in[PIPELINE_MAX_PORT_IN];
struct pipeline_port_out_params port_out[PIPELINE_MAX_PORT_OUT];
@@ -261,16 +299,11 @@ 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;
};
/* Pipeline specific config parse error messages */
diff --git a/examples/ip_pipeline/thread_fe.c b/examples/ip_pipeline/thread_fe.c
index 4a435f7c..6c547ca5 100644
--- a/examples/ip_pipeline/thread_fe.c
+++ b/examples/ip_pipeline/thread_fe.c
@@ -5,10 +5,6 @@
#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 "thread.h"
#include "thread_fe.h"
@@ -85,6 +81,9 @@ app_pipeline_enable(struct app_params *app,
p_params = &app->pipeline_params[pipeline_id];
p_type = app_pipeline_type_find(app, p_params->type);
+ if (p_type == NULL)
+ return -1;
+
if (p->enabled == 1)
return -1;
@@ -259,26 +258,26 @@ cmd_pipeline_enable_parsed(
printf("Command failed\n");
}
-cmdline_parse_token_string_t cmd_pipeline_enable_t_string =
+static cmdline_parse_token_string_t cmd_pipeline_enable_t_string =
TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_string, "t");
-cmdline_parse_token_string_t cmd_pipeline_enable_t_id_string =
+static cmdline_parse_token_string_t cmd_pipeline_enable_t_id_string =
TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_id_string,
NULL);
-cmdline_parse_token_string_t cmd_pipeline_enable_pipeline_string =
+static cmdline_parse_token_string_t cmd_pipeline_enable_pipeline_string =
TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_string,
"pipeline");
-cmdline_parse_token_num_t cmd_pipeline_enable_pipeline_id =
+static cmdline_parse_token_num_t cmd_pipeline_enable_pipeline_id =
TOKEN_NUM_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_id,
UINT32);
-cmdline_parse_token_string_t cmd_pipeline_enable_enable_string =
+static cmdline_parse_token_string_t cmd_pipeline_enable_enable_string =
TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, enable_string,
"enable");
-cmdline_parse_inst_t cmd_pipeline_enable = {
+static cmdline_parse_inst_t cmd_pipeline_enable = {
.f = cmd_pipeline_enable_parsed,
.data = NULL,
.help_str = "Enable pipeline on specified core",
@@ -333,26 +332,26 @@ cmd_pipeline_disable_parsed(
printf("Command failed\n");
}
-cmdline_parse_token_string_t cmd_pipeline_disable_t_string =
+static cmdline_parse_token_string_t cmd_pipeline_disable_t_string =
TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_string, "t");
-cmdline_parse_token_string_t cmd_pipeline_disable_t_id_string =
+static cmdline_parse_token_string_t cmd_pipeline_disable_t_id_string =
TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_id_string,
NULL);
-cmdline_parse_token_string_t cmd_pipeline_disable_pipeline_string =
+static cmdline_parse_token_string_t cmd_pipeline_disable_pipeline_string =
TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result,
pipeline_string, "pipeline");
-cmdline_parse_token_num_t cmd_pipeline_disable_pipeline_id =
+static cmdline_parse_token_num_t cmd_pipeline_disable_pipeline_id =
TOKEN_NUM_INITIALIZER(struct cmd_pipeline_disable_result, pipeline_id,
UINT32);
-cmdline_parse_token_string_t cmd_pipeline_disable_disable_string =
+static cmdline_parse_token_string_t cmd_pipeline_disable_disable_string =
TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, disable_string,
"disable");
-cmdline_parse_inst_t cmd_pipeline_disable = {
+static cmdline_parse_inst_t cmd_pipeline_disable = {
.f = cmd_pipeline_disable_parsed,
.data = NULL,
.help_str = "Disable pipeline on specified core",
@@ -405,19 +404,19 @@ cmd_thread_headroom_parsed(
printf("Command failed\n");
}
-cmdline_parse_token_string_t cmd_thread_headroom_t_string =
+static cmdline_parse_token_string_t cmd_thread_headroom_t_string =
TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result,
t_string, "t");
-cmdline_parse_token_string_t cmd_thread_headroom_t_id_string =
+static cmdline_parse_token_string_t cmd_thread_headroom_t_id_string =
TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result,
t_id_string, NULL);
-cmdline_parse_token_string_t cmd_thread_headroom_headroom_string =
+static cmdline_parse_token_string_t cmd_thread_headroom_headroom_string =
TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result,
headroom_string, "headroom");
-cmdline_parse_inst_t cmd_thread_headroom = {
+static cmdline_parse_inst_t cmd_thread_headroom = {
.f = cmd_thread_headroom_parsed,
.data = NULL,
.help_str = "Display thread headroom",
diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c
index c27e7353..ef09a2ed 100644
--- a/examples/ip_reassembly/main.c
+++ b/examples/ip_reassembly/main.c
@@ -963,7 +963,7 @@ init_mem(void)
RTE_LOG(INFO, IP_RSMBL, "Creating LPM6 table on socket %i\n", socket);
snprintf(buf, sizeof(buf), "IP_RSMBL_LPM_%i", socket);
- lpm6 = rte_lpm6_create("IP_RSMBL_LPM6", socket, &lpm6_config);
+ lpm6 = rte_lpm6_create(buf, socket, &lpm6_config);
if (lpm6 == NULL) {
RTE_LOG(ERR, IP_RSMBL, "Cannot create LPM table\n");
return -1;
@@ -1040,9 +1040,7 @@ main(int argc, char **argv)
rte_exit(EXIT_FAILURE, "Invalid IP reassembly parameters\n");
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
- else if (nb_ports == 0)
+ if (nb_ports == 0)
rte_exit(EXIT_FAILURE, "No ports found!\n");
nb_lcores = rte_lcore_count();
diff --git a/examples/ipsec-secgw/Makefile b/examples/ipsec-secgw/Makefile
index f9b59c22..06b6db1e 100644
--- a/examples/ipsec-secgw/Makefile
+++ b/examples/ipsec-secgw/Makefile
@@ -46,15 +46,17 @@ ifeq ($(CONFIG_RTE_TOOLCHAIN_ICC),y)
CFLAGS_sa.o += -diag-disable=vec
endif
-
-VPATH += $(SRCDIR)/librte_ipsec
+ifeq ($(DEBUG),1)
+CFLAGS += -DIPSEC_DEBUG -fstack-protector-all -O0
+endif
#
# all source are stored in SRCS-y
#
SRCS-y += ipsec.c
SRCS-y += esp.c
-SRCS-y += sp.c
+SRCS-y += sp4.c
+SRCS-y += sp6.c
SRCS-y += sa.c
SRCS-y += rt.c
SRCS-y += ipsec-secgw.c
diff --git a/examples/ipsec-secgw/esp.c b/examples/ipsec-secgw/esp.c
index 19273807..05caa77a 100644
--- a/examples/ipsec-secgw/esp.c
+++ b/examples/ipsec-secgw/esp.c
@@ -37,11 +37,11 @@
#include <sys/stat.h>
#include <netinet/in.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <fcntl.h>
#include <unistd.h>
#include <rte_common.h>
-#include <rte_memcpy.h>
#include <rte_crypto.h>
#include <rte_cryptodev.h>
#include <rte_random.h>
@@ -50,15 +50,13 @@
#include "esp.h"
#include "ipip.h"
-#define IP_ESP_HDR_SZ (sizeof(struct ip) + sizeof(struct esp_hdr))
-
static inline void
random_iv_u64(uint64_t *buf, uint16_t n)
{
- unsigned left = n & 0x7;
- unsigned i;
+ uint32_t left = n & 0x7;
+ uint32_t i;
- IPSEC_ASSERT((n & 0x3) == 0);
+ RTE_ASSERT((n & 0x3) == 0);
for (i = 0; i < (n >> 3); i++)
buf[i] = rte_rand();
@@ -67,23 +65,35 @@ random_iv_u64(uint64_t *buf, uint16_t n)
*((uint32_t *)&buf[i]) = (uint32_t)lrand48();
}
-/* IPv4 Tunnel */
int
-esp4_tunnel_inbound_pre_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
+esp_inbound(struct rte_mbuf *m, struct ipsec_sa *sa,
struct rte_crypto_op *cop)
{
- int32_t payload_len;
+ struct ip *ip4;
struct rte_crypto_sym_op *sym_cop;
+ int32_t payload_len, ip_hdr_len;
+
+ RTE_ASSERT(m != NULL);
+ RTE_ASSERT(sa != NULL);
+ RTE_ASSERT(cop != NULL);
+
+ ip4 = rte_pktmbuf_mtod(m, struct ip *);
+ if (likely(ip4->ip_v == IPVERSION))
+ ip_hdr_len = ip4->ip_hl * 4;
+ else if (ip4->ip_v == IP6_VERSION)
+ /* XXX No option headers supported */
+ ip_hdr_len = sizeof(struct ip6_hdr);
+ else {
+ RTE_LOG(ERR, IPSEC_ESP, "invalid IP packet type %d\n",
+ ip4->ip_v);
+ return -EINVAL;
+ }
- IPSEC_ASSERT(m != NULL);
- IPSEC_ASSERT(sa != NULL);
- IPSEC_ASSERT(cop != NULL);
-
- payload_len = rte_pktmbuf_pkt_len(m) - IP_ESP_HDR_SZ - sa->iv_len -
- sa->digest_len;
+ payload_len = rte_pktmbuf_pkt_len(m) - ip_hdr_len -
+ sizeof(struct esp_hdr) - sa->iv_len - sa->digest_len;
if ((payload_len & (sa->block_size - 1)) || (payload_len <= 0)) {
- IPSEC_LOG(DEBUG, IPSEC_ESP, "payload %d not multiple of %u\n",
+ RTE_LOG(DEBUG, IPSEC_ESP, "payload %d not multiple of %u\n",
payload_len, sa->block_size);
return -EINVAL;
}
@@ -91,21 +101,19 @@ esp4_tunnel_inbound_pre_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
sym_cop = (struct rte_crypto_sym_op *)(cop + 1);
sym_cop->m_src = m;
- sym_cop->cipher.data.offset = IP_ESP_HDR_SZ + sa->iv_len;
+ sym_cop->cipher.data.offset = ip_hdr_len + sizeof(struct esp_hdr) +
+ sa->iv_len;
sym_cop->cipher.data.length = payload_len;
sym_cop->cipher.iv.data = rte_pktmbuf_mtod_offset(m, void*,
- IP_ESP_HDR_SZ);
+ ip_hdr_len + sizeof(struct esp_hdr));
sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(m,
- IP_ESP_HDR_SZ);
+ ip_hdr_len + sizeof(struct esp_hdr));
sym_cop->cipher.iv.length = sa->iv_len;
- sym_cop->auth.data.offset = sizeof(struct ip);
- if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GCM)
- sym_cop->auth.data.length = sizeof(struct esp_hdr);
- else
- sym_cop->auth.data.length = sizeof(struct esp_hdr) +
- sa->iv_len + payload_len;
+ sym_cop->auth.data.offset = ip_hdr_len;
+ sym_cop->auth.data.length = sizeof(struct esp_hdr) +
+ sa->iv_len + payload_len;
sym_cop->auth.digest.data = rte_pktmbuf_mtod_offset(m, void*,
rte_pktmbuf_pkt_len(m) - sa->digest_len);
@@ -117,19 +125,21 @@ esp4_tunnel_inbound_pre_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
}
int
-esp4_tunnel_inbound_post_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
+esp_inbound_post(struct rte_mbuf *m, struct ipsec_sa *sa,
struct rte_crypto_op *cop)
{
+ struct ip *ip4, *ip;
+ struct ip6_hdr *ip6;
uint8_t *nexthdr, *pad_len;
uint8_t *padding;
uint16_t i;
- IPSEC_ASSERT(m != NULL);
- IPSEC_ASSERT(sa != NULL);
- IPSEC_ASSERT(cop != NULL);
+ RTE_ASSERT(m != NULL);
+ RTE_ASSERT(sa != NULL);
+ RTE_ASSERT(cop != NULL);
if (cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
- IPSEC_LOG(ERR, IPSEC_ESP, "Failed crypto op\n");
+ RTE_LOG(ERR, IPSEC_ESP, "failed crypto op\n");
return -1;
}
@@ -139,111 +149,187 @@ esp4_tunnel_inbound_post_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
padding = pad_len - *pad_len;
for (i = 0; i < *pad_len; i++) {
- if (padding[i] != i) {
- IPSEC_LOG(ERR, IPSEC_ESP, "invalid pad_len field\n");
+ if (padding[i] != i + 1) {
+ RTE_LOG(ERR, IPSEC_ESP, "invalid padding\n");
return -EINVAL;
}
}
if (rte_pktmbuf_trim(m, *pad_len + 2 + sa->digest_len)) {
- IPSEC_LOG(ERR, IPSEC_ESP,
+ RTE_LOG(ERR, IPSEC_ESP,
"failed to remove pad_len + digest\n");
return -EINVAL;
}
- return ip4ip_inbound(m, sizeof(struct esp_hdr) + sa->iv_len);
+ if (unlikely(sa->flags == TRANSPORT)) {
+ ip = rte_pktmbuf_mtod(m, struct ip *);
+ ip4 = (struct ip *)rte_pktmbuf_adj(m,
+ sizeof(struct esp_hdr) + sa->iv_len);
+ if (likely(ip->ip_v == IPVERSION)) {
+ memmove(ip4, ip, ip->ip_hl * 4);
+ ip4->ip_p = *nexthdr;
+ ip4->ip_len = htons(rte_pktmbuf_data_len(m));
+ } else {
+ ip6 = (struct ip6_hdr *)ip4;
+ /* XXX No option headers supported */
+ memmove(ip6, ip, sizeof(struct ip6_hdr));
+ ip6->ip6_nxt = *nexthdr;
+ ip6->ip6_plen = htons(rte_pktmbuf_data_len(m));
+ }
+ } else
+ ipip_inbound(m, sizeof(struct esp_hdr) + sa->iv_len);
+
+ return 0;
}
int
-esp4_tunnel_outbound_pre_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
+esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,
struct rte_crypto_op *cop)
{
- uint16_t pad_payload_len, pad_len;
- struct ip *ip;
- struct esp_hdr *esp;
- int i;
- char *padding;
+ struct ip *ip4;
+ struct ip6_hdr *ip6;
+ struct esp_hdr *esp = NULL;
+ uint8_t *padding, *new_ip, nlp;
struct rte_crypto_sym_op *sym_cop;
+ int32_t i;
+ uint16_t pad_payload_len, pad_len, ip_hdr_len;
+
+ RTE_ASSERT(m != NULL);
+ RTE_ASSERT(sa != NULL);
+ RTE_ASSERT(cop != NULL);
+
+ ip_hdr_len = 0;
+
+ ip4 = rte_pktmbuf_mtod(m, struct ip *);
+ if (likely(ip4->ip_v == IPVERSION)) {
+ if (unlikely(sa->flags == TRANSPORT)) {
+ ip_hdr_len = ip4->ip_hl * 4;
+ nlp = ip4->ip_p;
+ } else
+ nlp = IPPROTO_IPIP;
+ } else if (ip4->ip_v == IP6_VERSION) {
+ if (unlikely(sa->flags == TRANSPORT)) {
+ /* XXX No option headers supported */
+ ip_hdr_len = sizeof(struct ip6_hdr);
+ ip6 = (struct ip6_hdr *)ip4;
+ nlp = ip6->ip6_nxt;
+ } else
+ nlp = IPPROTO_IPV6;
+ } else {
+ RTE_LOG(ERR, IPSEC_ESP, "invalid IP packet type %d\n",
+ ip4->ip_v);
+ return -EINVAL;
+ }
- IPSEC_ASSERT(m != NULL);
- IPSEC_ASSERT(sa != NULL);
- IPSEC_ASSERT(cop != NULL);
-
- /* Payload length */
- pad_payload_len = RTE_ALIGN_CEIL(rte_pktmbuf_pkt_len(m) + 2,
- sa->block_size);
- pad_len = pad_payload_len - rte_pktmbuf_pkt_len(m);
-
- rte_prefetch0(rte_pktmbuf_mtod_offset(m, void *,
- rte_pktmbuf_pkt_len(m)));
+ /* Padded payload length */
+ pad_payload_len = RTE_ALIGN_CEIL(rte_pktmbuf_pkt_len(m) -
+ ip_hdr_len + 2, sa->block_size);
+ pad_len = pad_payload_len + ip_hdr_len - rte_pktmbuf_pkt_len(m);
+
+ RTE_ASSERT(sa->flags == IP4_TUNNEL || sa->flags == IP6_TUNNEL ||
+ sa->flags == TRANSPORT);
+
+ if (likely(sa->flags == IP4_TUNNEL))
+ ip_hdr_len = sizeof(struct ip);
+ else if (sa->flags == IP6_TUNNEL)
+ ip_hdr_len = sizeof(struct ip6_hdr);
+ else if (sa->flags != TRANSPORT) {
+ RTE_LOG(ERR, IPSEC_ESP, "Unsupported SA flags: 0x%x\n",
+ sa->flags);
+ return -EINVAL;
+ }
/* Check maximum packet size */
- if (unlikely(IP_ESP_HDR_SZ + sa->iv_len + pad_payload_len +
- sa->digest_len > IP_MAXPACKET)) {
- IPSEC_LOG(DEBUG, IPSEC_ESP, "ipsec packet is too big\n");
+ if (unlikely(ip_hdr_len + sizeof(struct esp_hdr) + sa->iv_len +
+ pad_payload_len + sa->digest_len > IP_MAXPACKET)) {
+ RTE_LOG(ERR, IPSEC_ESP, "ipsec packet is too big\n");
return -EINVAL;
}
- padding = rte_pktmbuf_append(m, pad_len + sa->digest_len);
-
- IPSEC_ASSERT(padding != NULL);
-
- ip = ip4ip_outbound(m, sizeof(struct esp_hdr) + sa->iv_len,
- sa->src, sa->dst);
+ padding = (uint8_t *)rte_pktmbuf_append(m, pad_len + sa->digest_len);
+ if (unlikely(padding == NULL)) {
+ RTE_LOG(ERR, IPSEC_ESP, "not enough mbuf trailing space\n");
+ return -ENOSPC;
+ }
+ rte_prefetch0(padding);
+
+ switch (sa->flags) {
+ case IP4_TUNNEL:
+ ip4 = ip4ip_outbound(m, sizeof(struct esp_hdr) + sa->iv_len,
+ &sa->src, &sa->dst);
+ esp = (struct esp_hdr *)(ip4 + 1);
+ break;
+ case IP6_TUNNEL:
+ ip6 = ip6ip_outbound(m, sizeof(struct esp_hdr) + sa->iv_len,
+ &sa->src, &sa->dst);
+ esp = (struct esp_hdr *)(ip6 + 1);
+ break;
+ case TRANSPORT:
+ new_ip = (uint8_t *)rte_pktmbuf_prepend(m,
+ sizeof(struct esp_hdr) + sa->iv_len);
+ memmove(new_ip, ip4, ip_hdr_len);
+ esp = (struct esp_hdr *)(new_ip + ip_hdr_len);
+ if (likely(ip4->ip_v == IPVERSION)) {
+ ip4 = (struct ip *)new_ip;
+ ip4->ip_p = IPPROTO_ESP;
+ ip4->ip_len = htons(rte_pktmbuf_data_len(m));
+ } else {
+ ip6 = (struct ip6_hdr *)new_ip;
+ ip6->ip6_nxt = IPPROTO_ESP;
+ ip6->ip6_plen = htons(rte_pktmbuf_data_len(m));
+ }
+ }
- esp = (struct esp_hdr *)(ip + 1);
- esp->spi = sa->spi;
- esp->seq = htonl(sa->seq++);
+ sa->seq++;
+ esp->spi = rte_cpu_to_be_32(sa->spi);
+ esp->seq = rte_cpu_to_be_32(sa->seq);
- IPSEC_LOG(DEBUG, IPSEC_ESP, "pktlen %u\n", rte_pktmbuf_pkt_len(m));
+ if (sa->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC)
+ random_iv_u64((uint64_t *)(esp + 1), sa->iv_len);
/* Fill pad_len using default sequential scheme */
for (i = 0; i < pad_len - 2; i++)
padding[i] = i + 1;
-
padding[pad_len - 2] = pad_len - 2;
- padding[pad_len - 1] = IPPROTO_IPIP;
+ padding[pad_len - 1] = nlp;
sym_cop = (struct rte_crypto_sym_op *)(cop + 1);
sym_cop->m_src = m;
- sym_cop->cipher.data.offset = IP_ESP_HDR_SZ + sa->iv_len;
+ sym_cop->cipher.data.offset = ip_hdr_len + sizeof(struct esp_hdr) +
+ sa->iv_len;
sym_cop->cipher.data.length = pad_payload_len;
sym_cop->cipher.iv.data = rte_pktmbuf_mtod_offset(m, uint8_t *,
- IP_ESP_HDR_SZ);
+ ip_hdr_len + sizeof(struct esp_hdr));
sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(m,
- IP_ESP_HDR_SZ);
+ ip_hdr_len + sizeof(struct esp_hdr));
sym_cop->cipher.iv.length = sa->iv_len;
- sym_cop->auth.data.offset = sizeof(struct ip);
+ sym_cop->auth.data.offset = ip_hdr_len;
sym_cop->auth.data.length = sizeof(struct esp_hdr) + sa->iv_len +
pad_payload_len;
sym_cop->auth.digest.data = rte_pktmbuf_mtod_offset(m, uint8_t *,
- IP_ESP_HDR_SZ + sa->iv_len + pad_payload_len);
+ rte_pktmbuf_pkt_len(m) - sa->digest_len);
sym_cop->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(m,
- IP_ESP_HDR_SZ + sa->iv_len + pad_payload_len);
+ rte_pktmbuf_pkt_len(m) - sa->digest_len);
sym_cop->auth.digest.length = sa->digest_len;
- if (sa->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC)
- random_iv_u64((uint64_t *)sym_cop->cipher.iv.data,
- sym_cop->cipher.iv.length);
-
return 0;
}
int
-esp4_tunnel_outbound_post_crypto(struct rte_mbuf *m __rte_unused,
+esp_outbound_post(struct rte_mbuf *m __rte_unused,
struct ipsec_sa *sa __rte_unused,
struct rte_crypto_op *cop)
{
- IPSEC_ASSERT(m != NULL);
- IPSEC_ASSERT(sa != NULL);
- IPSEC_ASSERT(cop != NULL);
+ RTE_ASSERT(m != NULL);
+ RTE_ASSERT(sa != NULL);
+ RTE_ASSERT(cop != NULL);
if (cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
- IPSEC_LOG(ERR, IPSEC_ESP, "Failed crypto op\n");
+ RTE_LOG(ERR, IPSEC_ESP, "Failed crypto op\n");
return -1;
}
diff --git a/examples/ipsec-secgw/esp.h b/examples/ipsec-secgw/esp.h
index 31018823..fa5cc8af 100644
--- a/examples/ipsec-secgw/esp.h
+++ b/examples/ipsec-secgw/esp.h
@@ -46,21 +46,20 @@ struct esp_hdr {
/* Integrity Check Value - ICV */
};
-/* IPv4 Tunnel */
int
-esp4_tunnel_inbound_pre_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
+esp_inbound(struct rte_mbuf *m, struct ipsec_sa *sa,
struct rte_crypto_op *cop);
int
-esp4_tunnel_inbound_post_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
+esp_inbound_post(struct rte_mbuf *m, struct ipsec_sa *sa,
struct rte_crypto_op *cop);
int
-esp4_tunnel_outbound_pre_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
+esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,
struct rte_crypto_op *cop);
int
-esp4_tunnel_outbound_post_crypto(struct rte_mbuf *m, struct ipsec_sa *sa,
+esp_outbound_post(struct rte_mbuf *m, struct ipsec_sa *sa,
struct rte_crypto_op *cop);
#endif /* __RTE_IPSEC_XFORM_ESP_H__ */
diff --git a/examples/ipsec-secgw/ipip.h b/examples/ipsec-secgw/ipip.h
index 322076ce..ce25a2e2 100644
--- a/examples/ipsec-secgw/ipip.h
+++ b/examples/ipsec-secgw/ipip.h
@@ -37,67 +37,144 @@
#include <stdint.h>
#include <netinet/in.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <rte_mbuf.h>
-#define IPV6_VERSION (6)
-
-static inline struct ip *
-ip4ip_outbound(struct rte_mbuf *m, uint32_t offset, uint32_t src, uint32_t dst)
+static inline void *
+ipip_outbound(struct rte_mbuf *m, uint32_t offset, uint32_t is_ipv6,
+ struct ip_addr *src, struct ip_addr *dst)
{
- struct ip *inip, *outip;
+ struct ip *inip4, *outip4;
+ struct ip6_hdr *inip6, *outip6;
+ uint8_t ds_ecn;
- inip = rte_pktmbuf_mtod(m, struct ip*);
+ inip4 = rte_pktmbuf_mtod(m, struct ip *);
- IPSEC_ASSERT(inip->ip_v == IPVERSION || inip->ip_v == IPV6_VERSION);
+ RTE_ASSERT(inip4->ip_v == IPVERSION || inip4->ip_v == IP6_VERSION);
- offset += sizeof(struct ip);
+ if (inip4->ip_v == IPVERSION) {
+ /* XXX This should be done by the forwarding engine instead */
+ inip4->ip_ttl -= 1;
+ ds_ecn = inip4->ip_tos;
+ } else {
+ inip6 = (struct ip6_hdr *)inip4;
+ /* XXX This should be done by the forwarding engine instead */
+ inip6->ip6_hops -= 1;
+ ds_ecn = ntohl(inip6->ip6_flow) >> 20;
+ }
+
+ if (is_ipv6) {
+ offset += sizeof(struct ip6_hdr);
+ outip6 = (struct ip6_hdr *)rte_pktmbuf_prepend(m, offset);
+
+ RTE_ASSERT(outip6 != NULL);
+
+ /* Per RFC4301 5.1.2.1 */
+ outip6->ip6_flow = htonl(IP6_VERSION << 28 | ds_ecn << 20);
+ outip6->ip6_plen = htons(rte_pktmbuf_data_len(m));
+
+ outip6->ip6_nxt = IPPROTO_ESP;
+ outip6->ip6_hops = IPDEFTTL;
- outip = (struct ip *)rte_pktmbuf_prepend(m, offset);
+ memcpy(&outip6->ip6_src.s6_addr, src, 16);
+ memcpy(&outip6->ip6_dst.s6_addr, dst, 16);
- IPSEC_ASSERT(outip != NULL);
+ return outip6;
+ }
+
+ offset += sizeof(struct ip);
+ outip4 = (struct ip *)rte_pktmbuf_prepend(m, offset);
+
+ RTE_ASSERT(outip4 != NULL);
/* Per RFC4301 5.1.2.1 */
- outip->ip_v = IPVERSION;
- outip->ip_hl = 5;
- outip->ip_tos = inip->ip_tos;
- outip->ip_len = htons(rte_pktmbuf_data_len(m));
+ outip4->ip_v = IPVERSION;
+ outip4->ip_hl = 5;
+ outip4->ip_tos = ds_ecn;
+ outip4->ip_len = htons(rte_pktmbuf_data_len(m));
+
+ outip4->ip_id = 0;
+ outip4->ip_off = 0;
+
+ outip4->ip_ttl = IPDEFTTL;
+ outip4->ip_p = IPPROTO_ESP;
+
+ outip4->ip_src.s_addr = src->ip4;
+ outip4->ip_dst.s_addr = dst->ip4;
- outip->ip_id = 0;
- outip->ip_off = 0;
+ return outip4;
+}
+
+static inline struct ip *
+ip4ip_outbound(struct rte_mbuf *m, uint32_t offset,
+ struct ip_addr *src, struct ip_addr *dst)
+{
+ return ipip_outbound(m, offset, 0, src, dst);
+}
- outip->ip_ttl = IPDEFTTL;
- outip->ip_p = IPPROTO_ESP;
+static inline struct ip6_hdr *
+ip6ip_outbound(struct rte_mbuf *m, uint32_t offset,
+ struct ip_addr *src, struct ip_addr *dst)
+{
+ return ipip_outbound(m, offset, 1, src, dst);
+}
- outip->ip_src.s_addr = src;
- outip->ip_dst.s_addr = dst;
+static inline void
+ip4_ecn_setup(struct ip *ip4)
+{
+ if (ip4->ip_tos & IPTOS_ECN_MASK)
+ ip4->ip_tos |= IPTOS_ECN_CE;
+}
- return outip;
+static inline void
+ip6_ecn_setup(struct ip6_hdr *ip6)
+{
+ if ((ntohl(ip6->ip6_flow) >> 20) & IPTOS_ECN_MASK)
+ ip6->ip6_flow = htonl(ntohl(ip6->ip6_flow) |
+ (IPTOS_ECN_CE << 20));
}
-static inline int
-ip4ip_inbound(struct rte_mbuf *m, uint32_t offset)
+static inline void
+ipip_inbound(struct rte_mbuf *m, uint32_t offset)
{
- struct ip *inip;
- struct ip *outip;
+ struct ip *inip4, *outip4;
+ struct ip6_hdr *inip6, *outip6;
+ uint32_t ip_len, set_ecn;
- outip = rte_pktmbuf_mtod(m, struct ip*);
+ outip4 = rte_pktmbuf_mtod(m, struct ip*);
- IPSEC_ASSERT(outip->ip_v == IPVERSION);
+ RTE_ASSERT(outip4->ip_v == IPVERSION || outip4->ip_v == IP6_VERSION);
- offset += sizeof(struct ip);
- inip = (struct ip *)rte_pktmbuf_adj(m, offset);
- IPSEC_ASSERT(inip->ip_v == IPVERSION || inip->ip_v == IPV6_VERSION);
+ if (outip4->ip_v == IPVERSION) {
+ ip_len = sizeof(struct ip);
+ set_ecn = ((outip4->ip_tos & IPTOS_ECN_CE) == IPTOS_ECN_CE);
+ } else {
+ outip6 = (struct ip6_hdr *)outip4;
+ ip_len = sizeof(struct ip6_hdr);
+ set_ecn = ntohl(outip6->ip6_flow) >> 20;
+ set_ecn = ((set_ecn & IPTOS_ECN_CE) == IPTOS_ECN_CE);
+ }
+
+ inip4 = (struct ip *)rte_pktmbuf_adj(m, offset + ip_len);
+ RTE_ASSERT(inip4->ip_v == IPVERSION || inip4->ip_v == IP6_VERSION);
/* Check packet is still bigger than IP header (inner) */
- IPSEC_ASSERT(rte_pktmbuf_pkt_len(m) > sizeof(struct ip));
+ RTE_ASSERT(rte_pktmbuf_pkt_len(m) > ip_len);
/* RFC4301 5.1.2.1 Note 6 */
- if ((inip->ip_tos & htons(IPTOS_ECN_ECT0 | IPTOS_ECN_ECT1)) &&
- ((outip->ip_tos & htons(IPTOS_ECN_CE)) == IPTOS_ECN_CE))
- inip->ip_tos |= htons(IPTOS_ECN_CE);
-
- return 0;
+ if (inip4->ip_v == IPVERSION) {
+ if (set_ecn)
+ ip4_ecn_setup(inip4);
+ /* XXX This should be done by the forwarding engine instead */
+ inip4->ip_ttl -= 1;
+ } else {
+ inip6 = (struct ip6_hdr *)inip4;
+ if (set_ecn)
+ ip6_ecn_setup(inip6);
+ /* XXX This should be done by the forwarding engine instead */
+ inip6->ip6_hops -= 1;
+ }
}
#endif /* __IPIP_H__ */
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 00ab2d84..f78743d0 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -38,6 +38,7 @@
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <string.h>
#include <sys/queue.h>
#include <stdarg.h>
@@ -65,6 +66,7 @@
#include <rte_mbuf.h>
#include <rte_acl.h>
#include <rte_lpm.h>
+#include <rte_lpm6.h>
#include <rte_hash.h>
#include <rte_jhash.h>
#include <rte_cryptodev.h>
@@ -192,7 +194,8 @@ struct lcore_conf {
struct buffer tx_mbufs[RTE_MAX_ETHPORTS];
struct ipsec_ctx inbound;
struct ipsec_ctx outbound;
- struct rt_ctx *rt_ctx;
+ struct rt_ctx *rt4_ctx;
+ struct rt_ctx *rt6_ctx;
} __rte_cache_aligned;
static struct lcore_conf lcore_conf[RTE_MAX_LCORE];
@@ -230,27 +233,39 @@ struct traffic_type {
};
struct ipsec_traffic {
- struct traffic_type ipsec4;
- struct traffic_type ipv4;
+ struct traffic_type ipsec;
+ struct traffic_type ip4;
+ struct traffic_type ip6;
};
static inline void
prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
{
uint8_t *nlp;
+ struct ether_hdr *eth;
- if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
- rte_pktmbuf_adj(pkt, ETHER_HDR_LEN);
- nlp = rte_pktmbuf_mtod_offset(pkt, uint8_t *,
- offsetof(struct ip, ip_p));
+ eth = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
+ if (eth->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
+ nlp = (uint8_t *)rte_pktmbuf_adj(pkt, ETHER_HDR_LEN);
+ nlp = RTE_PTR_ADD(nlp, offsetof(struct ip, ip_p));
if (*nlp == IPPROTO_ESP)
- t->ipsec4.pkts[(t->ipsec4.num)++] = pkt;
+ t->ipsec.pkts[(t->ipsec.num)++] = pkt;
else {
- t->ipv4.data[t->ipv4.num] = nlp;
- t->ipv4.pkts[(t->ipv4.num)++] = pkt;
+ t->ip4.data[t->ip4.num] = nlp;
+ t->ip4.pkts[(t->ip4.num)++] = pkt;
+ }
+ } else if (eth->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv6)) {
+ nlp = (uint8_t *)rte_pktmbuf_adj(pkt, ETHER_HDR_LEN);
+ nlp = RTE_PTR_ADD(nlp, offsetof(struct ip6_hdr, ip6_nxt));
+ if (*nlp == IPPROTO_ESP)
+ t->ipsec.pkts[(t->ipsec.num)++] = pkt;
+ else {
+ t->ip6.data[t->ip6.num] = nlp;
+ t->ip6.pkts[(t->ip6.num)++] = pkt;
}
} else {
/* Unknown/Unsupported type, drop the packet */
+ RTE_LOG(ERR, IPSEC, "Unsupported packet type\n");
rte_pktmbuf_free(pkt);
}
}
@@ -261,8 +276,9 @@ prepare_traffic(struct rte_mbuf **pkts, struct ipsec_traffic *t,
{
int32_t i;
- t->ipsec4.num = 0;
- t->ipv4.num = 0;
+ t->ipsec.num = 0;
+ t->ip4.num = 0;
+ t->ip6.num = 0;
for (i = 0; i < (nb_pkts - PREFETCH_OFFSET); i++) {
rte_prefetch0(rte_pktmbuf_mtod(pkts[i + PREFETCH_OFFSET],
@@ -277,14 +293,27 @@ prepare_traffic(struct rte_mbuf **pkts, struct ipsec_traffic *t,
static inline void
prepare_tx_pkt(struct rte_mbuf *pkt, uint8_t port)
{
- pkt->ol_flags |= PKT_TX_IP_CKSUM | PKT_TX_IPV4;
- pkt->l3_len = sizeof(struct ip);
- pkt->l2_len = ETHER_HDR_LEN;
+ struct ip *ip;
+ struct ether_hdr *ethhdr;
+
+ ip = rte_pktmbuf_mtod(pkt, struct ip *);
+
+ ethhdr = (struct ether_hdr *)rte_pktmbuf_prepend(pkt, ETHER_HDR_LEN);
- struct ether_hdr *ethhdr = (struct ether_hdr *)rte_pktmbuf_prepend(pkt,
- ETHER_HDR_LEN);
+ if (ip->ip_v == IPVERSION) {
+ pkt->ol_flags |= PKT_TX_IP_CKSUM | PKT_TX_IPV4;
+ pkt->l3_len = sizeof(struct ip);
+ pkt->l2_len = ETHER_HDR_LEN;
+
+ ethhdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+ } else {
+ pkt->ol_flags |= PKT_TX_IPV6;
+ pkt->l3_len = sizeof(struct ip6_hdr);
+ pkt->l2_len = ETHER_HDR_LEN;
+
+ ethhdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
+ }
- ethhdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
memcpy(&ethhdr->s_addr, &ethaddr_tbl[port].src,
sizeof(struct ether_addr));
memcpy(&ethhdr->d_addr, &ethaddr_tbl[port].dst,
@@ -298,7 +327,7 @@ prepare_tx_burst(struct rte_mbuf *pkts[], uint16_t nb_pkts, uint8_t port)
const int32_t prefetch_offset = 2;
for (i = 0; i < (nb_pkts - prefetch_offset); i++) {
- rte_prefetch0(pkts[i + prefetch_offset]->cacheline1);
+ rte_mbuf_prefetch_part2(pkts[i + prefetch_offset]);
prepare_tx_pkt(pkts[i], port);
}
/* Process left packets */
@@ -355,94 +384,133 @@ send_single_packet(struct rte_mbuf *m, uint8_t port)
}
static inline void
-process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
- struct ipsec_traffic *traffic)
+inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip)
{
struct rte_mbuf *m;
- uint16_t idx, nb_pkts_in, i, j;
- uint32_t sa_idx, res;
-
- nb_pkts_in = ipsec_inbound(ipsec_ctx, traffic->ipsec4.pkts,
- traffic->ipsec4.num, MAX_PKT_BURST);
+ uint32_t i, j, res, sa_idx;
- /* SP/ACL Inbound check ipsec and ipv4 */
- for (i = 0; i < nb_pkts_in; i++) {
- idx = traffic->ipv4.num++;
- m = traffic->ipsec4.pkts[i];
- traffic->ipv4.pkts[idx] = m;
- traffic->ipv4.data[idx] = rte_pktmbuf_mtod_offset(m,
- uint8_t *, offsetof(struct ip, ip_p));
- }
+ if (ip->num == 0)
+ return;
- rte_acl_classify((struct rte_acl_ctx *)ipsec_ctx->sp_ctx,
- traffic->ipv4.data, traffic->ipv4.res,
- traffic->ipv4.num, DEFAULT_MAX_CATEGORIES);
+ rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
+ ip->num, DEFAULT_MAX_CATEGORIES);
j = 0;
- for (i = 0; i < traffic->ipv4.num - nb_pkts_in; i++) {
- m = traffic->ipv4.pkts[i];
- res = traffic->ipv4.res[i];
- if (res & ~BYPASS) {
+ for (i = 0; i < ip->num; i++) {
+ m = ip->pkts[i];
+ res = ip->res[i];
+ if (res & DISCARD) {
rte_pktmbuf_free(m);
continue;
}
- traffic->ipv4.pkts[j++] = m;
- }
- /* Check return SA SPI matches pkt SPI */
- for ( ; i < traffic->ipv4.num; i++) {
- m = traffic->ipv4.pkts[i];
- sa_idx = traffic->ipv4.res[i] & PROTECT_MASK;
- if (sa_idx == 0 || !inbound_sa_check(ipsec_ctx->sa_ctx,
- m, sa_idx)) {
+ if (res & BYPASS) {
+ ip->pkts[j++] = m;
+ continue;
+ }
+ /* Check return SA SPI matches pkt SPI */
+ sa_idx = ip->res[i] & PROTECT_MASK;
+ if (sa_idx == 0 || !inbound_sa_check(sa, m, sa_idx)) {
rte_pktmbuf_free(m);
continue;
}
- traffic->ipv4.pkts[j++] = m;
+ ip->pkts[j++] = m;
}
- traffic->ipv4.num = j;
+ ip->num = j;
}
static inline void
-process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
+process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
struct ipsec_traffic *traffic)
{
struct rte_mbuf *m;
- uint16_t idx, nb_pkts_out, i, j;
- uint32_t sa_idx, res;
+ uint16_t idx, nb_pkts_in, i;
- rte_acl_classify((struct rte_acl_ctx *)ipsec_ctx->sp_ctx,
- traffic->ipv4.data, traffic->ipv4.res,
- traffic->ipv4.num, DEFAULT_MAX_CATEGORIES);
+ nb_pkts_in = ipsec_inbound(ipsec_ctx, traffic->ipsec.pkts,
+ traffic->ipsec.num, MAX_PKT_BURST);
- /* Drop any IPsec traffic from protected ports */
- for (i = 0; i < traffic->ipsec4.num; i++)
- rte_pktmbuf_free(traffic->ipsec4.pkts[i]);
+ /* SP/ACL Inbound check ipsec and ip4 */
+ for (i = 0; i < nb_pkts_in; i++) {
+ m = traffic->ipsec.pkts[i];
+ struct ip *ip = rte_pktmbuf_mtod(m, struct ip *);
+ if (ip->ip_v == IPVERSION) {
+ idx = traffic->ip4.num++;
+ traffic->ip4.pkts[idx] = m;
+ traffic->ip4.data[idx] = rte_pktmbuf_mtod_offset(m,
+ uint8_t *, offsetof(struct ip, ip_p));
+ } else if (ip->ip_v == IP6_VERSION) {
+ idx = traffic->ip6.num++;
+ traffic->ip6.pkts[idx] = m;
+ traffic->ip6.data[idx] = rte_pktmbuf_mtod_offset(m,
+ uint8_t *,
+ offsetof(struct ip6_hdr, ip6_nxt));
+ } else
+ rte_pktmbuf_free(m);
+ }
+
+ inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4);
+
+ inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6);
+}
+
+static inline void
+outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
+ struct traffic_type *ipsec)
+{
+ struct rte_mbuf *m;
+ uint32_t i, j, sa_idx;
+
+ if (ip->num == 0)
+ return;
- traffic->ipsec4.num = 0;
+ rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
+ ip->num, DEFAULT_MAX_CATEGORIES);
j = 0;
- for (i = 0; i < traffic->ipv4.num; i++) {
- m = traffic->ipv4.pkts[i];
- res = traffic->ipv4.res[i];
- sa_idx = res & PROTECT_MASK;
- if ((res == 0) || (res & DISCARD))
+ for (i = 0; i < ip->num; i++) {
+ m = ip->pkts[i];
+ sa_idx = ip->res[i] & PROTECT_MASK;
+ if ((ip->res[i] == 0) || (ip->res[i] & DISCARD))
rte_pktmbuf_free(m);
else if (sa_idx != 0) {
- traffic->ipsec4.res[traffic->ipsec4.num] = sa_idx;
- traffic->ipsec4.pkts[traffic->ipsec4.num++] = m;
+ ipsec->res[ipsec->num] = sa_idx;
+ ipsec->pkts[ipsec->num++] = m;
} else /* BYPASS */
- traffic->ipv4.pkts[j++] = m;
+ ip->pkts[j++] = m;
}
- traffic->ipv4.num = j;
+ ip->num = j;
+}
+
+static inline void
+process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
+ struct ipsec_traffic *traffic)
+{
+ struct rte_mbuf *m;
+ uint16_t idx, nb_pkts_out, i;
+
+ /* Drop any IPsec traffic from protected ports */
+ for (i = 0; i < traffic->ipsec.num; i++)
+ rte_pktmbuf_free(traffic->ipsec.pkts[i]);
- nb_pkts_out = ipsec_outbound(ipsec_ctx, traffic->ipsec4.pkts,
- traffic->ipsec4.res, traffic->ipsec4.num,
+ traffic->ipsec.num = 0;
+
+ outbound_sp(ipsec_ctx->sp4_ctx, &traffic->ip4, &traffic->ipsec);
+
+ outbound_sp(ipsec_ctx->sp6_ctx, &traffic->ip6, &traffic->ipsec);
+
+ nb_pkts_out = ipsec_outbound(ipsec_ctx, traffic->ipsec.pkts,
+ traffic->ipsec.res, traffic->ipsec.num,
MAX_PKT_BURST);
for (i = 0; i < nb_pkts_out; i++) {
- idx = traffic->ipv4.num++;
- m = traffic->ipsec4.pkts[i];
- traffic->ipv4.pkts[idx] = m;
+ m = traffic->ipsec.pkts[i];
+ struct ip *ip = rte_pktmbuf_mtod(m, struct ip *);
+ if (ip->ip_v == IPVERSION) {
+ idx = traffic->ip4.num++;
+ traffic->ip4.pkts[idx] = m;
+ } else {
+ idx = traffic->ip6.num++;
+ traffic->ip6.pkts[idx] = m;
+ }
}
}
@@ -450,47 +518,72 @@ static inline void
process_pkts_inbound_nosp(struct ipsec_ctx *ipsec_ctx,
struct ipsec_traffic *traffic)
{
- uint16_t nb_pkts_in, i;
+ struct rte_mbuf *m;
+ uint32_t nb_pkts_in, i, idx;
/* Drop any IPv4 traffic from unprotected ports */
- for (i = 0; i < traffic->ipv4.num; i++)
- rte_pktmbuf_free(traffic->ipv4.pkts[i]);
+ for (i = 0; i < traffic->ip4.num; i++)
+ rte_pktmbuf_free(traffic->ip4.pkts[i]);
- traffic->ipv4.num = 0;
+ traffic->ip4.num = 0;
- nb_pkts_in = ipsec_inbound(ipsec_ctx, traffic->ipsec4.pkts,
- traffic->ipsec4.num, MAX_PKT_BURST);
+ /* Drop any IPv6 traffic from unprotected ports */
+ for (i = 0; i < traffic->ip6.num; i++)
+ rte_pktmbuf_free(traffic->ip6.pkts[i]);
- for (i = 0; i < nb_pkts_in; i++)
- traffic->ipv4.pkts[i] = traffic->ipsec4.pkts[i];
+ traffic->ip6.num = 0;
- traffic->ipv4.num = nb_pkts_in;
+ nb_pkts_in = ipsec_inbound(ipsec_ctx, traffic->ipsec.pkts,
+ traffic->ipsec.num, MAX_PKT_BURST);
+
+ for (i = 0; i < nb_pkts_in; i++) {
+ m = traffic->ipsec.pkts[i];
+ struct ip *ip = rte_pktmbuf_mtod(m, struct ip *);
+ if (ip->ip_v == IPVERSION) {
+ idx = traffic->ip4.num++;
+ traffic->ip4.pkts[idx] = m;
+ } else {
+ idx = traffic->ip6.num++;
+ traffic->ip6.pkts[idx] = m;
+ }
+ }
}
static inline void
process_pkts_outbound_nosp(struct ipsec_ctx *ipsec_ctx,
struct ipsec_traffic *traffic)
{
- uint16_t nb_pkts_out, i;
+ struct rte_mbuf *m;
+ uint32_t nb_pkts_out, i;
+ struct ip *ip;
/* Drop any IPsec traffic from protected ports */
- for (i = 0; i < traffic->ipsec4.num; i++)
- rte_pktmbuf_free(traffic->ipsec4.pkts[i]);
+ for (i = 0; i < traffic->ipsec.num; i++)
+ rte_pktmbuf_free(traffic->ipsec.pkts[i]);
- traffic->ipsec4.num = 0;
+ traffic->ipsec.num = 0;
- for (i = 0; i < traffic->ipv4.num; i++)
- traffic->ipv4.res[i] = single_sa_idx;
+ for (i = 0; i < traffic->ip4.num; i++)
+ traffic->ip4.res[i] = single_sa_idx;
- nb_pkts_out = ipsec_outbound(ipsec_ctx, traffic->ipv4.pkts,
- traffic->ipv4.res, traffic->ipv4.num,
+ for (i = 0; i < traffic->ip6.num; i++)
+ traffic->ip6.res[i] = single_sa_idx;
+
+ nb_pkts_out = ipsec_outbound(ipsec_ctx, traffic->ip4.pkts,
+ traffic->ip4.res, traffic->ip4.num,
MAX_PKT_BURST);
- traffic->ipv4.num = nb_pkts_out;
+ /* They all sue the same SA (ip4 or ip6 tunnel) */
+ m = traffic->ipsec.pkts[i];
+ ip = rte_pktmbuf_mtod(m, struct ip *);
+ if (ip->ip_v == IPVERSION)
+ traffic->ip4.num = nb_pkts_out;
+ else
+ traffic->ip6.num = nb_pkts_out;
}
static inline void
-route_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
+route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
{
uint32_t hop[MAX_PKT_BURST * 2];
uint32_t dst_ip[MAX_PKT_BURST * 2];
@@ -518,6 +611,35 @@ route_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
}
static inline void
+route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
+{
+ int16_t hop[MAX_PKT_BURST * 2];
+ uint8_t dst_ip[MAX_PKT_BURST * 2][16];
+ uint8_t *ip6_dst;
+ uint16_t i, offset;
+
+ if (nb_pkts == 0)
+ return;
+
+ for (i = 0; i < nb_pkts; i++) {
+ offset = offsetof(struct ip6_hdr, ip6_dst);
+ ip6_dst = rte_pktmbuf_mtod_offset(pkts[i], uint8_t *, offset);
+ memcpy(&dst_ip[i][0], ip6_dst, 16);
+ }
+
+ rte_lpm6_lookup_bulk_func((struct rte_lpm6 *)rt_ctx, dst_ip,
+ hop, nb_pkts);
+
+ for (i = 0; i < nb_pkts; i++) {
+ if (hop[i] == -1) {
+ rte_pktmbuf_free(pkts[i]);
+ continue;
+ }
+ send_single_packet(pkts[i], hop[i] & 0xff);
+ }
+}
+
+static inline void
process_pkts(struct lcore_conf *qconf, struct rte_mbuf **pkts,
uint8_t nb_pkts, uint8_t portid)
{
@@ -525,7 +647,7 @@ process_pkts(struct lcore_conf *qconf, struct rte_mbuf **pkts,
prepare_traffic(pkts, &traffic, nb_pkts);
- if (single_sa) {
+ if (unlikely(single_sa)) {
if (UNPROTECTED_PORT(portid))
process_pkts_inbound_nosp(&qconf->inbound, &traffic);
else
@@ -537,7 +659,8 @@ process_pkts(struct lcore_conf *qconf, struct rte_mbuf **pkts,
process_pkts_outbound(&qconf->outbound, &traffic);
}
- route_pkts(qconf->rt_ctx, traffic.ipv4.pkts, traffic.ipv4.num);
+ route4_pkts(qconf->rt4_ctx, traffic.ip4.pkts, traffic.ip4.num);
+ route6_pkts(qconf->rt6_ctx, traffic.ip6.pkts, traffic.ip6.num);
}
static inline void
@@ -576,12 +699,15 @@ main_loop(__attribute__((unused)) void *dummy)
rxql = qconf->rx_queue_list;
socket_id = rte_lcore_to_socket_id(lcore_id);
- qconf->rt_ctx = socket_ctx[socket_id].rt_ipv4;
- qconf->inbound.sp_ctx = socket_ctx[socket_id].sp_ipv4_in;
- qconf->inbound.sa_ctx = socket_ctx[socket_id].sa_ipv4_in;
+ qconf->rt4_ctx = socket_ctx[socket_id].rt_ip4;
+ qconf->rt6_ctx = socket_ctx[socket_id].rt_ip6;
+ qconf->inbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_in;
+ qconf->inbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_in;
+ qconf->inbound.sa_ctx = socket_ctx[socket_id].sa_in;
qconf->inbound.cdev_map = cdev_map_in;
- qconf->outbound.sp_ctx = socket_ctx[socket_id].sp_ipv4_out;
- qconf->outbound.sa_ctx = socket_ctx[socket_id].sa_ipv4_out;
+ qconf->outbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_out;
+ qconf->outbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_out;
+ qconf->outbound.sa_ctx = socket_ctx[socket_id].sa_out;
qconf->outbound.cdev_map = cdev_map_out;
if (qconf->nb_rx_queue == 0) {
@@ -636,8 +762,6 @@ check_params(void)
}
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
for (i = 0; i < nb_lcore_params; ++i) {
lcore = lcore_params[i].lcore_id;
@@ -762,7 +886,7 @@ parse_config(const char *q_arg)
FLD_LCORE,
_NUM_FLD
};
- int long int_fld[_NUM_FLD];
+ unsigned long int_fld[_NUM_FLD];
char *str_fld[_NUM_FLD];
int32_t i;
uint32_t size;
@@ -1286,8 +1410,6 @@ main(int32_t argc, char **argv)
unprotected_port_mask);
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
if (check_params() < 0)
rte_exit(EXIT_FAILURE, "check_params failed\n");
@@ -1313,7 +1435,9 @@ main(int32_t argc, char **argv)
sa_init(&socket_ctx[socket_id], socket_id, ep);
- sp_init(&socket_ctx[socket_id], socket_id, ep);
+ sp4_init(&socket_ctx[socket_id], socket_id, ep);
+
+ sp6_init(&socket_ctx[socket_id], socket_id, ep);
rt_init(&socket_ctx[socket_id], socket_id, ep);
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index baf30d4b..1e87d0df 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -42,11 +42,12 @@
#include <rte_hash.h>
#include "ipsec.h"
+#include "esp.h"
static inline int
create_session(struct ipsec_ctx *ipsec_ctx __rte_unused, struct ipsec_sa *sa)
{
- uint32_t cdev_id_qp = 0;
+ unsigned long cdev_id_qp = 0;
int32_t ret;
struct cdev_key key = { 0 };
@@ -58,14 +59,15 @@ create_session(struct ipsec_ctx *ipsec_ctx __rte_unused, struct ipsec_sa *sa)
ret = rte_hash_lookup_data(ipsec_ctx->cdev_map, &key,
(void **)&cdev_id_qp);
if (ret < 0) {
- IPSEC_LOG(ERR, IPSEC, "No cryptodev: core %u, cipher_algo %u, "
+ RTE_LOG(ERR, IPSEC, "No cryptodev: core %u, cipher_algo %u, "
"auth_algo %u\n", key.lcore_id, key.cipher_algo,
key.auth_algo);
return -1;
}
- IPSEC_LOG(DEBUG, IPSEC, "Create session for SA spi %u on cryptodev "
- "%u qp %u\n", sa->spi, ipsec_ctx->tbl[cdev_id_qp].id,
+ RTE_LOG(DEBUG, IPSEC, "Create session for SA spi %u on cryptodev "
+ "%u qp %u\n", sa->spi,
+ ipsec_ctx->tbl[cdev_id_qp].id,
ipsec_ctx->tbl[cdev_id_qp].qp);
sa->crypto_session = rte_cryptodev_sym_session_create(
@@ -79,7 +81,7 @@ create_session(struct ipsec_ctx *ipsec_ctx __rte_unused, struct ipsec_sa *sa)
static inline void
enqueue_cop(struct cdev_qp *cqp, struct rte_crypto_op *cop)
{
- int ret, i;
+ int32_t ret, i;
cqp->buf[cqp->len++] = cop;
@@ -87,7 +89,7 @@ enqueue_cop(struct cdev_qp *cqp, struct rte_crypto_op *cop)
ret = rte_cryptodev_enqueue_burst(cqp->id, cqp->qp,
cqp->buf, cqp->len);
if (ret < cqp->len) {
- IPSEC_LOG(DEBUG, IPSEC, "Cryptodev %u queue %u:"
+ RTE_LOG(DEBUG, IPSEC, "Cryptodev %u queue %u:"
" enqueued %u crypto ops out of %u\n",
cqp->id, cqp->qp,
ret, cqp->len);
@@ -99,17 +101,21 @@ enqueue_cop(struct cdev_qp *cqp, struct rte_crypto_op *cop)
}
}
-static inline uint16_t
-ipsec_processing(struct ipsec_ctx *ipsec_ctx, struct rte_mbuf *pkts[],
- struct ipsec_sa *sas[], uint16_t nb_pkts, uint16_t max_pkts)
+static inline void
+ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,
+ struct rte_mbuf *pkts[], struct ipsec_sa *sas[],
+ uint16_t nb_pkts)
{
- int ret = 0, i, j, nb_cops;
+ int32_t ret = 0, i;
struct ipsec_mbuf_metadata *priv;
- struct rte_crypto_op *cops[max_pkts];
struct ipsec_sa *sa;
- struct rte_mbuf *pkt;
for (i = 0; i < nb_pkts; i++) {
+ if (unlikely(sas[i] == NULL)) {
+ rte_pktmbuf_free(pkts[i]);
+ continue;
+ }
+
rte_prefetch0(sas[i]);
rte_prefetch0(pkts[i]);
@@ -117,8 +123,6 @@ ipsec_processing(struct ipsec_ctx *ipsec_ctx, struct rte_mbuf *pkts[],
sa = sas[i];
priv->sa = sa;
- IPSEC_ASSERT(sa != NULL);
-
priv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
rte_prefetch0(&priv->sym_cop);
@@ -133,17 +137,27 @@ ipsec_processing(struct ipsec_ctx *ipsec_ctx, struct rte_mbuf *pkts[],
rte_crypto_op_attach_sym_session(&priv->cop,
sa->crypto_session);
- ret = sa->pre_crypto(pkts[i], sa, &priv->cop);
+ ret = xform_func(pkts[i], sa, &priv->cop);
if (unlikely(ret)) {
rte_pktmbuf_free(pkts[i]);
continue;
}
- IPSEC_ASSERT(sa->cdev_id_qp < ipsec_ctx->nb_qps);
+ RTE_ASSERT(sa->cdev_id_qp < ipsec_ctx->nb_qps);
enqueue_cop(&ipsec_ctx->tbl[sa->cdev_id_qp], &priv->cop);
}
+}
+
+static inline int
+ipsec_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,
+ struct rte_mbuf *pkts[], uint16_t max_pkts)
+{
+ int32_t nb_pkts = 0, ret = 0, i, j, nb_cops;
+ struct ipsec_mbuf_metadata *priv;
+ struct rte_crypto_op *cops[max_pkts];
+ struct ipsec_sa *sa;
+ struct rte_mbuf *pkt;
- nb_pkts = 0;
for (i = 0; i < ipsec_ctx->nb_qps && nb_pkts < max_pkts; i++) {
struct cdev_qp *cqp;
@@ -166,9 +180,9 @@ ipsec_processing(struct ipsec_ctx *ipsec_ctx, struct rte_mbuf *pkts[],
priv = get_priv(pkt);
sa = priv->sa;
- IPSEC_ASSERT(sa != NULL);
+ RTE_ASSERT(sa != NULL);
- ret = sa->post_crypto(pkt, sa, cops[j]);
+ ret = xform_func(pkt, sa, cops[j]);
if (unlikely(ret))
rte_pktmbuf_free(pkt);
else
@@ -188,7 +202,9 @@ ipsec_inbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
inbound_sa_lookup(ctx->sa_ctx, pkts, sas, nb_pkts);
- return ipsec_processing(ctx, pkts, sas, nb_pkts, len);
+ ipsec_enqueue(esp_inbound, ctx, pkts, sas, nb_pkts);
+
+ return ipsec_dequeue(esp_inbound_post, ctx, pkts, len);
}
uint16_t
@@ -199,5 +215,7 @@ ipsec_outbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
outbound_sa_lookup(ctx->sa_ctx, sa_idx, sas, nb_pkts);
- return ipsec_processing(ctx, pkts, sas, nb_pkts, len);
+ ipsec_enqueue(esp_outbound, ctx, pkts, sas, nb_pkts);
+
+ return ipsec_dequeue(esp_outbound_post, ctx, pkts, len);
}
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index a13fdef9..0d2ee254 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -37,7 +37,6 @@
#include <stdint.h>
#include <rte_byteorder.h>
-#include <rte_ip.h>
#include <rte_crypto.h>
#define RTE_LOGTYPE_IPSEC RTE_LOGTYPE_USER1
@@ -47,30 +46,18 @@
#define MAX_PKT_BURST 32
#define MAX_QP_PER_LCORE 256
-#ifdef IPSEC_DEBUG
-#define IPSEC_ASSERT(exp) \
-if (!(exp)) { \
- rte_panic("line%d\tassert \"" #exp "\" failed\n", __LINE__); \
-}
-
-#define IPSEC_LOG RTE_LOG
-#else
-#define IPSEC_ASSERT(exp) do {} while (0)
-#define IPSEC_LOG(...) do {} while (0)
-#endif /* IPSEC_DEBUG */
-
#define MAX_DIGEST_SIZE 32 /* Bytes -- 256 bits */
#define uint32_t_to_char(ip, a, b, c, d) do {\
- *a = (unsigned char)(ip >> 24 & 0xff);\
- *b = (unsigned char)(ip >> 16 & 0xff);\
- *c = (unsigned char)(ip >> 8 & 0xff);\
- *d = (unsigned char)(ip & 0xff);\
+ *a = (uint8_t)(ip >> 24 & 0xff);\
+ *b = (uint8_t)(ip >> 16 & 0xff);\
+ *c = (uint8_t)(ip >> 8 & 0xff);\
+ *d = (uint8_t)(ip & 0xff);\
} while (0)
#define DEFAULT_MAX_CATEGORIES 1
-#define IPSEC_SA_MAX_ENTRIES (64) /* must be power of 2, max 2 power 30 */
+#define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
#define SPI2IDX(spi) (spi & (IPSEC_SA_MAX_ENTRIES - 1))
#define INVALID_SPI (0)
@@ -81,6 +68,8 @@ if (!(exp)) { \
#define IPSEC_XFORM_MAX 2
+#define IP6_VERSION (6)
+
struct rte_crypto_xform;
struct ipsec_xform;
struct rte_cryptodev_session;
@@ -88,25 +77,36 @@ struct rte_mbuf;
struct ipsec_sa;
-typedef int (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa,
+typedef int32_t (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa,
struct rte_crypto_op *cop);
+struct ip_addr {
+ union {
+ uint32_t ip4;
+ union {
+ uint64_t ip6[2];
+ uint8_t ip6_b[16];
+ };
+ };
+};
+
struct ipsec_sa {
uint32_t spi;
uint32_t cdev_id_qp;
- uint32_t src;
- uint32_t dst;
struct rte_cryptodev_sym_session *crypto_session;
- struct rte_crypto_sym_xform *xforms;
- ipsec_xform_fn pre_crypto;
- ipsec_xform_fn post_crypto;
+ uint32_t seq;
enum rte_crypto_cipher_algorithm cipher_algo;
enum rte_crypto_auth_algorithm auth_algo;
uint16_t digest_len;
uint16_t iv_len;
uint16_t block_size;
uint16_t flags;
- uint32_t seq;
+#define IP4_TUNNEL (1 << 0)
+#define IP6_TUNNEL (1 << 1)
+#define TRANSPORT (1 << 2)
+ struct ip_addr src;
+ struct ip_addr dst;
+ struct rte_crypto_sym_xform *xforms;
} __rte_cache_aligned;
struct ipsec_mbuf_metadata {
@@ -125,7 +125,8 @@ struct cdev_qp {
struct ipsec_ctx {
struct rte_hash *cdev_map;
- struct sp_ctx *sp_ctx;
+ struct sp_ctx *sp4_ctx;
+ struct sp_ctx *sp6_ctx;
struct sa_ctx *sa_ctx;
uint16_t nb_qps;
uint16_t last_qp;
@@ -139,11 +140,14 @@ struct cdev_key {
};
struct socket_ctx {
- struct sa_ctx *sa_ipv4_in;
- struct sa_ctx *sa_ipv4_out;
- struct sp_ctx *sp_ipv4_in;
- struct sp_ctx *sp_ipv4_out;
- struct rt_ctx *rt_ipv4;
+ struct sa_ctx *sa_in;
+ struct sa_ctx *sa_out;
+ struct sp_ctx *sp_ip4_in;
+ struct sp_ctx *sp_ip4_out;
+ struct sp_ctx *sp_ip6_in;
+ struct sp_ctx *sp_ip6_out;
+ struct rt_ctx *rt_ip4;
+ struct rt_ctx *rt_ip6;
struct rte_mempool *mbuf_pool;
};
@@ -179,12 +183,15 @@ outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
struct ipsec_sa *sa[], uint16_t nb_pkts);
void
-sp_init(struct socket_ctx *ctx, int socket_id, unsigned ep);
+sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
+
+void
+sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
void
-sa_init(struct socket_ctx *ctx, int socket_id, unsigned ep);
+sa_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
void
-rt_init(struct socket_ctx *ctx, int socket_id, unsigned ep);
+rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
#endif /* __IPSEC_H__ */
diff --git a/examples/ipsec-secgw/rt.c b/examples/ipsec-secgw/rt.c
index a6d0866a..fa5f0420 100644
--- a/examples/ipsec-secgw/rt.c
+++ b/examples/ipsec-secgw/rt.c
@@ -36,110 +36,237 @@
*/
#include <sys/types.h>
#include <rte_lpm.h>
+#include <rte_lpm6.h>
#include <rte_errno.h>
+#include <rte_ip.h>
#include "ipsec.h"
-#define RT_IPV4_MAX_RULES 64
+#define RT_IPV4_MAX_RULES 1024
+#define RT_IPV6_MAX_RULES 1024
-struct ipv4_route {
+struct ip4_route {
uint32_t ip;
- uint8_t depth;
- uint8_t if_out;
+ uint8_t depth;
+ uint8_t if_out;
};
-/* In the default routing table we have:
- * ep0 protected ports 0 and 1, and unprotected ports 2 and 3.
- */
-static struct ipv4_route rt_ipv4_ep0[] = {
+struct ip6_route {
+ uint8_t ip[16];
+ uint8_t depth;
+ uint8_t if_out;
+};
+
+static struct ip4_route rt_ip4_ep0[] = {
+ /* Outbound */
+ /* Tunnels */
{ IPv4(172, 16, 2, 5), 32, 0 },
- { IPv4(172, 16, 2, 6), 32, 0 },
- { IPv4(172, 16, 2, 7), 32, 1 },
- { IPv4(172, 16, 2, 8), 32, 1 },
+ { IPv4(172, 16, 2, 6), 32, 1 },
+ /* Transport */
+ { IPv4(192, 168, 175, 0), 24, 0 },
+ { IPv4(192, 168, 176, 0), 24, 1 },
+ /* Bypass */
+ { IPv4(192, 168, 240, 0), 24, 0 },
+ { IPv4(192, 168, 241, 0), 24, 1 },
+ /* Inbound */
+ /* Tunnels */
{ IPv4(192, 168, 115, 0), 24, 2 },
- { IPv4(192, 168, 116, 0), 24, 2 },
- { IPv4(192, 168, 117, 0), 24, 3 },
- { IPv4(192, 168, 118, 0), 24, 3 },
-
+ { IPv4(192, 168, 116, 0), 24, 3 },
+ { IPv4(192, 168, 65, 0), 24, 2 },
+ { IPv4(192, 168, 66, 0), 24, 3 },
+ /* Transport */
+ { IPv4(192, 168, 185, 0), 24, 2 },
+ { IPv4(192, 168, 186, 0), 24, 3 },
+ /* NULL */
{ IPv4(192, 168, 210, 0), 24, 2 },
+ { IPv4(192, 168, 211, 0), 24, 3 },
+ /* Bypass */
+ { IPv4(192, 168, 245, 0), 24, 2 },
+ { IPv4(192, 168, 246, 0), 24, 3 },
+};
- { IPv4(192, 168, 240, 0), 24, 2 },
- { IPv4(192, 168, 250, 0), 24, 0 }
+static struct ip6_route rt_ip6_ep0[] = {
+ /* Outbound */
+ /* Tunnels */
+ { { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 }, 116, 0 },
+ { { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 }, 116, 1 },
+ /* Transport */
+ { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 0 },
+ { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 1 },
+ /* Inbound */
+ /* Tunnels */
+ { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
+ { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
+ { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
+ { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66,
+ 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
+ /* Transport */
+ { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
+ { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
};
-/* In the default routing table we have:
- * ep1 protected ports 0 and 1, and unprotected ports 2 and 3.
- */
-static struct ipv4_route rt_ipv4_ep1[] = {
- { IPv4(172, 16, 1, 5), 32, 2 },
- { IPv4(172, 16, 1, 6), 32, 2 },
- { IPv4(172, 16, 1, 7), 32, 3 },
- { IPv4(172, 16, 1, 8), 32, 3 },
+static struct ip4_route rt_ip4_ep1[] = {
+ /* Outbound */
+ /* Tunnels */
+ { IPv4(172, 16, 1, 5), 32, 0 },
+ { IPv4(172, 16, 1, 6), 32, 1 },
+ /* Transport */
+ { IPv4(192, 168, 185, 0), 24, 0 },
+ { IPv4(192, 168, 186, 0), 24, 1 },
+ /* Bypass */
+ { IPv4(192, 168, 245, 0), 24, 0 },
+ { IPv4(192, 168, 246, 0), 24, 1 },
- { IPv4(192, 168, 105, 0), 24, 0 },
- { IPv4(192, 168, 106, 0), 24, 0 },
- { IPv4(192, 168, 107, 0), 24, 1 },
- { IPv4(192, 168, 108, 0), 24, 1 },
+ /* Inbound */
+ /* Tunnels */
+ { IPv4(192, 168, 105, 0), 24, 2 },
+ { IPv4(192, 168, 106, 0), 24, 3 },
+ { IPv4(192, 168, 55, 0), 24, 2 },
+ { IPv4(192, 168, 56, 0), 24, 3 },
+ /* Transport */
+ { IPv4(192, 168, 175, 0), 24, 2 },
+ { IPv4(192, 168, 176, 0), 24, 3 },
+ /* NULL */
+ { IPv4(192, 168, 200, 0), 24, 2 },
+ { IPv4(192, 168, 201, 0), 24, 3 },
+ /* Bypass */
+ { IPv4(192, 168, 240, 0), 24, 2 },
+ { IPv4(192, 168, 241, 0), 24, 3 },
+};
- { IPv4(192, 168, 200, 0), 24, 0 },
+static struct ip6_route rt_ip6_ep1[] = {
+ /* Outbound */
+ /* Tunnels */
+ { { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 }, 116, 0 },
+ { { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 }, 116, 1 },
+ /* Transport */
+ { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 0 },
+ { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 1 },
- { IPv4(192, 168, 240, 0), 24, 2 },
- { IPv4(192, 168, 250, 0), 24, 0 }
+ /* Inbound */
+ /* Tunnels */
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66,
+ 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
+ /* Transport */
+ { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
+ { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
};
void
-rt_init(struct socket_ctx *ctx, int socket_id, unsigned ep)
+rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
{
char name[PATH_MAX];
- unsigned i;
- int ret;
+ uint32_t i;
+ int32_t ret;
struct rte_lpm *lpm;
- struct ipv4_route *rt;
+ struct rte_lpm6 *lpm6;
+ struct ip4_route *rt;
+ struct ip6_route *rt6;
char a, b, c, d;
- unsigned nb_routes;
+ uint32_t nb_routes, nb_routes6;
struct rte_lpm_config conf = { 0 };
+ struct rte_lpm6_config conf6 = { 0 };
if (ctx == NULL)
rte_exit(EXIT_FAILURE, "NULL context.\n");
- if (ctx->rt_ipv4 != NULL)
- rte_exit(EXIT_FAILURE, "Routing Table for socket %u already "
- "initialized\n", socket_id);
+ if (ctx->rt_ip4 != NULL)
+ rte_exit(EXIT_FAILURE, "IPv4 Routing Table for socket %u "
+ "already initialized\n", socket_id);
+
+ if (ctx->rt_ip6 != NULL)
+ rte_exit(EXIT_FAILURE, "IPv6 Routing Table for socket %u "
+ "already initialized\n", socket_id);
- printf("Creating Routing Table (RT) context with %u max routes\n",
+ printf("Creating IPv4 Routing Table (RT) context with %u max routes\n",
RT_IPV4_MAX_RULES);
if (ep == 0) {
- rt = rt_ipv4_ep0;
- nb_routes = RTE_DIM(rt_ipv4_ep0);
+ rt = rt_ip4_ep0;
+ nb_routes = RTE_DIM(rt_ip4_ep0);
+ rt6 = rt_ip6_ep0;
+ nb_routes6 = RTE_DIM(rt_ip6_ep0);
} else if (ep == 1) {
- rt = rt_ipv4_ep1;
- nb_routes = RTE_DIM(rt_ipv4_ep1);
+ rt = rt_ip4_ep1;
+ nb_routes = RTE_DIM(rt_ip4_ep1);
+ rt6 = rt_ip6_ep1;
+ nb_routes6 = RTE_DIM(rt_ip6_ep1);
} else
rte_exit(EXIT_FAILURE, "Invalid EP value %u. Only 0 or 1 "
"supported.\n", ep);
/* create the LPM table */
- snprintf(name, sizeof(name), "%s_%u", "rt_ipv4", socket_id);
+ snprintf(name, sizeof(name), "%s_%u", "rt_ip4", socket_id);
conf.max_rules = RT_IPV4_MAX_RULES;
conf.number_tbl8s = RTE_LPM_TBL8_NUM_ENTRIES;
lpm = rte_lpm_create(name, socket_id, &conf);
if (lpm == NULL)
- rte_exit(EXIT_FAILURE, "Unable to create LPM table "
- "on socket %d\n", socket_id);
+ rte_exit(EXIT_FAILURE, "Unable to create %s LPM table "
+ "on socket %d\n", name, socket_id);
/* populate the LPM table */
for (i = 0; i < nb_routes; i++) {
ret = rte_lpm_add(lpm, rt[i].ip, rt[i].depth, rt[i].if_out);
if (ret < 0)
- rte_exit(EXIT_FAILURE, "Unable to add entry num %u to "
- "LPM table on socket %d\n", i, socket_id);
+ rte_exit(EXIT_FAILURE, "Fail to add entry num %u to %s "
+ "LPM table on socket %d\n", i, name, socket_id);
uint32_t_to_char(rt[i].ip, &a, &b, &c, &d);
printf("LPM: Adding route %hhu.%hhu.%hhu.%hhu/%hhu (%hhu)\n",
a, b, c, d, rt[i].depth, rt[i].if_out);
}
- ctx->rt_ipv4 = (struct rt_ctx *)lpm;
+ snprintf(name, sizeof(name), "%s_%u", "rt_ip6", socket_id);
+ conf6.max_rules = RT_IPV6_MAX_RULES;
+ conf6.number_tbl8s = RTE_LPM_TBL8_NUM_ENTRIES;
+ lpm6 = rte_lpm6_create(name, socket_id, &conf6);
+ if (lpm6 == NULL)
+ rte_exit(EXIT_FAILURE, "Unable to create %s LPM table "
+ "on socket %d\n", name, socket_id);
+
+ /* populate the LPM table */
+ for (i = 0; i < nb_routes6; i++) {
+ ret = rte_lpm6_add(lpm6, rt6[i].ip, rt6[i].depth,
+ rt6[i].if_out);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Fail to add entry num %u to %s "
+ "LPM table on socket %d\n", i, name, socket_id);
+
+ printf("LPM6: Adding route "
+ " %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hhx (%hhx)\n",
+ (uint16_t)((rt6[i].ip[0] << 8) | rt6[i].ip[1]),
+ (uint16_t)((rt6[i].ip[2] << 8) | rt6[i].ip[3]),
+ (uint16_t)((rt6[i].ip[4] << 8) | rt6[i].ip[5]),
+ (uint16_t)((rt6[i].ip[6] << 8) | rt6[i].ip[7]),
+ (uint16_t)((rt6[i].ip[8] << 8) | rt6[i].ip[9]),
+ (uint16_t)((rt6[i].ip[10] << 8) | rt6[i].ip[11]),
+ (uint16_t)((rt6[i].ip[12] << 8) | rt6[i].ip[13]),
+ (uint16_t)((rt6[i].ip[14] << 8) | rt6[i].ip[15]),
+ rt6[i].depth, rt6[i].if_out);
+ }
+
+ ctx->rt_ip4 = (struct rt_ctx *)lpm;
+ ctx->rt_ip6 = (struct rt_ctx *)lpm6;
}
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index b6260ede..ab18b811 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -37,170 +37,200 @@
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <rte_memzone.h>
#include <rte_crypto.h>
#include <rte_cryptodev.h>
#include <rte_byteorder.h>
#include <rte_errno.h>
+#include <rte_ip.h>
#include "ipsec.h"
#include "esp.h"
-/* SAs EP0 Outbound */
-const struct ipsec_sa sa_ep0_out[] = {
- { 5, 0, IPv4(172, 16, 1, 5), IPv4(172, 16, 2, 5),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 6, 0, IPv4(172, 16, 1, 6), IPv4(172, 16, 2, 6),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 7, 0, IPv4(172, 16, 1, 7), IPv4(172, 16, 2, 7),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 8, 0, IPv4(172, 16, 1, 8), IPv4(172, 16, 2, 8),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 9, 0, IPv4(172, 16, 1, 5), IPv4(172, 16, 2, 5),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_NULL, RTE_CRYPTO_AUTH_NULL,
- 0, 0, 4,
- 0, 0 },
+/* SAs Outbound */
+const struct ipsec_sa sa_out[] = {
+ {
+ .spi = 5,
+ .src.ip4 = IPv4(172, 16, 1, 5),
+ .dst.ip4 = IPv4(172, 16, 2, 5),
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = IP4_TUNNEL
+ },
+ {
+ .spi = 6,
+ .src.ip4 = IPv4(172, 16, 1, 6),
+ .dst.ip4 = IPv4(172, 16, 2, 6),
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = IP4_TUNNEL
+ },
+ {
+ .spi = 10,
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = TRANSPORT
+ },
+ {
+ .spi = 11,
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = TRANSPORT
+ },
+ {
+ .spi = 15,
+ .src.ip4 = IPv4(172, 16, 1, 5),
+ .dst.ip4 = IPv4(172, 16, 2, 5),
+ .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .digest_len = 0,
+ .iv_len = 0,
+ .block_size = 4,
+ .flags = IP4_TUNNEL
+ },
+ {
+ .spi = 16,
+ .src.ip4 = IPv4(172, 16, 1, 6),
+ .dst.ip4 = IPv4(172, 16, 2, 6),
+ .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .digest_len = 0,
+ .iv_len = 0,
+ .block_size = 4,
+ .flags = IP4_TUNNEL
+ },
+ {
+ .spi = 25,
+ .src.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 },
+ .dst.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 },
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = IP6_TUNNEL
+ },
+ {
+ .spi = 26,
+ .src.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 },
+ .dst.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 },
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = IP6_TUNNEL
+ },
};
-/* SAs EP0 Inbound */
-const struct ipsec_sa sa_ep0_in[] = {
- { 5, 0, IPv4(172, 16, 2, 5), IPv4(172, 16, 1, 5),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 6, 0, IPv4(172, 16, 2, 6), IPv4(172, 16, 1, 6),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 7, 0, IPv4(172, 16, 2, 7), IPv4(172, 16, 1, 7),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 8, 0, IPv4(172, 16, 2, 8), IPv4(172, 16, 1, 8),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 9, 0, IPv4(172, 16, 2, 5), IPv4(172, 16, 1, 5),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_NULL, RTE_CRYPTO_AUTH_NULL,
- 0, 0, 4,
- 0, 0 },
-};
-
-/* SAs EP1 Outbound */
-const struct ipsec_sa sa_ep1_out[] = {
- { 5, 0, IPv4(172, 16, 2, 5), IPv4(172, 16, 1, 5),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 6, 0, IPv4(172, 16, 2, 6), IPv4(172, 16, 1, 6),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 7, 0, IPv4(172, 16, 2, 7), IPv4(172, 16, 1, 7),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 8, 0, IPv4(172, 16, 2, 8), IPv4(172, 16, 1, 8),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 9, 0, IPv4(172, 16, 2, 5), IPv4(172, 16, 1, 5),
- NULL, NULL,
- esp4_tunnel_outbound_pre_crypto,
- esp4_tunnel_outbound_post_crypto,
- RTE_CRYPTO_CIPHER_NULL, RTE_CRYPTO_AUTH_NULL,
- 0, 0, 4,
- 0, 0 },
-};
-
-/* SAs EP1 Inbound */
-const struct ipsec_sa sa_ep1_in[] = {
- { 5, 0, IPv4(172, 16, 1, 5), IPv4(172, 16, 2, 5),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 6, 0, IPv4(172, 16, 1, 6), IPv4(172, 16, 2, 6),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 7, 0, IPv4(172, 16, 1, 7), IPv4(172, 16, 2, 7),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 8, 0, IPv4(172, 16, 1, 8), IPv4(172, 16, 2, 8),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_AES_CBC, RTE_CRYPTO_AUTH_SHA1_HMAC,
- 12, 16, 16,
- 0, 0 },
- { 9, 0, IPv4(172, 16, 1, 5), IPv4(172, 16, 2, 5),
- NULL, NULL,
- esp4_tunnel_inbound_pre_crypto,
- esp4_tunnel_inbound_post_crypto,
- RTE_CRYPTO_CIPHER_NULL, RTE_CRYPTO_AUTH_NULL,
- 0, 0, 4,
- 0, 0 },
+/* SAs Inbound */
+const struct ipsec_sa sa_in[] = {
+ {
+ .spi = 105,
+ .src.ip4 = IPv4(172, 16, 2, 5),
+ .dst.ip4 = IPv4(172, 16, 1, 5),
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = IP4_TUNNEL
+ },
+ {
+ .spi = 106,
+ .src.ip4 = IPv4(172, 16, 2, 6),
+ .dst.ip4 = IPv4(172, 16, 1, 6),
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = IP4_TUNNEL
+ },
+ {
+ .spi = 110,
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = TRANSPORT
+ },
+ {
+ .spi = 111,
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = TRANSPORT
+ },
+ {
+ .spi = 115,
+ .src.ip4 = IPv4(172, 16, 2, 5),
+ .dst.ip4 = IPv4(172, 16, 1, 5),
+ .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .digest_len = 0,
+ .iv_len = 0,
+ .block_size = 4,
+ .flags = IP4_TUNNEL
+ },
+ {
+ .spi = 116,
+ .src.ip4 = IPv4(172, 16, 2, 6),
+ .dst.ip4 = IPv4(172, 16, 1, 6),
+ .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .digest_len = 0,
+ .iv_len = 0,
+ .block_size = 4,
+ .flags = IP4_TUNNEL
+ },
+ {
+ .spi = 125,
+ .src.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 },
+ .dst.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 },
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = IP6_TUNNEL
+ },
+ {
+ .spi = 126,
+ .src.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 },
+ .dst.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 },
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .iv_len = 16,
+ .block_size = 16,
+ .flags = IP6_TUNNEL
+ },
};
static uint8_t cipher_key[256] = "sixteenbytes key";
@@ -265,11 +295,11 @@ struct sa_ctx {
};
static struct sa_ctx *
-sa_ipv4_create(const char *name, int socket_id)
+sa_create(const char *name, int32_t socket_id)
{
char s[PATH_MAX];
struct sa_ctx *sa_ctx;
- unsigned mz_size;
+ uint32_t mz_size;
const struct rte_memzone *mz;
snprintf(s, sizeof(s), "%s_%u", name, socket_id);
@@ -294,10 +324,10 @@ sa_ipv4_create(const char *name, int socket_id)
static int
sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
- unsigned nb_entries, unsigned inbound)
+ uint32_t nb_entries, uint32_t inbound)
{
struct ipsec_sa *sa;
- unsigned i, idx;
+ uint32_t i, idx;
for (i = 0; i < nb_entries; i++) {
idx = SPI2IDX(entries[i].spi);
@@ -308,8 +338,14 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
return -EINVAL;
}
*sa = entries[i];
- sa->src = rte_cpu_to_be_32(sa->src);
- sa->dst = rte_cpu_to_be_32(sa->dst);
+ sa->seq = 0;
+
+ switch (sa->flags) {
+ case IP4_TUNNEL:
+ sa->src.ip4 = rte_cpu_to_be_32(sa->src.ip4);
+ sa->dst.ip4 = rte_cpu_to_be_32(sa->dst.ip4);
+ }
+
if (inbound) {
if (sa->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
sa_ctx->xf[idx].a = null_auth_xf;
@@ -337,65 +373,65 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
static inline int
sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
- unsigned nb_entries)
+ uint32_t nb_entries)
{
return sa_add_rules(sa_ctx, entries, nb_entries, 0);
}
static inline int
sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
- unsigned nb_entries)
+ uint32_t nb_entries)
{
return sa_add_rules(sa_ctx, entries, nb_entries, 1);
}
void
-sa_init(struct socket_ctx *ctx, int socket_id, unsigned ep)
+sa_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
{
const struct ipsec_sa *sa_out_entries, *sa_in_entries;
- unsigned nb_out_entries, nb_in_entries;
+ uint32_t nb_out_entries, nb_in_entries;
const char *name;
if (ctx == NULL)
rte_exit(EXIT_FAILURE, "NULL context.\n");
- if (ctx->sa_ipv4_in != NULL)
+ if (ctx->sa_in != NULL)
rte_exit(EXIT_FAILURE, "Inbound SA DB for socket %u already "
"initialized\n", socket_id);
- if (ctx->sa_ipv4_out != NULL)
+ if (ctx->sa_out != NULL)
rte_exit(EXIT_FAILURE, "Outbound SA DB for socket %u already "
"initialized\n", socket_id);
if (ep == 0) {
- sa_out_entries = sa_ep0_out;
- nb_out_entries = RTE_DIM(sa_ep0_out);
- sa_in_entries = sa_ep0_in;
- nb_in_entries = RTE_DIM(sa_ep0_in);
+ sa_out_entries = sa_out;
+ nb_out_entries = RTE_DIM(sa_out);
+ sa_in_entries = sa_in;
+ nb_in_entries = RTE_DIM(sa_in);
} else if (ep == 1) {
- sa_out_entries = sa_ep1_out;
- nb_out_entries = RTE_DIM(sa_ep1_out);
- sa_in_entries = sa_ep1_in;
- nb_in_entries = RTE_DIM(sa_ep1_in);
+ sa_out_entries = sa_in;
+ nb_out_entries = RTE_DIM(sa_in);
+ sa_in_entries = sa_out;
+ nb_in_entries = RTE_DIM(sa_out);
} else
rte_exit(EXIT_FAILURE, "Invalid EP value %u. "
"Only 0 or 1 supported.\n", ep);
- name = "sa_ipv4_in";
- ctx->sa_ipv4_in = sa_ipv4_create(name, socket_id);
- if (ctx->sa_ipv4_in == NULL)
+ name = "sa_in";
+ ctx->sa_in = sa_create(name, socket_id);
+ if (ctx->sa_in == NULL)
rte_exit(EXIT_FAILURE, "Error [%d] creating SA context %s "
"in socket %d\n", rte_errno, name, socket_id);
- name = "sa_ipv4_out";
- ctx->sa_ipv4_out = sa_ipv4_create(name, socket_id);
- if (ctx->sa_ipv4_out == NULL)
+ name = "sa_out";
+ ctx->sa_out = sa_create(name, socket_id);
+ if (ctx->sa_out == NULL)
rte_exit(EXIT_FAILURE, "Error [%d] creating SA context %s "
"in socket %d\n", rte_errno, name, socket_id);
- sa_in_add_rules(ctx->sa_ipv4_in, sa_in_entries, nb_in_entries);
+ sa_in_add_rules(ctx->sa_in, sa_in_entries, nb_in_entries);
- sa_out_add_rules(ctx->sa_ipv4_out, sa_out_entries, nb_out_entries);
+ sa_out_add_rules(ctx->sa_out, sa_out_entries, nb_out_entries);
}
int
@@ -408,38 +444,66 @@ inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx)
return (sa_ctx->sa[sa_idx].spi == priv->sa->spi);
}
+static inline void
+single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,
+ struct ipsec_sa **sa_ret)
+{
+ struct esp_hdr *esp;
+ struct ip *ip;
+ uint32_t *src4_addr;
+ uint8_t *src6_addr;
+ struct ipsec_sa *sa;
+
+ *sa_ret = NULL;
+
+ ip = rte_pktmbuf_mtod(pkt, struct ip *);
+ if (ip->ip_v == IPVERSION)
+ esp = (struct esp_hdr *)(ip + 1);
+ else
+ esp = (struct esp_hdr *)(((struct ip6_hdr *)ip) + 1);
+
+ if (esp->spi == INVALID_SPI)
+ return;
+
+ sa = &sadb[SPI2IDX(rte_be_to_cpu_32(esp->spi))];
+ if (rte_be_to_cpu_32(esp->spi) != sa->spi)
+ return;
+
+ switch (sa->flags) {
+ case IP4_TUNNEL:
+ src4_addr = RTE_PTR_ADD(ip, offsetof(struct ip, ip_src));
+ if ((ip->ip_v == IPVERSION) &&
+ (sa->src.ip4 == *src4_addr) &&
+ (sa->dst.ip4 == *(src4_addr + 1)))
+ *sa_ret = sa;
+ break;
+ case IP6_TUNNEL:
+ src6_addr = RTE_PTR_ADD(ip, offsetof(struct ip6_hdr, ip6_src));
+ if ((ip->ip_v == IP6_VERSION) &&
+ !memcmp(&sa->src.ip6, src6_addr, 16) &&
+ !memcmp(&sa->dst.ip6, src6_addr + 16, 16))
+ *sa_ret = sa;
+ break;
+ case TRANSPORT:
+ *sa_ret = sa;
+ }
+}
+
void
inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
struct ipsec_sa *sa[], uint16_t nb_pkts)
{
- unsigned i;
- uint32_t *src, spi;
-
- for (i = 0; i < nb_pkts; i++) {
- spi = rte_pktmbuf_mtod_offset(pkts[i], struct esp_hdr *,
- sizeof(struct ip))->spi;
-
- if (spi == INVALID_SPI)
- continue;
+ uint32_t i;
- sa[i] = &sa_ctx->sa[SPI2IDX(spi)];
- if (spi != sa[i]->spi) {
- sa[i] = NULL;
- continue;
- }
-
- src = rte_pktmbuf_mtod_offset(pkts[i], uint32_t *,
- offsetof(struct ip, ip_src));
- if ((sa[i]->src != *src) || (sa[i]->dst != *(src + 1)))
- sa[i] = NULL;
- }
+ for (i = 0; i < nb_pkts; i++)
+ single_inbound_lookup(sa_ctx->sa, pkts[i], &sa[i]);
}
void
outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
struct ipsec_sa *sa[], uint16_t nb_pkts)
{
- unsigned i;
+ uint32_t i;
for (i = 0; i < nb_pkts; i++)
sa[i] = &sa_ctx->sa[sa_idx[i]];
diff --git a/examples/ipsec-secgw/sp.c b/examples/ipsec-secgw/sp4.c
index 4f167301..9c4b256b 100644
--- a/examples/ipsec-secgw/sp.c
+++ b/examples/ipsec-secgw/sp4.c
@@ -39,6 +39,7 @@
#include <netinet/ip.h>
#include <rte_acl.h>
+#include <rte_ip.h>
#include "ipsec.h"
@@ -71,7 +72,7 @@ enum {
RTE_ACL_IPV4_NUM
};
-struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
+struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = {
{
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint8_t),
@@ -110,9 +111,9 @@ struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
},
};
-RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ipv4_defs));
+RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs));
-const struct acl4_rules acl4_rules_in[] = {
+const struct acl4_rules acl4_rules_out[] = {
{
.data = {.userdata = PROTECT(5), .category_mask = 1, .priority = 1},
/* destination IPv4 */
@@ -124,7 +125,7 @@ const struct acl4_rules acl4_rules_in[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 2},
+ .data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 1},
/* destination IPv4 */
.field[2] = {.value.u32 = IPv4(192, 168, 106, 0),
.mask_range.u32 = 24,},
@@ -134,9 +135,9 @@ const struct acl4_rules acl4_rules_in[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = PROTECT(7), .category_mask = 1, .priority = 3},
+ .data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1},
/* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 107, 0),
+ .field[2] = {.value.u32 = IPv4(192, 168, 175, 0),
.mask_range.u32 = 24,},
/* source port */
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
@@ -144,9 +145,9 @@ const struct acl4_rules acl4_rules_in[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = PROTECT(8), .category_mask = 1, .priority = 4},
+ .data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1},
/* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 108, 0),
+ .field[2] = {.value.u32 = IPv4(192, 168, 176, 0),
.mask_range.u32 = 24,},
/* source port */
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
@@ -154,7 +155,7 @@ const struct acl4_rules acl4_rules_in[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = PROTECT(9), .category_mask = 1, .priority = 5},
+ .data = {.userdata = PROTECT(15), .category_mask = 1, .priority = 1},
/* destination IPv4 */
.field[2] = {.value.u32 = IPv4(192, 168, 200, 0),
.mask_range.u32 = 24,},
@@ -164,9 +165,49 @@ const struct acl4_rules acl4_rules_in[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = BYPASS, .category_mask = 1, .priority = 6},
+ .data = {.userdata = PROTECT(16), .category_mask = 1, .priority = 1},
/* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 250, 0),
+ .field[2] = {.value.u32 = IPv4(192, 168, 201, 0),
+ .mask_range.u32 = 24,},
+ /* source port */
+ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(25), .category_mask = 1, .priority = 1},
+ /* destination IPv4 */
+ .field[2] = {.value.u32 = IPv4(192, 168, 55, 0),
+ .mask_range.u32 = 24,},
+ /* source port */
+ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(26), .category_mask = 1, .priority = 1},
+ /* destination IPv4 */
+ .field[2] = {.value.u32 = IPv4(192, 168, 56, 0),
+ .mask_range.u32 = 24,},
+ /* source port */
+ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
+ /* destination IPv4 */
+ .field[2] = {.value.u32 = IPv4(192, 168, 240, 0),
+ .mask_range.u32 = 24,},
+ /* source port */
+ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
+ /* destination IPv4 */
+ .field[2] = {.value.u32 = IPv4(192, 168, 241, 0),
.mask_range.u32 = 24,},
/* source port */
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
@@ -175,9 +216,9 @@ const struct acl4_rules acl4_rules_in[] = {
}
};
-const struct acl4_rules acl4_rules_out[] = {
+const struct acl4_rules acl4_rules_in[] = {
{
- .data = {.userdata = PROTECT(5), .category_mask = 1, .priority = 1},
+ .data = {.userdata = PROTECT(105), .category_mask = 1, .priority = 1},
/* destination IPv4 */
.field[2] = {.value.u32 = IPv4(192, 168, 115, 0),
.mask_range.u32 = 24,},
@@ -187,7 +228,7 @@ const struct acl4_rules acl4_rules_out[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 2},
+ .data = {.userdata = PROTECT(106), .category_mask = 1, .priority = 1},
/* destination IPv4 */
.field[2] = {.value.u32 = IPv4(192, 168, 116, 0),
.mask_range.u32 = 24,},
@@ -197,9 +238,9 @@ const struct acl4_rules acl4_rules_out[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = PROTECT(7), .category_mask = 1, .priority = 3},
+ .data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1},
/* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 117, 0),
+ .field[2] = {.value.u32 = IPv4(192, 168, 185, 0),
.mask_range.u32 = 24,},
/* source port */
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
@@ -207,9 +248,9 @@ const struct acl4_rules acl4_rules_out[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = PROTECT(8), .category_mask = 1, .priority = 4},
+ .data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1},
/* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 118, 0),
+ .field[2] = {.value.u32 = IPv4(192, 168, 186, 0),
.mask_range.u32 = 24,},
/* source port */
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
@@ -217,7 +258,7 @@ const struct acl4_rules acl4_rules_out[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = PROTECT(9), .category_mask = 1, .priority = 5},
+ .data = {.userdata = PROTECT(115), .category_mask = 1, .priority = 1},
/* destination IPv4 */
.field[2] = {.value.u32 = IPv4(192, 168, 210, 0),
.mask_range.u32 = 24,},
@@ -227,9 +268,49 @@ const struct acl4_rules acl4_rules_out[] = {
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
},
{
- .data = {.userdata = BYPASS, .category_mask = 1, .priority = 6},
+ .data = {.userdata = PROTECT(116), .category_mask = 1, .priority = 1},
/* destination IPv4 */
- .field[2] = {.value.u32 = IPv4(192, 168, 240, 0),
+ .field[2] = {.value.u32 = IPv4(192, 168, 211, 0),
+ .mask_range.u32 = 24,},
+ /* source port */
+ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(125), .category_mask = 1, .priority = 1},
+ /* destination IPv4 */
+ .field[2] = {.value.u32 = IPv4(192, 168, 65, 0),
+ .mask_range.u32 = 24,},
+ /* source port */
+ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(126), .category_mask = 1, .priority = 1},
+ /* destination IPv4 */
+ .field[2] = {.value.u32 = IPv4(192, 168, 66, 0),
+ .mask_range.u32 = 24,},
+ /* source port */
+ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
+ /* destination IPv4 */
+ .field[2] = {.value.u32 = IPv4(192, 168, 245, 0),
+ .mask_range.u32 = 24,},
+ /* source port */
+ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
+ /* destination IPv4 */
+ .field[2] = {.value.u32 = IPv4(192, 168, 246, 0),
.mask_range.u32 = 24,},
/* source port */
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
@@ -239,9 +320,9 @@ const struct acl4_rules acl4_rules_out[] = {
};
static void
-print_one_ipv4_rule(const struct acl4_rules *rule, int extra)
+print_one_ip4_rule(const struct acl4_rules *rule, int32_t extra)
{
- unsigned char a, b, c, d;
+ uint8_t a, b, c, d;
uint32_t_to_char(rule->field[SRC_FIELD_IPV4].value.u32,
&a, &b, &c, &d);
@@ -266,20 +347,20 @@ print_one_ipv4_rule(const struct acl4_rules *rule, int extra)
}
static inline void
-dump_ipv4_rules(const struct acl4_rules *rule, int num, int extra)
+dump_ip4_rules(const struct acl4_rules *rule, int32_t num, int32_t extra)
{
- int i;
+ int32_t i;
for (i = 0; i < num; i++, rule++) {
printf("\t%d:", i + 1);
- print_one_ipv4_rule(rule, extra);
+ print_one_ip4_rule(rule, extra);
printf("\n");
}
}
static struct rte_acl_ctx *
-acl4_init(const char *name, int socketid, const struct acl4_rules *rules,
- unsigned rules_nb)
+acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
+ uint32_t rules_nb)
{
char s[PATH_MAX];
struct rte_acl_param acl_param;
@@ -294,11 +375,11 @@ acl4_init(const char *name, int socketid, const struct acl4_rules *rules,
snprintf(s, sizeof(s), "%s_%d", name, socketid);
printf("IPv4 %s entries [%u]:\n", s, rules_nb);
- dump_ipv4_rules(rules, rules_nb, 1);
+ dump_ip4_rules(rules, rules_nb, 1);
acl_param.name = s;
acl_param.socket_id = socketid;
- acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ipv4_defs));
+ acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip4_defs));
acl_param.max_rule_num = MAX_ACL_RULE_NUM;
ctx = rte_acl_create(&acl_param);
@@ -313,8 +394,8 @@ acl4_init(const char *name, int socketid, const struct acl4_rules *rules,
memset(&acl_build_param, 0, sizeof(acl_build_param));
acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;
- acl_build_param.num_fields = RTE_DIM(ipv4_defs);
- memcpy(&acl_build_param.defs, ipv4_defs, sizeof(ipv4_defs));
+ acl_build_param.num_fields = RTE_DIM(ip4_defs);
+ memcpy(&acl_build_param.defs, ip4_defs, sizeof(ip4_defs));
if (rte_acl_build(ctx, &acl_build_param) != 0)
rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n");
@@ -325,42 +406,42 @@ acl4_init(const char *name, int socketid, const struct acl4_rules *rules,
}
void
-sp_init(struct socket_ctx *ctx, int socket_id, unsigned ep)
+sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
{
const char *name;
const struct acl4_rules *rules_out, *rules_in;
- unsigned nb_out_rules, nb_in_rules;
+ uint32_t nb_out_rules, nb_in_rules;
if (ctx == NULL)
rte_exit(EXIT_FAILURE, "NULL context.\n");
- if (ctx->sp_ipv4_in != NULL)
+ if (ctx->sp_ip4_in != NULL)
rte_exit(EXIT_FAILURE, "Inbound SP DB for socket %u already "
"initialized\n", socket_id);
- if (ctx->sp_ipv4_out != NULL)
+ if (ctx->sp_ip4_out != NULL)
rte_exit(EXIT_FAILURE, "Outbound SP DB for socket %u already "
"initialized\n", socket_id);
if (ep == 0) {
- rules_out = acl4_rules_in;
- nb_out_rules = RTE_DIM(acl4_rules_in);
- rules_in = acl4_rules_out;
- nb_in_rules = RTE_DIM(acl4_rules_out);
- } else if (ep == 1) {
rules_out = acl4_rules_out;
nb_out_rules = RTE_DIM(acl4_rules_out);
rules_in = acl4_rules_in;
nb_in_rules = RTE_DIM(acl4_rules_in);
+ } else if (ep == 1) {
+ rules_out = acl4_rules_in;
+ nb_out_rules = RTE_DIM(acl4_rules_in);
+ rules_in = acl4_rules_out;
+ nb_in_rules = RTE_DIM(acl4_rules_out);
} else
rte_exit(EXIT_FAILURE, "Invalid EP value %u. "
"Only 0 or 1 supported.\n", ep);
- name = "sp_ipv4_in";
- ctx->sp_ipv4_in = (struct sp_ctx *)acl4_init(name, socket_id,
+ name = "sp_ip4_in";
+ ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name, socket_id,
rules_in, nb_in_rules);
- name = "sp_ipv4_out";
- ctx->sp_ipv4_out = (struct sp_ctx *)acl4_init(name, socket_id,
+ name = "sp_ip4_out";
+ ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name, socket_id,
rules_out, nb_out_rules);
}
diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c
new file mode 100644
index 00000000..1dda11a4
--- /dev/null
+++ b/examples/ipsec-secgw/sp6.c
@@ -0,0 +1,448 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Security Policies
+ */
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+
+#include <rte_acl.h>
+#include <rte_ip.h>
+
+#include "ipsec.h"
+
+#define MAX_ACL_RULE_NUM 1000
+
+enum {
+ IP6_PROTO,
+ IP6_SRC0,
+ IP6_SRC1,
+ IP6_SRC2,
+ IP6_SRC3,
+ IP6_DST0,
+ IP6_DST1,
+ IP6_DST2,
+ IP6_DST3,
+ IP6_SRCP,
+ IP6_DSTP,
+ IP6_NUM
+};
+
+#define IP6_ADDR_SIZE 16
+
+struct rte_acl_field_def ip6_defs[IP6_NUM] = {
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = IP6_PROTO,
+ .input_index = IP6_PROTO,
+ .offset = 0,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = 4,
+ .field_index = IP6_SRC0,
+ .input_index = IP6_SRC0,
+ .offset = 2
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = 4,
+ .field_index = IP6_SRC1,
+ .input_index = IP6_SRC1,
+ .offset = 6
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = 4,
+ .field_index = IP6_SRC2,
+ .input_index = IP6_SRC2,
+ .offset = 10
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = 4,
+ .field_index = IP6_SRC3,
+ .input_index = IP6_SRC3,
+ .offset = 14
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = 4,
+ .field_index = IP6_DST0,
+ .input_index = IP6_DST0,
+ .offset = 18
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = 4,
+ .field_index = IP6_DST1,
+ .input_index = IP6_DST1,
+ .offset = 22
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = 4,
+ .field_index = IP6_DST2,
+ .input_index = IP6_DST2,
+ .offset = 26
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = 4,
+ .field_index = IP6_DST3,
+ .input_index = IP6_DST3,
+ .offset = 30
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = IP6_SRCP,
+ .input_index = IP6_SRCP,
+ .offset = 34
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = IP6_DSTP,
+ .input_index = IP6_SRCP,
+ .offset = 36
+ }
+};
+
+RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
+
+const struct acl6_rules acl6_rules_out[] = {
+ {
+ .data = {.userdata = PROTECT(5), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0x55555555, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0x66666666, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(25), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0xaaaaaaaa, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(26), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0xbbbbbbbb, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ }
+};
+
+const struct acl6_rules acl6_rules_in[] = {
+ {
+ .data = {.userdata = PROTECT(15), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0x55555555, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(16), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0x66666666, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(125), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0xaaaaaaaa, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ },
+ {
+ .data = {.userdata = PROTECT(126), .category_mask = 1, .priority = 1},
+ /* destination IPv6 */
+ .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
+ .field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
+ .field[7] = {.value.u32 = 0xbbbbbbbb, .mask_range.u32 = 32,},
+ .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
+ /* source port */
+ .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
+ /* destination port */
+ .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
+ }
+};
+
+static inline void
+print_one_ip6_rule(const struct acl6_rules *rule, int32_t extra)
+{
+ uint8_t a, b, c, d;
+
+ uint32_t_to_char(rule->field[IP6_SRC0].value.u32,
+ &a, &b, &c, &d);
+ printf("%.2x%.2x:%.2x%.2x", a, b, c, d);
+ uint32_t_to_char(rule->field[IP6_SRC1].value.u32,
+ &a, &b, &c, &d);
+ printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
+ uint32_t_to_char(rule->field[IP6_SRC2].value.u32,
+ &a, &b, &c, &d);
+ printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
+ uint32_t_to_char(rule->field[IP6_SRC3].value.u32,
+ &a, &b, &c, &d);
+ printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d,
+ rule->field[IP6_SRC0].mask_range.u32
+ + rule->field[IP6_SRC1].mask_range.u32
+ + rule->field[IP6_SRC2].mask_range.u32
+ + rule->field[IP6_SRC3].mask_range.u32);
+
+ uint32_t_to_char(rule->field[IP6_DST0].value.u32,
+ &a, &b, &c, &d);
+ printf("%.2x%.2x:%.2x%.2x", a, b, c, d);
+ uint32_t_to_char(rule->field[IP6_DST1].value.u32,
+ &a, &b, &c, &d);
+ printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
+ uint32_t_to_char(rule->field[IP6_DST2].value.u32,
+ &a, &b, &c, &d);
+ printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
+ uint32_t_to_char(rule->field[IP6_DST3].value.u32,
+ &a, &b, &c, &d);
+ printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d,
+ rule->field[IP6_DST0].mask_range.u32
+ + rule->field[IP6_DST1].mask_range.u32
+ + rule->field[IP6_DST2].mask_range.u32
+ + rule->field[IP6_DST3].mask_range.u32);
+
+ printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ",
+ rule->field[IP6_SRCP].value.u16,
+ rule->field[IP6_SRCP].mask_range.u16,
+ rule->field[IP6_DSTP].value.u16,
+ rule->field[IP6_DSTP].mask_range.u16,
+ rule->field[IP6_PROTO].value.u8,
+ rule->field[IP6_PROTO].mask_range.u8);
+ if (extra)
+ printf("0x%x-0x%x-0x%x ",
+ rule->data.category_mask,
+ rule->data.priority,
+ rule->data.userdata);
+}
+
+static inline void
+dump_ip6_rules(const struct acl6_rules *rule, int32_t num, int32_t extra)
+{
+ int32_t i;
+
+ for (i = 0; i < num; i++, rule++) {
+ printf("\t%d:", i + 1);
+ print_one_ip6_rule(rule, extra);
+ printf("\n");
+ }
+}
+
+static struct rte_acl_ctx *
+acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
+ uint32_t rules_nb)
+{
+ char s[PATH_MAX];
+ struct rte_acl_param acl_param;
+ struct rte_acl_config acl_build_param;
+ struct rte_acl_ctx *ctx;
+
+ printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
+
+ memset(&acl_param, 0, sizeof(acl_param));
+
+ /* Create ACL contexts */
+ snprintf(s, sizeof(s), "%s_%d", name, socketid);
+
+ printf("IPv4 %s entries [%u]:\n", s, rules_nb);
+ dump_ip6_rules(rules, rules_nb, 1);
+
+ acl_param.name = s;
+ acl_param.socket_id = socketid;
+ acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs));
+ acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+
+ ctx = rte_acl_create(&acl_param);
+ if (ctx == NULL)
+ rte_exit(EXIT_FAILURE, "Failed to create ACL context\n");
+
+ if (rte_acl_add_rules(ctx, (const struct rte_acl_rule *)rules,
+ rules_nb) < 0)
+ rte_exit(EXIT_FAILURE, "add rules failed\n");
+
+ /* Perform builds */
+ memset(&acl_build_param, 0, sizeof(acl_build_param));
+
+ acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;
+ acl_build_param.num_fields = RTE_DIM(ip6_defs);
+ memcpy(&acl_build_param.defs, ip6_defs, sizeof(ip6_defs));
+
+ if (rte_acl_build(ctx, &acl_build_param) != 0)
+ rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n");
+
+ rte_acl_dump(ctx);
+
+ return ctx;
+}
+
+void
+sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
+{
+ const char *name;
+ const struct acl6_rules *rules_out, *rules_in;
+ uint32_t nb_out_rules, nb_in_rules;
+
+ if (ctx == NULL)
+ rte_exit(EXIT_FAILURE, "NULL context.\n");
+
+ if (ctx->sp_ip6_in != NULL)
+ rte_exit(EXIT_FAILURE, "Inbound IPv6 SP DB for socket %u "
+ "already initialized\n", socket_id);
+
+ if (ctx->sp_ip6_out != NULL)
+ rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
+ "already initialized\n", socket_id);
+
+ if (ep == 0) {
+ rules_out = acl6_rules_out;
+ nb_out_rules = RTE_DIM(acl6_rules_out);
+ rules_in = acl6_rules_in;
+ nb_in_rules = RTE_DIM(acl6_rules_in);
+ } else if (ep == 1) {
+ rules_out = acl6_rules_in;
+ nb_out_rules = RTE_DIM(acl6_rules_in);
+ rules_in = acl6_rules_out;
+ nb_in_rules = RTE_DIM(acl6_rules_out);
+ } else
+ rte_exit(EXIT_FAILURE, "Invalid EP value %u. "
+ "Only 0 or 1 supported.\n", ep);
+
+ name = "sp_ip6_in";
+ ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name, socket_id,
+ rules_in, nb_in_rules);
+
+ name = "sp_ip6_out";
+ ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name, socket_id,
+ rules_out, nb_out_rules);
+}
diff --git a/examples/ipv4_multicast/main.c b/examples/ipv4_multicast/main.c
index 96b41578..f013d927 100644
--- a/examples/ipv4_multicast/main.c
+++ b/examples/ipv4_multicast/main.c
@@ -321,7 +321,7 @@ mcast_send_pkt(struct rte_mbuf *pkt, struct ether_addr *dest_addr,
/* Construct Ethernet header. */
ethdr = (struct ether_hdr *)rte_pktmbuf_prepend(pkt, (uint16_t)sizeof(*ethdr));
- RTE_MBUF_ASSERT(ethdr != NULL);
+ RTE_ASSERT(ethdr != NULL);
ether_addr_copy(dest_addr, &ethdr->d_addr);
ether_addr_copy(&ports_eth_addr[port], &ethdr->s_addr);
@@ -353,7 +353,7 @@ mcast_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf)
/* Remove the Ethernet header from the input packet */
iphdr = (struct ipv4_hdr *)rte_pktmbuf_adj(m, (uint16_t)sizeof(struct ether_hdr));
- RTE_MBUF_ASSERT(iphdr != NULL);
+ RTE_ASSERT(iphdr != NULL);
dest_addr = rte_be_to_cpu_32(iphdr->dst_addr);
diff --git a/examples/kni/main.c b/examples/kni/main.c
index a5297f28..f9fc61e0 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -318,8 +318,6 @@ main_loop(__rte_unused void *arg)
};
enum lcore_rxtx flag = LCORE_NONE;
- nb_ports = (uint8_t)(nb_ports < RTE_MAX_ETHPORTS ?
- nb_ports : RTE_MAX_ETHPORTS);
for (i = 0; i < nb_ports; i++) {
if (!kni_port_params_array[i])
continue;
@@ -831,7 +829,8 @@ kni_free_kni(uint8_t port_id)
return -1;
for (i = 0; i < p[port_id]->nb_kni; i++) {
- rte_kni_release(p[port_id]->kni[i]);
+ if (rte_kni_release(p[port_id]->kni[i]))
+ printf("Fail to release kni\n");
p[port_id]->kni[i] = NULL;
}
rte_eth_dev_stop(port_id);
diff --git a/examples/l2fwd-crypto/main.c b/examples/l2fwd-crypto/main.c
index d4e2d8de..8dc616d4 100644
--- a/examples/l2fwd-crypto/main.c
+++ b/examples/l2fwd-crypto/main.c
@@ -341,20 +341,25 @@ fill_supported_algorithm_tables(void)
strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_AES_GCM], "AES_GCM");
strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_MD5_HMAC], "MD5_HMAC");
strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_NULL], "NULL");
+ strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_AES_XCBC_MAC],
+ "AES_XCBC_MAC");
strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_SHA1_HMAC], "SHA1_HMAC");
strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_SHA224_HMAC], "SHA224_HMAC");
strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_SHA256_HMAC], "SHA256_HMAC");
strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_SHA384_HMAC], "SHA384_HMAC");
strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_SHA512_HMAC], "SHA512_HMAC");
strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_SNOW3G_UIA2], "SNOW3G_UIA2");
+ strcpy(supported_auth_algo[RTE_CRYPTO_AUTH_KASUMI_F9], "KASUMI_F9");
for (i = 0; i < RTE_CRYPTO_CIPHER_LIST_END; i++)
strcpy(supported_cipher_algo[i], "NOT_SUPPORTED");
strcpy(supported_cipher_algo[RTE_CRYPTO_CIPHER_AES_CBC], "AES_CBC");
+ strcpy(supported_cipher_algo[RTE_CRYPTO_CIPHER_AES_CTR], "AES_CTR");
strcpy(supported_cipher_algo[RTE_CRYPTO_CIPHER_AES_GCM], "AES_GCM");
strcpy(supported_cipher_algo[RTE_CRYPTO_CIPHER_NULL], "NULL");
strcpy(supported_cipher_algo[RTE_CRYPTO_CIPHER_SNOW3G_UEA2], "SNOW3G_UEA2");
+ strcpy(supported_cipher_algo[RTE_CRYPTO_CIPHER_KASUMI_F8], "KASUMI_F8");
}
@@ -463,8 +468,9 @@ l2fwd_simple_crypto_enqueue(struct rte_mbuf *m,
rte_pktmbuf_pkt_len(m) - cparams->digest_length);
op->sym->auth.digest.length = cparams->digest_length;
- /* For SNOW3G algorithms, offset/length must be in bits */
- if (cparams->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2) {
+ /* For SNOW3G/KASUMI algorithms, offset/length must be in bits */
+ if (cparams->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 ||
+ cparams->auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9) {
op->sym->auth.data.offset = ipdata_offset << 3;
op->sym->auth.data.length = data_len << 3;
} else {
@@ -485,7 +491,8 @@ l2fwd_simple_crypto_enqueue(struct rte_mbuf *m,
op->sym->cipher.iv.length = cparams->iv.length;
/* For SNOW3G algorithms, offset/length must be in bits */
- if (cparams->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2) {
+ if (cparams->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 ||
+ cparams->cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8) {
op->sym->cipher.data.offset = ipdata_offset << 3;
if (cparams->do_hash && cparams->hash_verify)
/* Do not cipher the hash tag */
@@ -1486,6 +1493,15 @@ check_supported_size(uint16_t length, uint16_t min, uint16_t max,
{
uint16_t supp_size;
+ /* Single value */
+ if (increment == 0) {
+ if (length == min)
+ return 0;
+ else
+ return -1;
+ }
+
+ /* Range of values */
for (supp_size = min; supp_size <= max; supp_size += increment) {
if (length == supp_size)
return 0;
@@ -1785,9 +1801,6 @@ initialize_ports(struct l2fwd_crypto_options *options)
return -1;
}
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
-
/* Reset l2fwd_dst_ports */
for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
l2fwd_dst_ports[portid] = 0;
diff --git a/examples/l2fwd-ivshmem/host/host.c b/examples/l2fwd-ivshmem/host/host.c
index 4bd7c41d..cd284b7d 100644
--- a/examples/l2fwd-ivshmem/host/host.c
+++ b/examples/l2fwd-ivshmem/host/host.c
@@ -677,9 +677,6 @@ int main(int argc, char **argv)
if (nb_ports == 0)
rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
-
/*
* reserve memzone to communicate with VMs - we cannot use rte_malloc here
* because while it is technically possible, it is a very bad idea to share
diff --git a/examples/l2fwd-jobstats/main.c b/examples/l2fwd-jobstats/main.c
index 9f3a77d2..614ea604 100644
--- a/examples/l2fwd-jobstats/main.c
+++ b/examples/l2fwd-jobstats/main.c
@@ -811,9 +811,6 @@ main(int argc, char **argv)
if (nb_ports == 0)
rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
-
/* reset l2fwd_dst_ports */
for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
l2fwd_dst_ports[portid] = 0;
@@ -990,7 +987,7 @@ main(int argc, char **argv)
struct rte_jobstats *job = &qconf->port_fwd_jobs[i];
portid = qconf->rx_port_list[i];
- printf("Setting forward jon for port %u\n", portid);
+ printf("Setting forward job for port %u\n", portid);
snprintf(name, RTE_DIM(name), "port %u fwd", portid);
/* Setup forward job.
diff --git a/examples/l2fwd-keepalive/Makefile b/examples/l2fwd-keepalive/Makefile
index 568edcb4..ca45a798 100644
--- a/examples/l2fwd-keepalive/Makefile
+++ b/examples/l2fwd-keepalive/Makefile
@@ -1,6 +1,6 @@
# BSD LICENSE
#
-# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -42,9 +42,10 @@ include $(RTE_SDK)/mk/rte.vars.mk
APP = l2fwd-keepalive
# all source are stored in SRCS-y
-SRCS-y := main.c
+SRCS-y := main.c shm.c
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
+LDFLAGS += -lrt
include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/examples/l2fwd-keepalive/ka-agent/Makefile b/examples/l2fwd-keepalive/ka-agent/Makefile
new file mode 100644
index 00000000..fd0c38b4
--- /dev/null
+++ b/examples/l2fwd-keepalive/ka-agent/Makefile
@@ -0,0 +1,49 @@
+# BSD LICENSE
+#
+# Copyright(c) 2016 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# binary name
+APP = ka-agent
+
+# all source are stored in SRCS-y
+SRCS-y := main.c
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)/../
+LDFLAGS += -lrt
+include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/examples/l2fwd-keepalive/ka-agent/main.c b/examples/l2fwd-keepalive/ka-agent/main.c
new file mode 100644
index 00000000..be1c7f49
--- /dev/null
+++ b/examples/l2fwd-keepalive/ka-agent/main.c
@@ -0,0 +1,150 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/queue.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#include <rte_keepalive.h>
+
+#include <shm.h>
+
+#define MAX_TIMEOUTS 4
+#define SEM_TIMEOUT_SECS 2
+
+static struct rte_keepalive_shm *ka_shm_create(void)
+{
+ int fd = shm_open(RTE_KEEPALIVE_SHM_NAME, O_RDWR, 0666);
+ size_t size = sizeof(struct rte_keepalive_shm);
+ struct rte_keepalive_shm *shm;
+
+ if (fd < 0)
+ printf("Failed to open %s as SHM:%s\n",
+ RTE_KEEPALIVE_SHM_NAME,
+ strerror(errno));
+ else {
+ shm = (struct rte_keepalive_shm *) mmap(
+ 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ close(fd);
+ if (shm == MAP_FAILED)
+ printf("Failed to mmap SHM:%s\n", strerror(errno));
+ else
+ return shm;
+ }
+
+ /* Reset to zero, as it was set to MAP_FAILED aka: (void *)-1 */
+ shm = 0;
+ return NULL;
+}
+
+int main(void)
+{
+ struct rte_keepalive_shm *shm = ka_shm_create();
+ struct timespec timeout = { .tv_nsec = 0 };
+ int idx_core;
+ int cnt_cores;
+ uint64_t last_seen_alive_time = 0;
+ uint64_t most_recent_alive_time;
+ int cnt_timeouts = 0;
+ int sem_errno;
+
+ if (shm == NULL) {
+ printf("Unable to access shared core state\n");
+ return 1;
+ }
+ while (1) {
+ most_recent_alive_time = 0;
+ for (idx_core = 0; idx_core < RTE_KEEPALIVE_MAXCORES;
+ idx_core++)
+ if (shm->core_last_seen_times[idx_core] >
+ most_recent_alive_time)
+ most_recent_alive_time =
+ shm->core_last_seen_times[idx_core];
+
+ timeout.tv_sec = time(NULL) + SEM_TIMEOUT_SECS;
+ if (sem_timedwait(&shm->core_died, &timeout) == -1) {
+ /* Assume no core death signals and no change in any
+ * last-seen times is the keepalive monitor itself
+ * failing.
+ */
+ sem_errno = errno;
+ last_seen_alive_time = most_recent_alive_time;
+ if (sem_errno == ETIMEDOUT) {
+ if (last_seen_alive_time ==
+ most_recent_alive_time &&
+ cnt_timeouts++ >
+ MAX_TIMEOUTS) {
+ printf("No updates. Exiting..\n");
+ break;
+ }
+ } else
+ printf("sem_timedwait() error (%s)\n",
+ strerror(sem_errno));
+ continue;
+ }
+ cnt_timeouts = 0;
+
+ cnt_cores = 0;
+ for (idx_core = 0; idx_core < RTE_KEEPALIVE_MAXCORES;
+ idx_core++)
+ if (shm->core_state[idx_core] == RTE_KA_STATE_DEAD)
+ cnt_cores++;
+ if (cnt_cores == 0) {
+ /* Can happen if core was restarted since Semaphore
+ * was sent, due to agent being offline.
+ */
+ printf("Warning: Empty dead core report\n");
+ continue;
+ }
+
+ printf("%i dead cores: ", cnt_cores);
+ for (idx_core = 0;
+ idx_core < RTE_KEEPALIVE_MAXCORES;
+ idx_core++)
+ if (shm->core_state[idx_core] == RTE_KA_STATE_DEAD)
+ printf("%d, ", idx_core);
+ printf("\b\b\n");
+ }
+ if (munmap(shm, sizeof(struct rte_keepalive_shm)) != 0)
+ printf("Warning: munmap() failed\n");
+ return 0;
+}
diff --git a/examples/l2fwd-keepalive/main.c b/examples/l2fwd-keepalive/main.c
index 8da89aa1..84a59eb6 100644
--- a/examples/l2fwd-keepalive/main.c
+++ b/examples/l2fwd-keepalive/main.c
@@ -72,6 +72,8 @@
#include <rte_timer.h>
#include <rte_keepalive.h>
+#include "shm.h"
+
#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
#define NB_MBUF 8192
@@ -523,7 +525,7 @@ check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
}
static void
-dead_core(__attribute__((unused)) void *ptr_data, const int id_core)
+dead_core(__rte_unused void *ptr_data, const int id_core)
{
printf("Dead core %i - restarting..\n", id_core);
if (rte_eal_get_lcore_state(id_core) == FINISHED) {
@@ -534,6 +536,14 @@ dead_core(__attribute__((unused)) void *ptr_data, const int id_core)
}
}
+static void
+relay_core_state(void *ptr_data, const int id_core,
+ const enum rte_keepalive_state core_state, uint64_t last_alive)
+{
+ rte_keepalive_relayed_state((struct rte_keepalive_shm *)ptr_data,
+ id_core, core_state, last_alive);
+}
+
int
main(int argc, char **argv)
{
@@ -570,9 +580,6 @@ main(int argc, char **argv)
if (nb_ports == 0)
rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
-
/* reset l2fwd_dst_ports */
for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
l2fwd_dst_ports[portid] = 0;
@@ -725,10 +732,18 @@ main(int argc, char **argv)
rte_timer_init(&stats_timer);
if (check_period > 0) {
+ struct rte_keepalive_shm *ka_shm;
+
+ ka_shm = rte_keepalive_shm_create();
+ if (ka_shm == NULL)
+ rte_exit(EXIT_FAILURE,
+ "rte_keepalive_shm_create() failed");
rte_global_keepalive_info =
- rte_keepalive_create(&dead_core, NULL);
+ rte_keepalive_create(&dead_core, ka_shm);
if (rte_global_keepalive_info == NULL)
rte_exit(EXIT_FAILURE, "init_keep_alive() failed");
+ rte_keepalive_register_relay_callback(rte_global_keepalive_info,
+ relay_core_state, ka_shm);
rte_timer_init(&hb_timer);
if (rte_timer_reset(&hb_timer,
(check_period * rte_get_timer_hz()) / 1000,
diff --git a/examples/l2fwd-keepalive/shm.c b/examples/l2fwd-keepalive/shm.c
new file mode 100644
index 00000000..177aa5b8
--- /dev/null
+++ b/examples/l2fwd-keepalive/shm.c
@@ -0,0 +1,131 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <time.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_keepalive.h>
+
+#include "shm.h"
+
+struct rte_keepalive_shm *rte_keepalive_shm_create(void)
+{
+ int fd;
+ int idx_core;
+ struct rte_keepalive_shm *ka_shm;
+
+ /* If any existing object is not unlinked, it makes it all too easy
+ * for clients to end up with stale shared memory blocks when
+ * restarted. Unlinking makes sure subsequent shm_open by clients
+ * will get the new block mapped below.
+ */
+ if (shm_unlink(RTE_KEEPALIVE_SHM_NAME) == -1 && errno != ENOENT)
+ printf("Warning: Error unlinking stale %s (%s)\n",
+ RTE_KEEPALIVE_SHM_NAME, strerror(errno));
+
+ fd = shm_open(RTE_KEEPALIVE_SHM_NAME,
+ O_CREAT | O_TRUNC | O_RDWR, 0666);
+ if (fd < 0)
+ RTE_LOG(INFO, EAL,
+ "Failed to open %s as SHM (%s)\n",
+ RTE_KEEPALIVE_SHM_NAME,
+ strerror(errno));
+ else if (ftruncate(fd, sizeof(struct rte_keepalive_shm)) != 0)
+ RTE_LOG(INFO, EAL,
+ "Failed to resize SHM (%s)\n", strerror(errno));
+ else {
+ ka_shm = (struct rte_keepalive_shm *) mmap(
+ 0, sizeof(struct rte_keepalive_shm),
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ close(fd);
+ if (ka_shm == MAP_FAILED)
+ RTE_LOG(INFO, EAL,
+ "Failed to mmap SHM (%s)\n", strerror(errno));
+ else {
+ memset(ka_shm, 0, sizeof(struct rte_keepalive_shm));
+
+ /* Initialize the semaphores for IPC/SHM use */
+ if (sem_init(&ka_shm->core_died, 1, 0) != 0) {
+ RTE_LOG(INFO, EAL,
+ "Failed to setup SHM semaphore (%s)\n",
+ strerror(errno));
+ munmap(ka_shm,
+ sizeof(struct rte_keepalive_shm));
+ return NULL;
+ }
+
+ /* Set all cores to 'not present' */
+ for (idx_core = 0;
+ idx_core < RTE_KEEPALIVE_MAXCORES;
+ idx_core++) {
+ ka_shm->core_state[idx_core] =
+ RTE_KA_STATE_UNUSED;
+ ka_shm->core_last_seen_times[idx_core] = 0;
+ }
+
+ return ka_shm;
+ }
+ }
+return NULL;
+}
+
+void rte_keepalive_relayed_state(struct rte_keepalive_shm *shm,
+ const int id_core, const enum rte_keepalive_state core_state,
+ __rte_unused uint64_t last_alive)
+{
+ int count;
+
+ shm->core_state[id_core] = core_state;
+ shm->core_last_seen_times[id_core] = last_alive;
+
+ if (core_state == RTE_KEEPALIVE_SHM_DEAD) {
+ /* Since core has died, also signal ka_agent.
+ *
+ * Limit number of times semaphore can be incremented, in case
+ * ka_agent is not active.
+ */
+ if (sem_getvalue(&shm->core_died, &count) == -1) {
+ RTE_LOG(INFO, EAL, "Semaphore check failed(%s)\n",
+ strerror(errno));
+ return;
+ }
+ if (count > 1)
+ return;
+
+ if (sem_post(&shm->core_died) != 0)
+ RTE_LOG(INFO, EAL,
+ "Failed to increment semaphore (%s)\n",
+ strerror(errno));
+ }
+}
diff --git a/examples/l2fwd-keepalive/shm.h b/examples/l2fwd-keepalive/shm.h
new file mode 100644
index 00000000..25e1b61d
--- /dev/null
+++ b/examples/l2fwd-keepalive/shm.h
@@ -0,0 +1,89 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define RTE_KEEPALIVE_SHM_NAME "/dpdk_keepalive_shm_name"
+
+#define RTE_KEEPALIVE_SHM_ALIVE 1
+#define RTE_KEEPALIVE_SHM_DEAD 2
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <semaphore.h>
+#include <rte_keepalive.h>
+
+/**
+ * Keepalive SHM structure.
+ *
+ * The shared memory allocated by the primary is this size, and contains the
+ * information as contained within this struct. A secondary may open the SHM,
+ * and read the contents.
+ */
+struct rte_keepalive_shm {
+ /** IPC semaphore. Posted when a core dies */
+ sem_t core_died;
+
+ /**
+ * Relayed status of each core.
+ */
+ enum rte_keepalive_state core_state[RTE_KEEPALIVE_MAXCORES];
+
+ /**
+ * Last-seen-alive timestamps for the cores
+ */
+ uint64_t core_last_seen_times[RTE_KEEPALIVE_MAXCORES];
+};
+
+/**
+ * Create shared host memory keepalive object.
+ * @return
+ * Pointer to SHM keepalive structure, or NULL on failure.
+ */
+struct rte_keepalive_shm *rte_keepalive_shm_create(void);
+
+/**
+ * Relays state for given core
+ * @param *shm
+ * Pointer to SHM keepalive structure.
+ * @param id_core
+ * Id of core
+ * @param core_state
+ * State of core
+ * @param last_alive
+ * Last seen timestamp for core
+ */
+void rte_keepalive_relayed_state(struct rte_keepalive_shm *shm,
+ const int id_core, const enum rte_keepalive_state core_state,
+ uint64_t last_alive);
diff --git a/examples/l2fwd/main.c b/examples/l2fwd/main.c
index 1ad94887..88979216 100644
--- a/examples/l2fwd/main.c
+++ b/examples/l2fwd/main.c
@@ -80,6 +80,7 @@ static volatile bool force_quit;
#define MAX_PKT_BURST 32
#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
+#define MEMPOOL_CACHE_SIZE 256
/*
* Configurable number of RX/TX ring descriptors
@@ -134,10 +135,9 @@ struct l2fwd_port_statistics {
} __rte_cache_aligned;
struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];
-/* A tsc-based timer responsible for triggering statistics printout */
-#define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */
#define MAX_TIMER_PERIOD 86400 /* 1 day max */
-static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */
+/* A tsc-based timer responsible for triggering statistics printout */
+static uint64_t timer_period = 10; /* default period is 10 seconds */
/* Print out statistics on packets dropped */
static void
@@ -274,7 +274,7 @@ l2fwd_main_loop(void)
timer_tsc += diff_tsc;
/* if timer has reached its timeout */
- if (unlikely(timer_tsc >= (uint64_t) timer_period)) {
+ if (unlikely(timer_tsc >= timer_period)) {
/* do this only on master core */
if (lcore_id == rte_get_master_lcore()) {
@@ -381,7 +381,7 @@ l2fwd_parse_timer_period(const char *q_arg)
static int
l2fwd_parse_args(int argc, char **argv)
{
- int opt, ret;
+ int opt, ret, timer_secs;
char **argvopt;
int option_index;
char *prgname = argv[0];
@@ -417,12 +417,13 @@ l2fwd_parse_args(int argc, char **argv)
/* timer period */
case 'T':
- timer_period = l2fwd_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND;
- if (timer_period < 0) {
+ timer_secs = l2fwd_parse_timer_period(optarg);
+ if (timer_secs < 0) {
printf("invalid timer period\n");
l2fwd_usage(prgname);
return -1;
}
+ timer_period = timer_secs;
break;
/* long options */
@@ -541,9 +542,13 @@ main(int argc, char **argv)
if (ret < 0)
rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n");
+ /* convert to number of cycles */
+ timer_period *= rte_get_timer_hz();
+
/* create the mbuf pool */
- l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32,
- 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+ l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF,
+ MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
+ rte_socket_id());
if (l2fwd_pktmbuf_pool == NULL)
rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
@@ -551,9 +556,6 @@ main(int argc, char **argv)
if (nb_ports == 0)
rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
-
/* reset l2fwd_dst_ports */
for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
l2fwd_dst_ports[portid] = 0;
diff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c
index 26d9f5eb..16f6110e 100644
--- a/examples/l3fwd-acl/main.c
+++ b/examples/l3fwd-acl/main.c
@@ -72,6 +72,9 @@
#include <rte_string_fns.h>
#include <rte_acl.h>
+#if RTE_LOG_LEVEL >= RTE_LOG_DEBUG
+#define L3FWDACL_DEBUG
+#endif
#define DO_RFC_1812_CHECKS
#define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1
@@ -1914,8 +1917,6 @@ main(int argc, char **argv)
rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
if (check_port_config(nb_ports) < 0)
rte_exit(EXIT_FAILURE, "check_port_config failed\n");
diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c
index cb42bfb9..f746960e 100644
--- a/examples/l3fwd-power/main.c
+++ b/examples/l3fwd-power/main.c
@@ -1572,10 +1572,7 @@ main(int argc, char **argv)
if (ret < 0)
rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
-
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
if (check_port_config(nb_ports) < 0)
rte_exit(EXIT_FAILURE, "check_port_config failed\n");
diff --git a/examples/l3fwd-vf/main.c b/examples/l3fwd-vf/main.c
index 034c22a7..ca01b112 100644
--- a/examples/l3fwd-vf/main.c
+++ b/examples/l3fwd-vf/main.c
@@ -982,8 +982,6 @@ main(int argc, char **argv)
rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
if (check_port_config(nb_ports) < 0)
rte_exit(EXIT_FAILURE, "check_port_config failed\n");
diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c
index fc59243d..def5a024 100644
--- a/examples/l3fwd/l3fwd_em.c
+++ b/examples/l3fwd/l3fwd_em.c
@@ -259,6 +259,8 @@ em_mask_key(void *key, xmm_t mask)
return vandq_s32(data, mask);
}
+#else
+#error No vector engine (SSE, NEON) available, check your toolchain
#endif
static inline uint8_t
diff --git a/examples/l3fwd/l3fwd_em_hlm_sse.h b/examples/l3fwd/l3fwd_em_hlm_sse.h
index 5001c724..7714a20c 100644
--- a/examples/l3fwd/l3fwd_em_hlm_sse.h
+++ b/examples/l3fwd/l3fwd_em_hlm_sse.h
@@ -81,7 +81,7 @@ em_get_dst_port_ipv4x8(struct lcore_conf *qconf, struct rte_mbuf *m[8],
const void *key_array[8] = {&key[0], &key[1], &key[2], &key[3],
&key[4], &key[5], &key[6], &key[7]};
- rte_hash_lookup_multi(qconf->ipv4_lookup_struct, &key_array[0], 8, ret);
+ rte_hash_lookup_bulk(qconf->ipv4_lookup_struct, &key_array[0], 8, ret);
dst_port[0] = (uint8_t) ((ret[0] < 0) ?
portid : ipv4_l3fwd_out_if[ret[0]]);
@@ -179,7 +179,7 @@ em_get_dst_port_ipv6x8(struct lcore_conf *qconf, struct rte_mbuf *m[8],
const void *key_array[8] = {&key[0], &key[1], &key[2], &key[3],
&key[4], &key[5], &key[6], &key[7]};
- rte_hash_lookup_multi(qconf->ipv6_lookup_struct, &key_array[0], 8, ret);
+ rte_hash_lookup_bulk(qconf->ipv6_lookup_struct, &key_array[0], 8, ret);
dst_port[0] = (uint8_t) ((ret[0] < 0) ?
portid : ipv6_l3fwd_out_if[ret[0]]);
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index bf6d8856..7a79cd2c 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -868,8 +868,6 @@ main(int argc, char **argv)
rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
if (check_port_config(nb_ports) < 0)
rte_exit(EXIT_FAILURE, "check_port_config failed\n");
diff --git a/examples/link_status_interrupt/main.c b/examples/link_status_interrupt/main.c
index 99815989..04dc3e40 100644
--- a/examples/link_status_interrupt/main.c
+++ b/examples/link_status_interrupt/main.c
@@ -580,9 +580,6 @@ main(int argc, char **argv)
if (nb_ports == 0)
rte_panic("No Ethernet port - bye\n");
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
-
/*
* Each logical core is assigned a dedicated TX queue on each port.
*/
diff --git a/examples/multi_process/l2fwd_fork/main.c b/examples/multi_process/l2fwd_fork/main.c
index 2dc8b829..2d951d93 100644
--- a/examples/multi_process/l2fwd_fork/main.c
+++ b/examples/multi_process/l2fwd_fork/main.c
@@ -442,7 +442,8 @@ reset_slave_all_ports(unsigned slaveid)
pool = rte_mempool_lookup(buf_name);
if (pool)
printf("Port %d mempool free object is %u(%u)\n", slave->port[i],
- rte_mempool_count(pool), (unsigned)NB_MBUF);
+ rte_mempool_avail_count(pool),
+ (unsigned int)NB_MBUF);
else
printf("Can't find mempool %s\n", buf_name);
@@ -979,9 +980,6 @@ main(int argc, char **argv)
if (nb_ports == 0)
rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
-
/* create the mbuf pool */
for (portid = 0; portid < nb_ports; portid++) {
/* skip ports that are not enabled */
diff --git a/examples/netmap_compat/lib/compat_netmap.c b/examples/netmap_compat/lib/compat_netmap.c
index bf1b418a..112c551f 100644
--- a/examples/netmap_compat/lib/compat_netmap.c
+++ b/examples/netmap_compat/lib/compat_netmap.c
@@ -865,6 +865,9 @@ rte_netmap_poll(struct pollfd *fds, nfds_t nfds, int timeout)
uint32_t i, idx, port;
uint32_t want_rx, want_tx;
+ if (timeout > 0)
+ return -1;
+
ret = 0;
do {
for (i = 0; i < nfds; i++) {
diff --git a/examples/packet_ordering/main.c b/examples/packet_ordering/main.c
index 15bb900c..3c88b86e 100644
--- a/examples/packet_ordering/main.c
+++ b/examples/packet_ordering/main.c
@@ -55,17 +55,6 @@
#define RING_SIZE 16384
-/* uncomment below line to enable debug logs */
-/* #define DEBUG */
-
-#ifdef DEBUG
-#define LOG_LEVEL RTE_LOG_DEBUG
-#define LOG_DEBUG(log_type, fmt, args...) RTE_LOG(DEBUG, log_type, fmt, ##args)
-#else
-#define LOG_LEVEL RTE_LOG_INFO
-#define LOG_DEBUG(log_type, fmt, args...) do {} while (0)
-#endif
-
/* Macros for printing using RTE_LOG */
#define RTE_LOGTYPE_REORDERAPP RTE_LOGTYPE_USER1
@@ -240,7 +229,7 @@ flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count,
/* free the mbufs which failed from transmit */
app_stats.tx.ro_tx_failed_pkts += count;
- LOG_DEBUG(REORDERAPP, "%s:Packet loss with tx_burst\n", __func__);
+ RTE_LOG(DEBUG, REORDERAPP, "%s:Packet loss with tx_burst\n", __func__);
pktmbuf_free_bulk(unsent, count);
}
@@ -421,7 +410,7 @@ rx_thread(struct rte_ring *ring_out)
nb_rx_pkts = rte_eth_rx_burst(port_id, 0,
pkts, MAX_PKTS_BURST);
if (nb_rx_pkts == 0) {
- LOG_DEBUG(REORDERAPP,
+ RTE_LOG(DEBUG, REORDERAPP,
"%s():Received zero packets\n", __func__);
continue;
}
@@ -533,7 +522,8 @@ send_thread(struct send_thread_args *args)
if (ret == -1 && rte_errno == ERANGE) {
/* Too early pkts should be transmitted out directly */
- LOG_DEBUG(REORDERAPP, "%s():Cannot reorder early packet "
+ RTE_LOG(DEBUG, REORDERAPP,
+ "%s():Cannot reorder early packet "
"direct enqueuing to TX\n", __func__);
outp = mbufs[i]->port;
if ((portmask & (1 << outp)) == 0) {
diff --git a/examples/performance-thread/common/lthread.c b/examples/performance-thread/common/lthread.c
index 8fbff737..062275a4 100644
--- a/examples/performance-thread/common/lthread.c
+++ b/examples/performance-thread/common/lthread.c
@@ -143,7 +143,7 @@ struct lthread_stack *_stack_alloc(void)
struct lthread_stack *s;
s = _lthread_objcache_alloc((THIS_SCHED)->stack_cache);
- LTHREAD_ASSERT(s != NULL);
+ RTE_ASSERT(s != NULL);
s->root_sched = THIS_SCHED;
s->stack_size = LTHREAD_MAX_STACK_SIZE;
diff --git a/examples/performance-thread/common/lthread_int.h b/examples/performance-thread/common/lthread_int.h
index c8357f4a..b858b55e 100644
--- a/examples/performance-thread/common/lthread_int.h
+++ b/examples/performance-thread/common/lthread_int.h
@@ -197,16 +197,4 @@ struct lthread {
uint64_t diag_ref; /* ref to user diag data */
} __rte_cache_aligned;
-/*
- * Assert
- */
-#if LTHREAD_DIAG
-#define LTHREAD_ASSERT(expr) do { \
- if (!(expr)) \
- rte_panic("line%d\tassert \"" #expr "\" failed\n", __LINE__);\
-} while (0)
-#else
-#define LTHREAD_ASSERT(expr) do {} while (0)
-#endif
-
#endif /* LTHREAD_INT_H */
diff --git a/examples/performance-thread/common/lthread_mutex.c b/examples/performance-thread/common/lthread_mutex.c
index af8b82d2..c1bc6271 100644
--- a/examples/performance-thread/common/lthread_mutex.c
+++ b/examples/performance-thread/common/lthread_mutex.c
@@ -170,7 +170,6 @@ int lthread_mutex_lock(struct lthread_mutex *m)
_suspend();
/* resumed, must loop and compete for the lock again */
}
- LTHREAD_ASSERT(0);
return 0;
}
@@ -231,7 +230,7 @@ int lthread_mutex_unlock(struct lthread_mutex *m)
if (unblocked != NULL) {
rte_atomic64_dec(&m->count);
DIAG_EVENT(m, LT_DIAG_MUTEX_UNLOCKED, m, unblocked);
- LTHREAD_ASSERT(unblocked->sched != NULL);
+ RTE_ASSERT(unblocked->sched != NULL);
_ready_queue_insert((struct lthread_sched *)
unblocked->sched, unblocked);
break;
diff --git a/examples/performance-thread/common/lthread_pool.h b/examples/performance-thread/common/lthread_pool.h
index a5f32515..27680eab 100644
--- a/examples/performance-thread/common/lthread_pool.h
+++ b/examples/performance-thread/common/lthread_pool.h
@@ -138,14 +138,14 @@ _qnode_pool_create(const char *name, int prealloc_size) {
RTE_CACHE_LINE_SIZE,
rte_socket_id());
- LTHREAD_ASSERT(p);
+ RTE_ASSERT(p);
p->stub = rte_malloc_socket(NULL,
sizeof(struct qnode),
RTE_CACHE_LINE_SIZE,
rte_socket_id());
- LTHREAD_ASSERT(p->stub);
+ RTE_ASSERT(p->stub);
if (name != NULL)
strncpy(p->name, name, LT_MAX_NAME_SIZE);
diff --git a/examples/performance-thread/common/lthread_queue.h b/examples/performance-thread/common/lthread_queue.h
index 0c395167..2c55fcec 100644
--- a/examples/performance-thread/common/lthread_queue.h
+++ b/examples/performance-thread/common/lthread_queue.h
@@ -129,7 +129,7 @@ _lthread_queue_create(const char *name)
/* allocated stub node */
stub = _qnode_alloc();
- LTHREAD_ASSERT(stub);
+ RTE_ASSERT(stub);
if (name != NULL)
strncpy(new_queue->name, name, sizeof(new_queue->name));
diff --git a/examples/performance-thread/common/lthread_sched.c b/examples/performance-thread/common/lthread_sched.c
index 7c40bc05..c64c21ff 100644
--- a/examples/performance-thread/common/lthread_sched.c
+++ b/examples/performance-thread/common/lthread_sched.c
@@ -268,7 +268,7 @@ struct lthread_sched *_lthread_sched_create(size_t stack_size)
struct lthread_sched *new_sched;
unsigned lcoreid = rte_lcore_id();
- LTHREAD_ASSERT(stack_size <= LTHREAD_MAX_STACK_SIZE);
+ RTE_ASSERT(stack_size <= LTHREAD_MAX_STACK_SIZE);
if (stack_size == 0)
stack_size = LTHREAD_MAX_STACK_SIZE;
diff --git a/examples/performance-thread/common/lthread_tls.c b/examples/performance-thread/common/lthread_tls.c
index 43cda4ff..6876f831 100644
--- a/examples/performance-thread/common/lthread_tls.c
+++ b/examples/performance-thread/common/lthread_tls.c
@@ -94,7 +94,7 @@ void _lthread_key_pool_init(void)
pool = rte_ring_create(name,
LTHREAD_MAX_KEYS, 0, 0);
- LTHREAD_ASSERT(pool);
+ RTE_ASSERT(pool);
int i;
@@ -240,7 +240,7 @@ void _lthread_tls_alloc(struct lthread *lt)
tls = _lthread_objcache_alloc((THIS_SCHED)->tls_cache);
- LTHREAD_ASSERT(tls != NULL);
+ RTE_ASSERT(tls != NULL);
tls->root_sched = (THIS_SCHED);
lt->tls = tls;
diff --git a/examples/performance-thread/l3fwd-thread/main.c b/examples/performance-thread/l3fwd-thread/main.c
index 15c0a4de..fdc90b28 100644
--- a/examples/performance-thread/l3fwd-thread/main.c
+++ b/examples/performance-thread/l3fwd-thread/main.c
@@ -996,7 +996,7 @@ simple_ipv4_fwd_8pkts(struct rte_mbuf *m[8], uint8_t portid)
const void *key_array[8] = {&key[0], &key[1], &key[2], &key[3],
&key[4], &key[5], &key[6], &key[7]};
- rte_hash_lookup_multi(RTE_PER_LCORE(lcore_conf)->ipv4_lookup_struct,
+ rte_hash_lookup_bulk(RTE_PER_LCORE(lcore_conf)->ipv4_lookup_struct,
&key_array[0], 8, ret);
dst_port[0] = (uint8_t) ((ret[0] < 0) ? portid : ipv4_l3fwd_out_if[ret[0]]);
dst_port[1] = (uint8_t) ((ret[1] < 0) ? portid : ipv4_l3fwd_out_if[ret[1]]);
@@ -1150,7 +1150,7 @@ simple_ipv6_fwd_8pkts(struct rte_mbuf *m[8], uint8_t portid)
const void *key_array[8] = {&key[0], &key[1], &key[2], &key[3],
&key[4], &key[5], &key[6], &key[7]};
- rte_hash_lookup_multi(RTE_PER_LCORE(lcore_conf)->ipv6_lookup_struct,
+ rte_hash_lookup_bulk(RTE_PER_LCORE(lcore_conf)->ipv6_lookup_struct,
&key_array[0], 4, ret);
dst_port[0] = (uint8_t) ((ret[0] < 0) ? portid : ipv6_l3fwd_out_if[ret[0]]);
dst_port[1] = (uint8_t) ((ret[1] < 0) ? portid : ipv6_l3fwd_out_if[ret[1]]);
@@ -1307,7 +1307,7 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid)
* to BAD_PORT value.
*/
static inline __attribute__((always_inline)) void
-rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint32_t *dp, uint32_t ptype)
+rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t ptype)
{
uint8_t ihl;
@@ -1326,7 +1326,7 @@ rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint32_t *dp, uint32_t ptype)
}
#else
-#define rfc1812_process(mb, dp) do { } while (0)
+#define rfc1812_process(mb, dp, ptype) do { } while (0)
#endif /* DO_RFC_1812_CHECKS */
#endif /* APP_LOOKUP_LPM && ENABLE_MULTI_BUFFER_OPTIMIZE */
@@ -1343,28 +1343,27 @@ get_dst_port(struct rte_mbuf *pkt, uint32_t dst_ipv4, uint8_t portid)
struct ether_hdr *eth_hdr;
if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
- if (rte_lpm_lookup(RTE_PER_LCORE(lcore_conf)->ipv4_lookup_struct,
- dst_ipv4, &next_hop_ipv4) != 0) {
- next_hop_ipv4 = portid;
- return next_hop_ipv4;
- }
+ return (uint16_t) ((rte_lpm_lookup(
+ RTE_PER_LCORE(lcore_conf)->ipv4_lookup_struct, dst_ipv4,
+ &next_hop_ipv4) == 0) ? next_hop_ipv4 : portid);
+
} else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+
eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
ipv6_hdr = (struct ipv6_hdr *)(eth_hdr + 1);
- if (rte_lpm6_lookup(RTE_PER_LCORE(lcore_conf)->ipv6_lookup_struct,
- ipv6_hdr->dst_addr, &next_hop_ipv6) != 0) {
- next_hop_ipv6 = portid;
- return next_hop_ipv6;
- }
- } else {
- next_hop_ipv4 = portid;
- return next_hop_ipv4;
+
+ return (uint16_t) ((rte_lpm6_lookup(
+ RTE_PER_LCORE(lcore_conf)->ipv6_lookup_struct,
+ ipv6_hdr->dst_addr, &next_hop_ipv6) == 0) ? next_hop_ipv6 :
+ portid);
+
}
+ return portid;
}
static inline void
-process_packet(struct rte_mbuf *pkt, uint32_t *dst_port, uint8_t portid)
+process_packet(struct rte_mbuf *pkt, uint16_t *dst_port, uint8_t portid)
{
struct ether_hdr *eth_hdr;
struct ipv4_hdr *ipv4_hdr;
@@ -1431,9 +1430,9 @@ processx4_step1(struct rte_mbuf *pkt[FWDSTEP],
static inline void
processx4_step2(__m128i dip,
uint32_t ipv4_flag,
- uint32_t portid,
+ uint8_t portid,
struct rte_mbuf *pkt[FWDSTEP],
- uint32_t dprt[FWDSTEP])
+ uint16_t dprt[FWDSTEP])
{
rte_xmm_t dst;
const __m128i bswap_mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11,
@@ -1445,7 +1444,11 @@ processx4_step2(__m128i dip,
/* if all 4 packets are IPV4. */
if (likely(ipv4_flag)) {
rte_lpm_lookupx4(RTE_PER_LCORE(lcore_conf)->ipv4_lookup_struct, dip,
- dprt, portid);
+ dst.u32, portid);
+
+ /* get rid of unused upper 16 bit for each dport. */
+ dst.x = _mm_packs_epi32(dst.x, dst.x);
+ *(uint64_t *)dprt = dst.u64[0];
} else {
dst.x = dip;
dprt[0] = get_dst_port(pkt[0], dst.u32[0], portid);
@@ -1460,7 +1463,7 @@ processx4_step2(__m128i dip,
* Perform RFC1812 checks and updates for IPV4 packets.
*/
static inline void
-processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint32_t dst_port[FWDSTEP])
+processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t dst_port[FWDSTEP])
{
__m128i te[FWDSTEP];
__m128i ve[FWDSTEP];
@@ -1658,9 +1661,9 @@ port_groupx4(uint16_t pn[FWDSTEP + 1], uint16_t *lp, __m128i dp1, __m128i dp2)
/* if dest port value has changed. */
if (v != GRPMSK) {
- lp = pnum->u16 + gptbl[v].idx;
- lp[0] = 1;
pnum->u64 = gptbl[v].pnum;
+ pnum->u16[FWDSTEP] = 1;
+ lp = pnum->u16 + gptbl[v].idx;
}
return lp;
@@ -1679,7 +1682,7 @@ process_burst(struct rte_mbuf *pkts_burst[MAX_PKT_BURST], int nb_rx,
int32_t k;
uint16_t dlp;
uint16_t *lp;
- uint32_t dst_port[MAX_PKT_BURST];
+ uint16_t dst_port[MAX_PKT_BURST];
__m128i dip[MAX_PKT_BURST / FWDSTEP];
uint32_t ipv4_flag[MAX_PKT_BURST / FWDSTEP];
uint16_t pnum[MAX_PKT_BURST + 1];
@@ -3482,8 +3485,6 @@ main(int argc, char **argv)
rte_exit(EXIT_FAILURE, "init_rx_rings failed\n");
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
if (check_port_config(nb_ports) < 0)
rte_exit(EXIT_FAILURE, "check_port_config failed\n");
diff --git a/examples/qos_meter/main.c b/examples/qos_meter/main.c
index b968b001..15656155 100644
--- a/examples/qos_meter/main.c
+++ b/examples/qos_meter/main.c
@@ -133,14 +133,20 @@ struct rte_meter_trtcm_params app_trtcm_params[] = {
FLOW_METER app_flows[APP_FLOWS_MAX];
-static void
+static int
app_configure_flow_table(void)
{
uint32_t i, j;
+ int ret;
- for (i = 0, j = 0; i < APP_FLOWS_MAX; i ++, j = (j + 1) % RTE_DIM(PARAMS)){
- FUNC_CONFIG(&app_flows[i], &PARAMS[j]);
+ for (i = 0, j = 0; i < APP_FLOWS_MAX;
+ i ++, j = (j + 1) % RTE_DIM(PARAMS)) {
+ ret = FUNC_CONFIG(&app_flows[i], &PARAMS[j]);
+ if (ret)
+ return ret;
}
+
+ return 0;
}
static inline void
@@ -381,7 +387,9 @@ main(int argc, char **argv)
rte_eth_promiscuous_enable(port_tx);
/* App configuration */
- app_configure_flow_table();
+ ret = app_configure_flow_table();
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid configure flow table\n");
/* Launch per-lcore init on every lcore */
rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER);
diff --git a/examples/qos_meter/main.h b/examples/qos_meter/main.h
index 530bf69c..54867dcf 100644
--- a/examples/qos_meter/main.h
+++ b/examples/qos_meter/main.h
@@ -51,7 +51,7 @@ enum policer_action policer_table[e_RTE_METER_COLORS][e_RTE_METER_COLORS] =
#if APP_MODE == APP_MODE_FWD
#define FUNC_METER(a,b,c,d) color, flow_id=flow_id, pkt_len=pkt_len, time=time
-#define FUNC_CONFIG(a,b)
+#define FUNC_CONFIG(a, b) 0
#define PARAMS app_srtcm_params
#define FLOW_METER int
diff --git a/examples/qos_sched/args.c b/examples/qos_sched/args.c
index 3e7fd087..476a0ee1 100644
--- a/examples/qos_sched/args.c
+++ b/examples/qos_sched/args.c
@@ -123,7 +123,7 @@ app_eal_core_mask(void)
uint64_t cm = 0;
struct rte_config *cfg = rte_eal_get_configuration();
- for (i = 0; i < RTE_MAX_LCORE; i++) {
+ for (i = 0; i < APP_MAX_LCORE; i++) {
if (cfg->lcore_role[i] == ROLE_RTE)
cm |= (1ULL << i);
}
@@ -142,7 +142,7 @@ app_cpu_core_count(void)
char path[PATH_MAX];
uint32_t ncores = 0;
- for(i = 0; i < RTE_MAX_LCORE; i++) {
+ for (i = 0; i < APP_MAX_LCORE; i++) {
len = snprintf(path, sizeof(path), SYS_CPU_DIR, i);
if (len <= 0 || (unsigned)len >= sizeof(path))
continue;
@@ -162,7 +162,7 @@ static int
app_parse_opt_vals(const char *conf_str, char separator, uint32_t n_vals, uint32_t *opt_vals)
{
char *string;
- uint32_t i, n_tokens;
+ int i, n_tokens;
char *tokens[MAX_OPT_VALUES];
if (conf_str == NULL || opt_vals == NULL || n_vals == 0 || n_vals > MAX_OPT_VALUES)
@@ -175,9 +175,11 @@ app_parse_opt_vals(const char *conf_str, char separator, uint32_t n_vals, uint32
n_tokens = rte_strsplit(string, strnlen(string, 32), tokens, n_vals, separator);
- for(i = 0; i < n_tokens; i++) {
+ if (n_tokens > MAX_OPT_VALUES)
+ return -1;
+
+ for (i = 0; i < n_tokens; i++)
opt_vals[i] = (uint32_t)atol(tokens[i]);
- }
free(string);
@@ -270,7 +272,7 @@ app_parse_flow_conf(const char *conf_str)
}
if (pconf->tx_port >= RTE_MAX_ETHPORTS) {
RTE_LOG(ERR, APP, "pfc %u: invalid tx port %"PRIu8" index\n",
- nb_pfc, pconf->rx_port);
+ nb_pfc, pconf->tx_port);
return -1;
}
diff --git a/examples/qos_sched/main.c b/examples/qos_sched/main.c
index e16b164d..e10cfd44 100644
--- a/examples/qos_sched/main.c
+++ b/examples/qos_sched/main.c
@@ -201,8 +201,6 @@ app_stat(void)
stats.oerrors - tx_stats[i].oerrors);
memcpy(&tx_stats[i], &stats, sizeof(stats));
- //printf("MP = %d\n", rte_mempool_count(conf->app_pktmbuf_pool));
-
#if APP_COLLECT_STAT
printf("-------+------------+------------+\n");
printf(" | received | dropped |\n");
diff --git a/examples/qos_sched/main.h b/examples/qos_sched/main.h
index 82aa0fae..c7490c61 100644
--- a/examples/qos_sched/main.h
+++ b/examples/qos_sched/main.h
@@ -68,7 +68,10 @@ extern "C" {
#define BURST_TX_DRAIN_US 100
-#define MAX_DATA_STREAMS (RTE_MAX_LCORE/2)
+#ifndef APP_MAX_LCORE
+#define APP_MAX_LCORE 64
+#endif
+#define MAX_DATA_STREAMS (APP_MAX_LCORE/2)
#define MAX_SCHED_SUBPORTS 8
#define MAX_SCHED_PIPES 4096
diff --git a/examples/quota_watermark/qw/init.c b/examples/quota_watermark/qw/init.c
index afc13665..c2087218 100644
--- a/examples/quota_watermark/qw/init.c
+++ b/examples/quota_watermark/qw/init.c
@@ -170,5 +170,5 @@ setup_shared_variables(void)
rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
quota = qw_memzone->addr;
- low_watermark = (unsigned int *) qw_memzone->addr + sizeof(int);
+ low_watermark = (unsigned int *) qw_memzone->addr + 1;
}
diff --git a/examples/quota_watermark/qwctl/qwctl.c b/examples/quota_watermark/qwctl/qwctl.c
index eb2f618a..4961089b 100644
--- a/examples/quota_watermark/qwctl/qwctl.c
+++ b/examples/quota_watermark/qwctl/qwctl.c
@@ -68,7 +68,7 @@ setup_shared_variables(void)
rte_exit(EXIT_FAILURE, "Couldn't find memzone\n");
quota = qw_memzone->addr;
- low_watermark = (unsigned int *) qw_memzone->addr + sizeof(int);
+ low_watermark = (unsigned int *) qw_memzone->addr + 1;
}
int main(int argc, char **argv)
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index f97d552a..622f248a 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -566,10 +566,9 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m)
struct rte_mbuf **m_table;
unsigned len, ret = 0;
const uint16_t lcore_id = rte_lcore_id();
- struct virtio_net *dev = vdev->dev;
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is external\n",
- dev->device_fh);
+ RTE_LOG(DEBUG, VHOST_DATA, "(%d) TX: MAC address is external\n",
+ vdev->vid);
/* Add packet to the port tx queue */
tx_q = &lcore_tx_queue[lcore_id];
@@ -578,8 +577,8 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m)
tx_q->m_table[len] = m;
len++;
if (enable_stats) {
- dev_statistics[dev->device_fh].tx_total++;
- dev_statistics[dev->device_fh].tx++;
+ dev_statistics[vdev->vid].tx_total++;
+ dev_statistics[vdev->vid].tx++;
}
if (unlikely(len == MAX_PKT_BURST)) {
@@ -614,7 +613,6 @@ static int
switch_worker(__rte_unused void *arg)
{
struct rte_mempool *mbuf_pool = arg;
- struct virtio_net *dev = NULL;
struct vhost_dev *vdev = NULL;
struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
struct virtio_net_data_ll *dev_ll;
@@ -651,7 +649,7 @@ switch_worker(__rte_unused void *arg)
if (unlikely(diff_tsc > drain_tsc)) {
if (tx_q->len) {
- LOG_DEBUG(VHOST_DATA, "TX queue drained after "
+ RTE_LOG(DEBUG, VHOST_DATA, "TX queue drained after "
"timeout with burst size %u\n",
tx_q->len);
ret = overlay_options.tx_handle(ports[0],
@@ -688,7 +686,6 @@ switch_worker(__rte_unused void *arg)
while (dev_ll != NULL) {
vdev = dev_ll->vdev;
- dev = vdev->dev;
if (unlikely(vdev->remove)) {
dev_ll = dev_ll->next;
@@ -709,22 +706,22 @@ switch_worker(__rte_unused void *arg)
* must be less than virtio queue size
*/
if (enable_retry && unlikely(rx_count >
- rte_vring_available_entries(dev, VIRTIO_RXQ))) {
+ rte_vhost_avail_entries(vdev->vid, VIRTIO_RXQ))) {
for (retry = 0; retry < burst_rx_retry_num;
retry++) {
rte_delay_us(burst_rx_delay_time);
- if (rx_count <= rte_vring_available_entries(dev, VIRTIO_RXQ))
+ if (rx_count <= rte_vhost_avail_entries(vdev->vid, VIRTIO_RXQ))
break;
}
}
- ret_count = overlay_options.rx_handle(dev, pkts_burst, rx_count);
+ ret_count = overlay_options.rx_handle(vdev->vid, pkts_burst, rx_count);
if (enable_stats) {
rte_atomic64_add(
- &dev_statistics[dev->device_fh].rx_total_atomic,
+ &dev_statistics[vdev->vid].rx_total_atomic,
rx_count);
rte_atomic64_add(
- &dev_statistics[dev->device_fh].rx_atomic, ret_count);
+ &dev_statistics[vdev->vid].rx_atomic, ret_count);
}
while (likely(rx_count)) {
rx_count--;
@@ -736,7 +733,7 @@ switch_worker(__rte_unused void *arg)
if (likely(!vdev->remove)) {
/* Handle guest TX*/
- tx_count = rte_vhost_dequeue_burst(dev,
+ tx_count = rte_vhost_dequeue_burst(vdev->vid,
VIRTIO_TXQ, mbuf_pool,
pkts_burst, MAX_PKT_BURST);
/* If this is the first received packet we need to learn the MAC */
@@ -908,23 +905,27 @@ init_data_ll(void)
/**
* Remove a device from the specific data core linked list and
* from the main linked list. Synchonization occurs through the use
- * of the lcore dev_removal_flag. Device is made volatile here
- * to avoid re-ordering of dev->remove=1 which can cause an infinite
- * loop in the rte_pause loop.
+ * of the lcore dev_removal_flag.
*/
static void
-destroy_device(volatile struct virtio_net *dev)
+destroy_device(int vid)
{
struct virtio_net_data_ll *ll_lcore_dev_cur;
struct virtio_net_data_ll *ll_main_dev_cur;
struct virtio_net_data_ll *ll_lcore_dev_last = NULL;
struct virtio_net_data_ll *ll_main_dev_last = NULL;
- struct vhost_dev *vdev;
+ struct vhost_dev *vdev = NULL;
int lcore;
- dev->flags &= ~VIRTIO_DEV_RUNNING;
-
- vdev = (struct vhost_dev *)dev->priv;
+ ll_main_dev_cur = ll_root_used;
+ while (ll_main_dev_cur != NULL) {
+ if (ll_main_dev_cur->vdev->vid == vid) {
+ vdev = ll_main_dev_cur->vdev;
+ break;
+ }
+ }
+ if (!vdev)
+ return;
/* set the remove flag. */
vdev->remove = 1;
@@ -944,8 +945,7 @@ destroy_device(volatile struct virtio_net *dev)
if (ll_lcore_dev_cur == NULL) {
RTE_LOG(ERR, VHOST_CONFIG,
- "(%"PRIu64") Failed to find the dev to be destroy.\n",
- dev->device_fh);
+ "(%d) Failed to find the dev to be destroy.\n", vid);
return;
}
@@ -992,8 +992,8 @@ destroy_device(volatile struct virtio_net *dev)
/* Decrement number of device on the lcore. */
lcore_info[vdev->coreid].lcore_ll->device_num--;
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been removed "
- "from data core\n", dev->device_fh);
+ RTE_LOG(INFO, VHOST_DATA, "(%d) Device has been removed "
+ "from data core\n", vid);
rte_free(vdev);
@@ -1004,7 +1004,7 @@ destroy_device(volatile struct virtio_net *dev)
* to the main linked list and the allocated to a specific data core.
*/
static int
-new_device(struct virtio_net *dev)
+new_device(int vid)
{
struct virtio_net_data_ll *ll_dev;
int lcore, core_add = 0;
@@ -1014,18 +1014,16 @@ new_device(struct virtio_net *dev)
vdev = rte_zmalloc("vhost device", sizeof(*vdev), RTE_CACHE_LINE_SIZE);
if (vdev == NULL) {
RTE_LOG(INFO, VHOST_DATA,
- "(%"PRIu64") Couldn't allocate memory for vhost dev\n",
- dev->device_fh);
+ "(%d) Couldn't allocate memory for vhost dev\n", vid);
return -1;
}
- vdev->dev = dev;
- dev->priv = vdev;
+ vdev->vid = vid;
/* Add device to main ll */
ll_dev = get_data_ll_free_entry(&ll_root_free);
if (ll_dev == NULL) {
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") No free entry found in"
+ RTE_LOG(INFO, VHOST_DATA, "(%d) No free entry found in"
" linked list Device limit of %d devices per core"
- " has been reached\n", dev->device_fh, nb_devices);
+ " has been reached\n", vid, nb_devices);
if (vdev->regions_hpa)
rte_free(vdev->regions_hpa);
rte_free(vdev);
@@ -1033,7 +1031,7 @@ new_device(struct virtio_net *dev)
}
ll_dev->vdev = vdev;
add_data_ll_entry(&ll_root_used, ll_dev);
- vdev->rx_q = dev->device_fh;
+ vdev->rx_q = vid;
/* reset ready flag */
vdev->ready = DEVICE_MAC_LEARNING;
@@ -1050,10 +1048,10 @@ new_device(struct virtio_net *dev)
ll_dev = get_data_ll_free_entry(&lcore_info[core_add].lcore_ll->ll_root_free);
if (ll_dev == NULL) {
RTE_LOG(INFO, VHOST_DATA,
- "(%"PRIu64") Failed to add device to data core\n",
- dev->device_fh);
+ "(%d) Failed to add device to data core\n",
+ vid);
vdev->ready = DEVICE_SAFE_REMOVE;
- destroy_device(dev);
+ destroy_device(vid);
rte_free(vdev->regions_hpa);
rte_free(vdev);
return -1;
@@ -1065,17 +1063,16 @@ new_device(struct virtio_net *dev)
ll_dev);
/* Initialize device stats */
- memset(&dev_statistics[dev->device_fh], 0,
+ memset(&dev_statistics[vid], 0,
sizeof(struct device_statistics));
/* Disable notifications. */
- rte_vhost_enable_guest_notification(dev, VIRTIO_RXQ, 0);
- rte_vhost_enable_guest_notification(dev, VIRTIO_TXQ, 0);
+ rte_vhost_enable_guest_notification(vid, VIRTIO_RXQ, 0);
+ rte_vhost_enable_guest_notification(vid, VIRTIO_TXQ, 0);
lcore_info[vdev->coreid].lcore_ll->device_num++;
- dev->flags |= VIRTIO_DEV_RUNNING;
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been added to data core %d\n",
- dev->device_fh, vdev->coreid);
+ RTE_LOG(INFO, VHOST_DATA, "(%d) Device has been added to data core %d\n",
+ vid, vdev->coreid);
return 0;
}
@@ -1099,7 +1096,7 @@ print_stats(void)
struct virtio_net_data_ll *dev_ll;
uint64_t tx_dropped, rx_dropped;
uint64_t tx, tx_total, rx, rx_total, rx_ip_csum, rx_l4_csum;
- uint32_t device_fh;
+ int vid;
const char clr[] = { 27, '[', '2', 'J', '\0' };
const char top_left[] = { 27, '[', '1', ';', '1', 'H', '\0' };
@@ -1113,22 +1110,22 @@ print_stats(void)
dev_ll = ll_root_used;
while (dev_ll != NULL) {
- device_fh = (uint32_t)dev_ll->vdev->dev->device_fh;
- tx_total = dev_statistics[device_fh].tx_total;
- tx = dev_statistics[device_fh].tx;
+ vid = dev_ll->vdev->vid;
+ tx_total = dev_statistics[vid].tx_total;
+ tx = dev_statistics[vid].tx;
tx_dropped = tx_total - tx;
rx_total = rte_atomic64_read(
- &dev_statistics[device_fh].rx_total_atomic);
+ &dev_statistics[vid].rx_total_atomic);
rx = rte_atomic64_read(
- &dev_statistics[device_fh].rx_atomic);
+ &dev_statistics[vid].rx_atomic);
rx_dropped = rx_total - rx;
rx_ip_csum = rte_atomic64_read(
- &dev_statistics[device_fh].rx_bad_ip_csum);
+ &dev_statistics[vid].rx_bad_ip_csum);
rx_l4_csum = rte_atomic64_read(
- &dev_statistics[device_fh].rx_bad_l4_csum);
+ &dev_statistics[vid].rx_bad_l4_csum);
- printf("\nStatistics for device %"PRIu32" ----------"
+ printf("\nStatistics for device %d ----------"
"\nTX total: %"PRIu64""
"\nTX dropped: %"PRIu64""
"\nTX successful: %"PRIu64""
@@ -1137,7 +1134,7 @@ print_stats(void)
"\nRX bad L4 csum: %"PRIu64""
"\nRX dropped: %"PRIu64""
"\nRX successful: %"PRIu64"",
- device_fh,
+ vid,
tx_total,
tx_dropped,
tx,
@@ -1190,8 +1187,6 @@ main(int argc, char *argv[])
/* Get the number of physical ports. */
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
/*
* Update the global var NB_PORTS and global array PORTS
@@ -1220,9 +1215,6 @@ main(int argc, char *argv[])
for (queue_id = 0; queue_id < MAX_QUEUES + 1; queue_id++)
vpool_array[queue_id].pool = mbuf_pool;
- /* Set log level. */
- rte_set_log_level(LOG_LEVEL);
-
/* initialize all ports */
for (portid = 0; portid < nb_ports; portid++) {
/* skip ports that are not enabled */
@@ -1251,7 +1243,7 @@ main(int argc, char *argv[])
snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "print-stats");
ret = rte_thread_setname(tid, thread_name);
if (ret != 0)
- RTE_LOG(ERR, VHOST_CONFIG, "Cannot set print-stats name\n");
+ RTE_LOG(DEBUG, VHOST_CONFIG, "Cannot set print-stats name\n");
}
/* Launch all data cores. */
@@ -1262,7 +1254,7 @@ main(int argc, char *argv[])
rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
/* Register CUSE device to handle IOCTLs. */
- ret = rte_vhost_driver_register((char *)&dev_basename);
+ ret = rte_vhost_driver_register((char *)&dev_basename, 0);
if (ret != 0)
rte_exit(EXIT_FAILURE, "CUSE device setup failure.\n");
diff --git a/examples/tep_termination/main.h b/examples/tep_termination/main.h
index a34301ad..c0ea7667 100644
--- a/examples/tep_termination/main.h
+++ b/examples/tep_termination/main.h
@@ -36,14 +36,6 @@
#include <rte_ether.h>
-#ifdef DEBUG
-#define LOG_LEVEL RTE_LOG_DEBUG
-#define LOG_DEBUG(log_type, fmt, args...) RTE_LOG(DEBUG, log_type, fmt, ##args)
-#else
-#define LOG_LEVEL RTE_LOG_INFO
-#define LOG_DEBUG(log_type, fmt, args...) do {} while (0)
-#endif
-
/* Macros for printing using RTE_LOG */
#define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
#define RTE_LOGTYPE_VHOST_DATA RTE_LOGTYPE_USER2
@@ -79,8 +71,7 @@ struct device_statistics {
* Device linked list structure for data path.
*/
struct vhost_dev {
- /**< Pointer to device created by vhost lib. */
- struct virtio_net *dev;
+ int vid;
/**< Number of memory regions for gpa to hpa translation. */
uint32_t nregions_hpa;
/**< Memory region information for gpa to hpa translation. */
@@ -124,6 +115,6 @@ struct virtio_net_data_ll {
};
uint32_t
-virtio_dev_rx(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count);
+virtio_dev_rx(int vid, struct rte_mbuf **pkts, uint32_t count);
#endif /* _MAIN_H_ */
diff --git a/examples/tep_termination/vxlan_setup.c b/examples/tep_termination/vxlan_setup.c
index 2a48e142..37575c27 100644
--- a/examples/tep_termination/vxlan_setup.c
+++ b/examples/tep_termination/vxlan_setup.c
@@ -244,17 +244,16 @@ vxlan_link(struct vhost_dev *vdev, struct rte_mbuf *m)
{
int i, ret;
struct ether_hdr *pkt_hdr;
- struct virtio_net *dev = vdev->dev;
- uint64_t portid = dev->device_fh;
+ uint64_t portid = vdev->vid;
struct ipv4_hdr *ip;
struct rte_eth_tunnel_filter_conf tunnel_filter_conf;
if (unlikely(portid > VXLAN_N_PORTS)) {
RTE_LOG(INFO, VHOST_DATA,
- "(%"PRIu64") WARNING: Not configuring device,"
+ "(%d) WARNING: Not configuring device,"
"as already have %d ports for VXLAN.",
- dev->device_fh, VXLAN_N_PORTS);
+ vdev->vid, VXLAN_N_PORTS);
return -1;
}
@@ -262,9 +261,9 @@ vxlan_link(struct vhost_dev *vdev, struct rte_mbuf *m)
pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
if (is_same_ether_addr(&(pkt_hdr->s_addr), &vdev->mac_address)) {
RTE_LOG(INFO, VHOST_DATA,
- "(%"PRIu64") WARNING: This device is using an existing"
+ "(%d) WARNING: This device is using an existing"
" MAC address and has not been registered.\n",
- dev->device_fh);
+ vdev->vid);
return -1;
}
@@ -425,8 +424,7 @@ vxlan_tx_pkts(uint8_t port_id, uint16_t queue_id,
/* Check for decapsulation and pass packets directly to VIRTIO device */
int
-vxlan_rx_pkts(struct virtio_net *dev, struct rte_mbuf **pkts_burst,
- uint32_t rx_count)
+vxlan_rx_pkts(int vid, struct rte_mbuf **pkts_burst, uint32_t rx_count)
{
uint32_t i = 0;
uint32_t count = 0;
@@ -436,11 +434,11 @@ vxlan_rx_pkts(struct virtio_net *dev, struct rte_mbuf **pkts_burst,
for (i = 0; i < rx_count; i++) {
if (enable_stats) {
rte_atomic64_add(
- &dev_statistics[dev->device_fh].rx_bad_ip_csum,
+ &dev_statistics[vid].rx_bad_ip_csum,
(pkts_burst[i]->ol_flags & PKT_RX_IP_CKSUM_BAD)
!= 0);
rte_atomic64_add(
- &dev_statistics[dev->device_fh].rx_bad_ip_csum,
+ &dev_statistics[vid].rx_bad_ip_csum,
(pkts_burst[i]->ol_flags & PKT_RX_L4_CKSUM_BAD)
!= 0);
}
@@ -452,6 +450,6 @@ vxlan_rx_pkts(struct virtio_net *dev, struct rte_mbuf **pkts_burst,
count++;
}
- ret = rte_vhost_enqueue_burst(dev, VIRTIO_RXQ, pkts_valid, count);
+ ret = rte_vhost_enqueue_burst(vid, VIRTIO_RXQ, pkts_valid, count);
return ret;
}
diff --git a/examples/tep_termination/vxlan_setup.h b/examples/tep_termination/vxlan_setup.h
index 1846540f..8d264619 100644
--- a/examples/tep_termination/vxlan_setup.h
+++ b/examples/tep_termination/vxlan_setup.h
@@ -55,10 +55,10 @@ typedef void (*ol_tunnel_destroy_t)(struct vhost_dev *vdev);
typedef int (*ol_tx_handle_t)(uint8_t port_id, uint16_t queue_id,
struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
-typedef int (*ol_rx_handle_t)(struct virtio_net *dev, struct rte_mbuf **pkts,
+typedef int (*ol_rx_handle_t)(int vid, struct rte_mbuf **pkts,
uint32_t count);
-typedef int (*ol_param_handle)(struct virtio_net *dev);
+typedef int (*ol_param_handle)(int vid);
struct ol_switch_ops {
ol_port_configure_t port_configure;
@@ -82,6 +82,6 @@ int
vxlan_tx_pkts(uint8_t port_id, uint16_t queue_id,
struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
int
-vxlan_rx_pkts(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count);
+vxlan_rx_pkts(int vid, struct rte_mbuf **pkts, uint32_t count);
#endif /* VXLAN_SETUP_H_ */
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 28c17afd..3aff2cc8 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -62,26 +62,9 @@
/* the maximum number of external ports supported */
#define MAX_SUP_PORTS 1
-/*
- * Calculate the number of buffers needed per port
- */
-#define NUM_MBUFS_PER_PORT ((MAX_QUEUES*RTE_TEST_RX_DESC_DEFAULT) + \
- (num_switching_cores*MAX_PKT_BURST) + \
- (num_switching_cores*RTE_TEST_TX_DESC_DEFAULT) +\
- ((num_switching_cores+1)*MBUF_CACHE_SIZE))
-
#define MBUF_CACHE_SIZE 128
#define MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE
-/*
- * No frame data buffer allocated from host are required for zero copy
- * implementation, guest will allocate the frame data buffer, and vhost
- * directly use it.
- */
-#define VIRTIO_DESCRIPTOR_LEN_ZCP RTE_MBUF_DEFAULT_DATAROOM
-#define MBUF_DATA_SIZE_ZCP RTE_MBUF_DEFAULT_BUF_SIZE
-#define MBUF_CACHE_SIZE_ZCP 0
-
#define MAX_PKT_BURST 32 /* Max burst size for RX/TX */
#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
@@ -95,33 +78,10 @@
#define DEVICE_RX 1
#define DEVICE_SAFE_REMOVE 2
-/* Config_core_flag status definitions. */
-#define REQUEST_DEV_REMOVAL 1
-#define ACK_DEV_REMOVAL 0
-
/* Configurable number of RX/TX ring descriptors */
#define RTE_TEST_RX_DESC_DEFAULT 1024
#define RTE_TEST_TX_DESC_DEFAULT 512
-/*
- * Need refine these 2 macros for legacy and DPDK based front end:
- * Max vring avail descriptor/entries from guest - MAX_PKT_BURST
- * And then adjust power 2.
- */
-/*
- * For legacy front end, 128 descriptors,
- * half for virtio header, another half for mbuf.
- */
-#define RTE_TEST_RX_DESC_DEFAULT_ZCP 32 /* legacy: 32, DPDK virt FE: 128. */
-#define RTE_TEST_TX_DESC_DEFAULT_ZCP 64 /* legacy: 64, DPDK virt FE: 64. */
-
-/* Get first 4 bytes in mbuf headroom. */
-#define MBUF_HEADROOM_UINT32(mbuf) (*(uint32_t *)((uint8_t *)(mbuf) \
- + sizeof(struct rte_mbuf)))
-
-/* true if x is a power of 2 */
-#define POWEROF2(x) ((((x)-1) & (x)) == 0)
-
#define INVALID_PORT_ID 0xFF
/* Max number of devices. Limited by vmdq. */
@@ -136,50 +96,22 @@
/* Maximum long option length for option parsing. */
#define MAX_LONG_OPT_SZ 64
-/* Used to compare MAC addresses. */
-#define MAC_ADDR_CMP 0xFFFFFFFFFFFFULL
-
-/* Number of descriptors per cacheline. */
-#define DESC_PER_CACHELINE (RTE_CACHE_LINE_SIZE / sizeof(struct vring_desc))
-
-#define MBUF_EXT_MEM(mb) (rte_mbuf_from_indirect(mb) != (mb))
-
/* mask of enabled ports */
static uint32_t enabled_port_mask = 0;
/* Promiscuous mode */
static uint32_t promiscuous;
-/*Number of switching cores enabled*/
-static uint32_t num_switching_cores = 0;
-
/* number of devices/queues to support*/
static uint32_t num_queues = 0;
static uint32_t num_devices;
-/*
- * Enable zero copy, pkts buffer will directly dma to hw descriptor,
- * disabled on default.
- */
-static uint32_t zero_copy;
+static struct rte_mempool *mbuf_pool;
static int mergeable;
/* Do vlan strip on host, enabled on default */
static uint32_t vlan_strip = 1;
-/* number of descriptors to apply*/
-static uint32_t num_rx_descriptor = RTE_TEST_RX_DESC_DEFAULT_ZCP;
-static uint32_t num_tx_descriptor = RTE_TEST_TX_DESC_DEFAULT_ZCP;
-
-/* max ring descriptor, ixgbe, i40e, e1000 all are 4096. */
-#define MAX_RING_DESC 4096
-
-struct vpool {
- struct rte_mempool *pool;
- struct rte_ring *ring;
- uint32_t buf_size;
-} vpool_array[MAX_QUEUES+MAX_QUEUES];
-
/* Enable VM2VM communications. If this is disabled then the MAC address compare is skipped. */
typedef enum {
VM2VM_DISABLED = 0,
@@ -189,14 +121,6 @@ typedef enum {
} vm2vm_type;
static vm2vm_type vm2vm_mode = VM2VM_SOFTWARE;
-/* The type of host physical address translated from guest physical address. */
-typedef enum {
- PHYS_ADDR_CONTINUOUS = 0,
- PHYS_ADDR_CROSS_SUBREG = 1,
- PHYS_ADDR_INVALID = 2,
- PHYS_ADDR_LAST
-} hpa_type;
-
/* Enable stats. */
static uint32_t enable_stats = 0;
/* Enable retries on RX. */
@@ -208,6 +132,8 @@ static uint32_t enable_tx_csum;
/* Disable TSO offload */
static uint32_t enable_tso;
+static int client_mode;
+
/* Specify timeout (in useconds) between retries on RX. */
static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US;
/* Specify the number of retries on RX. */
@@ -259,7 +185,6 @@ static uint16_t num_pf_queues, num_vmdq_queues;
static uint16_t vmdq_pool_base, vmdq_queue_base;
static uint16_t queues_per_pool;
-static const uint16_t external_pkt_default_vlan_tag = 2000;
const uint16_t vlan_tags[] = {
1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015,
@@ -274,11 +199,9 @@ const uint16_t vlan_tags[] = {
/* ethernet addresses of ports */
static struct ether_addr vmdq_ports_eth_addr[RTE_MAX_ETHPORTS];
-/* heads for the main used and free linked lists for the data path. */
-static struct virtio_net_data_ll *ll_root_used = NULL;
-static struct virtio_net_data_ll *ll_root_free = NULL;
+static struct vhost_dev_tailq_list vhost_dev_list =
+ TAILQ_HEAD_INITIALIZER(vhost_dev_list);
-/* Array of data core structures containing information on individual core linked lists. */
static struct lcore_info lcore_info[RTE_MAX_LCORE];
/* Used for queueing bursts of TX packets. */
@@ -291,32 +214,9 @@ struct mbuf_table {
/* TX queue for each data core. */
struct mbuf_table lcore_tx_queue[RTE_MAX_LCORE];
-/* TX queue fori each virtio device for zero copy. */
-struct mbuf_table tx_queue_zcp[MAX_QUEUES];
-
-/* Vlan header struct used to insert vlan tags on TX. */
-struct vlan_ethhdr {
- unsigned char h_dest[ETH_ALEN];
- unsigned char h_source[ETH_ALEN];
- __be16 h_vlan_proto;
- __be16 h_vlan_TCI;
- __be16 h_vlan_encapsulated_proto;
-};
-
-/* Header lengths. */
+#define MBUF_TABLE_DRAIN_TSC ((rte_get_tsc_hz() + US_PER_S - 1) \
+ / US_PER_S * BURST_TX_DRAIN_US)
#define VLAN_HLEN 4
-#define VLAN_ETH_HLEN 18
-
-/* Per-device statistics struct */
-struct device_statistics {
- uint64_t tx_total;
- rte_atomic64_t rx_total_atomic;
- uint64_t rx_total;
- uint64_t tx;
- rte_atomic64_t rx_atomic;
- uint64_t rx;
-} __rte_cache_aligned;
-struct device_statistics dev_statistics[MAX_DEVICES];
/*
* Builds up the correct configuration for VMDQ VLAN pool map
@@ -394,29 +294,12 @@ port_init(uint8_t port)
/* Enable vlan offload */
txconf->txq_flags &= ~ETH_TXQ_FLAGS_NOVLANOFFL;
- /*
- * Zero copy defers queue RX/TX start to the time when guest
- * finishes its startup and packet buffers from that guest are
- * available.
- */
- if (zero_copy) {
- rxconf->rx_deferred_start = 1;
- rxconf->rx_drop_en = 0;
- txconf->tx_deferred_start = 1;
- }
-
/*configure the number of supported virtio devices based on VMDQ limits */
num_devices = dev_info.max_vmdq_pools;
- if (zero_copy) {
- rx_ring_size = num_rx_descriptor;
- tx_ring_size = num_tx_descriptor;
- tx_rings = dev_info.max_tx_queues;
- } else {
- rx_ring_size = RTE_TEST_RX_DESC_DEFAULT;
- tx_ring_size = RTE_TEST_TX_DESC_DEFAULT;
- tx_rings = (uint16_t)rte_lcore_count();
- }
+ rx_ring_size = RTE_TEST_RX_DESC_DEFAULT;
+ tx_ring_size = RTE_TEST_TX_DESC_DEFAULT;
+ tx_rings = (uint16_t)rte_lcore_count();
retval = validate_num_devices(MAX_DEVICES);
if (retval < 0)
@@ -457,7 +340,7 @@ port_init(uint8_t port)
retval = rte_eth_rx_queue_setup(port, q, rx_ring_size,
rte_eth_dev_socket_id(port),
rxconf,
- vpool_array[q].pool);
+ mbuf_pool);
if (retval < 0)
return retval;
}
@@ -576,14 +459,9 @@ us_vhost_usage(const char *prgname)
" --vlan-strip [0|1]: disable/enable(default) RX VLAN strip on host\n"
" --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n"
" --dev-basename: The basename to be used for the character device.\n"
- " --zero-copy [0|1]: disable(default)/enable rx/tx "
- "zero copy\n"
- " --rx-desc-num [0-N]: the number of descriptors on rx, "
- "used only when zero copy is enabled.\n"
- " --tx-desc-num [0-N]: the number of descriptors on tx, "
- "used only when zero copy is enabled.\n"
" --tx-csum [0|1] disable/enable TX checksum offload.\n"
- " --tso [0|1] disable/enable TCP segment offload.\n",
+ " --tso [0|1] disable/enable TCP segment offload.\n"
+ " --client register a vhost-user socket as client mode.\n",
prgname);
}
@@ -606,11 +484,9 @@ us_vhost_parse_args(int argc, char **argv)
{"vlan-strip", required_argument, NULL, 0},
{"stats", required_argument, NULL, 0},
{"dev-basename", required_argument, NULL, 0},
- {"zero-copy", required_argument, NULL, 0},
- {"rx-desc-num", required_argument, NULL, 0},
- {"tx-desc-num", required_argument, NULL, 0},
{"tx-csum", required_argument, NULL, 0},
{"tso", required_argument, NULL, 0},
+ {"client", no_argument, &client_mode, 1},
{NULL, 0, 0, 0},
};
@@ -765,50 +641,6 @@ us_vhost_parse_args(int argc, char **argv)
}
}
- /* Enable/disable rx/tx zero copy. */
- if (!strncmp(long_option[option_index].name,
- "zero-copy", MAX_LONG_OPT_SZ)) {
- ret = parse_num_opt(optarg, 1);
- if (ret == -1) {
- RTE_LOG(INFO, VHOST_CONFIG,
- "Invalid argument"
- " for zero-copy [0|1]\n");
- us_vhost_usage(prgname);
- return -1;
- } else
- zero_copy = ret;
- }
-
- /* Specify the descriptor number on RX. */
- if (!strncmp(long_option[option_index].name,
- "rx-desc-num", MAX_LONG_OPT_SZ)) {
- ret = parse_num_opt(optarg, MAX_RING_DESC);
- if ((ret == -1) || (!POWEROF2(ret))) {
- RTE_LOG(INFO, VHOST_CONFIG,
- "Invalid argument for rx-desc-num[0-N],"
- "power of 2 required.\n");
- us_vhost_usage(prgname);
- return -1;
- } else {
- num_rx_descriptor = ret;
- }
- }
-
- /* Specify the descriptor number on TX. */
- if (!strncmp(long_option[option_index].name,
- "tx-desc-num", MAX_LONG_OPT_SZ)) {
- ret = parse_num_opt(optarg, MAX_RING_DESC);
- if ((ret == -1) || (!POWEROF2(ret))) {
- RTE_LOG(INFO, VHOST_CONFIG,
- "Invalid argument for tx-desc-num [0-N],"
- "power of 2 required.\n");
- us_vhost_usage(prgname);
- return -1;
- } else {
- num_tx_descriptor = ret;
- }
- }
-
break;
/* Invalid option - print options. */
@@ -829,21 +661,6 @@ us_vhost_parse_args(int argc, char **argv)
return -1;
}
- if ((zero_copy == 1) && (vm2vm_mode == VM2VM_SOFTWARE)) {
- RTE_LOG(INFO, VHOST_PORT,
- "Vhost zero copy doesn't support software vm2vm,"
- "please specify 'vm2vm 2' to use hardware vm2vm.\n");
- return -1;
- }
-
- if ((zero_copy == 1) && (vmdq_conf_default.rxmode.jumbo_frame == 1)) {
- RTE_LOG(INFO, VHOST_PORT,
- "Vhost zero copy doesn't support jumbo frame,"
- "please specify '--mergeable 0' to disable the "
- "mergeable feature.\n");
- return -1;
- }
-
return 0;
}
@@ -873,74 +690,18 @@ static unsigned check_ports_num(unsigned nb_ports)
return valid_num_ports;
}
-/*
- * Macro to print out packet contents. Wrapped in debug define so that the
- * data path is not effected when debug is disabled.
- */
-#ifdef DEBUG
-#define PRINT_PACKET(device, addr, size, header) do { \
- char *pkt_addr = (char*)(addr); \
- unsigned int index; \
- char packet[MAX_PRINT_BUFF]; \
- \
- if ((header)) \
- snprintf(packet, MAX_PRINT_BUFF, "(%"PRIu64") Header size %d: ", (device->device_fh), (size)); \
- else \
- snprintf(packet, MAX_PRINT_BUFF, "(%"PRIu64") Packet size %d: ", (device->device_fh), (size)); \
- for (index = 0; index < (size); index++) { \
- snprintf(packet + strnlen(packet, MAX_PRINT_BUFF), MAX_PRINT_BUFF - strnlen(packet, MAX_PRINT_BUFF), \
- "%02hhx ", pkt_addr[index]); \
- } \
- snprintf(packet + strnlen(packet, MAX_PRINT_BUFF), MAX_PRINT_BUFF - strnlen(packet, MAX_PRINT_BUFF), "\n"); \
- \
- LOG_DEBUG(VHOST_DATA, "%s", packet); \
-} while(0)
-#else
-#define PRINT_PACKET(device, addr, size, header) do{} while(0)
-#endif
-
-/*
- * Function to convert guest physical addresses to vhost physical addresses.
- * This is used to convert virtio buffer addresses.
- */
-static inline uint64_t __attribute__((always_inline))
-gpa_to_hpa(struct vhost_dev *vdev, uint64_t guest_pa,
- uint32_t buf_len, hpa_type *addr_type)
+static inline struct vhost_dev *__attribute__((always_inline))
+find_vhost_dev(struct ether_addr *mac)
{
- struct virtio_memory_regions_hpa *region;
- uint32_t regionidx;
- uint64_t vhost_pa = 0;
-
- *addr_type = PHYS_ADDR_INVALID;
-
- for (regionidx = 0; regionidx < vdev->nregions_hpa; regionidx++) {
- region = &vdev->regions_hpa[regionidx];
- if ((guest_pa >= region->guest_phys_address) &&
- (guest_pa <= region->guest_phys_address_end)) {
- vhost_pa = region->host_phys_addr_offset + guest_pa;
- if (likely((guest_pa + buf_len - 1)
- <= region->guest_phys_address_end))
- *addr_type = PHYS_ADDR_CONTINUOUS;
- else
- *addr_type = PHYS_ADDR_CROSS_SUBREG;
- break;
- }
- }
-
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") GPA %p| HPA %p\n",
- vdev->dev->device_fh, (void *)(uintptr_t)guest_pa,
- (void *)(uintptr_t)vhost_pa);
+ struct vhost_dev *vdev;
- return vhost_pa;
-}
+ TAILQ_FOREACH(vdev, &vhost_dev_list, global_vdev_entry) {
+ if (vdev->ready == DEVICE_RX &&
+ is_same_ether_addr(mac, &vdev->mac_address))
+ return vdev;
+ }
-/*
- * Compares a packet destination MAC address to a device MAC address.
- */
-static inline int __attribute__((always_inline))
-ether_addr_cmp(struct ether_addr *ea, struct ether_addr *eb)
-{
- return ((*(uint64_t *)ea ^ *(uint64_t *)eb) & MAC_ADDR_CMP) == 0;
+ return NULL;
}
/*
@@ -951,32 +712,28 @@ static int
link_vmdq(struct vhost_dev *vdev, struct rte_mbuf *m)
{
struct ether_hdr *pkt_hdr;
- struct virtio_net_data_ll *dev_ll;
- struct virtio_net *dev = vdev->dev;
int i, ret;
/* Learn MAC address of guest device from packet */
pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
- dev_ll = ll_root_used;
-
- while (dev_ll != NULL) {
- if (ether_addr_cmp(&(pkt_hdr->s_addr), &dev_ll->vdev->mac_address)) {
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") WARNING: This device is using an existing MAC address and has not been registered.\n", dev->device_fh);
- return -1;
- }
- dev_ll = dev_ll->next;
+ if (find_vhost_dev(&pkt_hdr->s_addr)) {
+ RTE_LOG(ERR, VHOST_DATA,
+ "(%d) device is using a registered MAC!\n",
+ vdev->vid);
+ return -1;
}
for (i = 0; i < ETHER_ADDR_LEN; i++)
vdev->mac_address.addr_bytes[i] = pkt_hdr->s_addr.addr_bytes[i];
/* vlan_tag currently uses the device_id. */
- vdev->vlan_tag = vlan_tags[dev->device_fh];
+ vdev->vlan_tag = vlan_tags[vdev->vid];
/* Print out VMDQ registration info. */
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") MAC_ADDRESS %02x:%02x:%02x:%02x:%02x:%02x and VLAN_TAG %d registered\n",
- dev->device_fh,
+ RTE_LOG(INFO, VHOST_DATA,
+ "(%d) mac %02x:%02x:%02x:%02x:%02x:%02x and vlan %d registered\n",
+ vdev->vid,
vdev->mac_address.addr_bytes[0], vdev->mac_address.addr_bytes[1],
vdev->mac_address.addr_bytes[2], vdev->mac_address.addr_bytes[3],
vdev->mac_address.addr_bytes[4], vdev->mac_address.addr_bytes[5],
@@ -984,10 +741,11 @@ link_vmdq(struct vhost_dev *vdev, struct rte_mbuf *m)
/* Register the MAC address. */
ret = rte_eth_dev_mac_addr_add(ports[0], &vdev->mac_address,
- (uint32_t)dev->device_fh + vmdq_pool_base);
+ (uint32_t)vdev->vid + vmdq_pool_base);
if (ret)
- RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Failed to add device MAC address to VMDQ\n",
- dev->device_fh);
+ RTE_LOG(ERR, VHOST_DATA,
+ "(%d) failed to add device MAC address to VMDQ\n",
+ vdev->vid);
/* Enable stripping of the vlan tag as we handle routing. */
if (vlan_strip)
@@ -1035,6 +793,21 @@ unlink_vmdq(struct vhost_dev *vdev)
}
}
+static inline void __attribute__((always_inline))
+virtio_xmit(struct vhost_dev *dst_vdev, struct vhost_dev *src_vdev,
+ struct rte_mbuf *m)
+{
+ uint16_t ret;
+
+ ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
+ if (enable_stats) {
+ rte_atomic64_inc(&dst_vdev->stats.rx_total_atomic);
+ rte_atomic64_add(&dst_vdev->stats.rx_atomic, ret);
+ src_vdev->stats.tx_total++;
+ src_vdev->stats.tx += ret;
+ }
+}
+
/*
* Check if the packet destination MAC address is for a local device. If so then put
* the packet on that devices RX queue. If not then return.
@@ -1042,56 +815,33 @@ unlink_vmdq(struct vhost_dev *vdev)
static inline int __attribute__((always_inline))
virtio_tx_local(struct vhost_dev *vdev, struct rte_mbuf *m)
{
- struct virtio_net_data_ll *dev_ll;
struct ether_hdr *pkt_hdr;
- uint64_t ret = 0;
- struct virtio_net *dev = vdev->dev;
- struct virtio_net *tdev; /* destination virito device */
+ struct vhost_dev *dst_vdev;
pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
- /*get the used devices list*/
- dev_ll = ll_root_used;
+ dst_vdev = find_vhost_dev(&pkt_hdr->d_addr);
+ if (!dst_vdev)
+ return -1;
- while (dev_ll != NULL) {
- if ((dev_ll->vdev->ready == DEVICE_RX) && ether_addr_cmp(&(pkt_hdr->d_addr),
- &dev_ll->vdev->mac_address)) {
+ if (vdev->vid == dst_vdev->vid) {
+ RTE_LOG(DEBUG, VHOST_DATA,
+ "(%d) TX: src and dst MAC is same. Dropping packet.\n",
+ vdev->vid);
+ return 0;
+ }
- /* Drop the packet if the TX packet is destined for the TX device. */
- if (dev_ll->vdev->dev->device_fh == dev->device_fh) {
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: Source and destination MAC addresses are the same. Dropping packet.\n",
- dev->device_fh);
- return 0;
- }
- tdev = dev_ll->vdev->dev;
-
-
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is local\n", tdev->device_fh);
-
- if (unlikely(dev_ll->vdev->remove)) {
- /*drop the packet if the device is marked for removal*/
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Device is marked for removal\n", tdev->device_fh);
- } else {
- /*send the packet to the local virtio device*/
- ret = rte_vhost_enqueue_burst(tdev, VIRTIO_RXQ, &m, 1);
- if (enable_stats) {
- rte_atomic64_add(
- &dev_statistics[tdev->device_fh].rx_total_atomic,
- 1);
- rte_atomic64_add(
- &dev_statistics[tdev->device_fh].rx_atomic,
- ret);
- dev_statistics[dev->device_fh].tx_total++;
- dev_statistics[dev->device_fh].tx += ret;
- }
- }
+ RTE_LOG(DEBUG, VHOST_DATA,
+ "(%d) TX: MAC address is local\n", dst_vdev->vid);
- return 0;
- }
- dev_ll = dev_ll->next;
+ if (unlikely(dst_vdev->remove)) {
+ RTE_LOG(DEBUG, VHOST_DATA,
+ "(%d) device is marked for removal\n", dst_vdev->vid);
+ return 0;
}
- return -1;
+ virtio_xmit(dst_vdev, vdev, m);
+ return 0;
}
/*
@@ -1099,49 +849,35 @@ virtio_tx_local(struct vhost_dev *vdev, struct rte_mbuf *m)
* and get its vlan tag, and offset if it is.
*/
static inline int __attribute__((always_inline))
-find_local_dest(struct virtio_net *dev, struct rte_mbuf *m,
+find_local_dest(struct vhost_dev *vdev, struct rte_mbuf *m,
uint32_t *offset, uint16_t *vlan_tag)
{
- struct virtio_net_data_ll *dev_ll = ll_root_used;
+ struct vhost_dev *dst_vdev;
struct ether_hdr *pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
- while (dev_ll != NULL) {
- if ((dev_ll->vdev->ready == DEVICE_RX)
- && ether_addr_cmp(&(pkt_hdr->d_addr),
- &dev_ll->vdev->mac_address)) {
- /*
- * Drop the packet if the TX packet is
- * destined for the TX device.
- */
- if (dev_ll->vdev->dev->device_fh == dev->device_fh) {
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") TX: Source and destination"
- " MAC addresses are the same. Dropping "
- "packet.\n",
- dev_ll->vdev->dev->device_fh);
- return -1;
- }
-
- /*
- * HW vlan strip will reduce the packet length
- * by minus length of vlan tag, so need restore
- * the packet length by plus it.
- */
- *offset = VLAN_HLEN;
- *vlan_tag =
- (uint16_t)
- vlan_tags[(uint16_t)dev_ll->vdev->dev->device_fh];
-
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") TX: pkt to local VM device id:"
- "(%"PRIu64") vlan tag: %d.\n",
- dev->device_fh, dev_ll->vdev->dev->device_fh,
- (int)*vlan_tag);
+ dst_vdev = find_vhost_dev(&pkt_hdr->d_addr);
+ if (!dst_vdev)
+ return 0;
- break;
- }
- dev_ll = dev_ll->next;
+ if (vdev->vid == dst_vdev->vid) {
+ RTE_LOG(DEBUG, VHOST_DATA,
+ "(%d) TX: src and dst MAC is same. Dropping packet.\n",
+ vdev->vid);
+ return -1;
}
+
+ /*
+ * HW vlan strip will reduce the packet length
+ * by minus length of vlan tag, so need restore
+ * the packet length by plus it.
+ */
+ *offset = VLAN_HLEN;
+ *vlan_tag = vlan_tags[vdev->vid];
+
+ RTE_LOG(DEBUG, VHOST_DATA,
+ "(%d) TX: pkt to local VM device id: (%d), vlan tag: %u.\n",
+ vdev->vid, dst_vdev->vid, *vlan_tag);
+
return 0;
}
@@ -1173,20 +909,49 @@ static void virtio_tx_offload(struct rte_mbuf *m)
tcp_hdr->cksum = get_psd_sum(l3_hdr, m->ol_flags);
}
+static inline void
+free_pkts(struct rte_mbuf **pkts, uint16_t n)
+{
+ while (n--)
+ rte_pktmbuf_free(pkts[n]);
+}
+
+static inline void __attribute__((always_inline))
+do_drain_mbuf_table(struct mbuf_table *tx_q)
+{
+ uint16_t count;
+
+ count = rte_eth_tx_burst(ports[0], tx_q->txq_id,
+ tx_q->m_table, tx_q->len);
+ if (unlikely(count < tx_q->len))
+ free_pkts(&tx_q->m_table[count], tx_q->len - count);
+
+ tx_q->len = 0;
+}
+
/*
- * This function routes the TX packet to the correct interface. This may be a local device
- * or the physical port.
+ * This function routes the TX packet to the correct interface. This
+ * may be a local device or the physical port.
*/
static inline void __attribute__((always_inline))
virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag)
{
struct mbuf_table *tx_q;
- struct rte_mbuf **m_table;
- unsigned len, ret, offset = 0;
+ unsigned offset = 0;
const uint16_t lcore_id = rte_lcore_id();
- struct virtio_net *dev = vdev->dev;
struct ether_hdr *nh;
+
+ nh = rte_pktmbuf_mtod(m, struct ether_hdr *);
+ if (unlikely(is_broadcast_ether_addr(&nh->d_addr))) {
+ struct vhost_dev *vdev2;
+
+ TAILQ_FOREACH(vdev2, &vhost_dev_list, global_vdev_entry) {
+ virtio_xmit(vdev2, vdev, m);
+ }
+ goto queue2nic;
+ }
+
/*check if destination is local VM*/
if ((vm2vm_mode == VM2VM_SOFTWARE) && (virtio_tx_local(vdev, m) == 0)) {
rte_pktmbuf_free(m);
@@ -1194,17 +959,20 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag)
}
if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) {
- if (unlikely(find_local_dest(dev, m, &offset, &vlan_tag) != 0)) {
+ if (unlikely(find_local_dest(vdev, m, &offset,
+ &vlan_tag) != 0)) {
rte_pktmbuf_free(m);
return;
}
}
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is external\n", dev->device_fh);
+ RTE_LOG(DEBUG, VHOST_DATA,
+ "(%d) TX: MAC address is external\n", vdev->vid);
+
+queue2nic:
/*Add packet to the port tx queue*/
tx_q = &lcore_tx_queue[lcore_id];
- len = tx_q->len;
nh = rte_pktmbuf_mtod(m, struct ether_hdr *);
if (unlikely(nh->ether_type == rte_cpu_to_be_16(ETHER_TYPE_VLAN))) {
@@ -1242,1411 +1010,213 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag)
if (m->ol_flags & PKT_TX_TCP_SEG)
virtio_tx_offload(m);
- tx_q->m_table[len] = m;
- len++;
+ tx_q->m_table[tx_q->len++] = m;
if (enable_stats) {
- dev_statistics[dev->device_fh].tx_total++;
- dev_statistics[dev->device_fh].tx++;
- }
-
- if (unlikely(len == MAX_PKT_BURST)) {
- m_table = (struct rte_mbuf **)tx_q->m_table;
- ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id, m_table, (uint16_t) len);
- /* Free any buffers not handled by TX and update the port stats. */
- if (unlikely(ret < len)) {
- do {
- rte_pktmbuf_free(m_table[ret]);
- } while (++ret < len);
- }
-
- len = 0;
+ vdev->stats.tx_total++;
+ vdev->stats.tx++;
}
- tx_q->len = len;
- return;
+ if (unlikely(tx_q->len == MAX_PKT_BURST))
+ do_drain_mbuf_table(tx_q);
}
-/*
- * This function is called by each data core. It handles all RX/TX registered with the
- * core. For TX the specific lcore linked list is used. For RX, MAC addresses are compared
- * with all devices in the main linked list.
- */
-static int
-switch_worker(__attribute__((unused)) void *arg)
-{
- struct rte_mempool *mbuf_pool = arg;
- struct virtio_net *dev = NULL;
- struct vhost_dev *vdev = NULL;
- struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
- struct virtio_net_data_ll *dev_ll;
- struct mbuf_table *tx_q;
- volatile struct lcore_ll_info *lcore_ll;
- const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US;
- uint64_t prev_tsc, diff_tsc, cur_tsc, ret_count = 0;
- unsigned ret, i;
- const uint16_t lcore_id = rte_lcore_id();
- const uint16_t num_cores = (uint16_t)rte_lcore_count();
- uint16_t rx_count = 0;
- uint16_t tx_count;
- uint32_t retry = 0;
-
- RTE_LOG(INFO, VHOST_DATA, "Procesing on Core %u started\n", lcore_id);
- lcore_ll = lcore_info[lcore_id].lcore_ll;
- prev_tsc = 0;
-
- tx_q = &lcore_tx_queue[lcore_id];
- for (i = 0; i < num_cores; i ++) {
- if (lcore_ids[i] == lcore_id) {
- tx_q->txq_id = i;
- break;
- }
- }
-
- while(1) {
- cur_tsc = rte_rdtsc();
- /*
- * TX burst queue drain
- */
- diff_tsc = cur_tsc - prev_tsc;
- if (unlikely(diff_tsc > drain_tsc)) {
-
- if (tx_q->len) {
- LOG_DEBUG(VHOST_DATA, "TX queue drained after timeout with burst size %u \n", tx_q->len);
-
- /*Tx any packets in the queue*/
- ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id,
- (struct rte_mbuf **)tx_q->m_table,
- (uint16_t)tx_q->len);
- if (unlikely(ret < tx_q->len)) {
- do {
- rte_pktmbuf_free(tx_q->m_table[ret]);
- } while (++ret < tx_q->len);
- }
-
- tx_q->len = 0;
- }
- prev_tsc = cur_tsc;
- }
-
- rte_prefetch0(lcore_ll->ll_root_used);
- /*
- * Inform the configuration core that we have exited the linked list and that no devices are
- * in use if requested.
- */
- if (lcore_ll->dev_removal_flag == REQUEST_DEV_REMOVAL)
- lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL;
-
- /*
- * Process devices
- */
- dev_ll = lcore_ll->ll_root_used;
-
- while (dev_ll != NULL) {
- /*get virtio device ID*/
- vdev = dev_ll->vdev;
- dev = vdev->dev;
-
- if (unlikely(vdev->remove)) {
- dev_ll = dev_ll->next;
- unlink_vmdq(vdev);
- vdev->ready = DEVICE_SAFE_REMOVE;
- continue;
- }
- if (likely(vdev->ready == DEVICE_RX)) {
- /*Handle guest RX*/
- rx_count = rte_eth_rx_burst(ports[0],
- vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
-
- if (rx_count) {
- /*
- * Retry is enabled and the queue is full then we wait and retry to avoid packet loss
- * Here MAX_PKT_BURST must be less than virtio queue size
- */
- if (enable_retry && unlikely(rx_count > rte_vring_available_entries(dev, VIRTIO_RXQ))) {
- for (retry = 0; retry < burst_rx_retry_num; retry++) {
- rte_delay_us(burst_rx_delay_time);
- if (rx_count <= rte_vring_available_entries(dev, VIRTIO_RXQ))
- break;
- }
- }
- ret_count = rte_vhost_enqueue_burst(dev, VIRTIO_RXQ, pkts_burst, rx_count);
- if (enable_stats) {
- rte_atomic64_add(
- &dev_statistics[dev_ll->vdev->dev->device_fh].rx_total_atomic,
- rx_count);
- rte_atomic64_add(
- &dev_statistics[dev_ll->vdev->dev->device_fh].rx_atomic, ret_count);
- }
- while (likely(rx_count)) {
- rx_count--;
- rte_pktmbuf_free(pkts_burst[rx_count]);
- }
+static inline void __attribute__((always_inline))
+drain_mbuf_table(struct mbuf_table *tx_q)
+{
+ static uint64_t prev_tsc;
+ uint64_t cur_tsc;
- }
- }
+ if (tx_q->len == 0)
+ return;
- if (likely(!vdev->remove)) {
- /* Handle guest TX*/
- tx_count = rte_vhost_dequeue_burst(dev, VIRTIO_TXQ, mbuf_pool, pkts_burst, MAX_PKT_BURST);
- /* If this is the first received packet we need to learn the MAC and setup VMDQ */
- if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && tx_count) {
- if (vdev->remove || (link_vmdq(vdev, pkts_burst[0]) == -1)) {
- while (tx_count)
- rte_pktmbuf_free(pkts_burst[--tx_count]);
- }
- }
- for (i = 0; i < tx_count; ++i) {
- virtio_tx_route(vdev, pkts_burst[i],
- vlan_tags[(uint16_t)dev->device_fh]);
- }
- }
+ cur_tsc = rte_rdtsc();
+ if (unlikely(cur_tsc - prev_tsc > MBUF_TABLE_DRAIN_TSC)) {
+ prev_tsc = cur_tsc;
- /*move to the next device in the list*/
- dev_ll = dev_ll->next;
- }
+ RTE_LOG(DEBUG, VHOST_DATA,
+ "TX queue drained after timeout with burst size %u\n",
+ tx_q->len);
+ do_drain_mbuf_table(tx_q);
}
-
- return 0;
}
-/*
- * This function gets available ring number for zero copy rx.
- * Only one thread will call this funciton for a paticular virtio device,
- * so, it is designed as non-thread-safe function.
- */
-static inline uint32_t __attribute__((always_inline))
-get_available_ring_num_zcp(struct virtio_net *dev)
-{
- struct vhost_virtqueue *vq = dev->virtqueue[VIRTIO_RXQ];
- uint16_t avail_idx;
-
- avail_idx = *((volatile uint16_t *)&vq->avail->idx);
- return (uint32_t)(avail_idx - vq->last_used_idx_res);
-}
-
-/*
- * This function gets available ring index for zero copy rx,
- * it will retry 'burst_rx_retry_num' times till it get enough ring index.
- * Only one thread will call this funciton for a paticular virtio device,
- * so, it is designed as non-thread-safe function.
- */
-static inline uint32_t __attribute__((always_inline))
-get_available_ring_index_zcp(struct virtio_net *dev,
- uint16_t *res_base_idx, uint32_t count)
+static inline void __attribute__((always_inline))
+drain_eth_rx(struct vhost_dev *vdev)
{
- struct vhost_virtqueue *vq = dev->virtqueue[VIRTIO_RXQ];
- uint16_t avail_idx;
- uint32_t retry = 0;
- uint16_t free_entries;
-
- *res_base_idx = vq->last_used_idx_res;
- avail_idx = *((volatile uint16_t *)&vq->avail->idx);
- free_entries = (avail_idx - *res_base_idx);
+ uint16_t rx_count, enqueue_count;
+ struct rte_mbuf *pkts[MAX_PKT_BURST];
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in get_available_ring_index_zcp: "
- "avail idx: %d, "
- "res base idx:%d, free entries:%d\n",
- dev->device_fh, avail_idx, *res_base_idx,
- free_entries);
+ rx_count = rte_eth_rx_burst(ports[0], vdev->vmdq_rx_q,
+ pkts, MAX_PKT_BURST);
+ if (!rx_count)
+ return;
/*
- * If retry is enabled and the queue is full then we wait
- * and retry to avoid packet loss.
+ * When "enable_retry" is set, here we wait and retry when there
+ * is no enough free slots in the queue to hold @rx_count packets,
+ * to diminish packet loss.
*/
- if (enable_retry && unlikely(count > free_entries)) {
+ if (enable_retry &&
+ unlikely(rx_count > rte_vhost_avail_entries(vdev->vid,
+ VIRTIO_RXQ))) {
+ uint32_t retry;
+
for (retry = 0; retry < burst_rx_retry_num; retry++) {
rte_delay_us(burst_rx_delay_time);
- avail_idx = *((volatile uint16_t *)&vq->avail->idx);
- free_entries = (avail_idx - *res_base_idx);
- if (count <= free_entries)
+ if (rx_count <= rte_vhost_avail_entries(vdev->vid,
+ VIRTIO_RXQ))
break;
}
}
- /*check that we have enough buffers*/
- if (unlikely(count > free_entries))
- count = free_entries;
-
- if (unlikely(count == 0)) {
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") Fail in get_available_ring_index_zcp: "
- "avail idx: %d, res base idx:%d, free entries:%d\n",
- dev->device_fh, avail_idx,
- *res_base_idx, free_entries);
- return 0;
+ enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
+ pkts, rx_count);
+ if (enable_stats) {
+ rte_atomic64_add(&vdev->stats.rx_total_atomic, rx_count);
+ rte_atomic64_add(&vdev->stats.rx_atomic, enqueue_count);
}
- vq->last_used_idx_res = *res_base_idx + count;
-
- return count;
+ free_pkts(pkts, rx_count);
}
-/*
- * This function put descriptor back to used list.
- */
static inline void __attribute__((always_inline))
-put_desc_to_used_list_zcp(struct vhost_virtqueue *vq, uint16_t desc_idx)
+drain_virtio_tx(struct vhost_dev *vdev)
{
- uint16_t res_cur_idx = vq->last_used_idx;
- vq->used->ring[res_cur_idx & (vq->size - 1)].id = (uint32_t)desc_idx;
- vq->used->ring[res_cur_idx & (vq->size - 1)].len = 0;
- rte_compiler_barrier();
- *(volatile uint16_t *)&vq->used->idx += 1;
- vq->last_used_idx += 1;
-
- /* Kick the guest if necessary. */
- if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
- eventfd_write(vq->callfd, (eventfd_t)1);
-}
+ struct rte_mbuf *pkts[MAX_PKT_BURST];
+ uint16_t count;
+ uint16_t i;
-/*
- * This function get available descriptor from vitio vring and un-attached mbuf
- * from vpool->ring, and then attach them together. It needs adjust the offset
- * for buff_addr and phys_addr accroding to PMD implementation, otherwise the
- * frame data may be put to wrong location in mbuf.
- */
-static inline void __attribute__((always_inline))
-attach_rxmbuf_zcp(struct virtio_net *dev)
-{
- uint16_t res_base_idx, desc_idx;
- uint64_t buff_addr, phys_addr;
- struct vhost_virtqueue *vq;
- struct vring_desc *desc;
- void *obj = NULL;
- struct rte_mbuf *mbuf;
- struct vpool *vpool;
- hpa_type addr_type;
- struct vhost_dev *vdev = (struct vhost_dev *)dev->priv;
-
- vpool = &vpool_array[vdev->vmdq_rx_q];
- vq = dev->virtqueue[VIRTIO_RXQ];
-
- do {
- if (unlikely(get_available_ring_index_zcp(vdev->dev, &res_base_idx,
- 1) != 1))
- return;
- desc_idx = vq->avail->ring[(res_base_idx) & (vq->size - 1)];
-
- desc = &vq->desc[desc_idx];
- if (desc->flags & VRING_DESC_F_NEXT) {
- desc = &vq->desc[desc->next];
- buff_addr = gpa_to_vva(dev, desc->addr);
- phys_addr = gpa_to_hpa(vdev, desc->addr, desc->len,
- &addr_type);
- } else {
- buff_addr = gpa_to_vva(dev,
- desc->addr + vq->vhost_hlen);
- phys_addr = gpa_to_hpa(vdev,
- desc->addr + vq->vhost_hlen,
- desc->len, &addr_type);
- }
+ count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ, mbuf_pool,
+ pkts, MAX_PKT_BURST);
- if (unlikely(addr_type == PHYS_ADDR_INVALID)) {
- RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Invalid frame buffer"
- " address found when attaching RX frame buffer"
- " address!\n", dev->device_fh);
- put_desc_to_used_list_zcp(vq, desc_idx);
- continue;
- }
-
- /*
- * Check if the frame buffer address from guest crosses
- * sub-region or not.
- */
- if (unlikely(addr_type == PHYS_ADDR_CROSS_SUBREG)) {
- RTE_LOG(ERR, VHOST_DATA,
- "(%"PRIu64") Frame buffer address cross "
- "sub-regioin found when attaching RX frame "
- "buffer address!\n",
- dev->device_fh);
- put_desc_to_used_list_zcp(vq, desc_idx);
- continue;
- }
- } while (unlikely(phys_addr == 0));
-
- rte_ring_sc_dequeue(vpool->ring, &obj);
- mbuf = obj;
- if (unlikely(mbuf == NULL)) {
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in attach_rxmbuf_zcp: "
- "ring_sc_dequeue fail.\n",
- dev->device_fh);
- put_desc_to_used_list_zcp(vq, desc_idx);
- return;
- }
-
- if (unlikely(vpool->buf_size > desc->len)) {
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in attach_rxmbuf_zcp: frame buffer "
- "length(%d) of descriptor idx: %d less than room "
- "size required: %d\n",
- dev->device_fh, desc->len, desc_idx, vpool->buf_size);
- put_desc_to_used_list_zcp(vq, desc_idx);
- rte_ring_sp_enqueue(vpool->ring, obj);
- return;
+ /* setup VMDq for the first packet */
+ if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && count) {
+ if (vdev->remove || link_vmdq(vdev, pkts[0]) == -1)
+ free_pkts(pkts, count);
}
- mbuf->buf_addr = (void *)(uintptr_t)(buff_addr - RTE_PKTMBUF_HEADROOM);
- mbuf->data_off = RTE_PKTMBUF_HEADROOM;
- mbuf->buf_physaddr = phys_addr - RTE_PKTMBUF_HEADROOM;
- mbuf->data_len = desc->len;
- MBUF_HEADROOM_UINT32(mbuf) = (uint32_t)desc_idx;
-
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in attach_rxmbuf_zcp: res base idx:%d, "
- "descriptor idx:%d\n",
- dev->device_fh, res_base_idx, desc_idx);
-
- __rte_mbuf_raw_free(mbuf);
-
- return;
+ for (i = 0; i < count; ++i)
+ virtio_tx_route(vdev, pkts[i], vlan_tags[vdev->vid]);
}
/*
- * Detach an attched packet mbuf -
- * - restore original mbuf address and length values.
- * - reset pktmbuf data and data_len to their default values.
- * All other fields of the given packet mbuf will be left intact.
+ * Main function of vhost-switch. It basically does:
*
- * @param m
- * The attached packet mbuf.
- */
-static inline void pktmbuf_detach_zcp(struct rte_mbuf *m)
-{
- const struct rte_mempool *mp = m->pool;
- void *buf = rte_mbuf_to_baddr(m);
- uint32_t buf_ofs;
- uint32_t buf_len = mp->elt_size - sizeof(*m);
- m->buf_physaddr = rte_mempool_virt2phy(mp, m) + sizeof(*m);
-
- m->buf_addr = buf;
- m->buf_len = (uint16_t)buf_len;
-
- buf_ofs = (RTE_PKTMBUF_HEADROOM <= m->buf_len) ?
- RTE_PKTMBUF_HEADROOM : m->buf_len;
- m->data_off = buf_ofs;
-
- m->data_len = 0;
-}
-
-/*
- * This function is called after packets have been transimited. It fetchs mbuf
- * from vpool->pool, detached it and put into vpool->ring. It also update the
- * used index and kick the guest if necessary.
- */
-static inline uint32_t __attribute__((always_inline))
-txmbuf_clean_zcp(struct virtio_net *dev, struct vpool *vpool)
-{
- struct rte_mbuf *mbuf;
- struct vhost_virtqueue *vq = dev->virtqueue[VIRTIO_TXQ];
- uint32_t used_idx = vq->last_used_idx & (vq->size - 1);
- uint32_t index = 0;
- uint32_t mbuf_count = rte_mempool_count(vpool->pool);
-
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in txmbuf_clean_zcp: mbuf count in mempool before "
- "clean is: %d\n",
- dev->device_fh, mbuf_count);
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in txmbuf_clean_zcp: mbuf count in ring before "
- "clean is : %d\n",
- dev->device_fh, rte_ring_count(vpool->ring));
-
- for (index = 0; index < mbuf_count; index++) {
- mbuf = __rte_mbuf_raw_alloc(vpool->pool);
- if (likely(MBUF_EXT_MEM(mbuf)))
- pktmbuf_detach_zcp(mbuf);
- rte_ring_sp_enqueue(vpool->ring, mbuf);
-
- /* Update used index buffer information. */
- vq->used->ring[used_idx].id = MBUF_HEADROOM_UINT32(mbuf);
- vq->used->ring[used_idx].len = 0;
-
- used_idx = (used_idx + 1) & (vq->size - 1);
- }
-
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in txmbuf_clean_zcp: mbuf count in mempool after "
- "clean is: %d\n",
- dev->device_fh, rte_mempool_count(vpool->pool));
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in txmbuf_clean_zcp: mbuf count in ring after "
- "clean is : %d\n",
- dev->device_fh, rte_ring_count(vpool->ring));
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in txmbuf_clean_zcp: before updated "
- "vq->last_used_idx:%d\n",
- dev->device_fh, vq->last_used_idx);
-
- vq->last_used_idx += mbuf_count;
-
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in txmbuf_clean_zcp: after updated "
- "vq->last_used_idx:%d\n",
- dev->device_fh, vq->last_used_idx);
-
- rte_compiler_barrier();
-
- *(volatile uint16_t *)&vq->used->idx += mbuf_count;
-
- /* Kick guest if required. */
- if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
- eventfd_write(vq->callfd, (eventfd_t)1);
-
- return 0;
-}
-
-/*
- * This function is called when a virtio device is destroy.
- * It fetchs mbuf from vpool->pool, and detached it, and put into vpool->ring.
- */
-static void mbuf_destroy_zcp(struct vpool *vpool)
-{
- struct rte_mbuf *mbuf = NULL;
- uint32_t index, mbuf_count = rte_mempool_count(vpool->pool);
-
- LOG_DEBUG(VHOST_CONFIG,
- "in mbuf_destroy_zcp: mbuf count in mempool before "
- "mbuf_destroy_zcp is: %d\n",
- mbuf_count);
- LOG_DEBUG(VHOST_CONFIG,
- "in mbuf_destroy_zcp: mbuf count in ring before "
- "mbuf_destroy_zcp is : %d\n",
- rte_ring_count(vpool->ring));
-
- for (index = 0; index < mbuf_count; index++) {
- mbuf = __rte_mbuf_raw_alloc(vpool->pool);
- if (likely(mbuf != NULL)) {
- if (likely(MBUF_EXT_MEM(mbuf)))
- pktmbuf_detach_zcp(mbuf);
- rte_ring_sp_enqueue(vpool->ring, (void *)mbuf);
- }
- }
-
- LOG_DEBUG(VHOST_CONFIG,
- "in mbuf_destroy_zcp: mbuf count in mempool after "
- "mbuf_destroy_zcp is: %d\n",
- rte_mempool_count(vpool->pool));
- LOG_DEBUG(VHOST_CONFIG,
- "in mbuf_destroy_zcp: mbuf count in ring after "
- "mbuf_destroy_zcp is : %d\n",
- rte_ring_count(vpool->ring));
-}
-
-/*
- * This function update the use flag and counter.
- */
-static inline uint32_t __attribute__((always_inline))
-virtio_dev_rx_zcp(struct virtio_net *dev, struct rte_mbuf **pkts,
- uint32_t count)
-{
- struct vhost_virtqueue *vq;
- struct vring_desc *desc;
- struct rte_mbuf *buff;
- /* The virtio_hdr is initialised to 0. */
- struct virtio_net_hdr_mrg_rxbuf virtio_hdr
- = {{0, 0, 0, 0, 0, 0}, 0};
- uint64_t buff_hdr_addr = 0;
- uint32_t head[MAX_PKT_BURST], packet_len = 0;
- uint32_t head_idx, packet_success = 0;
- uint16_t res_cur_idx;
-
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_rx()\n", dev->device_fh);
-
- if (count == 0)
- return 0;
-
- vq = dev->virtqueue[VIRTIO_RXQ];
- count = (count > MAX_PKT_BURST) ? MAX_PKT_BURST : count;
-
- res_cur_idx = vq->last_used_idx;
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Current Index %d| End Index %d\n",
- dev->device_fh, res_cur_idx, res_cur_idx + count);
-
- /* Retrieve all of the head indexes first to avoid caching issues. */
- for (head_idx = 0; head_idx < count; head_idx++)
- head[head_idx] = MBUF_HEADROOM_UINT32(pkts[head_idx]);
-
- /*Prefetch descriptor index. */
- rte_prefetch0(&vq->desc[head[packet_success]]);
-
- while (packet_success != count) {
- /* Get descriptor from available ring */
- desc = &vq->desc[head[packet_success]];
-
- buff = pkts[packet_success];
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in dev_rx_zcp: update the used idx for "
- "pkt[%d] descriptor idx: %d\n",
- dev->device_fh, packet_success,
- MBUF_HEADROOM_UINT32(buff));
-
- PRINT_PACKET(dev,
- (uintptr_t)(((uint64_t)(uintptr_t)buff->buf_addr)
- + RTE_PKTMBUF_HEADROOM),
- rte_pktmbuf_data_len(buff), 0);
-
- /* Buffer address translation for virtio header. */
- buff_hdr_addr = gpa_to_vva(dev, desc->addr);
- packet_len = rte_pktmbuf_data_len(buff) + vq->vhost_hlen;
-
- /*
- * If the descriptors are chained the header and data are
- * placed in separate buffers.
- */
- if (desc->flags & VRING_DESC_F_NEXT) {
- desc->len = vq->vhost_hlen;
- desc = &vq->desc[desc->next];
- desc->len = rte_pktmbuf_data_len(buff);
- } else {
- desc->len = packet_len;
- }
-
- /* Update used ring with desc information */
- vq->used->ring[res_cur_idx & (vq->size - 1)].id
- = head[packet_success];
- vq->used->ring[res_cur_idx & (vq->size - 1)].len
- = packet_len;
- res_cur_idx++;
- packet_success++;
-
- /* A header is required per buffer. */
- rte_memcpy((void *)(uintptr_t)buff_hdr_addr,
- (const void *)&virtio_hdr, vq->vhost_hlen);
-
- PRINT_PACKET(dev, (uintptr_t)buff_hdr_addr, vq->vhost_hlen, 1);
-
- if (likely(packet_success < count)) {
- /* Prefetch descriptor index. */
- rte_prefetch0(&vq->desc[head[packet_success]]);
- }
- }
-
- rte_compiler_barrier();
-
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in dev_rx_zcp: before update used idx: "
- "vq.last_used_idx: %d, vq->used->idx: %d\n",
- dev->device_fh, vq->last_used_idx, vq->used->idx);
-
- *(volatile uint16_t *)&vq->used->idx += count;
- vq->last_used_idx += count;
-
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in dev_rx_zcp: after update used idx: "
- "vq.last_used_idx: %d, vq->used->idx: %d\n",
- dev->device_fh, vq->last_used_idx, vq->used->idx);
-
- /* Kick the guest if necessary. */
- if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
- eventfd_write(vq->callfd, (eventfd_t)1);
-
- return count;
-}
-
-/*
- * This function routes the TX packet to the correct interface.
- * This may be a local device or the physical port.
+ * for each vhost device {
+ * - drain_eth_rx()
+ *
+ * Which drains the host eth Rx queue linked to the vhost device,
+ * and deliver all of them to guest virito Rx ring associated with
+ * this vhost device.
+ *
+ * - drain_virtio_tx()
+ *
+ * Which drains the guest virtio Tx queue and deliver all of them
+ * to the target, which could be another vhost device, or the
+ * physical eth dev. The route is done in function "virtio_tx_route".
+ * }
*/
-static inline void __attribute__((always_inline))
-virtio_tx_route_zcp(struct virtio_net *dev, struct rte_mbuf *m,
- uint32_t desc_idx, uint8_t need_copy)
+static int
+switch_worker(void *arg __rte_unused)
{
+ unsigned i;
+ unsigned lcore_id = rte_lcore_id();
+ struct vhost_dev *vdev;
struct mbuf_table *tx_q;
- struct rte_mbuf **m_table;
- void *obj = NULL;
- struct rte_mbuf *mbuf;
- unsigned len, ret, offset = 0;
- struct vpool *vpool;
- uint16_t vlan_tag = (uint16_t)vlan_tags[(uint16_t)dev->device_fh];
- uint16_t vmdq_rx_q = ((struct vhost_dev *)dev->priv)->vmdq_rx_q;
-
- /*Add packet to the port tx queue*/
- tx_q = &tx_queue_zcp[vmdq_rx_q];
- len = tx_q->len;
-
- /* Allocate an mbuf and populate the structure. */
- vpool = &vpool_array[MAX_QUEUES + vmdq_rx_q];
- rte_ring_sc_dequeue(vpool->ring, &obj);
- mbuf = obj;
- if (unlikely(mbuf == NULL)) {
- struct vhost_virtqueue *vq = dev->virtqueue[VIRTIO_TXQ];
- RTE_LOG(ERR, VHOST_DATA,
- "(%"PRIu64") Failed to allocate memory for mbuf.\n",
- dev->device_fh);
- put_desc_to_used_list_zcp(vq, desc_idx);
- return;
- }
-
- if (vm2vm_mode == VM2VM_HARDWARE) {
- /* Avoid using a vlan tag from any vm for external pkt, such as
- * vlan_tags[dev->device_fh], oterwise, it conflicts when pool
- * selection, MAC address determines it as an external pkt
- * which should go to network, while vlan tag determine it as
- * a vm2vm pkt should forward to another vm. Hardware confuse
- * such a ambiguous situation, so pkt will lost.
- */
- vlan_tag = external_pkt_default_vlan_tag;
- if (find_local_dest(dev, m, &offset, &vlan_tag) != 0) {
- MBUF_HEADROOM_UINT32(mbuf) = (uint32_t)desc_idx;
- __rte_mbuf_raw_free(mbuf);
- return;
- }
- }
-
- mbuf->nb_segs = m->nb_segs;
- mbuf->next = m->next;
- mbuf->data_len = m->data_len + offset;
- mbuf->pkt_len = mbuf->data_len;
- if (unlikely(need_copy)) {
- /* Copy the packet contents to the mbuf. */
- rte_memcpy(rte_pktmbuf_mtod(mbuf, void *),
- rte_pktmbuf_mtod(m, void *),
- m->data_len);
- } else {
- mbuf->data_off = m->data_off;
- mbuf->buf_physaddr = m->buf_physaddr;
- mbuf->buf_addr = m->buf_addr;
- }
- mbuf->ol_flags |= PKT_TX_VLAN_PKT;
- mbuf->vlan_tci = vlan_tag;
- mbuf->l2_len = sizeof(struct ether_hdr);
- mbuf->l3_len = sizeof(struct ipv4_hdr);
- MBUF_HEADROOM_UINT32(mbuf) = (uint32_t)desc_idx;
-
- tx_q->m_table[len] = mbuf;
- len++;
-
- LOG_DEBUG(VHOST_DATA,
- "(%"PRIu64") in tx_route_zcp: pkt: nb_seg: %d, next:%s\n",
- dev->device_fh,
- mbuf->nb_segs,
- (mbuf->next == NULL) ? "null" : "non-null");
-
- if (enable_stats) {
- dev_statistics[dev->device_fh].tx_total++;
- dev_statistics[dev->device_fh].tx++;
- }
- if (unlikely(len == MAX_PKT_BURST)) {
- m_table = (struct rte_mbuf **)tx_q->m_table;
- ret = rte_eth_tx_burst(ports[0],
- (uint16_t)tx_q->txq_id, m_table, (uint16_t) len);
+ RTE_LOG(INFO, VHOST_DATA, "Procesing on Core %u started\n", lcore_id);
- /*
- * Free any buffers not handled by TX and update
- * the port stats.
- */
- if (unlikely(ret < len)) {
- do {
- rte_pktmbuf_free(m_table[ret]);
- } while (++ret < len);
+ tx_q = &lcore_tx_queue[lcore_id];
+ for (i = 0; i < rte_lcore_count(); i++) {
+ if (lcore_ids[i] == lcore_id) {
+ tx_q->txq_id = i;
+ break;
}
-
- len = 0;
- txmbuf_clean_zcp(dev, vpool);
}
- tx_q->len = len;
-
- return;
-}
-
-/*
- * This function TX all available packets in virtio TX queue for one
- * virtio-net device. If it is first packet, it learns MAC address and
- * setup VMDQ.
- */
-static inline void __attribute__((always_inline))
-virtio_dev_tx_zcp(struct virtio_net *dev)
-{
- struct rte_mbuf m;
- struct vhost_virtqueue *vq;
- struct vring_desc *desc;
- uint64_t buff_addr = 0, phys_addr;
- uint32_t head[MAX_PKT_BURST];
- uint32_t i;
- uint16_t free_entries, packet_success = 0;
- uint16_t avail_idx;
- uint8_t need_copy = 0;
- hpa_type addr_type;
- struct vhost_dev *vdev = (struct vhost_dev *)dev->priv;
-
- vq = dev->virtqueue[VIRTIO_TXQ];
- avail_idx = *((volatile uint16_t *)&vq->avail->idx);
-
- /* If there are no available buffers then return. */
- if (vq->last_used_idx_res == avail_idx)
- return;
-
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_tx()\n", dev->device_fh);
-
- /* Prefetch available ring to retrieve head indexes. */
- rte_prefetch0(&vq->avail->ring[vq->last_used_idx_res & (vq->size - 1)]);
-
- /* Get the number of free entries in the ring */
- free_entries = (avail_idx - vq->last_used_idx_res);
-
- /* Limit to MAX_PKT_BURST. */
- free_entries
- = (free_entries > MAX_PKT_BURST) ? MAX_PKT_BURST : free_entries;
-
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Buffers available %d\n",
- dev->device_fh, free_entries);
-
- /* Retrieve all of the head indexes first to avoid caching issues. */
- for (i = 0; i < free_entries; i++)
- head[i]
- = vq->avail->ring[(vq->last_used_idx_res + i)
- & (vq->size - 1)];
-
- vq->last_used_idx_res += free_entries;
-
- /* Prefetch descriptor index. */
- rte_prefetch0(&vq->desc[head[packet_success]]);
- rte_prefetch0(&vq->used->ring[vq->last_used_idx & (vq->size - 1)]);
-
- while (packet_success < free_entries) {
- desc = &vq->desc[head[packet_success]];
-
- /* Discard first buffer as it is the virtio header */
- desc = &vq->desc[desc->next];
-
- /* Buffer address translation. */
- buff_addr = gpa_to_vva(dev, desc->addr);
- /* Need check extra VLAN_HLEN size for inserting VLAN tag */
- phys_addr = gpa_to_hpa(vdev, desc->addr, desc->len + VLAN_HLEN,
- &addr_type);
-
- if (likely(packet_success < (free_entries - 1)))
- /* Prefetch descriptor index. */
- rte_prefetch0(&vq->desc[head[packet_success + 1]]);
-
- if (unlikely(addr_type == PHYS_ADDR_INVALID)) {
- RTE_LOG(ERR, VHOST_DATA,
- "(%"PRIu64") Invalid frame buffer address found"
- "when TX packets!\n",
- dev->device_fh);
- packet_success++;
- continue;
- }
-
- /* Prefetch buffer address. */
- rte_prefetch0((void *)(uintptr_t)buff_addr);
-
- /*
- * Setup dummy mbuf. This is copied to a real mbuf if
- * transmitted out the physical port.
- */
- m.data_len = desc->len;
- m.nb_segs = 1;
- m.next = NULL;
- m.data_off = 0;
- m.buf_addr = (void *)(uintptr_t)buff_addr;
- m.buf_physaddr = phys_addr;
-
- /*
- * Check if the frame buffer address from guest crosses
- * sub-region or not.
- */
- if (unlikely(addr_type == PHYS_ADDR_CROSS_SUBREG)) {
- RTE_LOG(ERR, VHOST_DATA,
- "(%"PRIu64") Frame buffer address cross "
- "sub-regioin found when attaching TX frame "
- "buffer address!\n",
- dev->device_fh);
- need_copy = 1;
- } else
- need_copy = 0;
-
- PRINT_PACKET(dev, (uintptr_t)buff_addr, desc->len, 0);
+ while(1) {
+ drain_mbuf_table(tx_q);
/*
- * If this is the first received packet we need to learn
- * the MAC and setup VMDQ
+ * Inform the configuration core that we have exited the
+ * linked list and that no devices are in use if requested.
*/
- if (unlikely(vdev->ready == DEVICE_MAC_LEARNING)) {
- if (vdev->remove || (link_vmdq(vdev, &m) == -1)) {
- /*
- * Discard frame if device is scheduled for
- * removal or a duplicate MAC address is found.
- */
- packet_success += free_entries;
- vq->last_used_idx += packet_success;
- break;
- }
- }
-
- virtio_tx_route_zcp(dev, &m, head[packet_success], need_copy);
- packet_success++;
- }
-}
-
-/*
- * This function is called by each data core. It handles all RX/TX registered
- * with the core. For TX the specific lcore linked list is used. For RX, MAC
- * addresses are compared with all devices in the main linked list.
- */
-static int
-switch_worker_zcp(__attribute__((unused)) void *arg)
-{
- struct virtio_net *dev = NULL;
- struct vhost_dev *vdev = NULL;
- struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
- struct virtio_net_data_ll *dev_ll;
- struct mbuf_table *tx_q;
- volatile struct lcore_ll_info *lcore_ll;
- const uint64_t drain_tsc
- = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S
- * BURST_TX_DRAIN_US;
- uint64_t prev_tsc, diff_tsc, cur_tsc, ret_count = 0;
- unsigned ret;
- const uint16_t lcore_id = rte_lcore_id();
- uint16_t count_in_ring, rx_count = 0;
-
- RTE_LOG(INFO, VHOST_DATA, "Procesing on Core %u started\n", lcore_id);
-
- lcore_ll = lcore_info[lcore_id].lcore_ll;
- prev_tsc = 0;
-
- while (1) {
- cur_tsc = rte_rdtsc();
-
- /* TX burst queue drain */
- diff_tsc = cur_tsc - prev_tsc;
- if (unlikely(diff_tsc > drain_tsc)) {
- /*
- * Get mbuf from vpool.pool and detach mbuf and
- * put back into vpool.ring.
- */
- dev_ll = lcore_ll->ll_root_used;
- while ((dev_ll != NULL) && (dev_ll->vdev != NULL)) {
- /* Get virtio device ID */
- vdev = dev_ll->vdev;
- dev = vdev->dev;
-
- if (likely(!vdev->remove)) {
- tx_q = &tx_queue_zcp[(uint16_t)vdev->vmdq_rx_q];
- if (tx_q->len) {
- LOG_DEBUG(VHOST_DATA,
- "TX queue drained after timeout"
- " with burst size %u\n",
- tx_q->len);
-
- /*
- * Tx any packets in the queue
- */
- ret = rte_eth_tx_burst(
- ports[0],
- (uint16_t)tx_q->txq_id,
- (struct rte_mbuf **)
- tx_q->m_table,
- (uint16_t)tx_q->len);
- if (unlikely(ret < tx_q->len)) {
- do {
- rte_pktmbuf_free(
- tx_q->m_table[ret]);
- } while (++ret < tx_q->len);
- }
- tx_q->len = 0;
-
- txmbuf_clean_zcp(dev,
- &vpool_array[MAX_QUEUES+vdev->vmdq_rx_q]);
- }
- }
- dev_ll = dev_ll->next;
- }
- prev_tsc = cur_tsc;
- }
-
- rte_prefetch0(lcore_ll->ll_root_used);
+ if (lcore_info[lcore_id].dev_removal_flag == REQUEST_DEV_REMOVAL)
+ lcore_info[lcore_id].dev_removal_flag = ACK_DEV_REMOVAL;
/*
- * Inform the configuration core that we have exited the linked
- * list and that no devices are in use if requested.
+ * Process vhost devices
*/
- if (lcore_ll->dev_removal_flag == REQUEST_DEV_REMOVAL)
- lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL;
-
- /* Process devices */
- dev_ll = lcore_ll->ll_root_used;
-
- while ((dev_ll != NULL) && (dev_ll->vdev != NULL)) {
- vdev = dev_ll->vdev;
- dev = vdev->dev;
+ TAILQ_FOREACH(vdev, &lcore_info[lcore_id].vdev_list,
+ lcore_vdev_entry) {
if (unlikely(vdev->remove)) {
- dev_ll = dev_ll->next;
unlink_vmdq(vdev);
vdev->ready = DEVICE_SAFE_REMOVE;
continue;
}
- if (likely(vdev->ready == DEVICE_RX)) {
- uint32_t index = vdev->vmdq_rx_q;
- uint16_t i;
- count_in_ring
- = rte_ring_count(vpool_array[index].ring);
- uint16_t free_entries
- = (uint16_t)get_available_ring_num_zcp(dev);
-
- /*
- * Attach all mbufs in vpool.ring and put back
- * into vpool.pool.
- */
- for (i = 0;
- i < RTE_MIN(free_entries,
- RTE_MIN(count_in_ring, MAX_PKT_BURST));
- i++)
- attach_rxmbuf_zcp(dev);
-
- /* Handle guest RX */
- rx_count = rte_eth_rx_burst(ports[0],
- vdev->vmdq_rx_q, pkts_burst,
- MAX_PKT_BURST);
-
- if (rx_count) {
- ret_count = virtio_dev_rx_zcp(dev,
- pkts_burst, rx_count);
- if (enable_stats) {
- dev_statistics[dev->device_fh].rx_total
- += rx_count;
- dev_statistics[dev->device_fh].rx
- += ret_count;
- }
- while (likely(rx_count)) {
- rx_count--;
- pktmbuf_detach_zcp(
- pkts_burst[rx_count]);
- rte_ring_sp_enqueue(
- vpool_array[index].ring,
- (void *)pkts_burst[rx_count]);
- }
- }
- }
+ if (likely(vdev->ready == DEVICE_RX))
+ drain_eth_rx(vdev);
if (likely(!vdev->remove))
- /* Handle guest TX */
- virtio_dev_tx_zcp(dev);
-
- /* Move to the next device in the list */
- dev_ll = dev_ll->next;
+ drain_virtio_tx(vdev);
}
}
return 0;
}
-
-/*
- * Add an entry to a used linked list. A free entry must first be found
- * in the free linked list using get_data_ll_free_entry();
- */
-static void
-add_data_ll_entry(struct virtio_net_data_ll **ll_root_addr,
- struct virtio_net_data_ll *ll_dev)
-{
- struct virtio_net_data_ll *ll = *ll_root_addr;
-
- /* Set next as NULL and use a compiler barrier to avoid reordering. */
- ll_dev->next = NULL;
- rte_compiler_barrier();
-
- /* If ll == NULL then this is the first device. */
- if (ll) {
- /* Increment to the tail of the linked list. */
- while ((ll->next != NULL) )
- ll = ll->next;
-
- ll->next = ll_dev;
- } else {
- *ll_root_addr = ll_dev;
- }
-}
-
-/*
- * Remove an entry from a used linked list. The entry must then be added to
- * the free linked list using put_data_ll_free_entry().
- */
-static void
-rm_data_ll_entry(struct virtio_net_data_ll **ll_root_addr,
- struct virtio_net_data_ll *ll_dev,
- struct virtio_net_data_ll *ll_dev_last)
-{
- struct virtio_net_data_ll *ll = *ll_root_addr;
-
- if (unlikely((ll == NULL) || (ll_dev == NULL)))
- return;
-
- if (ll_dev == ll)
- *ll_root_addr = ll_dev->next;
- else
- if (likely(ll_dev_last != NULL))
- ll_dev_last->next = ll_dev->next;
- else
- RTE_LOG(ERR, VHOST_CONFIG, "Remove entry form ll failed.\n");
-}
-
-/*
- * Find and return an entry from the free linked list.
- */
-static struct virtio_net_data_ll *
-get_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr)
-{
- struct virtio_net_data_ll *ll_free = *ll_root_addr;
- struct virtio_net_data_ll *ll_dev;
-
- if (ll_free == NULL)
- return NULL;
-
- ll_dev = ll_free;
- *ll_root_addr = ll_free->next;
-
- return ll_dev;
-}
-
-/*
- * Place an entry back on to the free linked list.
- */
-static void
-put_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr,
- struct virtio_net_data_ll *ll_dev)
-{
- struct virtio_net_data_ll *ll_free = *ll_root_addr;
-
- if (ll_dev == NULL)
- return;
-
- ll_dev->next = ll_free;
- *ll_root_addr = ll_dev;
-}
-
/*
- * Creates a linked list of a given size.
- */
-static struct virtio_net_data_ll *
-alloc_data_ll(uint32_t size)
-{
- struct virtio_net_data_ll *ll_new;
- uint32_t i;
-
- /* Malloc and then chain the linked list. */
- ll_new = malloc(size * sizeof(struct virtio_net_data_ll));
- if (ll_new == NULL) {
- RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for ll_new.\n");
- return NULL;
- }
-
- for (i = 0; i < size - 1; i++) {
- ll_new[i].vdev = NULL;
- ll_new[i].next = &ll_new[i+1];
- }
- ll_new[i].next = NULL;
-
- return ll_new;
-}
-
-/*
- * Create the main linked list along with each individual cores linked list. A used and a free list
- * are created to manage entries.
- */
-static int
-init_data_ll (void)
-{
- int lcore;
-
- RTE_LCORE_FOREACH_SLAVE(lcore) {
- lcore_info[lcore].lcore_ll = malloc(sizeof(struct lcore_ll_info));
- if (lcore_info[lcore].lcore_ll == NULL) {
- RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for lcore_ll.\n");
- return -1;
- }
-
- lcore_info[lcore].lcore_ll->device_num = 0;
- lcore_info[lcore].lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL;
- lcore_info[lcore].lcore_ll->ll_root_used = NULL;
- if (num_devices % num_switching_cores)
- lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll((num_devices / num_switching_cores) + 1);
- else
- lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll(num_devices / num_switching_cores);
- }
-
- /* Allocate devices up to a maximum of MAX_DEVICES. */
- ll_root_free = alloc_data_ll(MIN((num_devices), MAX_DEVICES));
-
- return 0;
-}
-
-/*
- * Remove a device from the specific data core linked list and from the main linked list. Synchonization
- * occurs through the use of the lcore dev_removal_flag. Device is made volatile here to avoid re-ordering
+ * Remove a device from the specific data core linked list and from the
+ * main linked list. Synchonization occurs through the use of the
+ * lcore dev_removal_flag. Device is made volatile here to avoid re-ordering
* of dev->remove=1 which can cause an infinite loop in the rte_pause loop.
*/
static void
-destroy_device (volatile struct virtio_net *dev)
+destroy_device(int vid)
{
- struct virtio_net_data_ll *ll_lcore_dev_cur;
- struct virtio_net_data_ll *ll_main_dev_cur;
- struct virtio_net_data_ll *ll_lcore_dev_last = NULL;
- struct virtio_net_data_ll *ll_main_dev_last = NULL;
- struct vhost_dev *vdev;
+ struct vhost_dev *vdev = NULL;
int lcore;
- dev->flags &= ~VIRTIO_DEV_RUNNING;
-
- vdev = (struct vhost_dev *)dev->priv;
+ TAILQ_FOREACH(vdev, &vhost_dev_list, global_vdev_entry) {
+ if (vdev->vid == vid)
+ break;
+ }
+ if (!vdev)
+ return;
/*set the remove flag. */
vdev->remove = 1;
while(vdev->ready != DEVICE_SAFE_REMOVE) {
rte_pause();
}
- /* Search for entry to be removed from lcore ll */
- ll_lcore_dev_cur = lcore_info[vdev->coreid].lcore_ll->ll_root_used;
- while (ll_lcore_dev_cur != NULL) {
- if (ll_lcore_dev_cur->vdev == vdev) {
- break;
- } else {
- ll_lcore_dev_last = ll_lcore_dev_cur;
- ll_lcore_dev_cur = ll_lcore_dev_cur->next;
- }
- }
-
- if (ll_lcore_dev_cur == NULL) {
- RTE_LOG(ERR, VHOST_CONFIG,
- "(%"PRIu64") Failed to find the dev to be destroy.\n",
- dev->device_fh);
- return;
- }
+ TAILQ_REMOVE(&lcore_info[vdev->coreid].vdev_list, vdev,
+ lcore_vdev_entry);
+ TAILQ_REMOVE(&vhost_dev_list, vdev, global_vdev_entry);
- /* Search for entry to be removed from main ll */
- ll_main_dev_cur = ll_root_used;
- ll_main_dev_last = NULL;
- while (ll_main_dev_cur != NULL) {
- if (ll_main_dev_cur->vdev == vdev) {
- break;
- } else {
- ll_main_dev_last = ll_main_dev_cur;
- ll_main_dev_cur = ll_main_dev_cur->next;
- }
- }
-
- /* Remove entries from the lcore and main ll. */
- rm_data_ll_entry(&lcore_info[vdev->coreid].lcore_ll->ll_root_used, ll_lcore_dev_cur, ll_lcore_dev_last);
- rm_data_ll_entry(&ll_root_used, ll_main_dev_cur, ll_main_dev_last);
/* Set the dev_removal_flag on each lcore. */
- RTE_LCORE_FOREACH_SLAVE(lcore) {
- lcore_info[lcore].lcore_ll->dev_removal_flag = REQUEST_DEV_REMOVAL;
- }
+ RTE_LCORE_FOREACH_SLAVE(lcore)
+ lcore_info[lcore].dev_removal_flag = REQUEST_DEV_REMOVAL;
/*
- * Once each core has set the dev_removal_flag to ACK_DEV_REMOVAL we can be sure that
- * they can no longer access the device removed from the linked lists and that the devices
- * are no longer in use.
+ * Once each core has set the dev_removal_flag to ACK_DEV_REMOVAL
+ * we can be sure that they can no longer access the device removed
+ * from the linked lists and that the devices are no longer in use.
*/
RTE_LCORE_FOREACH_SLAVE(lcore) {
- while (lcore_info[lcore].lcore_ll->dev_removal_flag != ACK_DEV_REMOVAL) {
+ while (lcore_info[lcore].dev_removal_flag != ACK_DEV_REMOVAL)
rte_pause();
- }
}
- /* Add the entries back to the lcore and main free ll.*/
- put_data_ll_free_entry(&lcore_info[vdev->coreid].lcore_ll->ll_root_free, ll_lcore_dev_cur);
- put_data_ll_free_entry(&ll_root_free, ll_main_dev_cur);
+ lcore_info[vdev->coreid].device_num--;
- /* Decrement number of device on the lcore. */
- lcore_info[vdev->coreid].lcore_ll->device_num--;
+ RTE_LOG(INFO, VHOST_DATA,
+ "(%d) device has been removed from data core\n",
+ vdev->vid);
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been removed from data core\n", dev->device_fh);
-
- if (zero_copy) {
- struct vpool *vpool = &vpool_array[vdev->vmdq_rx_q];
-
- /* Stop the RX queue. */
- if (rte_eth_dev_rx_queue_stop(ports[0], vdev->vmdq_rx_q) != 0) {
- LOG_DEBUG(VHOST_CONFIG,
- "(%"PRIu64") In destroy_device: Failed to stop "
- "rx queue:%d\n",
- dev->device_fh,
- vdev->vmdq_rx_q);
- }
-
- LOG_DEBUG(VHOST_CONFIG,
- "(%"PRIu64") in destroy_device: Start put mbuf in "
- "mempool back to ring for RX queue: %d\n",
- dev->device_fh, vdev->vmdq_rx_q);
-
- mbuf_destroy_zcp(vpool);
-
- /* Stop the TX queue. */
- if (rte_eth_dev_tx_queue_stop(ports[0], vdev->vmdq_rx_q) != 0) {
- LOG_DEBUG(VHOST_CONFIG,
- "(%"PRIu64") In destroy_device: Failed to "
- "stop tx queue:%d\n",
- dev->device_fh, vdev->vmdq_rx_q);
- }
-
- vpool = &vpool_array[vdev->vmdq_rx_q + MAX_QUEUES];
-
- LOG_DEBUG(VHOST_CONFIG,
- "(%"PRIu64") destroy_device: Start put mbuf in mempool "
- "back to ring for TX queue: %d, dev:(%"PRIu64")\n",
- dev->device_fh, (vdev->vmdq_rx_q + MAX_QUEUES),
- dev->device_fh);
-
- mbuf_destroy_zcp(vpool);
- rte_free(vdev->regions_hpa);
- }
rte_free(vdev);
-
-}
-
-/*
- * Calculate the region count of physical continous regions for one particular
- * region of whose vhost virtual address is continous. The particular region
- * start from vva_start, with size of 'size' in argument.
- */
-static uint32_t
-check_hpa_regions(uint64_t vva_start, uint64_t size)
-{
- uint32_t i, nregions = 0, page_size = getpagesize();
- uint64_t cur_phys_addr = 0, next_phys_addr = 0;
- if (vva_start % page_size) {
- LOG_DEBUG(VHOST_CONFIG,
- "in check_countinous: vva start(%p) mod page_size(%d) "
- "has remainder\n",
- (void *)(uintptr_t)vva_start, page_size);
- return 0;
- }
- if (size % page_size) {
- LOG_DEBUG(VHOST_CONFIG,
- "in check_countinous: "
- "size((%"PRIu64")) mod page_size(%d) has remainder\n",
- size, page_size);
- return 0;
- }
- for (i = 0; i < size - page_size; i = i + page_size) {
- cur_phys_addr
- = rte_mem_virt2phy((void *)(uintptr_t)(vva_start + i));
- next_phys_addr = rte_mem_virt2phy(
- (void *)(uintptr_t)(vva_start + i + page_size));
- if ((cur_phys_addr + page_size) != next_phys_addr) {
- ++nregions;
- LOG_DEBUG(VHOST_CONFIG,
- "in check_continuous: hva addr:(%p) is not "
- "continuous with hva addr:(%p), diff:%d\n",
- (void *)(uintptr_t)(vva_start + (uint64_t)i),
- (void *)(uintptr_t)(vva_start + (uint64_t)i
- + page_size), page_size);
- LOG_DEBUG(VHOST_CONFIG,
- "in check_continuous: hpa addr:(%p) is not "
- "continuous with hpa addr:(%p), "
- "diff:(%"PRIu64")\n",
- (void *)(uintptr_t)cur_phys_addr,
- (void *)(uintptr_t)next_phys_addr,
- (next_phys_addr-cur_phys_addr));
- }
- }
- return nregions;
-}
-
-/*
- * Divide each region whose vhost virtual address is continous into a few
- * sub-regions, make sure the physical address within each sub-region are
- * continous. And fill offset(to GPA) and size etc. information of each
- * sub-region into regions_hpa.
- */
-static uint32_t
-fill_hpa_memory_regions(struct virtio_memory_regions_hpa *mem_region_hpa, struct virtio_memory *virtio_memory)
-{
- uint32_t regionidx, regionidx_hpa = 0, i, k, page_size = getpagesize();
- uint64_t cur_phys_addr = 0, next_phys_addr = 0, vva_start;
-
- if (mem_region_hpa == NULL)
- return 0;
-
- for (regionidx = 0; regionidx < virtio_memory->nregions; regionidx++) {
- vva_start = virtio_memory->regions[regionidx].guest_phys_address +
- virtio_memory->regions[regionidx].address_offset;
- mem_region_hpa[regionidx_hpa].guest_phys_address
- = virtio_memory->regions[regionidx].guest_phys_address;
- mem_region_hpa[regionidx_hpa].host_phys_addr_offset =
- rte_mem_virt2phy((void *)(uintptr_t)(vva_start)) -
- mem_region_hpa[regionidx_hpa].guest_phys_address;
- LOG_DEBUG(VHOST_CONFIG,
- "in fill_hpa_regions: guest phys addr start[%d]:(%p)\n",
- regionidx_hpa,
- (void *)(uintptr_t)
- (mem_region_hpa[regionidx_hpa].guest_phys_address));
- LOG_DEBUG(VHOST_CONFIG,
- "in fill_hpa_regions: host phys addr start[%d]:(%p)\n",
- regionidx_hpa,
- (void *)(uintptr_t)
- (mem_region_hpa[regionidx_hpa].host_phys_addr_offset));
- for (i = 0, k = 0;
- i < virtio_memory->regions[regionidx].memory_size -
- page_size;
- i += page_size) {
- cur_phys_addr = rte_mem_virt2phy(
- (void *)(uintptr_t)(vva_start + i));
- next_phys_addr = rte_mem_virt2phy(
- (void *)(uintptr_t)(vva_start +
- i + page_size));
- if ((cur_phys_addr + page_size) != next_phys_addr) {
- mem_region_hpa[regionidx_hpa].guest_phys_address_end =
- mem_region_hpa[regionidx_hpa].guest_phys_address +
- k + page_size;
- mem_region_hpa[regionidx_hpa].memory_size
- = k + page_size;
- LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest "
- "phys addr end [%d]:(%p)\n",
- regionidx_hpa,
- (void *)(uintptr_t)
- (mem_region_hpa[regionidx_hpa].guest_phys_address_end));
- LOG_DEBUG(VHOST_CONFIG,
- "in fill_hpa_regions: guest phys addr "
- "size [%d]:(%p)\n",
- regionidx_hpa,
- (void *)(uintptr_t)
- (mem_region_hpa[regionidx_hpa].memory_size));
- mem_region_hpa[regionidx_hpa + 1].guest_phys_address
- = mem_region_hpa[regionidx_hpa].guest_phys_address_end;
- ++regionidx_hpa;
- mem_region_hpa[regionidx_hpa].host_phys_addr_offset =
- next_phys_addr -
- mem_region_hpa[regionidx_hpa].guest_phys_address;
- LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest"
- " phys addr start[%d]:(%p)\n",
- regionidx_hpa,
- (void *)(uintptr_t)
- (mem_region_hpa[regionidx_hpa].guest_phys_address));
- LOG_DEBUG(VHOST_CONFIG,
- "in fill_hpa_regions: host phys addr "
- "start[%d]:(%p)\n",
- regionidx_hpa,
- (void *)(uintptr_t)
- (mem_region_hpa[regionidx_hpa].host_phys_addr_offset));
- k = 0;
- } else {
- k += page_size;
- }
- }
- mem_region_hpa[regionidx_hpa].guest_phys_address_end
- = mem_region_hpa[regionidx_hpa].guest_phys_address
- + k + page_size;
- mem_region_hpa[regionidx_hpa].memory_size = k + page_size;
- LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest phys addr end "
- "[%d]:(%p)\n", regionidx_hpa,
- (void *)(uintptr_t)
- (mem_region_hpa[regionidx_hpa].guest_phys_address_end));
- LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest phys addr size "
- "[%d]:(%p)\n", regionidx_hpa,
- (void *)(uintptr_t)
- (mem_region_hpa[regionidx_hpa].memory_size));
- ++regionidx_hpa;
- }
- return regionidx_hpa;
}
/*
@@ -2654,148 +1224,23 @@ fill_hpa_memory_regions(struct virtio_memory_regions_hpa *mem_region_hpa, struct
* and the allocated to a specific data core.
*/
static int
-new_device (struct virtio_net *dev)
+new_device(int vid)
{
- struct virtio_net_data_ll *ll_dev;
int lcore, core_add = 0;
uint32_t device_num_min = num_devices;
struct vhost_dev *vdev;
- uint32_t regionidx;
vdev = rte_zmalloc("vhost device", sizeof(*vdev), RTE_CACHE_LINE_SIZE);
if (vdev == NULL) {
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Couldn't allocate memory for vhost dev\n",
- dev->device_fh);
+ RTE_LOG(INFO, VHOST_DATA,
+ "(%d) couldn't allocate memory for vhost dev\n",
+ vid);
return -1;
}
- vdev->dev = dev;
- dev->priv = vdev;
-
- if (zero_copy) {
- vdev->nregions_hpa = dev->mem->nregions;
- for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) {
- vdev->nregions_hpa
- += check_hpa_regions(
- dev->mem->regions[regionidx].guest_phys_address
- + dev->mem->regions[regionidx].address_offset,
- dev->mem->regions[regionidx].memory_size);
+ vdev->vid = vid;
- }
-
- vdev->regions_hpa = rte_calloc("vhost hpa region",
- vdev->nregions_hpa,
- sizeof(struct virtio_memory_regions_hpa),
- RTE_CACHE_LINE_SIZE);
- if (vdev->regions_hpa == NULL) {
- RTE_LOG(ERR, VHOST_CONFIG, "Cannot allocate memory for hpa region\n");
- rte_free(vdev);
- return -1;
- }
-
-
- if (fill_hpa_memory_regions(
- vdev->regions_hpa, dev->mem
- ) != vdev->nregions_hpa) {
-
- RTE_LOG(ERR, VHOST_CONFIG,
- "hpa memory regions number mismatch: "
- "[%d]\n", vdev->nregions_hpa);
- rte_free(vdev->regions_hpa);
- rte_free(vdev);
- return -1;
- }
- }
-
-
- /* Add device to main ll */
- ll_dev = get_data_ll_free_entry(&ll_root_free);
- if (ll_dev == NULL) {
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") No free entry found in linked list. Device limit "
- "of %d devices per core has been reached\n",
- dev->device_fh, num_devices);
- if (vdev->regions_hpa)
- rte_free(vdev->regions_hpa);
- rte_free(vdev);
- return -1;
- }
- ll_dev->vdev = vdev;
- add_data_ll_entry(&ll_root_used, ll_dev);
- vdev->vmdq_rx_q
- = dev->device_fh * queues_per_pool + vmdq_queue_base;
-
- if (zero_copy) {
- uint32_t index = vdev->vmdq_rx_q;
- uint32_t count_in_ring, i;
- struct mbuf_table *tx_q;
-
- count_in_ring = rte_ring_count(vpool_array[index].ring);
-
- LOG_DEBUG(VHOST_CONFIG,
- "(%"PRIu64") in new_device: mbuf count in mempool "
- "before attach is: %d\n",
- dev->device_fh,
- rte_mempool_count(vpool_array[index].pool));
- LOG_DEBUG(VHOST_CONFIG,
- "(%"PRIu64") in new_device: mbuf count in ring "
- "before attach is : %d\n",
- dev->device_fh, count_in_ring);
-
- /*
- * Attach all mbufs in vpool.ring and put back intovpool.pool.
- */
- for (i = 0; i < count_in_ring; i++)
- attach_rxmbuf_zcp(dev);
-
- LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") in new_device: mbuf count in "
- "mempool after attach is: %d\n",
- dev->device_fh,
- rte_mempool_count(vpool_array[index].pool));
- LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") in new_device: mbuf count in "
- "ring after attach is : %d\n",
- dev->device_fh,
- rte_ring_count(vpool_array[index].ring));
-
- tx_q = &tx_queue_zcp[(uint16_t)vdev->vmdq_rx_q];
- tx_q->txq_id = vdev->vmdq_rx_q;
-
- if (rte_eth_dev_tx_queue_start(ports[0], vdev->vmdq_rx_q) != 0) {
- struct vpool *vpool = &vpool_array[vdev->vmdq_rx_q];
-
- LOG_DEBUG(VHOST_CONFIG,
- "(%"PRIu64") In new_device: Failed to start "
- "tx queue:%d\n",
- dev->device_fh, vdev->vmdq_rx_q);
-
- mbuf_destroy_zcp(vpool);
- rte_free(vdev->regions_hpa);
- rte_free(vdev);
- return -1;
- }
-
- if (rte_eth_dev_rx_queue_start(ports[0], vdev->vmdq_rx_q) != 0) {
- struct vpool *vpool = &vpool_array[vdev->vmdq_rx_q];
-
- LOG_DEBUG(VHOST_CONFIG,
- "(%"PRIu64") In new_device: Failed to start "
- "rx queue:%d\n",
- dev->device_fh, vdev->vmdq_rx_q);
-
- /* Stop the TX queue. */
- if (rte_eth_dev_tx_queue_stop(ports[0],
- vdev->vmdq_rx_q) != 0) {
- LOG_DEBUG(VHOST_CONFIG,
- "(%"PRIu64") In new_device: Failed to "
- "stop tx queue:%d\n",
- dev->device_fh, vdev->vmdq_rx_q);
- }
-
- mbuf_destroy_zcp(vpool);
- rte_free(vdev->regions_hpa);
- rte_free(vdev);
- return -1;
- }
-
- }
+ TAILQ_INSERT_TAIL(&vhost_dev_list, vdev, global_vdev_entry);
+ vdev->vmdq_rx_q = vid * queues_per_pool + vmdq_queue_base;
/*reset ready flag*/
vdev->ready = DEVICE_MAC_LEARNING;
@@ -2803,36 +1248,24 @@ new_device (struct virtio_net *dev)
/* Find a suitable lcore to add the device. */
RTE_LCORE_FOREACH_SLAVE(lcore) {
- if (lcore_info[lcore].lcore_ll->device_num < device_num_min) {
- device_num_min = lcore_info[lcore].lcore_ll->device_num;
+ if (lcore_info[lcore].device_num < device_num_min) {
+ device_num_min = lcore_info[lcore].device_num;
core_add = lcore;
}
}
- /* Add device to lcore ll */
- ll_dev = get_data_ll_free_entry(&lcore_info[core_add].lcore_ll->ll_root_free);
- if (ll_dev == NULL) {
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Failed to add device to data core\n", dev->device_fh);
- vdev->ready = DEVICE_SAFE_REMOVE;
- destroy_device(dev);
- rte_free(vdev->regions_hpa);
- rte_free(vdev);
- return -1;
- }
- ll_dev->vdev = vdev;
vdev->coreid = core_add;
- add_data_ll_entry(&lcore_info[vdev->coreid].lcore_ll->ll_root_used, ll_dev);
-
- /* Initialize device stats */
- memset(&dev_statistics[dev->device_fh], 0, sizeof(struct device_statistics));
+ TAILQ_INSERT_TAIL(&lcore_info[vdev->coreid].vdev_list, vdev,
+ lcore_vdev_entry);
+ lcore_info[vdev->coreid].device_num++;
/* Disable notifications. */
- rte_vhost_enable_guest_notification(dev, VIRTIO_RXQ, 0);
- rte_vhost_enable_guest_notification(dev, VIRTIO_TXQ, 0);
- lcore_info[vdev->coreid].lcore_ll->device_num++;
- dev->flags |= VIRTIO_DEV_RUNNING;
+ rte_vhost_enable_guest_notification(vid, VIRTIO_RXQ, 0);
+ rte_vhost_enable_guest_notification(vid, VIRTIO_TXQ, 0);
- RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been added to data core %d\n", dev->device_fh, vdev->coreid);
+ RTE_LOG(INFO, VHOST_DATA,
+ "(%d) device has been added to data core %d\n",
+ vid, vdev->coreid);
return 0;
}
@@ -2854,10 +1287,9 @@ static const struct virtio_net_device_ops virtio_net_device_ops =
static void
print_stats(void)
{
- struct virtio_net_data_ll *dev_ll;
+ struct vhost_dev *vdev;
uint64_t tx_dropped, rx_dropped;
uint64_t tx, tx_total, rx, rx_total;
- uint32_t device_fh;
const char clr[] = { 27, '[', '2', 'J', '\0' };
const char top_left[] = { 27, '[', '1', ';', '1', 'H','\0' };
@@ -2865,77 +1297,32 @@ print_stats(void)
sleep(enable_stats);
/* Clear screen and move to top left */
- printf("%s%s", clr, top_left);
-
- printf("\nDevice statistics ====================================");
+ printf("%s%s\n", clr, top_left);
+ printf("Device statistics =================================\n");
- dev_ll = ll_root_used;
- while (dev_ll != NULL) {
- device_fh = (uint32_t)dev_ll->vdev->dev->device_fh;
- tx_total = dev_statistics[device_fh].tx_total;
- tx = dev_statistics[device_fh].tx;
+ TAILQ_FOREACH(vdev, &vhost_dev_list, global_vdev_entry) {
+ tx_total = vdev->stats.tx_total;
+ tx = vdev->stats.tx;
tx_dropped = tx_total - tx;
- if (zero_copy == 0) {
- rx_total = rte_atomic64_read(
- &dev_statistics[device_fh].rx_total_atomic);
- rx = rte_atomic64_read(
- &dev_statistics[device_fh].rx_atomic);
- } else {
- rx_total = dev_statistics[device_fh].rx_total;
- rx = dev_statistics[device_fh].rx;
- }
+
+ rx_total = rte_atomic64_read(&vdev->stats.rx_total_atomic);
+ rx = rte_atomic64_read(&vdev->stats.rx_atomic);
rx_dropped = rx_total - rx;
- printf("\nStatistics for device %"PRIu32" ------------------------------"
- "\nTX total: %"PRIu64""
- "\nTX dropped: %"PRIu64""
- "\nTX successful: %"PRIu64""
- "\nRX total: %"PRIu64""
- "\nRX dropped: %"PRIu64""
- "\nRX successful: %"PRIu64"",
- device_fh,
- tx_total,
- tx_dropped,
- tx,
- rx_total,
- rx_dropped,
- rx);
-
- dev_ll = dev_ll->next;
+ printf("Statistics for device %d\n"
+ "-----------------------\n"
+ "TX total: %" PRIu64 "\n"
+ "TX dropped: %" PRIu64 "\n"
+ "TX successful: %" PRIu64 "\n"
+ "RX total: %" PRIu64 "\n"
+ "RX dropped: %" PRIu64 "\n"
+ "RX successful: %" PRIu64 "\n",
+ vdev->vid,
+ tx_total, tx_dropped, tx,
+ rx_total, rx_dropped, rx);
}
- printf("\n======================================================\n");
- }
-}
-static void
-setup_mempool_tbl(int socket, uint32_t index, char *pool_name,
- char *ring_name, uint32_t nb_mbuf)
-{
- vpool_array[index].pool = rte_pktmbuf_pool_create(pool_name, nb_mbuf,
- MBUF_CACHE_SIZE_ZCP, 0, MBUF_DATA_SIZE_ZCP, socket);
- if (vpool_array[index].pool != NULL) {
- vpool_array[index].ring
- = rte_ring_create(ring_name,
- rte_align32pow2(nb_mbuf + 1),
- socket, RING_F_SP_ENQ | RING_F_SC_DEQ);
- if (likely(vpool_array[index].ring != NULL)) {
- LOG_DEBUG(VHOST_CONFIG,
- "in setup_mempool_tbl: mbuf count in "
- "mempool is: %d\n",
- rte_mempool_count(vpool_array[index].pool));
- LOG_DEBUG(VHOST_CONFIG,
- "in setup_mempool_tbl: mbuf count in "
- "ring is: %d\n",
- rte_ring_count(vpool_array[index].ring));
- } else {
- rte_exit(EXIT_FAILURE, "ring_create(%s) failed",
- ring_name);
- }
-
- /* Need consider head room. */
- vpool_array[index].buf_size = VIRTIO_DESCRIPTOR_LEN_ZCP;
- } else {
- rte_exit(EXIT_FAILURE, "mempool_create(%s) failed", pool_name);
+ printf("===================================================\n");
}
}
@@ -2951,20 +1338,70 @@ sigint_handler(__rte_unused int signum)
}
/*
+ * While creating an mbuf pool, one key thing is to figure out how
+ * many mbuf entries is enough for our use. FYI, here are some
+ * guidelines:
+ *
+ * - Each rx queue would reserve @nr_rx_desc mbufs at queue setup stage
+ *
+ * - For each switch core (A CPU core does the packet switch), we need
+ * also make some reservation for receiving the packets from virtio
+ * Tx queue. How many is enough depends on the usage. It's normally
+ * a simple calculation like following:
+ *
+ * MAX_PKT_BURST * max packet size / mbuf size
+ *
+ * So, we definitely need allocate more mbufs when TSO is enabled.
+ *
+ * - Similarly, for each switching core, we should serve @nr_rx_desc
+ * mbufs for receiving the packets from physical NIC device.
+ *
+ * - We also need make sure, for each switch core, we have allocated
+ * enough mbufs to fill up the mbuf cache.
+ */
+static void
+create_mbuf_pool(uint16_t nr_port, uint32_t nr_switch_core, uint32_t mbuf_size,
+ uint32_t nr_queues, uint32_t nr_rx_desc, uint32_t nr_mbuf_cache)
+{
+ uint32_t nr_mbufs;
+ uint32_t nr_mbufs_per_core;
+ uint32_t mtu = 1500;
+
+ if (mergeable)
+ mtu = 9000;
+ if (enable_tso)
+ mtu = 64 * 1024;
+
+ nr_mbufs_per_core = (mtu + mbuf_size) * MAX_PKT_BURST /
+ (mbuf_size - RTE_PKTMBUF_HEADROOM) * MAX_PKT_BURST;
+ nr_mbufs_per_core += nr_rx_desc;
+ nr_mbufs_per_core = RTE_MAX(nr_mbufs_per_core, nr_mbuf_cache);
+
+ nr_mbufs = nr_queues * nr_rx_desc;
+ nr_mbufs += nr_mbufs_per_core * nr_switch_core;
+ nr_mbufs *= nr_port;
+
+ mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", nr_mbufs,
+ nr_mbuf_cache, 0, mbuf_size,
+ rte_socket_id());
+ if (mbuf_pool == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
+}
+
+/*
* Main function, does initialisation and calls the per-lcore functions. The CUSE
* device is also registered here to handle the IOCTLs.
*/
int
main(int argc, char *argv[])
{
- struct rte_mempool *mbuf_pool = NULL;
unsigned lcore_id, core_id = 0;
unsigned nb_ports, valid_num_ports;
int ret;
uint8_t portid;
- uint16_t queue_id;
static pthread_t tid;
char thread_name[RTE_MAX_THREAD_NAME_LEN];
+ uint64_t flags = 0;
signal(SIGINT, sigint_handler);
@@ -2981,19 +1418,16 @@ main(int argc, char *argv[])
rte_exit(EXIT_FAILURE, "Invalid argument\n");
for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id ++)
+ TAILQ_INIT(&lcore_info[lcore_id].vdev_list);
+
if (rte_lcore_is_enabled(lcore_id))
lcore_ids[core_id ++] = lcore_id;
if (rte_lcore_count() > RTE_MAX_LCORE)
rte_exit(EXIT_FAILURE,"Not enough cores\n");
- /*set the number of swithcing cores available*/
- num_switching_cores = rte_lcore_count()-1;
-
/* Get the number of physical ports. */
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
/*
* Update the global var NUM_PORTS and global array PORTS
@@ -3007,64 +1441,21 @@ main(int argc, char *argv[])
return -1;
}
- if (zero_copy == 0) {
- /* Create the mbuf pool. */
- mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL",
- NUM_MBUFS_PER_PORT * valid_num_ports, MBUF_CACHE_SIZE,
- 0, MBUF_DATA_SIZE, rte_socket_id());
- if (mbuf_pool == NULL)
- rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
-
- for (queue_id = 0; queue_id < MAX_QUEUES + 1; queue_id++)
- vpool_array[queue_id].pool = mbuf_pool;
-
- if (vm2vm_mode == VM2VM_HARDWARE) {
- /* Enable VT loop back to let L2 switch to do it. */
- vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.enable_loop_back = 1;
- LOG_DEBUG(VHOST_CONFIG,
- "Enable loop back for L2 switch in vmdq.\n");
- }
- } else {
- uint32_t nb_mbuf;
- char pool_name[RTE_MEMPOOL_NAMESIZE];
- char ring_name[RTE_MEMPOOL_NAMESIZE];
-
- nb_mbuf = num_rx_descriptor
- + num_switching_cores * MBUF_CACHE_SIZE_ZCP
- + num_switching_cores * MAX_PKT_BURST;
-
- for (queue_id = 0; queue_id < MAX_QUEUES; queue_id++) {
- snprintf(pool_name, sizeof(pool_name),
- "rxmbuf_pool_%u", queue_id);
- snprintf(ring_name, sizeof(ring_name),
- "rxmbuf_ring_%u", queue_id);
- setup_mempool_tbl(rte_socket_id(), queue_id,
- pool_name, ring_name, nb_mbuf);
- }
-
- nb_mbuf = num_tx_descriptor
- + num_switching_cores * MBUF_CACHE_SIZE_ZCP
- + num_switching_cores * MAX_PKT_BURST;
-
- for (queue_id = 0; queue_id < MAX_QUEUES; queue_id++) {
- snprintf(pool_name, sizeof(pool_name),
- "txmbuf_pool_%u", queue_id);
- snprintf(ring_name, sizeof(ring_name),
- "txmbuf_ring_%u", queue_id);
- setup_mempool_tbl(rte_socket_id(),
- (queue_id + MAX_QUEUES),
- pool_name, ring_name, nb_mbuf);
- }
+ /*
+ * FIXME: here we are trying to allocate mbufs big enough for
+ * @MAX_QUEUES, but the truth is we're never going to use that
+ * many queues here. We probably should only do allocation for
+ * those queues we are going to use.
+ */
+ create_mbuf_pool(valid_num_ports, rte_lcore_count() - 1, MBUF_DATA_SIZE,
+ MAX_QUEUES, RTE_TEST_RX_DESC_DEFAULT, MBUF_CACHE_SIZE);
- if (vm2vm_mode == VM2VM_HARDWARE) {
- /* Enable VT loop back to let L2 switch to do it. */
- vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.enable_loop_back = 1;
- LOG_DEBUG(VHOST_CONFIG,
- "Enable loop back for L2 switch in vmdq.\n");
- }
+ if (vm2vm_mode == VM2VM_HARDWARE) {
+ /* Enable VT loop back to let L2 switch to do it. */
+ vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.enable_loop_back = 1;
+ RTE_LOG(DEBUG, VHOST_CONFIG,
+ "Enable loop back for L2 switch in vmdq.\n");
}
- /* Set log level. */
- rte_set_log_level(LOG_LEVEL);
/* initialize all ports */
for (portid = 0; portid < nb_ports; portid++) {
@@ -3079,13 +1470,6 @@ main(int argc, char *argv[])
"Cannot initialize network ports\n");
}
- /* Initialise all linked lists. */
- if (init_data_ll() == -1)
- rte_exit(EXIT_FAILURE, "Failed to initialize linked list\n");
-
- /* Initialize device stats */
- memset(&dev_statistics, 0, sizeof(dev_statistics));
-
/* Enable stats if the user option is set. */
if (enable_stats) {
ret = pthread_create(&tid, NULL, (void *)print_stats, NULL);
@@ -3097,54 +1481,22 @@ main(int argc, char *argv[])
snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "print-stats");
ret = rte_thread_setname(tid, thread_name);
if (ret != 0)
- RTE_LOG(ERR, VHOST_CONFIG,
+ RTE_LOG(DEBUG, VHOST_CONFIG,
"Cannot set print-stats name\n");
}
/* Launch all data cores. */
- if (zero_copy == 0) {
- RTE_LCORE_FOREACH_SLAVE(lcore_id) {
- rte_eal_remote_launch(switch_worker,
- mbuf_pool, lcore_id);
- }
- } else {
- uint32_t count_in_mempool, index, i;
- for (index = 0; index < 2*MAX_QUEUES; index++) {
- /* For all RX and TX queues. */
- count_in_mempool
- = rte_mempool_count(vpool_array[index].pool);
-
- /*
- * Transfer all un-attached mbufs from vpool.pool
- * to vpoo.ring.
- */
- for (i = 0; i < count_in_mempool; i++) {
- struct rte_mbuf *mbuf
- = __rte_mbuf_raw_alloc(
- vpool_array[index].pool);
- rte_ring_sp_enqueue(vpool_array[index].ring,
- (void *)mbuf);
- }
-
- LOG_DEBUG(VHOST_CONFIG,
- "in main: mbuf count in mempool at initial "
- "is: %d\n", count_in_mempool);
- LOG_DEBUG(VHOST_CONFIG,
- "in main: mbuf count in ring at initial is :"
- " %d\n",
- rte_ring_count(vpool_array[index].ring));
- }
-
- RTE_LCORE_FOREACH_SLAVE(lcore_id)
- rte_eal_remote_launch(switch_worker_zcp, NULL,
- lcore_id);
- }
+ RTE_LCORE_FOREACH_SLAVE(lcore_id)
+ rte_eal_remote_launch(switch_worker, NULL, lcore_id);
if (mergeable == 0)
rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
+ if (client_mode)
+ flags |= RTE_VHOST_USER_CLIENT;
+
/* Register vhost(cuse or user) driver to handle vhost messages. */
- ret = rte_vhost_driver_register((char *)&dev_basename);
+ ret = rte_vhost_driver_register(dev_basename, flags);
if (ret != 0)
rte_exit(EXIT_FAILURE, "vhost driver register failure.\n");
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index d04e2be2..6bb42e89 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,48 +34,23 @@
#ifndef _MAIN_H_
#define _MAIN_H_
-//#define DEBUG
-
-#ifdef DEBUG
-#define LOG_LEVEL RTE_LOG_DEBUG
-#define LOG_DEBUG(log_type, fmt, args...) do { \
- RTE_LOG(DEBUG, log_type, fmt, ##args); \
-} while (0)
-#else
-#define LOG_LEVEL RTE_LOG_INFO
-#define LOG_DEBUG(log_type, fmt, args...) do{} while(0)
-#endif
+#include <sys/queue.h>
/* Macros for printing using RTE_LOG */
#define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
#define RTE_LOGTYPE_VHOST_DATA RTE_LOGTYPE_USER2
#define RTE_LOGTYPE_VHOST_PORT RTE_LOGTYPE_USER3
-/**
- * Information relating to memory regions including offsets to
- * addresses in host physical space.
- */
-struct virtio_memory_regions_hpa {
- /**< Base guest physical address of region. */
- uint64_t guest_phys_address;
- /**< End guest physical address of region. */
- uint64_t guest_phys_address_end;
- /**< Size of region. */
- uint64_t memory_size;
- /**< Offset of region for gpa to hpa translation. */
- uint64_t host_phys_addr_offset;
+struct device_statistics {
+ uint64_t tx;
+ uint64_t tx_total;
+ rte_atomic64_t rx_atomic;
+ rte_atomic64_t rx_total_atomic;
};
-/*
- * Device linked list structure for data path.
- */
struct vhost_dev {
- /**< Pointer to device created by vhost lib. */
- struct virtio_net *dev;
/**< Number of memory regions for gpa to hpa translation. */
uint32_t nregions_hpa;
- /**< Memory region information for gpa to hpa translation. */
- struct virtio_memory_regions_hpa *regions_hpa;
/**< Device MAC address (Obtained on first TX packet). */
struct ether_addr mac_address;
/**< RX VMDQ queue number. */
@@ -88,28 +63,29 @@ struct vhost_dev {
volatile uint8_t ready;
/**< Device is marked for removal from the data core. */
volatile uint8_t remove;
+
+ int vid;
+ struct device_statistics stats;
+ TAILQ_ENTRY(vhost_dev) global_vdev_entry;
+ TAILQ_ENTRY(vhost_dev) lcore_vdev_entry;
} __rte_cache_aligned;
-struct virtio_net_data_ll
-{
- struct vhost_dev *vdev; /* Pointer to device created by configuration core. */
- struct virtio_net_data_ll *next; /* Pointer to next device in linked list. */
-};
+TAILQ_HEAD(vhost_dev_tailq_list, vhost_dev);
+
+
+#define REQUEST_DEV_REMOVAL 1
+#define ACK_DEV_REMOVAL 0
/*
* Structure containing data core specific information.
*/
-struct lcore_ll_info
-{
- struct virtio_net_data_ll *ll_root_free; /* Pointer to head in free linked list. */
- struct virtio_net_data_ll *ll_root_used; /* Pointer to head of used linked list. */
- uint32_t device_num; /* Number of devices on lcore. */
- volatile uint8_t dev_removal_flag; /* Flag to synchronize device removal. */
-};
+struct lcore_info {
+ uint32_t device_num;
+
+ /* Flag to synchronize device removal. */
+ volatile uint8_t dev_removal_flag;
-struct lcore_info
-{
- struct lcore_ll_info *lcore_ll; /* Pointer to data core specific lcore_ll_info struct */
+ struct vhost_dev_tailq_list vdev_list;
};
#endif /* _MAIN_H_ */
diff --git a/examples/vhost_xen/main.c b/examples/vhost_xen/main.c
index d83138d6..2e403576 100644
--- a/examples/vhost_xen/main.c
+++ b/examples/vhost_xen/main.c
@@ -507,32 +507,6 @@ static unsigned check_ports_num(unsigned nb_ports)
}
/*
- * Macro to print out packet contents. Wrapped in debug define so that the
- * data path is not effected when debug is disabled.
- */
-#ifdef DEBUG
-#define PRINT_PACKET(device, addr, size, header) do { \
- char *pkt_addr = (char*)(addr); \
- unsigned int index; \
- char packet[MAX_PRINT_BUFF]; \
- \
- if ((header)) \
- snprintf(packet, MAX_PRINT_BUFF, "(%"PRIu64") Header size %d: ", (device->device_fh), (size)); \
- else \
- snprintf(packet, MAX_PRINT_BUFF, "(%"PRIu64") Packet size %d: ", (device->device_fh), (size)); \
- for (index = 0; index < (size); index++) { \
- snprintf(packet + strnlen(packet, MAX_PRINT_BUFF), MAX_PRINT_BUFF - strnlen(packet, MAX_PRINT_BUFF), \
- "%02hhx ", pkt_addr[index]); \
- } \
- snprintf(packet + strnlen(packet, MAX_PRINT_BUFF), MAX_PRINT_BUFF - strnlen(packet, MAX_PRINT_BUFF), "\n"); \
- \
- LOG_DEBUG(VHOST_DATA, "%s", packet); \
-} while(0)
-#else
-#define PRINT_PACKET(device, addr, size, header) do{} while(0)
-#endif
-
-/*
* Function to convert guest physical addresses to vhost virtual addresses. This
* is used to convert virtio buffer addresses.
*/
@@ -551,7 +525,7 @@ gpa_to_vva(struct virtio_net *dev, uint64_t guest_pa)
break;
}
}
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") GPA %p| VVA %p\n",
+ RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") GPA %p| VVA %p\n",
dev->device_fh, (void*)(uintptr_t)guest_pa, (void*)(uintptr_t)vhost_va);
return vhost_va;
@@ -581,7 +555,7 @@ virtio_dev_rx(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count)
uint8_t success = 0;
void *userdata;
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_rx()\n", dev->device_fh);
+ RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") virtio_dev_rx()\n", dev->device_fh);
vq = dev->virtqueue_rx;
count = (count > MAX_PKT_BURST) ? MAX_PKT_BURST : count;
/* As many data cores may want access to available buffers, they need to be reserved. */
@@ -606,7 +580,8 @@ virtio_dev_rx(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count)
res_end_idx);
} while (unlikely(success == 0));
res_cur_idx = res_base_idx;
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Current Index %d| End Index %d\n", dev->device_fh, res_cur_idx, res_end_idx);
+ RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") Current Index %d| End Index %d\n",
+ dev->device_fh, res_cur_idx, res_end_idx);
/* Prefetch available ring to retrieve indexes. */
rte_prefetch0(&vq->avail->ring[res_cur_idx & (vq->size - 1)]);
@@ -800,17 +775,22 @@ virtio_tx_local(struct virtio_net *dev, struct rte_mbuf *m)
/* Drop the packet if the TX packet is destined for the TX device. */
if (dev_ll->dev->device_fh == dev->device_fh) {
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: Source and destination MAC addresses are the same. Dropping packet.\n",
- dev_ll->dev->device_fh);
+ RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") TX: "
+ "Source and destination MAC addresses are the same. "
+ "Dropping packet.\n",
+ dev_ll->dev->device_fh);
return 0;
}
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is local\n", dev_ll->dev->device_fh);
+ RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") TX: "
+ "MAC address is local\n", dev_ll->dev->device_fh);
if (dev_ll->dev->remove) {
/*drop the packet if the device is marked for removal*/
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Device is marked for removal\n", dev_ll->dev->device_fh);
+ RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") "
+ "Device is marked for removal\n",
+ dev_ll->dev->device_fh);
} else {
/*send the packet to the local virtio device*/
ret = virtio_dev_rx(dev_ll->dev, &m, 1);
@@ -849,7 +829,8 @@ virtio_tx_route(struct virtio_net* dev, struct rte_mbuf *m, struct rte_mempool *
return;
}
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is external\n", dev->device_fh);
+ RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") TX: "
+ "MAC address is external\n", dev->device_fh);
/*Add packet to the port tx queue*/
tx_q = &lcore_tx_queue[lcore_id];
@@ -922,7 +903,8 @@ virtio_dev_tx(struct virtio_net* dev, struct rte_mempool *mbuf_pool)
if (vq->last_used_idx == avail_idx)
return;
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_tx()\n", dev->device_fh);
+ RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") virtio_dev_tx()\n",
+ dev->device_fh);
/* Prefetch available ring to retrieve head indexes. */
rte_prefetch0(&vq->avail->ring[vq->last_used_idx & (vq->size - 1)]);
@@ -931,7 +913,8 @@ virtio_dev_tx(struct virtio_net* dev, struct rte_mempool *mbuf_pool)
free_entries = avail_idx - vq->last_used_idx;
free_entries = unlikely(free_entries < MAX_PKT_BURST) ? free_entries : MAX_PKT_BURST;
- LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Buffers available %d\n", dev->device_fh, free_entries);
+ RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") Buffers available %d\n",
+ dev->device_fh, free_entries);
/* Retrieve all of the head indexes first to avoid caching issues. */
for (i = 0; i < free_entries; i++)
head[i] = vq->avail->ring[(vq->last_used_idx + i) & (vq->size - 1)];
@@ -1020,7 +1003,9 @@ switch_worker(__attribute__((unused)) void *arg)
if (unlikely(diff_tsc > drain_tsc)) {
if (tx_q->len) {
- LOG_DEBUG(VHOST_DATA, "TX queue drained after timeout with burst size %u \n", tx_q->len);
+ RTE_LOG(DEBUG, VHOST_DATA,
+ "TX queue drained after timeout with burst size %u\n",
+ tx_q->len);
/*Tx any packets in the queue*/
ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id,
@@ -1460,8 +1445,6 @@ main(int argc, char *argv[])
/* Get the number of physical ports. */
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
/*
* Update the global var NUM_PORTS and global array PORTS
@@ -1482,9 +1465,6 @@ main(int argc, char *argv[])
if (mbuf_pool == NULL)
rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
- /* Set log level. */
- rte_set_log_level(LOG_LEVEL);
-
/* initialize all ports */
for (portid = 0; portid < nb_ports; portid++) {
/* skip ports that are not enabled */
@@ -1514,7 +1494,7 @@ main(int argc, char *argv[])
snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "print-xen-stats");
ret = rte_thread_setname(tid, thread_name);
if (ret != 0)
- RTE_LOG(ERR, VHOST_CONFIG,
+ RTE_LOG(DEBUG, VHOST_CONFIG,
"Cannot set print-stats name\n");
}
diff --git a/examples/vhost_xen/main.h b/examples/vhost_xen/main.h
index 481572e6..5ff48fd9 100644
--- a/examples/vhost_xen/main.h
+++ b/examples/vhost_xen/main.h
@@ -34,17 +34,6 @@
#ifndef _MAIN_H_
#define _MAIN_H_
-//#define DEBUG
-
-#ifdef DEBUG
-#define LOG_LEVEL RTE_LOG_DEBUG
-#define LOG_DEBUG(log_type, fmt, args...) \
- RTE_LOG(DEBUG, log_type, fmt, ##args)
-#else
-#define LOG_LEVEL RTE_LOG_INFO
-#define LOG_DEBUG(log_type, fmt, args...) do{} while(0)
-#endif
-
/* Macros for printing using RTE_LOG */
#define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
#define RTE_LOGTYPE_VHOST_DATA RTE_LOGTYPE_USER2
diff --git a/examples/vm_power_manager/channel_manager.c b/examples/vm_power_manager/channel_manager.c
index 22c2ddd5..e068ae28 100644
--- a/examples/vm_power_manager/channel_manager.c
+++ b/examples/vm_power_manager/channel_manager.c
@@ -667,6 +667,7 @@ add_vm(const char *vm_name)
return -1;
}
strncpy(new_domain->name, vm_name, sizeof(new_domain->name));
+ new_domain->name[sizeof(new_domain->name) - 1] = '\0';
new_domain->channel_mask = 0;
new_domain->num_channels = 0;
diff --git a/examples/vmdq/main.c b/examples/vmdq/main.c
index 178af2f5..360492ba 100644
--- a/examples/vmdq/main.c
+++ b/examples/vmdq/main.c
@@ -599,8 +599,6 @@ main(int argc, char *argv[])
rte_exit(EXIT_FAILURE, "Not enough cores\n");
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
/*
* Update the global var NUM_PORTS and global array PORTS
diff --git a/examples/vmdq_dcb/main.c b/examples/vmdq_dcb/main.c
index 62e1422a..617263b4 100644
--- a/examples/vmdq_dcb/main.c
+++ b/examples/vmdq_dcb/main.c
@@ -662,8 +662,6 @@ main(int argc, char *argv[])
}
nb_ports = rte_eth_dev_count();
- if (nb_ports > RTE_MAX_ETHPORTS)
- nb_ports = RTE_MAX_ETHPORTS;
/*
* Update the global var NUM_PORTS and global array PORTS