get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 10569,
    "url": "https://patches.dpdk.org/api/patches/10569/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1455707651-13878-1-git-send-email-roy.fan.zhang@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": "<1455707651-13878-1-git-send-email-roy.fan.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1455707651-13878-1-git-send-email-roy.fan.zhang@intel.com",
    "date": "2016-02-17T11:14:11",
    "name": "[dpdk-dev,v2] examples/ip_pipeline: config parser clean-up",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "4ec59235037afea0a32406a92aa2ed81837898d0",
    "submitter": {
        "id": 304,
        "url": "https://patches.dpdk.org/api/people/304/?format=api",
        "name": "Fan Zhang",
        "email": "roy.fan.zhang@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1455707651-13878-1-git-send-email-roy.fan.zhang@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/10569/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/10569/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 01D01C166;\n\tWed, 17 Feb 2016 12:14:16 +0100 (CET)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id D6D5EC360\n\tfor <dev@dpdk.org>; Wed, 17 Feb 2016 12:14:13 +0100 (CET)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby fmsmga103.fm.intel.com with ESMTP; 17 Feb 2016 03:14:12 -0800",
            "from sie-lab-212-033.ir.intel.com (HELO\n\tsilpixa00383881.ir.intel.com) ([10.237.212.33])\n\tby FMSMGA003.fm.intel.com with ESMTP; 17 Feb 2016 03:14:12 -0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.22,460,1449561600\"; d=\"scan'208\";a=\"653496553\"",
        "From": "Fan Zhang <roy.fan.zhang@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Wed, 17 Feb 2016 11:14:11 +0000",
        "Message-Id": "<1455707651-13878-1-git-send-email-roy.fan.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.5.0",
        "Subject": "[dpdk-dev] [PATCH v2] examples/ip_pipeline: config parser clean-up",
        "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": "This patch updates the pipelne configuration file parser, cleans up nesting\nif/else conditions, and add clearer error message display.\n\nSigned-off-by: Fan Zhang <roy.fan.zhang@intel.com>\nAcked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>\n---\n examples/ip_pipeline/config_parse.c                | 1008 ++++++++++++--------\n examples/ip_pipeline/parser.h                      |   50 +\n .../ip_pipeline/pipeline/pipeline_firewall_be.c    |   25 +-\n .../pipeline/pipeline_flow_actions_be.c            |   91 +-\n .../pipeline/pipeline_flow_classification_be.c     |  142 ++-\n .../ip_pipeline/pipeline/pipeline_passthrough_be.c |  140 ++-\n .../ip_pipeline/pipeline/pipeline_routing_be.c     |  204 ++--\n examples/ip_pipeline/pipeline_be.h                 |   31 +-\n 8 files changed, 1112 insertions(+), 579 deletions(-)\n create mode 100644 examples/ip_pipeline/parser.h",
    "diff": "diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c\nindex 1bedbe4..5f72af9 100644\n--- a/examples/ip_pipeline/config_parse.c\n+++ b/examples/ip_pipeline/config_parse.c\n@@ -47,6 +47,7 @@\n #include <rte_string_fns.h>\n \n #include \"app.h\"\n+#include \"parser.h\"\n \n /**\n  * Default config values\n@@ -229,31 +230,19 @@ app_print_usage(char *prgname)\n \t_p;\t\t\t\t\t\\\n })\n \n-#define PARSER_IMPLICIT_PARAM_ADD_CHECK(result, section_name)\t\t\\\n-do {\t\t\t\t\t\t\t\t\t\\\n-\tAPP_CHECK((result != -EINVAL),\t\t\t\t\t\\\n-\t\t\"CFG: [%s] name too long\", section_name);\t\t\\\n-\tAPP_CHECK(result != -ENOMEM,\t\t\t\t\t\\\n-\t\t\"CFG: [%s] too much sections\", section_name);\t\t\\\n-\tAPP_CHECK(result >= 0,\t\t\t\t\t\t\\\n-\t\t\"CFG: [%s] Unknown error while adding '%s'\",\t\t\\\n-\t\tsection_name, section_name);\t\t\t\t\\\n-} while (0)\n-\n #define PARSER_PARAM_ADD_CHECK(result, params_array, section_name)\t\\\n do {\t\t\t\t\t\t\t\t\t\\\n \tAPP_CHECK((result != -EINVAL),\t\t\t\t\t\\\n-\t\t\"CFG: [%s] name too long\", section_name);\t\t\\\n+\t\t\"Parse error: no free memory\");\t\t\t\t\\\n \tAPP_CHECK((result != -ENOMEM),\t\t\t\t\t\\\n-\t\t\"CFG: [%s] too much sections\", section_name);\t\t\\\n+\t\t\"Parse error: too many \\\"%s\\\" sections\", section_name);\t\\\n \tAPP_CHECK(((result >= 0) && (params_array)[result].parsed == 0),\\\n-\t\t\"CFG: [%s] duplicate section\", section_name);\t\t\\\n+\t\t\"Parse error: duplicate \\\"%s\\\" section\", section_name);\t\\\n \tAPP_CHECK((result >= 0),\t\t\t\t\t\\\n-\t\t\"CFG: [%s] Unknown error while adding '%s'\",\t\t\\\n-\t\tsection_name, section_name);\t\t\t\t\\\n+\t\t\"Parse error in section \\\"%s\\\"\", section_name);\t\t\\\n } while (0)\n \n-static int\n+int\n parser_read_arg_bool(const char *p)\n {\n \tp = skip_white_spaces(p);\n@@ -318,7 +307,7 @@ APP_CHECK(exp, \"Parse error in section \\\"%s\\\": unrecognized entry \\\"%s\\\"\\n\",\\\n APP_CHECK(exp, \"Parse error in section \\\"%s\\\": duplicate entry \\\"%s\\\"\\n\",\\\n \tsection, entry)\n \n-static int\n+int\n parser_read_uint64(uint64_t *value, const char *p)\n {\n \tchar *next;\n@@ -336,13 +325,13 @@ parser_read_uint64(uint64_t *value, const char *p)\n \tswitch (*p) {\n \tcase 'T':\n \t\tval *= 1024ULL;\n-\t\t/* fall trought */\n+\t\t/* fall through */\n \tcase 'G':\n \t\tval *= 1024ULL;\n-\t\t/* fall trought */\n+\t\t/* fall through */\n \tcase 'M':\n \t\tval *= 1024ULL;\n-\t\t/* fall trought */\n+\t\t/* fall through */\n \tcase 'k':\n \tcase 'K':\n \t\tval *= 1024ULL;\n@@ -358,7 +347,7 @@ parser_read_uint64(uint64_t *value, const char *p)\n \treturn 0;\n }\n \n-static int\n+int\n parser_read_uint32(uint32_t *value, const char *p)\n {\n \tuint64_t val = 0;\n@@ -366,7 +355,8 @@ parser_read_uint32(uint32_t *value, const char *p)\n \n \tif (ret < 0)\n \t\treturn ret;\n-\telse if (val > UINT32_MAX)\n+\n+\tif (val > UINT32_MAX)\n \t\treturn -ERANGE;\n \n \t*value = val;\n@@ -936,8 +926,25 @@ parse_pipeline_pktq_in(struct app_params *app,\n \twhile (*next != '\\0') {\n \t\tenum app_pktq_in_type type;\n \t\tint id;\n+\t\tchar *end_space;\n+\t\tchar *end_tab;\n+\n+\t\tnext = skip_white_spaces(next);\n+\t\tif (!next)\n+\t\t\tbreak;\n+\n+\t\tend_space = strchr(next, ' ');\n+\t\tend_tab = strchr(next, '\t');\n+\n+\t\tif (end_space && (!end_tab))\n+\t\t\tend = end_space;\n+\t\telse if ((!end_space) && end_tab)\n+\t\t\tend = end_tab;\n+\t\telse if (end_space && end_tab)\n+\t\t\tend = RTE_MIN(end_space, end_tab);\n+\t\telse\n+\t\t\tend = NULL;\n \n-\t\tend = strchr(next, ' ');\n \t\tif (!end)\n \t\t\tname_len = strlen(next);\n \t\telse\n@@ -991,8 +998,25 @@ parse_pipeline_pktq_out(struct app_params *app,\n \twhile (*next != '\\0') {\n \t\tenum app_pktq_out_type type;\n \t\tint id;\n+\t\tchar *end_space;\n+\t\tchar *end_tab;\n+\n+\t\tnext = skip_white_spaces(next);\n+\t\tif (!next)\n+\t\t\tbreak;\n+\n+\t\tend_space = strchr(next, ' ');\n+\t\tend_tab = strchr(next, '\t');\n+\n+\t\tif (end_space && (!end_tab))\n+\t\t\tend = end_space;\n+\t\telse if ((!end_space) && end_tab)\n+\t\t\tend = end_tab;\n+\t\telse if (end_space && end_tab)\n+\t\t\tend = RTE_MIN(end_space, end_tab);\n+\t\telse\n+\t\t\tend = NULL;\n \n-\t\tend = strchr(next, ' ');\n \t\tif (!end)\n \t\t\tname_len = strlen(next);\n \t\telse\n@@ -1006,7 +1030,6 @@ parse_pipeline_pktq_out(struct app_params *app,\n \t\tnext += name_len;\n \t\tif (*next != '\\0')\n \t\t\tnext++;\n-\n \t\tif (validate_name(name, \"TXQ\", 2) == 0) {\n \t\t\ttype = APP_PKTQ_OUT_HWQ;\n \t\t\tid = APP_PARAM_ADD(app->hwq_out_params, name);\n@@ -1045,7 +1068,25 @@ parse_pipeline_msgq_in(struct app_params *app,\n \tssize_t idx;\n \n \twhile (*next != '\\0') {\n-\t\tend = strchr(next, ' ');\n+\t\tchar *end_space;\n+\t\tchar *end_tab;\n+\n+\t\tnext = skip_white_spaces(next);\n+\t\tif (!next)\n+\t\t\tbreak;\n+\n+\t\tend_space = strchr(next, ' ');\n+\t\tend_tab = strchr(next, '\t');\n+\n+\t\tif (end_space && (!end_tab))\n+\t\t\tend = end_space;\n+\t\telse if ((!end_space) && end_tab)\n+\t\t\tend = end_tab;\n+\t\telse if (end_space && end_tab)\n+\t\t\tend = RTE_MIN(end_space, end_tab);\n+\t\telse\n+\t\t\tend = NULL;\n+\n \t\tif (!end)\n \t\t\tname_len = strlen(next);\n \t\telse\n@@ -1086,7 +1127,25 @@ parse_pipeline_msgq_out(struct app_params *app,\n \tssize_t idx;\n \n \twhile (*next != '\\0') {\n-\t\tend = strchr(next, ' ');\n+\t\tchar *end_space;\n+\t\tchar *end_tab;\n+\n+\t\tnext = skip_white_spaces(next);\n+\t\tif (!next)\n+\t\t\tbreak;\n+\n+\t\tend_space = strchr(next, ' ');\n+\t\tend_tab = strchr(next, '\t');\n+\n+\t\tif (end_space && (!end_tab))\n+\t\t\tend = end_space;\n+\t\telse if ((!end_space) && end_tab)\n+\t\t\tend = end_tab;\n+\t\telse if (end_space && end_tab)\n+\t\t\tend = RTE_MIN(end_space, end_tab);\n+\t\telse\n+\t\t\tend = NULL;\n+\n \t\tif (!end)\n \t\t\tname_len = strlen(next);\n \t\telse\n@@ -1115,7 +1174,6 @@ parse_pipeline_msgq_out(struct app_params *app,\n \treturn 0;\n }\n \n-\n static void\n parse_pipeline(struct app_params *app,\n \tconst char *section_name,\n@@ -1125,7 +1183,7 @@ parse_pipeline(struct app_params *app,\n \tstruct app_pipeline_params *param;\n \tstruct rte_cfgfile_entry *entries;\n \tssize_t param_idx;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n \tPARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);\n@@ -1139,69 +1197,103 @@ parse_pipeline(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->pipeline_params, section_name);\n \n \tparam = &app->pipeline_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n \t\tif (strcmp(ent->name, \"type\") == 0) {\n-\t\t\tret = snprintf(param->type,\n-\t\t\t\tRTE_DIM(param->type),\n-\t\t\t\t\"%s\",\n+\t\t\tint w_size = snprintf(param->type, RTE_DIM(param->type),\n+\t\t\t\t\t\"%s\", ent->value);\n+\n+\t\t\tPARSE_ERROR(((w_size > 0) &&\n+\t\t\t\t(w_size < (int)RTE_DIM(param->type))),\n+\t\t\t\tsection_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"core\") == 0) {\n+\t\t\tint status = parse_pipeline_core(\n+\t\t\t\t&param->socket_id, &param->core_id,\n+\t\t\t\t&param->hyper_th_id, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"pktq_in\") == 0) {\n+\t\t\tint status = parse_pipeline_pktq_in(app, param,\n \t\t\t\tent->value);\n-\t\t\tif ((ret > 0) && (ret < (int)RTE_DIM(param->type)))\n-\t\t\t\tret = 0;\n-\t\t\telse\n-\t\t\t\tret = -EINVAL;\n-\t\t} else if (strcmp(ent->name, \"core\") == 0)\n-\t\t\tret = parse_pipeline_core(&param->socket_id,\n-\t\t\t\t&param->core_id,\n-\t\t\t\t&param->hyper_th_id,\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"pktq_out\") == 0) {\n+\t\t\tint status = parse_pipeline_pktq_out(app, param,\n \t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"pktq_in\") == 0)\n-\t\t\tret = parse_pipeline_pktq_in(app, param, ent->value);\n-\t\telse if (strcmp(ent->name, \"pktq_out\") == 0)\n-\t\t\tret = parse_pipeline_pktq_out(app, param, ent->value);\n-\t\telse if (strcmp(ent->name, \"msgq_in\") == 0)\n-\t\t\tret = parse_pipeline_msgq_in(app, param, ent->value);\n-\t\telse if (strcmp(ent->name, \"msgq_out\") == 0)\n-\t\t\tret = parse_pipeline_msgq_out(app, param, ent->value);\n-\t\telse if (strcmp(ent->name, \"timer_period\") == 0)\n-\t\t\tret = parser_read_uint32(&param->timer_period,\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"msgq_in\") == 0) {\n+\t\t\tint status = parse_pipeline_msgq_in(app, param,\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+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n \n-\t\t\tAPP_CHECK((param->args_name[param->n_args] != NULL) &&\n-\t\t\t\t(param->args_value[param->n_args] != NULL),\n-\t\t\t\t\"CFG: [%s] out of memory\",\n-\t\t\t\tsection_name);\n+\t\tif (strcmp(ent->name, \"msgq_out\") == 0) {\n+\t\t\tint status = parse_pipeline_msgq_out(app, param,\n+\t\t\t\tent->value);\n \n-\t\t\tparam->n_args++;\n-\t\t\tret = 0;\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n \t\t}\n \n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\tif (strcmp(ent->name, \"timer_period\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->timer_period,\n+\t\t\t\tent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* pipeline type specific items */\n+\t\tAPP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS),\n+\t\t\t\"Parse error in section \\\"%s\\\": too many \"\n+\t\t\t\"pipeline specified parameters\", section_name);\n+\n+\t\tparam->args_name[param->n_args] = strdup(ent->name);\n+\t\tparam->args_value[param->n_args] = strdup(ent->value);\n+\n+\t\tAPP_CHECK((param->args_name[param->n_args] != NULL) &&\n+\t\t\t(param->args_value[param->n_args] != NULL),\n+\t\t\t\"Parse error: no free memory\");\n+\n+\t\tparam->n_args++;\n \t}\n \n+\tparam->parsed = 1;\n+\n \tsnprintf(name, sizeof(name), \"MSGQ-REQ-%s\", section_name);\n \tparam_idx = APP_PARAM_ADD(app->msgq_params, name);\n-\tPARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name);\n+\tPARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name);\n \tapp->msgq_params[param_idx].cpu_socket_id = param->socket_id;\n \tparam->msgq_in[param->n_msgq_in++] = param_idx;\n \n \tsnprintf(name, sizeof(name), \"MSGQ-RSP-%s\", section_name);\n \tparam_idx = APP_PARAM_ADD(app->msgq_params, name);\n-\tPARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name);\n+\tPARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name);\n \tapp->msgq_params[param_idx].cpu_socket_id = param->socket_id;\n \tparam->msgq_out[param->n_msgq_out++] = param_idx;\n \n@@ -1210,7 +1302,7 @@ parse_pipeline(struct app_params *app,\n \t\tparam->core_id,\n \t\t(param->hyper_th_id) ? \"h\" : \"\");\n \tparam_idx = APP_PARAM_ADD(app->msgq_params, name);\n-\tPARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name);\n+\tPARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name);\n \tapp->msgq_params[param_idx].cpu_socket_id = param->socket_id;\n \n \tsnprintf(name, sizeof(name), \"MSGQ-RSP-CORE-s%\" PRIu32 \"c%\" PRIu32 \"%s\",\n@@ -1218,7 +1310,7 @@ parse_pipeline(struct app_params *app,\n \t\tparam->core_id,\n \t\t(param->hyper_th_id) ? \"h\" : \"\");\n \tparam_idx = APP_PARAM_ADD(app->msgq_params, name);\n-\tPARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name);\n+\tPARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name);\n \tapp->msgq_params[param_idx].cpu_socket_id = param->socket_id;\n \n \tfree(entries);\n@@ -1232,7 +1324,7 @@ parse_mempool(struct app_params *app,\n \tstruct app_mempool_params *param;\n \tstruct rte_cfgfile_entry *entries;\n \tssize_t param_idx;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n \tPARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);\n@@ -1246,36 +1338,52 @@ parse_mempool(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->mempool_params, section_name);\n \n \tparam = &app->mempool_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n-\t\tif (strcmp(ent->name, \"buffer_size\") == 0)\n-\t\t\tret = parser_read_uint32(&param->buffer_size,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"pool_size\") == 0)\n-\t\t\tret = parser_read_uint32(&param->pool_size,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"cache_size\") == 0)\n-\t\t\tret = parser_read_uint32(&param->cache_size,\n-\t\t\t\tent->value);\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\tif (strcmp(ent->name, \"buffer_size\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->buffer_size, ent->value);\n \n-\t\tAPP_CHECK(ret != -ESRCH,\n-\t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"pool_size\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->pool_size, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"cache_size\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->cache_size, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"cpu\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->cpu_socket_id, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tparam->parsed = 1;\n+\n \tfree(entries);\n }\n \n@@ -1286,7 +1394,7 @@ parse_link(struct app_params *app,\n {\n \tstruct app_link_params *param;\n \tstruct rte_cfgfile_entry *entries;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1301,48 +1409,79 @@ parse_link(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->link_params, section_name);\n \n \tparam = &app->link_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n \t\tif (strcmp(ent->name, \"promisc\") == 0) {\n-\t\t\tret = parser_read_arg_bool(ent->value);\n-\t\t\tif (ret >= 0) {\n-\t\t\t\tparam->promisc = ret;\n-\t\t\t\tret = 0;\n-\t\t\t}\n-\t\t} else if (strcmp(ent->name, \"arp_q\") == 0)\n-\t\t\tret = parser_read_uint32(&param->arp_q,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"tcp_syn_q\") == 0)\n-\t\t\tret = parser_read_uint32(&param->tcp_syn_local_q,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"ip_local_q\") == 0)\n-\t\t\tret = parser_read_uint32(&param->ip_local_q,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"tcp_local_q\") == 0)\n-\t\t\tret = parser_read_uint32(&param->tcp_local_q,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"udp_local_q\") == 0)\n-\t\t\tret = parser_read_uint32(&param->udp_local_q,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"sctp_local_q\") == 0)\n-\t\t\tret = parser_read_uint32(&param->sctp_local_q,\n+\t\t\tint status = parser_read_arg_bool(ent->value);\n+\n+\t\t\tPARSE_ERROR((status != -EINVAL), section_name,\n+\t\t\t\tent->name);\n+\t\t\tparam->promisc = status;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"arp_q\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->arp_q,\n \t\t\t\tent->value);\n \n-\t\tAPP_CHECK(ret != -ESRCH,\n-\t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"tcp_syn_q\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->tcp_syn_local_q, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name, ent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"ip_local_q\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->ip_local_q, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\n+\t\tif (strcmp(ent->name, \"tcp_local_q\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->tcp_local_q, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"udp_local_q\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->udp_local_q, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"sctp_local_q\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->sctp_local_q, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tparam->parsed = 1;\n+\n \tfree(entries);\n }\n \n@@ -1353,7 +1492,7 @@ parse_rxq(struct app_params *app,\n {\n \tstruct app_pktq_hwq_in_params *param;\n \tstruct rte_cfgfile_entry *entries;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1368,43 +1507,49 @@ parse_rxq(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->hwq_in_params, section_name);\n \n \tparam = &app->hwq_in_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n \t\tif (strcmp(ent->name, \"mempool\") == 0) {\n-\t\t\tint status = validate_name(ent->value, \"MEMPOOL\", 1);\n+\t\t\tint status = validate_name(ent->value,\n+\t\t\t\t\"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\tPARSE_ERROR((status == 0), section_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\tidx = APP_PARAM_ADD(app->mempool_params,\n+\t\t\t\tent->value);\n+\t\t\tPARSER_PARAM_ADD_CHECK(idx, app->mempool_params,\n+\t\t\t\tsection_name);\n \t\t\tparam->mempool_id = idx;\n-\t\t\tret = 0;\n-\t\t} else if (strcmp(ent->name, \"size\") == 0)\n-\t\t\tret = parser_read_uint32(&param->size,\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"size\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->size,\n \t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"burst\") == 0)\n-\t\t\tret = parser_read_uint32(&param->burst,\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"burst\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->burst,\n \t\t\t\tent->value);\n \n-\t\tAPP_CHECK(ret != -ESRCH,\n-\t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tparam->parsed = 1;\n+\n \tfree(entries);\n }\n \n@@ -1415,7 +1560,7 @@ parse_txq(struct app_params *app,\n {\n \tstruct app_pktq_hwq_out_params *param;\n \tstruct rte_cfgfile_entry *entries;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1430,35 +1575,44 @@ parse_txq(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->hwq_out_params, section_name);\n \n \tparam = &app->hwq_out_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n-\t\tif (strcmp(ent->name, \"size\") == 0)\n-\t\t\tret = parser_read_uint32(&param->size, ent->value);\n-\t\telse if (strcmp(ent->name, \"burst\") == 0)\n-\t\t\tret = parser_read_uint32(&param->burst, ent->value);\n-\t\telse if (strcmp(ent->name, \"dropless\") == 0) {\n-\t\t\tret = parser_read_arg_bool(ent->value);\n-\t\t\tif (ret >= 0) {\n-\t\t\t\tparam->dropless = ret;\n-\t\t\t\tret = 0;\n-\t\t\t}\n+\t\tif (strcmp(ent->name, \"size\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->size,\n+\t\t\t\tent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n \t\t}\n \n-\t\tAPP_CHECK(ret != -ESRCH,\n-\t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\tif (strcmp(ent->name, \"burst\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->burst,\n+\t\t\t\tent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"dropless\") == 0) {\n+\t\t\tint status = parser_read_arg_bool(ent->value);\n+\n+\n+\t\t\tPARSE_ERROR((status != -EINVAL), section_name,\n+\t\t\t\tent->name);\n+\t\t\tparam->dropless = status;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tparam->parsed = 1;\n+\n \tfree(entries);\n }\n \n@@ -1469,8 +1623,12 @@ parse_swq(struct app_params *app,\n {\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+\tint n_entries, i;\n+\tuint32_t mtu_present = 0;\n+\tuint32_t metadata_size_present = 0;\n+\tuint32_t mempool_direct_present = 0;\n+\tuint32_t mempool_indirect_present = 0;\n+\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1485,117 +1643,188 @@ parse_swq(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->swq_params, section_name);\n \n \tparam = &app->swq_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n-\t\tif (strcmp(ent->name, \"size\") == 0)\n-\t\t\tret = parser_read_uint32(&param->size,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"burst_read\") == 0)\n-\t\t\tret = parser_read_uint32(&param->burst_read,\n+\t\tif (strcmp(ent->name, \"size\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->size,\n \t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"burst_write\") == 0)\n-\t\t\tret = parser_read_uint32(&param->burst_write,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"dropless\") == 0) {\n-\t\t\tret = parser_read_arg_bool(ent->value);\n-\t\t\tif (ret >= 0) {\n-\t\t\t\tparam->dropless = ret;\n-\t\t\t\tret = 0;\n-\t\t\t}\n-\t\t} else if (strcmp(ent->name, \"n_retries\") == 0)\n-\t\t\tret = parser_read_uint64(&param->n_retries,\n-\t\t\t\tent->value);\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+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"burst_read\") == 0) {\n+\t\t\tint status = parser_read_uint32(&\n+\t\t\t\tparam->burst_read, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"burst_write\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->burst_write, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"dropless\") == 0) {\n+\t\t\tint status = parser_read_arg_bool(ent->value);\n+\n+\t\t\tPARSE_ERROR((status != -EINVAL), section_name,\n+\t\t\t\tent->name);\n+\t\t\tparam->dropless = status;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"n_retries\") == 0) {\n+\t\t\tint status = parser_read_uint64(&param->n_retries,\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+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"cpu\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->cpu_socket_id, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name, ent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"ipv4_frag\") == 0) {\n+\t\t\tint status = parser_read_arg_bool(ent->value);\n+\n+\t\t\tPARSE_ERROR((status != -EINVAL), section_name,\n+\t\t\t\tent->name);\n+\n+\t\t\tparam->ipv4_frag = status;\n+\t\t\tif (param->mtu == 0)\n+\t\t\t\tparam->mtu = 1500;\n+\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"ipv6_frag\") == 0) {\n+\t\t\tint status = parser_read_arg_bool(ent->value);\n+\n+\t\t\tPARSE_ERROR((status != -EINVAL), section_name,\n+\t\t\t\tent->name);\n+\t\t\tparam->ipv6_frag = status;\n+\t\t\tif (param->mtu == 0)\n+\t\t\t\tparam->mtu = 1320;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"ipv4_ras\") == 0) {\n+\t\t\tint status = parser_read_arg_bool(ent->value);\n+\n+\t\t\tPARSE_ERROR((status != -EINVAL), section_name,\n+\t\t\t\tent->name);\n+\t\t\tparam->ipv4_ras = status;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"ipv6_ras\") == 0) {\n+\t\t\tint status = parser_read_arg_bool(ent->value);\n+\n+\t\t\tPARSE_ERROR((status != -EINVAL), section_name,\n+\t\t\t\tent->name);\n+\t\t\tparam->ipv6_ras = status;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"mtu\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->mtu,\n+\t\t\t\t\tent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tmtu_present = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"metadata_size\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->metadata_size, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tmetadata_size_present = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"mempool_direct\") == 0) {\n+\t\t\tint status = validate_name(ent->value,\n+\t\t\t\t\"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\tPARSE_ERROR((status == 0), section_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\tidx = APP_PARAM_ADD(app->mempool_params,\n+\t\t\t\tent->value);\n+\t\t\tPARSER_PARAM_ADD_CHECK(idx, app->mempool_params,\n+\t\t\t\tsection_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\tmempool_direct_present = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"mempool_indirect\") == 0) {\n+\t\t\tint status = validate_name(ent->value,\n+\t\t\t\t\"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\tPARSE_ERROR((status == 0), section_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\tidx = APP_PARAM_ADD(app->mempool_params,\n+\t\t\t\tent->value);\n+\t\t\tPARSER_PARAM_ADD_CHECK(idx, app->mempool_params,\n+\t\t\t\tsection_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-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n-\t}\n+\t\t\tmempool_indirect_present = 1;\n+\t\t\tcontinue;\n+\t\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\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tAPP_CHECK(((mtu_present) &&\n+\t\t((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),\n+\t\t\"Parse error in section \\\"%s\\\": IPv4/IPv6 fragmentation \"\n+\t\t\"is off, therefore entry \\\"mtu\\\" is not allowed\",\n+\t\tsection_name);\n+\n+\tAPP_CHECK(((metadata_size_present) &&\n+\t\t((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),\n+\t\t\"Parse error in section \\\"%s\\\": IPv4/IPv6 fragmentation \"\n+\t\t\"is off, therefore entry \\\"metadata_size\\\" is \"\n+\t\t\"not allowed\", section_name);\n+\n+\tAPP_CHECK(((mempool_direct_present) &&\n+\t\t((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),\n+\t\t\"Parse error in section \\\"%s\\\": IPv4/IPv6 fragmentation \"\n+\t\t\"is off, therefore entry \\\"mempool_direct\\\" is \"\n+\t\t\"not allowed\", section_name);\n+\n+\tAPP_CHECK(((mempool_indirect_present) &&\n+\t\t((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),\n+\t\t\"Parse error in section \\\"%s\\\": IPv4/IPv6 fragmentation \"\n+\t\t\"is off, therefore entry \\\"mempool_indirect\\\" is \"\n+\t\t\"not allowed\", section_name);\n+\n+\tparam->parsed = 1;\n+\n \tfree(entries);\n }\n \n@@ -1606,7 +1835,7 @@ parse_tm(struct app_params *app,\n {\n \tstruct app_pktq_tm_params *param;\n \tstruct rte_cfgfile_entry *entries;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1621,41 +1850,40 @@ parse_tm(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->tm_params, section_name);\n \n \tparam = &app->tm_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n \t\tif (strcmp(ent->name, \"cfg\") == 0) {\n \t\t\tparam->file_name = strdup(ent->value);\n-\t\t\tif (param->file_name == NULL)\n-\t\t\t\tret = -EINVAL;\n-\t\t\telse\n-\t\t\t\tret = 0;\n-\t\t} else if (strcmp(ent->name, \"burst_read\") == 0)\n-\t\t\tret = parser_read_uint32(&param->burst_read,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"burst_write\") == 0)\n-\t\t\tret = parser_read_uint32(&param->burst_write,\n-\t\t\t\tent->value);\n+\t\t\tPARSE_ERROR_MALLOC(param->file_name != NULL);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"burst_read\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->burst_read, ent->value);\n \n-\t\tAPP_CHECK(ret != -ESRCH,\n-\t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret != -EBADF,\n-\t\t\t\"CFG: [%s] entry '%s': TM cfg parse error '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"burst_write\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->burst_write, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tparam->parsed = 1;\n+\n \tfree(entries);\n }\n \n@@ -1666,7 +1894,7 @@ parse_source(struct app_params *app,\n {\n \tstruct app_pktq_source_params *param;\n \tstruct rte_cfgfile_entry *entries;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1681,39 +1909,40 @@ parse_source(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->source_params, section_name);\n \n \tparam = &app->source_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n \t\tif (strcmp(ent->name, \"mempool\") == 0) {\n-\t\t\tint status = validate_name(ent->value, \"MEMPOOL\", 1);\n+\t\t\tint status = validate_name(ent->value,\n+\t\t\t\t\"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\t\tsection_name,\n-\t\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\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tidx = APP_PARAM_ADD(app->mempool_params,\n+\t\t\t\tent->value);\n+\t\t\tPARSER_PARAM_ADD_CHECK(idx, app->mempool_params,\n+\t\t\t\tsection_name);\n \t\t\tparam->mempool_id = idx;\n-\t\t\tret = 0;\n-\t\t} else if (strcmp(ent->name, \"burst\") == 0)\n-\t\t\tret = parser_read_uint32(&param->burst, ent->value);\n-\n-\t\tAPP_CHECK(ret != -ESRCH,\n-\t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"burst\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->burst,\n+\t\t\t\tent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tparam->parsed = 1;\n+\n \tfree(entries);\n }\n \n@@ -1724,7 +1953,7 @@ parse_msgq_req_pipeline(struct app_params *app,\n {\n \tstruct app_msgq_params *param;\n \tstruct rte_cfgfile_entry *entries;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1739,26 +1968,24 @@ parse_msgq_req_pipeline(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name);\n \n \tparam = &app->msgq_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n-\t\tif (strcmp(ent->name, \"size\") == 0)\n-\t\t\tret = parser_read_uint32(&param->size, ent->value);\n-\n-\t\tAPP_CHECK(ret != -ESRCH,\n-\t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\tif (strcmp(ent->name, \"size\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->size,\n+\t\t\t\tent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tparam->parsed = 1;\n \tfree(entries);\n }\n \n@@ -1769,7 +1996,7 @@ parse_msgq_rsp_pipeline(struct app_params *app,\n {\n \tstruct app_msgq_params *param;\n \tstruct rte_cfgfile_entry *entries;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1784,26 +2011,25 @@ parse_msgq_rsp_pipeline(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name);\n \n \tparam = &app->msgq_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n-\t\tif (strcmp(ent->name, \"size\") == 0)\n-\t\t\tret = parser_read_uint32(&param->size, ent->value);\n-\n-\t\tAPP_CHECK(ret != -ESRCH,\n-\t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\tif (strcmp(ent->name, \"size\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->size,\n+\t\t\t\tent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tparam->parsed = 1;\n+\n \tfree(entries);\n }\n \n@@ -1814,7 +2040,7 @@ parse_msgq(struct app_params *app,\n {\n \tstruct app_msgq_params *param;\n \tstruct rte_cfgfile_entry *entries;\n-\tint n_entries, ret, i;\n+\tint n_entries, i;\n \tssize_t param_idx;\n \n \tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n@@ -1829,30 +2055,34 @@ parse_msgq(struct app_params *app,\n \tPARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name);\n \n \tparam = &app->msgq_params[param_idx];\n-\tparam->parsed = 1;\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n \n-\t\tret = -ESRCH;\n-\t\tif (strcmp(ent->name, \"size\") == 0)\n-\t\t\tret = parser_read_uint32(&param->size,\n-\t\t\t\tent->value);\n-\t\telse if (strcmp(ent->name, \"cpu\") == 0)\n-\t\t\tret = parser_read_uint32(&param->cpu_socket_id,\n+\t\tif (strcmp(ent->name, \"size\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->size,\n \t\t\t\tent->value);\n \n-\t\tAPP_CHECK(ret != -ESRCH,\n-\t\t\t\"CFG: [%s] entry '%s': unknown entry\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name);\n-\t\tAPP_CHECK(ret == 0,\n-\t\t\t\"CFG: [%s] entry '%s': Invalid value '%s'\\n\",\n-\t\t\tsection_name,\n-\t\t\tent->name,\n-\t\t\tent->value);\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"cpu\") == 0) {\n+\t\t\tint status = parser_read_uint32(\n+\t\t\t\t&param->cpu_socket_id, ent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n \t}\n \n+\tparam->parsed = 1;\n+\n \tfree(entries);\n }\n \n@@ -1887,7 +2117,7 @@ create_implicit_mempools(struct app_params *app)\n \tssize_t idx;\n \n \tidx = APP_PARAM_ADD(app->mempool_params, \"MEMPOOL0\");\n-\tPARSER_IMPLICIT_PARAM_ADD_CHECK(idx, \"start-up\");\n+\tPARSER_PARAM_ADD_CHECK(idx, app->mempool_params, \"start-up\");\n }\n \n static void\n@@ -1905,7 +2135,7 @@ parse_port_mask(struct app_params *app, uint64_t port_mask)\n \n \t\tsnprintf(name, sizeof(name), \"LINK%\" PRIu32, link_id);\n \t\tidx = APP_PARAM_ADD(app->link_params, name);\n-\t\tPARSER_IMPLICIT_PARAM_ADD_CHECK(idx, name);\n+\t\tPARSER_PARAM_ADD_CHECK(idx, app->link_params, name);\n \n \t\tapp->link_params[idx].pmd_id = pmd_id;\n \t\tlink_id++;\n@@ -1927,13 +2157,16 @@ app_config_parse(struct app_params *app, const char *file_name)\n \n \t/* Load application configuration file */\n \tcfg = rte_cfgfile_load(file_name, 0);\n-\tAPP_CHECK(cfg != NULL, \"Unable to load config file %s\", file_name);\n+\tAPP_CHECK((cfg != NULL), \"Parse error: Unable to load config \"\n+\t\t\"file %s\", file_name);\n \n \tsect_count = rte_cfgfile_num_sections(cfg, NULL, 0);\n-\tAPP_CHECK(sect_count > 0, \"Number of sections return %d\", sect_count);\n+\tAPP_CHECK((sect_count > 0), \"Parse error: number of sections \"\n+\t\t\"in file \\\"%s\\\" return %d\", file_name,\n+\t\tsect_count);\n \n \tsection_names = malloc(sect_count * sizeof(char *));\n-\tAPP_CHECK(section_names != NULL, \"Failed to allocate memory\");\n+\tPARSE_ERROR_MALLOC(section_names != NULL);\n \n \tfor (i = 0; i < sect_count; i++)\n \t\tsection_names[i] = malloc(CFG_NAME_LEN);\n@@ -1969,13 +2202,13 @@ app_config_parse(struct app_params *app, const char *file_name)\n \t\t}\n \n \t\tAPP_CHECK(j < (int)RTE_DIM(cfg_file_scheme),\n-\t\t\t\"Unknown section %s\",\n+\t\t\t\"Parse error: unknown section %s\",\n \t\t\tsection_names[i]);\n \n \t\tAPP_CHECK(validate_name(section_names[i],\n \t\t\tsch_s->prefix,\n \t\t\tsch_s->numbers) == 0,\n-\t\t\t\"Invalid section name '%s'\",\n+\t\t\t\"Parse error: invalid section name \\\"%s\\\"\",\n \t\t\tsection_names[i]);\n \n \t\tsch_s->load(app, section_names[i], cfg);\n@@ -2343,7 +2576,9 @@ save_pipeline_params(struct app_params *app, FILE *f)\n \t\t\t\t\tname = app->source_params[pp->id].name;\n \t\t\t\t\tbreak;\n \t\t\t\tdefault:\n-\t\t\t\t\tAPP_CHECK(0, \"Error\\n\");\n+\t\t\t\t\tAPP_CHECK(0, \"System error \"\n+\t\t\t\t\t\t\"occurred while saving \"\n+\t\t\t\t\t\t\"parameter to file\");\n \t\t\t\t}\n \n \t\t\t\tfprintf(f, \" %s\", name);\n@@ -2375,7 +2610,9 @@ save_pipeline_params(struct app_params *app, FILE *f)\n \t\t\t\t\tname = app->sink_params[pp->id].name;\n \t\t\t\t\tbreak;\n \t\t\t\tdefault:\n-\t\t\t\t\tAPP_CHECK(0, \"Error\\n\");\n+\t\t\t\t\tAPP_CHECK(0, \"System error \"\n+\t\t\t\t\t\t\"occurred while saving \"\n+\t\t\t\t\t\t\"parameter to file\");\n \t\t\t\t}\n \n \t\t\t\tfprintf(f, \" %s\", name);\n@@ -2438,12 +2675,13 @@ app_config_save(struct app_params *app, const char *file_name)\n \tdir_name = dirname(name);\n \tstatus = access(dir_name, W_OK);\n \tAPP_CHECK((status == 0),\n-\t\t\"Need write access to directory \\\"%s\\\" to save configuration\\n\",\n-\t\tdir_name);\n+\t\t\"Error: need write access privilege to directory \"\n+\t\t\"\\\"%s\\\" to save configuration\\n\", dir_name);\n \n \tfile = fopen(file_name, \"w\");\n \tAPP_CHECK((file != NULL),\n-\t\t\"Failed to save configuration to file \\\"%s\\\"\", file_name);\n+\t\t\"Error: failed to save configuration to file \\\"%s\\\"\",\n+\t\tfile_name);\n \n \tsave_eal_params(app, file);\n \tsave_pipeline_params(app, file);\n@@ -2680,7 +2918,8 @@ app_config_preproc(struct app_params *app)\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+\tAPP_CHECK((status == 0), \"Error: Unable to open file %s\",\n+\t\tapp->config_file);\n \n \tsnprintf(buffer, sizeof(buffer), \"%s %s %s > %s\",\n \t\tapp->preproc,\n@@ -2690,7 +2929,8 @@ app_config_preproc(struct app_params *app)\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+\t\t\"Error occurred while pre-processing file \\\"%s\\\"\\n\",\n+\t\tapp->config_file);\n \n \treturn status;\n }\ndiff --git a/examples/ip_pipeline/parser.h b/examples/ip_pipeline/parser.h\nnew file mode 100644\nindex 0000000..58b59da\n--- /dev/null\n+++ b/examples/ip_pipeline/parser.h\n@@ -0,0 +1,50 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef __INCLUDE_PARSER_H__\n+#define __INCLUDE_PARSER_H__\n+\n+int\n+parser_read_arg_bool(const char *p);\n+\n+int\n+parser_read_uint64(uint64_t *value, const char *p);\n+\n+int\n+parser_read_uint32(uint32_t *value, const char *p);\n+\n+int\n+parse_hex_string(char *src, uint8_t *dst, uint32_t *size);\n+\n+#endif\n+\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c\nindex 1c376f7..1981cc7 100644\n--- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c\n+++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c\n@@ -42,6 +42,7 @@\n #include <rte_table_acl.h>\n \n #include \"pipeline_firewall_be.h\"\n+#include \"parser.h\"\n \n struct pipeline_firewall {\n \tstruct pipeline p;\n@@ -308,17 +309,26 @@ pipeline_firewall_parse_args(struct pipeline_firewall *p,\n \t\tchar *arg_value = params->args_value[i];\n \n \t\tif (strcmp(arg_name, \"n_rules\") == 0) {\n-\t\t\tif (n_rules_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tn_rules_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tn_rules_present = 1;\n \n-\t\t\tp->n_rules = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->n_rules,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \t\t\tcontinue;\n \t\t}\n \n \t\tif (strcmp(arg_name, \"pkt_type\") == 0) {\n-\t\t\tif (pkt_type_present)\n-\t\t\t\treturn -1;\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tpkt_type_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tpkt_type_present = 1;\n \n \t\t\t/* ipv4 */\n@@ -351,11 +361,12 @@ pipeline_firewall_parse_args(struct pipeline_firewall *p,\n \t\t\t}\n \n \t\t\t/* other */\n-\t\t\treturn -1;\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(0, params->name,\n+\t\t\t\targ_name, arg_value);\n \t\t}\n \n \t\t/* other */\n-\t\treturn -1;\n+\t\tPIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name);\n \t}\n \n \treturn 0;\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c\nindex 73dbe7a..d502be0 100644\n--- a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c\n+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c\n@@ -42,6 +42,7 @@\n \n #include \"pipeline_actions_common.h\"\n #include \"pipeline_flow_actions_be.h\"\n+#include \"parser.h\"\n #include \"hash_func.h\"\n \n int\n@@ -415,80 +416,118 @@ pipeline_fa_parse_args(struct pipeline_fa_params *p,\n \n \t\t/* n_flows */\n \t\tif (strcmp(arg_name, \"n_flows\") == 0) {\n-\t\t\tif (n_flows_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n \n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tn_flows_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tn_flows_present = 1;\n \n-\t\t\tp->n_flows = atoi(arg_value);\n-\t\t\tif (p->n_flows == 0)\n-\t\t\t\treturn -1;\n+\t\t\tstatus = parser_read_uint32(&p->n_flows,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&\n+\t\t\t\t(p->n_flows != 0)), params->name,\n+\t\t\t\targ_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* n_meters_per_flow */\n \t\tif (strcmp(arg_name, \"n_meters_per_flow\") == 0) {\n-\t\t\tif (n_meters_per_flow_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n \n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tn_meters_per_flow_present == 0,\n+\t\t\t\tparams->name, arg_name);\n \t\t\tn_meters_per_flow_present = 1;\n \n-\t\t\tp->n_meters_per_flow = atoi(arg_value);\n-\t\t\tif ((p->n_meters_per_flow == 0) ||\n-\t\t\t\t(p->n_meters_per_flow > PIPELINE_FA_N_TC_MAX))\n-\t\t\t\treturn -1;\n+\t\t\tstatus = parser_read_uint32(&p->n_meters_per_flow,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&\n+\t\t\t\t(p->n_meters_per_flow != 0)),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) &&\n+\t\t\t\t(p->n_meters_per_flow <=\n+\t\t\t\tPIPELINE_FA_N_TC_MAX)), params->name,\n+\t\t\t\targ_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* flow_id_offset */\n \t\tif (strcmp(arg_name, \"flow_id_offset\") == 0) {\n-\t\t\tif (flow_id_offset_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n \n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tflow_id_offset_present == 0,\n+\t\t\t\tparams->name, arg_name);\n \t\t\tflow_id_offset_present = 1;\n \n-\t\t\tp->flow_id_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->flow_id_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* ip_hdr_offset */\n \t\tif (strcmp(arg_name, \"ip_hdr_offset\") == 0) {\n-\t\t\tif (ip_hdr_offset_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n \n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tip_hdr_offset_present == 0,\n+\t\t\t\tparams->name, arg_name);\n \t\t\tip_hdr_offset_present = 1;\n \n-\t\t\tp->ip_hdr_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->ip_hdr_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* color_offset */\n \t\tif (strcmp(arg_name, \"color_offset\") == 0) {\n-\t\t\tif (color_offset_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n \n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tcolor_offset_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tcolor_offset_present = 1;\n \n+\t\t\tstatus = parser_read_uint32(&p->color_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\n \t\t\tp->dscp_enabled = 1;\n-\t\t\tp->color_offset = atoi(arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* Unknown argument */\n-\t\treturn -1;\n+\t\tPIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name);\n \t}\n \n \t/* Check that mandatory arguments are present */\n-\tif ((n_flows_present == 0) ||\n-\t\t(flow_id_offset_present == 0) ||\n-\t\t(ip_hdr_offset_present == 0) ||\n-\t\t(color_offset_present == 0))\n-\t\treturn -1;\n+\tPIPELINE_PARSE_ERR_MANDATORY((n_flows_present), params->name,\n+\t\t\"n_flows\");\n+\tPIPELINE_PARSE_ERR_MANDATORY((flow_id_offset_present),\n+\t\tparams->name, \"flow_id_offset\");\n+\tPIPELINE_PARSE_ERR_MANDATORY((ip_hdr_offset_present),\n+\t\tparams->name, \"ip_hdr_offset\");\n+\tPIPELINE_PARSE_ERR_MANDATORY((color_offset_present), params->name,\n+\t\t\"color_offset\");\n \n \treturn 0;\n }\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c\nindex ac80fc6..c528dfb 100644\n--- a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c\n+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c\n@@ -41,6 +41,7 @@\n \n #include \"pipeline_flow_classification_be.h\"\n #include \"pipeline_actions_common.h\"\n+#include \"parser.h\"\n #include \"hash_func.h\"\n \n struct pipeline_flow_classification {\n@@ -53,7 +54,7 @@ struct pipeline_flow_classification {\n \n \tuint32_t key_offset;\n \tuint32_t hash_offset;\n-\tuint8_t *key_mask;\n+\tuint8_t key_mask[PIPELINE_FC_FLOW_KEY_MAX_SIZE];\n \tuint32_t flow_id_offset;\n \n } __rte_cache_aligned;\n@@ -219,7 +220,7 @@ pipeline_fc_parse_args(struct pipeline_flow_classification *p,\n \tuint32_t flow_id_offset_present = 0;\n \n \tuint32_t i;\n-\tchar *key_mask_str = NULL;\n+\tchar key_mask_str[PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2];\n \n \tp->hash_offset = 0;\n \n@@ -232,110 +233,157 @@ pipeline_fc_parse_args(struct pipeline_flow_classification *p,\n \n \t\t/* n_flows */\n \t\tif (strcmp(arg_name, \"n_flows\") == 0) {\n-\t\t\tif (n_flows_present)\n-\t\t\t\tgoto error_parse;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tn_flows_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tn_flows_present = 1;\n \n-\t\t\tp->n_flows = atoi(arg_value);\n-\t\t\tif (p->n_flows == 0)\n-\t\t\t\tgoto error_parse;\n+\t\t\tstatus = parser_read_uint32(&p->n_flows,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&\n+\t\t\t\t(p->n_flows != 0)), params->name,\n+\t\t\t\targ_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* key_offset */\n \t\tif (strcmp(arg_name, \"key_offset\") == 0) {\n-\t\t\tif (key_offset_present)\n-\t\t\t\tgoto error_parse;\n+\t\t\tint status;\n \n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tkey_offset_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tkey_offset_present = 1;\n \n-\t\t\tp->key_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->key_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* key_size */\n \t\tif (strcmp(arg_name, \"key_size\") == 0) {\n-\t\t\tif (key_size_present)\n-\t\t\t\tgoto error_parse;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tkey_size_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tkey_size_present = 1;\n \n-\t\t\tp->key_size = atoi(arg_value);\n-\t\t\tif ((p->key_size == 0) ||\n-\t\t\t\t(p->key_size > PIPELINE_FC_FLOW_KEY_MAX_SIZE) ||\n-\t\t\t\t(p->key_size % 8))\n-\t\t\t\tgoto error_parse;\n+\t\t\tstatus = parser_read_uint32(&p->key_size,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&\n+\t\t\t\t(p->key_size != 0) &&\n+\t\t\t\t(p->key_size % 8 == 0)),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) &&\n+\t\t\t\t(p->key_size <=\n+\t\t\t\tPIPELINE_FC_FLOW_KEY_MAX_SIZE)),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* key_mask */\n \t\tif (strcmp(arg_name, \"key_mask\") == 0) {\n-\t\t\tif (key_mask_present)\n-\t\t\t\tgoto error_parse;\n-\n-\t\t\tkey_mask_str = strdup(arg_value);\n-\t\t\tif (key_mask_str == NULL)\n-\t\t\t\tgoto error_parse;\n+\t\t\tint mask_str_len = strlen(arg_value);\n \n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tkey_mask_present == 0,\n+\t\t\t\tparams->name, arg_name);\n \t\t\tkey_mask_present = 1;\n \n+\t\t\tPIPELINE_ARG_CHECK((mask_str_len <\n+\t\t\t\t(PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2)),\n+\t\t\t\t\"Parse error in section \\\"%s\\\": entry \"\n+\t\t\t\t\"\\\"%s\\\" is too long\", params->name,\n+\t\t\t\targ_name);\n+\n+\t\t\tsnprintf(key_mask_str, mask_str_len, \"%s\",\n+\t\t\t\targ_value);\n+\n \t\t\tcontinue;\n \t\t}\n \n \t\t/* hash_offset */\n \t\tif (strcmp(arg_name, \"hash_offset\") == 0) {\n-\t\t\tif (hash_offset_present)\n-\t\t\t\tgoto error_parse;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\thash_offset_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\thash_offset_present = 1;\n \n-\t\t\tp->hash_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->hash_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* flow_id_offset */\n \t\tif (strcmp(arg_name, \"flowid_offset\") == 0) {\n-\t\t\tif (flow_id_offset_present)\n-\t\t\t\tgoto error_parse;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tflow_id_offset_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tflow_id_offset_present = 1;\n \n+\t\t\tstatus = parser_read_uint32(&p->flow_id_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\n \t\t\tp->flow_id = 1;\n-\t\t\tp->flow_id_offset = atoi(arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* Unknown argument */\n-\t\tgoto error_parse;\n+\t\tPIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name);\n \t}\n \n \t/* Check that mandatory arguments are present */\n-\tif ((n_flows_present == 0) ||\n-\t\t(key_offset_present == 0) ||\n-\t\t(key_size_present == 0))\n-\t\tgoto error_parse;\n+\tPIPELINE_PARSE_ERR_MANDATORY((n_flows_present), params->name,\n+\t\t\"n_flows\");\n+\tPIPELINE_PARSE_ERR_MANDATORY((key_offset_present), params->name,\n+\t\t\"key_offset\");\n+\tPIPELINE_PARSE_ERR_MANDATORY((key_size_present), params->name,\n+\t\t\"key_size\");\n \n \tif (key_mask_present) {\n-\t\tp->key_mask = rte_malloc(NULL, p->key_size, 0);\n-\t\tif (p->key_mask == NULL)\n-\t\t\tgoto error_parse;\n+\t\tuint32_t key_size = p->key_size;\n+\t\tint status;\n \n-\t\tif (parse_hex_string(key_mask_str, p->key_mask, &p->key_size)\n-\t\t\t!= 0) {\n-\t\t\tgoto error_parse;\n-\t\t}\n+\t\tPIPELINE_ARG_CHECK((strlen(key_mask_str) ==\n+\t\t\t(key_size * 2)), \"Parse error in section \"\n+\t\t\t\"\\\"%s\\\": key_mask should have exactly %u hex \"\n+\t\t\t\"digits\", params->name, (key_size * 2));\n \n-\t\tfree(key_mask_str);\n+\t\tstatus = parse_hex_string(key_mask_str, p->key_mask,\n+\t\t\t&p->key_size);\n+\n+\t\tPIPELINE_PARSE_ERR_INV_VAL(((status == 0) &&\n+\t\t\t(key_size == p->key_size)), params->name,\n+\t\t\t\"key_mask\", key_mask_str);\n \t}\n \n \treturn 0;\n-\n-error_parse:\n-\tfree(key_mask_str);\n-\tfree(p->key_mask);\n-\treturn -1;\n }\n \n static void *pipeline_fc_init(struct pipeline_params *params,\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c\nindex a898f7d..630de3b 100644\n--- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c\n+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c\n@@ -42,6 +42,7 @@\n \n #include \"pipeline_passthrough_be.h\"\n #include \"pipeline_actions_common.h\"\n+#include \"parser.h\"\n #include \"hash_func.h\"\n \n struct pipeline_passthrough {\n@@ -238,6 +239,7 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,\n \tuint32_t dma_size_present = 0;\n \tuint32_t dma_hash_offset_present = 0;\n \tuint32_t i;\n+\tchar dma_mask_str[PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2];\n \n \t/* default values */\n \tp->dma_enabled = 0;\n@@ -250,11 +252,20 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,\n \n \t\t/* dma_dst_offset */\n \t\tif (strcmp(arg_name, \"dma_dst_offset\") == 0) {\n-\t\t\tif (dma_dst_offset_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tdma_dst_offset_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tdma_dst_offset_present = 1;\n \n-\t\t\tp->dma_dst_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->dma_dst_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\n \t\t\tp->dma_enabled = 1;\n \n \t\t\tcontinue;\n@@ -262,11 +273,20 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,\n \n \t\t/* dma_src_offset */\n \t\tif (strcmp(arg_name, \"dma_src_offset\") == 0) {\n-\t\t\tif (dma_src_offset_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tdma_src_offset_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tdma_src_offset_present = 1;\n \n-\t\t\tp->dma_src_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->dma_src_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\n \t\t\tp->dma_enabled = 1;\n \n \t\t\tcontinue;\n@@ -274,15 +294,23 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,\n \n \t\t/* dma_size */\n \t\tif (strcmp(arg_name, \"dma_size\") == 0) {\n-\t\t\tif (dma_size_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tdma_size_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tdma_size_present = 1;\n \n-\t\t\tp->dma_size = atoi(arg_value);\n-\t\t\tif ((p->dma_size == 0) ||\n-\t\t\t\t(p->dma_size > PIPELINE_PASSTHROUGH_DMA_SIZE_MAX) ||\n-\t\t\t\t((p->dma_size % 8) != 0))\n-\t\t\t\treturn -1;\n+\t\t\tstatus = parser_read_uint32(&p->dma_size,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&\n+\t\t\t\t(p->dma_size != 0) &&\n+\t\t\t\t((p->dma_size % 8) == 0)),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) &&\n+\t\t\t\t(p->dma_size <=\n+\t\t\t\tPIPELINE_PASSTHROUGH_DMA_SIZE_MAX)),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tp->dma_enabled = 1;\n \n@@ -291,34 +319,22 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,\n \n \t\t/* dma_src_mask */\n \t\tif (strcmp(arg_name, \"dma_src_mask\") == 0) {\n-\t\t\tuint32_t dma_size;\n-\t\t\tint status;\n+\t\t\tint mask_str_len = strlen(arg_value);\n \n-\t\t\tif (dma_src_mask_present ||\n-\t\t\t\t(dma_size_present == 0))\n-\t\t\t\treturn -1;\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tdma_src_mask_present == 0,\n+\t\t\t\tparams->name, arg_name);\n \t\t\tdma_src_mask_present = 1;\n \n-\t\t\tdma_size = p->dma_size;\n-\t\t\tstatus = parse_hex_string(arg_value,\n-\t\t\t\tp->dma_src_mask,\n-\t\t\t\t&dma_size);\n-\t\t\tif (status ||\n-\t\t\t\t(dma_size != p->dma_size))\n-\t\t\t\treturn -1;\n+\t\t\tPIPELINE_ARG_CHECK((mask_str_len <\n+\t\t\t\t(PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2)),\n+\t\t\t\t\"Parse error in section \\\"%s\\\": entry \"\n+\t\t\t\t\"\\\"%s\\\" too long\", params->name,\n+\t\t\t\targ_name);\n \n-\t\t\tp->dma_enabled = 1;\n+\t\t\tsnprintf(dma_mask_str, mask_str_len + 1,\n+\t\t\t\t\"%s\", arg_value);\n \n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* dma_dst_offset */\n-\t\tif (strcmp(arg_name, \"dma_dst_offset\") == 0) {\n-\t\t\tif (dma_dst_offset_present)\n-\t\t\t\treturn -1;\n-\t\t\tdma_dst_offset_present = 1;\n-\n-\t\t\tp->dma_dst_offset = atoi(arg_value);\n \t\t\tp->dma_enabled = 1;\n \n \t\t\tcontinue;\n@@ -326,11 +342,20 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,\n \n \t\t/* dma_hash_offset */\n \t\tif (strcmp(arg_name, \"dma_hash_offset\") == 0) {\n-\t\t\tif (dma_hash_offset_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tdma_hash_offset_present == 0,\n+\t\t\t\tparams->name, arg_name);\n \t\t\tdma_hash_offset_present = 1;\n \n-\t\t\tp->dma_hash_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->dma_hash_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\n \t\t\tp->dma_hash_enabled = 1;\n \t\t\tp->dma_enabled = 1;\n \n@@ -338,16 +363,39 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,\n \t\t}\n \n \t\t/* any other */\n-\t\treturn -1;\n+\t\tPIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name);\n \t}\n \n \t/* Check correlations between arguments */\n-\tif ((dma_dst_offset_present != p->dma_enabled) ||\n-\t\t(dma_src_offset_present != p->dma_enabled) ||\n-\t\t(dma_size_present != p->dma_enabled) ||\n-\t\t(dma_hash_offset_present != p->dma_hash_enabled) ||\n-\t\t(p->dma_hash_enabled > p->dma_enabled))\n-\t\treturn -1;\n+\tPIPELINE_ARG_CHECK((dma_dst_offset_present == p->dma_enabled),\n+\t\t\"Parse error in section \\\"%s\\\": missing entry \"\n+\t\t\"\\\"dma_dst_offset\\\"\", params->name);\n+\tPIPELINE_ARG_CHECK((dma_src_offset_present == p->dma_enabled),\n+\t\t\"Parse error in section \\\"%s\\\": missing entry \"\n+\t\t\"\\\"dma_src_offset\\\"\", params->name);\n+\tPIPELINE_ARG_CHECK((dma_size_present == p->dma_enabled),\n+\t\t\"Parse error in section \\\"%s\\\": missing entry \"\n+\t\t\"\\\"dma_size\\\"\", params->name);\n+\tPIPELINE_ARG_CHECK((dma_hash_offset_present == p->dma_enabled),\n+\t\t\"Parse error in section \\\"%s\\\": missing entry \"\n+\t\t\"\\\"dma_hash_offset\\\"\", params->name);\n+\n+\tif (dma_src_mask_present) {\n+\t\tuint32_t dma_size = p->dma_size;\n+\t\tint status;\n+\n+\t\tPIPELINE_ARG_CHECK((strlen(dma_mask_str) ==\n+\t\t\t(dma_size * 2)), \"Parse error in section \"\n+\t\t\t\"\\\"%s\\\": dma_src_mask should have exactly %u hex \"\n+\t\t\t\"digits\", params->name, (dma_size * 2));\n+\n+\t\tstatus = parse_hex_string(dma_mask_str, p->dma_src_mask,\n+\t\t\t&p->dma_size);\n+\n+\t\tPIPELINE_PARSE_ERR_INV_VAL(((status == 0) &&\n+\t\t\t(dma_size == p->dma_size)), params->name,\n+\t\t\t\"dma_src_mask\", dma_mask_str);\n+\t}\n \n \treturn 0;\n }\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.c b/examples/ip_pipeline/pipeline/pipeline_routing_be.c\nindex 9baabd0..4fb6b59 100644\n--- a/examples/ip_pipeline/pipeline/pipeline_routing_be.c\n+++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.c\n@@ -47,6 +47,7 @@\n \n #include \"pipeline_routing_be.h\"\n #include \"pipeline_actions_common.h\"\n+#include \"parser.h\"\n #include \"hash_func.h\"\n \n #define MPLS_LABEL(label, exp, s, ttl)\t\t\t\t\t\\\n@@ -940,21 +941,28 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p,\n \n \t\t/* n_routes */\n \t\tif (strcmp(arg_name, \"n_routes\") == 0) {\n-\t\t\tif (n_routes_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tn_routes_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tn_routes_present = 1;\n \n-\t\t\tp->n_routes = atoi(arg_value);\n-\t\t\tif (p->n_routes == 0)\n-\t\t\t\treturn -1;\n+\t\t\tstatus = parser_read_uint32(&p->n_routes,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&\n+\t\t\t\t(p->n_routes != 0)), params->name,\n+\t\t\t\targ_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* encap */\n \t\tif (strcmp(arg_name, \"encap\") == 0) {\n-\t\t\tif (encap_present)\n-\t\t\t\treturn -1;\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(encap_present == 0,\n+\t\t\t\tparams->name, arg_name);\n \t\t\tencap_present = 1;\n \n \t\t\t/* ethernet */\n@@ -976,140 +984,204 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p,\n \t\t\t}\n \n \t\t\t/* any other */\n-\t\t\treturn -1;\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(0, params->name,\n+\t\t\t\targ_name, arg_value);\n \t\t}\n \n \t\t/* qinq_sched */\n \t\tif (strcmp(arg_name, \"qinq_sched\") == 0) {\n-\t\t\tif (qinq_sched_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n \n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tqinq_sched_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tqinq_sched_present = 1;\n \n-\t\t\tif (strcmp(arg_value, \"no\") == 0)\n-\t\t\t\tp->qinq_sched = 0;\n-\t\t\telse if (strcmp(arg_value, \"yes\") == 0)\n-\t\t\t\tp->qinq_sched = 1;\n-\t\t\telse if (strcmp(arg_value, \"test\") == 0)\n-\t\t\t\tp->qinq_sched = 2;\n-\t\t\telse\n-\t\t\t\treturn -1;\n+\t\t\tstatus = parser_read_arg_bool(arg_value);\n+\t\t\tif (status == -EINVAL) {\n+\t\t\t\tif (strcmp(arg_value, \"test\") == 0) {\n+\t\t\t\t\tp->qinq_sched = 2;\n+\t\t\t\t\tcontinue;\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tp->qinq_sched = status;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \n-\t\t\tcontinue;\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(0, params->name,\n+\t\t\t\targ_name, arg_value);\n \t\t}\n \n \t\t/* mpls_color_mark */\n \t\tif (strcmp(arg_name, \"mpls_color_mark\") == 0) {\n-\t\t\tif (mpls_color_mark_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n \n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tmpls_color_mark_present == 0,\n+\t\t\t\tparams->name, arg_name);\n \t\t\tmpls_color_mark_present = 1;\n \n-\t\t\tif (strcmp(arg_value, \"no\") == 0)\n-\t\t\t\tp->mpls_color_mark = 0;\n-\t\t\telse if (strcmp(arg_value, \"yes\") == 0)\n-\t\t\t\tp->mpls_color_mark = 1;\n-\t\t\telse\n-\t\t\t\treturn -1;\n \n-\t\t\tcontinue;\n+\t\t\tstatus = parser_read_arg_bool(arg_value);\n+\t\t\tif (status >= 0) {\n+\t\t\t\tp->mpls_color_mark = status;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(0, params->name,\n+\t\t\t\targ_name, arg_value);\n \t\t}\n \n \t\t/* n_arp_entries */\n \t\tif (strcmp(arg_name, \"n_arp_entries\") == 0) {\n-\t\t\tif (n_arp_entries_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tn_arp_entries_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tn_arp_entries_present = 1;\n \n-\t\t\tp->n_arp_entries = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->n_arp_entries,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* ip_hdr_offset */\n \t\tif (strcmp(arg_name, \"ip_hdr_offset\") == 0) {\n-\t\t\tif (ip_hdr_offset_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tip_hdr_offset_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tip_hdr_offset_present = 1;\n \n-\t\t\tp->ip_hdr_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->ip_hdr_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* arp_key_offset */\n \t\tif (strcmp(arg_name, \"arp_key_offset\") == 0) {\n-\t\t\tif (arp_key_offset_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tarp_key_offset_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tarp_key_offset_present = 1;\n \n-\t\t\tp->arp_key_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->arp_key_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* color_offset */\n \t\tif (strcmp(arg_name, \"color_offset\") == 0) {\n-\t\t\tif (color_offset_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tcolor_offset_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tcolor_offset_present = 1;\n \n-\t\t\tp->color_offset = atoi(arg_value);\n+\t\t\tstatus = parser_read_uint32(&p->color_offset,\n+\t\t\t\targ_value);\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),\n+\t\t\t\tparams->name, arg_name, arg_value);\n+\t\t\tPIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),\n+\t\t\t\tparams->name, arg_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* debug */\n \t\tif (strcmp(arg_name, \"dbg_ah_disable\") == 0) {\n-\t\t\tif (dbg_ah_disable_present)\n-\t\t\t\treturn -1;\n+\t\t\tint status;\n+\n+\t\t\tPIPELINE_PARSE_ERR_DUPLICATE(\n+\t\t\t\tdbg_ah_disable_present == 0, params->name,\n+\t\t\t\targ_name);\n \t\t\tdbg_ah_disable_present = 1;\n \n-\t\t\tif (strcmp(arg_value, \"no\") == 0)\n-\t\t\t\tp->dbg_ah_disable = 0;\n-\t\t\telse if (strcmp(arg_value, \"yes\") == 0)\n-\t\t\t\tp->dbg_ah_disable = 1;\n-\t\t\telse\n-\t\t\t\treturn -1;\n+\t\t\tstatus = parser_read_arg_bool(arg_value);\n+\t\t\tif (status >= 0) {\n+\t\t\t\tp->dbg_ah_disable = status;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tPIPELINE_PARSE_ERR_INV_VAL(0, params->name,\n+\t\t\t\targ_name, arg_value);\n \n \t\t\tcontinue;\n \t\t}\n \n \t\t/* any other */\n-\t\treturn -1;\n+\t\tPIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name);\n \t}\n \n \t/* Check that mandatory arguments are present */\n-\tif (ip_hdr_offset_present == 0)\n-\t\treturn -1;\n+\tPIPELINE_PARSE_ERR_MANDATORY(ip_hdr_offset_present, params->name,\n+\t\t\"ip_hdr_offset\");\n \n \t/* Check relations between arguments */\n \tswitch (p->encap) {\n \tcase PIPELINE_ROUTING_ENCAP_ETHERNET:\n-\t\tif (p->qinq_sched ||\n-\t\t\tp->mpls_color_mark ||\n-\t\t\tcolor_offset_present)\n-\t\t\treturn -1;\n+\t\tPIPELINE_ARG_CHECK((!p->qinq_sched), \"Parse error in \"\n+\t\t\t\"section \\\"%s\\\": encap = ethernet, therefore \"\n+\t\t\t\"qinq_sched = yes/test is not allowed\",\n+\t\t\tparams->name);\n+\t\tPIPELINE_ARG_CHECK((!p->mpls_color_mark), \"Parse error \"\n+\t\t\t\"in section \\\"%s\\\": encap = ethernet, therefore \"\n+\t\t\t\"mpls_color_mark = yes is not allowed\",\n+\t\t\tparams->name);\n+\t\tPIPELINE_ARG_CHECK((!color_offset_present), \"Parse error \"\n+\t\t\t\"in section \\\"%s\\\": encap = ethernet, therefore \"\n+\t\t\t\"color_offset is not allowed\",\n+\t\t\tparams->name);\n \t\tbreak;\n \n \tcase PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ:\n-\t\tif (p->mpls_color_mark ||\n-\t\t\tcolor_offset_present)\n-\t\t\treturn -1;\n+\t\tPIPELINE_ARG_CHECK((!p->mpls_color_mark), \"Parse error \"\n+\t\t\t\"in section \\\"%s\\\": encap = ethernet_qinq, \"\n+\t\t\t\"therefore mpls_color_mark = yes is not allowed\",\n+\t\t\tparams->name);\n+\t\tPIPELINE_ARG_CHECK((!color_offset_present), \"Parse error \"\n+\t\t\t\"in section \\\"%s\\\": encap = ethernet_qinq, \"\n+\t\t\t\"therefore color_offset is not allowed\",\n+\t\t\tparams->name);\n \t\tbreak;\n \n \tcase PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS:\n-\t\tif (p->qinq_sched)\n-\t\t\treturn -1;\n+\t\tPIPELINE_ARG_CHECK((!p->qinq_sched), \"Parse error in \"\n+\t\t\t\"section \\\"%s\\\": encap = ethernet_mpls, therefore \"\n+\t\t\t\"qinq_sched  = yes/test is not allowed\",\n+\t\t\tparams->name);\n \t\tbreak;\n-\n-\tdefault:\n-\t\treturn -1;\n \t}\n \n-\tif ((p->n_arp_entries && (arp_key_offset_present == 0)) ||\n-\t\t((p->n_arp_entries == 0) && arp_key_offset_present))\n-\t\treturn -1;\n+\tPIPELINE_ARG_CHECK((!(p->n_arp_entries &&\n+\t\t(!arp_key_offset_present))), \"Parse error in section \"\n+\t\t\t\"\\\"%s\\\": n_arp_entries is set while \"\n+\t\t\t\"arp_key_offset is not set\", params->name);\n+\n+\tPIPELINE_ARG_CHECK((!((p->n_arp_entries == 0) &&\n+\t\tarp_key_offset_present)), \"Parse error in section \"\n+\t\t\t\"\\\"%s\\\": arp_key_offset present while \"\n+\t\t\t\"n_arp_entries is not set\", params->name);\n \n \treturn 0;\n }\ndiff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h\nindex 0ba00f6..d820435 100644\n--- a/examples/ip_pipeline/pipeline_be.h\n+++ b/examples/ip_pipeline/pipeline_be.h\n@@ -271,8 +271,33 @@ struct pipeline_be_ops {\n \tpipeline_be_op_track f_track;\n };\n \n-/* Parse hex string to uint8_t array */\n-int\n-parse_hex_string(char *src, uint8_t *dst, uint32_t *size);\n+/* Pipeline specific config parse error messages */\n+#define PIPELINE_ARG_CHECK(exp, fmt, ...)\t\t\t\t\\\n+do {\t\t\t\t\t\t\t\t\t\\\n+\tif (!(exp)) {\t\t\t\t\t\t\t\\\n+\t\tfprintf(stderr, fmt \"\\n\", ## __VA_ARGS__);\t\t\\\n+\t\treturn -1;\t\t\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\t\\\n+} while (0)\n+\n+#define PIPELINE_PARSE_ERR_INV_VAL(exp, section, entry, val)\t\t\\\n+PIPELINE_ARG_CHECK(exp, \"Parse error in section \\\"%s\\\": entry \\\"%s\\\" \"\t\\\n+\t\"has invalid value (\\\"%s\\\")\", section, entry, val)\n+\n+#define PIPELINE_PARSE_ERR_OUT_RNG(exp, section, entry, val)\t\t\\\n+PIPELINE_ARG_CHECK(exp, \"Parse error in section \\\"%s\\\": entry \\\"%s\\\" \"\t\\\n+\t\"value is out of range (\\\"%s\\\")\", section, entry, val)\n+\n+#define PIPELINE_PARSE_ERR_DUPLICATE(exp, section, entry)\t\t\\\n+PIPELINE_ARG_CHECK(exp, \"Parse error in section \\\"%s\\\": duplicated \"\t\\\n+\t\"entry \\\"%s\\\"\", section, entry)\n+\n+#define PIPELINE_PARSE_ERR_INV_ENT(exp, section, entry)\t\t\t\\\n+PIPELINE_ARG_CHECK(exp, \"Parse error in section \\\"%s\\\": invalid entry \"\t\\\n+\t\"\\\"%s\\\"\", section, entry)\n+\n+#define PIPELINE_PARSE_ERR_MANDATORY(exp, section, entry)\t\t\\\n+PIPELINE_ARG_CHECK(exp, \"Parse error in section \\\"%s\\\": mandatory \"\t\\\n+\t\"entry \\\"%s\\\" is missing\", section, entry)\n \n #endif\n",
    "prefixes": [
        "dpdk-dev",
        "v2"
    ]
}