[v3] app/testpmd: add device related cmds

Message ID 20190717123055.106873-1-ndabilpuram@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series [v3] app/testpmd: add device related cmds |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK
ci/mellanox-Performance-Testing success Performance Testing PASS
ci/intel-Performance-Testing success Performance Testing PASS

Commit Message

Nithin Dabilpuram July 17, 2019, 12:30 p.m. UTC
  With the latest published interface of
rte_eal_hotplug_[add,remove](), and rte_eth_dev_close(),
rte_eth_dev_close() would cleanup all the data structures of
port's eth dev leaving the device common resource intact
if RTE_ETH_DEV_CLOSE_REMOVE is set in dev flags.

So a new command "detach device" (~hotplug remove) to work,
with device identifier like "port attach" is added
to be able to detach closed devices.

Also to display currently probed devices, another command
"show device info <identifier>|all" is also added as a
part of this change.

Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
---

v3:
* Add help command text for new device related commands
v2:
* Add new commands "device detach" and "show device info all"
  instead of change in existing command "port detach"

 app/test-pmd/cmdline.c                      | 107 +++++++++++++++++++++++++++-
 app/test-pmd/config.c                       |  73 +++++++++++++++++++
 app/test-pmd/testpmd.c                      |  45 ++++++++++++
 app/test-pmd/testpmd.h                      |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  64 +++++++++++++++++
 5 files changed, 289 insertions(+), 2 deletions(-)
  

Comments

Ferruh Yigit July 17, 2019, 4:51 p.m. UTC | #1
On 7/17/2019 1:30 PM, Nithin Dabilpuram wrote:
> With the latest published interface of
> rte_eal_hotplug_[add,remove](), and rte_eth_dev_close(),
> rte_eth_dev_close() would cleanup all the data structures of
> port's eth dev leaving the device common resource intact
> if RTE_ETH_DEV_CLOSE_REMOVE is set in dev flags.
> 
> So a new command "detach device" (~hotplug remove) to work,
> with device identifier like "port attach" is added
> to be able to detach closed devices.
> 
> Also to display currently probed devices, another command
> "show device info <identifier>|all" is also added as a
> part of this change.

In "show device info all" output [1] there are 'dpaa' & 'fslmc' logs [2], do you
know why we are getting them, can we get rid of them?




[1]
"
********************* Infos for device net_null0 *********************
Bus name: vdev
Driver name: net_null
Devargs:
Connect to socket: 0

        Port id: 1
        MAC address: 8A:D0:A1:F3:B5:0C
        Device name: net_null0
dpaa: Invalid device string ()

fslmc: Invalid device string ()
"


[2]
"
dpaa: Invalid device string ()

fslmc: Invalid device string ()
"
  
Ferruh Yigit July 17, 2019, 4:54 p.m. UTC | #2
On 7/17/2019 1:30 PM, Nithin Dabilpuram wrote:
> With the latest published interface of
> rte_eal_hotplug_[add,remove](), and rte_eth_dev_close(),
> rte_eth_dev_close() would cleanup all the data structures of
> port's eth dev leaving the device common resource intact
> if RTE_ETH_DEV_CLOSE_REMOVE is set in dev flags.
> 
> So a new command "detach device" (~hotplug remove) to work,
> with device identifier like "port attach" is added
> to be able to detach closed devices.
> 
> Also to display currently probed devices, another command
> "show device info <identifier>|all" is also added as a
> part of this change.
> 
> Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>

Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>

Applied to dpdk-next-net/master, thanks.
  
Nithin Dabilpuram July 18, 2019, 5:27 a.m. UTC | #3
Hi Ferruh,

On 7/17/2019 10:21 PM, Ferruh Yigit wrote:
> External Email
>
> ----------------------------------------------------------------------
> On 7/17/2019 1:30 PM, Nithin Dabilpuram wrote:
>> With the latest published interface of
>> rte_eal_hotplug_[add,remove](), and rte_eth_dev_close(),
>> rte_eth_dev_close() would cleanup all the data structures of
>> port's eth dev leaving the device common resource intact
>> if RTE_ETH_DEV_CLOSE_REMOVE is set in dev flags.
>>
>> So a new command "detach device" (~hotplug remove) to work,
>> with device identifier like "port attach" is added
>> to be able to detach closed devices.
>>
>> Also to display currently probed devices, another command
>> "show device info <identifier>|all" is also added as a
>> part of this change.
> In "show device info all" output [1] there are 'dpaa' & 'fslmc' logs [2], do you
> know why we are getting them, can we get rid of them?
>
Is this issue sill there ?  I'm not able to see it in my setup.

