From: Nithin Dabilpuram Date: Wed, 17 Jul 2019 12:30:55 +0000 (+0530) Subject: app/testpmd: add device related commands X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=55e51c962432;p=dpdk.git app/testpmd: add device related commands 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 |all" is also added as a part of this change. Signed-off-by: Nithin Dabilpuram Reviewed-by: Ferruh Yigit --- diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 11801769a0..a28362d881 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 (|all)" + " Show general information about devices probed.\n\n" ); } @@ -1247,6 +1251,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 = @@ -1255,13 +1270,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, @@ -1500,6 +1515,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: 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; @@ -7463,6 +7519,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 |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; @@ -18730,6 +18831,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, @@ -18818,6 +18920,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 ba43be52ef..1a5a5c13c0 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 3ed3523b79..a3b1542ed3 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -2475,6 +2475,51 @@ detach_port_device(portid_t port_id) return; } +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) { diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index ba04c3ba53..77994546e8 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -691,6 +691,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); @@ -790,6 +791,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 e1fcef9f2d..313e0707e2 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 (|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 ~~~~~~~~~~~~ @@ -2313,6 +2336,47 @@ hash of input [IP] packets received on port:: ipv6-udp-ex ) +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 ----------------------