From patchwork Wed Feb 17 11:14:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fan Zhang X-Patchwork-Id: 10569 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 01D01C166; Wed, 17 Feb 2016 12:14:16 +0100 (CET) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id D6D5EC360 for ; Wed, 17 Feb 2016 12:14:13 +0100 (CET) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga103.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" Received: from sie-lab-212-033.ir.intel.com (HELO silpixa00383881.ir.intel.com) ([10.237.212.33]) by FMSMGA003.fm.intel.com with ESMTP; 17 Feb 2016 03:14:12 -0800 From: Fan Zhang 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch updates the pipelne configuration file parser, cleans up nesting if/else conditions, and add clearer error message display. Signed-off-by: Fan Zhang Acked-by: Cristian Dumitrescu --- examples/ip_pipeline/config_parse.c | 1008 ++++++++++++-------- examples/ip_pipeline/parser.h | 50 + .../ip_pipeline/pipeline/pipeline_firewall_be.c | 25 +- .../pipeline/pipeline_flow_actions_be.c | 91 +- .../pipeline/pipeline_flow_classification_be.c | 142 ++- .../ip_pipeline/pipeline/pipeline_passthrough_be.c | 140 ++- .../ip_pipeline/pipeline/pipeline_routing_be.c | 204 ++-- examples/ip_pipeline/pipeline_be.h | 31 +- 8 files changed, 1112 insertions(+), 579 deletions(-) create mode 100644 examples/ip_pipeline/parser.h diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c index 1bedbe4..5f72af9 100644 --- a/examples/ip_pipeline/config_parse.c +++ b/examples/ip_pipeline/config_parse.c @@ -47,6 +47,7 @@ #include #include "app.h" +#include "parser.h" /** * Default config values @@ -229,31 +230,19 @@ app_print_usage(char *prgname) _p; \ }) -#define PARSER_IMPLICIT_PARAM_ADD_CHECK(result, section_name) \ -do { \ - APP_CHECK((result != -EINVAL), \ - "CFG: [%s] name too long", section_name); \ - APP_CHECK(result != -ENOMEM, \ - "CFG: [%s] too much sections", section_name); \ - APP_CHECK(result >= 0, \ - "CFG: [%s] Unknown error while adding '%s'", \ - section_name, section_name); \ -} while (0) - #define PARSER_PARAM_ADD_CHECK(result, params_array, section_name) \ do { \ APP_CHECK((result != -EINVAL), \ - "CFG: [%s] name too long", section_name); \ + "Parse error: no free memory"); \ APP_CHECK((result != -ENOMEM), \ - "CFG: [%s] too much sections", section_name); \ + "Parse error: too many \"%s\" sections", section_name); \ APP_CHECK(((result >= 0) && (params_array)[result].parsed == 0),\ - "CFG: [%s] duplicate section", section_name); \ + "Parse error: duplicate \"%s\" section", section_name); \ APP_CHECK((result >= 0), \ - "CFG: [%s] Unknown error while adding '%s'", \ - section_name, section_name); \ + "Parse error in section \"%s\"", section_name); \ } while (0) -static int +int parser_read_arg_bool(const char *p) { p = skip_white_spaces(p); @@ -318,7 +307,7 @@ APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"\n",\ APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"\n",\ section, entry) -static int +int parser_read_uint64(uint64_t *value, const char *p) { char *next; @@ -336,13 +325,13 @@ parser_read_uint64(uint64_t *value, const char *p) switch (*p) { case 'T': val *= 1024ULL; - /* fall trought */ + /* fall through */ case 'G': val *= 1024ULL; - /* fall trought */ + /* fall through */ case 'M': val *= 1024ULL; - /* fall trought */ + /* fall through */ case 'k': case 'K': val *= 1024ULL; @@ -358,7 +347,7 @@ parser_read_uint64(uint64_t *value, const char *p) return 0; } -static int +int parser_read_uint32(uint32_t *value, const char *p) { uint64_t val = 0; @@ -366,7 +355,8 @@ parser_read_uint32(uint32_t *value, const char *p) if (ret < 0) return ret; - else if (val > UINT32_MAX) + + if (val > UINT32_MAX) return -ERANGE; *value = val; @@ -936,8 +926,25 @@ parse_pipeline_pktq_in(struct app_params *app, while (*next != '\0') { enum app_pktq_in_type type; int id; + char *end_space; + char *end_tab; + + next = skip_white_spaces(next); + if (!next) + break; + + end_space = strchr(next, ' '); + end_tab = strchr(next, ' '); + + if (end_space && (!end_tab)) + end = end_space; + else if ((!end_space) && end_tab) + end = end_tab; + else if (end_space && end_tab) + end = RTE_MIN(end_space, end_tab); + else + end = NULL; - end = strchr(next, ' '); if (!end) name_len = strlen(next); else @@ -991,8 +998,25 @@ parse_pipeline_pktq_out(struct app_params *app, while (*next != '\0') { enum app_pktq_out_type type; int id; + char *end_space; + char *end_tab; + + next = skip_white_spaces(next); + if (!next) + break; + + end_space = strchr(next, ' '); + end_tab = strchr(next, ' '); + + if (end_space && (!end_tab)) + end = end_space; + else if ((!end_space) && end_tab) + end = end_tab; + else if (end_space && end_tab) + end = RTE_MIN(end_space, end_tab); + else + end = NULL; - end = strchr(next, ' '); if (!end) name_len = strlen(next); else @@ -1006,7 +1030,6 @@ parse_pipeline_pktq_out(struct app_params *app, next += name_len; if (*next != '\0') next++; - if (validate_name(name, "TXQ", 2) == 0) { type = APP_PKTQ_OUT_HWQ; id = APP_PARAM_ADD(app->hwq_out_params, name); @@ -1045,7 +1068,25 @@ parse_pipeline_msgq_in(struct app_params *app, ssize_t idx; while (*next != '\0') { - end = strchr(next, ' '); + char *end_space; + char *end_tab; + + next = skip_white_spaces(next); + if (!next) + break; + + end_space = strchr(next, ' '); + end_tab = strchr(next, ' '); + + if (end_space && (!end_tab)) + end = end_space; + else if ((!end_space) && end_tab) + end = end_tab; + else if (end_space && end_tab) + end = RTE_MIN(end_space, end_tab); + else + end = NULL; + if (!end) name_len = strlen(next); else @@ -1086,7 +1127,25 @@ parse_pipeline_msgq_out(struct app_params *app, ssize_t idx; while (*next != '\0') { - end = strchr(next, ' '); + char *end_space; + char *end_tab; + + next = skip_white_spaces(next); + if (!next) + break; + + end_space = strchr(next, ' '); + end_tab = strchr(next, ' '); + + if (end_space && (!end_tab)) + end = end_space; + else if ((!end_space) && end_tab) + end = end_tab; + else if (end_space && end_tab) + end = RTE_MIN(end_space, end_tab); + else + end = NULL; + if (!end) name_len = strlen(next); else @@ -1115,7 +1174,6 @@ parse_pipeline_msgq_out(struct app_params *app, return 0; } - static void parse_pipeline(struct app_params *app, const char *section_name, @@ -1125,7 +1183,7 @@ parse_pipeline(struct app_params *app, struct app_pipeline_params *param; struct rte_cfgfile_entry *entries; ssize_t param_idx; - int n_entries, ret, i; + int n_entries, i; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); @@ -1139,69 +1197,103 @@ parse_pipeline(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->pipeline_params, section_name); param = &app->pipeline_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; if (strcmp(ent->name, "type") == 0) { - ret = snprintf(param->type, - RTE_DIM(param->type), - "%s", + int w_size = snprintf(param->type, RTE_DIM(param->type), + "%s", ent->value); + + PARSE_ERROR(((w_size > 0) && + (w_size < (int)RTE_DIM(param->type))), + section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "core") == 0) { + int status = parse_pipeline_core( + ¶m->socket_id, ¶m->core_id, + ¶m->hyper_th_id, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "pktq_in") == 0) { + int status = parse_pipeline_pktq_in(app, param, ent->value); - if ((ret > 0) && (ret < (int)RTE_DIM(param->type))) - ret = 0; - else - ret = -EINVAL; - } else if (strcmp(ent->name, "core") == 0) - ret = parse_pipeline_core(¶m->socket_id, - ¶m->core_id, - ¶m->hyper_th_id, + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "pktq_out") == 0) { + int status = parse_pipeline_pktq_out(app, param, ent->value); - else if (strcmp(ent->name, "pktq_in") == 0) - ret = parse_pipeline_pktq_in(app, param, ent->value); - else if (strcmp(ent->name, "pktq_out") == 0) - ret = parse_pipeline_pktq_out(app, param, ent->value); - else if (strcmp(ent->name, "msgq_in") == 0) - ret = parse_pipeline_msgq_in(app, param, ent->value); - else if (strcmp(ent->name, "msgq_out") == 0) - ret = parse_pipeline_msgq_out(app, param, ent->value); - else if (strcmp(ent->name, "timer_period") == 0) - ret = parser_read_uint32(¶m->timer_period, + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "msgq_in") == 0) { + int status = parse_pipeline_msgq_in(app, param, ent->value); - else { - APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS), - "CFG: [%s] out of memory", - section_name); - param->args_name[param->n_args] = strdup(ent->name); - param->args_value[param->n_args] = strdup(ent->value); + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } - APP_CHECK((param->args_name[param->n_args] != NULL) && - (param->args_value[param->n_args] != NULL), - "CFG: [%s] out of memory", - section_name); + if (strcmp(ent->name, "msgq_out") == 0) { + int status = parse_pipeline_msgq_out(app, param, + ent->value); - param->n_args++; - ret = 0; + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; } - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + if (strcmp(ent->name, "timer_period") == 0) { + int status = parser_read_uint32( + ¶m->timer_period, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* pipeline type specific items */ + APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS), + "Parse error in section \"%s\": too many " + "pipeline specified parameters", section_name); + + param->args_name[param->n_args] = strdup(ent->name); + param->args_value[param->n_args] = strdup(ent->value); + + APP_CHECK((param->args_name[param->n_args] != NULL) && + (param->args_value[param->n_args] != NULL), + "Parse error: no free memory"); + + param->n_args++; } + param->parsed = 1; + snprintf(name, sizeof(name), "MSGQ-REQ-%s", section_name); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name); + PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; param->msgq_in[param->n_msgq_in++] = param_idx; snprintf(name, sizeof(name), "MSGQ-RSP-%s", section_name); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name); + PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; param->msgq_out[param->n_msgq_out++] = param_idx; @@ -1210,7 +1302,7 @@ parse_pipeline(struct app_params *app, param->core_id, (param->hyper_th_id) ? "h" : ""); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name); + PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; snprintf(name, sizeof(name), "MSGQ-RSP-CORE-s%" PRIu32 "c%" PRIu32 "%s", @@ -1218,7 +1310,7 @@ parse_pipeline(struct app_params *app, param->core_id, (param->hyper_th_id) ? "h" : ""); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name); + PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; free(entries); @@ -1232,7 +1324,7 @@ parse_mempool(struct app_params *app, struct app_mempool_params *param; struct rte_cfgfile_entry *entries; ssize_t param_idx; - int n_entries, ret, i; + int n_entries, i; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); @@ -1246,36 +1338,52 @@ parse_mempool(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->mempool_params, section_name); param = &app->mempool_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; - if (strcmp(ent->name, "buffer_size") == 0) - ret = parser_read_uint32(¶m->buffer_size, - ent->value); - else if (strcmp(ent->name, "pool_size") == 0) - ret = parser_read_uint32(¶m->pool_size, - ent->value); - else if (strcmp(ent->name, "cache_size") == 0) - ret = parser_read_uint32(¶m->cache_size, - ent->value); - else if (strcmp(ent->name, "cpu") == 0) - ret = parser_read_uint32(¶m->cpu_socket_id, - ent->value); + if (strcmp(ent->name, "buffer_size") == 0) { + int status = parser_read_uint32( + ¶m->buffer_size, ent->value); - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "pool_size") == 0) { + int status = parser_read_uint32( + ¶m->pool_size, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "cache_size") == 0) { + int status = parser_read_uint32( + ¶m->cache_size, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "cpu") == 0) { + int status = parser_read_uint32( + ¶m->cpu_socket_id, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + param->parsed = 1; + free(entries); } @@ -1286,7 +1394,7 @@ parse_link(struct app_params *app, { struct app_link_params *param; struct rte_cfgfile_entry *entries; - int n_entries, ret, i; + int n_entries, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1301,48 +1409,79 @@ parse_link(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->link_params, section_name); param = &app->link_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; if (strcmp(ent->name, "promisc") == 0) { - ret = parser_read_arg_bool(ent->value); - if (ret >= 0) { - param->promisc = ret; - ret = 0; - } - } else if (strcmp(ent->name, "arp_q") == 0) - ret = parser_read_uint32(¶m->arp_q, - ent->value); - else if (strcmp(ent->name, "tcp_syn_q") == 0) - ret = parser_read_uint32(¶m->tcp_syn_local_q, - ent->value); - else if (strcmp(ent->name, "ip_local_q") == 0) - ret = parser_read_uint32(¶m->ip_local_q, - ent->value); - else if (strcmp(ent->name, "tcp_local_q") == 0) - ret = parser_read_uint32(¶m->tcp_local_q, - ent->value); - else if (strcmp(ent->name, "udp_local_q") == 0) - ret = parser_read_uint32(¶m->udp_local_q, - ent->value); - else if (strcmp(ent->name, "sctp_local_q") == 0) - ret = parser_read_uint32(¶m->sctp_local_q, + int status = parser_read_arg_bool(ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + param->promisc = status; + continue; + } + + if (strcmp(ent->name, "arp_q") == 0) { + int status = parser_read_uint32(¶m->arp_q, ent->value); - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "tcp_syn_q") == 0) { + int status = parser_read_uint32( + ¶m->tcp_syn_local_q, ent->value); + + PARSE_ERROR((status == 0), section_name, ent->name); + continue; + } + + if (strcmp(ent->name, "ip_local_q") == 0) { + int status = parser_read_uint32( + ¶m->ip_local_q, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + + if (strcmp(ent->name, "tcp_local_q") == 0) { + int status = parser_read_uint32( + ¶m->tcp_local_q, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "udp_local_q") == 0) { + int status = parser_read_uint32( + ¶m->udp_local_q, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "sctp_local_q") == 0) { + int status = parser_read_uint32( + ¶m->sctp_local_q, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + param->parsed = 1; + free(entries); } @@ -1353,7 +1492,7 @@ parse_rxq(struct app_params *app, { struct app_pktq_hwq_in_params *param; struct rte_cfgfile_entry *entries; - int n_entries, ret, i; + int n_entries, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1368,43 +1507,49 @@ parse_rxq(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_in_params, section_name); param = &app->hwq_in_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; if (strcmp(ent->name, "mempool") == 0) { - int status = validate_name(ent->value, "MEMPOOL", 1); + int status = validate_name(ent->value, + "MEMPOOL", 1); ssize_t idx; - APP_CHECK((status == 0), - "CFG: [%s] entry '%s': invalid mempool\n", - section_name, + PARSE_ERROR((status == 0), section_name, ent->name); - - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name); + idx = APP_PARAM_ADD(app->mempool_params, + ent->value); + PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, + section_name); param->mempool_id = idx; - ret = 0; - } else if (strcmp(ent->name, "size") == 0) - ret = parser_read_uint32(¶m->size, + continue; + } + + if (strcmp(ent->name, "size") == 0) { + int status = parser_read_uint32(¶m->size, ent->value); - else if (strcmp(ent->name, "burst") == 0) - ret = parser_read_uint32(¶m->burst, + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "burst") == 0) { + int status = parser_read_uint32(¶m->burst, ent->value); - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + param->parsed = 1; + free(entries); } @@ -1415,7 +1560,7 @@ parse_txq(struct app_params *app, { struct app_pktq_hwq_out_params *param; struct rte_cfgfile_entry *entries; - int n_entries, ret, i; + int n_entries, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1430,35 +1575,44 @@ parse_txq(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_out_params, section_name); param = &app->hwq_out_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; - if (strcmp(ent->name, "size") == 0) - ret = parser_read_uint32(¶m->size, ent->value); - else if (strcmp(ent->name, "burst") == 0) - ret = parser_read_uint32(¶m->burst, ent->value); - else if (strcmp(ent->name, "dropless") == 0) { - ret = parser_read_arg_bool(ent->value); - if (ret >= 0) { - param->dropless = ret; - ret = 0; - } + if (strcmp(ent->name, "size") == 0) { + int status = parser_read_uint32(¶m->size, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; } - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + if (strcmp(ent->name, "burst") == 0) { + int status = parser_read_uint32(¶m->burst, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "dropless") == 0) { + int status = parser_read_arg_bool(ent->value); + + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + param->dropless = status; + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + param->parsed = 1; + free(entries); } @@ -1469,8 +1623,12 @@ parse_swq(struct app_params *app, { struct app_pktq_swq_params *param; struct rte_cfgfile_entry *entries; - int n_entries, ret, i; - unsigned frag_entries = 0; + int n_entries, i; + uint32_t mtu_present = 0; + uint32_t metadata_size_present = 0; + uint32_t mempool_direct_present = 0; + uint32_t mempool_indirect_present = 0; + ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1485,117 +1643,188 @@ parse_swq(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->swq_params, section_name); param = &app->swq_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; - if (strcmp(ent->name, "size") == 0) - ret = parser_read_uint32(¶m->size, - ent->value); - else if (strcmp(ent->name, "burst_read") == 0) - ret = parser_read_uint32(¶m->burst_read, + if (strcmp(ent->name, "size") == 0) { + int status = parser_read_uint32(¶m->size, ent->value); - else if (strcmp(ent->name, "burst_write") == 0) - ret = parser_read_uint32(¶m->burst_write, - ent->value); - else if (strcmp(ent->name, "dropless") == 0) { - ret = parser_read_arg_bool(ent->value); - if (ret >= 0) { - param->dropless = ret; - ret = 0; - } - } else if (strcmp(ent->name, "n_retries") == 0) - ret = parser_read_uint64(¶m->n_retries, - ent->value); - else if (strcmp(ent->name, "cpu") == 0) - ret = parser_read_uint32(¶m->cpu_socket_id, - ent->value); - else if (strcmp(ent->name, "ipv4_frag") == 0) { - ret = parser_read_arg_bool(ent->value); - if (ret >= 0) { - param->ipv4_frag = ret; - if (param->mtu == 0) - param->mtu = 1500; - ret = 0; - } - } else if (strcmp(ent->name, "ipv6_frag") == 0) { - ret = parser_read_arg_bool(ent->value); - if (ret >= 0) { - param->ipv6_frag = ret; - if (param->mtu == 0) - param->mtu = 1320; - ret = 0; - } - } else if (strcmp(ent->name, "ipv4_ras") == 0) { - ret = parser_read_arg_bool(ent->value); - if (ret >= 0) { - param->ipv4_ras = ret; - ret = 0; - } - } else if (strcmp(ent->name, "ipv6_ras") == 0) { - ret = parser_read_arg_bool(ent->value); - if (ret >= 0) { - param->ipv6_ras = ret; - ret = 0; - } - } else if (strcmp(ent->name, "mtu") == 0) { - frag_entries = 1; - ret = parser_read_uint32(¶m->mtu, - ent->value); - } else if (strcmp(ent->name, "metadata_size") == 0) { - frag_entries = 1; - ret = parser_read_uint32(¶m->metadata_size, + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "burst_read") == 0) { + int status = parser_read_uint32(& + param->burst_read, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "burst_write") == 0) { + int status = parser_read_uint32( + ¶m->burst_write, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "dropless") == 0) { + int status = parser_read_arg_bool(ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + param->dropless = status; + continue; + } + + if (strcmp(ent->name, "n_retries") == 0) { + int status = parser_read_uint64(¶m->n_retries, ent->value); - } else if (strcmp(ent->name, "mempool_direct") == 0) { - int status = validate_name(ent->value, "MEMPOOL", 1); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "cpu") == 0) { + int status = parser_read_uint32( + ¶m->cpu_socket_id, ent->value); + + PARSE_ERROR((status == 0), section_name, ent->name); + continue; + } + + if (strcmp(ent->name, "ipv4_frag") == 0) { + int status = parser_read_arg_bool(ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + + param->ipv4_frag = status; + if (param->mtu == 0) + param->mtu = 1500; + + continue; + } + + if (strcmp(ent->name, "ipv6_frag") == 0) { + int status = parser_read_arg_bool(ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + param->ipv6_frag = status; + if (param->mtu == 0) + param->mtu = 1320; + continue; + } + + if (strcmp(ent->name, "ipv4_ras") == 0) { + int status = parser_read_arg_bool(ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + param->ipv4_ras = status; + continue; + } + + if (strcmp(ent->name, "ipv6_ras") == 0) { + int status = parser_read_arg_bool(ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + param->ipv6_ras = status; + continue; + } + + if (strcmp(ent->name, "mtu") == 0) { + int status = parser_read_uint32(¶m->mtu, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + mtu_present = 1; + continue; + } + + if (strcmp(ent->name, "metadata_size") == 0) { + int status = parser_read_uint32( + ¶m->metadata_size, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + metadata_size_present = 1; + continue; + } + + if (strcmp(ent->name, "mempool_direct") == 0) { + int status = validate_name(ent->value, + "MEMPOOL", 1); ssize_t idx; - APP_CHECK((status == 0), - "CFG: [%s] entry '%s': invalid mempool\n", - section_name, + PARSE_ERROR((status == 0), section_name, ent->name); - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name); + idx = APP_PARAM_ADD(app->mempool_params, + ent->value); + PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, + section_name); param->mempool_direct_id = idx; - frag_entries = 1; - ret = 0; - } else if (strcmp(ent->name, "mempool_indirect") == 0) { - int status = validate_name(ent->value, "MEMPOOL", 1); + mempool_direct_present = 1; + continue; + } + + if (strcmp(ent->name, "mempool_indirect") == 0) { + int status = validate_name(ent->value, + "MEMPOOL", 1); ssize_t idx; - APP_CHECK((status == 0), - "CFG: [%s] entry '%s': invalid mempool\n", - section_name, + PARSE_ERROR((status == 0), section_name, ent->name); - - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name); + idx = APP_PARAM_ADD(app->mempool_params, + ent->value); + PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, + section_name); param->mempool_indirect_id = idx; - frag_entries = 1; - ret = 0; - } - - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); - } + mempool_indirect_present = 1; + continue; + } - if (frag_entries == 1) { - APP_CHECK(((param->ipv4_frag == 1) || (param->ipv6_frag == 1)), - "CFG: [%s] ipv4/ipv6 frag is off : unsupported entries on this" - " configuration\n", - section_name); + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + APP_CHECK(((mtu_present) && + ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), + "Parse error in section \"%s\": IPv4/IPv6 fragmentation " + "is off, therefore entry \"mtu\" is not allowed", + section_name); + + APP_CHECK(((metadata_size_present) && + ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), + "Parse error in section \"%s\": IPv4/IPv6 fragmentation " + "is off, therefore entry \"metadata_size\" is " + "not allowed", section_name); + + APP_CHECK(((mempool_direct_present) && + ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), + "Parse error in section \"%s\": IPv4/IPv6 fragmentation " + "is off, therefore entry \"mempool_direct\" is " + "not allowed", section_name); + + APP_CHECK(((mempool_indirect_present) && + ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), + "Parse error in section \"%s\": IPv4/IPv6 fragmentation " + "is off, therefore entry \"mempool_indirect\" is " + "not allowed", section_name); + + param->parsed = 1; + free(entries); } @@ -1606,7 +1835,7 @@ parse_tm(struct app_params *app, { struct app_pktq_tm_params *param; struct rte_cfgfile_entry *entries; - int n_entries, ret, i; + int n_entries, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1621,41 +1850,40 @@ parse_tm(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->tm_params, section_name); param = &app->tm_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; if (strcmp(ent->name, "cfg") == 0) { param->file_name = strdup(ent->value); - if (param->file_name == NULL) - ret = -EINVAL; - else - ret = 0; - } else if (strcmp(ent->name, "burst_read") == 0) - ret = parser_read_uint32(¶m->burst_read, - ent->value); - else if (strcmp(ent->name, "burst_write") == 0) - ret = parser_read_uint32(¶m->burst_write, - ent->value); + PARSE_ERROR_MALLOC(param->file_name != NULL); + continue; + } + + if (strcmp(ent->name, "burst_read") == 0) { + int status = parser_read_uint32( + ¶m->burst_read, ent->value); - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret != -EBADF, - "CFG: [%s] entry '%s': TM cfg parse error '%s'\n", - section_name, - ent->name, - ent->value); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "burst_write") == 0) { + int status = parser_read_uint32( + ¶m->burst_write, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + param->parsed = 1; + free(entries); } @@ -1666,7 +1894,7 @@ parse_source(struct app_params *app, { struct app_pktq_source_params *param; struct rte_cfgfile_entry *entries; - int n_entries, ret, i; + int n_entries, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1681,39 +1909,40 @@ parse_source(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->source_params, section_name); param = &app->source_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; if (strcmp(ent->name, "mempool") == 0) { - int status = validate_name(ent->value, "MEMPOOL", 1); + int status = validate_name(ent->value, + "MEMPOOL", 1); ssize_t idx; - APP_CHECK((status == 0), - "CFG: [%s] entry '%s': invalid mempool\n", - section_name, - ent->name); - - idx = APP_PARAM_ADD(app->mempool_params, ent->value); - PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name); + PARSE_ERROR((status == 0), section_name, + ent->name); + idx = APP_PARAM_ADD(app->mempool_params, + ent->value); + PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, + section_name); param->mempool_id = idx; - ret = 0; - } else if (strcmp(ent->name, "burst") == 0) - ret = parser_read_uint32(¶m->burst, ent->value); - - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + continue; + } + + if (strcmp(ent->name, "burst") == 0) { + int status = parser_read_uint32(¶m->burst, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + param->parsed = 1; + free(entries); } @@ -1724,7 +1953,7 @@ parse_msgq_req_pipeline(struct app_params *app, { struct app_msgq_params *param; struct rte_cfgfile_entry *entries; - int n_entries, ret, i; + int n_entries, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1739,26 +1968,24 @@ parse_msgq_req_pipeline(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); param = &app->msgq_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; - if (strcmp(ent->name, "size") == 0) - ret = parser_read_uint32(¶m->size, ent->value); - - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + if (strcmp(ent->name, "size") == 0) { + int status = parser_read_uint32(¶m->size, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + param->parsed = 1; free(entries); } @@ -1769,7 +1996,7 @@ parse_msgq_rsp_pipeline(struct app_params *app, { struct app_msgq_params *param; struct rte_cfgfile_entry *entries; - int n_entries, ret, i; + int n_entries, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1784,26 +2011,25 @@ parse_msgq_rsp_pipeline(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); param = &app->msgq_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; - if (strcmp(ent->name, "size") == 0) - ret = parser_read_uint32(¶m->size, ent->value); - - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + if (strcmp(ent->name, "size") == 0) { + int status = parser_read_uint32(¶m->size, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + param->parsed = 1; + free(entries); } @@ -1814,7 +2040,7 @@ parse_msgq(struct app_params *app, { struct app_msgq_params *param; struct rte_cfgfile_entry *entries; - int n_entries, ret, i; + int n_entries, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1829,30 +2055,34 @@ parse_msgq(struct app_params *app, PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); param = &app->msgq_params[param_idx]; - param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - ret = -ESRCH; - if (strcmp(ent->name, "size") == 0) - ret = parser_read_uint32(¶m->size, - ent->value); - else if (strcmp(ent->name, "cpu") == 0) - ret = parser_read_uint32(¶m->cpu_socket_id, + if (strcmp(ent->name, "size") == 0) { + int status = parser_read_uint32(¶m->size, ent->value); - APP_CHECK(ret != -ESRCH, - "CFG: [%s] entry '%s': unknown entry\n", - section_name, - ent->name); - APP_CHECK(ret == 0, - "CFG: [%s] entry '%s': Invalid value '%s'\n", - section_name, - ent->name, - ent->value); + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "cpu") == 0) { + int status = parser_read_uint32( + ¶m->cpu_socket_id, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); } + param->parsed = 1; + free(entries); } @@ -1887,7 +2117,7 @@ create_implicit_mempools(struct app_params *app) ssize_t idx; idx = APP_PARAM_ADD(app->mempool_params, "MEMPOOL0"); - PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, "start-up"); + PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, "start-up"); } static void @@ -1905,7 +2135,7 @@ parse_port_mask(struct app_params *app, uint64_t port_mask) snprintf(name, sizeof(name), "LINK%" PRIu32, link_id); idx = APP_PARAM_ADD(app->link_params, name); - PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, name); + PARSER_PARAM_ADD_CHECK(idx, app->link_params, name); app->link_params[idx].pmd_id = pmd_id; link_id++; @@ -1927,13 +2157,16 @@ app_config_parse(struct app_params *app, const char *file_name) /* Load application configuration file */ cfg = rte_cfgfile_load(file_name, 0); - APP_CHECK(cfg != NULL, "Unable to load config file %s", file_name); + APP_CHECK((cfg != NULL), "Parse error: Unable to load config " + "file %s", file_name); sect_count = rte_cfgfile_num_sections(cfg, NULL, 0); - APP_CHECK(sect_count > 0, "Number of sections return %d", sect_count); + APP_CHECK((sect_count > 0), "Parse error: number of sections " + "in file \"%s\" return %d", file_name, + sect_count); section_names = malloc(sect_count * sizeof(char *)); - APP_CHECK(section_names != NULL, "Failed to allocate memory"); + PARSE_ERROR_MALLOC(section_names != NULL); for (i = 0; i < sect_count; i++) section_names[i] = malloc(CFG_NAME_LEN); @@ -1969,13 +2202,13 @@ app_config_parse(struct app_params *app, const char *file_name) } APP_CHECK(j < (int)RTE_DIM(cfg_file_scheme), - "Unknown section %s", + "Parse error: unknown section %s", section_names[i]); APP_CHECK(validate_name(section_names[i], sch_s->prefix, sch_s->numbers) == 0, - "Invalid section name '%s'", + "Parse error: invalid section name \"%s\"", section_names[i]); sch_s->load(app, section_names[i], cfg); @@ -2343,7 +2576,9 @@ save_pipeline_params(struct app_params *app, FILE *f) name = app->source_params[pp->id].name; break; default: - APP_CHECK(0, "Error\n"); + APP_CHECK(0, "System error " + "occurred while saving " + "parameter to file"); } fprintf(f, " %s", name); @@ -2375,7 +2610,9 @@ save_pipeline_params(struct app_params *app, FILE *f) name = app->sink_params[pp->id].name; break; default: - APP_CHECK(0, "Error\n"); + APP_CHECK(0, "System error " + "occurred while saving " + "parameter to file"); } fprintf(f, " %s", name); @@ -2438,12 +2675,13 @@ app_config_save(struct app_params *app, const char *file_name) dir_name = dirname(name); status = access(dir_name, W_OK); APP_CHECK((status == 0), - "Need write access to directory \"%s\" to save configuration\n", - dir_name); + "Error: need write access privilege to directory " + "\"%s\" to save configuration\n", dir_name); file = fopen(file_name, "w"); APP_CHECK((file != NULL), - "Failed to save configuration to file \"%s\"", file_name); + "Error: failed to save configuration to file \"%s\"", + file_name); save_eal_params(app, file); save_pipeline_params(app, file); @@ -2680,7 +2918,8 @@ app_config_preproc(struct app_params *app) return 0; status = access(app->config_file, F_OK | R_OK); - APP_CHECK((status == 0), "Unable to open file %s", app->config_file); + APP_CHECK((status == 0), "Error: Unable to open file %s", + app->config_file); snprintf(buffer, sizeof(buffer), "%s %s %s > %s", app->preproc, @@ -2690,7 +2929,8 @@ app_config_preproc(struct app_params *app) status = system(buffer); APP_CHECK((WIFEXITED(status) && (WEXITSTATUS(status) == 0)), - "Error while preprocessing file \"%s\"\n", app->config_file); + "Error occurred while pre-processing file \"%s\"\n", + app->config_file); return status; } diff --git a/examples/ip_pipeline/parser.h b/examples/ip_pipeline/parser.h new file mode 100644 index 0000000..58b59da --- /dev/null +++ b/examples/ip_pipeline/parser.h @@ -0,0 +1,50 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __INCLUDE_PARSER_H__ +#define __INCLUDE_PARSER_H__ + +int +parser_read_arg_bool(const char *p); + +int +parser_read_uint64(uint64_t *value, const char *p); + +int +parser_read_uint32(uint32_t *value, const char *p); + +int +parse_hex_string(char *src, uint8_t *dst, uint32_t *size); + +#endif + diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c index 1c376f7..1981cc7 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c @@ -42,6 +42,7 @@ #include #include "pipeline_firewall_be.h" +#include "parser.h" struct pipeline_firewall { struct pipeline p; @@ -308,17 +309,26 @@ pipeline_firewall_parse_args(struct pipeline_firewall *p, char *arg_value = params->args_value[i]; if (strcmp(arg_name, "n_rules") == 0) { - if (n_rules_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + n_rules_present == 0, params->name, + arg_name); n_rules_present = 1; - p->n_rules = atoi(arg_value); + status = parser_read_uint32(&p->n_rules, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } if (strcmp(arg_name, "pkt_type") == 0) { - if (pkt_type_present) - return -1; + PIPELINE_PARSE_ERR_DUPLICATE( + pkt_type_present == 0, params->name, + arg_name); pkt_type_present = 1; /* ipv4 */ @@ -351,11 +361,12 @@ pipeline_firewall_parse_args(struct pipeline_firewall *p, } /* other */ - return -1; + PIPELINE_PARSE_ERR_INV_VAL(0, params->name, + arg_name, arg_value); } /* other */ - return -1; + PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); } return 0; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c index 73dbe7a..d502be0 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c @@ -42,6 +42,7 @@ #include "pipeline_actions_common.h" #include "pipeline_flow_actions_be.h" +#include "parser.h" #include "hash_func.h" int @@ -415,80 +416,118 @@ pipeline_fa_parse_args(struct pipeline_fa_params *p, /* n_flows */ if (strcmp(arg_name, "n_flows") == 0) { - if (n_flows_present) - return -1; + int status; + PIPELINE_PARSE_ERR_DUPLICATE( + n_flows_present == 0, params->name, + arg_name); n_flows_present = 1; - p->n_flows = atoi(arg_value); - if (p->n_flows == 0) - return -1; + status = parser_read_uint32(&p->n_flows, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && + (p->n_flows != 0)), params->name, + arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* n_meters_per_flow */ if (strcmp(arg_name, "n_meters_per_flow") == 0) { - if (n_meters_per_flow_present) - return -1; + int status; + PIPELINE_PARSE_ERR_DUPLICATE( + n_meters_per_flow_present == 0, + params->name, arg_name); n_meters_per_flow_present = 1; - p->n_meters_per_flow = atoi(arg_value); - if ((p->n_meters_per_flow == 0) || - (p->n_meters_per_flow > PIPELINE_FA_N_TC_MAX)) - return -1; + status = parser_read_uint32(&p->n_meters_per_flow, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && + (p->n_meters_per_flow != 0)), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) && + (p->n_meters_per_flow <= + PIPELINE_FA_N_TC_MAX)), params->name, + arg_name, arg_value); continue; } /* flow_id_offset */ if (strcmp(arg_name, "flow_id_offset") == 0) { - if (flow_id_offset_present) - return -1; + int status; + PIPELINE_PARSE_ERR_DUPLICATE( + flow_id_offset_present == 0, + params->name, arg_name); flow_id_offset_present = 1; - p->flow_id_offset = atoi(arg_value); + status = parser_read_uint32(&p->flow_id_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* ip_hdr_offset */ if (strcmp(arg_name, "ip_hdr_offset") == 0) { - if (ip_hdr_offset_present) - return -1; + int status; + PIPELINE_PARSE_ERR_DUPLICATE( + ip_hdr_offset_present == 0, + params->name, arg_name); ip_hdr_offset_present = 1; - p->ip_hdr_offset = atoi(arg_value); + status = parser_read_uint32(&p->ip_hdr_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* color_offset */ if (strcmp(arg_name, "color_offset") == 0) { - if (color_offset_present) - return -1; + int status; + PIPELINE_PARSE_ERR_DUPLICATE( + color_offset_present == 0, params->name, + arg_name); color_offset_present = 1; + status = parser_read_uint32(&p->color_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + p->dscp_enabled = 1; - p->color_offset = atoi(arg_value); continue; } /* Unknown argument */ - return -1; + PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); } /* Check that mandatory arguments are present */ - if ((n_flows_present == 0) || - (flow_id_offset_present == 0) || - (ip_hdr_offset_present == 0) || - (color_offset_present == 0)) - return -1; + PIPELINE_PARSE_ERR_MANDATORY((n_flows_present), params->name, + "n_flows"); + PIPELINE_PARSE_ERR_MANDATORY((flow_id_offset_present), + params->name, "flow_id_offset"); + PIPELINE_PARSE_ERR_MANDATORY((ip_hdr_offset_present), + params->name, "ip_hdr_offset"); + PIPELINE_PARSE_ERR_MANDATORY((color_offset_present), params->name, + "color_offset"); return 0; } diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c index ac80fc6..c528dfb 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c @@ -41,6 +41,7 @@ #include "pipeline_flow_classification_be.h" #include "pipeline_actions_common.h" +#include "parser.h" #include "hash_func.h" struct pipeline_flow_classification { @@ -53,7 +54,7 @@ struct pipeline_flow_classification { uint32_t key_offset; uint32_t hash_offset; - uint8_t *key_mask; + uint8_t key_mask[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; uint32_t flow_id_offset; } __rte_cache_aligned; @@ -219,7 +220,7 @@ pipeline_fc_parse_args(struct pipeline_flow_classification *p, uint32_t flow_id_offset_present = 0; uint32_t i; - char *key_mask_str = NULL; + char key_mask_str[PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2]; p->hash_offset = 0; @@ -232,110 +233,157 @@ pipeline_fc_parse_args(struct pipeline_flow_classification *p, /* n_flows */ if (strcmp(arg_name, "n_flows") == 0) { - if (n_flows_present) - goto error_parse; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + n_flows_present == 0, params->name, + arg_name); n_flows_present = 1; - p->n_flows = atoi(arg_value); - if (p->n_flows == 0) - goto error_parse; + status = parser_read_uint32(&p->n_flows, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && + (p->n_flows != 0)), params->name, + arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* key_offset */ if (strcmp(arg_name, "key_offset") == 0) { - if (key_offset_present) - goto error_parse; + int status; + PIPELINE_PARSE_ERR_DUPLICATE( + key_offset_present == 0, params->name, + arg_name); key_offset_present = 1; - p->key_offset = atoi(arg_value); + status = parser_read_uint32(&p->key_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* key_size */ if (strcmp(arg_name, "key_size") == 0) { - if (key_size_present) - goto error_parse; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + key_size_present == 0, params->name, + arg_name); key_size_present = 1; - p->key_size = atoi(arg_value); - if ((p->key_size == 0) || - (p->key_size > PIPELINE_FC_FLOW_KEY_MAX_SIZE) || - (p->key_size % 8)) - goto error_parse; + status = parser_read_uint32(&p->key_size, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && + (p->key_size != 0) && + (p->key_size % 8 == 0)), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) && + (p->key_size <= + PIPELINE_FC_FLOW_KEY_MAX_SIZE)), + params->name, arg_name, arg_value); continue; } /* key_mask */ if (strcmp(arg_name, "key_mask") == 0) { - if (key_mask_present) - goto error_parse; - - key_mask_str = strdup(arg_value); - if (key_mask_str == NULL) - goto error_parse; + int mask_str_len = strlen(arg_value); + PIPELINE_PARSE_ERR_DUPLICATE( + key_mask_present == 0, + params->name, arg_name); key_mask_present = 1; + PIPELINE_ARG_CHECK((mask_str_len < + (PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2)), + "Parse error in section \"%s\": entry " + "\"%s\" is too long", params->name, + arg_name); + + snprintf(key_mask_str, mask_str_len, "%s", + arg_value); + continue; } /* hash_offset */ if (strcmp(arg_name, "hash_offset") == 0) { - if (hash_offset_present) - goto error_parse; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + hash_offset_present == 0, params->name, + arg_name); hash_offset_present = 1; - p->hash_offset = atoi(arg_value); + status = parser_read_uint32(&p->hash_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* flow_id_offset */ if (strcmp(arg_name, "flowid_offset") == 0) { - if (flow_id_offset_present) - goto error_parse; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + flow_id_offset_present == 0, params->name, + arg_name); flow_id_offset_present = 1; + status = parser_read_uint32(&p->flow_id_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + p->flow_id = 1; - p->flow_id_offset = atoi(arg_value); continue; } /* Unknown argument */ - goto error_parse; + PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); } /* Check that mandatory arguments are present */ - if ((n_flows_present == 0) || - (key_offset_present == 0) || - (key_size_present == 0)) - goto error_parse; + PIPELINE_PARSE_ERR_MANDATORY((n_flows_present), params->name, + "n_flows"); + PIPELINE_PARSE_ERR_MANDATORY((key_offset_present), params->name, + "key_offset"); + PIPELINE_PARSE_ERR_MANDATORY((key_size_present), params->name, + "key_size"); if (key_mask_present) { - p->key_mask = rte_malloc(NULL, p->key_size, 0); - if (p->key_mask == NULL) - goto error_parse; + uint32_t key_size = p->key_size; + int status; - if (parse_hex_string(key_mask_str, p->key_mask, &p->key_size) - != 0) { - goto error_parse; - } + PIPELINE_ARG_CHECK((strlen(key_mask_str) == + (key_size * 2)), "Parse error in section " + "\"%s\": key_mask should have exactly %u hex " + "digits", params->name, (key_size * 2)); - free(key_mask_str); + status = parse_hex_string(key_mask_str, p->key_mask, + &p->key_size); + + PIPELINE_PARSE_ERR_INV_VAL(((status == 0) && + (key_size == p->key_size)), params->name, + "key_mask", key_mask_str); } return 0; - -error_parse: - free(key_mask_str); - free(p->key_mask); - return -1; } static void *pipeline_fc_init(struct pipeline_params *params, diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c index a898f7d..630de3b 100644 --- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c @@ -42,6 +42,7 @@ #include "pipeline_passthrough_be.h" #include "pipeline_actions_common.h" +#include "parser.h" #include "hash_func.h" struct pipeline_passthrough { @@ -238,6 +239,7 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, uint32_t dma_size_present = 0; uint32_t dma_hash_offset_present = 0; uint32_t i; + char dma_mask_str[PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2]; /* default values */ p->dma_enabled = 0; @@ -250,11 +252,20 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, /* dma_dst_offset */ if (strcmp(arg_name, "dma_dst_offset") == 0) { - if (dma_dst_offset_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + dma_dst_offset_present == 0, params->name, + arg_name); dma_dst_offset_present = 1; - p->dma_dst_offset = atoi(arg_value); + status = parser_read_uint32(&p->dma_dst_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + p->dma_enabled = 1; continue; @@ -262,11 +273,20 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, /* dma_src_offset */ if (strcmp(arg_name, "dma_src_offset") == 0) { - if (dma_src_offset_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + dma_src_offset_present == 0, params->name, + arg_name); dma_src_offset_present = 1; - p->dma_src_offset = atoi(arg_value); + status = parser_read_uint32(&p->dma_src_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + p->dma_enabled = 1; continue; @@ -274,15 +294,23 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, /* dma_size */ if (strcmp(arg_name, "dma_size") == 0) { - if (dma_size_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + dma_size_present == 0, params->name, + arg_name); dma_size_present = 1; - p->dma_size = atoi(arg_value); - if ((p->dma_size == 0) || - (p->dma_size > PIPELINE_PASSTHROUGH_DMA_SIZE_MAX) || - ((p->dma_size % 8) != 0)) - return -1; + status = parser_read_uint32(&p->dma_size, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && + (p->dma_size != 0) && + ((p->dma_size % 8) == 0)), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) && + (p->dma_size <= + PIPELINE_PASSTHROUGH_DMA_SIZE_MAX)), + params->name, arg_name, arg_value); p->dma_enabled = 1; @@ -291,34 +319,22 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, /* dma_src_mask */ if (strcmp(arg_name, "dma_src_mask") == 0) { - uint32_t dma_size; - int status; + int mask_str_len = strlen(arg_value); - if (dma_src_mask_present || - (dma_size_present == 0)) - return -1; + PIPELINE_PARSE_ERR_DUPLICATE( + dma_src_mask_present == 0, + params->name, arg_name); dma_src_mask_present = 1; - dma_size = p->dma_size; - status = parse_hex_string(arg_value, - p->dma_src_mask, - &dma_size); - if (status || - (dma_size != p->dma_size)) - return -1; + PIPELINE_ARG_CHECK((mask_str_len < + (PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2)), + "Parse error in section \"%s\": entry " + "\"%s\" too long", params->name, + arg_name); - p->dma_enabled = 1; + snprintf(dma_mask_str, mask_str_len + 1, + "%s", arg_value); - continue; - } - - /* dma_dst_offset */ - if (strcmp(arg_name, "dma_dst_offset") == 0) { - if (dma_dst_offset_present) - return -1; - dma_dst_offset_present = 1; - - p->dma_dst_offset = atoi(arg_value); p->dma_enabled = 1; continue; @@ -326,11 +342,20 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, /* dma_hash_offset */ if (strcmp(arg_name, "dma_hash_offset") == 0) { - if (dma_hash_offset_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + dma_hash_offset_present == 0, + params->name, arg_name); dma_hash_offset_present = 1; - p->dma_hash_offset = atoi(arg_value); + status = parser_read_uint32(&p->dma_hash_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + p->dma_hash_enabled = 1; p->dma_enabled = 1; @@ -338,16 +363,39 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, } /* any other */ - return -1; + PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); } /* Check correlations between arguments */ - if ((dma_dst_offset_present != p->dma_enabled) || - (dma_src_offset_present != p->dma_enabled) || - (dma_size_present != p->dma_enabled) || - (dma_hash_offset_present != p->dma_hash_enabled) || - (p->dma_hash_enabled > p->dma_enabled)) - return -1; + PIPELINE_ARG_CHECK((dma_dst_offset_present == p->dma_enabled), + "Parse error in section \"%s\": missing entry " + "\"dma_dst_offset\"", params->name); + PIPELINE_ARG_CHECK((dma_src_offset_present == p->dma_enabled), + "Parse error in section \"%s\": missing entry " + "\"dma_src_offset\"", params->name); + PIPELINE_ARG_CHECK((dma_size_present == p->dma_enabled), + "Parse error in section \"%s\": missing entry " + "\"dma_size\"", params->name); + PIPELINE_ARG_CHECK((dma_hash_offset_present == p->dma_enabled), + "Parse error in section \"%s\": missing entry " + "\"dma_hash_offset\"", params->name); + + if (dma_src_mask_present) { + uint32_t dma_size = p->dma_size; + int status; + + PIPELINE_ARG_CHECK((strlen(dma_mask_str) == + (dma_size * 2)), "Parse error in section " + "\"%s\": dma_src_mask should have exactly %u hex " + "digits", params->name, (dma_size * 2)); + + status = parse_hex_string(dma_mask_str, p->dma_src_mask, + &p->dma_size); + + PIPELINE_PARSE_ERR_INV_VAL(((status == 0) && + (dma_size == p->dma_size)), params->name, + "dma_src_mask", dma_mask_str); + } return 0; } diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.c b/examples/ip_pipeline/pipeline/pipeline_routing_be.c index 9baabd0..4fb6b59 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.c @@ -47,6 +47,7 @@ #include "pipeline_routing_be.h" #include "pipeline_actions_common.h" +#include "parser.h" #include "hash_func.h" #define MPLS_LABEL(label, exp, s, ttl) \ @@ -940,21 +941,28 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p, /* n_routes */ if (strcmp(arg_name, "n_routes") == 0) { - if (n_routes_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + n_routes_present == 0, params->name, + arg_name); n_routes_present = 1; - p->n_routes = atoi(arg_value); - if (p->n_routes == 0) - return -1; + status = parser_read_uint32(&p->n_routes, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && + (p->n_routes != 0)), params->name, + arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* encap */ if (strcmp(arg_name, "encap") == 0) { - if (encap_present) - return -1; + PIPELINE_PARSE_ERR_DUPLICATE(encap_present == 0, + params->name, arg_name); encap_present = 1; /* ethernet */ @@ -976,140 +984,204 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p, } /* any other */ - return -1; + PIPELINE_PARSE_ERR_INV_VAL(0, params->name, + arg_name, arg_value); } /* qinq_sched */ if (strcmp(arg_name, "qinq_sched") == 0) { - if (qinq_sched_present) - return -1; + int status; + PIPELINE_PARSE_ERR_DUPLICATE( + qinq_sched_present == 0, params->name, + arg_name); qinq_sched_present = 1; - if (strcmp(arg_value, "no") == 0) - p->qinq_sched = 0; - else if (strcmp(arg_value, "yes") == 0) - p->qinq_sched = 1; - else if (strcmp(arg_value, "test") == 0) - p->qinq_sched = 2; - else - return -1; + status = parser_read_arg_bool(arg_value); + if (status == -EINVAL) { + if (strcmp(arg_value, "test") == 0) { + p->qinq_sched = 2; + continue; + } + } else { + p->qinq_sched = status; + continue; + } - continue; + PIPELINE_PARSE_ERR_INV_VAL(0, params->name, + arg_name, arg_value); } /* mpls_color_mark */ if (strcmp(arg_name, "mpls_color_mark") == 0) { - if (mpls_color_mark_present) - return -1; + int status; + PIPELINE_PARSE_ERR_DUPLICATE( + mpls_color_mark_present == 0, + params->name, arg_name); mpls_color_mark_present = 1; - if (strcmp(arg_value, "no") == 0) - p->mpls_color_mark = 0; - else if (strcmp(arg_value, "yes") == 0) - p->mpls_color_mark = 1; - else - return -1; - continue; + status = parser_read_arg_bool(arg_value); + if (status >= 0) { + p->mpls_color_mark = status; + continue; + } + + PIPELINE_PARSE_ERR_INV_VAL(0, params->name, + arg_name, arg_value); } /* n_arp_entries */ if (strcmp(arg_name, "n_arp_entries") == 0) { - if (n_arp_entries_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + n_arp_entries_present == 0, params->name, + arg_name); n_arp_entries_present = 1; - p->n_arp_entries = atoi(arg_value); + status = parser_read_uint32(&p->n_arp_entries, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* ip_hdr_offset */ if (strcmp(arg_name, "ip_hdr_offset") == 0) { - if (ip_hdr_offset_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + ip_hdr_offset_present == 0, params->name, + arg_name); ip_hdr_offset_present = 1; - p->ip_hdr_offset = atoi(arg_value); + status = parser_read_uint32(&p->ip_hdr_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* arp_key_offset */ if (strcmp(arg_name, "arp_key_offset") == 0) { - if (arp_key_offset_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + arp_key_offset_present == 0, params->name, + arg_name); arp_key_offset_present = 1; - p->arp_key_offset = atoi(arg_value); + status = parser_read_uint32(&p->arp_key_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* color_offset */ if (strcmp(arg_name, "color_offset") == 0) { - if (color_offset_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + color_offset_present == 0, params->name, + arg_name); color_offset_present = 1; - p->color_offset = atoi(arg_value); + status = parser_read_uint32(&p->color_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* debug */ if (strcmp(arg_name, "dbg_ah_disable") == 0) { - if (dbg_ah_disable_present) - return -1; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + dbg_ah_disable_present == 0, params->name, + arg_name); dbg_ah_disable_present = 1; - if (strcmp(arg_value, "no") == 0) - p->dbg_ah_disable = 0; - else if (strcmp(arg_value, "yes") == 0) - p->dbg_ah_disable = 1; - else - return -1; + status = parser_read_arg_bool(arg_value); + if (status >= 0) { + p->dbg_ah_disable = status; + continue; + } + + PIPELINE_PARSE_ERR_INV_VAL(0, params->name, + arg_name, arg_value); continue; } /* any other */ - return -1; + PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); } /* Check that mandatory arguments are present */ - if (ip_hdr_offset_present == 0) - return -1; + PIPELINE_PARSE_ERR_MANDATORY(ip_hdr_offset_present, params->name, + "ip_hdr_offset"); /* Check relations between arguments */ switch (p->encap) { case PIPELINE_ROUTING_ENCAP_ETHERNET: - if (p->qinq_sched || - p->mpls_color_mark || - color_offset_present) - return -1; + PIPELINE_ARG_CHECK((!p->qinq_sched), "Parse error in " + "section \"%s\": encap = ethernet, therefore " + "qinq_sched = yes/test is not allowed", + params->name); + PIPELINE_ARG_CHECK((!p->mpls_color_mark), "Parse error " + "in section \"%s\": encap = ethernet, therefore " + "mpls_color_mark = yes is not allowed", + params->name); + PIPELINE_ARG_CHECK((!color_offset_present), "Parse error " + "in section \"%s\": encap = ethernet, therefore " + "color_offset is not allowed", + params->name); break; case PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ: - if (p->mpls_color_mark || - color_offset_present) - return -1; + PIPELINE_ARG_CHECK((!p->mpls_color_mark), "Parse error " + "in section \"%s\": encap = ethernet_qinq, " + "therefore mpls_color_mark = yes is not allowed", + params->name); + PIPELINE_ARG_CHECK((!color_offset_present), "Parse error " + "in section \"%s\": encap = ethernet_qinq, " + "therefore color_offset is not allowed", + params->name); break; case PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS: - if (p->qinq_sched) - return -1; + PIPELINE_ARG_CHECK((!p->qinq_sched), "Parse error in " + "section \"%s\": encap = ethernet_mpls, therefore " + "qinq_sched = yes/test is not allowed", + params->name); break; - - default: - return -1; } - if ((p->n_arp_entries && (arp_key_offset_present == 0)) || - ((p->n_arp_entries == 0) && arp_key_offset_present)) - return -1; + PIPELINE_ARG_CHECK((!(p->n_arp_entries && + (!arp_key_offset_present))), "Parse error in section " + "\"%s\": n_arp_entries is set while " + "arp_key_offset is not set", params->name); + + PIPELINE_ARG_CHECK((!((p->n_arp_entries == 0) && + arp_key_offset_present)), "Parse error in section " + "\"%s\": arp_key_offset present while " + "n_arp_entries is not set", params->name); return 0; } diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h index 0ba00f6..d820435 100644 --- a/examples/ip_pipeline/pipeline_be.h +++ b/examples/ip_pipeline/pipeline_be.h @@ -271,8 +271,33 @@ struct pipeline_be_ops { pipeline_be_op_track f_track; }; -/* Parse hex string to uint8_t array */ -int -parse_hex_string(char *src, uint8_t *dst, uint32_t *size); +/* Pipeline specific config parse error messages */ +#define PIPELINE_ARG_CHECK(exp, fmt, ...) \ +do { \ + if (!(exp)) { \ + fprintf(stderr, fmt "\n", ## __VA_ARGS__); \ + return -1; \ + } \ +} while (0) + +#define PIPELINE_PARSE_ERR_INV_VAL(exp, section, entry, val) \ +PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": entry \"%s\" " \ + "has invalid value (\"%s\")", section, entry, val) + +#define PIPELINE_PARSE_ERR_OUT_RNG(exp, section, entry, val) \ +PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": entry \"%s\" " \ + "value is out of range (\"%s\")", section, entry, val) + +#define PIPELINE_PARSE_ERR_DUPLICATE(exp, section, entry) \ +PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": duplicated " \ + "entry \"%s\"", section, entry) + +#define PIPELINE_PARSE_ERR_INV_ENT(exp, section, entry) \ +PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": invalid entry " \ + "\"%s\"", section, entry) + +#define PIPELINE_PARSE_ERR_MANDATORY(exp, section, entry) \ +PIPELINE_ARG_CHECK(exp, "Parse error in section \"%s\": mandatory " \ + "entry \"%s\" is missing", section, entry) #endif