>
>
> [1]
> "
> ********************* Infos for device net_null0 *********************
> Bus name: vdev
> Driver name: net_null
> Devargs:
> Connect to socket: 0
>
>          Port id: 1
>          MAC address: 8A:D0:A1:F3:B5:0C
>          Device name: net_null0
> dpaa: Invalid device string ()
>
> fslmc: Invalid device string ()
> "
>
>
> [2]
> "
> dpaa: Invalid device string ()
>
> fslmc: Invalid device string ()
> "
  
Ferruh Yigit July 19, 2019, 7 p.m. UTC | #4
On 7/18/2019 6:27 AM, Nithin Kumar Dabilpuram wrote:
> Hi Ferruh,
> 
> On 7/17/2019 10:21 PM, Ferruh Yigit wrote:
>> External Email
>>
>> ----------------------------------------------------------------------
>> On 7/17/2019 1:30 PM, Nithin Dabilpuram wrote:
>>> With the latest published interface of
>>> rte_eal_hotplug_[add,remove](), and rte_eth_dev_close(),
>>> rte_eth_dev_close() would cleanup all the data structures of
>>> port's eth dev leaving the device common resource intact
>>> if RTE_ETH_DEV_CLOSE_REMOVE is set in dev flags.
>>>
>>> So a new command "detach device" (~hotplug remove) to work,
>>> with device identifier like "port attach" is added
>>> to be able to detach closed devices.
>>>
>>> Also to display currently probed devices, another command
>>> "show device info <identifier>|all" is also added as a
>>> part of this change.
>> In "show device info all" output [1] there are 'dpaa' & 'fslmc' logs [2], do you
>> know why we are getting them, can we get rid of them?
>>
> Is this issue sill there ?  I'm not able to see it in my setup.

Yes, still there. I can see them with latest next-net.

> 
>>
>>
>> [1]
>> "
>> ********************* Infos for device net_null0 *********************
>> Bus name: vdev
>> Driver name: net_null
>> Devargs:
>> Connect to socket: 0
>>
>>          Port id: 1
>>          MAC address: 8A:D0:A1:F3:B5:0C
>>          Device name: net_null0
>> dpaa: Invalid device string ()
>>
>> fslmc: Invalid device string ()
>> "
>>
>>
>> [2]
>> "
>> dpaa: Invalid device string ()
>>
>> fslmc: Invalid device string ()
>> "
  
Hemant Agrawal July 22, 2019, 6:01 a.m. UTC | #5
HI,
> On 7/18/2019 6:27 AM, Nithin Kumar Dabilpuram wrote:
> > Hi Ferruh,
> >
> > On 7/17/2019 10:21 PM, Ferruh Yigit wrote:
> >> External Email
> >>
> >> ---------------------------------------------------------------------
> >> - On 7/17/2019 1:30 PM, Nithin Dabilpuram wrote:
> >>> With the latest published interface of
> >>> rte_eal_hotplug_[add,remove](), and rte_eth_dev_close(),
> >>> rte_eth_dev_close() would cleanup all the data structures of port's
> >>> eth dev leaving the device common resource intact if
> >>> RTE_ETH_DEV_CLOSE_REMOVE is set in dev flags.
> >>>
> >>> So a new command "detach device" (~hotplug remove) to work, with
> >>> device identifier like "port attach" is added to be able to detach
> >>> closed devices.
> >>>
> >>> Also to display currently probed devices, another command "show
> >>> device info <identifier>|all" is also added as a part of this
> >>> change.
> >> In "show device info all" output [1] there are 'dpaa' & 'fslmc' logs
> >> [2], do you know why we are getting them, can we get rid of them?
> >>
> > Is this issue sill there ?  I'm not able to see it in my setup.
> 
> Yes, still there. I can see them with latest next-net.
> 
[Hemant] Patch is on the way.
  
