Add integrated MP/MC and fragmentation/reassembly support to SWQs

Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz at intel.com>
---
 examples/ip_pipeline/app.h          |   14 +++
 examples/ip_pipeline/config_check.c |   45 +++++++-
 examples/ip_pipeline/config_parse.c |  195 +++++++++++++++++++++++++++++++++--
 examples/ip_pipeline/init.c         |  165 ++++++++++++++++++++++++-----
 examples/ip_pipeline/main.c         |    4 +-
 examples/ip_pipeline/pipeline_be.h  |   18 ++++
 6 files changed, 402 insertions(+), 39 deletions(-)

diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h
index 521e3a0..943466e 100644
--- a/examples/ip_pipeline/app.h
+++ b/examples/ip_pipeline/app.h
@@ -107,6 +107,14 @@ struct app_pktq_swq_params {
        uint32_t dropless;
        uint64_t n_retries;
        uint32_t cpu_socket_id;
+       uint32_t ipv4_frag;
+       uint32_t ipv6_frag;
+       uint32_t ipv4_ras;
+       uint32_t ipv6_ras;
+       uint32_t mtu;
+       uint32_t metadata_size;
+       uint32_t mempool_direct_id;
+       uint32_t mempool_indirect_id;
 };

 #ifndef APP_FILE_NAME_SIZE
@@ -405,6 +413,10 @@ struct app_params {
        char app_name[APP_APPNAME_SIZE];
        const char *config_file;
        const char *script_file;
+       const char *parser_file;
+       const char *output_file;
+       const char *preproc;
+       const char *preproc_args;
        uint64_t port_mask;
        uint32_t log_level;

@@ -880,6 +892,8 @@ int app_config_init(struct app_params *app);
 int app_config_args(struct app_params *app,
        int argc, char **argv);

+int app_config_preproc(struct app_params *app);
+
 int app_config_parse(struct app_params *app,
        const char *file_name);

diff --git a/examples/ip_pipeline/config_check.c 
b/examples/ip_pipeline/config_check.c
index 07f4c8b..8052bc4 100644
--- a/examples/ip_pipeline/config_check.c
+++ b/examples/ip_pipeline/config_check.c
@@ -33,6 +33,8 @@

 #include <stdio.h>

+#include <rte_ip.h>
+
 #include "app.h"

 static void
@@ -193,6 +195,7 @@ check_swqs(struct app_params *app)
                struct app_pktq_swq_params *p = &app->swq_params[i];
                uint32_t n_readers = app_swq_get_readers(app, p);
                uint32_t n_writers = app_swq_get_writers(app, p);
+               uint32_t n_flags;

                APP_CHECK((p->size > 0),
                        "%s size is 0\n", p->name);
@@ -217,14 +220,48 @@ check_swqs(struct app_params *app)
                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);
+               if (n_readers > 1)
+                       APP_LOG(app, LOW, "%s has more than one reader", 
p->name);

                APP_CHECK((n_writers != 0),
                        "%s has no writer\n", p->name);

-               APP_CHECK((n_writers == 1),
-                       "%s has more than one writer\n", p->name);
+               if (n_writers > 1)
+                       APP_LOG(app, LOW, "%s has more than one writer", 
p->name);
+
+               n_flags = p->ipv4_frag + p->ipv6_frag + p->ipv4_ras + 
p->ipv6_ras;
+
+               APP_CHECK((n_flags < 2),
+                       "%s has more than one fragmentation or reassembly mode 
enabled\n",
+                       p->name);
+
+               APP_CHECK((!((n_readers > 1) && (n_flags == 1))),
+                       "%s has more than one reader when fragmentation or 
reassembly"
+                       " mode enabled\n",
+                       p->name);
+
+               APP_CHECK((!((n_writers > 1) && (n_flags == 1))),
+                       "%s has more than one writer when fragmentation or 
reassembly"
+                       " mode enabled\n",
+                       p->name);
+
+               n_flags = p->ipv4_ras + p->ipv6_ras;
+
+               APP_CHECK((!((p->dropless == 1) && (n_flags == 1))),
+                       "%s has dropless when reassembly mode enabled\n", 
p->name);
+
+               n_flags = p->ipv4_frag + p->ipv6_frag;
+
+               if (n_flags == 1) {
+                       uint16_t ip_hdr_size = (p->ipv4_frag) ? sizeof(struct 
ipv4_hdr) :
+                               sizeof(struct ipv6_hdr);
+
+                       APP_CHECK((p->mtu > ip_hdr_size),
+                               "%s mtu size is smaller than ip header\n", 
p->name);
+
+                       APP_CHECK((!((p->mtu - ip_hdr_size) % 8)),
+                               "%s mtu size is incorrect\n", p->name);
+               }
        }
 }

