From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 4CE2B2C68 for ; Fri, 11 Mar 2016 18:08:16 +0100 (CET) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga103.fm.intel.com with ESMTP; 11 Mar 2016 09:08:15 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.24,321,1455004800"; d="scan'208";a="667774605" Received: from sie-lab-212-033.ir.intel.com (HELO silpixa00383881.ir.intel.com) ([10.237.212.33]) by FMSMGA003.fm.intel.com with ESMTP; 11 Mar 2016 09:08:14 -0800 From: Fan Zhang To: dev@dpdk.org Date: Fri, 11 Mar 2016 17:08:10 +0000 Message-Id: <1457716090-26742-5-git-send-email-roy.fan.zhang@intel.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1457716090-26742-1-git-send-email-roy.fan.zhang@intel.com> References: <1457539652-17337-1-git-send-email-roy.fan.zhang@intel.com> <1457716090-26742-1-git-send-email-roy.fan.zhang@intel.com> Subject: [dpdk-dev] [PATCH v4 4/4] examples/ip_pipeline: add packets dumping to PCAP file support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Mar 2016 17:08:17 -0000 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 Acked-by: Cristian Dumitrescu --- examples/ip_pipeline/app.h | 2 + examples/ip_pipeline/config_parse.c | 172 ++++++++++++++++++++++++++++++++++++ examples/ip_pipeline/init.c | 15 ++++ examples/ip_pipeline/pipeline_be.h | 4 +- 4 files changed, 192 insertions(+), 1 deletion(-) diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h index 0c22f7f..55a9841 100644 --- a/examples/ip_pipeline/app.h +++ b/examples/ip_pipeline/app.h @@ -156,6 +156,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 291dbfb..e39c23e 100644 --- a/examples/ip_pipeline/config_parse.c +++ b/examples/ip_pipeline/config_parse.c @@ -187,6 +187,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 = { @@ -1036,6 +1038,85 @@ 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) @@ -1408,6 +1489,24 @@ parse_pipeline(struct app_params *app, continue; } + if (strcmp(ent->name, "pcap_file_wr") == 0) { + int status = parse_pipeline_pcap_sink(app, param, + ent->value, NULL); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "pcap_n_pkt_wr") == 0) { + int status = parse_pipeline_pcap_sink(app, param, + NULL, 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 " @@ -2124,6 +2223,57 @@ 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, 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]; + + for (i = 0; i < n_entries; i++) { + struct rte_cfgfile_entry *ent = &entries[i]; + + if (strcmp(ent->name, "pcap_file_wr")) { + param->file_name = strdup(ent->value); + + PARSE_ERROR_MALLOC((param->file_name != NULL)); + continue; + } + + if (strcmp(ent->name, "pcap_n_pkt_wr")) { + int status = parser_read_uint32( + ¶m->n_pkts_to_dump, 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); +} + +static void parse_msgq_req_pipeline(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) @@ -2283,6 +2433,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}, @@ -2726,6 +2877,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; @@ -2908,6 +3079,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 40bb506..e59a6b4 100644 --- a/examples/ip_pipeline/init.c +++ b/examples/ip_pipeline/init.c @@ -1362,6 +1362,21 @@ 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; + } else { + out->params.sink.file_name = NULL; + out->params.sink.max_n_pkts = 0; + } break; default: break; diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h index d820435..f4ff262 100644 --- a/examples/ip_pipeline/pipeline_be.h +++ b/examples/ip_pipeline/pipeline_be.h @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -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