Nithin Dabilpuram July 22, 2019, 6:15 a.m. UTC | #6
On 7/22/2019 11:31 AM, Hemant Agrawal wrote:
> HI,
>> On 7/18/2019 6:27 AM, Nithin Kumar Dabilpuram wrote:
>>> Hi Ferruh,
>>>
>>> On 7/17/2019 10:21 PM, Ferruh Yigit wrote:
>>>> External Email
>>>>
>>>> ---------------------------------------------------------------------
>>>> - On 7/17/2019 1:30 PM, Nithin Dabilpuram wrote:
>>>>> With the latest published interface of
>>>>> rte_eal_hotplug_[add,remove](), and rte_eth_dev_close(),
>>>>> rte_eth_dev_close() would cleanup all the data structures of port's
>>>>> eth dev leaving the device common resource intact if
>>>>> RTE_ETH_DEV_CLOSE_REMOVE is set in dev flags.
>>>>>
>>>>> So a new command "detach device" (~hotplug remove) to work, with
>>>>> device identifier like "port attach" is added to be able to detach
>>>>> closed devices.
>>>>>
>>>>> Also to display currently probed devices, another command "show
>>>>> device info <identifier>|all" is also added as a part of this
>>>>> change.
>>>> In "show device info all" output [1] there are 'dpaa' & 'fslmc' logs
>>>> [2], do you know why we are getting them, can we get rid of them?
>>>>
>>> Is this issue sill there ?  I'm not able to see it in my setup.
>> Yes, still there. I can see them with latest next-net.
>>
> [Hemant] Patch is on the way.
Thanks.
  
Ferruh Yigit July 22, 2019, 4:04 p.m. UTC | #7
On 7/22/2019 7:15 AM, Nithin Kumar Dabilpuram wrote:
> 
> On 7/22/2019 11:31 AM, Hemant Agrawal wrote:
>> HI,
>>> On 7/18/2019 6:27 AM, Nithin Kumar Dabilpuram wrote:
>>>> Hi Ferruh,
>>>>
>>>> On 7/17/2019 10:21 PM, Ferruh Yigit wrote:
>>>>> External Email
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> - On 7/17/2019 1:30 PM, Nithin Dabilpuram wrote:
>>>>>> With the latest published interface of
>>>>>> rte_eal_hotplug_[add,remove](), and rte_eth_dev_close(),
>>>>>> rte_eth_dev_close() would cleanup all the data structures of port's
>>>>>> eth dev leaving the device common resource intact if
>>>>>> RTE_ETH_DEV_CLOSE_REMOVE is set in dev flags.
>>>>>>
>>>>>> So a new command "detach device" (~hotplug remove) to work, with
>>>>>> device identifier like "port attach" is added to be able to detach
>>>>>> closed devices.
>>>>>>
>>>>>> Also to display currently probed devices, another command "show
>>>>>> device info <identifier>|all" is also added as a part of this
>>>>>> change.
>>>>> In "show device info all" output [1] there are 'dpaa' & 'fslmc' logs
>>>>> [2], do you know why we are getting them, can we get rid of them?
>>>>>
>>>> Is this issue sill there ?  I'm not able to see it in my setup.
>>> Yes, still there. I can see them with latest next-net.
>>>
>> [Hemant] Patch is on the way.
> Thanks.
> 

Hi Hemant, I confirm logs are gone (unless debug level enabled), thanks.
  

Patch

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 01dd45f..6b8aeed 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -101,6 +101,7 @@  static void cmd_help_brief_parsed(__attribute__((unused)) void *parsed_result,
 		"    help registers                  : Reading and setting port registers.\n"
 		"    help filters                    : Filters configuration help.\n"
 		"    help traffic_management         : Traffic Management commmands.\n"
+		"    help devices                    : Device related cmds.\n"
 		"    help all                        : All of the above sections.\n\n"
 	);
 
@@ -236,6 +237,9 @@  static void cmd_help_long_parsed(void *parsed_result,
 			"show port (port_id) tx_metadata\n"
 			"    Show Tx metadata value set"
 			" for a specific port\n\n"
+
+			"show device info (<identifier>|all)"
+			"       Show general information about devices probed.\n\n"
 		);
 	}
 
@@ -1240,6 +1244,17 @@  static void cmd_help_long_parsed(void *parsed_result,
 		);
 	}
 