diff --git a/examples/ip_pipeline/config_parse.c 
b/examples/ip_pipeline/config_parse.c
index c9b78f9..a35bd3e 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -156,6 +156,14 @@ static const struct app_pktq_swq_params default_swq_params 
= {
        .dropless = 0,
        .n_retries = 0,
        .cpu_socket_id = 0,
+       .ipv4_frag = 0,
+       .ipv6_frag = 0,
+       .ipv4_ras = 0,
+       .ipv6_ras = 0,
+       .mtu = 0,
+       .metadata_size = 0,
+       .mempool_direct_id = 0,
+       .mempool_indirect_id = 0,
 };

 struct app_pktq_tm_params default_tm_params = {
@@ -196,13 +204,15 @@ struct app_pipeline_params default_pipeline_params = {

 static const char app_usage[] =
        "Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] -p PORT_MASK "
-       "[-l LOG_LEVEL]\n"
+       "[-l LOG_LEVEL] [--preproc PREPROCESSOR] [--preproc-args ARGS]\n"
        "\n"
        "Arguments:\n"
        "\t-f CONFIG_FILE: Default config file is %s\n"
        "\t-p PORT_MASK: Mask of NIC port IDs in hexadecimal format\n"
        "\t-s SCRIPT_FILE: No CLI script file is run when not specified\n"
        "\t-l LOG_LEVEL: 0 = NONE, 1 = HIGH PRIO (default), 2 = LOW PRIO\n"
+       "\t--preproc PREPROCESSOR: Configuration file pre-processor\n"
+       "\t--preproc-args ARGS: Arguments to be passed to pre-processor\n"
        "\n";

 static void
@@ -1107,6 +1117,10 @@ parse_pipeline(struct app_params *app,
                        ret = parser_read_uint32(&param->timer_period,
                                ent->value);
                else {
+                       APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS),
+                               "CFG: [%s] out of memory",
+                               section_name);
+
                        param->args_name[param->n_args] = strdup(ent->name);
                        param->args_value[param->n_args] = strdup(ent->value);

@@ -1397,6 +1411,7 @@ parse_swq(struct app_params *app,
        struct app_pktq_swq_params *param;
        struct rte_cfgfile_entry *entries;
        int n_entries, ret, i;
+       unsigned frag_entries = 0;
        ssize_t param_idx;

        n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
@@ -1438,6 +1453,71 @@ parse_swq(struct app_params *app,
                else if (strcmp(ent->name, "cpu") == 0)
                        ret = parser_read_uint32(&param->cpu_socket_id,
                                ent->value);
+               else if (strcmp(ent->name, "ipv4_frag") == 0) {
+                       ret = parser_read_arg_bool(ent->value);
+                       if (ret >= 0) {
+                               param->ipv4_frag = ret;
+                               if (param->mtu == 0)
+                                       param->mtu = 1500;
+                               ret = 0;
+                       }
+               } else if (strcmp(ent->name, "ipv6_frag") == 0) {
+                       ret = parser_read_arg_bool(ent->value);
+                       if (ret >= 0) {
+                               param->ipv6_frag = ret;
+                               if (param->mtu == 0)
+                                       param->mtu = 1320;
+                               ret = 0;
+                       }
+               } else if (strcmp(ent->name, "ipv4_ras") == 0) {
+                       ret = parser_read_arg_bool(ent->value);
+                       if (ret >= 0) {
+                               param->ipv4_ras = ret;
+                               ret = 0;
+                       }
+               } else if (strcmp(ent->name, "ipv6_ras") == 0) {
+                       ret = parser_read_arg_bool(ent->value);
+                       if (ret >= 0) {
+                               param->ipv6_ras = ret;
+                               ret = 0;
+                       }
+               } else if (strcmp(ent->name, "mtu") == 0) {
+                       frag_entries = 1;
+                       ret = parser_read_uint32(&param->mtu,
+                               ent->value);
+               } else if (strcmp(ent->name, "metadata_size") == 0) {
+                       frag_entries = 1;
+                       ret = parser_read_uint32(&param->metadata_size,
+                               ent->value);
+               } else if (strcmp(ent->name, "mempool_direct") == 0) {
+                       int status = validate_name(ent->value, "MEMPOOL", 1);
+                       ssize_t idx;
+
+                       APP_CHECK((status == 0),
+                               "CFG: [%s] entry '%s': invalid mempool\n",
+                               section_name,
+                               ent->name);
+
+                       idx = APP_PARAM_ADD(app->mempool_params, ent->value);
+                       PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
+                       param->mempool_direct_id = idx;
+                       frag_entries = 1;
+                       ret = 0;
+               } else if (strcmp(ent->name, "mempool_indirect") == 0) {
+                       int status = validate_name(ent->value, "MEMPOOL", 1);
+                       ssize_t idx;
+
+                       APP_CHECK((status == 0),
+                               "CFG: [%s] entry '%s': invalid mempool\n",
+                               section_name,
+                               ent->name);
+
+                       idx = APP_PARAM_ADD(app->mempool_params, ent->value);
+                       PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
+                       param->mempool_indirect_id = idx;
+                       frag_entries = 1;
+                       ret = 0;
+               }

                APP_CHECK(ret != -ESRCH,
                        "CFG: [%s] entry '%s': unknown entry\n",
@@ -1450,6 +1530,13 @@ parse_swq(struct app_params *app,
                        ent->value);
        }

+       if (frag_entries == 1) {
+               APP_CHECK(((param->ipv4_frag == 1) || (param->ipv6_frag == 1)),
+                       "CFG: [%s] ipv4/ipv6 frag is off : unsupported entries 
on this"
+                       " configuration\n",
+                       section_name);
+       }
+
        free(entries);
 }

@@ -1769,7 +1856,6 @@ parse_port_mask(struct app_params *app, uint64_t 
port_mask)
 int
 app_config_parse(struct app_params *app, const char *file_name)
 {
-       char config_file_out[APP_FILE_NAME_SIZE];
        struct rte_cfgfile *cfg;
        char **section_names;
        int i, j, sect_count;
@@ -1851,11 +1937,7 @@ app_config_parse(struct app_params *app, const char 
*file_name)
        APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines);

        /* Save configuration to output file */
-       snprintf(config_file_out,
-               APP_FILE_NAME_SIZE,
-               "%s.out",
-               app->config_file);
-       app_config_save(app, config_file_out);
+       app_config_save(app, app->output_file);

        /* Load TM configuration files */
        app_config_parse_tm(app);
@@ -2069,6 +2151,20 @@ save_swq_params(struct app_params *app, FILE *f)
                fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no");
                fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
                fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id);
+               fprintf(f, "%s = %s\n", "ipv4_frag", p->ipv4_frag ? "yes" : 
"no");
+               fprintf(f, "%s = %s\n", "ipv6_frag", p->ipv6_frag ? "yes" : 
"no");
+               fprintf(f, "%s = %s\n", "ipv4_ras", p->ipv4_ras ? "yes" : "no");
+               fprintf(f, "%s = %s\n", "ipv6_ras", p->ipv6_ras ? "yes" : "no");
+               if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1)) {
+                       fprintf(f, "%s = %" PRIu32 "\n", "mtu", p->mtu);
+                       fprintf(f, "%s = %" PRIu32 "\n", "metadata_size", 
p->metadata_size);
+                       fprintf(f, "%s = %s\n",
+                               "mempool_direct",
+                               app->mempool_params[p->mempool_direct_id].name);
+                       fprintf(f, "%s = %s\n",
+                               "mempool_indirect",
+                               
app->mempool_params[p->mempool_indirect_id].name);
+               }

                fputc('\n', f);
        }
