get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/7777/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 7777,
    "url": "https://patches.dpdk.org/api/patches/7777/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1445351774-4459-4-git-send-email-piotrx.t.azarewicz@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1445351774-4459-4-git-send-email-piotrx.t.azarewicz@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1445351774-4459-4-git-send-email-piotrx.t.azarewicz@intel.com",
    "date": "2015-10-20T14:36:14",
    "name": "[dpdk-dev,v3,3/3] examples/ip_pipeline: add mp/mc and frag/ras swq",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "b672cbdcf552e40e11adadc94001cd2aa3cd1d38",
    "submitter": {
        "id": 273,
        "url": "https://patches.dpdk.org/api/people/273/?format=api",
        "name": "Piotr Azarewicz",
        "email": "piotrx.t.azarewicz@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1445351774-4459-4-git-send-email-piotrx.t.azarewicz@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/7777/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/7777/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id BB0098E83;\n\tTue, 20 Oct 2015 16:42:12 +0200 (CEST)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n\tby dpdk.org (Postfix) with ESMTP id 618C611F5\n\tfor <dev@dpdk.org>; Tue, 20 Oct 2015 16:42:10 +0200 (CEST)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga103.jf.intel.com with ESMTP; 20 Oct 2015 07:42:10 -0700",
            "from unknown (HELO stargo) ([10.217.248.233])\n\tby orsmga002.jf.intel.com with SMTP; 20 Oct 2015 07:42:07 -0700",
            "by stargo (sSMTP sendmail emulation);\n\tTue, 20 Oct 2015 16:43:03 +0200"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.17,707,1437462000\"; d=\"scan'208\";a=\"830923811\"",
        "From": "Piotr Azarewicz <piotrx.t.azarewicz@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Tue, 20 Oct 2015 16:36:14 +0200",
        "Message-Id": "<1445351774-4459-4-git-send-email-piotrx.t.azarewicz@intel.com>",
        "X-Mailer": "git-send-email 1.9.1",
        "In-Reply-To": "<1445351774-4459-1-git-send-email-piotrx.t.azarewicz@intel.com>",
        "References": "<1443088539-28194-1-git-send-email-piotrx.t.azarewicz@intel.com>\n\t<1445351774-4459-1-git-send-email-piotrx.t.azarewicz@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 3/3] examples/ip_pipeline: add mp/mc and\n\tfrag/ras swq",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add integrated MP/MC and fragmentation/reassembly support to SWQs\n\nSigned-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>\n---\n examples/ip_pipeline/app.h          |   14 +++\n examples/ip_pipeline/config_check.c |   45 +++++++-\n examples/ip_pipeline/config_parse.c |  195 +++++++++++++++++++++++++++++++++--\n examples/ip_pipeline/init.c         |  165 ++++++++++++++++++++++++-----\n examples/ip_pipeline/main.c         |    4 +-\n examples/ip_pipeline/pipeline_be.h  |   18 ++++\n 6 files changed, 402 insertions(+), 39 deletions(-)",
    "diff": "diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h\nindex 521e3a0..943466e 100644\n--- a/examples/ip_pipeline/app.h\n+++ b/examples/ip_pipeline/app.h\n@@ -107,6 +107,14 @@ struct app_pktq_swq_params {\n \tuint32_t dropless;\n \tuint64_t n_retries;\n \tuint32_t cpu_socket_id;\n+\tuint32_t ipv4_frag;\n+\tuint32_t ipv6_frag;\n+\tuint32_t ipv4_ras;\n+\tuint32_t ipv6_ras;\n+\tuint32_t mtu;\n+\tuint32_t metadata_size;\n+\tuint32_t mempool_direct_id;\n+\tuint32_t mempool_indirect_id;\n };\n \n #ifndef APP_FILE_NAME_SIZE\n@@ -405,6 +413,10 @@ struct app_params {\n \tchar app_name[APP_APPNAME_SIZE];\n \tconst char *config_file;\n \tconst char *script_file;\n+\tconst char *parser_file;\n+\tconst char *output_file;\n+\tconst char *preproc;\n+\tconst char *preproc_args;\n \tuint64_t port_mask;\n \tuint32_t log_level;\n \n@@ -880,6 +892,8 @@ int app_config_init(struct app_params *app);\n int app_config_args(struct app_params *app,\n \tint argc, char **argv);\n \n+int app_config_preproc(struct app_params *app);\n+\n int app_config_parse(struct app_params *app,\n \tconst char *file_name);\n \ndiff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c\nindex 07f4c8b..8052bc4 100644\n--- a/examples/ip_pipeline/config_check.c\n+++ b/examples/ip_pipeline/config_check.c\n@@ -33,6 +33,8 @@\n \n #include <stdio.h>\n \n+#include <rte_ip.h>\n+\n #include \"app.h\"\n \n static void\n@@ -193,6 +195,7 @@ check_swqs(struct app_params *app)\n \t\tstruct app_pktq_swq_params *p = &app->swq_params[i];\n \t\tuint32_t n_readers = app_swq_get_readers(app, p);\n \t\tuint32_t n_writers = app_swq_get_writers(app, p);\n+\t\tuint32_t n_flags;\n \n \t\tAPP_CHECK((p->size > 0),\n \t\t\t\"%s size is 0\\n\", p->name);\n@@ -217,14 +220,48 @@ check_swqs(struct app_params *app)\n \t\tAPP_CHECK((n_readers != 0),\n \t\t\t\"%s has no reader\\n\", p->name);\n \n-\t\tAPP_CHECK((n_readers == 1),\n-\t\t\t\"%s has more than one reader\\n\", p->name);\n+\t\tif (n_readers > 1)\n+\t\t\tAPP_LOG(app, LOW, \"%s has more than one reader\", p->name);\n \n \t\tAPP_CHECK((n_writers != 0),\n \t\t\t\"%s has no writer\\n\", p->name);\n \n-\t\tAPP_CHECK((n_writers == 1),\n-\t\t\t\"%s has more than one writer\\n\", p->name);\n+\t\tif (n_writers > 1)\n+\t\t\tAPP_LOG(app, LOW, \"%s has more than one writer\", p->name);\n+\n+\t\tn_flags = p->ipv4_frag + p->ipv6_frag + p->ipv4_ras + p->ipv6_ras;\n+\n+\t\tAPP_CHECK((n_flags < 2),\n+\t\t\t\"%s has more than one fragmentation or reassembly mode enabled\\n\",\n+\t\t\tp->name);\n+\n+\t\tAPP_CHECK((!((n_readers > 1) && (n_flags == 1))),\n+\t\t\t\"%s has more than one reader when fragmentation or reassembly\"\n+\t\t\t\" mode enabled\\n\",\n+\t\t\tp->name);\n+\n+\t\tAPP_CHECK((!((n_writers > 1) && (n_flags == 1))),\n+\t\t\t\"%s has more than one writer when fragmentation or reassembly\"\n+\t\t\t\" mode enabled\\n\",\n+\t\t\tp->name);\n+\n+\t\tn_flags = p->ipv4_ras + p->ipv6_ras;\n+\n+\t\tAPP_CHECK((!((p->dropless == 1) && (n_flags == 1))),\n+\t\t\t\"%s has dropless when reassembly mode enabled\\n\", p->name);\n+\n+\t\tn_flags = p->ipv4_frag + p->ipv6_frag;\n+\n+\t\tif (n_flags == 1) {\n+\t\t\tuint16_t ip_hdr_size = (p->ipv4_frag) ? sizeof(struct ipv4_hdr) :\n+\t\t\t\tsizeof(struct ipv6_hdr);\n+\n+\t\t\tAPP_CHECK((p->mtu > ip_hdr_size),\n+\t\t\t\t\"%s mtu size is smaller than ip header\\n\", p->name);\n+\n+\t\t\tAPP_CHECK((!((p->mtu - ip_hdr_size) % 8)),\n+\t\t\t\t\"%s mtu size is incorrect\\n\", p->name);\n+\t\t}\n \t}\n }\n \ndiff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c\nindex c9b78f9..a35bd3e 100644\n--- a/examples/ip_pipeline/config_parse.c\n+++ b/examples/ip_pipeline/config_parse.c\n@@ -156,6 +156,14 @@ static const struct app_pktq_swq_params default_swq_params = {\n \t.dropless = 0,\n \t.n_retries = 0,\n \t.cpu_socket_id = 0,\n+\t.ipv4_frag = 0,\n+\t.ipv6_frag = 0,\n+\t.ipv4_ras = 0,\n+\t.ipv6_ras = 0,\n+\t.mtu = 0,\n+\t.metadata_size = 0,\n+\t.mempool_direct_id = 0,\n+\t.mempool_indirect_id = 0,\n };\n \n struct app_pktq_tm_params default_tm_params = {\n@@ -196,13 +204,15 @@ struct app_pipeline_params default_pipeline_params = {\n \n static const char app_usage[] =\n \t\"Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] -p PORT_MASK \"\n-\t\"[-l LOG_LEVEL]\\n\"\n+\t\"[-l LOG_LEVEL] [--preproc PREPROCESSOR] [--preproc-args ARGS]\\n\"\n \t\"\\n\"\n \t\"Arguments:\\n\"\n \t\"\\t-f CONFIG_FILE: Default config file is %s\\n\"\n \t\"\\t-p PORT_MASK: Mask of NIC port IDs in hexadecimal format\\n\"\n \t\"\\t-s SCRIPT_FILE: No CLI script file is run when not specified\\n\"\n \t\"\\t-l LOG_LEVEL: 0 = NONE, 1 = HIGH PRIO (default), 2 = LOW PRIO\\n\"\n+\t\"\\t--preproc PREPROCESSOR: Configuration file pre-processor\\n\"\n+\t\"\\t--preproc-args ARGS: Arguments to be passed to pre-processor\\n\"\n \t\"\\n\";\n \n static void\n@@ -1107,6 +1117,10 @@ parse_pipeline(struct app_params *app,\n \t\t\tret = parser_read_uint32(&param->timer_period,\n \t\t\t\tent->value);\n \t\telse {\n+\t\t\tAPP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS),\n+\t\t\t\t\"CFG: [%s] out of memory\",\n+\t\t\t\tsection_name);\n+\n \t\t\tparam->args_name[param->n_args] = strdup(ent->name);\n \t\t\tparam->args_value[param->n_args] = strdup(ent->value);\n \n@@ -1397,6 +1411,7 @@ parse_swq(struct app_params *app,\n \tstruct app_pktq_swq_params *param;\n \tstruct rte_cfgfile_entry *entries;\n \tint n_entries, ret, i;\n+\tunsigned frag_entries = 0;\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1438,6 +1453,71 @@ parse_swq(struct app_params *app,\n \t\telse if (strcmp(ent->name, \"cpu\") == 0)\n \t\t\tret = parser_read_uint32(&param->cpu_socket_id,\n \t\t\t\tent->value);\n+\t\telse if (strcmp(ent->name, \"ipv4_frag\") == 0) {\n+\t\t\tret = parser_read_arg_bool(ent->value);\n+\t\t\tif (ret >= 0) {\n+\t\t\t\tparam->ipv4_frag = ret;\n+\t\t\t\tif (param->mtu == 0)\n+\t\t\t\t\tparam->mtu = 1500;\n+\t\t\t\tret = 0;\n+\t\t\t}\n+\t\t} else if (strcmp(ent->name, \"ipv6_frag\") == 0) {\n+\t\t\tret = parser_read_arg_bool(ent->value);\n+\t\t\tif (ret >= 0) {\n+\t\t\t\tparam->ipv6_frag = ret;\n+\t\t\t\tif (param->mtu == 0)\n+\t\t\t\t\tparam->mtu = 1320;\n+\t\t\t\tret = 0;\n+\t\t\t}\n+\t\t} else if (strcmp(ent->name, \"ipv4_ras\") == 0) {\n+\t\t\tret = parser_read_arg_bool(ent->value);\n+\t\t\tif (ret >= 0) {\n+\t\t\t\tparam->ipv4_ras = ret;\n+\t\t\t\tret = 0;\n+\t\t\t}\n+\t\t} else if (strcmp(ent->name, \"ipv6_ras\") == 0) {\n+\t\t\tret = parser_read_arg_bool(ent->value);\n+\t\t\tif (ret >= 0) {\n+\t\t\t\tparam->ipv6_ras = ret;\n+\t\t\t\tret = 0;\n+\t\t\t}\n+\t\t} else if (strcmp(ent->name, \"mtu\") == 0) {\n+\t\t\tfrag_entries = 1;\n+\t\t\tret = parser_read_uint32(&param->mtu,\n+\t\t\t\tent->value);\n+\t\t} else if (strcmp(ent->name, \"metadata_size\") == 0) {\n+\t\t\tfrag_entries = 1;\n+\t\t\tret = parser_read_uint32(&param->metadata_size,\n+\t\t\t\tent->value);\n+\t\t} else if (strcmp(ent->name, \"mempool_direct\") == 0) {\n+\t\t\tint status = validate_name(ent->value, \"MEMPOOL\", 1);\n+\t\t\tssize_t idx;\n+\n+\t\t\tAPP_CHECK((status == 0),\n+\t\t\t\t\"CFG: [%s] entry '%s': invalid mempool\\n\",\n+\t\t\t\tsection_name,\n+\t\t\t\tent->name);\n+\n+\t\t\tidx = APP_PARAM_ADD(app->mempool_params, ent->value);\n+\t\t\tPARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);\n+\t\t\tparam->mempool_direct_id = idx;\n+\t\t\tfrag_entries = 1;\n+\t\t\tret = 0;\n+\t\t} else if (strcmp(ent->name, \"mempool_indirect\") == 0) {\n+\t\t\tint status = validate_name(ent->value, \"MEMPOOL\", 1);\n+\t\t\tssize_t idx;\n+\n+\t\t\tAPP_CHECK((status == 0),\n+\t\t\t\t\"CFG: [%s] entry '%s': invalid mempool\\n\",\n+\t\t\t\tsection_name,\n+\t\t\t\tent->name);\n+\n+\t\t\tidx = APP_PARAM_ADD(app->mempool_params, ent->value);\n+\t\t\tPARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);\n+\t\t\tparam->mempool_indirect_id = idx;\n+\t\t\tfrag_entries = 1;\n+\t\t\tret = 0;\n+\t\t}\n \n \t\tAPP_CHECK(ret != -ESRCH,\n \t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n@@ -1450,6 +1530,13 @@ parse_swq(struct app_params *app,\n \t\t\tent->value);\n \t}\n \n+\tif (frag_entries == 1) {\n+\t\tAPP_CHECK(((param->ipv4_frag == 1) || (param->ipv6_frag == 1)),\n+\t\t\t\"CFG: [%s] ipv4/ipv6 frag is off : unsupported entries on this\"\n+\t\t\t\" configuration\\n\",\n+\t\t\tsection_name);\n+\t}\n+\n \tfree(entries);\n }\n \n@@ -1769,7 +1856,6 @@ parse_port_mask(struct app_params *app, uint64_t port_mask)\n int\n app_config_parse(struct app_params *app, const char *file_name)\n {\n-\tchar config_file_out[APP_FILE_NAME_SIZE];\n \tstruct rte_cfgfile *cfg;\n \tchar **section_names;\n \tint i, j, sect_count;\n@@ -1851,11 +1937,7 @@ app_config_parse(struct app_params *app, const char *file_name)\n \tAPP_PARAM_COUNT(app->pipeline_params, app->n_pipelines);\n \n \t/* Save configuration to output file */\n-\tsnprintf(config_file_out,\n-\t\tAPP_FILE_NAME_SIZE,\n-\t\t\"%s.out\",\n-\t\tapp->config_file);\n-\tapp_config_save(app, config_file_out);\n+\tapp_config_save(app, app->output_file);\n \n \t/* Load TM configuration files */\n \tapp_config_parse_tm(app);\n@@ -2069,6 +2151,20 @@ save_swq_params(struct app_params *app, FILE *f)\n \t\tfprintf(f, \"%s = %s\\n\", \"dropless\", p->dropless ? \"yes\" : \"no\");\n \t\tfprintf(f, \"%s = %\" PRIu64 \"\\n\", \"n_retries\", p->n_retries);\n \t\tfprintf(f, \"%s = %\" PRIu32 \"\\n\", \"cpu\", p->cpu_socket_id);\n+\t\tfprintf(f, \"%s = %s\\n\", \"ipv4_frag\", p->ipv4_frag ? \"yes\" : \"no\");\n+\t\tfprintf(f, \"%s = %s\\n\", \"ipv6_frag\", p->ipv6_frag ? \"yes\" : \"no\");\n+\t\tfprintf(f, \"%s = %s\\n\", \"ipv4_ras\", p->ipv4_ras ? \"yes\" : \"no\");\n+\t\tfprintf(f, \"%s = %s\\n\", \"ipv6_ras\", p->ipv6_ras ? \"yes\" : \"no\");\n+\t\tif ((p->ipv4_frag == 1) || (p->ipv6_frag == 1)) {\n+\t\t\tfprintf(f, \"%s = %\" PRIu32 \"\\n\", \"mtu\", p->mtu);\n+\t\t\tfprintf(f, \"%s = %\" PRIu32 \"\\n\", \"metadata_size\", p->metadata_size);\n+\t\t\tfprintf(f, \"%s = %s\\n\",\n+\t\t\t\t\"mempool_direct\",\n+\t\t\t\tapp->mempool_params[p->mempool_direct_id].name);\n+\t\t\tfprintf(f, \"%s = %s\\n\",\n+\t\t\t\t\"mempool_indirect\",\n+\t\t\t\tapp->mempool_params[p->mempool_indirect_id].name);\n+\t\t}\n \n \t\tfputc('\\n', f);\n \t}\n@@ -2360,15 +2456,31 @@ app_config_init(struct app_params *app)\n \treturn 0;\n }\n \n+static char *\n+filenamedup(const char *filename, const char *suffix)\n+{\n+\tchar *s = malloc(strlen(filename) + strlen(suffix) + 1);\n+\n+\tif (!s)\n+\t\treturn NULL;\n+\n+\tsprintf(s, \"%s%s\", filename, suffix);\n+\treturn s;\n+}\n+\n int\n app_config_args(struct app_params *app, int argc, char **argv)\n {\n-\tint opt;\n-\tint option_index, f_present, s_present, p_present, l_present;\n+\tconst char *optname;\n+\tint opt, option_index;\n+\tint f_present, s_present, p_present, l_present;\n+\tint preproc_present, preproc_params_present;\n \tint scaned = 0;\n \n \tstatic struct option lgopts[] = {\n-\t\t{NULL, 0, 0, 0}\n+\t\t{ \"preproc\", 1, 0, 0 },\n+\t\t{ \"preproc-args\", 1, 0, 0 },\n+\t\t{ NULL,  0, 0, 0 }\n \t};\n \n \t/* Copy application name */\n@@ -2378,6 +2490,8 @@ app_config_args(struct app_params *app, int argc, char **argv)\n \ts_present = 0;\n \tp_present = 0;\n \tl_present = 0;\n+\tpreproc_present = 0;\n+\tpreproc_params_present = 0;\n \n \twhile ((opt = getopt_long(argc, argv, \"f:s:p:l:\", lgopts,\n \t\t\t&option_index)) != EOF)\n@@ -2443,6 +2557,32 @@ app_config_args(struct app_params *app, int argc, char **argv)\n \n \t\t\tbreak;\n \n+\t\tcase 0:\n+\t\t\toptname = lgopts[option_index].name;\n+\n+\t\t\tif (strcmp(optname, \"preproc\") == 0) {\n+\t\t\t\tif (preproc_present)\n+\t\t\t\t\trte_panic(\"Error: Preprocessor argument \"\n+\t\t\t\t\t\t\"is provided more than once\\n\");\n+\t\t\t\tpreproc_present = 1;\n+\n+\t\t\t\tapp->preproc = strdup(optarg);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tif (strcmp(optname, \"preproc-args\") == 0) {\n+\t\t\t\tif (preproc_params_present)\n+\t\t\t\t\trte_panic(\"Error: Preprocessor args \"\n+\t\t\t\t\t\t\"are provided more than once\\n\");\n+\t\t\t\tpreproc_params_present = 1;\n+\n+\t\t\t\tapp->preproc_args = strdup(optarg);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tapp_print_usage(argv[0]);\n+\t\t\tbreak;\n+\n \t\tdefault:\n \t\t\tapp_print_usage(argv[0]);\n \t\t}\n@@ -2453,5 +2593,40 @@ app_config_args(struct app_params *app, int argc, char **argv)\n \tif (!p_present)\n \t\trte_panic(\"Error: PORT_MASK is not provided\\n\");\n \n+\t/* Check dependencies between args */\n+\tif (preproc_params_present && (preproc_present == 0))\n+\t\trte_panic(\"Error: Preprocessor args specified while \"\n+\t\t\t\"preprocessor is not defined\\n\");\n+\n+\tapp->parser_file = preproc_present ?\n+\t\tfilenamedup(app->config_file, \".preproc\") :\n+\t\tstrdup(app->config_file);\n+\tapp->output_file = filenamedup(app->config_file, \".out\");\n+\n \treturn 0;\n }\n+\n+int\n+app_config_preproc(struct app_params *app)\n+{\n+\tchar buffer[256];\n+\tint status;\n+\n+\tif (app->preproc == NULL)\n+\t\treturn 0;\n+\n+\tstatus = access(app->config_file, F_OK | R_OK);\n+\tAPP_CHECK((status == 0), \"Unable to open file %s\", app->config_file);\n+\n+\tsnprintf(buffer, sizeof(buffer), \"%s %s %s > %s\",\n+\t\tapp->preproc,\n+\t\tapp->preproc_args ? app->preproc_args : \"\",\n+\t\tapp->config_file,\n+\t\tapp->parser_file);\n+\n+\tstatus = system(buffer);\n+\tAPP_CHECK((WIFEXITED(status) && (WEXITSTATUS(status) == 0)),\n+\t\t\"Error while preprocessing file \\\"%s\\\"\\n\", app->config_file);\n+\n+\treturn status;\n+}\ndiff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c\nindex 3f9c68d..46d044e 100644\n--- a/examples/ip_pipeline/init.c\n+++ b/examples/ip_pipeline/init.c\n@@ -803,11 +803,43 @@ app_check_link(struct app_params *app)\n \t\trte_panic(\"Some links are DOWN\\n\");\n }\n \n+static uint32_t\n+is_any_swq_frag_or_ras(struct app_params *app)\n+{\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < app->n_pktq_swq; i++) {\n+\t\tstruct app_pktq_swq_params *p = &app->swq_params[i];\n+\n+\t\tif ((p->ipv4_frag == 1) || (p->ipv6_frag == 1) ||\n+\t\t\t(p->ipv4_ras == 1) || (p->ipv6_ras == 1))\n+\t\t\treturn 1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void\n+app_init_link_frag_ras(struct app_params *app)\n+{\n+\tuint32_t i;\n+\n+\tif (is_any_swq_frag_or_ras(app)) {\n+\t\tfor (i = 0; i < app->n_pktq_hwq_out; i++) {\n+\t\t\tstruct app_pktq_hwq_out_params *p_txq = &app->hwq_out_params[i];\n+\n+\t\t\tp_txq->conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;\n+\t\t}\n+\t}\n+}\n+\n static void\n app_init_link(struct app_params *app)\n {\n \tuint32_t i;\n \n+\tapp_init_link_frag_ras(app);\n+\n \tfor (i = 0; i < app->n_links; i++) {\n \t\tstruct app_link_params *p_link = &app->link_params[i];\n \t\tuint32_t link_id, n_hwq_in, n_hwq_out, j;\n@@ -916,13 +948,19 @@ app_init_swq(struct app_params *app)\n \n \tfor (i = 0; i < app->n_pktq_swq; i++) {\n \t\tstruct app_pktq_swq_params *p = &app->swq_params[i];\n+\t\tunsigned flags = 0;\n+\n+\t\tif (app_swq_get_readers(app, p) == 1)\n+\t\t\tflags |= RING_F_SC_DEQ;\n+\t\tif (app_swq_get_writers(app, p) == 1)\n+\t\t\tflags |= RING_F_SP_ENQ;\n \n \t\tAPP_LOG(app, HIGH, \"Initializing %s...\", p->name);\n \t\tapp->swq[i] = rte_ring_create(\n \t\t\t\tp->name,\n \t\t\t\tp->size,\n \t\t\t\tp->cpu_socket_id,\n-\t\t\t\tRING_F_SP_ENQ | RING_F_SC_DEQ);\n+\t\t\t\tflags);\n \n \t\tif (app->swq[i] == NULL)\n \t\t\trte_panic(\"%s init error\\n\", p->name);\n@@ -1059,11 +1097,50 @@ static void app_pipeline_params_get(struct app_params *app,\n \t\t\tbreak;\n \t\t}\n \t\tcase APP_PKTQ_IN_SWQ:\n-\t\t\tout->type = PIPELINE_PORT_IN_RING_READER;\n-\t\t\tout->params.ring.ring = app->swq[in->id];\n-\t\t\tout->burst_size = app->swq_params[in->id].burst_read;\n-\t\t\t/* What about frag and ras ports? */\n+\t\t{\n+\t\t\tstruct app_pktq_swq_params *swq_params = &app->swq_params[in->id];\n+\n+\t\t\tif ((swq_params->ipv4_frag == 0) && (swq_params->ipv6_frag == 0)) {\n+\t\t\t\tif (app_swq_get_readers(app, swq_params) == 1) {\n+\t\t\t\t\tout->type = PIPELINE_PORT_IN_RING_READER;\n+\t\t\t\t\tout->params.ring.ring = app->swq[in->id];\n+\t\t\t\t\tout->burst_size = app->swq_params[in->id].burst_read;\n+\t\t\t\t} else {\n+\t\t\t\t\tout->type = PIPELINE_PORT_IN_RING_MULTI_READER;\n+\t\t\t\t\tout->params.ring_multi.ring = app->swq[in->id];\n+\t\t\t\t\tout->burst_size = swq_params->burst_read;\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tif (swq_params->ipv4_frag == 1) {\n+\t\t\t\t\tstruct rte_port_ring_reader_ipv4_frag_params *params =\n+\t\t\t\t\t\t&out->params.ring_ipv4_frag;\n+\n+\t\t\t\t\tout->type = PIPELINE_PORT_IN_RING_READER_IPV4_FRAG;\n+\t\t\t\t\tparams->ring = app->swq[in->id];\n+\t\t\t\t\tparams->mtu = swq_params->mtu;\n+\t\t\t\t\tparams->metadata_size = swq_params->metadata_size;\n+\t\t\t\t\tparams->pool_direct =\n+\t\t\t\t\t\tapp->mempool[swq_params->mempool_direct_id];\n+\t\t\t\t\tparams->pool_indirect =\n+\t\t\t\t\t\tapp->mempool[swq_params->mempool_indirect_id];\n+\t\t\t\t\tout->burst_size = swq_params->burst_read;\n+\t\t\t\t} else {\n+\t\t\t\t\tstruct rte_port_ring_reader_ipv6_frag_params *params =\n+\t\t\t\t\t\t&out->params.ring_ipv6_frag;\n+\n+\t\t\t\t\tout->type = PIPELINE_PORT_IN_RING_READER_IPV6_FRAG;\n+\t\t\t\t\tparams->ring = app->swq[in->id];\n+\t\t\t\t\tparams->mtu = swq_params->mtu;\n+\t\t\t\t\tparams->metadata_size = swq_params->metadata_size;\n+\t\t\t\t\tparams->pool_direct =\n+\t\t\t\t\t\tapp->mempool[swq_params->mempool_direct_id];\n+\t\t\t\t\tparams->pool_indirect =\n+\t\t\t\t\t\tapp->mempool[swq_params->mempool_indirect_id];\n+\t\t\t\t\tout->burst_size = swq_params->burst_read;\n+\t\t\t\t}\n+\t\t\t}\n \t\t\tbreak;\n+\t\t}\n \t\tcase APP_PKTQ_IN_TM:\n \t\t\tout->type = PIPELINE_PORT_IN_SCHED_READER;\n \t\t\tout->params.sched.sched = app->tm[in->id];\n@@ -1122,28 +1199,68 @@ static void app_pipeline_params_get(struct app_params *app,\n \t\t\tbreak;\n \t\t}\n \t\tcase APP_PKTQ_OUT_SWQ:\n-\t\t\tif (app->swq_params[in->id].dropless == 0) {\n-\t\t\t\tstruct rte_port_ring_writer_params *params =\n-\t\t\t\t\t&out->params.ring;\n-\n-\t\t\t\tout->type = PIPELINE_PORT_OUT_RING_WRITER;\n-\t\t\t\tparams->ring = app->swq[in->id];\n-\t\t\t\tparams->tx_burst_sz =\n-\t\t\t\t\tapp->swq_params[in->id].burst_write;\n+\t\t{\n+\t\t\tstruct app_pktq_swq_params *swq_params = &app->swq_params[in->id];\n+\n+\t\t\tif ((swq_params->ipv4_ras == 0) && (swq_params->ipv6_ras == 0)) {\n+\t\t\t\tif (app_swq_get_writers(app, swq_params) == 1) {\n+\t\t\t\t\tif (app->swq_params[in->id].dropless == 0) {\n+\t\t\t\t\t\tstruct rte_port_ring_writer_params *params =\n+\t\t\t\t\t\t\t&out->params.ring;\n+\n+\t\t\t\t\t\tout->type = PIPELINE_PORT_OUT_RING_WRITER;\n+\t\t\t\t\t\tparams->ring = app->swq[in->id];\n+\t\t\t\t\t\tparams->tx_burst_sz =\n+\t\t\t\t\t\t\tapp->swq_params[in->id].burst_write;\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tstruct rte_port_ring_writer_nodrop_params\n+\t\t\t\t\t\t\t*params = &out->params.ring_nodrop;\n+\n+\t\t\t\t\t\tout->type =\n+\t\t\t\t\t\t\tPIPELINE_PORT_OUT_RING_WRITER_NODROP;\n+\t\t\t\t\t\tparams->ring = app->swq[in->id];\n+\t\t\t\t\t\tparams->tx_burst_sz =\n+\t\t\t\t\t\t\tapp->swq_params[in->id].burst_write;\n+\t\t\t\t\t\tparams->n_retries =\n+\t\t\t\t\t\t\tapp->swq_params[in->id].n_retries;\n+\t\t\t\t\t}\n+\t\t\t\t} else {\n+\t\t\t\t\tif (swq_params->dropless == 0) {\n+\t\t\t\t\t\tstruct rte_port_ring_multi_writer_params *params =\n+\t\t\t\t\t\t\t&out->params.ring_multi;\n+\n+\t\t\t\t\t\tout->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER;\n+\t\t\t\t\t\tparams->ring = app->swq[in->id];\n+\t\t\t\t\t\tparams->tx_burst_sz = swq_params->burst_write;\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tstruct rte_port_ring_multi_writer_nodrop_params\n+\t\t\t\t\t\t\t*params = &out->params.ring_multi_nodrop;\n+\n+\t\t\t\t\t\tout->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP;\n+\t\t\t\t\t\tparams->ring = app->swq[in->id];\n+\t\t\t\t\t\tparams->tx_burst_sz = swq_params->burst_write;\n+\t\t\t\t\t\tparams->n_retries = swq_params->n_retries;\n+\t\t\t\t\t}\n+\t\t\t\t}\n \t\t\t} else {\n-\t\t\t\tstruct rte_port_ring_writer_nodrop_params\n-\t\t\t\t\t*params = &out->params.ring_nodrop;\n-\n-\t\t\t\tout->type =\n-\t\t\t\t\tPIPELINE_PORT_OUT_RING_WRITER_NODROP;\n-\t\t\t\tparams->ring = app->swq[in->id];\n-\t\t\t\tparams->tx_burst_sz =\n-\t\t\t\t\tapp->swq_params[in->id].burst_write;\n-\t\t\t\tparams->n_retries =\n-\t\t\t\t\tapp->swq_params[in->id].n_retries;\n+\t\t\t\tif (swq_params->ipv4_ras == 1) {\n+\t\t\t\t\tstruct rte_port_ring_writer_ipv4_ras_params *params =\n+\t\t\t\t\t\t&out->params.ring_ipv4_ras;\n+\n+\t\t\t\t\tout->type = PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS;\n+\t\t\t\t\tparams->ring = app->swq[in->id];\n+\t\t\t\t\tparams->tx_burst_sz = swq_params->burst_write;\n+\t\t\t\t} else {\n+\t\t\t\t\tstruct rte_port_ring_writer_ipv6_ras_params *params =\n+\t\t\t\t\t\t&out->params.ring_ipv6_ras;\n+\n+\t\t\t\t\tout->type = PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS;\n+\t\t\t\t\tparams->ring = app->swq[in->id];\n+\t\t\t\t\tparams->tx_burst_sz = swq_params->burst_write;\n+\t\t\t\t}\n \t\t\t}\n-\t\t\t/* What about frag and ras ports? */\n \t\t\tbreak;\n+\t\t}\n \t\tcase APP_PKTQ_OUT_TM: {\n \t\t\tstruct rte_port_sched_writer_params *params =\n \t\t\t\t&out->params.sched;\ndiff --git a/examples/ip_pipeline/main.c b/examples/ip_pipeline/main.c\nindex 862e2f2..4944dcf 100644\n--- a/examples/ip_pipeline/main.c\n+++ b/examples/ip_pipeline/main.c\n@@ -45,7 +45,9 @@ main(int argc, char **argv)\n \n \tapp_config_args(&app, argc, argv);\n \n-\tapp_config_parse(&app, app.config_file);\n+\tapp_config_preproc(&app);\n+\n+\tapp_config_parse(&app, app.parser_file);\n \n \tapp_config_check(&app);\n \ndiff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h\nindex 51f1e4f..f7269c0 100644\n--- a/examples/ip_pipeline/pipeline_be.h\n+++ b/examples/ip_pipeline/pipeline_be.h\n@@ -45,6 +45,7 @@\n enum pipeline_port_in_type {\n \tPIPELINE_PORT_IN_ETHDEV_READER,\n \tPIPELINE_PORT_IN_RING_READER,\n+\tPIPELINE_PORT_IN_RING_MULTI_READER,\n \tPIPELINE_PORT_IN_RING_READER_IPV4_FRAG,\n \tPIPELINE_PORT_IN_RING_READER_IPV6_FRAG,\n \tPIPELINE_PORT_IN_SCHED_READER,\n@@ -56,6 +57,7 @@ struct pipeline_port_in_params {\n \tunion {\n \t\tstruct rte_port_ethdev_reader_params ethdev;\n \t\tstruct rte_port_ring_reader_params ring;\n+\t\tstruct rte_port_ring_multi_reader_params ring_multi;\n \t\tstruct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag;\n \t\tstruct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag;\n \t\tstruct rte_port_sched_reader_params sched;\n@@ -72,6 +74,8 @@ pipeline_port_in_params_convert(struct pipeline_port_in_params  *p)\n \t\treturn (void *) &p->params.ethdev;\n \tcase PIPELINE_PORT_IN_RING_READER:\n \t\treturn (void *) &p->params.ring;\n+\tcase PIPELINE_PORT_IN_RING_MULTI_READER:\n+\t\treturn (void *) &p->params.ring_multi;\n \tcase PIPELINE_PORT_IN_RING_READER_IPV4_FRAG:\n \t\treturn (void *) &p->params.ring_ipv4_frag;\n \tcase PIPELINE_PORT_IN_RING_READER_IPV6_FRAG:\n@@ -93,6 +97,8 @@ pipeline_port_in_params_get_ops(struct pipeline_port_in_params  *p)\n \t\treturn &rte_port_ethdev_reader_ops;\n \tcase PIPELINE_PORT_IN_RING_READER:\n \t\treturn &rte_port_ring_reader_ops;\n+\tcase PIPELINE_PORT_IN_RING_MULTI_READER:\n+\t\treturn &rte_port_ring_multi_reader_ops;\n \tcase PIPELINE_PORT_IN_RING_READER_IPV4_FRAG:\n \t\treturn &rte_port_ring_reader_ipv4_frag_ops;\n \tcase PIPELINE_PORT_IN_RING_READER_IPV6_FRAG:\n@@ -110,7 +116,9 @@ enum pipeline_port_out_type {\n \tPIPELINE_PORT_OUT_ETHDEV_WRITER,\n \tPIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP,\n \tPIPELINE_PORT_OUT_RING_WRITER,\n+\tPIPELINE_PORT_OUT_RING_MULTI_WRITER,\n \tPIPELINE_PORT_OUT_RING_WRITER_NODROP,\n+\tPIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP,\n \tPIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS,\n \tPIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS,\n \tPIPELINE_PORT_OUT_SCHED_WRITER,\n@@ -123,7 +131,9 @@ struct pipeline_port_out_params {\n \t\tstruct rte_port_ethdev_writer_params ethdev;\n \t\tstruct rte_port_ethdev_writer_nodrop_params ethdev_nodrop;\n \t\tstruct rte_port_ring_writer_params ring;\n+\t\tstruct rte_port_ring_multi_writer_params ring_multi;\n \t\tstruct rte_port_ring_writer_nodrop_params ring_nodrop;\n+\t\tstruct rte_port_ring_multi_writer_nodrop_params ring_multi_nodrop;\n \t\tstruct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras;\n \t\tstruct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras;\n \t\tstruct rte_port_sched_writer_params sched;\n@@ -140,8 +150,12 @@ pipeline_port_out_params_convert(struct pipeline_port_out_params  *p)\n \t\treturn (void *) &p->params.ethdev_nodrop;\n \tcase PIPELINE_PORT_OUT_RING_WRITER:\n \t\treturn (void *) &p->params.ring;\n+\tcase PIPELINE_PORT_OUT_RING_MULTI_WRITER:\n+\t\treturn (void *) &p->params.ring_multi;\n \tcase PIPELINE_PORT_OUT_RING_WRITER_NODROP:\n \t\treturn (void *) &p->params.ring_nodrop;\n+\tcase PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP:\n+\t\treturn (void *) &p->params.ring_multi_nodrop;\n \tcase PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS:\n \t\treturn (void *) &p->params.ring_ipv4_ras;\n \tcase PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS:\n@@ -164,8 +178,12 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params  *p)\n \t\treturn &rte_port_ethdev_writer_nodrop_ops;\n \tcase PIPELINE_PORT_OUT_RING_WRITER:\n \t\treturn &rte_port_ring_writer_ops;\n+\tcase PIPELINE_PORT_OUT_RING_MULTI_WRITER:\n+\t\treturn &rte_port_ring_multi_writer_ops;\n \tcase PIPELINE_PORT_OUT_RING_WRITER_NODROP:\n \t\treturn &rte_port_ring_writer_nodrop_ops;\n+\tcase PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP:\n+\t\treturn &rte_port_ring_multi_writer_nodrop_ops;\n \tcase PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS:\n \t\treturn &rte_port_ring_writer_ipv4_ras_ops;\n \tcase PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS:\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "3/3"
    ]
}