[dpdk-dev,v3,3/3] app/testpmd: add port reset command into testpmd

Message ID 1490688547-4831-4-git-send-email-wei.zhao1@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Zhao1, Wei March 28, 2017, 8:09 a.m. UTC
  Add port reset command into testpmd project,
it is the interface for user to reset port.
And also it is not limit to be used only in vf reset,
but also for pf port reset.But this patch set only
realted to vf reset feature.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c | 17 ++++++++++----
 app/test-pmd/testpmd.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/testpmd.h |  1 +
 3 files changed, 77 insertions(+), 4 deletions(-)
  

Comments

Jingjing Wu March 30, 2017, 8:55 a.m. UTC | #1
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> Sent: Tuesday, March 28, 2017 4:09 PM
> To: dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>
> Subject: [dpdk-dev] [PATCH v3 3/3] app/testpmd: add port reset command into
> testpmd
> 
> Add port reset command into testpmd project, it is the interface for user to
> reset port.
> And also it is not limit to be used only in vf reset, but also for pf port reset.But
> this patch set only realted to vf reset feature.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> ---
>  app/test-pmd/cmdline.c | 17 ++++++++++----  app/test-pmd/testpmd.c | 63
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  app/test-pmd/testpmd.h |  1 +
>  3 files changed, 77 insertions(+), 4 deletions(-)
> 
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> 47f935d..6cbdcc8 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -599,6 +599,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>  			"port close (port_id|all)\n"
>  			"    Close all ports or port_id.\n\n"
> 
> +			"port reset (port_id|all)\n"
> +			"    Reset all ports or port_id.\n\n"
> +
>  			"port attach (ident)\n"
>  			"    Attach physical or virtual dev by pci address or
> virtual device name\n\n"
> 
> @@ -909,6 +912,8 @@ static void cmd_operate_port_parsed(void
> *parsed_result,
>  		stop_port(RTE_PORT_ALL);
>  	else if (!strcmp(res->name, "close"))
>  		close_port(RTE_PORT_ALL);
> +	else if (!strcmp(res->name, "reset"))
> +		reset_port(RTE_PORT_ALL);
>  	else
>  		printf("Unknown parameter\n");
>  }
> @@ -918,14 +923,15 @@ cmdline_parse_token_string_t
> cmd_operate_port_all_cmd =
>  								"port");
>  cmdline_parse_token_string_t cmd_operate_port_all_port =
>  	TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, name,
> -						"start#stop#close");
> +						"start#stop#close#reset");
>  cmdline_parse_token_string_t cmd_operate_port_all_all =
>  	TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, value,
> "all");
> 
>  cmdline_parse_inst_t cmd_operate_port = {
>  	.f = cmd_operate_port_parsed,
>  	.data = NULL,
> -	.help_str = "port start|stop|close all: Start/Stop/Close all ports",
> +	.help_str = "port start|stop|close|reset all: Start/Stop/Close/"
> +			"Reset all ports",
>  	.tokens = {
>  		(void *)&cmd_operate_port_all_cmd,
>  		(void *)&cmd_operate_port_all_port,
> @@ -953,6 +959,8 @@ static void cmd_operate_specific_port_parsed(void
> *parsed_result,
>  		stop_port(res->value);
>  	else if (!strcmp(res->name, "close"))
>  		close_port(res->value);
> +	else if (!strcmp(res->name, "reset"))
> +		reset_port(res->value);
>  	else
>  		printf("Unknown parameter\n");
>  }
> @@ -962,7 +970,7 @@ cmdline_parse_token_string_t
> cmd_operate_specific_port_cmd =
>  							keyword, "port");
>  cmdline_parse_token_string_t cmd_operate_specific_port_port =
>  	TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result,
> -						name, "start#stop#close");
> +						name,
> "start#stop#close#reset");
>  cmdline_parse_token_num_t cmd_operate_specific_port_id =
>  	TOKEN_NUM_INITIALIZER(struct cmd_operate_specific_port_result,
>  							value, UINT8);
> @@ -970,7 +978,8 @@ cmdline_parse_token_num_t
> cmd_operate_specific_port_id =  cmdline_parse_inst_t
> cmd_operate_specific_port = {
>  	.f = cmd_operate_specific_port_parsed,
>  	.data = NULL,
> -	.help_str = "port start|stop|close <port_id>: Start/Stop/Close port_id",
> +	.help_str = "port start|stop|close|reset <port_id>: Start/Stop/Close/"
> +			"Reset port_id",
>  	.tokens = {
>  		(void *)&cmd_operate_specific_port_cmd,
>  		(void *)&cmd_operate_specific_port_port,
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> 484c19b..a053562 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -137,6 +137,7 @@ portid_t  nb_fwd_ports;  /**< Number of forwarding
> ports. */
> 
>  unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids configuration.
> */
>  portid_t fwd_ports_ids[RTE_MAX_ETHPORTS];      /**< Port ids configuration.
> */
> +volatile char reset_ports[RTE_MAX_ETHPORTS] = {0};  /**< Portr reset
> +falg. */
> 
>  struct fwd_stream **fwd_streams; /**< For each RX queue of each port. */
>  streamid_t nb_fwd_streams;       /**< Is equal to (nb_ports * nb_rxq). */
> @@ -1305,6 +1306,17 @@ port_is_closed(portid_t port_id)
>  	return 1;
>  }
> 
> +static void
> +reset_event_callback(uint8_t port_id, enum rte_eth_event_type type,
> +void *param) {
> +	RTE_SET_USED(param);
> +
> +	printf("Event type: %s on port %d\n",
> +		type == RTE_ETH_EVENT_INTR_RESET ? "RESET interrupt" :
> +		"unknown event", port_id);
> +	reset_ports[port_id] = 1;
It's better to add rte_wmb() after change the reset_ports.
> +}
> +
>  int
>  start_port(portid_t pid)
>  {
> @@ -1350,6 +1362,10 @@ start_port(portid_t pid)
>  				return -1;
>  			}
>  		}
> +
> +		/* register reset interrupt callback */
> +		rte_eth_dev_callback_register(pi,
> RTE_ETH_EVENT_INTR_RESET,
> +			reset_event_callback, NULL);
>  		if (port->need_reconfig_queues > 0) {
>  			port->need_reconfig_queues = 0;
>  			/* setup tx queues */
> @@ -1559,6 +1575,53 @@ close_port(portid_t pid)  }
> 
>  void
> +reset_port(portid_t pid)
> +{
> +	portid_t pi;
> +	struct rte_port *port;
> +
> +	if (port_id_is_invalid(pid, ENABLED_WARN))
> +		return;
> +
> +	printf("Reset ports...\n");
> +
> +	FOREACH_PORT(pi, ports) {
> +		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
> +			continue;
> +
> +		if (port_is_forwarding(pi) != 0 && test_done == 0) {
> +			printf("Please remove port %d from forwarding "
> +					"configuration.\n", pi);
> +			continue;
> +		}
> +
> +		if (port_is_bonding_slave(pi)) {
> +			printf("Please remove port %d from "
> +					"bonded device.\n", pi);
> +			continue;
> +		}
> +
> +		if (!reset_ports[pi]) {
> +			printf("vf must get reset port %d info from "
> +					"pf before reset.\n", pi);
> +			continue;
> +		}
> +
> +		port = &ports[pi];
> +		if (rte_atomic16_cmpset(&(port->port_status),
> +			RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 1) {
> +			printf("Port %d is not stopped\n", pi);
> +			continue;
> +		}
> +
> +		rte_eth_dev_reset(pi);
> +		reset_ports[pi] = 0;
It's better to add rte_wmb() after change the reset_ports.

> +	}
> +
> +	printf("Done\n");
> +}
> +
> +void
>  attach_port(char *identifier)
>  {
>  	portid_t pi = 0;
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index
> 8cf2860..0c7e44c 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -586,6 +586,7 @@ int init_port_dcb_config(portid_t pid, enum
> dcb_mode_enable dcb_mode,  int start_port(portid_t pid);  void
> stop_port(portid_t pid);  void close_port(portid_t pid);
> +void reset_port(portid_t pid);
>  void attach_port(char *identifier);
>  void detach_port(uint8_t port_id);
>  int all_ports_stopped(void);
> --
> 2.9.3
  
Jingjing Wu March 30, 2017, 8:57 a.m. UTC | #2
> -----Original Message-----
> From: Wu, Jingjing
> Sent: Thursday, March 30, 2017 4:55 PM
> To: 'Wei Zhao' <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v3 3/3] app/testpmd: add port reset command
> into testpmd
> 
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > Sent: Tuesday, March 28, 2017 4:09 PM
> > To: dev@dpdk.org
> > Cc: Zhao1, Wei <wei.zhao1@intel.com>; Lu, Wenzhuo
> > <wenzhuo.lu@intel.com>
> > Subject: [dpdk-dev] [PATCH v3 3/3] app/testpmd: add port reset command
> > into testpmd
> >
> > Add port reset command into testpmd project, it is the interface for
> > user to reset port.
> > And also it is not limit to be used only in vf reset, but also for pf
> > port reset.But this patch set only realted to vf reset feature.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > ---
> >  app/test-pmd/cmdline.c | 17 ++++++++++----  app/test-pmd/testpmd.c |
> > 63
> > ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  app/test-pmd/testpmd.h |  1 +
> >  3 files changed, 77 insertions(+), 4 deletions(-)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > 47f935d..6cbdcc8 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -599,6 +599,9 @@ static void cmd_help_long_parsed(void
> *parsed_result,
> >  			"port close (port_id|all)\n"
> >  			"    Close all ports or port_id.\n\n"
> >
> > +			"port reset (port_id|all)\n"
> > +			"    Reset all ports or port_id.\n\n"
> > +
> >  			"port attach (ident)\n"
> >  			"    Attach physical or virtual dev by pci address or
> > virtual device name\n\n"
> >
> > @@ -909,6 +912,8 @@ static void cmd_operate_port_parsed(void
> > *parsed_result,
> >  		stop_port(RTE_PORT_ALL);
> >  	else if (!strcmp(res->name, "close"))
> >  		close_port(RTE_PORT_ALL);
> > +	else if (!strcmp(res->name, "reset"))
> > +		reset_port(RTE_PORT_ALL);
> >  	else
> >  		printf("Unknown parameter\n");
> >  }
> > @@ -918,14 +923,15 @@ cmdline_parse_token_string_t
> > cmd_operate_port_all_cmd =
> >  								"port");
> >  cmdline_parse_token_string_t cmd_operate_port_all_port =
> >  	TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, name,
> > -						"start#stop#close");
> > +						"start#stop#close#reset");
> >  cmdline_parse_token_string_t cmd_operate_port_all_all =
> >  	TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, value,
> > "all");
> >
> >  cmdline_parse_inst_t cmd_operate_port = {
> >  	.f = cmd_operate_port_parsed,
> >  	.data = NULL,
> > -	.help_str = "port start|stop|close all: Start/Stop/Close all ports",
> > +	.help_str = "port start|stop|close|reset all: Start/Stop/Close/"
> > +			"Reset all ports",
> >  	.tokens = {
> >  		(void *)&cmd_operate_port_all_cmd,
> >  		(void *)&cmd_operate_port_all_port, @@ -953,6 +959,8 @@
> static void
> > cmd_operate_specific_port_parsed(void
> > *parsed_result,
> >  		stop_port(res->value);
> >  	else if (!strcmp(res->name, "close"))
> >  		close_port(res->value);
> > +	else if (!strcmp(res->name, "reset"))
> > +		reset_port(res->value);
> >  	else
> >  		printf("Unknown parameter\n");
> >  }
> > @@ -962,7 +970,7 @@ cmdline_parse_token_string_t
> > cmd_operate_specific_port_cmd =
> >  							keyword, "port");
> >  cmdline_parse_token_string_t cmd_operate_specific_port_port =
> >  	TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result,
> > -						name, "start#stop#close");
> > +						name,
> > "start#stop#close#reset");
> >  cmdline_parse_token_num_t cmd_operate_specific_port_id =
> >  	TOKEN_NUM_INITIALIZER(struct cmd_operate_specific_port_result,
> >  							value, UINT8);
> > @@ -970,7 +978,8 @@ cmdline_parse_token_num_t
> > cmd_operate_specific_port_id =  cmdline_parse_inst_t
> > cmd_operate_specific_port = {
> >  	.f = cmd_operate_specific_port_parsed,
> >  	.data = NULL,
> > -	.help_str = "port start|stop|close <port_id>: Start/Stop/Close port_id",
> > +	.help_str = "port start|stop|close|reset <port_id>: Start/Stop/Close/"
> > +			"Reset port_id",
> >  	.tokens = {
> >  		(void *)&cmd_operate_specific_port_cmd,
> >  		(void *)&cmd_operate_specific_port_port,
> > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> > 484c19b..a053562 100644
> > --- a/app/test-pmd/testpmd.c
> > +++ b/app/test-pmd/testpmd.c
> > @@ -137,6 +137,7 @@ portid_t  nb_fwd_ports;  /**< Number of forwarding
> > ports. */
> >
> >  unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids
> configuration.
> > */
> >  portid_t fwd_ports_ids[RTE_MAX_ETHPORTS];      /**< Port ids configuration.
> > */
> > +volatile char reset_ports[RTE_MAX_ETHPORTS] = {0};  /**< Portr reset
> > +falg. */
Typo: Portr->port, and falg->flag
  
Zhao1, Wei March 30, 2017, 8:58 a.m. UTC | #3
HI, jingjing
    Ok, I will commit a v4 version.

> -----Original Message-----
> From: Wu, Jingjing
> Sent: Thursday, March 30, 2017 4:55 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v3 3/3] app/testpmd: add port reset
> command into testpmd
> 
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > Sent: Tuesday, March 28, 2017 4:09 PM
> > To: dev@dpdk.org
> > Cc: Zhao1, Wei <wei.zhao1@intel.com>; Lu, Wenzhuo
> > <wenzhuo.lu@intel.com>
> > Subject: [dpdk-dev] [PATCH v3 3/3] app/testpmd: add port reset command
> > into testpmd
> >
> > Add port reset command into testpmd project, it is the interface for
> > user to reset port.
> > And also it is not limit to be used only in vf reset, but also for pf
> > port reset.But this patch set only realted to vf reset feature.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > ---
> >  app/test-pmd/cmdline.c | 17 ++++++++++----  app/test-pmd/testpmd.c |
> > 63
> > ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  app/test-pmd/testpmd.h |  1 +
> >  3 files changed, 77 insertions(+), 4 deletions(-)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > 47f935d..6cbdcc8 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -599,6 +599,9 @@ static void cmd_help_long_parsed(void
> *parsed_result,
> >  			"port close (port_id|all)\n"
> >  			"    Close all ports or port_id.\n\n"
> >
> > +			"port reset (port_id|all)\n"
> > +			"    Reset all ports or port_id.\n\n"
> > +
> >  			"port attach (ident)\n"
> >  			"    Attach physical or virtual dev by pci address or
> > virtual device name\n\n"
> >
> > @@ -909,6 +912,8 @@ static void cmd_operate_port_parsed(void
> > *parsed_result,
> >  		stop_port(RTE_PORT_ALL);
> >  	else if (!strcmp(res->name, "close"))
> >  		close_port(RTE_PORT_ALL);
> > +	else if (!strcmp(res->name, "reset"))
> > +		reset_port(RTE_PORT_ALL);
> >  	else
> >  		printf("Unknown parameter\n");
> >  }
> > @@ -918,14 +923,15 @@ cmdline_parse_token_string_t
> > cmd_operate_port_all_cmd =
> >  								"port");
> >  cmdline_parse_token_string_t cmd_operate_port_all_port =
> >  	TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, name,
> > -						"start#stop#close");
> > +						"start#stop#close#reset");
> >  cmdline_parse_token_string_t cmd_operate_port_all_all =
> >  	TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, value,
> > "all");
> >
> >  cmdline_parse_inst_t cmd_operate_port = {
> >  	.f = cmd_operate_port_parsed,
> >  	.data = NULL,
> > -	.help_str = "port start|stop|close all: Start/Stop/Close all ports",
> > +	.help_str = "port start|stop|close|reset all: Start/Stop/Close/"
> > +			"Reset all ports",
> >  	.tokens = {
> >  		(void *)&cmd_operate_port_all_cmd,
> >  		(void *)&cmd_operate_port_all_port, @@ -953,6 +959,8 @@
> static void
> > cmd_operate_specific_port_parsed(void
> > *parsed_result,
> >  		stop_port(res->value);
> >  	else if (!strcmp(res->name, "close"))
> >  		close_port(res->value);
> > +	else if (!strcmp(res->name, "reset"))
> > +		reset_port(res->value);
> >  	else
> >  		printf("Unknown parameter\n");
> >  }
> > @@ -962,7 +970,7 @@ cmdline_parse_token_string_t
> > cmd_operate_specific_port_cmd =
> >  							keyword, "port");
> >  cmdline_parse_token_string_t cmd_operate_specific_port_port =
> >  	TOKEN_STRING_INITIALIZER(struct
> cmd_operate_specific_port_result,
> > -						name, "start#stop#close");
> > +						name,
> > "start#stop#close#reset");
> >  cmdline_parse_token_num_t cmd_operate_specific_port_id =
> >  	TOKEN_NUM_INITIALIZER(struct cmd_operate_specific_port_result,
> >  							value, UINT8);
> > @@ -970,7 +978,8 @@ cmdline_parse_token_num_t
> > cmd_operate_specific_port_id =  cmdline_parse_inst_t
> > cmd_operate_specific_port = {
> >  	.f = cmd_operate_specific_port_parsed,
> >  	.data = NULL,
> > -	.help_str = "port start|stop|close <port_id>: Start/Stop/Close
> port_id",
> > +	.help_str = "port start|stop|close|reset <port_id>:
> Start/Stop/Close/"
> > +			"Reset port_id",
> >  	.tokens = {
> >  		(void *)&cmd_operate_specific_port_cmd,
> >  		(void *)&cmd_operate_specific_port_port,
> > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> > 484c19b..a053562 100644
> > --- a/app/test-pmd/testpmd.c
> > +++ b/app/test-pmd/testpmd.c
> > @@ -137,6 +137,7 @@ portid_t  nb_fwd_ports;  /**< Number of
> forwarding
> > ports. */
> >
> >  unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids
> configuration.
> > */
> >  portid_t fwd_ports_ids[RTE_MAX_ETHPORTS];      /**< Port ids
> configuration.
> > */
> > +volatile char reset_ports[RTE_MAX_ETHPORTS] = {0};  /**< Portr reset
> > +falg. */
> >
> >  struct fwd_stream **fwd_streams; /**< For each RX queue of each port.
> */
> >  streamid_t nb_fwd_streams;       /**< Is equal to (nb_ports * nb_rxq). */
> > @@ -1305,6 +1306,17 @@ port_is_closed(portid_t port_id)
> >  	return 1;
> >  }
> >
> > +static void
> > +reset_event_callback(uint8_t port_id, enum rte_eth_event_type type,
> > +void *param) {
> > +	RTE_SET_USED(param);
> > +
> > +	printf("Event type: %s on port %d\n",
> > +		type == RTE_ETH_EVENT_INTR_RESET ? "RESET interrupt" :
> > +		"unknown event", port_id);
> > +	reset_ports[port_id] = 1;
> It's better to add rte_wmb() after change the reset_ports.
> > +}
> > +
> >  int
> >  start_port(portid_t pid)
> >  {
> > @@ -1350,6 +1362,10 @@ start_port(portid_t pid)
> >  				return -1;
> >  			}
> >  		}
> > +
> > +		/* register reset interrupt callback */
> > +		rte_eth_dev_callback_register(pi,
> > RTE_ETH_EVENT_INTR_RESET,
> > +			reset_event_callback, NULL);
> >  		if (port->need_reconfig_queues > 0) {
> >  			port->need_reconfig_queues = 0;
> >  			/* setup tx queues */
> > @@ -1559,6 +1575,53 @@ close_port(portid_t pid)  }
> >
> >  void
> > +reset_port(portid_t pid)
> > +{
> > +	portid_t pi;
> > +	struct rte_port *port;
> > +
> > +	if (port_id_is_invalid(pid, ENABLED_WARN))
> > +		return;
> > +
> > +	printf("Reset ports...\n");
> > +
> > +	FOREACH_PORT(pi, ports) {
> > +		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
> > +			continue;
> > +
> > +		if (port_is_forwarding(pi) != 0 && test_done == 0) {
> > +			printf("Please remove port %d from forwarding "
> > +					"configuration.\n", pi);
> > +			continue;
> > +		}
> > +
> > +		if (port_is_bonding_slave(pi)) {
> > +			printf("Please remove port %d from "
> > +					"bonded device.\n", pi);
> > +			continue;
> > +		}
> > +
> > +		if (!reset_ports[pi]) {
> > +			printf("vf must get reset port %d info from "
> > +					"pf before reset.\n", pi);
> > +			continue;
> > +		}
> > +
> > +		port = &ports[pi];
> > +		if (rte_atomic16_cmpset(&(port->port_status),
> > +			RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 1) {
> > +			printf("Port %d is not stopped\n", pi);
> > +			continue;
> > +		}
> > +
> > +		rte_eth_dev_reset(pi);
> > +		reset_ports[pi] = 0;
> It's better to add rte_wmb() after change the reset_ports.
> 
> > +	}
> > +
> > +	printf("Done\n");
> > +}
> > +
> > +void
> >  attach_port(char *identifier)
> >  {
> >  	portid_t pi = 0;
> > diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index
> > 8cf2860..0c7e44c 100644
> > --- a/app/test-pmd/testpmd.h
> > +++ b/app/test-pmd/testpmd.h
> > @@ -586,6 +586,7 @@ int init_port_dcb_config(portid_t pid, enum
> > dcb_mode_enable dcb_mode,  int start_port(portid_t pid);  void
> > stop_port(portid_t pid);  void close_port(portid_t pid);
> > +void reset_port(portid_t pid);
> >  void attach_port(char *identifier);
> >  void detach_port(uint8_t port_id);
> >  int all_ports_stopped(void);
> > --
> > 2.9.3
  

Patch

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 47f935d..6cbdcc8 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -599,6 +599,9 @@  static void cmd_help_long_parsed(void *parsed_result,
 			"port close (port_id|all)\n"
 			"    Close all ports or port_id.\n\n"
 
+			"port reset (port_id|all)\n"
+			"    Reset all ports or port_id.\n\n"
+
 			"port attach (ident)\n"
 			"    Attach physical or virtual dev by pci address or virtual device name\n\n"
 
@@ -909,6 +912,8 @@  static void cmd_operate_port_parsed(void *parsed_result,
 		stop_port(RTE_PORT_ALL);
 	else if (!strcmp(res->name, "close"))
 		close_port(RTE_PORT_ALL);
+	else if (!strcmp(res->name, "reset"))
+		reset_port(RTE_PORT_ALL);
 	else
 		printf("Unknown parameter\n");
 }
@@ -918,14 +923,15 @@  cmdline_parse_token_string_t cmd_operate_port_all_cmd =
 								"port");
 cmdline_parse_token_string_t cmd_operate_port_all_port =
 	TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, name,
-						"start#stop#close");
+						"start#stop#close#reset");
 cmdline_parse_token_string_t cmd_operate_port_all_all =
 	TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, value, "all");
 
 cmdline_parse_inst_t cmd_operate_port = {
 	.f = cmd_operate_port_parsed,
 	.data = NULL,
-	.help_str = "port start|stop|close all: Start/Stop/Close all ports",
+	.help_str = "port start|stop|close|reset all: Start/Stop/Close/"
+			"Reset all ports",
 	.tokens = {
 		(void *)&cmd_operate_port_all_cmd,
 		(void *)&cmd_operate_port_all_port,
@@ -953,6 +959,8 @@  static void cmd_operate_specific_port_parsed(void *parsed_result,
 		stop_port(res->value);
 	else if (!strcmp(res->name, "close"))
 		close_port(res->value);
+	else if (!strcmp(res->name, "reset"))
+		reset_port(res->value);
 	else
 		printf("Unknown parameter\n");
 }
@@ -962,7 +970,7 @@  cmdline_parse_token_string_t cmd_operate_specific_port_cmd =
 							keyword, "port");
 cmdline_parse_token_string_t cmd_operate_specific_port_port =
 	TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result,
-						name, "start#stop#close");
+						name, "start#stop#close#reset");
 cmdline_parse_token_num_t cmd_operate_specific_port_id =
 	TOKEN_NUM_INITIALIZER(struct cmd_operate_specific_port_result,
 							value, UINT8);
