[dpdk-dev] [PATCH v2 3/3] examples/ip_pipeline: add mp/mc and frag/ras swq

Piotr Azarewicz piotrx.t.azarewicz at intel.com
Thu Sep 24 11:55:39 CEST 2015


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

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

diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h
index 521e3a0..943466e 100644
--- a/examples/ip_pipeline/app.h
+++ b/examples/ip_pipeline/app.h
@@ -107,6 +107,14 @@ struct app_pktq_swq_params {
 	uint32_t dropless;
 	uint64_t n_retries;
 	uint32_t cpu_socket_id;
+	uint32_t ipv4_frag;
+	uint32_t ipv6_frag;
+	uint32_t ipv4_ras;
+	uint32_t ipv6_ras;
+	uint32_t mtu;
+	uint32_t metadata_size;
+	uint32_t mempool_direct_id;
+	uint32_t mempool_indirect_id;
 };
 
 #ifndef APP_FILE_NAME_SIZE
@@ -405,6 +413,10 @@ struct app_params {
 	char app_name[APP_APPNAME_SIZE];
 	const char *config_file;
 	const char *script_file;
+	const char *parser_file;
+	const char *output_file;
+	const char *preproc;
+	const char *preproc_args;
 	uint64_t port_mask;
 	uint32_t log_level;
 
@@ -880,6 +892,8 @@ int app_config_init(struct app_params *app);
 int app_config_args(struct app_params *app,
 	int argc, char **argv);
 
+int app_config_preproc(struct app_params *app);
+
 int app_config_parse(struct app_params *app,
 	const char *file_name);
 
diff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c
index 07f4c8b..8052bc4 100644
--- a/examples/ip_pipeline/config_check.c
+++ b/examples/ip_pipeline/config_check.c
@@ -33,6 +33,8 @@
 
 #include <stdio.h>
 
+#include <rte_ip.h>
+
 #include "app.h"
 
 static void
@@ -193,6 +195,7 @@ check_swqs(struct app_params *app)
 		struct app_pktq_swq_params *p = &app->swq_params[i];
 		uint32_t n_readers = app_swq_get_readers(app, p);
 		uint32_t n_writers = app_swq_get_writers(app, p);
+		uint32_t n_flags;
 
 		APP_CHECK((p->size > 0),
 			"%s size is 0\n", p->name);
@@ -217,14 +220,48 @@ check_swqs(struct app_params *app)
 		APP_CHECK((n_readers != 0),
 			"%s has no reader\n", p->name);
 
-		APP_CHECK((n_readers == 1),
-			"%s has more than one reader\n", p->name);
+		if (n_readers > 1)
+			APP_LOG(app, LOW, "%s has more than one reader", p->name);
 
 		APP_CHECK((n_writers != 0),
 			"%s has no writer\n", p->name);
 
-		APP_CHECK((n_writers == 1),
-			"%s has more than one writer\n", p->name);
+		if (n_writers > 1)
+			APP_LOG(app, LOW, "%s has more than one writer", p->name);
+
+		n_flags = p->ipv4_frag + p->ipv6_frag + p->ipv4_ras + p->ipv6_ras;
+
+		APP_CHECK((n_flags < 2),
+			"%s has more than one fragmentation or reassembly mode enabled\n",
+			p->name);
+
+		APP_CHECK((!((n_readers > 1) && (n_flags == 1))),
+			"%s has more than one reader when fragmentation or reassembly"
+			" mode enabled\n",
+			p->name);
+
+		APP_CHECK((!((n_writers > 1) && (n_flags == 1))),
+			"%s has more than one writer when fragmentation or reassembly"
+			" mode enabled\n",
+			p->name);
+
+		n_flags = p->ipv4_ras + p->ipv6_ras;
+
+		APP_CHECK((!((p->dropless == 1) && (n_flags == 1))),
+			"%s has dropless when reassembly mode enabled\n", p->name);
+
+		n_flags = p->ipv4_frag + p->ipv6_frag;
+
+		if (n_flags == 1) {
+			uint16_t ip_hdr_size = (p->ipv4_frag) ? sizeof(struct ipv4_hdr) :
+				sizeof(struct ipv6_hdr);
+
+			APP_CHECK((p->mtu > ip_hdr_size),
+				"%s mtu size is smaller than ip header\n", p->name);
+
+			APP_CHECK((!((p->mtu - ip_hdr_size) % 8)),
+				"%s mtu size is incorrect\n", p->name);
+		}
 	}
 }
 
diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c
index c9b78f9..a35bd3e 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -156,6 +156,14 @@ static const struct app_pktq_swq_params default_swq_params = {
 	.dropless = 0,
 	.n_retries = 0,
 	.cpu_socket_id = 0,
+	.ipv4_frag = 0,
+	.ipv6_frag = 0,
+	.ipv4_ras = 0,
+	.ipv6_ras = 0,
+	.mtu = 0,
+	.metadata_size = 0,
+	.mempool_direct_id = 0,
+	.mempool_indirect_id = 0,
 };
 
 struct app_pktq_tm_params default_tm_params = {
@@ -196,13 +204,15 @@ struct app_pipeline_params default_pipeline_params = {
 
 static const char app_usage[] =
 	"Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] -p PORT_MASK "
-	"[-l LOG_LEVEL]\n"
+	"[-l LOG_LEVEL] [--preproc PREPROCESSOR] [--preproc-args ARGS]\n"
 	"\n"
 	"Arguments:\n"
 	"\t-f CONFIG_FILE: Default config file is %s\n"
 	"\t-p PORT_MASK: Mask of NIC port IDs in hexadecimal format\n"
 	"\t-s SCRIPT_FILE: No CLI script file is run when not specified\n"
 	"\t-l LOG_LEVEL: 0 = NONE, 1 = HIGH PRIO (default), 2 = LOW PRIO\n"
+	"\t--preproc PREPROCESSOR: Configuration file pre-processor\n"
+	"\t--preproc-args ARGS: Arguments to be passed to pre-processor\n"
 	"\n";
 
 static void
@@ -1107,6 +1117,10 @@ parse_pipeline(struct app_params *app,
 			ret = parser_read_uint32(&param->timer_period,
 				ent->value);
 		else {
+			APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS),
+				"CFG: [%s] out of memory",
+				section_name);
+
 			param->args_name[param->n_args] = strdup(ent->name);
 			param->args_value[param->n_args] = strdup(ent->value);
 
@@ -1397,6 +1411,7 @@ parse_swq(struct app_params *app,
 	struct app_pktq_swq_params *param;
 	struct rte_cfgfile_entry *entries;
 	int n_entries, ret, i;
+	unsigned frag_entries = 0;
 	ssize_t param_idx;
 
 	n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
@@ -1438,6 +1453,71 @@ parse_swq(struct app_params *app,
 		else if (strcmp(ent->name, "cpu") == 0)
 			ret = parser_read_uint32(&param->cpu_socket_id,
 				ent->value);
+		else if (strcmp(ent->name, "ipv4_frag") == 0) {
+			ret = parser_read_arg_bool(ent->value);
+			if (ret >= 0) {
+				param->ipv4_frag = ret;
+				if (param->mtu == 0)
+					param->mtu = 1500;
+				ret = 0;
+			}
+		} else if (strcmp(ent->name, "ipv6_frag") == 0) {
+			ret = parser_read_arg_bool(ent->value);
+			if (ret >= 0) {
+				param->ipv6_frag = ret;
+				if (param->mtu == 0)
+					param->mtu = 1320;
+				ret = 0;
+			}
+		} else if (strcmp(ent->name, "ipv4_ras") == 0) {
+			ret = parser_read_arg_bool(ent->value);
+			if (ret >= 0) {
+				param->ipv4_ras = ret;
+				ret = 0;
+			}
+		} else if (strcmp(ent->name, "ipv6_ras") == 0) {
+			ret = parser_read_arg_bool(ent->value);
+			if (ret >= 0) {
+				param->ipv6_ras = ret;
+				ret = 0;
+			}
+		} else if (strcmp(ent->name, "mtu") == 0) {
+			frag_entries = 1;
+			ret = parser_read_uint32(&param->mtu,
+				ent->value);
+		} else if (strcmp(ent->name, "metadata_size") == 0) {
+			frag_entries = 1;
+			ret = parser_read_uint32(&param->metadata_size,
+				ent->value);
+		} else if (strcmp(ent->name, "mempool_direct") == 0) {
+			int status = validate_name(ent->value, "MEMPOOL", 1);
+			ssize_t idx;
+
+			APP_CHECK((status == 0),
+				"CFG: [%s] entry '%s': invalid mempool\n",
+				section_name,
+				ent->name);
+
+			idx = APP_PARAM_ADD(app->mempool_params, ent->value);
+			PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
+			param->mempool_direct_id = idx;
+			frag_entries = 1;
+			ret = 0;
+		} else if (strcmp(ent->name, "mempool_indirect") == 0) {
+			int status = validate_name(ent->value, "MEMPOOL", 1);
+			ssize_t idx;
+
+			APP_CHECK((status == 0),
+				"CFG: [%s] entry '%s': invalid mempool\n",
+				section_name,
+				ent->name);
+
+			idx = APP_PARAM_ADD(app->mempool_params, ent->value);
+			PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
+			param->mempool_indirect_id = idx;
+			frag_entries = 1;
+			ret = 0;
+		}
 
 		APP_CHECK(ret != -ESRCH,
 			"CFG: [%s] entry '%s': unknown entry\n",
@@ -1450,6 +1530,13 @@ parse_swq(struct app_params *app,
 			ent->value);
 	}
 
+	if (frag_entries == 1) {
+		APP_CHECK(((param->ipv4_frag == 1) || (param->ipv6_frag == 1)),
+			"CFG: [%s] ipv4/ipv6 frag is off : unsupported entries on this"
+			" configuration\n",
+			section_name);
+	}
+
 	free(entries);
 }
 
@@ -1769,7 +1856,6 @@ parse_port_mask(struct app_params *app, uint64_t port_mask)
 int
 app_config_parse(struct app_params *app, const char *file_name)
 {
-	char config_file_out[APP_FILE_NAME_SIZE];
 	struct rte_cfgfile *cfg;
 	char **section_names;
 	int i, j, sect_count;
@@ -1851,11 +1937,7 @@ app_config_parse(struct app_params *app, const char *file_name)
 	APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines);
 
 	/* Save configuration to output file */
-	snprintf(config_file_out,
-		APP_FILE_NAME_SIZE,
-		"%s.out",
-		app->config_file);
-	app_config_save(app, config_file_out);
+	app_config_save(app, app->output_file);
 
 	/* Load TM configuration files */
 	app_config_parse_tm(app);
@@ -2069,6 +2151,20 @@ save_swq_params(struct app_params *app, FILE *f)
 		fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no");
 		fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
 		fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id);
+		fprintf(f, "%s = %s\n", "ipv4_frag", p->ipv4_frag ? "yes" : "no");
+		fprintf(f, "%s = %s\n", "ipv6_frag", p->ipv6_frag ? "yes" : "no");
+		fprintf(f, "%s = %s\n", "ipv4_ras", p->ipv4_ras ? "yes" : "no");
+		fprintf(f, "%s = %s\n", "ipv6_ras", p->ipv6_ras ? "yes" : "no");
+		if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1)) {
+			fprintf(f, "%s = %" PRIu32 "\n", "mtu", p->mtu);
+			fprintf(f, "%s = %" PRIu32 "\n", "metadata_size", p->metadata_size);
+			fprintf(f, "%s = %s\n",
+				"mempool_direct",
+				app->mempool_params[p->mempool_direct_id].name);
+			fprintf(f, "%s = %s\n",
+				"mempool_indirect",
+				app->mempool_params[p->mempool_indirect_id].name);
+		}
 
 		fputc('\n', f);
 	}
