From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by dpdk.space (Postfix) with ESMTP id E4C68A0096 for ; Tue, 4 Jun 2019 10:12:57 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id AF5865424; Tue, 4 Jun 2019 10:12:57 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id C9FBA5424 for ; Tue, 4 Jun 2019 10:12:55 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 04 Jun 2019 01:12:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,550,1549958400"; d="scan'208";a="181456462" Received: from fmsmsx105.amr.corp.intel.com ([10.18.124.203]) by fmsmga002.fm.intel.com with ESMTP; 04 Jun 2019 01:12:54 -0700 Received: from FMSMSX109.amr.corp.intel.com (10.18.116.9) by FMSMSX105.amr.corp.intel.com (10.18.124.203) with Microsoft SMTP Server (TLS) id 14.3.408.0; Tue, 4 Jun 2019 01:12:54 -0700 Received: from shsmsx151.ccr.corp.intel.com (10.239.6.50) by fmsmsx109.amr.corp.intel.com (10.18.116.9) with Microsoft SMTP Server (TLS) id 14.3.408.0; Tue, 4 Jun 2019 01:12:54 -0700 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.10]) by SHSMSX151.ccr.corp.intel.com ([169.254.3.6]) with mapi id 14.03.0415.000; Tue, 4 Jun 2019 16:12:52 +0800 From: "Li, Xiaoyun" To: "Ye, Xiaolong" CC: "Wu, Jingjing" , "Wiles, Keith" , "Liang, Cunming" , "Maslekar, Omkar" , "dev@dpdk.org" Thread-Topic: [dpdk-dev] [PATCH 4/6] examples/ntb: enable an example for ntb Thread-Index: AQHVGejlkP1iUW2xJEm5zaROxaK52aaKiPmAgACdgNA= Date: Tue, 4 Jun 2019 08:12:50 +0000 Message-ID: References: <20190603084611.40931-1-xiaoyun.li@intel.com> <20190603084611.40931-5-xiaoyun.li@intel.com> <20190604064801.GA94383@intel.com> In-Reply-To: <20190604064801.GA94383@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH 4/6] examples/ntb: enable an example for ntb X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" OK. Will fix them in next version including other patches' comments. Thanks= . > -----Original Message----- > From: Ye, Xiaolong > Sent: Tuesday, June 4, 2019 14:48 > To: Li, Xiaoyun > Cc: Wu, Jingjing ; Wiles, Keith ; > Liang, Cunming ; Maslekar, Omkar > ; dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH 4/6] examples/ntb: enable an example for n= tb >=20 > On 06/03, Xiaoyun Li wrote: > >Enable an example for rawdev ntb. Support interactive mode to send file > >on one host and receive file from another host. The command line would > >be 'send [filepath]' and 'receive [filepath]'. > > > >But since the FIFO is not enabled right now, use rte_memcpy as the > >enqueue and dequeue functions and only support transmitting file no more > than 4M. > > > >Signed-off-by: Xiaoyun Li > >--- > > drivers/raw/ntb_rawdev/ntb_rawdev.c | 25 +- > > examples/Makefile | 1 + > > examples/meson.build | 21 +- > > examples/ntb/Makefile | 68 ++++++ > > examples/ntb/meson.build | 16 ++ > > examples/ntb/ntb_fwd.c | 364 ++++++++++++++++++++++++++++ > > 6 files changed, 477 insertions(+), 18 deletions(-) create mode > >100644 examples/ntb/Makefile create mode 100644 > >examples/ntb/meson.build create mode 100644 examples/ntb/ntb_fwd.c > > > >diff --git a/drivers/raw/ntb_rawdev/ntb_rawdev.c > >b/drivers/raw/ntb_rawdev/ntb_rawdev.c > >index 35bc34c54..1824842f2 100644 > >--- a/drivers/raw/ntb_rawdev/ntb_rawdev.c > >+++ b/drivers/raw/ntb_rawdev/ntb_rawdev.c > >@@ -212,11 +212,16 @@ ntb_enqueue_bufs(struct rte_rawdev *dev, > > unsigned int count, > > rte_rawdev_obj_t context) > > { > >- RTE_SET_USED(dev); > >- RTE_SET_USED(buffers); > >- RTE_SET_USED(count); > >- RTE_SET_USED(context); > >+ /* Not FIFO right now. Just for test memory write. */ > >+ struct ntb_hw *hw =3D dev->dev_private; > >+ uint64_t bar_addr, size; > >+ unsigned int i; > >+ > >+ bar_addr =3D (*hw->ntb_ops->get_peer_mw_addr)(dev, 0); >=20 > check the func pointer before calling it. >=20 > >+ size =3D (uint64_t)context; > > > >+ for (i =3D 0; i < count; i++) > >+ rte_memcpy((void *)bar_addr, buffers[i]->buf_addr, size); > > return 0; > > } > > > >@@ -226,11 +231,15 @@ ntb_dequeue_bufs(struct rte_rawdev *dev, > > unsigned int count, > > rte_rawdev_obj_t context) > > { > >- RTE_SET_USED(dev); > >- RTE_SET_USED(buffers); > >- RTE_SET_USED(count); > >- RTE_SET_USED(context); > >+ /* Not FIFO. Just for test memory read. */ > >+ struct ntb_hw *hw =3D dev->dev_private; > >+ uint64_t size; > >+ unsigned int i; > >+ > >+ size =3D (uint64_t)context; > > > >+ for (i =3D 0; i < count; i++) > >+ rte_memcpy(buffers[i]->buf_addr, hw->mz[i]->addr, size); > > return 0; > > } > > > >diff --git a/examples/Makefile b/examples/Makefile index > >7562424d9..de11dd487 100644 > >--- a/examples/Makefile > >+++ b/examples/Makefile > >@@ -53,6 +53,7 @@ DIRS-y +=3D link_status_interrupt > > DIRS-$(CONFIG_RTE_LIBRTE_LPM) +=3D load_balancer DIRS-y +=3D > >multi_process DIRS-y +=3D netmap_compat/bridge > >+DIRS-y +=3D ntb > > DIRS-$(CONFIG_RTE_LIBRTE_REORDER) +=3D packet_ordering ifeq > >($(CONFIG_RTE_ARCH_X86_64),y) DIRS-y +=3D performance-thread diff --git > >a/examples/meson.build b/examples/meson.build index > >de35656d4..dda4a07a8 100644 > >--- a/examples/meson.build > >+++ b/examples/meson.build > >@@ -25,16 +25,17 @@ all_examples =3D [ > > 'l3fwd-acl', 'l3fwd-power', > > 'l3fwd-vf', 'link_status_interrupt', > > 'load_balancer', 'multi_process', > >- 'netmap_compat', 'packet_ordering', > >- 'performance-thread', 'ptpclient', > >- 'qos_meter', 'qos_sched', > >- 'quota_watermark', 'rxtx_callbacks', > >- 'server_node_efd', 'service_cores', > >- 'skeleton', 'tep_termination', > >- 'timer', 'vdpa', > >- 'vhost', 'vhost_crypto', > >- 'vhost_scsi', 'vm_power_manager', > >- 'vmdq', 'vmdq_dcb', > >+ 'netmap_compat', 'ntb', > >+ 'packet_ordering', 'performance-thread', > >+ 'ptpclient', 'qos_meter', > >+ 'qos_sched', 'quota_watermark', > >+ 'rxtx_callbacks', 'server_node_efd', > >+ 'service_cores', 'skeleton', > >+ 'tep_termination', 'timer', > >+ 'vdpa', 'vhost', > >+ 'vhost_crypto', 'vhost_scsi', > >+ 'vm_power_manager', 'vmdq', > >+ 'vmdq_dcb', > > ] > > # install all example code on install - irrespective of whether the > >example in # question is to be built as part of this build or not. > >diff --git a/examples/ntb/Makefile b/examples/ntb/Makefile new file > >mode 100644 index 000000000..5ddd9b95f > >--- /dev/null > >+++ b/examples/ntb/Makefile > >@@ -0,0 +1,68 @@ > >+# SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2019 Intel > >+Corporation > >+ > >+# binary name > >+APP =3D ntb_fwd > >+ > >+# all source are stored in SRCS-y > >+SRCS-y :=3D ntb_fwd.c > >+ > >+# Build using pkg-config variables if possible $(shell pkg-config > >+--exists libdpdk) ifeq ($(.SHELLSTATUS),0) > >+ > >+all: shared > >+.PHONY: shared static > >+shared: build/$(APP)-shared > >+ ln -sf $(APP)-shared build/$(APP) > >+static: build/$(APP)-static > >+ ln -sf $(APP)-static build/$(APP) > >+ > >+CFLAGS +=3D -D_FILE_OFFSET_BITS=3D64 > >+LDFLAGS +=3D -pthread > >+ > >+PC_FILE :=3D $(shell pkg-config --path libdpdk) CFLAGS +=3D -O3 $(shell > >+pkg-config --cflags libdpdk) LDFLAGS_SHARED =3D $(shell pkg-config > >+--libs libdpdk) LDFLAGS_STATIC =3D -Wl,-Bstatic $(shell pkg-config > >+--static --libs libdpdk) > >+ > >+build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build > >+ $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) > >+ > >+build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build > >+ $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) > >+ > >+build: > >+ @mkdir -p $@ > >+ > >+.PHONY: clean > >+clean: > >+ rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared > >+ rmdir --ignore-fail-on-non-empty build > >+ > >+else # Build using legacy build system > >+ > >+ifeq ($(RTE_SDK),) > >+$(error "Please define RTE_SDK environment variable") endif > >+ > >+# Default target, can be overridden by command line or environment > >+RTE_TARGET ?=3D x86_64-native-linuxapp-gcc > >+ > >+include $(RTE_SDK)/mk/rte.vars.mk > >+ > >+ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) > >+$(info This application can only operate in a linuxapp environment, \ > >+please change the definition of the RTE_TARGET environment variable) > >+all: > >+else > >+ > >+CFLAGS +=3D -D_FILE_OFFSET_BITS=3D64 > >+CFLAGS +=3D -O2 > >+CFLAGS +=3D $(WERROR_FLAGS) > >+CFLAGS +=3D -DALLOW_EXPERIMENTAL_API > >+ > >+include $(RTE_SDK)/mk/rte.extapp.mk > >+ > >+endif > >+endif > >diff --git a/examples/ntb/meson.build b/examples/ntb/meson.build new > >file mode 100644 index 000000000..9a6288f4f > >--- /dev/null > >+++ b/examples/ntb/meson.build > >@@ -0,0 +1,16 @@ > >+# SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2019 Intel > >+Corporation > >+ > >+# meson file, for building this example as part of a main DPDK build. > >+# > >+# To build this example as a standalone application with an > >+already-installed # DPDK instance, use 'make' > >+ > >+if host_machine.system() !=3D 'linux' > >+ build =3D false > >+endif > >+deps +=3D 'rawdev' > >+cflags +=3D ['-D_FILE_OFFSET_BITS=3D64'] > >+sources =3D files( > >+ 'ntb_fwd.c' > >+) > >diff --git a/examples/ntb/ntb_fwd.c b/examples/ntb/ntb_fwd.c new file > >mode 100644 index 000000000..7835d817a > >--- /dev/null > >+++ b/examples/ntb/ntb_fwd.c > >@@ -0,0 +1,364 @@ > >+/* SPDX-License-Identifier: BSD-3-Clause > >+ * Copyright(c) 2019 Intel Corporation */ #include > >+#include #include #include #include > >+ #include > >+ > >+#include > >+#include > >+#include > >+#include > >+#include > >+#include > >+ > >+static uint64_t max_file_size =3D 0x400000; static uint8_t interactive = =3D > >+1; static uint16_t dev_id; > >+ > >+/* *** Help command with introduction. *** */ struct cmd_help_result { > >+ cmdline_fixed_string_t help; > >+}; > >+ > >+static void cmd_help_parsed(__attribute__((unused)) void *parsed_result= , > >+ struct cmdline *cl, > >+ __attribute__((unused)) void *data) { > >+ cmdline_printf( > >+ cl, > >+ "\n" > >+ "The following commands are currently available:\n\n" > >+ "Control:\n" > >+ " quit :" > >+ " Quit the application.\n" > >+ "\nFile transmit:\n" > >+ " send [path] :" > >+ " Send [path] file. (No more than %lu)\n" > >+ " recv [path] :" > >+ " Receive file to [path]. Make sure sending is done" > >+ " on the other side.\n", > >+ max_file_size > >+ ); > >+ > >+} > >+ > >+cmdline_parse_token_string_t cmd_help_help =3D > >+ TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); > >+ > >+cmdline_parse_inst_t cmd_help =3D { > >+ .f =3D cmd_help_parsed, > >+ .data =3D NULL, > >+ .help_str =3D "show help", > >+ .tokens =3D { > >+ (void *)&cmd_help_help, > >+ NULL, > >+ }, > >+}; > >+ > >+/* *** QUIT *** */ > >+struct cmd_quit_result { > >+ cmdline_fixed_string_t quit; > >+}; > >+ > >+static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result= , > >+ struct cmdline *cl, > >+ __attribute__((unused)) void *data) { > >+ /* Stop traffic and Close port. */ > >+ rte_rawdev_stop(dev_id); > >+ rte_rawdev_close(dev_id); > >+ > >+ cmdline_quit(cl); > >+} > >+ > >+cmdline_parse_token_string_t cmd_quit_quit =3D > >+ TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, > "quit"); > >+ > >+cmdline_parse_inst_t cmd_quit =3D { > >+ .f =3D cmd_quit_parsed, > >+ .data =3D NULL, > >+ .help_str =3D "exit application", > >+ .tokens =3D { > >+ (void *)&cmd_quit_quit, > >+ NULL, > >+ }, > >+}; > >+ > >+/* *** SEND FILE PARAMETERS *** */ > >+struct cmd_sendfile_result { > >+ cmdline_fixed_string_t send_string; > >+ char filepath[]; > >+}; > >+ > >+static void > >+cmd_sendfile_parsed(void *parsed_result, > >+ __attribute__((unused)) struct cmdline *cl, > >+ __attribute__((unused)) void *data) { > >+ struct cmd_sendfile_result *res =3D parsed_result; > >+ struct rte_rawdev_buf *pkts_send[1]; > >+ uint64_t rsize, size, link; > >+ char *filepath; > >+ uint8_t *buff; > >+ uint32_t val; > >+ FILE *file; > >+ > >+ if (!rte_rawdevs[dev_id].started) > >+ printf("Device needs to be up first. Try later.\n"); >=20 > I think we can directly return here when the device is not started, inste= ad of > continuing the execution. >=20 > >+ > >+ rte_rawdev_get_attr(dev_id, "link_status", &link); > >+ if (!link) > >+ printf("Link is not up, cannot send file.\n"); >=20 > return if link is down. >=20 > >+ > >+ filepath =3D strdup(res->filepath); > >+ if (filepath =3D=3D NULL) { > >+ printf("Fail to get filepath.\n"); > >+ return; > >+ } > >+ > >+ file =3D fopen(filepath, "r"); >=20 > Actually I was thinking why we need the filepath, why not just >=20 > file =3D fopen(res->filepath, "r") >=20 > Then we don't need to handle filepath free at all. >=20 > >+ if (!file) { >=20 > style 1.8.1 >=20 > >+ printf("Fail to open the file.\n"); >=20 > Need to free filepath in this error handling. >=20 > >+ return; > >+ } > >+ > >+ fseek(file, 0, SEEK_END); > >+ size =3D ftell(file); > >+ fseek(file, 0, SEEK_SET); > >+ > >+ /** > >+ * No FIFO now. Only test memory. Limit sending file > >+ * size <=3D max_file_size. > >+ */ > >+ if (size > max_file_size) > >+ size =3D max_file_size; >=20 > It's better to give the user some reminder info about the max size limiti= on, > rather than truncate the file silently. >=20 > >+ > >+ buff =3D (uint8_t *)malloc(size); > >+ rsize =3D fread(buff, size, 1, file); > >+ if (rsize !=3D 1) { > >+ printf("Fail to read file.\n"); > >+ fclose(file); >=20 > Need to free filepath and buff. >=20 > >+ return; > >+ } > >+ > >+ /* Tell remote about the file size. */ > >+ val =3D size >> 32; > >+ rte_rawdev_set_attr(dev_id, "spad14", val); > >+ val =3D size; > >+ rte_rawdev_set_attr(dev_id, "spad15", val); > >+ > >+ pkts_send[0] =3D (struct rte_rawdev_buf *)malloc > >+ (sizeof(struct rte_rawdev_buf)); > >+ pkts_send[0]->buf_addr =3D buff; > >+ rte_rawdev_enqueue_buffers(dev_id, pkts_send, 1, (void *)size); >=20 > May need to check the return value. >=20 > >+ printf("Done sending file.\n"); > >+ > >+ fclose(file); > >+ free((void *)filepath); >=20 > Need to free allocated pkts_send[0] and buff. >=20 > >+} > >+ > >+cmdline_parse_token_string_t cmd_send_file_send =3D > >+ TOKEN_STRING_INITIALIZER(struct cmd_sendfile_result, send_string, > >+ "send"); > >+cmdline_parse_token_string_t cmd_send_file_filepath =3D > >+ TOKEN_STRING_INITIALIZER(struct cmd_sendfile_result, filepath, NULL); > >+ > >+ > >+cmdline_parse_inst_t cmd_send_file =3D { > >+ .f =3D cmd_sendfile_parsed, > >+ .data =3D NULL, > >+ .help_str =3D "send ", > >+ .tokens =3D { > >+ (void *)&cmd_send_file_send, > >+ (void *)&cmd_send_file_filepath, > >+ NULL, > >+ }, > >+}; > >+ > >+/* *** RECEIVE FILE PARAMETERS *** */ > >+struct cmd_recvfile_result { > >+ cmdline_fixed_string_t recv_string; > >+ char filepath[]; > >+}; > >+ > >+static void > >+cmd_recvfile_parsed(void *parsed_result, > >+ __attribute__((unused)) struct cmdline *cl, > >+ __attribute__((unused)) void *data) { > >+ struct cmd_sendfile_result *res =3D parsed_result; > >+ struct rte_rawdev_buf *pkts_recv[1]; > >+ uint64_t size, val; > >+ char *filepath; > >+ uint8_t *buff; > >+ FILE *file; > >+ > >+ if (!rte_rawdevs[dev_id].started) > >+ printf("Device needs to be up first. Try later.\n"); >=20 > return directly. >=20 > >+ > >+ rte_rawdev_get_attr(dev_id, "link_status", &val); > >+ if (!val) > >+ printf("Link is not up, cannot receive file.\n"); >=20 > return directly. >=20 > >+ > >+ filepath =3D strdup(res->filepath); > >+ if (filepath =3D=3D NULL) { > >+ printf("Fail to get filepath.\n"); > >+ return; > >+ } > >+ > >+ file =3D fopen(filepath, "w"); > >+ if (!file) { >=20 > style 1.8.1 >=20 > >+ printf("Fail to open the file.\n"); > >+ return; > >+ } > >+ > >+ rte_rawdev_get_attr(dev_id, "spad14", &val); > >+ size =3D val << 32; > >+ rte_rawdev_get_attr(dev_id, "spad15", &val); > >+ size |=3D val; > >+ > >+ buff =3D (uint8_t *)malloc(size); > >+ pkts_recv[0] =3D (struct rte_rawdev_buf *)malloc > >+ (sizeof(struct rte_rawdev_buf)); > >+ pkts_recv[0]->buf_addr =3D buff; > >+ > >+ rte_rawdev_dequeue_buffers(dev_id, pkts_recv, 1, (void *)size); > >+ > >+ fwrite(buff, size, 1, file); > >+ printf("Done receiving to file.\n"); > >+ > >+ fclose(file); > >+ free((void *)filepath); >=20 > free buff and pkts_recv[0] as well. >=20 > I noticed that there are two allocations, one for pkts_recv[0] and anothe= r for > pkts_recv[0]->buf_addr, How about we declare >=20 > struct rte_rawdev_buf pkts_recv[1]; >=20 > and allocate memory for its buf_addr >=20 > pkts_recv[0].buf_addr =3D malloc(size); >=20 > then we call >=20 > rte_rawdev_dequeue_buffers(dev_id, &pkts_recv, 1, (void *)size); >=20 > After that, we just need to free once. >=20 > free(pkts_recv[0].buf_addr); >=20 >=20 > >+} > >+ > >+cmdline_parse_token_string_t cmd_recv_file_recv =3D > >+ TOKEN_STRING_INITIALIZER(struct cmd_recvfile_result, recv_string, > >+ "recv"); > >+cmdline_parse_token_string_t cmd_recv_file_filepath =3D > >+ TOKEN_STRING_INITIALIZER(struct cmd_recvfile_result, filepath, NULL); > >+ > >+ > >+cmdline_parse_inst_t cmd_recv_file =3D { > >+ .f =3D cmd_recvfile_parsed, > >+ .data =3D NULL, > >+ .help_str =3D "recv ", > >+ .tokens =3D { > >+ (void *)&cmd_recv_file_recv, > >+ (void *)&cmd_recv_file_filepath, > >+ NULL, > >+ }, > >+}; > >+ > >+/* list of instructions */ > >+cmdline_parse_ctx_t main_ctx[] =3D { > >+ (cmdline_parse_inst_t *)&cmd_help, > >+ (cmdline_parse_inst_t *)&cmd_send_file, > >+ (cmdline_parse_inst_t *)&cmd_recv_file, > >+ (cmdline_parse_inst_t *)&cmd_quit, > >+ NULL, > >+}; > >+ > >+/* prompt function, called from main on MASTER lcore */ static void > >+prompt(void) > >+{ > >+ struct cmdline *cl; > >+ > >+ cl =3D cmdline_stdin_new(main_ctx, "ntb> "); > >+ if (cl =3D=3D NULL) > >+ return; > >+ > >+ cmdline_interact(cl); > >+ cmdline_stdin_exit(cl); > >+} > >+ > >+static void > >+signal_handler(int signum) > >+{ > >+ if (signum =3D=3D SIGINT || signum =3D=3D SIGTERM) { > >+ printf("\nSignal %d received, preparing to exit...\n", signum); > >+ signal(signum, SIG_DFL); > >+ kill(getpid(), signum); > >+ } > >+} > >+ > >+static void > >+ntb_usage(const char *prgname) > >+{ > >+ printf("%s [EAL options] -- [options]\n" > >+ "-i : run in interactive mode (default value is 1)\n", > >+ prgname); > >+} > >+ > >+static int > >+parse_args(int argc, char **argv) > >+{ > >+ char *prgname =3D argv[0], **argvopt =3D argv; > >+ int opt, ret; > >+ > >+ /* Only support interactive mode to send/recv file first. */ > >+ while ((opt =3D getopt(argc, argvopt, "i")) !=3D EOF) { > >+ switch (opt) { > >+ case 'i': > >+ printf("Interactive-mode selected\n"); > >+ interactive =3D 1; > >+ break; > >+ > >+ default: > >+ ntb_usage(prgname); > >+ return -1; > >+ } > >+ } > >+ > >+ if (optind >=3D 0) > >+ argv[optind-1] =3D prgname; > >+ > >+ ret =3D optind-1; > >+ optind =3D 1; /* reset getopt lib */ > >+ return ret; > >+} > >+ > >+int > >+main(int argc, char **argv) > >+{ > >+ int ret, i; > >+ > >+ signal(SIGINT, signal_handler); > >+ signal(SIGTERM, signal_handler); > >+ > >+ ret =3D rte_eal_init(argc, argv); > >+ if (ret < 0) > >+ rte_exit(EXIT_FAILURE, "Error with EAL initialization.\n"); > >+ > >+ /* Find 1st ntb rawdev. */ > >+ for (i =3D 0; i < RTE_RAWDEV_MAX_DEVS; i++) > >+ if (rte_rawdevs[i].driver_name && > >+ (strncmp(rte_rawdevs[i].driver_name, "raw_ntb", 7) =3D=3D 0) && >=20 > Use Macro for the 7. >=20 > >+ (rte_rawdevs[i].attached =3D=3D 1)) > >+ break; > >+ > >+ if (i =3D=3D RTE_RAWDEV_MAX_DEVS) > >+ rte_exit(EXIT_FAILURE, "Cannot find any ntb device.\n"); > >+ > >+ dev_id =3D i; > >+ > >+ argc -=3D ret; > >+ argv +=3D ret; > >+ > >+ ret =3D parse_args(argc, argv); > >+ if (ret < 0) > >+ rte_exit(EXIT_FAILURE, "Invalid arguments\n"); > >+ > >+ rte_rawdev_start(dev_id); > >+ > >+ if (interactive) { > >+ sleep(1); > >+ prompt(); > >+ } > >+ > >+ return 0; > >+} > >-- > >2.17.1 > >