From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pa0-f44.google.com (mail-pa0-f44.google.com [209.85.220.44]) by dpdk.org (Postfix) with ESMTP id C22009AAD for ; Tue, 3 Feb 2015 11:26:59 +0100 (CET) Received: by mail-pa0-f44.google.com with SMTP id rd3so94544294pab.3 for ; Tue, 03 Feb 2015 02:26:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-type :content-transfer-encoding; bh=+Kza5OMLjusTpomRTcJP33hKTxKo5JLT/Q4TxC7ZbZk=; b=hEOC8e0aIO2DbpCBQEYEL2hryHi7uPsa3NS3ogBf4xStzjgH6zINdOKg5rTXYqMxIO cs4czG5t4tTEl9FLK/CRpRn3uVHQtJrR/vnQUfeXyuhzgHFcNovakhYE6oQa7bdKLvef 1mGL4u393ega6UrCRZ5uDapAt7BGh8Vs+umUR4I9QeVEYL9LnYqMizC1mT/Ist+1+/3t +QzEQdki3L8P9ldrFkqIr1CXhhS0TUt5KHzR1wQKMv7jfoAhnxTYqJwLabRlVC4DCooz kmQY2HN4ZmtZiw2QYFuZakrUVDy/5P4ybe+P/+AIMqs2uYbkCTxUzWQkXdw3ZuFtdIea v43w== X-Gm-Message-State: ALoCoQm/OyHkEegAsDfc0ViECbTXV8LtOzwV5TQtWNn3Su45Sj64dZCoq9zgAtyEFUGqD9JRyojV X-Received: by 10.66.193.228 with SMTP id hr4mr37084599pac.46.1422959219001; Tue, 03 Feb 2015 02:26:59 -0800 (PST) Received: from [10.16.129.101] (napt.igel.co.jp. [219.106.231.132]) by mx.google.com with ESMTPSA id pm2sm1687520pbb.81.2015.02.03.02.26.57 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Feb 2015 02:26:58 -0800 (PST) Message-ID: <54D0A26E.7030709@igel.co.jp> Date: Tue, 03 Feb 2015 19:26:54 +0900 From: Tetsuya Mukawa User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: "Qiu, Michael" , "dev@dpdk.org" References: <1421664027-17971-9-git-send-email-mukawa@igel.co.jp> <1422763322-13742-1-git-send-email-mukawa@igel.co.jp> <1422763322-13742-16-git-send-email-mukawa@igel.co.jp> <533710CFB86FA344BFBF2D6802E60286CD3EA9@SHSMSX101.ccr.corp.intel.com> In-Reply-To: <533710CFB86FA344BFBF2D6802E60286CD3EA9@SHSMSX101.ccr.corp.intel.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable Subject: Re: [dpdk-dev] [PATCH v6] 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: Tue, 03 Feb 2015 10:27:00 -0000 On 2015/02/03 15:59, Qiu, Michael wrote: > On 2/1/2015 12:02 PM, Tetsuya Mukawa wrote: >> 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 paramerters of virtual device. >> (ex. 0000:02:00.0, eth_pcap0,iface=3Deth0) >> - port_id: port identifier >> >> v5: >> - Add testpmd documentation. >> (Thanks to Iremonger, Bernard) >> v4: >> - Fix strings of command help. >> >> Signed-off-by: Tetsuya Mukawa >> --- >> app/test-pmd/cmdline.c | 133 +++++++++++++++----= >> app/test-pmd/config.c | 116 +++++++++------- >> 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, 415 insertions(+), 130 deletions(-) >> >> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c >> index 4beb404..2f813d8 100644 >> --- a/app/test-pmd/cmdline.c >> +++ b/app/test-pmd/cmdline.c >> @@ -572,6 +572,12 @@ static void cmd_help_long_parsed(void *parsed_res= ult, >> "port close (port_id|all)\n" >> " Close all ports or port_id.\n\n" >> =20 >> + "port attach (ident)\n" >> + " Attach physical or virtual dev by pci address or virtual devi= ce 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" >> @@ -848,6 +854,89 @@ cmdline_parse_inst_t cmd_operate_specific_port =3D= { >> }, >> }; >> =20 >> +/* *** attach a specificied 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 =3D 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 =3D >> + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, >> + port, "port"); >> +cmdline_parse_token_string_t cmd_operate_attach_port_keyword =3D >> + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, >> + keyword, "attach"); >> +cmdline_parse_token_string_t cmd_operate_attach_port_identifier =3D >> + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, >> + identifier, NULL); >> + >> +cmdline_parse_inst_t cmd_operate_attach_port =3D { >> + .f =3D cmd_operate_attach_port_parsed, >> + .data =3D NULL, >> + .help_str =3D "port attach identifier, " >> + "identifier: pci address or virtual dev name", >> + .tokens =3D { >> + (void *)&cmd_operate_attach_port_port, >> + (void *)&cmd_operate_attach_port_keyword, >> + (void *)&cmd_operate_attach_port_identifier, >> + NULL, >> + }, >> +}; >> + >> +/* *** detach a specificied 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 =3D 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 =3D >> + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, >> + port, "port"); >> +cmdline_parse_token_string_t cmd_operate_detach_port_keyword =3D >> + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, >> + keyword, "detach"); >> +cmdline_parse_token_num_t cmd_operate_detach_port_port_id =3D >> + TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result, >> + port_id, UINT8); >> + >> +cmdline_parse_inst_t cmd_operate_detach_port =3D { >> + .f =3D cmd_operate_detach_port_parsed, >> + .data =3D NULL, >> + .help_str =3D "port detach port_id", >> + .tokens =3D { >> + (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; >> @@ -902,7 +991,7 @@ cmd_config_speed_all_parsed(void *parsed_result, >> return; >> } >> =20 >> - for (pid =3D 0; pid < nb_ports; pid++) { >> + FOREACH_PORT(pid, ports) { >> ports[pid].dev_conf.link_speed =3D link_speed; >> ports[pid].dev_conf.link_duplex =3D link_duplex; >> } >> @@ -970,10 +1059,8 @@ cmd_config_speed_specific_parsed(void *parsed_re= sult, >> return; >> } >> =20 >> - if (res->id >=3D 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; >> - } >> =20 >> if (!strcmp(res->value1, "10")) >> link_speed =3D ETH_LINK_SPEED_10; >> @@ -1533,7 +1620,7 @@ cmd_config_rxtx_queue_parsed(void *parsed_result= , >> return; >> } >> =20 >> - if (port_id_is_invalid(res->portid)) >> + if (port_id_is_invalid(res->portid, ENABLED_WARN)) >> return; >> =20 >> if (port_is_started(res->portid) !=3D 1) { >> @@ -2876,7 +2963,7 @@ cmd_tx_cksum_parsed(void *parsed_result, >> uint16_t ol_flags, mask =3D 0; >> struct rte_eth_dev_info dev_info; >> =20 >> - 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; >> } >> @@ -3003,7 +3090,7 @@ cmd_tso_set_parsed(void *parsed_result, >> struct cmd_tso_set_result *res =3D parsed_result; >> struct rte_eth_dev_info dev_info; >> =20 >> - if (port_id_is_invalid(res->port_id)) >> + if (port_id_is_invalid(res->port_id, ENABLED_WARN)) >> return; >> =20 >> if (!strcmp(res->mode, "set")) >> @@ -3979,10 +4066,8 @@ static void cmd_set_bond_mac_addr_parsed(void *= parsed_result, >> struct cmd_set_bond_mac_addr_result *res =3D parsed_result; >> int ret; >> =20 >> - if (res->port_num >=3D 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; >> - } >> =20 >> ret =3D rte_eth_bond_mac_address_set(res->port_num, &res->address); >> =20 >> @@ -4219,7 +4304,7 @@ static void cmd_set_promisc_mode_parsed(void *pa= rsed_result, >> =20 >> /* all ports */ >> if (allports) { >> - for (i =3D 0; i < nb_ports; i++) { >> + FOREACH_PORT(i, ports) { >> if (enable) >> rte_eth_promiscuous_enable(i); >> else >> @@ -4299,7 +4384,7 @@ static void cmd_set_allmulti_mode_parsed(void *p= arsed_result, >> =20 >> /* all ports */ >> if (allports) { >> - for (i =3D 0; i < nb_ports; i++) { >> + FOREACH_PORT(i, ports) { >> if (enable) >> rte_eth_allmulticast_enable(i); >> else >> @@ -5484,25 +5569,25 @@ static void cmd_showportall_parsed(void *parse= d_result, >> struct cmd_showportall_result *res =3D parsed_result; >> if (!strcmp(res->show, "clear")) { >> if (!strcmp(res->what, "stats")) >> - for (i =3D 0; i < nb_ports; i++) >> + FOREACH_PORT(i, ports) >> nic_stats_clear(i); >> else if (!strcmp(res->what, "xstats")) >> - for (i =3D 0; i < nb_ports; i++) >> + FOREACH_PORT(i, ports) >> nic_xstats_clear(i); >> } else if (!strcmp(res->what, "info")) >> - for (i =3D 0; i < nb_ports; i++) >> + FOREACH_PORT(i, ports) >> port_infos_display(i); >> else if (!strcmp(res->what, "stats")) >> - for (i =3D 0; i < nb_ports; i++) >> + FOREACH_PORT(i, ports) >> nic_stats_display(i); >> else if (!strcmp(res->what, "xstats")) >> - for (i =3D 0; i < nb_ports; i++) >> + FOREACH_PORT(i, ports) >> nic_xstats_display(i); >> else if (!strcmp(res->what, "fdir")) >> - for (i =3D 0; i < nb_ports; i++) >> + FOREACH_PORT(i, ports) >> fdir_get_infos(i); >> else if (!strcmp(res->what, "stat_qmap")) >> - for (i =3D 0; i < nb_ports; i++) >> + FOREACH_PORT(i, ports) >> nic_stats_mapping_display(i); >> } >> =20 >> @@ -8756,6 +8841,8 @@ cmdline_parse_ctx_t main_ctx[] =3D { >> (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, >> @@ -8830,7 +8917,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 =3D=3D 0) >> ports[id].need_reconfig =3D dev; >> @@ -8840,7 +8927,7 @@ cmd_reconfig_device_queue(portid_t id, uint8_t d= ev, uint8_t queue) >> } else { >> portid_t pid; >> =20 >> - for (pid =3D 0; pid < nb_ports; pid++) { >> + FOREACH_PORT(pid, ports) { >> /* check if need_reconfig has been set to 1 */ >> if (ports[pid].need_reconfig =3D=3D 0) >> ports[pid].need_reconfig =3D dev; >> @@ -8858,10 +8945,8 @@ bypass_is_supported(portid_t port_id) >> struct rte_port *port; >> struct rte_pci_id *pci_id; >> =20 >> - if (port_id >=3D nb_ports) { >> - printf("\tPort id must be less than %d.\n", nb_ports); >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return 0; >> - } >> =20 >> /* Get the device id. */ >> port =3D &ports[port_id]; >> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c >> index c40f819..32d8f9a 100644 >> --- a/app/test-pmd/config.c >> +++ b/app/test-pmd/config.c >> @@ -124,11 +124,15 @@ nic_stats_display(portid_t port_id) >> struct rte_eth_stats stats; >> struct rte_port *port =3D &ports[port_id]; >> uint8_t i; >> + portid_t pid; >> =20 >> static const char *nic_stats_border =3D "########################"; >> =20 >> - if (port_id >=3D 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); >> @@ -201,8 +205,13 @@ nic_stats_display(portid_t port_id) >> void >> nic_stats_clear(portid_t port_id) >> { >> - if (port_id >=3D 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); >> @@ -249,11 +258,15 @@ nic_stats_mapping_display(portid_t port_id) >> { >> struct rte_port *port =3D &ports[port_id]; >> uint16_t i; >> + portid_t pid; >> =20 >> static const char *nic_stats_mapping_border =3D "###################= #####"; >> =20 >> - if (port_id >=3D 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; >> } >> =20 >> @@ -302,9 +315,13 @@ port_infos_display(portid_t port_id) >> int vlan_offload; >> struct rte_mempool * mp; >> static const char *info_border =3D "*********************"; >> + portid_t pid; >> =20 >> - if (port_id >=3D 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 =3D &ports[port_id]; >> @@ -362,11 +379,14 @@ port_infos_display(portid_t port_id) >> } >> =20 >> 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) > Here maybe care about overflow, it could be passed a value of > RTE_PORT_ALL, which is 255. Thanks, I will fix like above. Tetsuya > Thanks, > Michael >> return 0; >> - printf("Invalid port %d (must be < nb_ports=3D%d)\n", port_id, nb_po= rts); >> + >> + if (warning =3D=3D ENABLED_WARN) >> + printf("Invalid port %d\n", port_id); >> + >> return 1; >> } >> =20 >> @@ -425,7 +445,7 @@ port_reg_bit_display(portid_t port_id, uint32_t re= g_off, uint8_t bit_x) >> uint32_t reg_v; >> =20 >> =20 >> - 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; >> @@ -444,7 +464,7 @@ port_reg_bit_field_display(portid_t port_id, uint3= 2_t reg_off, >> uint8_t l_bit; >> uint8_t h_bit; >> =20 >> - 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; >> @@ -471,7 +491,7 @@ port_reg_display(portid_t port_id, uint32_t reg_of= f) >> { >> uint32_t reg_v; >> =20 >> - 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; >> @@ -485,7 +505,7 @@ port_reg_bit_set(portid_t port_id, uint32_t reg_of= f, uint8_t bit_pos, >> { >> uint32_t reg_v; >> =20 >> - 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; >> @@ -513,7 +533,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t = reg_off, >> uint8_t l_bit; >> uint8_t h_bit; >> =20 >> - 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; >> @@ -547,7 +567,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; >> @@ -560,7 +580,7 @@ port_mtu_set(portid_t port_id, uint16_t mtu) >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> diag =3D rte_eth_dev_set_mtu(port_id, mtu); >> if (diag =3D=3D 0) >> @@ -723,7 +743,7 @@ rx_ring_desc_display(portid_t port_id, queueid_t r= xq_id, uint16_t rxd_id) >> { >> const struct rte_memzone *rx_mz; >> =20 >> - 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; >> @@ -740,7 +760,7 @@ tx_ring_desc_display(portid_t port_id, queueid_t t= xq_id, uint16_t txd_id) >> { >> const struct rte_memzone *tx_mz; >> =20 >> - 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; >> @@ -796,7 +816,7 @@ port_rss_reta_info(portid_t port_id, >> uint16_t i, idx, shift; >> int ret; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> ret =3D rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries); >> @@ -828,7 +848,7 @@ port_rss_hash_conf_show(portid_t port_id, int show= _rss_key) >> uint8_t i; >> int diag; >> =20 >> - 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 =3D (show_rss_key) ? rss_key : NULL; >> @@ -1406,12 +1426,8 @@ set_fwd_ports_list(unsigned int *portlist, unsi= gned int nb_pt) >> again: >> for (i =3D 0; i < nb_pt; i++) { >> port_id =3D (portid_t) portlist[i]; >> - if (port_id >=3D nb_ports) { >> - printf("Invalid port id %u >=3D %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] =3D port_id; >> } >> @@ -1569,7 +1585,7 @@ vlan_extend_set(portid_t port_id, int on) >> int diag; >> int vlan_offload; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> vlan_offload =3D rte_eth_dev_get_vlan_offload(port_id); >> @@ -1591,7 +1607,7 @@ rx_vlan_strip_set(portid_t port_id, int on) >> int diag; >> int vlan_offload; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> vlan_offload =3D rte_eth_dev_get_vlan_offload(port_id); >> @@ -1612,7 +1628,7 @@ rx_vlan_strip_set_on_queue(portid_t port_id, uin= t16_t queue_id, int on) >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> diag =3D rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on);= >> @@ -1627,7 +1643,7 @@ rx_vlan_filter_set(portid_t port_id, int on) >> int diag; >> int vlan_offload; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> vlan_offload =3D rte_eth_dev_get_vlan_offload(port_id); >> @@ -1648,7 +1664,7 @@ rx_vft_set(portid_t port_id, uint16_t vlan_id, i= nt on) >> { >> int diag; >> =20 >> - 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; >> @@ -1665,7 +1681,7 @@ rx_vlan_all_filter_set(portid_t port_id, int on)= >> { >> uint16_t vlan_id; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> for (vlan_id =3D 0; vlan_id < 4096; vlan_id++) >> rx_vft_set(port_id, vlan_id, on); >> @@ -1675,7 +1691,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; >> =20 >> diag =3D rte_eth_dev_set_vlan_ether_type(port_id, tp_id); >> @@ -1690,7 +1706,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; >> @@ -1701,7 +1717,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 &=3D ~TESTPMD_TX_OFFLOAD_INSERT_VLAN; >> } >> @@ -1709,7 +1725,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; >> =20 >> rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on); >> @@ -1721,7 +1737,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 =3D 0; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_inv= alid(queue_id))) >> @@ -1773,7 +1789,7 @@ fdir_add_signature_filter(portid_t port_id, uint= 8_t queue_id, >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> diag =3D rte_eth_dev_fdir_add_signature_filter(port_id, fdir_filter,= >> @@ -1791,7 +1807,7 @@ fdir_update_signature_filter(portid_t port_id, u= int8_t queue_id, >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> diag =3D rte_eth_dev_fdir_update_signature_filter(port_id, fdir_filt= er, >> @@ -1809,7 +1825,7 @@ fdir_remove_signature_filter(portid_t port_id, >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> diag =3D rte_eth_dev_fdir_remove_signature_filter(port_id, fdir_filt= er); >> @@ -1881,7 +1897,7 @@ fdir_get_infos(portid_t port_id) >> =20 >> static const char *fdir_stats_border =3D "########################";= >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> ret =3D rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR); >> if (ret < 0) { >> @@ -1955,7 +1971,7 @@ fdir_add_perfect_filter(portid_t port_id, uint16= _t soft_id, uint8_t queue_id, >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> diag =3D rte_eth_dev_fdir_add_perfect_filter(port_id, fdir_filter, >> @@ -1973,7 +1989,7 @@ fdir_update_perfect_filter(portid_t port_id, uin= t16_t soft_id, uint8_t queue_id, >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> diag =3D rte_eth_dev_fdir_update_perfect_filter(port_id, fdir_filter= , >> @@ -1991,7 +2007,7 @@ fdir_remove_perfect_filter(portid_t port_id, uin= t16_t soft_id, >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> diag =3D rte_eth_dev_fdir_remove_perfect_filter(port_id, fdir_filter= , >> @@ -2008,7 +2024,7 @@ fdir_set_masks(portid_t port_id, struct rte_fdir= _masks *fdir_masks) >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> =20 >> diag =3D rte_eth_dev_fdir_set_masks(port_id, fdir_masks); >> @@ -2085,7 +2101,7 @@ set_vf_traffic(portid_t port_id, uint8_t is_rx, = uint16_t vf, uint8_t on) >> { >> int diag; >> =20 >> - if (port_id_is_invalid(port_id)) >> + if (port_id_is_invalid(port_id, ENABLED_WARN)) >> return; >> if (is_rx) >> diag =3D rte_eth_dev_set_vf_rx(port_id,vf,on); >> @@ -2107,7 +2123,7 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_i= d, uint64_t vf_mask, uint8_t on) >> { >> int diag; >> =20 >> - 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; >> @@ -2124,7 +2140,7 @@ set_queue_rate_limit(portid_t port_id, uint16_t = queue_idx, uint16_t rate) >> int diag; >> struct rte_eth_link link; >> =20 >> - 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) { >> @@ -2149,7 +2165,7 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf,= uint16_t rate, uint64_t q_msk) >> if (q_msk =3D=3D 0) >> return 0; >> =20 >> - 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 adf3203..6f2af18 100644 >> --- a/app/test-pmd/parameters.c >> +++ b/app/test-pmd/parameters.c >> @@ -376,6 +376,7 @@ parse_portnuma_config(const char *q_arg) >> }; >> unsigned long int_fld[_NUM_FLD]; >> char *str_fld[_NUM_FLD]; >> + portid_t pid; >> =20 >> /* reset from value set at definition */ >> while ((p =3D strchr(p0,'(')) !=3D NULL) { >> @@ -397,8 +398,11 @@ parse_portnuma_config(const char *q_arg) >> return -1; >> } >> port_id =3D (uint8_t)int_fld[FLD_PORT]; >> - if (port_id >=3D 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 =3D (uint8_t)int_fld[FLD_SOCKET]; >> @@ -429,6 +433,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 >> @@ -453,8 +458,11 @@ parse_ringnuma_config(const char *q_arg) >> return -1; >> } >> port_id =3D (uint8_t)int_fld[FLD_PORT]; >> - if (port_id >=3D 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 =3D (uint8_t)int_fld[FLD_SOCKET]; >> @@ -626,12 +634,12 @@ launch_args_parse(int argc, char** argv) >> #endif >> if (!strcmp(lgopts[opt_idx].name, "nb-ports")) { >> n =3D atoi(optarg); >> - if (n > 0 && n <=3D nb_ports) >> + if (n > 0 && >> + !port_id_is_invalid(n, DISABLED_WARN)) >> nb_fwd_ports =3D (uint8_t) n; >> else >> rte_exit(EXIT_FAILURE, >> - "nb-ports should be > 0 and <=3D %d\n", >> - nb_ports); >> + "Invalid port %d\n", n); >> } >> if (!strcmp(lgopts[opt_idx].name, "nb-cores")) { >> n =3D atoi(optarg); >> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c >> index 773b8af..c18c1a9 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 =3D 0; >> =20 >> /* 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 po= rt_mask); >> +static void check_all_ports_link_status(uint32_t port_mask); >> =20 >> /* >> * Check if all the ports are started. >> @@ -324,6 +325,20 @@ static void check_all_ports_link_status(uint8_t p= ort_num, uint32_t port_mask); >> static int all_ports_started(void); >> =20 >> /* >> + * Find next enabled port >> + */ >> +portid_t >> +find_next_port(portid_t p, struct rte_port *ports, int size) >> +{ >> + if (ports =3D=3D NULL) >> + rte_exit(-EINVAL, "failed to find a next port id\n"); >> + >> + while ((ports[p].enabled =3D=3D 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; >> =20 >> if (!numa_support) >> - nb_mbuf_per_pool =3D (nb_mbuf_per_pool * nb_ports); >> + nb_mbuf_per_pool =3D >> + (nb_mbuf_per_pool * RTE_MAX_ETHPORTS); >> } >> =20 >> if (!numa_support) { >> @@ -565,14 +581,19 @@ init_config(void) >> =20 >> /* Configuration of Ethernet ports. */ >> ports =3D rte_zmalloc("testpmd: ports", >> - sizeof(struct rte_port) * nb_ports, >> + sizeof(struct rte_port) * RTE_MAX_ETHPORTS, >> RTE_CACHE_LINE_SIZE); >> if (ports =3D=3D 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); >> } >> =20 >> - for (pid =3D 0; pid < nb_ports; pid++) { >> + /* enabled allocated ports */ >> + for (pid =3D 0; pid < nb_ports; pid++) >> + ports[pid].enabled =3D 1; >> + >> + FOREACH_PORT(pid, ports) { >> port =3D &ports[pid]; >> rte_eth_dev_info_get(pid, &port->dev_info); >> =20 >> @@ -602,8 +623,7 @@ init_config(void) >> nb_mbuf_per_pool =3D nb_mbuf_per_pool/nb_ports; >> =20 >> for (i =3D 0; i < MAX_SOCKET; i++) { >> - nb_mbuf =3D (nb_mbuf_per_pool * >> - port_per_socket[i]); >> + nb_mbuf =3D (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; >> =20 >> /* Reconfiguration of Ethernet ports. */ >> - ports =3D rte_realloc(ports, >> - sizeof(struct rte_port) * nb_ports, >> - RTE_CACHE_LINE_SIZE); >> - if (ports =3D=3D NULL) { >> - rte_exit(EXIT_FAILURE, "rte_realloc(%d struct rte_port) failed\n", >> - nb_ports); >> - } >> - >> port =3D &ports[new_port_id]; >> rte_eth_dev_info_get(new_port_id, &port->dev_info); >> =20 >> @@ -663,7 +675,7 @@ init_fwd_streams(void) >> streamid_t sm_id, nb_fwd_streams_new; >> =20 >> /* set socket id according to numa or not */ >> - for (pid =3D 0; pid < nb_ports; pid++) { >> + FOREACH_PORT(pid, ports) { >> port =3D &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; >> =20 >> - for (pi =3D 0; pi < nb_ports; pi++) { >> + FOREACH_PORT(pi, ports) { >> port =3D &ports[pi]; >> /* Check if there is a port which is not started */ >> if (port->port_status !=3D RTE_PORT_STARTED) >> @@ -1276,6 +1288,45 @@ all_ports_started(void) >> } >> =20 >> int >> +all_ports_stopped(void) >> +{ >> + portid_t pi; >> + struct rte_port *port; >> + >> + FOREACH_PORT(pi, ports) { >> + port =3D &ports[pi]; >> + if (port->port_status !=3D 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 !=3D 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 !=3D RTE_PORT_CLOSED) >> + return 0; >> + >> + return 1; >> +} >> + >> +int >> start_port(portid_t pid) >> { >> int diag, need_check_link_status =3D 0; >> @@ -1296,8 +1347,8 @@ start_port(portid_t pid) >> =20 >> if(dcb_config) >> dcb_test =3D 1; >> - for (pi =3D 0; pi < nb_ports; pi++) { >> - if (pid < nb_ports && pid !=3D pi) >> + FOREACH_PORT(pi, ports) { >> + if (!port_id_is_invalid(pid, DISABLED_WARN) && pid !=3D pi) >> continue; >> =20 >> port =3D &ports[pi]; >> @@ -1421,7 +1472,7 @@ start_port(portid_t pid) >> } >> =20 >> 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"); >> =20 >> @@ -1446,8 +1497,8 @@ stop_port(portid_t pid) >> } >> printf("Stopping ports...\n"); >> =20 >> - for (pi =3D 0; pi < nb_ports; pi++) { >> - if (pid < nb_ports && pid !=3D pi) >> + FOREACH_PORT(pi, ports) { >> + if (!port_id_is_invalid(pid, DISABLED_WARN) && pid !=3D pi) >> continue; >> =20 >> port =3D &ports[pi]; >> @@ -1463,7 +1514,7 @@ stop_port(portid_t pid) >> need_check_link_status =3D 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); >> =20 >> printf("Done\n"); >> } >> @@ -1481,8 +1532,8 @@ close_port(portid_t pid) >> =20 >> printf("Closing ports...\n"); >> =20 >> - for (pi =3D 0; pi < nb_ports; pi++) { >> - if (pid < nb_ports && pid !=3D pi) >> + FOREACH_PORT(pi, ports) { >> + if (!port_id_is_invalid(pid, DISABLED_WARN) && pid !=3D pi) >> continue; >> =20 >> port =3D &ports[pi]; >> @@ -1502,31 +1553,83 @@ close_port(portid_t pid) >> printf("Done\n"); >> } >> =20 >> -int >> -all_ports_stopped(void) >> +void >> +attach_port(char *identifier) >> { >> - portid_t pi; >> - struct rte_port *port; >> + portid_t i, j, pi =3D 0; >> =20 >> - for (pi =3D 0; pi < nb_ports; pi++) { >> - port =3D &ports[pi]; >> - if (port->port_status !=3D RTE_PORT_STOPPED) >> - return 0; >> + printf("Attaching a new port...\n"); >> + >> + if (identifier =3D=3D NULL) { >> + printf("Invalid parameters are speficied\n"); >> + return; >> } >> =20 >> - return 1; >> + if (test_done =3D=3D 0) { >> + printf("Please stop forwarding first\n"); >> + return; >> + } >> + >> + if (rte_eal_dev_attach(identifier, &pi)) >> + return; >> + >> + ports[pi].enabled =3D 1; >> + reconfig(pi, rte_eth_dev_socket_id(pi)); >> + rte_eth_promiscuous_enable(pi); >> + >> + nb_ports =3D rte_eth_dev_count(); >> + >> + /* set_default_fwd_ports_config(); */ >> + bzero(fwd_ports_ids, sizeof(fwd_ports_ids)); >> + i =3D 0; >> + FOREACH_PORT(j, ports) { >> + fwd_ports_ids[i] =3D j; >> + i++; >> + } >> + nb_cfg_ports =3D nb_ports; >> + nb_fwd_ports++; >> + >> + ports[pi].port_status =3D RTE_PORT_STOPPED; >> + >> + printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports)= ; >> + printf("Done\n"); >> } >> =20 >> -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 =3D 0; >> + char name[RTE_ETH_NAME_MAX_LEN]; >> =20 >> - if (ports[port_id].port_status !=3D RTE_PORT_STARTED) >> - return 0; >> + printf("Detaching a port...\n"); >> =20 >> - 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 =3D 0; >> + nb_ports =3D rte_eth_dev_count(); >> + >> + /* set_default_fwd_ports_config(); */ >> + bzero(fwd_ports_ids, sizeof(fwd_ports_ids)); >> + i =3D 0; >> + FOREACH_PORT(pi, ports) { >> + fwd_ports_ids[i] =3D pi; >> + i++; >> + } >> + nb_cfg_ports =3D nb_ports; >> + nb_fwd_ports--; >> + >> + printf("Port '%s' is detached. Now total ports is %d\n", >> + name, nb_ports); >> + printf("Done\n"); >> + return; >> } >> =20 >> void >> @@ -1534,7 +1637,7 @@ pmd_test_exit(void) >> { >> portid_t pt_id; >> =20 >> - for (pt_id =3D 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 { >> =20 >> /* Check the link status of all ports in up to 9s, and print them fin= ally */ >> 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, ui= nt32_t port_mask) >> fflush(stdout); >> for (count =3D 0; count <=3D MAX_CHECK_TIME; count++) { >> all_ports_up =3D 1; >> - for (portid =3D 0; portid < port_num; portid++) { >> + FOREACH_PORT(portid, ports) { >> if ((port_mask & (1 << portid)) =3D=3D 0) >> continue; >> memset(&link, 0, sizeof(link)); >> @@ -1688,7 +1791,7 @@ init_port_config(void) >> portid_t pid; >> struct rte_port *port; >> =20 >> - for (pid =3D 0; pid < nb_ports; pid++) { >> + FOREACH_PORT(pid, ports) { >> port =3D &ports[pid]; >> port->dev_conf.rxmode =3D rx_mode; >> port->dev_conf.fdir_conf =3D fdir_conf; >> @@ -1877,7 +1980,7 @@ main(int argc, char** argv) >> =20 >> nb_ports =3D (portid_t) rte_eth_dev_count(); >> if (nb_ports =3D=3D 0) >> - rte_exit(EXIT_FAILURE, "No probed ethernet device\n"); >> + RTE_LOG(WARNING, EAL, "No probed ethernet devices\n"); >> =20 >> set_def_fwd_config(); >> if (nb_lcores =3D=3D 0) >> @@ -1899,7 +2002,7 @@ main(int argc, char** argv) >> rte_exit(EXIT_FAILURE, "Start ports failed\n"); >> =20 >> /* set all ports to promiscuous mode by default */ >> - for (port_id =3D 0; port_id < nb_ports; port_id++) >> + FOREACH_PORT(port_id, ports) >> rte_eth_promiscuous_enable(port_id); >> =20 >> #ifdef RTE_LIBRTE_CMDLINE >> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h >> index 8f5e6c7..109c670 100644 >> --- a/app/test-pmd/testpmd.h >> +++ b/app/test-pmd/testpmd.h >> @@ -134,6 +134,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 */ >> @@ -159,6 +160,14 @@ struct rte_port { >> struct rte_eth_txconf tx_conf; /**< tx configuration */ >> }; >> =20 >> +extern portid_t __rte_unused >> +find_next_port(portid_t p, struct rte_port *ports, int size); >> + >> +#define FOREACH_PORT(p, ports) \ >> + for (p =3D find_next_port(0, ports, RTE_MAX_ETHPORTS); \ >> + p < RTE_MAX_ETHPORTS; \ >> + p =3D 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 t= o >> @@ -515,6 +524,8 @@ int init_port_dcb_config(portid_t pid,struct dcb_c= onfig *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); >> @@ -558,10 +569,15 @@ void get_ethertype_filter(uint8_t port_id, uint1= 6_t index); >> void get_2tuple_filter(uint8_t port_id, uint16_t index); >> void get_5tuple_filter(uint8_t port_id, uint16_t index); >> void get_flex_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); >> =20 >> +enum print_warning { >> + ENABLED_WARN =3D 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 218835a..1cacbcf 100644 >> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst >> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst >> @@ -808,6 +808,63 @@ The following sections show functions for configu= ring ports. >> =20 >> Port configuration changes only become active when forwarding is = started/restarted. >> =20 >> +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 that 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=3Deth0 >> + Attaching a new port... >> + ... snip ... >> + Port 0 is attached. Now total ports is 1 >> + Done >> + >> +In this case, identifier is "eth_pcap0,iface=3Deth0". >> +This identifier format is the same as "--vdev" format of DPDK applica= tions. >> + >> +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 remove using kernel pci hotplug functionali= ty. >> +On the other hand, to remove a port created by 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 >> ~~~~~~~~~~ >> =20