@@ -2360,15 +2456,31 @@ app_config_init(struct app_params *app)
 	return 0;
 }
 
+static char *
+filenamedup(const char *filename, const char *suffix)
+{
+	char *s = malloc(strlen(filename) + strlen(suffix) + 1);
+
+	if (!s)
+		return NULL;
+
+	sprintf(s, "%s%s", filename, suffix);
+	return s;
+}
+
 int
 app_config_args(struct app_params *app, int argc, char **argv)
 {
-	int opt;
-	int option_index, f_present, s_present, p_present, l_present;
+	const char *optname;
+	int opt, option_index;
+	int f_present, s_present, p_present, l_present;
+	int preproc_present, preproc_params_present;
 	int scaned = 0;
 
 	static struct option lgopts[] = {
-		{NULL, 0, 0, 0}
+		{ "preproc", 1, 0, 0 },
+		{ "preproc-args", 1, 0, 0 },
+		{ NULL,  0, 0, 0 }
 	};
 
 	/* Copy application name */
@@ -2378,6 +2490,8 @@ app_config_args(struct app_params *app, int argc, char **argv)
 	s_present = 0;
 	p_present = 0;
 	l_present = 0;
+	preproc_present = 0;
+	preproc_params_present = 0;
 
 	while ((opt = getopt_long(argc, argv, "f:s:p:l:", lgopts,
 			&option_index)) != EOF)
@@ -2443,6 +2557,32 @@ app_config_args(struct app_params *app, int argc, char **argv)
 
 			break;
 
+		case 0:
+			optname = lgopts[option_index].name;
+
+			if (strcmp(optname, "preproc") == 0) {
+				if (preproc_present)
+					rte_panic("Error: Preprocessor argument "
+						"is provided more than once\n");
+				preproc_present = 1;
+
+				app->preproc = strdup(optarg);
+				break;
+			}
+
+			if (strcmp(optname, "preproc-args") == 0) {
+				if (preproc_params_present)
+					rte_panic("Error: Preprocessor args "
+						"are provided more than once\n");
+				preproc_params_present = 1;
+
+				app->preproc_args = strdup(optarg);
+				break;
+			}
+
+			app_print_usage(argv[0]);
+			break;
+
 		default:
 			app_print_usage(argv[0]);
 		}