@@ -970,7 +978,8 @@  cmdline_parse_token_num_t cmd_operate_specific_port_id =
 cmdline_parse_inst_t cmd_operate_specific_port = {
 	.f = cmd_operate_specific_port_parsed,
 	.data = NULL,
-	.help_str = "port start|stop|close <port_id>: Start/Stop/Close port_id",
+	.help_str = "port start|stop|close|reset <port_id>: Start/Stop/Close/"
+			"Reset port_id",
 	.tokens = {
 		(void *)&cmd_operate_specific_port_cmd,
 		(void *)&cmd_operate_specific_port_port,
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 484c19b..a053562 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -137,6 +137,7 @@  portid_t  nb_fwd_ports;  /**< Number of forwarding ports. */
 
 unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids configuration. */
 portid_t fwd_ports_ids[RTE_MAX_ETHPORTS];      /**< Port ids configuration. */
+volatile char reset_ports[RTE_MAX_ETHPORTS] = {0};  /**< Portr reset falg. */
 
 struct fwd_stream **fwd_streams; /**< For each RX queue of each port. */
 streamid_t nb_fwd_streams;       /**< Is equal to (nb_ports * nb_rxq). */
@@ -1305,6 +1306,17 @@  port_is_closed(portid_t port_id)
 	return 1;
 }
 
+static void
+reset_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param)
+{
+	RTE_SET_USED(param);
+
+	printf("Event type: %s on port %d\n",
+		type == RTE_ETH_EVENT_INTR_RESET ? "RESET interrupt" :
+		"unknown event", port_id);
+	reset_ports[port_id] = 1;
+}
+
 int
 start_port(portid_t pid)
 {
@@ -1350,6 +1362,10 @@  start_port(portid_t pid)
 				return -1;
 			}
 		}