+	if (show_all || !strcmp(res->section, "devices")) {
+		cmdline_printf(
+			cl,
+			"\n"
+			"Device Operations:\n"
+			"--------------\n"
+			"device detach (identifier)\n"
+			"       Detach device by identifier.\n\n"
+		);
+	}
+
 }
 
 cmdline_parse_token_string_t cmd_help_long_help =
@@ -1248,13 +1263,13 @@  cmdline_parse_token_string_t cmd_help_long_help =
 cmdline_parse_token_string_t cmd_help_long_section =
 	TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, section,
 			"all#control#display#config#"
-			"ports#registers#filters#traffic_management");
+			"ports#registers#filters#traffic_management#devices");
 
 cmdline_parse_inst_t cmd_help_long = {
 	.f = cmd_help_long_parsed,
 	.data = NULL,
 	.help_str = "help all|control|display|config|ports|register|"
-		"filters|traffic_management: "
+		"filters|traffic_management|devices: "
 		"Show help",
 	.tokens = {
 		(void *)&cmd_help_long_help,
@@ -1493,6 +1508,47 @@  cmdline_parse_inst_t cmd_operate_detach_port = {
 	},
 };
 
+/* *** detach device by identifier *** */
+struct cmd_operate_detach_device_result {
+	cmdline_fixed_string_t device;
+	cmdline_fixed_string_t keyword;
+	cmdline_fixed_string_t identifier;
+};
+
+static void cmd_operate_detach_device_parsed(void *parsed_result,
+				__attribute__((unused)) struct cmdline *cl,
+				__attribute__((unused)) void *data)
+{
+	struct cmd_operate_detach_device_result *res = parsed_result;
+
+	if (!strcmp(res->keyword, "detach"))
+		detach_device(res->identifier);
+	else
+		printf("Unknown parameter\n");
+}
+
+cmdline_parse_token_string_t cmd_operate_detach_device_device =
+	TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_device_result,
+			device, "device");
+cmdline_parse_token_string_t cmd_operate_detach_device_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_device_result,
+			keyword, "detach");
+cmdline_parse_token_string_t cmd_operate_detach_device_identifier =
+	TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_device_result,
+			identifier, NULL);
+
+cmdline_parse_inst_t cmd_operate_detach_device = {
+	.f = cmd_operate_detach_device_parsed,
+	.data = NULL,
+	.help_str = "device detach <identifier>:"
+		"(identifier: pci address or virtual dev name)",
+	.tokens = {
+		(void *)&cmd_operate_detach_device_device,
+		(void *)&cmd_operate_detach_device_keyword,
+		(void *)&cmd_operate_detach_device_identifier,
+		NULL,
+	},
+};
 /* *** configure speed for all ports *** */
 struct cmd_config_speed_all {
 	cmdline_fixed_string_t port;
@@ -7456,6 +7512,51 @@  cmdline_parse_inst_t cmd_showport = {
 	},
 };
 
+/* *** SHOW DEVICE INFO *** */
+struct cmd_showdevice_result {
+	cmdline_fixed_string_t show;
+	cmdline_fixed_string_t device;
+	cmdline_fixed_string_t what;
+	cmdline_fixed_string_t identifier;
+};
+
+static void cmd_showdevice_parsed(void *parsed_result,
+				__attribute__((unused)) struct cmdline *cl,
+				__attribute__((unused)) void *data)
+{
+	struct cmd_showdevice_result *res = parsed_result;
+	if (!strcmp(res->what, "info")) {
+		if (!strcmp(res->identifier, "all"))
+			device_infos_display(NULL);
+		else
+			device_infos_display(res->identifier);
+	}
+}
+
+cmdline_parse_token_string_t cmd_showdevice_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, show,
+				 "show");
+cmdline_parse_token_string_t cmd_showdevice_device =
+	TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, device, "device");
+cmdline_parse_token_string_t cmd_showdevice_what =
+	TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, what,
+				 "info");
+cmdline_parse_token_string_t cmd_showdevice_identifier =
+	TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result,
+			identifier, NULL);
+
+cmdline_parse_inst_t cmd_showdevice = {
+	.f = cmd_showdevice_parsed,
+	.data = NULL,
+	.help_str = "show device info <identifier>|all",
+	.tokens = {
+		(void *)&cmd_showdevice_show,
+		(void *)&cmd_showdevice_device,
+		(void *)&cmd_showdevice_what,
+		(void *)&cmd_showdevice_identifier,
+		NULL,
+	},
+};
 /* *** SHOW QUEUE INFO *** */
 struct cmd_showqueue_result {
 	cmdline_fixed_string_t show;
@@ -18723,6 +18824,7 @@  cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_showport,
 	(cmdline_parse_inst_t *)&cmd_showqueue,
 	(cmdline_parse_inst_t *)&cmd_showportall,
+	(cmdline_parse_inst_t *)&cmd_showdevice,
 	(cmdline_parse_inst_t *)&cmd_showcfg,
 	(cmdline_parse_inst_t *)&cmd_showfwdall,
 	(cmdline_parse_inst_t *)&cmd_start,
@@ -18811,6 +18913,7 @@  cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_operate_specific_port,
 	(cmdline_parse_inst_t *)&cmd_operate_attach_port,
 	(cmdline_parse_inst_t *)&cmd_operate_detach_port,
+	(cmdline_parse_inst_t *)&cmd_operate_detach_device,
 	(cmdline_parse_inst_t *)&cmd_set_port_setup_on,
 	(cmdline_parse_inst_t *)&cmd_config_speed_all,
 	(cmdline_parse_inst_t *)&cmd_config_speed_specific,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 1d80470..537e73f 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -386,6 +386,79 @@  tx_queue_infos_display(portid_t port_id, uint16_t queue_id)
 	printf("\n");
 }
 
