aboutsummaryrefslogtreecommitdiffstats
path: root/examples/ip_pipeline
diff options
context:
space:
mode:
authorChristian Ehrhardt <christian.ehrhardt@canonical.com>2016-12-08 14:07:29 +0100
committerChristian Ehrhardt <christian.ehrhardt@canonical.com>2016-12-08 14:10:05 +0100
commit6b3e017e5d25f15da73f7700f7f2ac553ef1a2e9 (patch)
tree1b1fb3f903b2282e261ade69e3c17952b3fd3464 /examples/ip_pipeline
parent32e04ea00cd159613e04acef75e52bfca6eeff2f (diff)
Imported Upstream version 16.11
Change-Id: I1944c65ddc88a9ad70f8c0eb6731552b84fbcb77 Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Diffstat (limited to 'examples/ip_pipeline')
-rw-r--r--examples/ip_pipeline/app.h145
-rw-r--r--examples/ip_pipeline/config/network_layers.cfg4
-rw-r--r--examples/ip_pipeline/config/network_layers.sh10
-rw-r--r--examples/ip_pipeline/config/tap.cfg64
-rw-r--r--examples/ip_pipeline/config_check.c31
-rw-r--r--examples/ip_pipeline/config_parse.c141
-rw-r--r--examples/ip_pipeline/init.c100
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_common_be.c1
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_common_fe.c2
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_passthrough.c2
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_passthrough_be.c335
-rw-r--r--examples/ip_pipeline/pipeline/pipeline_passthrough_be.h16
-rw-r--r--examples/ip_pipeline/pipeline_be.h13
13 files changed, 737 insertions, 127 deletions
diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h
index 6a6fdd97..f8b84e09 100644
--- a/examples/ip_pipeline/app.h
+++ b/examples/ip_pipeline/app.h
@@ -177,19 +177,29 @@ struct app_pktq_tm_params {
uint32_t burst_write;
};
+struct app_pktq_tap_params {
+ char *name;
+ uint32_t parsed;
+ uint32_t burst_read;
+ uint32_t burst_write;
+ uint32_t dropless;
+ uint64_t n_retries;
+ uint32_t mempool_id; /* Position in the app->mempool_params */
+};
+
struct app_pktq_source_params {
char *name;
uint32_t parsed;
uint32_t mempool_id; /* Position in the app->mempool_params array */
uint32_t burst;
- char *file_name; /* Full path of PCAP file to be copied to mbufs */
+ const char *file_name; /* Full path of PCAP file to be copied to mbufs */
uint32_t n_bytes_per_pkt;
};
struct app_pktq_sink_params {
char *name;
uint8_t parsed;
- char *file_name; /* Full path of PCAP file to be copied to mbufs */
+ const char *file_name; /* Full path of PCAP file to be copied to mbufs */
uint32_t n_pkts_to_dump;
};
@@ -204,6 +214,7 @@ enum app_pktq_in_type {
APP_PKTQ_IN_HWQ,
APP_PKTQ_IN_SWQ,
APP_PKTQ_IN_TM,
+ APP_PKTQ_IN_TAP,
APP_PKTQ_IN_KNI,
APP_PKTQ_IN_SOURCE,
};
@@ -217,6 +228,7 @@ enum app_pktq_out_type {
APP_PKTQ_OUT_HWQ,
APP_PKTQ_OUT_SWQ,
APP_PKTQ_OUT_TM,
+ APP_PKTQ_OUT_TAP,
APP_PKTQ_OUT_KNI,
APP_PKTQ_OUT_SINK,
};
@@ -441,6 +453,10 @@ struct app_eal_params {
#define APP_MAX_PKTQ_TM APP_MAX_LINKS
+#ifndef APP_MAX_PKTQ_TAP
+#define APP_MAX_PKTQ_TAP APP_MAX_LINKS
+#endif
+
#define APP_MAX_PKTQ_KNI APP_MAX_LINKS
#ifndef APP_MAX_PKTQ_SOURCE
@@ -494,6 +510,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_tap_params tap_params[APP_MAX_PKTQ_TAP];
struct app_pktq_kni_params kni_params[APP_MAX_PKTQ_KNI];
struct app_pktq_source_params source_params[APP_MAX_PKTQ_SOURCE];
struct app_pktq_sink_params sink_params[APP_MAX_PKTQ_SINK];
@@ -506,6 +523,7 @@ struct app_params {
uint32_t n_pktq_hwq_out;
uint32_t n_pktq_swq;
uint32_t n_pktq_tm;
+ uint32_t n_pktq_tap;
uint32_t n_pktq_kni;
uint32_t n_pktq_source;
uint32_t n_pktq_sink;
@@ -520,6 +538,7 @@ struct app_params {
struct app_link_data link_data[APP_MAX_LINKS];
struct rte_ring *swq[APP_MAX_PKTQ_SWQ];
struct rte_sched_port *tm[APP_MAX_PKTQ_TM];
+ int tap[APP_MAX_PKTQ_TAP];
#ifdef RTE_LIBRTE_KNI
struct rte_kni *kni[APP_MAX_PKTQ_KNI];
#endif /* RTE_LIBRTE_KNI */
@@ -786,6 +805,66 @@ app_tm_get_reader(struct app_params *app,
}
static inline uint32_t
+app_tap_get_readers(struct app_params *app, struct app_pktq_tap_params *tap)
+{
+ uint32_t pos = tap - app->tap_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_readers = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_in; j++) {
+ struct app_pktq_in_params *pktq = &p->pktq_in[j];
+
+ if ((pktq->type == APP_PKTQ_IN_TAP) &&
+ (pktq->id == pos))
+ n_readers++;
+ }
+ }
+
+ return n_readers;
+}
+
+static inline struct app_pipeline_params *
+app_tap_get_reader(struct app_params *app,
+ struct app_pktq_tap_params *tap,
+ uint32_t *pktq_in_id)
+{
+ struct app_pipeline_params *reader = NULL;
+ uint32_t pos = tap - app->tap_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_readers = 0, id = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_in; j++) {
+ struct app_pktq_in_params *pktq = &p->pktq_in[j];
+
+ if ((pktq->type == APP_PKTQ_IN_TAP) &&
+ (pktq->id == pos)) {
+ n_readers++;
+ reader = p;
+ id = j;
+ }
+ }
+ }
+
+ if (n_readers != 1)
+ return NULL;
+
+ *pktq_in_id = id;
+ return reader;
+}
+
+static inline uint32_t
app_kni_get_readers(struct app_params *app, struct app_pktq_kni_params *kni)
{
uint32_t pos = kni - app->kni_params;
@@ -1043,6 +1122,68 @@ app_tm_get_writer(struct app_params *app,
}
static inline uint32_t
+app_tap_get_writers(struct app_params *app, struct app_pktq_tap_params *tap)
+{
+ uint32_t pos = tap - app->tap_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_writers = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
+ RTE_DIM(p->pktq_out));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_out; j++) {
+ struct app_pktq_out_params *pktq = &p->pktq_out[j];
+
+ if ((pktq->type == APP_PKTQ_OUT_TAP) &&
+ (pktq->id == pos))
+ n_writers++;
+ }
+ }
+
+ return n_writers;
+}
+
+static inline struct app_pipeline_params *
+app_tap_get_writer(struct app_params *app,
+ struct app_pktq_tap_params *tap,
+ uint32_t *pktq_out_id)
+{
+ struct app_pipeline_params *writer = NULL;
+ uint32_t pos = tap - app->tap_params;
+ uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+ RTE_DIM(app->pipeline_params));
+ uint32_t n_writers = 0, id = 0, i;
+
+ for (i = 0; i < n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
+ RTE_DIM(p->pktq_out));
+ uint32_t j;
+
+ for (j = 0; j < n_pktq_out; j++) {
+ struct app_pktq_out_params *pktq = &p->pktq_out[j];
+
+ if ((pktq->type == APP_PKTQ_OUT_TAP) &&
+ (pktq->id == pos)) {
+ n_writers++;
+ writer = p;
+ id = j;
+ }
+ }
+ }
+
+ if (n_writers != 1)
+ return NULL;
+
+ *pktq_out_id = id;
+ return writer;
+}
+
+static inline uint32_t
app_kni_get_writers(struct app_params *app, struct app_pktq_kni_params *kni)
{
uint32_t pos = kni - app->kni_params;
diff --git a/examples/ip_pipeline/config/network_layers.cfg b/examples/ip_pipeline/config/network_layers.cfg
index 8054d9fe..397b5d77 100644
--- a/examples/ip_pipeline/config/network_layers.cfg
+++ b/examples/ip_pipeline/config/network_layers.cfg
@@ -203,12 +203,16 @@ type = PASS-THROUGH ; Loop-back (UDP place-holder)
core = 1
pktq_in = SWQ2
pktq_out = SWQ0
+swap = 282 286 ; IPSRC <-> IPDST
+swap = 290 292 ; PORTSRC <-> PORTDST
[PIPELINE5]
type = PASS-THROUGH ; Loop-back (TCP place-holder)
core = 1
pktq_in = SWQ3
pktq_out = SWQ1
+swap = 282 286 ; IPSRC <-> IPDST
+swap = 290 292 ; PORTSRC <-> PORTDST
[PIPELINE6]
type = PASS-THROUGH ; Drop (ICMP place-holder)
diff --git a/examples/ip_pipeline/config/network_layers.sh b/examples/ip_pipeline/config/network_layers.sh
index 3b86bebd..449b0069 100644
--- a/examples/ip_pipeline/config/network_layers.sh
+++ b/examples/ip_pipeline/config/network_layers.sh
@@ -56,7 +56,7 @@ p 1 route add 100.3.0.0 16 port 3 ether 10.3.0.2
# 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 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
@@ -72,8 +72,8 @@ p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.3.0.1 32 0 65535 1003 1003 17 0xF
# 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 add ipv4 100.0.0.10 10.0.0.1 1000 80 6 port 0 id 0
+p 3 flow add ipv4 100.1.0.10 10.1.0.1 1001 80 6 port 0 id 1
+p 3 flow add ipv4 100.2.0.10 10.2.0.1 1002 80 6 port 0 id 2
+p 3 flow add ipv4 100.3.0.10 10.3.0.1 1003 80 6 port 0 id 3
#p 3 flow ls
diff --git a/examples/ip_pipeline/config/tap.cfg b/examples/ip_pipeline/config/tap.cfg
new file mode 100644
index 00000000..10d35ebb
--- /dev/null
+++ b/examples/ip_pipeline/config/tap.cfg
@@ -0,0 +1,64 @@
+; BSD LICENSE
+;
+; Copyright(c) 2016 Intel Corporation. All rights reserved.
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in
+; the documentation and/or other materials provided with the
+; distribution.
+; * Neither the name of Intel Corporation nor the names of its
+; contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+; ______________ ______________________
+; | | TAP0 | |
+; RXQ0.0 --->| |------->|--+ |
+; | | TAP1 | | br0 |
+; TXQ1.0 <---| |<-------|<-+ |
+; | Pass-through | | Linux Kernel |
+; | (P1) | | Network Stack |
+; | | TAP1 | |
+; RXQ1.0 --->| |------->|--+ |
+; | | TAP0 | | br0 |
+; TXQ0.0 <---| |<-------|<-+ |
+; |______________| |______________________|
+;
+; Configure Linux kernel bridge between TAP0 and TAP1 interfaces:
+; [Linux]$ ifconfig TAP0 up
+; [Linux]$ ifconfig TAP1 up
+; [Linux]$ brctl addbr "br0"
+; [Linux]$ brctl addif br0 TAP0
+; [Linux]$ brctl addif br0 TAP1
+; [Linux]$ ifconfig br0 up
+
+[EAL]
+log_level = 0
+
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = PASS-THROUGH
+core = 1
+pktq_in = RXQ0.0 TAP1 RXQ1.0 TAP0
+pktq_out = TAP0 TXQ1.0 TAP1 TXQ0.0
diff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c
index af1b6284..dd9d4d8b 100644
--- a/examples/ip_pipeline/config_check.c
+++ b/examples/ip_pipeline/config_check.c
@@ -316,6 +316,36 @@ check_tms(struct app_params *app)
}
static void
+check_taps(struct app_params *app)
+{
+ uint32_t i;
+
+ for (i = 0; i < app->n_pktq_tap; i++) {
+ struct app_pktq_tap_params *p = &app->tap_params[i];
+ uint32_t n_readers = app_tap_get_readers(app, p);
+ uint32_t n_writers = app_tap_get_writers(app, p);
+
+ APP_CHECK((n_readers != 0),
+ "%s has no reader\n", p->name);
+
+ APP_CHECK((n_readers == 1),
+ "%s has more than one reader\n", p->name);
+
+ APP_CHECK((n_writers != 0),
+ "%s has no writer\n", p->name);
+
+ APP_CHECK((n_writers == 1),
+ "%s has more than one writer\n", p->name);
+
+ APP_CHECK((p->burst_read > 0),
+ "%s read burst size is 0\n", p->name);
+
+ APP_CHECK((p->burst_write > 0),
+ "%s write burst size is 0\n", p->name);
+ }
+}
+
+static void
check_knis(struct app_params *app) {
uint32_t i;
@@ -476,6 +506,7 @@ app_config_check(struct app_params *app)
check_txqs(app);
check_swqs(app);
check_tms(app);
+ check_taps(app);
check_knis(app);
check_sources(app);
check_sinks(app);
diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c
index 8fe81577..8b372e94 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -189,6 +189,15 @@ struct app_pktq_tm_params default_tm_params = {
.burst_write = 32,
};
+struct app_pktq_tap_params default_tap_params = {
+ .parsed = 0,
+ .burst_read = 32,
+ .burst_write = 32,
+ .dropless = 0,
+ .n_retries = 0,
+ .mempool_id = 0,
+};
+
struct app_pktq_kni_params default_kni_params = {
.parsed = 0,
.socket_id = 0,
@@ -207,7 +216,7 @@ struct app_pktq_source_params default_source_params = {
.parsed = 0,
.mempool_id = 0,
.burst = 32,
- .file_name = NULL,
+ .file_name = "./config/packets.pcap",
.n_bytes_per_pkt = 0,
};
@@ -852,6 +861,9 @@ parse_pipeline_pktq_in(struct app_params *app,
type = APP_PKTQ_IN_TM;
id = APP_PARAM_ADD(app->tm_params, name);
APP_PARAM_ADD_LINK_FOR_TM(app, name);
+ } else if (validate_name(name, "TAP", 1) == 0) {
+ type = APP_PKTQ_IN_TAP;
+ id = APP_PARAM_ADD(app->tap_params, name);
} else if (validate_name(name, "KNI", 1) == 0) {
type = APP_PKTQ_IN_KNI;
id = APP_PARAM_ADD(app->kni_params, name);
@@ -901,6 +913,9 @@ parse_pipeline_pktq_out(struct app_params *app,
type = APP_PKTQ_OUT_TM;
id = APP_PARAM_ADD(app->tm_params, name);
APP_PARAM_ADD_LINK_FOR_TM(app, name);
+ } else if (validate_name(name, "TAP", 1) == 0) {
+ type = APP_PKTQ_OUT_TAP;
+ id = APP_PARAM_ADD(app->tap_params, name);
} else if (validate_name(name, "KNI", 1) == 0) {
type = APP_PKTQ_OUT_KNI;
id = APP_PARAM_ADD(app->kni_params, name);
@@ -1896,6 +1911,88 @@ parse_tm(struct app_params *app,
}
static void
+parse_tap(struct app_params *app,
+ const char *section_name,
+ struct rte_cfgfile *cfg)
+{
+ struct app_pktq_tap_params *param;
+ struct rte_cfgfile_entry *entries;
+ int n_entries, i;
+ ssize_t param_idx;
+
+ n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
+ PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
+
+ entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
+ PARSE_ERROR_MALLOC(entries != NULL);
+
+ rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
+
+ param_idx = APP_PARAM_ADD(app->tap_params, section_name);
+ param = &app->tap_params[param_idx];
+ PARSE_CHECK_DUPLICATE_SECTION(param);
+
+ for (i = 0; i < n_entries; i++) {
+ struct rte_cfgfile_entry *ent = &entries[i];
+
+ if (strcmp(ent->name, "burst_read") == 0) {
+ int status = parser_read_uint32(
+ &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;
+ }
+
+ if (strcmp(ent->name, "mempool") == 0) {
+ int status = validate_name(ent->value,
+ "MEMPOOL", 1);
+ ssize_t idx;
+
+ PARSE_ERROR((status == 0), section_name,
+ ent->name);
+
+ idx = APP_PARAM_ADD(app->mempool_params, ent->value);
+ param->mempool_id = idx;
+
+ continue;
+ }
+
+ /* unrecognized */
+ PARSE_ERROR_INVALID(0, section_name, ent->name);
+ }
+
+ free(entries);
+}
+
+static void
parse_kni(struct app_params *app,
const char *section_name,
struct rte_cfgfile *cfg)
@@ -2286,6 +2383,7 @@ static const struct config_section cfg_file_scheme[] = {
{"TXQ", 2, parse_txq},
{"SWQ", 1, parse_swq},
{"TM", 1, parse_tm},
+ {"TAP", 1, parse_tap},
{"KNI", 1, parse_kni},
{"SOURCE", 1, parse_source},
{"SINK", 1, parse_sink},
@@ -2425,6 +2523,7 @@ 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->tap_params, app->n_pktq_tap);
APP_PARAM_COUNT(app->kni_params, app->n_pktq_kni);
APP_PARAM_COUNT(app->source_params, app->n_pktq_source);
APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink);
@@ -2789,6 +2888,30 @@ save_tm_params(struct app_params *app, FILE *f)
}
static void
+save_tap_params(struct app_params *app, FILE *f)
+{
+ struct app_pktq_tap_params *p;
+ size_t i, count;
+
+ count = RTE_DIM(app->tap_params);
+ for (i = 0; i < count; i++) {
+ p = &app->tap_params[i];
+ if (!APP_PARAM_VALID(p))
+ continue;
+
+ fprintf(f, "[%s]\n", p->name);
+ fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read);
+ fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write);
+ fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no");
+ fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
+ fprintf(f, "%s = %s\n", "mempool",
+ app->mempool_params[p->mempool_id].name);
+
+ fputc('\n', f);
+ }
+}
+
+static void
save_kni_params(struct app_params *app, FILE *f)
{
struct app_pktq_kni_params *p;
@@ -2942,6 +3065,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_TAP:
+ name = app->tap_params[pp->id].name;
+ break;
case APP_PKTQ_IN_KNI:
name = app->kni_params[pp->id].name;
break;
@@ -2979,6 +3105,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_TAP:
+ name = app->tap_params[pp->id].name;
+ break;
case APP_PKTQ_OUT_KNI:
name = app->kni_params[pp->id].name;
break;
@@ -3067,6 +3196,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_tap_params(app, file);
save_kni_params(app, file);
save_source_params(app, file);
save_sink_params(app, file);
@@ -3083,10 +3213,6 @@ 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,
@@ -3117,6 +3243,11 @@ app_config_init(struct app_params *app)
&default_tm_params,
sizeof(default_tm_params));
+ for (i = 0; i < RTE_DIM(app->tap_params); i++)
+ memcpy(&app->tap_params[i],
+ &default_tap_params,
+ sizeof(default_tap_params));
+
for (i = 0; i < RTE_DIM(app->kni_params); i++)
memcpy(&app->kni_params[i],
&default_kni_params,
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index 891b3274..3b36b53a 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -34,6 +34,14 @@
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
+#include <netinet/in.h>
+#ifdef RTE_EXEC_ENV_LINUXAPP
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#endif
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
#include <rte_cycles.h>
#include <rte_ethdev.h>
@@ -606,29 +614,12 @@ app_link_set_tcp_syn_filter(struct app_params *app, struct app_link_params *cp)
}
}
-static int
-app_link_is_virtual(struct app_link_params *p)
-{
- uint32_t pmd_id = p->pmd_id;
- struct rte_eth_dev *dev = &rte_eth_devices[pmd_id];
-
- if (dev->dev_type == RTE_ETH_DEV_VIRTUAL)
- return 1;
-
- return 0;
-}
-
void
app_link_up_internal(struct app_params *app, struct app_link_params *cp)
{
uint32_t i;
int status;
- if (app_link_is_virtual(cp)) {
- cp->state = 1;
- return;
- }
-
/* For each link, add filters for IP of current link */
if (cp->ip != 0) {
for (i = 0; i < app->n_links; i++) {
@@ -736,11 +727,6 @@ app_link_down_internal(struct app_params *app, struct app_link_params *cp)
uint32_t i;
int status;
- if (app_link_is_virtual(cp)) {
- cp->state = 0;
- return;
- }
-
/* PMD link down */
status = rte_eth_dev_set_link_down(cp->pmd_id);
if (status < 0)
@@ -1176,6 +1162,44 @@ app_init_tm(struct app_params *app)
}
}
+#ifndef RTE_EXEC_ENV_LINUXAPP
+static void
+app_init_tap(struct app_params *app) {
+ if (app->n_pktq_tap == 0)
+ return;
+
+ rte_panic("TAP device not supported.\n");
+}
+#else
+static void
+app_init_tap(struct app_params *app)
+{
+ uint32_t i;
+
+ for (i = 0; i < app->n_pktq_tap; i++) {
+ struct app_pktq_tap_params *p_tap = &app->tap_params[i];
+ struct ifreq ifr;
+ int fd, status;
+
+ APP_LOG(app, HIGH, "Initializing %s ...", p_tap->name);
+
+ fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
+ if (fd < 0)
+ rte_panic("Cannot open file /dev/net/tun\n");
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", p_tap->name);
+
+ status = ioctl(fd, TUNSETIFF, (void *) &ifr);
+ if (status < 0)
+ rte_panic("TAP setup error\n");
+
+ app->tap[i] = fd;
+ }
+}
+#endif
+
#ifdef RTE_LIBRTE_KNI
static int
kni_config_network_interface(uint8_t port_id, uint8_t if_up) {
@@ -1392,6 +1416,24 @@ void app_pipeline_params_get(struct app_params *app,
out->burst_size = app->tm_params[in->id].burst_read;
break;
}
+#ifdef RTE_EXEC_ENV_LINUXAPP
+ case APP_PKTQ_IN_TAP:
+ {
+ struct app_pktq_tap_params *tap_params =
+ &app->tap_params[in->id];
+ struct app_mempool_params *mempool_params =
+ &app->mempool_params[tap_params->mempool_id];
+ struct rte_mempool *mempool =
+ app->mempool[tap_params->mempool_id];
+
+ out->type = PIPELINE_PORT_IN_FD_READER;
+ out->params.fd.fd = app->tap[in->id];
+ out->params.fd.mtu = mempool_params->buffer_size;
+ out->params.fd.mempool = mempool;
+ out->burst_size = app->tap_params[in->id].burst_read;
+ break;
+ }
+#endif
#ifdef RTE_LIBRTE_KNI
case APP_PKTQ_IN_KNI:
{
@@ -1536,6 +1578,19 @@ void app_pipeline_params_get(struct app_params *app,
app->tm_params[in->id].burst_write;
break;
}
+#ifdef RTE_EXEC_ENV_LINUXAPP
+ case APP_PKTQ_OUT_TAP:
+ {
+ struct rte_port_fd_writer_params *params =
+ &out->params.fd;
+
+ out->type = PIPELINE_PORT_OUT_FD_WRITER;
+ params->fd = app->tap[in->id];
+ params->tx_burst_sz =
+ app->tap_params[in->id].burst_write;
+ break;
+ }
+#endif
#ifdef RTE_LIBRTE_KNI
case APP_PKTQ_OUT_KNI:
{
@@ -1752,6 +1807,7 @@ int app_init(struct app_params *app)
app_init_link(app);
app_init_swq(app);
app_init_tm(app);
+ app_init_tap(app);
app_init_kni(app);
app_init_msgq(app);
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_be.c b/examples/ip_pipeline/pipeline/pipeline_common_be.c
index 50dcb694..347e72b5 100644
--- a/examples/ip_pipeline/pipeline/pipeline_common_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_common_be.c
@@ -32,7 +32,6 @@
*/
#include <rte_common.h>
-#include <rte_ring.h>
#include <rte_malloc.h>
#include "pipeline_common_be.h"
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c
index cd1d082a..75211878 100644
--- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c
+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c
@@ -36,7 +36,6 @@
#include <unistd.h>
#include <rte_common.h>
-#include <rte_ring.h>
#include <rte_malloc.h>
#include <cmdline_rdline.h>
#include <cmdline_parse.h>
@@ -157,6 +156,7 @@ app_pipeline_track_pktq_out_to_link(struct app_params *app,
break;
}
+ case APP_PKTQ_OUT_TAP:
case APP_PKTQ_OUT_SINK:
default:
return NULL;
diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough.c b/examples/ip_pipeline/pipeline/pipeline_passthrough.c
index 63ce1472..2c9eb2e3 100644
--- a/examples/ip_pipeline/pipeline/pipeline_passthrough.c
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough.c
@@ -52,7 +52,7 @@ app_pipeline_passthrough_track(struct pipeline_params *p,
if (status)
return -1;
- if (pp.lb_hash_enabled)
+ if (pp.dma_hash_lb_enabled)
return -1;
*port_out = port_in / (p->n_ports_in / p->n_ports_out);
diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
index 356f02d0..8b71a7d4 100644
--- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
@@ -31,6 +31,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <stdio.h>
#include <string.h>
#include <rte_common.h>
@@ -45,10 +46,17 @@
#include "parser.h"
#include "hash_func.h"
+#define SWAP_DIM (PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX * \
+ (PIPELINE_PASSTHROUGH_SWAP_FIELD_SIZE_MAX / sizeof(uint64_t)))
+
struct pipeline_passthrough {
struct pipeline p;
struct pipeline_passthrough_params params;
rte_table_hash_op_hash f_hash;
+ uint32_t swap_field0_offset[SWAP_DIM];
+ uint32_t swap_field1_offset[SWAP_DIM];
+ uint64_t swap_field_mask[SWAP_DIM];
+ uint32_t swap_n_fields;
} __rte_cache_aligned;
static pipeline_msg_req_handler handlers[] = {
@@ -69,7 +77,7 @@ static pipeline_msg_req_handler handlers[] = {
};
static inline __attribute__((always_inline)) void
-pkt_work(
+pkt_work_dma(
struct rte_mbuf *pkt,
void *arg,
uint32_t dma_size,
@@ -114,7 +122,7 @@ pkt_work(
}
static inline __attribute__((always_inline)) void
-pkt4_work(
+pkt4_work_dma(
struct rte_mbuf **pkts,
void *arg,
uint32_t dma_size,
@@ -209,148 +217,231 @@ pkt4_work(
}
}
-#define PKT_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \
+static inline __attribute__((always_inline)) void
+pkt_work_swap(
+ struct rte_mbuf *pkt,
+ void *arg)
+{
+ struct pipeline_passthrough *p = arg;
+ uint32_t i;
+
+ /* Read(field0, field1), compute(field0, field1), write(field0, field1) */
+ for (i = 0; i < p->swap_n_fields; i++) {
+ uint64_t *field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt,
+ p->swap_field0_offset[i]);
+ uint64_t *field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt,
+ p->swap_field1_offset[i]);
+ uint64_t mask = p->swap_field_mask[i];
+
+ uint64_t field0 = *field0_ptr;
+ uint64_t field1 = *field1_ptr;
+
+ *field0_ptr = (field0 & (~mask)) + (field1 & mask);
+ *field1_ptr = (field0 & mask) + (field1 & (~mask));
+ }
+}
+
+static inline __attribute__((always_inline)) void
+pkt4_work_swap(
+ struct rte_mbuf **pkts,
+ void *arg)
+{
+ struct pipeline_passthrough *p = arg;
+ uint32_t i;
+
+ /* Read(field0, field1), compute(field0, field1), write(field0, field1) */
+ for (i = 0; i < p->swap_n_fields; i++) {
+ uint64_t *pkt0_field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
+ p->swap_field0_offset[i]);
+ uint64_t *pkt1_field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
+ p->swap_field0_offset[i]);
+ uint64_t *pkt2_field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
+ p->swap_field0_offset[i]);
+ uint64_t *pkt3_field0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
+ p->swap_field0_offset[i]);
+
+ uint64_t *pkt0_field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
+ p->swap_field1_offset[i]);
+ uint64_t *pkt1_field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
+ p->swap_field1_offset[i]);
+ uint64_t *pkt2_field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
+ p->swap_field1_offset[i]);
+ uint64_t *pkt3_field1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
+ p->swap_field1_offset[i]);
+
+ uint64_t mask = p->swap_field_mask[i];
+
+ uint64_t pkt0_field0 = *pkt0_field0_ptr;
+ uint64_t pkt1_field0 = *pkt1_field0_ptr;
+ uint64_t pkt2_field0 = *pkt2_field0_ptr;
+ uint64_t pkt3_field0 = *pkt3_field0_ptr;
+
+ uint64_t pkt0_field1 = *pkt0_field1_ptr;
+ uint64_t pkt1_field1 = *pkt1_field1_ptr;
+ uint64_t pkt2_field1 = *pkt2_field1_ptr;
+ uint64_t pkt3_field1 = *pkt3_field1_ptr;
+
+ *pkt0_field0_ptr = (pkt0_field0 & (~mask)) + (pkt0_field1 & mask);
+ *pkt1_field0_ptr = (pkt1_field0 & (~mask)) + (pkt1_field1 & mask);
+ *pkt2_field0_ptr = (pkt2_field0 & (~mask)) + (pkt2_field1 & mask);
+ *pkt3_field0_ptr = (pkt3_field0 & (~mask)) + (pkt3_field1 & mask);
+
+ *pkt0_field1_ptr = (pkt0_field0 & mask) + (pkt0_field1 & (~mask));
+ *pkt1_field1_ptr = (pkt1_field0 & mask) + (pkt1_field1 & (~mask));
+ *pkt2_field1_ptr = (pkt2_field0 & mask) + (pkt2_field1 & (~mask));
+ *pkt3_field1_ptr = (pkt3_field0 & mask) + (pkt3_field1 & (~mask));
+ }
+}
+
+#define PKT_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \
static inline void \
-pkt_work_size##dma_size##_hash##hash_enabled \
+pkt_work_dma_size##dma_size##_hash##hash_enabled \
##_lb##lb_hash##_pw##port_pow2( \
struct rte_mbuf *pkt, \
void *arg) \
{ \
- pkt_work(pkt, arg, dma_size, hash_enabled, lb_hash, port_pow2); \
+ pkt_work_dma(pkt, arg, dma_size, hash_enabled, lb_hash, port_pow2); \
}
-#define PKT4_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \
+#define PKT4_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \
static inline void \
-pkt4_work_size##dma_size##_hash##hash_enabled \
+pkt4_work_dma_size##dma_size##_hash##hash_enabled \
##_lb##lb_hash##_pw##port_pow2( \
struct rte_mbuf **pkts, \
void *arg) \
{ \
- pkt4_work(pkts, arg, dma_size, hash_enabled, lb_hash, port_pow2); \
+ pkt4_work_dma(pkts, arg, dma_size, hash_enabled, lb_hash, port_pow2); \
}
-#define port_in_ah(dma_size, hash_enabled, lb_hash, port_pow2) \
-PKT_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \
-PKT4_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \
-PIPELINE_PORT_IN_AH(port_in_ah_size##dma_size##_hash \
+#define port_in_ah_dma(dma_size, hash_enabled, lb_hash, port_pow2) \
+PKT_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \
+PKT4_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \
+PIPELINE_PORT_IN_AH(port_in_ah_dma_size##dma_size##_hash \
##hash_enabled##_lb##lb_hash##_pw##port_pow2, \
- pkt_work_size##dma_size##_hash##hash_enabled \
+ pkt_work_dma_size##dma_size##_hash##hash_enabled \
##_lb##lb_hash##_pw##port_pow2, \
- pkt4_work_size##dma_size##_hash##hash_enabled \
+ pkt4_work_dma_size##dma_size##_hash##hash_enabled \
##_lb##lb_hash##_pw##port_pow2)
#define port_in_ah_lb(dma_size, hash_enabled, lb_hash, port_pow2) \
-PKT_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \
-PKT4_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \
+PKT_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \
+PKT4_WORK_DMA(dma_size, hash_enabled, lb_hash, port_pow2) \
PIPELINE_PORT_IN_AH_HIJACK_ALL( \
- port_in_ah_size##dma_size##_hash##hash_enabled \
+ port_in_ah_lb_size##dma_size##_hash##hash_enabled \
##_lb##lb_hash##_pw##port_pow2, \
- pkt_work_size##dma_size##_hash##hash_enabled \
+ pkt_work_dma_size##dma_size##_hash##hash_enabled \
##_lb##lb_hash##_pw##port_pow2, \
- pkt4_work_size##dma_size##_hash##hash_enabled \
+ pkt4_work_dma_size##dma_size##_hash##hash_enabled \
##_lb##lb_hash##_pw##port_pow2)
-/* Port in AH (dma_size, hash_enabled, lb_hash, port_pow2) */
+PIPELINE_PORT_IN_AH(port_in_ah_swap, pkt_work_swap, pkt4_work_swap)
+
+
+/* Port in AH DMA(dma_size, hash_enabled, lb_hash, port_pow2) */
-port_in_ah(8, 0, 0, 0)
-port_in_ah(8, 1, 0, 0)
+port_in_ah_dma(8, 0, 0, 0)
+port_in_ah_dma(8, 1, 0, 0)
port_in_ah_lb(8, 1, 1, 0)
port_in_ah_lb(8, 1, 1, 1)
-port_in_ah(16, 0, 0, 0)
-port_in_ah(16, 1, 0, 0)
+port_in_ah_dma(16, 0, 0, 0)
+port_in_ah_dma(16, 1, 0, 0)
port_in_ah_lb(16, 1, 1, 0)
port_in_ah_lb(16, 1, 1, 1)
-port_in_ah(24, 0, 0, 0)
-port_in_ah(24, 1, 0, 0)
+port_in_ah_dma(24, 0, 0, 0)
+port_in_ah_dma(24, 1, 0, 0)
port_in_ah_lb(24, 1, 1, 0)
port_in_ah_lb(24, 1, 1, 1)
-port_in_ah(32, 0, 0, 0)
-port_in_ah(32, 1, 0, 0)
+port_in_ah_dma(32, 0, 0, 0)
+port_in_ah_dma(32, 1, 0, 0)
port_in_ah_lb(32, 1, 1, 0)
port_in_ah_lb(32, 1, 1, 1)
-port_in_ah(40, 0, 0, 0)
-port_in_ah(40, 1, 0, 0)
+port_in_ah_dma(40, 0, 0, 0)
+port_in_ah_dma(40, 1, 0, 0)
port_in_ah_lb(40, 1, 1, 0)
port_in_ah_lb(40, 1, 1, 1)
-port_in_ah(48, 0, 0, 0)
-port_in_ah(48, 1, 0, 0)
+port_in_ah_dma(48, 0, 0, 0)
+port_in_ah_dma(48, 1, 0, 0)
port_in_ah_lb(48, 1, 1, 0)
port_in_ah_lb(48, 1, 1, 1)
-port_in_ah(56, 0, 0, 0)
-port_in_ah(56, 1, 0, 0)
+port_in_ah_dma(56, 0, 0, 0)
+port_in_ah_dma(56, 1, 0, 0)
port_in_ah_lb(56, 1, 1, 0)
port_in_ah_lb(56, 1, 1, 1)
-port_in_ah(64, 0, 0, 0)
-port_in_ah(64, 1, 0, 0)
+port_in_ah_dma(64, 0, 0, 0)
+port_in_ah_dma(64, 1, 0, 0)
port_in_ah_lb(64, 1, 1, 0)
port_in_ah_lb(64, 1, 1, 1)
static rte_pipeline_port_in_action_handler
get_port_in_ah(struct pipeline_passthrough *p)
{
- if (p->params.dma_enabled == 0)
+ if ((p->params.dma_enabled == 0) &&
+ (p->params.swap_enabled == 0))
return NULL;
+ if (p->params.swap_enabled)
+ return port_in_ah_swap;
+
if (p->params.dma_hash_enabled) {
- if (p->params.lb_hash_enabled) {
+ if (p->params.dma_hash_lb_enabled) {
if (rte_is_power_of_2(p->p.n_ports_out))
switch (p->params.dma_size) {
- case 8: return port_in_ah_size8_hash1_lb1_pw1;
- case 16: return port_in_ah_size16_hash1_lb1_pw1;
- case 24: return port_in_ah_size24_hash1_lb1_pw1;
- case 32: return port_in_ah_size32_hash1_lb1_pw1;
- case 40: return port_in_ah_size40_hash1_lb1_pw1;
- case 48: return port_in_ah_size48_hash1_lb1_pw1;
- case 56: return port_in_ah_size56_hash1_lb1_pw1;
- case 64: return port_in_ah_size64_hash1_lb1_pw1;
+ case 8: return port_in_ah_lb_size8_hash1_lb1_pw1;
+ case 16: return port_in_ah_lb_size16_hash1_lb1_pw1;
+ case 24: return port_in_ah_lb_size24_hash1_lb1_pw1;
+ case 32: return port_in_ah_lb_size32_hash1_lb1_pw1;
+ case 40: return port_in_ah_lb_size40_hash1_lb1_pw1;
+ case 48: return port_in_ah_lb_size48_hash1_lb1_pw1;
+ case 56: return port_in_ah_lb_size56_hash1_lb1_pw1;
+ case 64: return port_in_ah_lb_size64_hash1_lb1_pw1;
default: return NULL;
}
else
switch (p->params.dma_size) {
- case 8: return port_in_ah_size8_hash1_lb1_pw0;
- case 16: return port_in_ah_size16_hash1_lb1_pw0;
- case 24: return port_in_ah_size24_hash1_lb1_pw0;
- case 32: return port_in_ah_size32_hash1_lb1_pw0;
- case 40: return port_in_ah_size40_hash1_lb1_pw0;
- case 48: return port_in_ah_size48_hash1_lb1_pw0;
- case 56: return port_in_ah_size56_hash1_lb1_pw0;
- case 64: return port_in_ah_size64_hash1_lb1_pw0;
+ case 8: return port_in_ah_lb_size8_hash1_lb1_pw0;
+ case 16: return port_in_ah_lb_size16_hash1_lb1_pw0;
+ case 24: return port_in_ah_lb_size24_hash1_lb1_pw0;
+ case 32: return port_in_ah_lb_size32_hash1_lb1_pw0;
+ case 40: return port_in_ah_lb_size40_hash1_lb1_pw0;
+ case 48: return port_in_ah_lb_size48_hash1_lb1_pw0;
+ case 56: return port_in_ah_lb_size56_hash1_lb1_pw0;
+ case 64: return port_in_ah_lb_size64_hash1_lb1_pw0;
default: return NULL;
}
} else
switch (p->params.dma_size) {
- case 8: return port_in_ah_size8_hash1_lb0_pw0;
- case 16: return port_in_ah_size16_hash1_lb0_pw0;
- case 24: return port_in_ah_size24_hash1_lb0_pw0;
- case 32: return port_in_ah_size32_hash1_lb0_pw0;
- case 40: return port_in_ah_size40_hash1_lb0_pw0;
- case 48: return port_in_ah_size48_hash1_lb0_pw0;
- case 56: return port_in_ah_size56_hash1_lb0_pw0;
- case 64: return port_in_ah_size64_hash1_lb0_pw0;
+ case 8: return port_in_ah_dma_size8_hash1_lb0_pw0;
+ case 16: return port_in_ah_dma_size16_hash1_lb0_pw0;
+ case 24: return port_in_ah_dma_size24_hash1_lb0_pw0;
+ case 32: return port_in_ah_dma_size32_hash1_lb0_pw0;
+ case 40: return port_in_ah_dma_size40_hash1_lb0_pw0;
+ case 48: return port_in_ah_dma_size48_hash1_lb0_pw0;
+ case 56: return port_in_ah_dma_size56_hash1_lb0_pw0;
+ case 64: return port_in_ah_dma_size64_hash1_lb0_pw0;
default: return NULL;
}
} else
switch (p->params.dma_size) {
- case 8: return port_in_ah_size8_hash0_lb0_pw0;
- case 16: return port_in_ah_size16_hash0_lb0_pw0;
- case 24: return port_in_ah_size24_hash0_lb0_pw0;
- case 32: return port_in_ah_size32_hash0_lb0_pw0;
- case 40: return port_in_ah_size40_hash0_lb0_pw0;
- case 48: return port_in_ah_size48_hash0_lb0_pw0;
- case 56: return port_in_ah_size56_hash0_lb0_pw0;
- case 64: return port_in_ah_size64_hash0_lb0_pw0;
+ case 8: return port_in_ah_dma_size8_hash0_lb0_pw0;
+ case 16: return port_in_ah_dma_size16_hash0_lb0_pw0;
+ case 24: return port_in_ah_dma_size24_hash0_lb0_pw0;
+ case 32: return port_in_ah_dma_size32_hash0_lb0_pw0;
+ case 40: return port_in_ah_dma_size40_hash0_lb0_pw0;
+ case 48: return port_in_ah_dma_size48_hash0_lb0_pw0;
+ case 56: return port_in_ah_dma_size56_hash0_lb0_pw0;
+ case 64: return port_in_ah_dma_size64_hash0_lb0_pw0;
default: return NULL;
}
}
@@ -362,17 +453,19 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,
uint32_t dma_dst_offset_present = 0;
uint32_t dma_src_offset_present = 0;
uint32_t dma_src_mask_present = 0;
+ char dma_mask_str[PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2 + 1];
uint32_t dma_size_present = 0;
uint32_t dma_hash_offset_present = 0;
- uint32_t lb_present = 0;
+ uint32_t dma_hash_lb_present = 0;
uint32_t i;
- char dma_mask_str[PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2 + 1];
/* default values */
p->dma_enabled = 0;
p->dma_hash_enabled = 0;
- p->lb_hash_enabled = 0;
+ p->dma_hash_lb_enabled = 0;
memset(p->dma_src_mask, 0xFF, sizeof(p->dma_src_mask));
+ p->swap_enabled = 0;
+ p->swap_n_fields = 0;
for (i = 0; i < params->n_args; i++) {
char *arg_name = params->args_name[i];
@@ -485,7 +578,6 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,
params->name, arg_name, arg_value);
p->dma_hash_enabled = 1;
- p->dma_enabled = 1;
continue;
}
@@ -493,19 +585,39 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,
/* load_balance mode */
if (strcmp(arg_name, "lb") == 0) {
PIPELINE_PARSE_ERR_DUPLICATE(
- lb_present == 0,
+ dma_hash_lb_present == 0,
params->name, arg_name);
- lb_present = 1;
+ dma_hash_lb_present = 1;
+
+ if (strcmp(arg_value, "hash") ||
+ strcmp(arg_value, "HASH"))
- if ((strcmp(arg_value, "hash") == 0) ||
- (strcmp(arg_value, "HASH") == 0))
- p->lb_hash_enabled = 1;
- else
PIPELINE_PARSE_ERR_INV_VAL(0,
params->name,
arg_name,
arg_value);
+ p->dma_hash_lb_enabled = 1;
+
+ continue;
+ }
+
+ /* swap */
+ if (strcmp(arg_name, "swap") == 0) {
+ uint32_t a, b, n_args;
+ int len;
+
+ n_args = sscanf(arg_value, "%" SCNu32 " %" SCNu32 "%n",
+ &a, &b, &len);
+ PIPELINE_PARSE_ERR_INV_VAL(((n_args == 2) &&
+ ((size_t) len == strlen(arg_value))),
+ params->name, arg_name, arg_value);
+
+ p->swap_field0_offset[p->swap_n_fields] = a;
+ p->swap_field1_offset[p->swap_n_fields] = b;
+ p->swap_n_fields++;
+ p->swap_enabled = 1;
+
continue;
}
@@ -514,6 +626,9 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,
}
/* Check correlations between arguments */
+ PIPELINE_ARG_CHECK((p->dma_enabled + p->swap_enabled < 2),
+ "Parse error in section \"%s\": DMA and SWAP actions are both enabled",
+ params->name);
PIPELINE_ARG_CHECK((dma_dst_offset_present == p->dma_enabled),
"Parse error in section \"%s\": missing entry "
"\"dma_dst_offset\"", params->name);
@@ -523,12 +638,12 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,
PIPELINE_ARG_CHECK((dma_size_present == p->dma_enabled),
"Parse error in section \"%s\": missing entry "
"\"dma_size\"", params->name);
- PIPELINE_ARG_CHECK((dma_hash_offset_present == p->dma_enabled),
- "Parse error in section \"%s\": missing entry "
- "\"dma_hash_offset\"", params->name);
- PIPELINE_ARG_CHECK((p->lb_hash_enabled <= p->dma_hash_enabled),
- "Parse error in section \"%s\": missing entry "
- "\"dma_hash_offset\"", params->name);
+ PIPELINE_ARG_CHECK((p->dma_hash_enabled <= p->dma_enabled),
+ "Parse error in section \"%s\": missing all DMA entries",
+ params->name);
+ PIPELINE_ARG_CHECK((p->dma_hash_lb_enabled <= p->dma_hash_enabled),
+ "Parse error in section \"%s\": missing all DMA hash entries ",
+ params->name);
if (dma_src_mask_present) {
uint32_t dma_size = p->dma_size;
@@ -547,7 +662,7 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,
"dma_src_mask", dma_mask_str);
}
- if (p->lb_hash_enabled)
+ if (p->dma_hash_lb_enabled)
PIPELINE_ARG_CHECK((params->n_ports_out > 1),
"Parse error in section \"%s\": entry \"lb\" not "
"allowed for single output port pipeline",
@@ -562,7 +677,6 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,
return 0;
}
-
static rte_table_hash_op_hash
get_hash_function(struct pipeline_passthrough *p)
{
@@ -580,6 +694,47 @@ get_hash_function(struct pipeline_passthrough *p)
}
}
+static int
+pipeline_passthrough_swap_convert(struct pipeline_passthrough *p)
+{
+ uint32_t i;
+
+ p->swap_n_fields = 0;
+
+ for (i = 0; i < p->params.swap_n_fields; i++) {
+ uint32_t offset0 = p->params.swap_field0_offset[i];
+ uint32_t offset1 = p->params.swap_field1_offset[i];
+ uint32_t size = offset1 - offset0;
+ uint32_t j;
+
+ /* Check */
+ if ((offset0 >= offset1) ||
+ (size > PIPELINE_PASSTHROUGH_SWAP_FIELD_SIZE_MAX) ||
+ (p->swap_n_fields >= SWAP_DIM))
+ return -1;
+
+ for (j = 0; j < (size / sizeof(uint64_t)); j++) {
+ p->swap_field0_offset[p->swap_n_fields] = offset0;
+ p->swap_field1_offset[p->swap_n_fields] = offset1;
+ p->swap_field_mask[p->swap_n_fields] = UINT64_MAX;
+ p->swap_n_fields++;
+ offset0 += sizeof(uint64_t);
+ offset1 += sizeof(uint64_t);
+ }
+ if (size % sizeof(uint64_t)) {
+ uint32_t n_bits = (size % sizeof(uint64_t)) * 8;
+
+ p->swap_field0_offset[p->swap_n_fields] = offset0;
+ p->swap_field1_offset[p->swap_n_fields] = offset1;
+ p->swap_field_mask[p->swap_n_fields] =
+ RTE_LEN2MASK(n_bits, uint64_t);
+ p->swap_n_fields++;
+ }
+ }
+
+ return 0;
+}
+
static void*
pipeline_passthrough_init(struct pipeline_params *params,
__rte_unused void *arg)
@@ -609,6 +764,8 @@ pipeline_passthrough_init(struct pipeline_params *params,
/* Parse arguments */
if (pipeline_passthrough_parse_args(&p_pt->params, params))
return NULL;
+ if (pipeline_passthrough_swap_convert(p_pt))
+ return NULL;
p_pt->f_hash = get_hash_function(p_pt);
/* Pipeline */
@@ -712,7 +869,7 @@ 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) ?
+ uint32_t port_out_id = (p_pt->params.dma_hash_lb_enabled == 0) ?
(i / (p->n_ports_in / p->n_ports_out)) :
0;
diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h
index 9368cec7..decb2684 100644
--- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.h
@@ -38,6 +38,14 @@
#define PIPELINE_PASSTHROUGH_DMA_SIZE_MAX 64
+#ifndef PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX
+#define PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX 8
+#endif
+
+#ifndef PIPELINE_PASSTHROUGH_SWAP_FIELD_SIZE_MAX
+#define PIPELINE_PASSTHROUGH_SWAP_FIELD_SIZE_MAX 16
+#endif
+
struct pipeline_passthrough_params {
uint32_t dma_enabled;
uint32_t dma_dst_offset;
@@ -47,7 +55,13 @@ struct pipeline_passthrough_params {
uint32_t dma_hash_enabled;
uint32_t dma_hash_offset;
- uint32_t lb_hash_enabled;
+
+ uint32_t dma_hash_lb_enabled;
+
+ uint32_t swap_enabled;
+ uint32_t swap_field0_offset[PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX];
+ uint32_t swap_field1_offset[PIPELINE_PASSTHROUGH_SWAP_N_FIELDS_MAX];
+ uint32_t swap_n_fields;
};
int
diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h
index b562472b..0cfcc809 100644
--- a/examples/ip_pipeline/pipeline_be.h
+++ b/examples/ip_pipeline/pipeline_be.h
@@ -39,6 +39,7 @@
#include <rte_port_frag.h>
#include <rte_port_ras.h>
#include <rte_port_sched.h>
+#include <rte_port_fd.h>
#include <rte_port_source_sink.h>
#ifdef RTE_LIBRTE_KNI
#include <rte_port_kni.h>
@@ -52,6 +53,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_FD_READER,
PIPELINE_PORT_IN_KNI_READER,
PIPELINE_PORT_IN_SOURCE,
};
@@ -65,6 +67,7 @@ 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;
+ struct rte_port_fd_reader_params fd;
#ifdef RTE_LIBRTE_KNI
struct rte_port_kni_reader_params kni;
#endif
@@ -89,6 +92,8 @@ 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;
+ case PIPELINE_PORT_IN_FD_READER:
+ return (void *) &p->params.fd;
#ifdef RTE_LIBRTE_KNI
case PIPELINE_PORT_IN_KNI_READER:
return (void *) &p->params.kni;
@@ -116,6 +121,8 @@ 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;
+ case PIPELINE_PORT_IN_FD_READER:
+ return &rte_port_fd_reader_ops;
#ifdef RTE_LIBRTE_KNI
case PIPELINE_PORT_IN_KNI_READER:
return &rte_port_kni_reader_ops;
@@ -137,6 +144,7 @@ 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_FD_WRITER,
PIPELINE_PORT_OUT_KNI_WRITER,
PIPELINE_PORT_OUT_KNI_WRITER_NODROP,
PIPELINE_PORT_OUT_SINK,
@@ -154,6 +162,7 @@ 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;
+ struct rte_port_fd_writer_params fd;
#ifdef RTE_LIBRTE_KNI
struct rte_port_kni_writer_params kni;
struct rte_port_kni_writer_nodrop_params kni_nodrop;
@@ -184,6 +193,8 @@ 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;
+ case PIPELINE_PORT_OUT_FD_WRITER:
+ return (void *) &p->params.fd;
#ifdef RTE_LIBRTE_KNI
case PIPELINE_PORT_OUT_KNI_WRITER:
return (void *) &p->params.kni;
@@ -219,6 +230,8 @@ 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;
+ case PIPELINE_PORT_OUT_FD_WRITER:
+ return &rte_port_fd_writer_ops;
#ifdef RTE_LIBRTE_KNI
case PIPELINE_PORT_OUT_KNI_WRITER:
return &rte_port_kni_writer_ops;