@@ -2453,5 +2593,40 @@ app_config_args(struct app_params *app, int argc, char **argv)
 	if (!p_present)
 		rte_panic("Error: PORT_MASK is not provided\n");
 
+	/* Check dependencies between args */
+	if (preproc_params_present && (preproc_present == 0))
+		rte_panic("Error: Preprocessor args specified while "
+			"preprocessor is not defined\n");
+
+	app->parser_file = preproc_present ?
+		filenamedup(app->config_file, ".preproc") :
+		strdup(app->config_file);
+	app->output_file = filenamedup(app->config_file, ".out");
+
 	return 0;
 }
+
+int
+app_config_preproc(struct app_params *app)
+{
+	char buffer[256];
+	int status;
+
+	if (app->preproc == NULL)
+		return 0;
+
+	status = access(app->config_file, F_OK | R_OK);
+	APP_CHECK((status == 0), "Unable to open file %s", app->config_file);
+
+	snprintf(buffer, sizeof(buffer), "%s %s %s > %s",
+		app->preproc,
+		app->preproc_args ? app->preproc_args : "",
+		app->config_file,
+		app->parser_file);
+
+	status = system(buffer);
+	APP_CHECK((WIFEXITED(status) && (WEXITSTATUS(status) == 0)),
+		"Error while preprocessing file \"%s\"\n", app->config_file);
+
+	return status;
+}
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index 3f9c68d..46d044e 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -803,11 +803,43 @@ app_check_link(struct app_params *app)
 		rte_panic("Some links are DOWN\n");
 }
 