@@ -2360,15 +2456,31 @@ app_config_init(struct app_params *app)
        return 0;
 }

+static char *
+filenamedup(const char *filename, const char *suffix)
+{
+       char *s = malloc(strlen(filename) + strlen(suffix) + 1);
+
+       if (!s)
+               return NULL;
+
+       sprintf(s, "%s%s", filename, suffix);
+       return s;
+}
+
 int
 app_config_args(struct app_params *app, int argc, char **argv)
 {
-       int opt;
-       int option_index, f_present, s_present, p_present, l_present;
+       const char *optname;
+       int opt, option_index;
+       int f_present, s_present, p_present, l_present;
+       int preproc_present, preproc_params_present;
        int scaned = 0;

        static struct option lgopts[] = {
-               {NULL, 0, 0, 0}
+               { "preproc", 1, 0, 0 },
+               { "preproc-args", 1, 0, 0 },
+               { NULL,  0, 0, 0 }
        };

        /* Copy application name */
@@ -2378,6 +2490,8 @@ app_config_args(struct app_params *app, int argc, char 
**argv)
        s_present = 0;
        p_present = 0;
        l_present = 0;
+       preproc_present = 0;
+       preproc_params_present = 0;

        while ((opt = getopt_long(argc, argv, "f:s:p:l:", lgopts,
                        &option_index)) != EOF)
@@ -2443,6 +2557,32 @@ app_config_args(struct app_params *app, int argc, char 
**argv)

                        break;

+               case 0:
+                       optname = lgopts[option_index].name;
+
+                       if (strcmp(optname, "preproc") == 0) {
+                               if (preproc_present)
+                                       rte_panic("Error: Preprocessor argument 
"
+                                               "is provided more than once\n");
+                               preproc_present = 1;
+
+                               app->preproc = strdup(optarg);
+                               break;
+                       }
+
+                       if (strcmp(optname, "preproc-args") == 0) {
+                               if (preproc_params_present)
+                                       rte_panic("Error: Preprocessor args "
+                                               "are provided more than 
once\n");
+                               preproc_params_present = 1;
+
+                               app->preproc_args = strdup(optarg);
+                               break;
+                       }
+
+                       app_print_usage(argv[0]);
+                       break;
+
                default:
                        app_print_usage(argv[0]);
                }
@@ -2453,5 +2593,40 @@ app_config_args(struct app_params *app, int argc, char 
**argv)
        if (!p_present)
                rte_panic("Error: PORT_MASK is not provided\n");

+       /* Check dependencies between args */
+       if (preproc_params_present && (preproc_present == 0))
+               rte_panic("Error: Preprocessor args specified while "
+                       "preprocessor is not defined\n");
+
+       app->parser_file = preproc_present ?
+               filenamedup(app->config_file, ".preproc") :
+               strdup(app->config_file);
+       app->output_file = filenamedup(app->config_file, ".out");
+
        return 0;
 }
