diff options
Diffstat (limited to 'examples/ip_pipeline')
-rw-r--r-- | examples/ip_pipeline/app.h | 145 | ||||
-rw-r--r-- | examples/ip_pipeline/config/network_layers.cfg | 4 | ||||
-rw-r--r-- | examples/ip_pipeline/config/network_layers.sh | 10 | ||||
-rw-r--r-- | examples/ip_pipeline/config/tap.cfg | 64 | ||||
-rw-r--r-- | examples/ip_pipeline/config_check.c | 31 | ||||
-rw-r--r-- | examples/ip_pipeline/config_parse.c | 141 | ||||
-rw-r--r-- | examples/ip_pipeline/init.c | 100 | ||||
-rw-r--r-- | examples/ip_pipeline/pipeline/pipeline_common_be.c | 1 | ||||
-rw-r--r-- | examples/ip_pipeline/pipeline/pipeline_common_fe.c | 2 | ||||
-rw-r--r-- | examples/ip_pipeline/pipeline/pipeline_passthrough.c | 2 | ||||
-rw-r--r-- | examples/ip_pipeline/pipeline/pipeline_passthrough_be.c | 335 | ||||
-rw-r--r-- | examples/ip_pipeline/pipeline/pipeline_passthrough_be.h | 16 | ||||
-rw-r--r-- | examples/ip_pipeline/pipeline_be.h | 13 |
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( + ¶m->burst_read, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "burst_write") == 0) { + int status = parser_read_uint32( + ¶m->burst_write, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "dropless") == 0) { + int status = parser_read_arg_bool(ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + param->dropless = status; + continue; + } + + if (strcmp(ent->name, "n_retries") == 0) { + int status = parser_read_uint64(¶m->n_retries, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "mempool") == 0) { + int status = validate_name(ent->value, + "MEMPOOL", 1); + ssize_t idx; + + PARSE_ERROR((status == 0), section_name, + ent->name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); + param->mempool_id = idx; + + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); + } + + free(entries); +} + +static void parse_kni(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) @@ -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; |