+static uint32_t
+is_any_swq_frag_or_ras(struct app_params *app)
+{
+	uint32_t i;
+
+	for (i = 0; i < app->n_pktq_swq; i++) {
+		struct app_pktq_swq_params *p = &app->swq_params[i];
+
+		if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1) ||
+			(p->ipv4_ras == 1) || (p->ipv6_ras == 1))
+			return 1;
+	}
+
+	return 0;
+}
+
+static void
+app_init_link_frag_ras(struct app_params *app)
+{
+	uint32_t i;
+
+	if (is_any_swq_frag_or_ras(app)) {
+		for (i = 0; i < app->n_pktq_hwq_out; i++) {
+			struct app_pktq_hwq_out_params *p_txq = &app->hwq_out_params[i];
+
+			p_txq->conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;
+		}
+	}
+}
+
 static void
 app_init_link(struct app_params *app)
 {
 	uint32_t i;
 
+	app_init_link_frag_ras(app);
+
 	for (i = 0; i < app->n_links; i++) {
 		struct app_link_params *p_link = &app->link_params[i];
 		uint32_t link_id, n_hwq_in, n_hwq_out, j;
@@ -916,13 +948,19 @@ app_init_swq(struct app_params *app)
 
 	for (i = 0; i < app->n_pktq_swq; i++) {
 		struct app_pktq_swq_params *p = &app->swq_params[i];
+		unsigned flags = 0;
+
+		if (app_swq_get_readers(app, p) == 1)
+			flags |= RING_F_SC_DEQ;
+		if (app_swq_get_writers(app, p) == 1)
+			flags |= RING_F_SP_ENQ;
 
 		APP_LOG(app, HIGH, "Initializing %s...", p->name);
 		app->swq[i] = rte_ring_create(
 				p->name,
 				p->size,
 				p->cpu_socket_id,
-				RING_F_SP_ENQ | RING_F_SC_DEQ);
+				flags);
 
 		if (app->swq[i] == NULL)
 			rte_panic("%s init error\n", p->name);
@@ -1059,11 +1097,50 @@ static void app_pipeline_params_get(struct app_params *app,
 			break;
 		}
 		case APP_PKTQ_IN_SWQ:
-			out->type = PIPELINE_PORT_IN_RING_READER;
-			out->params.ring.ring = app->swq[in->id];
-			out->burst_size = app->swq_params[in->id].burst_read;
-			/* What about frag and ras ports? */
+		{
+			struct app_pktq_swq_params *swq_params = &app->swq_params[in->id];
+
+			if ((swq_params->ipv4_frag == 0) && (swq_params->ipv6_frag == 0)) {
+				if (app_swq_get_readers(app, swq_params) == 1) {
+					out->type = PIPELINE_PORT_IN_RING_READER;
+					out->params.ring.ring = app->swq[in->id];
+					out->burst_size = app->swq_params[in->id].burst_read;
+				} else {
+					out->type = PIPELINE_PORT_IN_RING_MULTI_READER;
+					out->params.ring_multi.ring = app->swq[in->id];
+					out->burst_size = swq_params->burst_read;
+				}
+			} else {
+				if (swq_params->ipv4_frag == 1) {
+					struct rte_port_ring_reader_ipv4_frag_params *params =
+						&out->params.ring_ipv4_frag;
+
+					out->type = PIPELINE_PORT_IN_RING_READER_IPV4_FRAG;
+					params->ring = app->swq[in->id];
+					params->mtu = swq_params->mtu;
+					params->metadata_size = swq_params->metadata_size;
+					params->pool_direct =
+						app->mempool[swq_params->mempool_direct_id];
+					params->pool_indirect =
+						app->mempool[swq_params->mempool_indirect_id];
+					out->burst_size = swq_params->burst_read;
+				} else {
+					struct rte_port_ring_reader_ipv6_frag_params *params =
+						&out->params.ring_ipv6_frag;
+
+					out->type = PIPELINE_PORT_IN_RING_READER_IPV6_FRAG;
+					params->ring = app->swq[in->id];
+					params->mtu = swq_params->mtu;
+					params->metadata_size = swq_params->metadata_size;
+					params->pool_direct =
+						app->mempool[swq_params->mempool_direct_id];
+					params->pool_indirect =
+						app->mempool[swq_params->mempool_indirect_id];
+					out->burst_size = swq_params->burst_read;
+				}
+			}
 			break;
+		}
 		case APP_PKTQ_IN_TM:
 			out->type = PIPELINE_PORT_IN_SCHED_READER;
 			out->params.sched.sched = app->tm[in->id];
@@ -1122,28 +1199,68 @@ static void app_pipeline_params_get(struct app_params *app,
 			break;
 		}
 		case APP_PKTQ_OUT_SWQ:
-			if (app->swq_params[in->id].dropless == 0) {
-				struct rte_port_ring_writer_params *params =
-					&out->params.ring;
-
-				out->type = PIPELINE_PORT_OUT_RING_WRITER;
-				params->ring = app->swq[in->id];
-				params->tx_burst_sz =
-					app->swq_params[in->id].burst_write;
+		{
+			struct app_pktq_swq_params *swq_params = &app->swq_params[in->id];
+
+			if ((swq_params->ipv4_ras == 0) && (swq_params->ipv6_ras == 0)) {
+				if (app_swq_get_writers(app, swq_params) == 1) {
+					if (app->swq_params[in->id].dropless == 0) {
+						struct rte_port_ring_writer_params *params =
+							&out->params.ring;
+
+						out->type = PIPELINE_PORT_OUT_RING_WRITER;
+						params->ring = app->swq[in->id];
+						params->tx_burst_sz =
+							app->swq_params[in->id].burst_write;
+					} else {
+						struct rte_port_ring_writer_nodrop_params
+							*params = &out->params.ring_nodrop;
+
+						out->type =
+							PIPELINE_PORT_OUT_RING_WRITER_NODROP;
+						params->ring = app->swq[in->id];
+						params->tx_burst_sz =
+							app->swq_params[in->id].burst_write;
+						params->n_retries =
+							app->swq_params[in->id].n_retries;
+					}
+				} else {
+					if (swq_params->dropless == 0) {
+						struct rte_port_ring_multi_writer_params *params =
+							&out->params.ring_multi;
+
+						out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER;
+						params->ring = app->swq[in->id];
+						params->tx_burst_sz = swq_params->burst_write;
+					} else {
+						struct rte_port_ring_multi_writer_nodrop_params
+							*params = &out->params.ring_multi_nodrop;
+
+						out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP;
+						params->ring = app->swq[in->id];
+						params->tx_burst_sz = swq_params->burst_write;
+						params->n_retries = swq_params->n_retries;
+					}
+				}
 			} else {
-				struct rte_port_ring_writer_nodrop_params
-					*params = &out->params.ring_nodrop;
-
-				out->type =
-					PIPELINE_PORT_OUT_RING_WRITER_NODROP;
-				params->ring = app->swq[in->id];
-				params->tx_burst_sz =
-					app->swq_params[in->id].burst_write;
-				params->n_retries =
-					app->swq_params[in->id].n_retries;
+				if (swq_params->ipv4_ras == 1) {
+					struct rte_port_ring_writer_ipv4_ras_params *params =
+						&out->params.ring_ipv4_ras;
+
+					out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS;
+					params->ring = app->swq[in->id];
+					params->tx_burst_sz = swq_params->burst_write;
+				} else {
+					struct rte_port_ring_writer_ipv6_ras_params *params =
+						&out->params.ring_ipv6_ras;
+
+					out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS;
+					params->ring = app->swq[in->id];
+					params->tx_burst_sz = swq_params->burst_write;
+				}
 			}
-			/* What about frag and ras ports? */
 			break;
+		}
 		case APP_PKTQ_OUT_TM: {
 			struct rte_port_sched_writer_params *params =
 				&out->params.sched;
diff --git a/examples/ip_pipeline/main.c b/examples/ip_pipeline/main.c
index 862e2f2..4944dcf 100644
--- a/examples/ip_pipeline/main.c
+++ b/examples/ip_pipeline/main.c
@@ -45,7 +45,9 @@ main(int argc, char **argv)
 
 	app_config_args(&app, argc, argv);
 
-	app_config_parse(&app, app.config_file);
+	app_config_preproc(&app);
+
+	app_config_parse(&app, app.parser_file);
 
 	app_config_check(&app);
 
diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h
index 51f1e4f..f7269c0 100644
--- a/examples/ip_pipeline/pipeline_be.h
+++ b/examples/ip_pipeline/pipeline_be.h
@@ -45,6 +45,7 @@
 enum pipeline_port_in_type {
 	PIPELINE_PORT_IN_ETHDEV_READER,
 	PIPELINE_PORT_IN_RING_READER,
+	PIPELINE_PORT_IN_RING_MULTI_READER,
 	PIPELINE_PORT_IN_RING_READER_IPV4_FRAG,
 	PIPELINE_PORT_IN_RING_READER_IPV6_FRAG,
 	PIPELINE_PORT_IN_SCHED_READER,
@@ -56,6 +57,7 @@ struct pipeline_port_in_params {
 	union {
 		struct rte_port_ethdev_reader_params ethdev;
 		struct rte_port_ring_reader_params ring;
+		struct rte_port_ring_multi_reader_params ring_multi;
 		struct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag;
 		struct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag;
 		struct rte_port_sched_reader_params sched;
@@ -72,6 +74,8 @@ pipeline_port_in_params_convert(struct pipeline_port_in_params  *p)
 		return (void *) &p->params.ethdev;
 	case PIPELINE_PORT_IN_RING_READER:
 		return (void *) &p->params.ring;
+	case PIPELINE_PORT_IN_RING_MULTI_READER:
+		return (void *) &p->params.ring_multi;
 	case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG:
 		return (void *) &p->params.ring_ipv4_frag;
 	case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG:
@@ -93,6 +97,8 @@ pipeline_port_in_params_get_ops(struct pipeline_port_in_params  *p)
 		return &rte_port_ethdev_reader_ops;
 	case PIPELINE_PORT_IN_RING_READER:
 		return &rte_port_ring_reader_ops;
+	case PIPELINE_PORT_IN_RING_MULTI_READER:
+		return &rte_port_ring_multi_reader_ops;
 	case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG:
 		return &rte_port_ring_reader_ipv4_frag_ops;
 	case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG:
@@ -110,7 +116,9 @@ enum pipeline_port_out_type {
 	PIPELINE_PORT_OUT_ETHDEV_WRITER,
 	PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP,
 	PIPELINE_PORT_OUT_RING_WRITER,
+	PIPELINE_PORT_OUT_RING_MULTI_WRITER,
 	PIPELINE_PORT_OUT_RING_WRITER_NODROP,
+	PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP,
 	PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS,
 	PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS,
 	PIPELINE_PORT_OUT_SCHED_WRITER,
@@ -123,7 +131,9 @@ struct pipeline_port_out_params {
 		struct rte_port_ethdev_writer_params ethdev;
 		struct rte_port_ethdev_writer_nodrop_params ethdev_nodrop;
 		struct rte_port_ring_writer_params ring;
+		struct rte_port_ring_multi_writer_params ring_multi;
 		struct rte_port_ring_writer_nodrop_params ring_nodrop;
+		struct rte_port_ring_multi_writer_nodrop_params ring_multi_nodrop;
 		struct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras;
 		struct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras;
 		struct rte_port_sched_writer_params sched;
@@ -140,8 +150,12 @@ pipeline_port_out_params_convert(struct pipeline_port_out_params  *p)
 		return (void *) &p->params.ethdev_nodrop;
 	case PIPELINE_PORT_OUT_RING_WRITER:
 		return (void *) &p->params.ring;
+	case PIPELINE_PORT_OUT_RING_MULTI_WRITER:
+		return (void *) &p->params.ring_multi;
 	case PIPELINE_PORT_OUT_RING_WRITER_NODROP:
 		return (void *) &p->params.ring_nodrop;
+	case PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP:
+		return (void *) &p->params.ring_multi_nodrop;
 	case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS:
 		return (void *) &p->params.ring_ipv4_ras;
 	case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS:
@@ -164,8 +178,12 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params  *p)
 		return &rte_port_ethdev_writer_nodrop_ops;
 	case PIPELINE_PORT_OUT_RING_WRITER:
 		return &rte_port_ring_writer_ops;
+	case PIPELINE_PORT_OUT_RING_MULTI_WRITER:
+		return &rte_port_ring_multi_writer_ops;
 	case PIPELINE_PORT_OUT_RING_WRITER_NODROP:
 		return &rte_port_ring_writer_nodrop_ops;
+	case PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP:
+		return &rte_port_ring_multi_writer_nodrop_ops;
 	case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS:
 		return &rte_port_ring_writer_ipv4_ras_ops;
 	case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS:
-- 
1.7.9.5



More information about the dev mailing list