+
+		/* register reset interrupt callback */
+		rte_eth_dev_callback_register(pi, RTE_ETH_EVENT_INTR_RESET,
+			reset_event_callback, NULL);
 		if (port->need_reconfig_queues > 0) {
 			port->need_reconfig_queues = 0;
 			/* setup tx queues */
@@ -1559,6 +1575,53 @@  close_port(portid_t pid)
 }
 
 void
+reset_port(portid_t pid)
+{
+	portid_t pi;
+	struct rte_port *port;
+
+	if (port_id_is_invalid(pid, ENABLED_WARN))
+		return;
+
+	printf("Reset ports...\n");
+
+	FOREACH_PORT(pi, ports) {
+		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
+			continue;
+
+		if (port_is_forwarding(pi) != 0 && test_done == 0) {
+			printf("Please remove port %d from forwarding "
+					"configuration.\n", pi);
+			continue;
+		}
+
+		if (port_is_bonding_slave(pi)) {
+			printf("Please remove port %d from "
+					"bonded device.\n", pi);
+			continue;
+		}
+
+		if (!reset_ports[pi]) {
+			printf("vf must get reset port %d info from "
+					"pf before reset.\n", pi);
+			continue;
+		}
+
+		port = &ports[pi];
+		if (rte_atomic16_cmpset(&(port->port_status),
+			RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 1) {
+			printf("Port %d is not stopped\n", pi);
+			continue;
+		}
+
+		rte_eth_dev_reset(pi);
+		reset_ports[pi] = 0;
+	}
+
+	printf("Done\n");
+}
+
+void
 attach_port(char *identifier)
 {
 	portid_t pi = 0;
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 8cf2860..0c7e44c 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -586,6 +586,7 @@  int init_port_dcb_config(portid_t pid, enum dcb_mode_enable dcb_mode,
 int start_port(portid_t pid);
 void stop_port(portid_t pid);
 void close_port(portid_t pid);
+void reset_port(portid_t pid);
 void attach_port(char *identifier);
 void detach_port(uint8_t port_id);
 int all_ports_stopped(void);