+static int bus_match_all(const struct rte_bus *bus, const void *data)
+{
+	RTE_SET_USED(bus);
+	RTE_SET_USED(data);
+	return 0;
+}
+
+void
+device_infos_display(const char *identifier)
+{
+	static const char *info_border = "*********************";
+	struct rte_bus *start = NULL, *next;
+	struct rte_dev_iterator dev_iter;
+	char name[RTE_ETH_NAME_MAX_LEN];
+	struct rte_ether_addr mac_addr;
+	struct rte_device *dev;
+	struct rte_devargs da;
+	portid_t port_id;
+	char devstr[128];
+
+	memset(&da, 0, sizeof(da));
+	if (!identifier)
+		goto skip_parse;
+
+	if (rte_devargs_parsef(&da, "%s", identifier)) {
+		printf("cannot parse identifier\n");
+		if (da.args)
+			free(da.args);
+		return;
+	}
+
+skip_parse:
+	while ((next = rte_bus_find(start, bus_match_all, NULL)) != NULL) {
+
+		start = next;
+		if (identifier && da.bus != next)
+			continue;
+
+		/* Skip buses that don't have iterate method */
+		if (!next->dev_iterate)
+			continue;
+
+		snprintf(devstr, sizeof(devstr), "bus=%s", next->name);
+		RTE_DEV_FOREACH(dev, devstr, &dev_iter) {
+
+			if (!dev->driver)
+				continue;
+			/* Check for matching device if identifier is present */
+			if (identifier &&
+			    strncmp(da.name, dev->name, strlen(dev->name)))
+				continue;
+			printf("\n%s Infos for device %s %s\n",
+			       info_border, dev->name, info_border);
+			printf("Bus name: %s", dev->bus->name);
+			printf("\nDriver name: %s", dev->driver->name);
+			printf("\nDevargs: %s",
+			       dev->devargs ? dev->devargs->args : "");
+			printf("\nConnect to socket: %d", dev->numa_node);
+			printf("\n");
+
+			/* List ports with matching device name */
+			RTE_ETH_FOREACH_DEV_OF(port_id, dev) {
+				rte_eth_macaddr_get(port_id, &mac_addr);
+				printf("\n\tPort id: %-2d", port_id);
+				print_ethaddr("\n\tMAC address: ", &mac_addr);
+				rte_eth_dev_get_name_by_port(port_id, name);
+				printf("\n\tDevice name: %s", name);
+				printf("\n");
+			}
+		}
+	};
+}
+
 void
 port_infos_display(portid_t port_id)
 {
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 3ed3523..a3b1542 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2476,6 +2476,51 @@  detach_port_device(portid_t port_id)
 }
 
 void
