From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pd0-f176.google.com (mail-pd0-f176.google.com [209.85.192.176]) by dpdk.org (Postfix) with ESMTP id AAA0AB3D3 for ; Mon, 23 Feb 2015 13:47:10 +0100 (CET) Received: by pdev10 with SMTP id v10so25197202pde.7 for ; Mon, 23 Feb 2015 04:47:09 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=d9LmT+c4BG49MwdvXf/j5wzCOmXreqnBmoTJMpHGbSI=; b=CXECd7dxT1k4QduFrUepPNAy1O6tV1PcENB+pBqpZaZL+XV7BiPTWDUUHMLUP97aLO cQ0jGTrudDOkULnVXAtR02ZnkmRFqwSlEffm/wkVONSk3/SFs3AkjhmMI9IpVRoanwst sxKcb+riW6EQfx3KggrDGsTsGJAgiz+/vnVSwwf0SWpSBtGUoy3BG58uaXQtIQg+x/IW IzXbK+/gEx511huQXTPhPqKZlchJICTV9AkgJRhh5hU9XWsT58gcrwvKOS9R4FZe9ffZ reUONw/pz/g5e/lrMdBtkOtZ/sLiQoGG5JayWy1TWXf93svsL4oIQMm9qUJDULip0H3f NdwA== X-Gm-Message-State: ALoCoQnr774jbekT3LdJD0Db5Bwld21RAih/eRkZN8JnoDdJz9DX5kEyX6T95JYlHGH5/JGpbQR6 X-Received: by 10.66.62.201 with SMTP id a9mr18713454pas.101.1424695629907; Mon, 23 Feb 2015 04:47:09 -0800 (PST) Received: from localhost.localdomain (napt.igel.co.jp. [219.106.231.132]) by mx.google.com with ESMTPSA id cf12sm10491641pdb.43.2015.02.23.04.47.07 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Feb 2015 04:47:09 -0800 (PST) From: Tetsuya Mukawa To: dev@dpdk.org Date: Mon, 23 Feb 2015 21:46:04 +0900 Message-Id: <1424695564-3913-16-git-send-email-mukawa@igel.co.jp> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1424695564-3913-1-git-send-email-mukawa@igel.co.jp> References: <1424060073-23484-2-git-send-email-mukawa@igel.co.jp> <1424695564-3913-1-git-send-email-mukawa@igel.co.jp> Subject: [dpdk-dev] [PATCH v12] testpmd: Add port hotplug support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Feb 2015 12:47:11 -0000 The patch introduces following commands. - port attach [ident] - port detach [port_id] - attach: attaching a port - detach: detaching a port - ident: pci address of physical device. Or device name and parameters of virtual device. (ex. 0000:02:00.0, eth_pcap0,iface=eth0) - port_id: port identifier v7: - Fix doc. (Thanks to Iremonger, Bernard) - Fix port checking implementation of star_port(); (Thanks to Qiu, Michael) v5: - Add testpmd documentation. (Thanks to Iremonger, Bernard) v4: - Fix strings of command help. Signed-off-by: Tetsuya Mukawa --- app/test-pmd/cmdline.c | 137 +++++++++++++++---- app/test-pmd/config.c | 102 ++++++++------ app/test-pmd/parameters.c | 22 ++- app/test-pmd/testpmd.c | 199 +++++++++++++++++++++------- app/test-pmd/testpmd.h | 18 ++- doc/guides/testpmd_app_ug/testpmd_funcs.rst | 57 ++++++++ 6 files changed, 409 insertions(+), 126 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index c6a1627..b78c659 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -513,6 +513,12 @@ static void cmd_help_long_parsed(void *parsed_result, "port close (port_id|all)\n" " Close 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" + + "port detach (port_id)\n" + " Detach physical or virtual dev by port_id\n\n" + "port config (port_id|all)" " speed (10|100|1000|10000|40000|auto)" " duplex (half|full|auto)\n" @@ -793,6 +799,89 @@ cmdline_parse_inst_t cmd_operate_specific_port = { }, }; +/* *** attach a specified port *** */ +struct cmd_operate_attach_port_result { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t identifier; +}; + +static void cmd_operate_attach_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_attach_port_result *res = parsed_result; + + if (!strcmp(res->keyword, "attach")) + attach_port(res->identifier); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_attach_port_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + port, "port"); +cmdline_parse_token_string_t cmd_operate_attach_port_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + keyword, "attach"); +cmdline_parse_token_string_t cmd_operate_attach_port_identifier = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + identifier, NULL); + +cmdline_parse_inst_t cmd_operate_attach_port = { + .f = cmd_operate_attach_port_parsed, + .data = NULL, + .help_str = "port attach identifier, " + "identifier: pci address or virtual dev name", + .tokens = { + (void *)&cmd_operate_attach_port_port, + (void *)&cmd_operate_attach_port_keyword, + (void *)&cmd_operate_attach_port_identifier, + NULL, + }, +}; + +/* *** detach a specified port *** */ +struct cmd_operate_detach_port_result { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + uint8_t port_id; +}; + +static void cmd_operate_detach_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_detach_port_result *res = parsed_result; + + if (!strcmp(res->keyword, "detach")) + detach_port(res->port_id); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_detach_port_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, + port, "port"); +cmdline_parse_token_string_t cmd_operate_detach_port_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, + keyword, "detach"); +cmdline_parse_token_num_t cmd_operate_detach_port_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result, + port_id, UINT8); + +cmdline_parse_inst_t cmd_operate_detach_port = { + .f = cmd_operate_detach_port_parsed, + .data = NULL, + .help_str = "port detach port_id", + .tokens = { + (void *)&cmd_operate_detach_port_port, + (void *)&cmd_operate_detach_port_keyword, + (void *)&cmd_operate_detach_port_port_id, + NULL, + }, +}; + /* *** configure speed for all ports *** */ struct cmd_config_speed_all { cmdline_fixed_string_t port; @@ -847,7 +936,7 @@ cmd_config_speed_all_parsed(void *parsed_result, return; } - for (pid = 0; pid < nb_ports; pid++) { + FOREACH_PORT(pid, ports) { ports[pid].dev_conf.link_speed = link_speed; ports[pid].dev_conf.link_duplex = link_duplex; } @@ -915,10 +1004,8 @@ cmd_config_speed_specific_parsed(void *parsed_result, return; } - if (res->id >= nb_ports) { - printf("Port id %d must be less than %d\n", res->id, nb_ports); + if (port_id_is_invalid(res->id, ENABLED_WARN)) return; - } if (!strcmp(res->value1, "10")) link_speed = ETH_LINK_SPEED_10; @@ -1489,7 +1576,7 @@ cmd_config_rxtx_queue_parsed(void *parsed_result, return; } - if (port_id_is_invalid(res->portid)) + if (port_id_is_invalid(res->portid, ENABLED_WARN)) return; if (port_is_started(res->portid) != 1) { @@ -2889,7 +2976,7 @@ cmd_csum_parsed(void *parsed_result, int hw = 0; uint16_t mask = 0; - if (port_id_is_invalid(res->port_id)) { + if (port_id_is_invalid(res->port_id, ENABLED_WARN)) { printf("invalid port %d\n", res->port_id); return; } @@ -2981,10 +3068,8 @@ cmd_csum_tunnel_parsed(void *parsed_result, { struct cmd_csum_tunnel_result *res = parsed_result; - if (port_id_is_invalid(res->port_id)) { - printf("invalid port %d\n", res->port_id); + if (port_id_is_invalid(res->port_id, ENABLED_WARN)) return; - } if (!strcmp(res->onoff, "on")) ports[res->port_id].tx_ol_flags |= @@ -3039,7 +3124,7 @@ cmd_tso_set_parsed(void *parsed_result, struct cmd_tso_set_result *res = parsed_result; struct rte_eth_dev_info dev_info; - if (port_id_is_invalid(res->port_id)) + if (port_id_is_invalid(res->port_id, ENABLED_WARN)) return; if (!strcmp(res->mode, "set")) @@ -4015,10 +4100,8 @@ static void cmd_set_bond_mac_addr_parsed(void *parsed_result, struct cmd_set_bond_mac_addr_result *res = parsed_result; int ret; - if (res->port_num >= nb_ports) { - printf("Port id %d must be less than %d\n", res->port_num, nb_ports); + if (port_id_is_invalid(res->port_num, ENABLED_WARN)) return; - } ret = rte_eth_bond_mac_address_set(res->port_num, &res->address); @@ -4255,7 +4338,7 @@ static void cmd_set_promisc_mode_parsed(void *parsed_result, /* all ports */ if (allports) { - for (i = 0; i < nb_ports; i++) { + FOREACH_PORT(i, ports) { if (enable) rte_eth_promiscuous_enable(i); else @@ -4335,7 +4418,7 @@ static void cmd_set_allmulti_mode_parsed(void *parsed_result, /* all ports */ if (allports) { - for (i = 0; i < nb_ports; i++) { + FOREACH_PORT(i, ports) { if (enable) rte_eth_allmulticast_enable(i); else @@ -5023,25 +5106,25 @@ static void cmd_showportall_parsed(void *parsed_result, struct cmd_showportall_result *res = parsed_result; if (!strcmp(res->show, "clear")) { if (!strcmp(res->what, "stats")) - for (i = 0; i < nb_ports; i++) + FOREACH_PORT(i, ports) nic_stats_clear(i); else if (!strcmp(res->what, "xstats")) - for (i = 0; i < nb_ports; i++) + FOREACH_PORT(i, ports) nic_xstats_clear(i); } else if (!strcmp(res->what, "info")) - for (i = 0; i < nb_ports; i++) + FOREACH_PORT(i, ports) port_infos_display(i); else if (!strcmp(res->what, "stats")) - for (i = 0; i < nb_ports; i++) + FOREACH_PORT(i, ports) nic_stats_display(i); else if (!strcmp(res->what, "xstats")) - for (i = 0; i < nb_ports; i++) + FOREACH_PORT(i, ports) nic_xstats_display(i); else if (!strcmp(res->what, "fdir")) - for (i = 0; i < nb_ports; i++) + FOREACH_PORT(i, ports) fdir_get_infos(i); else if (!strcmp(res->what, "stat_qmap")) - for (i = 0; i < nb_ports; i++) + FOREACH_PORT(i, ports) nic_stats_mapping_display(i); } @@ -8685,6 +8768,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_qmap, (cmdline_parse_inst_t *)&cmd_operate_port, (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_config_speed_all, (cmdline_parse_inst_t *)&cmd_config_speed_specific, (cmdline_parse_inst_t *)&cmd_config_rx_tx, @@ -8756,7 +8841,7 @@ prompt(void) static void cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue) { - if (id < nb_ports) { + if (!port_id_is_invalid(id, DISABLED_WARN)) { /* check if need_reconfig has been set to 1 */ if (ports[id].need_reconfig == 0) ports[id].need_reconfig = dev; @@ -8766,7 +8851,7 @@ cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue) } else { portid_t pid; - for (pid = 0; pid < nb_ports; pid++) { + FOREACH_PORT(pid, ports) { /* check if need_reconfig has been set to 1 */ if (ports[pid].need_reconfig == 0) ports[pid].need_reconfig = dev; @@ -8784,10 +8869,8 @@ bypass_is_supported(portid_t port_id) struct rte_port *port; struct rte_pci_id *pci_id; - if (port_id >= nb_ports) { - printf("\tPort id must be less than %d.\n", nb_ports); + if (port_id_is_invalid(port_id, ENABLED_WARN)) return 0; - } /* Get the device id. */ port = &ports[port_id]; diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index d436ce8..49be819 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -112,11 +112,15 @@ nic_stats_display(portid_t port_id) struct rte_eth_stats stats; struct rte_port *port = &ports[port_id]; uint8_t i; + portid_t pid; static const char *nic_stats_border = "########################"; - if (port_id >= nb_ports) { - printf("Invalid port, range is [0, %d]\n", nb_ports - 1); + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + printf("Valid port range is [0"); + FOREACH_PORT(pid, ports) + printf(", %d", pid); + printf("]\n"); return; } rte_eth_stats_get(port_id, &stats); @@ -189,8 +193,13 @@ nic_stats_display(portid_t port_id) void nic_stats_clear(portid_t port_id) { - if (port_id >= nb_ports) { - printf("Invalid port, range is [0, %d]\n", nb_ports - 1); + portid_t pid; + + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + printf("Valid port range is [0"); + FOREACH_PORT(pid, ports) + printf(", %d", pid); + printf("]\n"); return; } rte_eth_stats_reset(port_id); @@ -237,11 +246,15 @@ nic_stats_mapping_display(portid_t port_id) { struct rte_port *port = &ports[port_id]; uint16_t i; + portid_t pid; static const char *nic_stats_mapping_border = "########################"; - if (port_id >= nb_ports) { - printf("Invalid port, range is [0, %d]\n", nb_ports - 1); + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + printf("Valid port range is [0"); + FOREACH_PORT(pid, ports) + printf(", %d", pid); + printf("]\n"); return; } @@ -290,9 +303,13 @@ port_infos_display(portid_t port_id) int vlan_offload; struct rte_mempool * mp; static const char *info_border = "*********************"; + portid_t pid; - if (port_id >= nb_ports) { - printf("Invalid port, range is [0, %d]\n", nb_ports - 1); + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + printf("Valid port range is [0"); + FOREACH_PORT(pid, ports) + printf(", %d", pid); + printf("]\n"); return; } port = &ports[port_id]; @@ -365,11 +382,14 @@ port_infos_display(portid_t port_id) } int -port_id_is_invalid(portid_t port_id) +port_id_is_invalid(portid_t port_id, enum print_warning warning) { - if (port_id < nb_ports) + if (ports[port_id].enabled) return 0; - printf("Invalid port %d (must be < nb_ports=%d)\n", port_id, nb_ports); + + if (warning == ENABLED_WARN) + printf("Invalid port %d\n", port_id); + return 1; } @@ -428,7 +448,7 @@ port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x) uint32_t reg_v; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; @@ -447,7 +467,7 @@ port_reg_bit_field_display(portid_t port_id, uint32_t reg_off, uint8_t l_bit; uint8_t h_bit; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; @@ -474,7 +494,7 @@ port_reg_display(portid_t port_id, uint32_t reg_off) { uint32_t reg_v; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; @@ -488,7 +508,7 @@ port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos, { uint32_t reg_v; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; @@ -516,7 +536,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, uint8_t l_bit; uint8_t h_bit; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; @@ -550,7 +570,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, void port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v) { - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; @@ -563,7 +583,7 @@ port_mtu_set(portid_t port_id, uint16_t mtu) { int diag; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; diag = rte_eth_dev_set_mtu(port_id, mtu); if (diag == 0) @@ -726,7 +746,7 @@ rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id) { const struct rte_memzone *rx_mz; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (rx_queue_id_is_invalid(rxq_id)) return; @@ -743,7 +763,7 @@ tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id) { const struct rte_memzone *tx_mz; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (tx_queue_id_is_invalid(txq_id)) return; @@ -804,7 +824,7 @@ port_rss_reta_info(portid_t port_id, uint16_t i, idx, shift; int ret; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries); @@ -859,7 +879,7 @@ port_rss_hash_conf_show(portid_t port_id, int show_rss_key) uint8_t i; int diag; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; /* Get RSS hash key if asked to display it */ rss_conf.rss_key = (show_rss_key) ? rss_key : NULL; @@ -1423,12 +1443,8 @@ set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt) again: for (i = 0; i < nb_pt; i++) { port_id = (portid_t) portlist[i]; - if (port_id >= nb_ports) { - printf("Invalid port id %u >= %u\n", - (unsigned int) port_id, - (unsigned int) nb_ports); + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; - } if (record_now) fwd_ports_ids[i] = port_id; } @@ -1586,7 +1602,7 @@ vlan_extend_set(portid_t port_id, int on) int diag; int vlan_offload; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; vlan_offload = rte_eth_dev_get_vlan_offload(port_id); @@ -1608,7 +1624,7 @@ rx_vlan_strip_set(portid_t port_id, int on) int diag; int vlan_offload; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; vlan_offload = rte_eth_dev_get_vlan_offload(port_id); @@ -1629,7 +1645,7 @@ rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on) { int diag; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on); @@ -1644,7 +1660,7 @@ rx_vlan_filter_set(portid_t port_id, int on) int diag; int vlan_offload; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; vlan_offload = rte_eth_dev_get_vlan_offload(port_id); @@ -1665,7 +1681,7 @@ rx_vft_set(portid_t port_id, uint16_t vlan_id, int on) { int diag; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (vlan_id_is_invalid(vlan_id)) return; @@ -1682,7 +1698,7 @@ rx_vlan_all_filter_set(portid_t port_id, int on) { uint16_t vlan_id; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; for (vlan_id = 0; vlan_id < 4096; vlan_id++) rx_vft_set(port_id, vlan_id, on); @@ -1692,7 +1708,7 @@ void vlan_tpid_set(portid_t port_id, uint16_t tp_id) { int diag; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; diag = rte_eth_dev_set_vlan_ether_type(port_id, tp_id); @@ -1707,7 +1723,7 @@ vlan_tpid_set(portid_t port_id, uint16_t tp_id) void tx_vlan_set(portid_t port_id, uint16_t vlan_id) { - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (vlan_id_is_invalid(vlan_id)) return; @@ -1718,7 +1734,7 @@ tx_vlan_set(portid_t port_id, uint16_t vlan_id) void tx_vlan_reset(portid_t port_id) { - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; ports[port_id].tx_ol_flags &= ~TESTPMD_TX_OFFLOAD_INSERT_VLAN; } @@ -1726,7 +1742,7 @@ tx_vlan_reset(portid_t port_id) void tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on) { - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on); @@ -1738,7 +1754,7 @@ set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value) uint16_t i; uint8_t existing_mapping_found = 0; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id))) @@ -1904,7 +1920,7 @@ fdir_get_infos(portid_t port_id) static const char *fdir_stats_border = "########################"; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR); if (ret < 0) { @@ -2030,7 +2046,7 @@ set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on) { int diag; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (is_rx) diag = rte_eth_dev_set_vf_rx(port_id,vf,on); @@ -2052,7 +2068,7 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on) { int diag; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (vlan_id_is_invalid(vlan_id)) return; @@ -2069,7 +2085,7 @@ set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate) int diag; struct rte_eth_link link; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return 1; rte_eth_link_get_nowait(port_id, &link); if (rate > link.link_speed) { @@ -2094,7 +2110,7 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk) if (q_msk == 0) return 0; - if (port_id_is_invalid(port_id)) + if (port_id_is_invalid(port_id, ENABLED_WARN)) return 1; rte_eth_link_get_nowait(port_id, &link); if (rate > link.link_speed) { diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 473f824..fa5f2a8 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -366,6 +366,7 @@ parse_portnuma_config(const char *q_arg) }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; + portid_t pid; /* reset from value set at definition */ while ((p = strchr(p0,'(')) != NULL) { @@ -387,8 +388,11 @@ parse_portnuma_config(const char *q_arg) return -1; } port_id = (uint8_t)int_fld[FLD_PORT]; - if (port_id >= nb_ports) { - printf("Invalid port, range is [0, %d]\n", nb_ports - 1); + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + printf("Valid port range is [0"); + FOREACH_PORT(pid, ports) + printf(", %d", pid); + printf("]\n"); return -1; } socket_id = (uint8_t)int_fld[FLD_SOCKET]; @@ -419,6 +423,7 @@ parse_ringnuma_config(const char *q_arg) }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; + portid_t pid; #define RX_RING_ONLY 0x1 #define TX_RING_ONLY 0x2 #define RXTX_RING 0x3 @@ -443,8 +448,11 @@ parse_ringnuma_config(const char *q_arg) return -1; } port_id = (uint8_t)int_fld[FLD_PORT]; - if (port_id >= nb_ports) { - printf("Invalid port, range is [0, %d]\n", nb_ports - 1); + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + printf("Valid port range is [0"); + FOREACH_PORT(pid, ports) + printf(", %d", pid); + printf("]\n"); return -1; } socket_id = (uint8_t)int_fld[FLD_SOCKET]; @@ -615,12 +623,12 @@ launch_args_parse(int argc, char** argv) #endif if (!strcmp(lgopts[opt_idx].name, "nb-ports")) { n = atoi(optarg); - if (n > 0 && n <= nb_ports) + if (n > 0 && + !port_id_is_invalid(n, DISABLED_WARN)) nb_fwd_ports = (uint8_t) n; else rte_exit(EXIT_FAILURE, - "nb-ports should be > 0 and <= %d\n", - nb_ports); + "Invalid port %d\n", n); } if (!strcmp(lgopts[opt_idx].name, "nb-cores")) { n = atoi(optarg); diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 605163b..44bb8b3 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -71,6 +71,7 @@ #include #include #include +#include #include #ifdef RTE_LIBRTE_PMD_XENVIRT #include @@ -315,7 +316,7 @@ uint16_t nb_rx_queue_stats_mappings = 0; /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); -static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask); +static void check_all_ports_link_status(uint32_t port_mask); /* * Check if all the ports are started. @@ -324,6 +325,20 @@ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask); static int all_ports_started(void); /* + * Find next enabled port + */ +portid_t +find_next_port(portid_t p, struct rte_port *ports, int size) +{ + if (ports == NULL) + rte_exit(-EINVAL, "failed to find a next port id\n"); + + while ((ports[p].enabled == 0) && (p < size)) + p++; + return p; +} + +/* * Setup default configuration. */ static void @@ -552,7 +567,8 @@ init_config(void) + RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST; if (!numa_support) - nb_mbuf_per_pool = (nb_mbuf_per_pool * nb_ports); + nb_mbuf_per_pool = + (nb_mbuf_per_pool * RTE_MAX_ETHPORTS); } if (!numa_support) { @@ -565,14 +581,19 @@ init_config(void) /* Configuration of Ethernet ports. */ ports = rte_zmalloc("testpmd: ports", - sizeof(struct rte_port) * nb_ports, + sizeof(struct rte_port) * RTE_MAX_ETHPORTS, RTE_CACHE_LINE_SIZE); if (ports == NULL) { - rte_exit(EXIT_FAILURE, "rte_zmalloc(%d struct rte_port) " - "failed\n", nb_ports); + rte_exit(EXIT_FAILURE, + "rte_zmalloc(%d struct rte_port) failed\n", + RTE_MAX_ETHPORTS); } - for (pid = 0; pid < nb_ports; pid++) { + /* enabled allocated ports */ + for (pid = 0; pid < nb_ports; pid++) + ports[pid].enabled = 1; + + FOREACH_PORT(pid, ports) { port = &ports[pid]; rte_eth_dev_info_get(pid, &port->dev_info); @@ -602,8 +623,7 @@ init_config(void) nb_mbuf_per_pool = nb_mbuf_per_pool/nb_ports; for (i = 0; i < MAX_SOCKET; i++) { - nb_mbuf = (nb_mbuf_per_pool * - port_per_socket[i]); + nb_mbuf = (nb_mbuf_per_pool * RTE_MAX_ETHPORTS); if (nb_mbuf) mbuf_pool_create(mbuf_data_size, nb_mbuf,i); @@ -635,14 +655,6 @@ reconfig(portid_t new_port_id, unsigned socket_id) struct rte_port *port; /* Reconfiguration of Ethernet ports. */ - ports = rte_realloc(ports, - sizeof(struct rte_port) * nb_ports, - RTE_CACHE_LINE_SIZE); - if (ports == NULL) { - rte_exit(EXIT_FAILURE, "rte_realloc(%d struct rte_port) failed\n", - nb_ports); - } - port = &ports[new_port_id]; rte_eth_dev_info_get(new_port_id, &port->dev_info); @@ -663,7 +675,7 @@ init_fwd_streams(void) streamid_t sm_id, nb_fwd_streams_new; /* set socket id according to numa or not */ - for (pid = 0; pid < nb_ports; pid++) { + FOREACH_PORT(pid, ports) { port = &ports[pid]; if (nb_rxq > port->dev_info.max_rx_queues) { printf("Fail: nb_rxq(%d) is greater than " @@ -1264,7 +1276,7 @@ all_ports_started(void) portid_t pi; struct rte_port *port; - for (pi = 0; pi < nb_ports; pi++) { + FOREACH_PORT(pi, ports) { port = &ports[pi]; /* Check if there is a port which is not started */ if (port->port_status != RTE_PORT_STARTED) @@ -1276,6 +1288,45 @@ all_ports_started(void) } int +all_ports_stopped(void) +{ + portid_t pi; + struct rte_port *port; + + FOREACH_PORT(pi, ports) { + port = &ports[pi]; + if (port->port_status != RTE_PORT_STOPPED) + return 0; + } + + return 1; +} + +int +port_is_started(portid_t port_id) +{ + if (port_id_is_invalid(port_id, ENABLED_WARN)) + return 0; + + if (ports[port_id].port_status != RTE_PORT_STARTED) + return 0; + + return 1; +} + +static int +port_is_closed(portid_t port_id) +{ + if (port_id_is_invalid(port_id, ENABLED_WARN)) + return 0; + + if (ports[port_id].port_status != RTE_PORT_CLOSED) + return 0; + + return 1; +} + +int start_port(portid_t pid) { int diag, need_check_link_status = 0; @@ -1296,8 +1347,8 @@ start_port(portid_t pid) if(dcb_config) dcb_test = 1; - for (pi = 0; pi < nb_ports; pi++) { - if (pid < nb_ports && pid != pi) + FOREACH_PORT(pi, ports) { + if (pid != pi && pid != (portid_t)RTE_PORT_ALL) continue; port = &ports[pi]; @@ -1421,7 +1472,7 @@ start_port(portid_t pid) } if (need_check_link_status && !no_link_check) - check_all_ports_link_status(nb_ports, RTE_PORT_ALL); + check_all_ports_link_status(RTE_PORT_ALL); else printf("Please stop the ports first\n"); @@ -1446,8 +1497,8 @@ stop_port(portid_t pid) } printf("Stopping ports...\n"); - for (pi = 0; pi < nb_ports; pi++) { - if (pid < nb_ports && pid != pi) + FOREACH_PORT(pi, ports) { + if (!port_id_is_invalid(pid, DISABLED_WARN) && pid != pi) continue; port = &ports[pi]; @@ -1463,7 +1514,7 @@ stop_port(portid_t pid) need_check_link_status = 1; } if (need_check_link_status && !no_link_check) - check_all_ports_link_status(nb_ports, RTE_PORT_ALL); + check_all_ports_link_status(RTE_PORT_ALL); printf("Done\n"); } @@ -1481,8 +1532,8 @@ close_port(portid_t pid) printf("Closing ports...\n"); - for (pi = 0; pi < nb_ports; pi++) { - if (pid < nb_ports && pid != pi) + FOREACH_PORT(pi, ports) { + if (!port_id_is_invalid(pid, DISABLED_WARN) && pid != pi) continue; port = &ports[pi]; @@ -1502,31 +1553,83 @@ close_port(portid_t pid) printf("Done\n"); } -int -all_ports_stopped(void) +void +attach_port(char *identifier) { - portid_t pi; - struct rte_port *port; + portid_t i, j, pi = 0; - for (pi = 0; pi < nb_ports; pi++) { - port = &ports[pi]; - if (port->port_status != RTE_PORT_STOPPED) - return 0; + printf("Attaching a new port...\n"); + + if (identifier == NULL) { + printf("Invalid parameters are specified\n"); + return; } - return 1; + if (test_done == 0) { + printf("Please stop forwarding first\n"); + return; + } + + if (rte_eal_dev_attach(identifier, &pi)) + return; + + ports[pi].enabled = 1; + reconfig(pi, rte_eth_dev_socket_id(pi)); + rte_eth_promiscuous_enable(pi); + + nb_ports = rte_eth_dev_count(); + + /* set_default_fwd_ports_config(); */ + bzero(fwd_ports_ids, sizeof(fwd_ports_ids)); + i = 0; + FOREACH_PORT(j, ports) { + fwd_ports_ids[i] = j; + i++; + } + nb_cfg_ports = nb_ports; + nb_fwd_ports++; + + ports[pi].port_status = RTE_PORT_STOPPED; + + printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports); + printf("Done\n"); } -int -port_is_started(portid_t port_id) +void +detach_port(uint8_t port_id) { - if (port_id_is_invalid(port_id)) - return -1; + portid_t i, pi = 0; + char name[RTE_ETH_NAME_MAX_LEN]; - if (ports[port_id].port_status != RTE_PORT_STARTED) - return 0; + printf("Detaching a port...\n"); - return 1; + if (!port_is_closed(port_id)) { + printf("Please close port first\n"); + return; + } + + rte_eth_promiscuous_disable(port_id); + + if (rte_eal_dev_detach(port_id, name)) + return; + + ports[port_id].enabled = 0; + nb_ports = rte_eth_dev_count(); + + /* set_default_fwd_ports_config(); */ + bzero(fwd_ports_ids, sizeof(fwd_ports_ids)); + i = 0; + FOREACH_PORT(pi, ports) { + fwd_ports_ids[i] = pi; + i++; + } + nb_cfg_ports = nb_ports; + nb_fwd_ports--; + + printf("Port '%s' is detached. Now total ports is %d\n", + name, nb_ports); + printf("Done\n"); + return; } void @@ -1534,7 +1637,7 @@ pmd_test_exit(void) { portid_t pt_id; - for (pt_id = 0; pt_id < nb_ports; pt_id++) { + FOREACH_PORT(pt_id, ports) { printf("Stopping port %d...", pt_id); fflush(stdout); rte_eth_dev_close(pt_id); @@ -1553,7 +1656,7 @@ struct pmd_test_command { /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ @@ -1564,7 +1667,7 @@ check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + FOREACH_PORT(portid, ports) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -1729,7 +1832,7 @@ init_port_config(void) portid_t pid; struct rte_port *port; - for (pid = 0; pid < nb_ports; pid++) { + FOREACH_PORT(pid, ports) { port = &ports[pid]; port->dev_conf.rxmode = rx_mode; port->dev_conf.fdir_conf = fdir_conf; @@ -1908,7 +2011,7 @@ main(int argc, char** argv) nb_ports = (portid_t) rte_eth_dev_count(); if (nb_ports == 0) - rte_exit(EXIT_FAILURE, "No probed ethernet device\n"); + RTE_LOG(WARNING, EAL, "No probed ethernet devices\n"); set_def_fwd_config(); if (nb_lcores == 0) @@ -1930,7 +2033,7 @@ main(int argc, char** argv) rte_exit(EXIT_FAILURE, "Start ports failed\n"); /* set all ports to promiscuous mode by default */ - for (port_id = 0; port_id < nb_ports; port_id++) + FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); #ifdef RTE_LIBRTE_CMDLINE diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 126bef7..0d5a526 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -137,6 +137,7 @@ struct fwd_stream { * The data structure associated with each port. */ struct rte_port { + uint8_t enabled; /**< Port enabled or not */ struct rte_eth_dev_info dev_info; /**< PCI info + driver name */ struct rte_eth_conf dev_conf; /**< Port configuration. */ struct ether_addr eth_addr; /**< Port ethernet address */ @@ -162,6 +163,14 @@ struct rte_port { struct rte_eth_txconf tx_conf; /**< tx configuration */ }; +extern portid_t __rte_unused +find_next_port(portid_t p, struct rte_port *ports, int size); + +#define FOREACH_PORT(p, ports) \ + for (p = find_next_port(0, ports, RTE_MAX_ETHPORTS); \ + p < RTE_MAX_ETHPORTS; \ + p = find_next_port(p + 1, ports, RTE_MAX_ETHPORTS)) + /** * The data structure associated with each forwarding logical core. * The logical cores are internally numbered by a core index from 0 to @@ -522,6 +531,8 @@ int init_port_dcb_config(portid_t pid,struct dcb_config *dcb_conf); int start_port(portid_t pid); void stop_port(portid_t pid); void close_port(portid_t pid); +void attach_port(char *identifier); +void detach_port(uint8_t port_id); int all_ports_stopped(void); int port_is_started(portid_t port_id); void pmd_test_exit(void); @@ -548,10 +559,15 @@ void get_syn_filter(uint8_t port_id); void get_ethertype_filter(uint8_t port_id, uint16_t index); void get_2tuple_filter(uint8_t port_id, uint16_t index); void get_5tuple_filter(uint8_t port_id, uint16_t index); -int port_id_is_invalid(portid_t port_id); int rx_queue_id_is_invalid(queueid_t rxq_id); int tx_queue_id_is_invalid(queueid_t txq_id); +enum print_warning { + ENABLED_WARN = 0, + DISABLED_WARN +}; +int port_id_is_invalid(portid_t port_id, enum print_warning warning); + /* * Work-around of a compilation error with ICC on invocations of the * rte_be_to_cpu_16() function. diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index afe1970..a99e14d 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -807,6 +807,63 @@ The following sections show functions for configuring ports. Port configuration changes only become active when forwarding is started/restarted. +port attach +~~~~~~~~~~~ + +Attach a port specified by pci address or virtual device args. + +To attach a new pci device, the device should be recognized by kernel first. +Then it should be moved under DPDK management. +Finally the port can be attached to testpmd. +On the other hand, to attach a port created by virtual device, above steps are not needed. + +port attach (identifier) + +For example, to attach a port whose pci address is 0000:02:00.0. + +.. code-block:: console + + testpmd> port attach 0000:02:00.0 + Attaching a new port... + ... snip ... + Port 0 is attached. Now total ports is 1 + Done + +For example, to attach a port created by pcap PMD. + +.. code-block:: console + + testpmd> port attach eth_pcap0,iface=eth0 + Attaching a new port... + ... snip ... + Port 0 is attached. Now total ports is 1 + Done + +In this case, identifier is "eth_pcap0,iface=eth0". +This identifier format is the same as "--vdev" format of DPDK applications. + +port detach +~~~~~~~~~~~ + +Detach a specific port. + +Before detaching a port, the port should be closed. +Also to remove a pci device completely from the system, first detach the port from testpmd. +Then the device should be moved under kernel management. +Finally the device can be removed using kernel pci hotplug functionality. +On the other hand, to remove a port created by a virtual device, above steps are not needed. + +port detach (port_id) + +For example, to detach a port 0. + +.. code-block:: console + + testpmd> port detach 0 + Detaching a port... + ... snip ... + Done + port start ~~~~~~~~~~ -- 1.9.1