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 <rte_string_fns.h>
 
 #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(
+				&param->socket_id, &param->core_id,
+				&param->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(&param->socket_id,
-				&param->core_id,
-				&param->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(&param->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(
+				&param->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(&param->buffer_size,
-				ent->value);
-		else if (strcmp(ent->name, "pool_size") == 0)
-			ret = parser_read_uint32(&param->pool_size,
-				ent->value);
-		else if (strcmp(ent->name, "cache_size") == 0)
-			ret = parser_read_uint32(&param->cache_size,
-				ent->value);
-		else if (strcmp(ent->name, "cpu") == 0)
-			ret = parser_read_uint32(&param->cpu_socket_id,
-				ent->value);
+		if (strcmp(ent->name, "buffer_size") == 0) {
+			int status = parser_read_uint32(
+				&param->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(
+				&param->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(
+				&param->cache_size, ent->value);
+
+			PARSE_ERROR((status == 0), section_name,
+				ent->name);
+			continue;
+		}
+
+		if (strcmp(ent->name, "cpu") == 0) {
+			int status = parser_read_uint32(
+				&param->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(&param->arp_q,
-				ent->value);
-		else if (strcmp(ent->name, "tcp_syn_q") == 0)
-			ret = parser_read_uint32(&param->tcp_syn_local_q,
-				ent->value);
-		else if (strcmp(ent->name, "ip_local_q") == 0)
-			ret = parser_read_uint32(&param->ip_local_q,
-				ent->value);
-		else if (strcmp(ent->name, "tcp_local_q") == 0)
-			ret = parser_read_uint32(&param->tcp_local_q,
-				ent->value);
-		else if (strcmp(ent->name, "udp_local_q") == 0)
-			ret = parser_read_uint32(&param->udp_local_q,
-				ent->value);
-		else if (strcmp(ent->name, "sctp_local_q") == 0)
-			ret = parser_read_uint32(&param->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(&param->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(
+				&param->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(
+				&param->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(
+				&param->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(
+				&param->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(
+				&param->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(&param->size,
+			continue;
+		}
+
+		if (strcmp(ent->name, "size") == 0) {
+			int status = parser_read_uint32(&param->size,
 				ent->value);
-		else if (strcmp(ent->name, "burst") == 0)
-			ret = parser_read_uint32(&param->burst,
+
+			PARSE_ERROR((status == 0), section_name,
+				ent->name);
+			continue;
+		}
+
+		if (strcmp(ent->name, "burst") == 0) {
+			int status = parser_read_uint32(&param->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(&param->size, ent->value);
-		else if (strcmp(ent->name, "burst") == 0)
-			ret = parser_read_uint32(&param->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(&param->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(&param->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(&param->size,
-				ent->value);
-		else if (strcmp(ent->name, "burst_read") == 0)
-			ret = parser_read_uint32(&param->burst_read,
+		if (strcmp(ent->name, "size") == 0) {
+			int status = parser_read_uint32(&param->size,
 				ent->value);
-		else if (strcmp(ent->name, "burst_write") == 0)
-			ret = parser_read_uint32(&param->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(&param->n_retries,
-				ent->value);
-		else if (strcmp(ent->name, "cpu") == 0)
-			ret = parser_read_uint32(&param->cpu_socket_id,
-				ent->value);
-		else if (strcmp(ent->name, "ipv4_frag") == 0) {
-			ret = parser_read_arg_bool(ent->value);
-			if (ret >= 0) {
-				param->ipv4_frag = ret;
-				if (param->mtu == 0)
-					param->mtu = 1500;
-				ret = 0;
-			}
-		} else if (strcmp(ent->name, "ipv6_frag") == 0) {
-			ret = parser_read_arg_bool(ent->value);
-			if (ret >= 0) {
-				param->ipv6_frag = ret;
-				if (param->mtu == 0)
-					param->mtu = 1320;
-				ret = 0;
-			}
-		} else if (strcmp(ent->name, "ipv4_ras") == 0) {
-			ret = parser_read_arg_bool(ent->value);
-			if (ret >= 0) {
-				param->ipv4_ras = ret;
-				ret = 0;
-			}
-		} else if (strcmp(ent->name, "ipv6_ras") == 0) {
-			ret = parser_read_arg_bool(ent->value);
-			if (ret >= 0) {
-				param->ipv6_ras = ret;
-				ret = 0;
-			}
-		} else if (strcmp(ent->name, "mtu") == 0) {
-			frag_entries = 1;
-			ret = parser_read_uint32(&param->mtu,
-				ent->value);
-		} else if (strcmp(ent->name, "metadata_size") == 0) {
-			frag_entries = 1;
-			ret = parser_read_uint32(&param->metadata_size,
+
+			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(
+				&param->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(&param->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(
+				&param->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(&param->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(
+				&param->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(&param->burst_read,
-				ent->value);
-		else if (strcmp(ent->name, "burst_write") == 0)
-			ret = parser_read_uint32(&param->burst_write,
-				ent->value);
+			PARSE_ERROR_MALLOC(param->file_name != NULL);
+			continue;
+		}
+
+		if (strcmp(ent->name, "burst_read") == 0) {
+			int status = parser_read_uint32(
+				&param->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(
+				&param->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(&param->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(&param->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(&param->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(&param->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(&param->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(&param->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(&param->size,
-				ent->value);
-		else if (strcmp(ent->name, "cpu") == 0)
-			ret = parser_read_uint32(&param->cpu_socket_id,
+		if (strcmp(ent->name, "size") == 0) {
+			int status = parser_read_uint32(&param->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(
+				&param->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 <rte_table_acl.h>
 
 #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
