DPDK patches and discussions
 help / color / mirror / Atom feed
From: Fan Zhang <roy.fan.zhang@intel.com>
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v2 4/4] examples/ip_pipeline: add packets dumping to PCAP file support
Date: Wed, 17 Feb 2016 11:11:30 +0000	[thread overview]
Message-ID: <1455707490-13826-5-git-send-email-roy.fan.zhang@intel.com> (raw)
In-Reply-To: <1455707490-13826-1-git-send-email-roy.fan.zhang@intel.com>

This patch add packet dumping feature to ip_pipeline. Output port type
SINK now supports dumping packets to PCAP file before releasing mbuf back
to mempool. This feature can be applied by specifying parameters in
configuration file as shown below:

[PIPELINE1]
type = PASS-THROUGH
core = 1
pktq_in = SOURCE0 SOURCE1
pktq_out = SINK0 SINK1
pcap_file_wr = /path/to/eth1.pcap /path/to/eth2.pcap
pcap_n_pkt_wr = 80 0

The configuration section "pcap_file_wr" contains full path and name of
the PCAP file which the packets will be dumped to. If multiple SINKs
exists, each shall have its own PCAP file path listed in this section,
separated by spaces. Multiple SINK ports shall NOT share same PCAP file to
be dumped.

The configuration section "pcap_n_pkt_wr" contains integer value(s)
and indicates the maximum number of packets to be dumped to the PCAP file.
If this value is "0", the "infinite" dumping mode will be used. If this
value is N (N > 0), the dumping will be finished when the number of
packets dumped to the file reaches N.

To enable PCAP dumping support to IP pipeline, the compiler option
CONFIG_RTE_PORT_PCAP must be set to 'y'. It is possible to disable this
feature by removing "pcap_file_wr" and "pcap_n_pkt_wr" lines from the
configuration file.

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 examples/ip_pipeline/app.h          |   2 +
 examples/ip_pipeline/config_parse.c | 159 ++++++++++++++++++++++++++++++++++++
 examples/ip_pipeline/init.c         |  11 +++
 examples/ip_pipeline/pipeline_be.h  |   2 +
 4 files changed, 174 insertions(+)

diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h
index 9dbe668..144fab8 100644
--- a/examples/ip_pipeline/app.h
+++ b/examples/ip_pipeline/app.h
@@ -155,6 +155,8 @@ struct app_pktq_source_params {
 struct app_pktq_sink_params {
 	char *name;
 	uint8_t parsed;
+	char *file_name; /* Full path of PCAP file to be copied to mbufs */
+	uint32_t n_pkts_to_dump;
 };
 
 struct app_msgq_params {
diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c
index f0bed81..9f5b974 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -184,6 +184,8 @@ struct app_pktq_source_params default_source_params = {
 
 struct app_pktq_sink_params default_sink_params = {
 	.parsed = 0,
+	.file_name = NULL,
+	.n_pkts_to_dump = 0,
 };
 
 struct app_msgq_params default_msgq_params = {
@@ -1003,6 +1005,83 @@ parse_pipeline_pcap_source(struct app_params *app,
 }
 
 static int
+parse_pipeline_pcap_sink(struct app_params *app,
+	struct app_pipeline_params *p,
+	const char *file_name, const char *n_pkts_to_dump)
+{
+	const char *next = NULL;
+	char *end;
+	uint32_t i;
+	int parse_file = 0;
+
+	if (file_name && !n_pkts_to_dump) {
+		next = file_name;
+		parse_file = 1; /* parse file path */
+	} else if (n_pkts_to_dump && !file_name) {
+		next = n_pkts_to_dump;
+		parse_file = 0; /* parse copy size */
+	} else
+		return -EINVAL;
+
+	char name[APP_PARAM_NAME_SIZE];
+	size_t name_len;
+
+	if (p->n_pktq_out == 0)
+		return -EINVAL;
+
+	for (i = 0; i < p->n_pktq_out; i++) {
+		if (p->pktq_out[i].type != APP_PKTQ_OUT_SINK)
+			return -EINVAL;
+	}
+
+	i = 0;
+	while (*next != '\0') {
+		uint32_t id;
+
+		if (i >= p->n_pktq_out)
+			return -EINVAL;
+
+		id = p->pktq_out[i].id;
+
+		end = strchr(next, ' ');
+		if (!end)
+			name_len = strlen(next);
+		else
+			name_len = end - next;
+
+		if (name_len == 0 || name_len == sizeof(name))
+			return -EINVAL;
+
+		strncpy(name, next, name_len);
+		name[name_len] = '\0';
+		next += name_len;
+		if (*next != '\0')
+			next++;
+
+		if (parse_file) {
+			app->sink_params[id].file_name = strdup(name);
+			if (app->sink_params[id].file_name == NULL)
+				return -ENOMEM;
+		} else {
+			if (parser_read_uint32(
+				&app->sink_params[id].n_pkts_to_dump,
+				name) != 0) {
+				if (app->sink_params[id].file_name != NULL)
+					free(app->sink_params[id].file_name);
+				return -EINVAL;
+			}
+		}
+
+		i++;
+
+		if (i == p->n_pktq_out)
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int
 parse_pipeline_pktq_in(struct app_params *app,
 	struct app_pipeline_params *p,
 	const char *value)
@@ -1254,6 +1333,12 @@ parse_pipeline(struct app_params *app,
 		else if (strcmp(ent->name, "pcap_bytes_rd_per_pkt") == 0)
 			ret = parse_pipeline_pcap_source(app, param,
 					NULL, ent->value);
+		else if (strcmp(ent->name, "pcap_file_wr") == 0)
+			ret = parse_pipeline_pcap_sink(app, param,
+					ent->value, NULL);
+		else if (strcmp(ent->name, "pcap_n_pkt_wr") == 0)
+			ret = parse_pipeline_pcap_sink(app, param,
+					NULL, ent->value);
 		else {
 			APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS),
 				"CFG: [%s] out of memory",
@@ -1813,6 +1898,58 @@ parse_source(struct app_params *app,
 }
 
 static void
+parse_sink(struct app_params *app,
+	const char *section_name,
+	struct rte_cfgfile *cfg)
+{
+	struct app_pktq_sink_params *param;
+	struct rte_cfgfile_entry *entries;
+	int n_entries, ret, i;
+	ssize_t param_idx;
+
+	n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
+	PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
+
+	entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
+	PARSE_ERROR_MALLOC(entries != NULL);
+
+	rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
+
+	param_idx = APP_PARAM_ADD(app->sink_params, section_name);
+	PARSER_PARAM_ADD_CHECK(param_idx, app->sink_params, section_name);
+
+	param = &app->sink_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, "pcap_file_wr")) {
+			param->file_name = strdup(ent->value);
+			if (param->file_name != NULL)
+				ret = 0;
+			else
+				ret = -ENOMEM;
+		} else if (strcmp(ent->name, "pcap_n_pkt_wr")) {
+			ret = parser_read_uint32(&param->n_pkts_to_dump,
+					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);
+	}
+
+	free(entries);
+}
+
+static void
 parse_msgq_req_pipeline(struct app_params *app,
 	const char *section_name,
 	struct rte_cfgfile *cfg)
@@ -1971,6 +2108,7 @@ static const struct config_section cfg_file_scheme[] = {
 	{"SWQ", 1, parse_swq},
 	{"TM", 1, parse_tm},
 	{"SOURCE", 1, parse_source},
+	{"SINK", 1, parse_sink},
 	{"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline},
 	{"MSGQ-RSP-PIPELINE", 1, parse_msgq_rsp_pipeline},
 	{"MSGQ", 1, parse_msgq},
@@ -2375,6 +2513,26 @@ save_source_params(struct app_params *app, FILE *f)
 }
 
 static void
+save_sink_params(struct app_params *app, FILE *f)
+{
+	struct app_pktq_sink_params *p;
+	size_t i, count;
+
+	count = RTE_DIM(app->sink_params);
+	for (i = 0; i < count; i++) {
+		p = &app->sink_params[i];
+		if (!APP_PARAM_VALID(p))
+			continue;
+
+		fprintf(f, "[%s]\n", p->name);
+		fprintf(f, "%s = %s\n", "pcap_file_wr", p->file_name);
+		fprintf(f, "%s = %" PRIu32 "\n",
+				"pcap_n_pkt_wr", p->n_pkts_to_dump);
+		fputc('\n', f);
+	}
+}
+
+static void
 save_msgq_params(struct app_params *app, FILE *f)
 {
 	struct app_msgq_params *p;
@@ -2552,6 +2710,7 @@ app_config_save(struct app_params *app, const char *file_name)
 	save_swq_params(app, file);
 	save_tm_params(app, file);
 	save_source_params(app, file);
+	save_sink_params(app, file);
 	save_msgq_params(app, file);
 
 	fclose(file);
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index e513a2d..1cb62e5 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -1288,6 +1288,16 @@ static void app_pipeline_params_get(struct app_params *app,
 		}
 		case APP_PKTQ_OUT_SINK:
 			out->type = PIPELINE_PORT_OUT_SINK;
+			if (app->sink_params[in->id].file_name != NULL) {
+				out->params.sink.file_name = strdup(
+					app->sink_params[in->id].file_name);
+				if (out->params.sink.file_name == NULL) {
+					out->params.sink.max_n_pkts = 0;
+					break;
+				}
+				out->params.sink.max_n_pkts =
+					app->sink_params[in->id].n_pkts_to_dump;
+			}
 			break;
 		default:
 			break;
@@ -1325,6 +1335,7 @@ app_init_pipelines(struct app_params *app)
 
 		APP_LOG(app, HIGH, "Initializing %s ...", params->name);
 
+		memset(&pp, 0, sizeof(pp));
 		ptype = app_pipeline_type_find(app, params->type);
 		if (ptype == NULL)
 			rte_panic("Init error: Unknown pipeline type \"%s\"\n",
diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h
index 0ba00f6..b8f229e 100644
--- a/examples/ip_pipeline/pipeline_be.h
+++ b/examples/ip_pipeline/pipeline_be.h
@@ -137,6 +137,7 @@ struct pipeline_port_out_params {
 		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;
+		struct rte_port_sink_params sink;
 	} params;
 };
 
@@ -163,6 +164,7 @@ pipeline_port_out_params_convert(struct pipeline_port_out_params  *p)
 	case PIPELINE_PORT_OUT_SCHED_WRITER:
 		return (void *) &p->params.sched;
 	case PIPELINE_PORT_OUT_SINK:
+		return (void *) &p->params.sink;
 	default:
 		return NULL;
 	}
-- 
2.5.0

  parent reply	other threads:[~2016-02-17 11:11 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-17 11:11 [dpdk-dev] [PATCH v2 0/4] Add PCAP support to source and sink port Fan Zhang
2016-02-17 11:11 ` [dpdk-dev] [PATCH v2 1/4] lib/librte_port: add PCAP file support to source port Fan Zhang
2016-03-07 11:17   ` Thomas Monjalon
2016-03-08  8:36     ` Dumitrescu, Cristian
2016-03-08  9:06       ` Panu Matilainen
2016-03-08 10:14       ` Thomas Monjalon
2016-02-17 11:11 ` [dpdk-dev] [PATCH v2 2/4] example/ip_pipeline: add PCAP file support Fan Zhang
2016-02-17 11:11 ` [dpdk-dev] [PATCH v2 3/4] lib/librte_port: add packet dumping to PCAP file support in sink port Fan Zhang
2016-02-17 11:11 ` Fan Zhang [this message]
2016-03-09 16:07 ` [dpdk-dev] [PATCH v3 0/4] Add PCAP support to source and " Fan Zhang
2016-03-09 16:07   ` [dpdk-dev] [PATCH v3 1/4] lib/librte_port: add PCAP file support to source port Fan Zhang
2016-03-09 16:07   ` [dpdk-dev] [PATCH v3 2/4] example/ip_pipeline: add PCAP file support Fan Zhang
2016-03-11 11:10     ` Thomas Monjalon
2016-03-25 12:00       ` Zhang, Roy Fan
2016-03-09 16:07   ` [dpdk-dev] [PATCH v3 3/4] lib/librte_port: add packet dumping to PCAP file support in sink port Fan Zhang
2016-03-09 16:07   ` [dpdk-dev] [PATCH v3 4/4] examples/ip_pipeline: add packets dumping to PCAP file support Fan Zhang
2016-03-11 17:08   ` [dpdk-dev] [PATCH v4 0/4] Add PCAP support to source and sink port Fan Zhang
2016-03-11 17:08     ` [dpdk-dev] [PATCH v4 1/4] lib/librte_port: add PCAP file support to source port Fan Zhang
2016-03-11 17:08     ` [dpdk-dev] [PATCH v4 2/4] example/ip_pipeline: add PCAP file support Fan Zhang
2016-03-11 17:08     ` [dpdk-dev] [PATCH v4 3/4] lib/librte_port: add packet dumping to PCAP file support in sink port Fan Zhang
2016-03-11 17:08     ` [dpdk-dev] [PATCH v4 4/4] examples/ip_pipeline: add packets dumping to PCAP file support Fan Zhang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1455707490-13826-5-git-send-email-roy.fan.zhang@intel.com \
    --to=roy.fan.zhang@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).