From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 3D198C366 for ; Wed, 17 Feb 2016 12:11:34 +0100 (CET) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga101.jf.intel.com with ESMTP; 17 Feb 2016 03:11:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,460,1449561600"; d="scan'208";a="653495223" Received: from sie-lab-212-033.ir.intel.com (HELO silpixa00383881.ir.intel.com) ([10.237.212.33]) by FMSMGA003.fm.intel.com with ESMTP; 17 Feb 2016 03:11:33 -0800 From: Fan Zhang To: dev@dpdk.org Date: Wed, 17 Feb 2016 11:11:28 +0000 Message-Id: <1455707490-13826-3-git-send-email-roy.fan.zhang@intel.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1455707490-13826-1-git-send-email-roy.fan.zhang@intel.com> References: <1455707490-13826-1-git-send-email-roy.fan.zhang@intel.com> Subject: [dpdk-dev] [PATCH v2 2/4] example/ip_pipeline: add 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: Wed, 17 Feb 2016 11:11:34 -0000 This patch add PCAP file support to ip_pipeline. Input port type SOURCE now supports loading specific PCAP file and sends the packets in it to pipeline instance. The packets are then released by SINK output port. 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_rd = /path/to/eth1.PCAP /path/to/eth2.PCAP pcap_bytes_rd_per_pkt = 0 64 The configuration section "pcap_file_rd" contains full path and name of the PCAP file to be loaded. If multiple SOURCEs exists, each shall have its own PCAP file path listed in this section, separated by spaces. Multiple SOURCE ports may share same PCAP file to be copied. The configuration section "pcap_bytes_rd_per_pkt" contains integer value and indicates the maximum number of bytes to be copied from each packet in the PCAP file. If this value is "0", all packets in the file will be copied fully; if the packet size is smaller than the assigned value, the entire packet is copied. Same as "pcap_file_rd", every SOURCE shall have its own maximum copy byte number. To enable PCAP support to IP pipeline, the compiler option CONFIG_RTE_PORT_PCAP must be set to 'y'. It is possible to disable PCAP support by removing "pcap_file_rd" and "pcap_bytes_rd_per_pkt" 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 | 102 +++++++++++++++++++++++++++++++++++- examples/ip_pipeline/init.c | 11 ++++ 3 files changed, 113 insertions(+), 2 deletions(-) diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h index 6510d6d..9dbe668 100644 --- a/examples/ip_pipeline/app.h +++ b/examples/ip_pipeline/app.h @@ -148,6 +148,8 @@ struct app_pktq_source_params { uint32_t parsed; uint32_t mempool_id; /* Position in the app->mempool_params array */ uint32_t burst; + char *file_name; /* Full path of PCAP file to be copied to mbufs */ + uint32_t n_bytes_per_pkt; }; struct app_pktq_sink_params { diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c index 1bedbe4..f0bed81 100644 --- a/examples/ip_pipeline/config_parse.c +++ b/examples/ip_pipeline/config_parse.c @@ -178,6 +178,8 @@ struct app_pktq_source_params default_source_params = { .parsed = 0, .mempool_id = 0, .burst = 32, + .file_name = NULL, + .n_bytes_per_pkt = 0, }; struct app_pktq_sink_params default_sink_params = { @@ -924,6 +926,83 @@ parse_eal(struct app_params *app, } static int +parse_pipeline_pcap_source(struct app_params *app, + struct app_pipeline_params *p, + const char *file_name, const char *cp_size) +{ + const char *next = NULL; + char *end; + uint32_t i; + int parse_file = 0; + + if (file_name && !cp_size) { + next = file_name; + parse_file = 1; /* parse file path */ + } else if (cp_size && !file_name) { + next = cp_size; + parse_file = 0; /* parse copy size */ + } else + return -EINVAL; + + char name[APP_PARAM_NAME_SIZE]; + size_t name_len; + + if (p->n_pktq_in == 0) + return -EINVAL; + + for (i = 0; i < p->n_pktq_in; i++) { + if (p->pktq_in[i].type != APP_PKTQ_IN_SOURCE) + return -EINVAL; + } + + i = 0; + while (*next != '\0') { + uint32_t id; + + if (i >= p->n_pktq_in) + return -EINVAL; + + id = p->pktq_in[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->source_params[id].file_name = strdup(name); + if (app->source_params[id].file_name == NULL) + return -ENOMEM; + } else { + if (parser_read_uint32( + &app->source_params[id].n_bytes_per_pkt, + name) != 0) { + if (app->source_params[id].file_name != NULL) + free(app->source_params[id].file_name); + return -EINVAL; + } + } + + i++; + + if (i == p->n_pktq_in) + return 0; + } + + return -EINVAL; +} + +static int parse_pipeline_pktq_in(struct app_params *app, struct app_pipeline_params *p, const char *value) @@ -1169,6 +1248,12 @@ parse_pipeline(struct app_params *app, else if (strcmp(ent->name, "timer_period") == 0) ret = parser_read_uint32(¶m->timer_period, ent->value); + else if (strcmp(ent->name, "pcap_file_rd") == 0) + ret = parse_pipeline_pcap_source(app, param, + ent->value, NULL); + else if (strcmp(ent->name, "pcap_bytes_rd_per_pkt") == 0) + ret = parse_pipeline_pcap_source(app, param, + NULL, ent->value); else { APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS), "CFG: [%s] out of memory", @@ -1700,8 +1785,18 @@ parse_source(struct app_params *app, PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name); param->mempool_id = idx; ret = 0; - } else if (strcmp(ent->name, "burst") == 0) + } else if (strcmp(ent->name, "burst") == 0) { ret = parser_read_uint32(¶m->burst, ent->value); + } else if (strcmp(ent->name, "pcap_file_rd")) { + param->file_name = strdup(ent->value); + if (param->file_name != NULL) + ret = 0; + else + ret = -ENOMEM; + } else if (strcmp(ent->name, "pcap_bytes_rd_per_pkt") == 0) { + ret = parser_read_uint32(¶m->n_bytes_per_pkt, + ent->value); + } APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", @@ -2272,6 +2367,9 @@ save_source_params(struct app_params *app, FILE *f) "mempool", app->mempool_params[p->mempool_id].name); fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst); + fprintf(f, "%s = %s\n", "pcap_file_rd", p->file_name); + fprintf(f, "%s = %" PRIu32 "\n", + "pcap_bytes_rd_per_pkt", p->n_bytes_per_pkt); fputc('\n', f); } } @@ -2654,7 +2752,7 @@ app_config_args(struct app_params *app, int argc, char **argv) optind = 0; /* reset getopt lib */ /* Check that mandatory args have been provided */ - if (!p_present) + if (!p_present && (app->n_pktq_hwq_in != 0)) rte_panic("Error: PORT_MASK is not provided\n"); /* Check dependencies between args */ diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c index 186ca03..e513a2d 100644 --- a/examples/ip_pipeline/init.c +++ b/examples/ip_pipeline/init.c @@ -1154,6 +1154,17 @@ static void app_pipeline_params_get(struct app_params *app, out->type = PIPELINE_PORT_IN_SOURCE; out->params.source.mempool = app->mempool[mempool_id]; out->burst_size = app->source_params[in->id].burst; + if (app->source_params[in->id].file_name != NULL) { + out->params.source.file_name = strdup( + app->source_params[in->id].file_name); + out->params.source.n_bytes_per_pkt = + app->source_params[in->id]. + n_bytes_per_pkt; + if (out->params.source.file_name == NULL) { + out->params.source.n_bytes_per_pkt = 0; + break; + } + } break; default: break; -- 2.5.0