+detach_device(char *identifier)
+{
+	struct rte_dev_iterator iterator;
+	struct rte_devargs da;
+	portid_t port_id;
+
+	printf("Removing a device...\n");
+
+	memset(&da, 0, sizeof(da));
+	if (rte_devargs_parsef(&da, "%s", identifier)) {
+		printf("cannot parse identifier\n");
+		if (da.args)
+			free(da.args);
+		return;
+	}
+
+	RTE_ETH_FOREACH_MATCHING_DEV(port_id, identifier, &iterator) {
+		if (ports[port_id].port_status != RTE_PORT_CLOSED) {
+			if (ports[port_id].port_status != RTE_PORT_STOPPED) {
+				printf("Port %u not stopped\n", port_id);
+				return;
+			}
+
+			/* sibling ports are forced to be closed */
+			if (ports[port_id].flow_list)
+				port_flow_flush(port_id);
+			ports[port_id].port_status = RTE_PORT_CLOSED;
+			printf("Port %u is now closed\n", port_id);
+		}
+	}
+
+	if (rte_eal_hotplug_remove(da.bus->name, da.name) != 0) {
+		TESTPMD_LOG(ERR, "Failed to detach device %s(%s)\n",
+			    da.name, da.bus->name);
+		return;
+	}
+
+	remove_invalid_ports();
+
+	printf("Device %s is detached\n", identifier);
+	printf("Now total ports is %d\n", nb_ports);
+	printf("Done\n");
+}
+
+void
 pmd_test_exit(void)
 {
 	portid_t pt_id;
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index e3a6f7c..93bed6d 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -689,6 +689,7 @@  void nic_stats_clear(portid_t port_id);
 void nic_xstats_display(portid_t port_id);
 void nic_xstats_clear(portid_t port_id);
 void nic_stats_mapping_display(portid_t port_id);
+void device_infos_display(const char *identifier);
 void port_infos_display(portid_t port_id);
 void port_summary_display(portid_t port_id);
 void port_summary_header_display(void);
@@ -788,6 +789,7 @@  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_device(char *identifier);
 void detach_port_device(portid_t port_id);
 int all_ports_stopped(void);
 int port_is_stopped(portid_t port_id);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index ebab2f1..04b9a31 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -467,6 +467,29 @@  Show Tx metadata value set for a specific port::
 
    testpmd> show port (port_id) tx_metadata
 
+show device info
+~~~~~~~~~~~~~~~~
+
+Show general information about devices probed::
+
+   testpmd> show device info (<identifier>|all)
+
+For example:
+
+.. code-block:: console
+
+    testpmd> show device info net_pcap0
+
+    ********************* Infos for device net_pcap0 *********************
+    Bus name: vdev
+    Driver name: net_pcap
+    Devargs: iface=enP2p6s0,phy_mac=1
+    Connect to socket: -1
+
+            Port id: 2
+            MAC address: 1E:37:93:28:04:B8
+            Device name: net_pcap0
+
 dump physmem
 ~~~~~~~~~~~~
 
@@ -2289,6 +2312,47 @@  hash of input [IP] packets received on port::
                      ipv6-udp-ex <string of hex digits \
                      (variable length, NIC dependent)>)
 
+Device Functions
+----------------
+
+The following sections show functions for device operations.
+
+device detach
+~~~~~~~~~~~~~
+
+Detach a device specified by pci address or virtual device args::
+
+   testpmd> device detach (identifier)
+
+Before detaching a device associated with ports, the ports should be stopped and closed.
+
+For example, to detach a pci device whose address is 0002:03:00.0.
+
+.. code-block:: console
+
+    testpmd> device detach 0002:03:00.0
+    Removing a device...
+    Port 1 is now closed
+    EAL: Releasing pci mapped resource for 0002:03:00.0
+    EAL: Calling pci_unmap_resource for 0002:03:00.0 at 0x218a050000
+    EAL: Calling pci_unmap_resource for 0002:03:00.0 at 0x218c050000
+    Device 0002:03:00.0 is detached
+    Now total ports is 1
+
+For example, to detach a port created by pcap PMD.
+
+.. code-block:: console
+
+    testpmd> device detach net_pcap0
+    Removing a device...
+    Port 0 is now closed
+    Device net_pcap0 is detached
+    Now total ports is 0
+    Done
+
+In this case, identifier is ``net_pcap0``.
+This identifier format is the same as ``--vdev`` format of DPDK applications.
+
 Link Bonding Functions
 ----------------------