[v2] app/testpmd: add device related cmds

Message ID 20190710130704.131936-1-ndabilpuram@marvell.com
State Superseded
Delegated to: Ferruh Yigit
Headers show
Series
  • [v2] app/testpmd: add device related cmds
Related show

Checks

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

Commit Message

Nithin Dabilpuram July 10, 2019, 1:07 p.m.
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>
---
 app/test-pmd/cmdline.c                      | 88 +++++++++++++++++++++++++++++
 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, 272 insertions(+)

Comments

Ferruh Yigit July 16, 2019, 6:30 p.m. | #1
On 7/10/2019 2:07 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>
> ---
>  app/test-pmd/cmdline.c                      | 88 +++++++++++++++++++++++++++++
>  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, 272 insertions(+)

Can you please add new commands to help string in 'cmd_help_long_parsed()' too?

<...>
Nithin Dabilpuram July 17, 2019, 8:08 a.m. | #2
On Tue, Jul 16, 2019 at 07:30:23PM +0100, Ferruh Yigit wrote:
> External Email
> 
> ----------------------------------------------------------------------
> On 7/10/2019 2:07 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>
> > ---
> >  app/test-pmd/cmdline.c                      | 88 +++++++++++++++++++++++++++++
> >  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, 272 insertions(+)
> 
> Can you please add new commands to help string in 'cmd_help_long_parsed()' too?
>

Sorry, I missed that, will add it in next version.

> <...>
> 
>

Patch

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 01dd45f..e10e82a 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -1493,6 +1493,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 +7497,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 +18809,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 +18898,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
 ----------------------