+
+int
+app_config_preproc(struct app_params *app)
+{
+       char buffer[256];
+       int status;
+
+       if (app->preproc == NULL)
+               return 0;
+
+       status = access(app->config_file, F_OK | R_OK);
+       APP_CHECK((status == 0), "Unable to open file %s", app->config_file);
+
+       snprintf(buffer, sizeof(buffer), "%s %s %s > %s",
+               app->preproc,
+               app->preproc_args ? app->preproc_args : "",
+               app->config_file,
+               app->parser_file);
+
+       status = system(buffer);
+       APP_CHECK((WIFEXITED(status) && (WEXITSTATUS(status) == 0)),
+               "Error while preprocessing file \"%s\"\n", app->config_file);
+
+       return status;
+}
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index 3f9c68d..46d044e 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -803,11 +803,43 @@ app_check_link(struct app_params *app)
                rte_panic("Some links are DOWN\n");
 }

+static uint32_t
+is_any_swq_frag_or_ras(struct app_params *app)
+{
+       uint32_t i;
+
+       for (i = 0; i < app->n_pktq_swq; i++) {
+               struct app_pktq_swq_params *p = &app->swq_params[i];
+
+               if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1) ||
+                       (p->ipv4_ras == 1) || (p->ipv6_ras == 1))
+                       return 1;
+       }
+
+       return 0;
+}
+
+static void
+app_init_link_frag_ras(struct app_params *app)
+{
+       uint32_t i;
+
+       if (is_any_swq_frag_or_ras(app)) {
+               for (i = 0; i < app->n_pktq_hwq_out; i++) {
+                       struct app_pktq_hwq_out_params *p_txq = 
&app->hwq_out_params[i];
+
+                       p_txq->conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;
+               }
+       }
+}
+
 static void
 app_init_link(struct app_params *app)
 {
        uint32_t i;

+       app_init_link_frag_ras(app);
+
        for (i = 0; i < app->n_links; i++) {
                struct app_link_params *p_link = &app->link_params[i];
                uint32_t link_id, n_hwq_in, n_hwq_out, j;
@@ -916,13 +948,19 @@ app_init_swq(struct app_params *app)

        for (i = 0; i < app->n_pktq_swq; i++) {
                struct app_pktq_swq_params *p = &app->swq_params[i];
+               unsigned flags = 0;
+
+               if (app_swq_get_readers(app, p) == 1)
+                       flags |= RING_F_SC_DEQ;
+               if (app_swq_get_writers(app, p) == 1)
+                       flags |= RING_F_SP_ENQ;

                APP_LOG(app, HIGH, "Initializing %s...", p->name);
                app->swq[i] = rte_ring_create(
                                p->name,
                                p->size,
                                p->cpu_socket_id,
-                               RING_F_SP_ENQ | RING_F_SC_DEQ);
+                               flags);

                if (app->swq[i] == NULL)
                        rte_panic("%s init error\n", p->name);
@@ -1059,11 +1097,50 @@ static void app_pipeline_params_get(struct app_params 
*app,
                        break;
                }
                case APP_PKTQ_IN_SWQ:
-                       out->type = PIPELINE_PORT_IN_RING_READER;
-                       out->params.ring.ring = app->swq[in->id];
-                       out->burst_size = app->swq_params[in->id].burst_read;
-                       /* What about frag and ras ports? */
+               {
+                       struct app_pktq_swq_params *swq_params = 
&app->swq_params[in->id];
+
+                       if ((swq_params->ipv4_frag == 0) && 
(swq_params->ipv6_frag == 0)) {
+                               if (app_swq_get_readers(app, swq_params) == 1) {
+                                       out->type = 
PIPELINE_PORT_IN_RING_READER;
+                                       out->params.ring.ring = 
app->swq[in->id];
+                                       out->burst_size = 
app->swq_params[in->id].burst_read;
+                               } else {
+                                       out->type = 
PIPELINE_PORT_IN_RING_MULTI_READER;
+                                       out->params.ring_multi.ring = 
app->swq[in->id];
+                                       out->burst_size = 
swq_params->burst_read;
+                               }
+                       } else {
+                               if (swq_params->ipv4_frag == 1) {
+                                       struct 
rte_port_ring_reader_ipv4_frag_params *params =
+                                               &out->params.ring_ipv4_frag;
+
+                                       out->type = 
PIPELINE_PORT_IN_RING_READER_IPV4_FRAG;
+                                       params->ring = app->swq[in->id];
+                                       params->mtu = swq_params->mtu;
+                                       params->metadata_size = 
swq_params->metadata_size;
+                                       params->pool_direct =
+                                               
app->mempool[swq_params->mempool_direct_id];
+                                       params->pool_indirect =
+                                               
app->mempool[swq_params->mempool_indirect_id];
+                                       out->burst_size = 
swq_params->burst_read;
+                               } else {
+                                       struct 
rte_port_ring_reader_ipv6_frag_params *params =
+                                               &out->params.ring_ipv6_frag;
+
+                                       out->type = 
PIPELINE_PORT_IN_RING_READER_IPV6_FRAG;
+                                       params->ring = app->swq[in->id];
+                                       params->mtu = swq_params->mtu;
+                                       params->metadata_size = 
swq_params->metadata_size;
+                                       params->pool_direct =
+                                               
app->mempool[swq_params->mempool_direct_id];
+                                       params->pool_indirect =
+                                               
app->mempool[swq_params->mempool_indirect_id];
+                                       out->burst_size = 
swq_params->burst_read;
+                               }
+                       }
                        break;
+               }
                case APP_PKTQ_IN_TM:
                        out->type = PIPELINE_PORT_IN_SCHED_READER;
                        out->params.sched.sched = app->tm[in->id];
@@ -1122,28 +1199,68 @@ static void app_pipeline_params_get(struct app_params 
*app,
                        break;
                }
                case APP_PKTQ_OUT_SWQ:
-                       if (app->swq_params[in->id].dropless == 0) {
-                               struct rte_port_ring_writer_params *params =
-                                       &out->params.ring;
-
-                               out->type = PIPELINE_PORT_OUT_RING_WRITER;
-                               params->ring = app->swq[in->id];
-                               params->tx_burst_sz =
-                                       app->swq_params[in->id].burst_write;
+               {
+                       struct app_pktq_swq_params *swq_params = 
&app->swq_params[in->id];
+
+                       if ((swq_params->ipv4_ras == 0) && 
(swq_params->ipv6_ras == 0)) {
+                               if (app_swq_get_writers(app, swq_params) == 1) {
+                                       if (app->swq_params[in->id].dropless == 
0) {
+                                               struct 
rte_port_ring_writer_params *params =
+                                                       &out->params.ring;
+
+                                               out->type = 
PIPELINE_PORT_OUT_RING_WRITER;
+                                               params->ring = app->swq[in->id];
+                                               params->tx_burst_sz =
+                                                       
app->swq_params[in->id].burst_write;
+                                       } else {
+                                               struct 
rte_port_ring_writer_nodrop_params
+                                                       *params = 
&out->params.ring_nodrop;
+
+                                               out->type =
+                                                       
PIPELINE_PORT_OUT_RING_WRITER_NODROP;
+                                               params->ring = app->swq[in->id];
+                                               params->tx_burst_sz =
+                                                       
app->swq_params[in->id].burst_write;
+                                               params->n_retries =
+                                                       
app->swq_params[in->id].n_retries;
+                                       }
+                               } else {
+                                       if (swq_params->dropless == 0) {
+                                               struct 
rte_port_ring_multi_writer_params *params =
+                                                       &out->params.ring_multi;
+
+                                               out->type = 
PIPELINE_PORT_OUT_RING_MULTI_WRITER;
+                                               params->ring = app->swq[in->id];
+                                               params->tx_burst_sz = 
swq_params->burst_write;
+                                       } else {
+                                               struct 
rte_port_ring_multi_writer_nodrop_params
+                                                       *params = 
&out->params.ring_multi_nodrop;
+
+                                               out->type = 
PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP;
+                                               params->ring = app->swq[in->id];
+                                               params->tx_burst_sz = 
swq_params->burst_write;
+                                               params->n_retries = 
swq_params->n_retries;
+                                       }
+                               }
                        } else {
-                               struct rte_port_ring_writer_nodrop_params
-                                       *params = &out->params.ring_nodrop;
-
-                               out->type =
-                                       PIPELINE_PORT_OUT_RING_WRITER_NODROP;
-                               params->ring = app->swq[in->id];
-                               params->tx_burst_sz =
-                                       app->swq_params[in->id].burst_write;
-                               params->n_retries =
-                                       app->swq_params[in->id].n_retries;
+                               if (swq_params->ipv4_ras == 1) {
+                                       struct 
rte_port_ring_writer_ipv4_ras_params *params =
+                                               &out->params.ring_ipv4_ras;
+
+                                       out->type = 
PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS;
+                                       params->ring = app->swq[in->id];
+                                       params->tx_burst_sz = 
swq_params->burst_write;
+                               } else {
+                                       struct 
rte_port_ring_writer_ipv6_ras_params *params =
+                                               &out->params.ring_ipv6_ras;
+
+                                       out->type = 
PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS;
+                                       params->ring = app->swq[in->id];
+                                       params->tx_burst_sz = 
swq_params->burst_write;
+                               }
                        }
-                       /* What about frag and ras ports? */
                        break;
+               }
                case APP_PKTQ_OUT_TM: {
                        struct rte_port_sched_writer_params *params =
                                &out->params.sched;
diff --git a/examples/ip_pipeline/main.c b/examples/ip_pipeline/main.c
index 862e2f2..4944dcf 100644
--- a/examples/ip_pipeline/main.c
+++ b/examples/ip_pipeline/main.c
@@ -45,7 +45,9 @@ main(int argc, char **argv)

        app_config_args(&app, argc, argv);

-       app_config_parse(&app, app.config_file);
+       app_config_preproc(&app);
+
+       app_config_parse(&app, app.parser_file);

        app_config_check(&app);

diff --git a/examples/ip_pipeline/pipeline_be.h 
b/examples/ip_pipeline/pipeline_be.h
index 51f1e4f..f7269c0 100644
--- a/examples/ip_pipeline/pipeline_be.h
+++ b/examples/ip_pipeline/pipeline_be.h
@@ -45,6 +45,7 @@
 enum pipeline_port_in_type {
        PIPELINE_PORT_IN_ETHDEV_READER,
        PIPELINE_PORT_IN_RING_READER,
+       PIPELINE_PORT_IN_RING_MULTI_READER,
        PIPELINE_PORT_IN_RING_READER_IPV4_FRAG,
        PIPELINE_PORT_IN_RING_READER_IPV6_FRAG,
        PIPELINE_PORT_IN_SCHED_READER,
@@ -56,6 +57,7 @@ struct pipeline_port_in_params {
        union {
                struct rte_port_ethdev_reader_params ethdev;
                struct rte_port_ring_reader_params ring;
+               struct rte_port_ring_multi_reader_params ring_multi;
                struct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag;
                struct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag;
                struct rte_port_sched_reader_params sched;
@@ -72,6 +74,8 @@ pipeline_port_in_params_convert(struct 
pipeline_port_in_params  *p)
                return (void *) &p->params.ethdev;
        case PIPELINE_PORT_IN_RING_READER:
                return (void *) &p->params.ring;
+       case PIPELINE_PORT_IN_RING_MULTI_READER:
+               return (void *) &p->params.ring_multi;
        case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG:
                return (void *) &p->params.ring_ipv4_frag;
        case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG:
@@ -93,6 +97,8 @@ pipeline_port_in_params_get_ops(struct 
pipeline_port_in_params  *p)
                return &rte_port_ethdev_reader_ops;
        case PIPELINE_PORT_IN_RING_READER:
                return &rte_port_ring_reader_ops;
+       case PIPELINE_PORT_IN_RING_MULTI_READER:
+               return &rte_port_ring_multi_reader_ops;
        case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG:
                return &rte_port_ring_reader_ipv4_frag_ops;
        case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG:
@@ -110,7 +116,9 @@ enum pipeline_port_out_type {
        PIPELINE_PORT_OUT_ETHDEV_WRITER,
        PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP,
        PIPELINE_PORT_OUT_RING_WRITER,
+       PIPELINE_PORT_OUT_RING_MULTI_WRITER,
        PIPELINE_PORT_OUT_RING_WRITER_NODROP,
+       PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP,
        PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS,
        PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS,
        PIPELINE_PORT_OUT_SCHED_WRITER,
@@ -123,7 +131,9 @@ struct pipeline_port_out_params {
                struct rte_port_ethdev_writer_params ethdev;
                struct rte_port_ethdev_writer_nodrop_params ethdev_nodrop;
                struct rte_port_ring_writer_params ring;
+               struct rte_port_ring_multi_writer_params ring_multi;
                struct rte_port_ring_writer_nodrop_params ring_nodrop;
+               struct rte_port_ring_multi_writer_nodrop_params 
ring_multi_nodrop;
                struct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras;
                struct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras;
                struct rte_port_sched_writer_params sched;
@@ -140,8 +150,12 @@ pipeline_port_out_params_convert(struct 
pipeline_port_out_params  *p)
                return (void *) &p->params.ethdev_nodrop;
        case PIPELINE_PORT_OUT_RING_WRITER:
                return (void *) &p->params.ring;
+       case PIPELINE_PORT_OUT_RING_MULTI_WRITER:
+               return (void *) &p->params.ring_multi;
        case PIPELINE_PORT_OUT_RING_WRITER_NODROP:
                return (void *) &p->params.ring_nodrop;
+       case PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP:
+               return (void *) &p->params.ring_multi_nodrop;
        case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS:
                return (void *) &p->params.ring_ipv4_ras;
        case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS:
@@ -164,8 +178,12 @@ pipeline_port_out_params_get_ops(struct 
pipeline_port_out_params  *p)
                return &rte_port_ethdev_writer_nodrop_ops;
        case PIPELINE_PORT_OUT_RING_WRITER:
                return &rte_port_ring_writer_ops;
+       case PIPELINE_PORT_OUT_RING_MULTI_WRITER:
+               return &rte_port_ring_multi_writer_ops;
        case PIPELINE_PORT_OUT_RING_WRITER_NODROP:
                return &rte_port_ring_writer_nodrop_ops;
+       case PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP:
+               return &rte_port_ring_multi_writer_nodrop_ops;
        case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS:
                return &rte_port_ring_writer_ipv4_ras_ops;
        case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS:
-- 
1.7.9.5

Reply via email to