From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id DC7119AA4 for ; Tue, 3 Feb 2015 08:02:23 +0100 (CET) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga102.jf.intel.com with ESMTP; 02 Feb 2015 22:58:52 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.09,511,1418112000"; d="scan'208";a="671884790" Received: from pgsmsx102.gar.corp.intel.com ([10.221.44.80]) by fmsmga002.fm.intel.com with ESMTP; 02 Feb 2015 23:02:16 -0800 Received: from shsmsx102.ccr.corp.intel.com (10.239.4.154) by PGSMSX102.gar.corp.intel.com (10.221.44.80) with Microsoft SMTP Server (TLS) id 14.3.195.1; Tue, 3 Feb 2015 14:59:30 +0800 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.253]) by shsmsx102.ccr.corp.intel.com ([169.254.2.124]) with mapi id 14.03.0195.001; Tue, 3 Feb 2015 14:59:28 +0800 From: "Qiu, Michael" To: Tetsuya Mukawa , "dev@dpdk.org" Thread-Topic: [PATCH v6] testpmd: Add port hotplug support Thread-Index: AQHQPdP23bysSjCN/EiSLvqSV3tO8A== Date: Tue, 3 Feb 2015 06:59:28 +0000 Message-ID: <533710CFB86FA344BFBF2D6802E60286CD3EA9@SHSMSX101.ccr.corp.intel.com> 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> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 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 07:02:25 -0000 On 2/1/2015 12:02 PM, Tetsuya Mukawa wrote:=0A= > The patch introduces following commands.=0A= > - port attach [ident]=0A= > - port detach [port_id]=0A= > - attach: attaching a port=0A= > - detach: detaching a port=0A= > - ident: pci address of physical device.=0A= > Or device name and paramerters of virtual device.=0A= > (ex. 0000:02:00.0, eth_pcap0,iface=3Deth0)=0A= > - port_id: port identifier=0A= >=0A= > v5:=0A= > - Add testpmd documentation.=0A= > (Thanks to Iremonger, Bernard)=0A= > v4:=0A= > - Fix strings of command help.=0A= >=0A= > Signed-off-by: Tetsuya Mukawa =0A= > ---=0A= > app/test-pmd/cmdline.c | 133 +++++++++++++++----=0A= > app/test-pmd/config.c | 116 +++++++++-------=0A= > app/test-pmd/parameters.c | 22 ++-=0A= > app/test-pmd/testpmd.c | 199 +++++++++++++++++++++-= ------=0A= > app/test-pmd/testpmd.h | 18 ++-=0A= > doc/guides/testpmd_app_ug/testpmd_funcs.rst | 57 ++++++++=0A= > 6 files changed, 415 insertions(+), 130 deletions(-)=0A= >=0A= > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c=0A= > index 4beb404..2f813d8 100644=0A= > --- a/app/test-pmd/cmdline.c=0A= > +++ b/app/test-pmd/cmdline.c=0A= > @@ -572,6 +572,12 @@ static void cmd_help_long_parsed(void *parsed_result= ,=0A= > "port close (port_id|all)\n"=0A= > " Close all ports or port_id.\n\n"=0A= > =0A= > + "port attach (ident)\n"=0A= > + " Attach physical or virtual dev by pci address or virtual device = name\n\n"=0A= > +=0A= > + "port detach (port_id)\n"=0A= > + " Detach physical or virtual dev by port_id\n\n"=0A= > +=0A= > "port config (port_id|all)"=0A= > " speed (10|100|1000|10000|40000|auto)"=0A= > " duplex (half|full|auto)\n"=0A= > @@ -848,6 +854,89 @@ cmdline_parse_inst_t cmd_operate_specific_port =3D {= =0A= > },=0A= > };=0A= > =0A= > +/* *** attach a specificied port *** */=0A= > +struct cmd_operate_attach_port_result {=0A= > + cmdline_fixed_string_t port;=0A= > + cmdline_fixed_string_t keyword;=0A= > + cmdline_fixed_string_t identifier;=0A= > +};=0A= > +=0A= > +static void cmd_operate_attach_port_parsed(void *parsed_result,=0A= > + __attribute__((unused)) struct cmdline *cl,=0A= > + __attribute__((unused)) void *data)=0A= > +{=0A= > + struct cmd_operate_attach_port_result *res =3D parsed_result;=0A= > +=0A= > + if (!strcmp(res->keyword, "attach"))=0A= > + attach_port(res->identifier);=0A= > + else=0A= > + printf("Unknown parameter\n");=0A= > +}=0A= > +=0A= > +cmdline_parse_token_string_t cmd_operate_attach_port_port =3D=0A= > + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,=0A= > + port, "port");=0A= > +cmdline_parse_token_string_t cmd_operate_attach_port_keyword =3D=0A= > + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,=0A= > + keyword, "attach");=0A= > +cmdline_parse_token_string_t cmd_operate_attach_port_identifier =3D=0A= > + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,=0A= > + identifier, NULL);=0A= > +=0A= > +cmdline_parse_inst_t cmd_operate_attach_port =3D {=0A= > + .f =3D cmd_operate_attach_port_parsed,=0A= > + .data =3D NULL,=0A= > + .help_str =3D "port attach identifier, "=0A= > + "identifier: pci address or virtual dev name",=0A= > + .tokens =3D {=0A= > + (void *)&cmd_operate_attach_port_port,=0A= > + (void *)&cmd_operate_attach_port_keyword,=0A= > + (void *)&cmd_operate_attach_port_identifier,=0A= > + NULL,=0A= > + },=0A= > +};=0A= > +=0A= > +/* *** detach a specificied port *** */=0A= > +struct cmd_operate_detach_port_result {=0A= > + cmdline_fixed_string_t port;=0A= > + cmdline_fixed_string_t keyword;=0A= > + uint8_t port_id;=0A= > +};=0A= > +=0A= > +static void cmd_operate_detach_port_parsed(void *parsed_result,=0A= > + __attribute__((unused)) struct cmdline *cl,=0A= > + __attribute__((unused)) void *data)=0A= > +{=0A= > + struct cmd_operate_detach_port_result *res =3D parsed_result;=0A= > +=0A= > + if (!strcmp(res->keyword, "detach"))=0A= > + detach_port(res->port_id);=0A= > + else=0A= > + printf("Unknown parameter\n");=0A= > +}=0A= > +=0A= > +cmdline_parse_token_string_t cmd_operate_detach_port_port =3D=0A= > + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result,=0A= > + port, "port");=0A= > +cmdline_parse_token_string_t cmd_operate_detach_port_keyword =3D=0A= > + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result,=0A= > + keyword, "detach");=0A= > +cmdline_parse_token_num_t cmd_operate_detach_port_port_id =3D=0A= > + TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result,=0A= > + port_id, UINT8);=0A= > +=0A= > +cmdline_parse_inst_t cmd_operate_detach_port =3D {=0A= > + .f =3D cmd_operate_detach_port_parsed,=0A= > + .data =3D NULL,=0A= > + .help_str =3D "port detach port_id",=0A= > + .tokens =3D {=0A= > + (void *)&cmd_operate_detach_port_port,=0A= > + (void *)&cmd_operate_detach_port_keyword,=0A= > + (void *)&cmd_operate_detach_port_port_id,=0A= > + NULL,=0A= > + },=0A= > +};=0A= > +=0A= > /* *** configure speed for all ports *** */=0A= > struct cmd_config_speed_all {=0A= > cmdline_fixed_string_t port;=0A= > @@ -902,7 +991,7 @@ cmd_config_speed_all_parsed(void *parsed_result,=0A= > return;=0A= > }=0A= > =0A= > - for (pid =3D 0; pid < nb_ports; pid++) {=0A= > + FOREACH_PORT(pid, ports) {=0A= > ports[pid].dev_conf.link_speed =3D link_speed;=0A= > ports[pid].dev_conf.link_duplex =3D link_duplex;=0A= > }=0A= > @@ -970,10 +1059,8 @@ cmd_config_speed_specific_parsed(void *parsed_resul= t,=0A= > return;=0A= > }=0A= > =0A= > - if (res->id >=3D nb_ports) {=0A= > - printf("Port id %d must be less than %d\n", res->id, nb_ports);=0A= > + if (port_id_is_invalid(res->id, ENABLED_WARN))=0A= > return;=0A= > - }=0A= > =0A= > if (!strcmp(res->value1, "10"))=0A= > link_speed =3D ETH_LINK_SPEED_10;=0A= > @@ -1533,7 +1620,7 @@ cmd_config_rxtx_queue_parsed(void *parsed_result,= =0A= > return;=0A= > }=0A= > =0A= > - if (port_id_is_invalid(res->portid))=0A= > + if (port_id_is_invalid(res->portid, ENABLED_WARN))=0A= > return;=0A= > =0A= > if (port_is_started(res->portid) !=3D 1) {=0A= > @@ -2876,7 +2963,7 @@ cmd_tx_cksum_parsed(void *parsed_result,=0A= > uint16_t ol_flags, mask =3D 0;=0A= > struct rte_eth_dev_info dev_info;=0A= > =0A= > - if (port_id_is_invalid(res->port_id)) {=0A= > + if (port_id_is_invalid(res->port_id, ENABLED_WARN)) {=0A= > printf("invalid port %d\n", res->port_id);=0A= > return;=0A= > }=0A= > @@ -3003,7 +3090,7 @@ cmd_tso_set_parsed(void *parsed_result,=0A= > struct cmd_tso_set_result *res =3D parsed_result;=0A= > struct rte_eth_dev_info dev_info;=0A= > =0A= > - if (port_id_is_invalid(res->port_id))=0A= > + if (port_id_is_invalid(res->port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > if (!strcmp(res->mode, "set"))=0A= > @@ -3979,10 +4066,8 @@ static void cmd_set_bond_mac_addr_parsed(void *par= sed_result,=0A= > struct cmd_set_bond_mac_addr_result *res =3D parsed_result;=0A= > int ret;=0A= > =0A= > - if (res->port_num >=3D nb_ports) {=0A= > - printf("Port id %d must be less than %d\n", res->port_num, nb_ports);= =0A= > + if (port_id_is_invalid(res->port_num, ENABLED_WARN))=0A= > return;=0A= > - }=0A= > =0A= > ret =3D rte_eth_bond_mac_address_set(res->port_num, &res->address);=0A= > =0A= > @@ -4219,7 +4304,7 @@ static void cmd_set_promisc_mode_parsed(void *parse= d_result,=0A= > =0A= > /* all ports */=0A= > if (allports) {=0A= > - for (i =3D 0; i < nb_ports; i++) {=0A= > + FOREACH_PORT(i, ports) {=0A= > if (enable)=0A= > rte_eth_promiscuous_enable(i);=0A= > else=0A= > @@ -4299,7 +4384,7 @@ static void cmd_set_allmulti_mode_parsed(void *pars= ed_result,=0A= > =0A= > /* all ports */=0A= > if (allports) {=0A= > - for (i =3D 0; i < nb_ports; i++) {=0A= > + FOREACH_PORT(i, ports) {=0A= > if (enable)=0A= > rte_eth_allmulticast_enable(i);=0A= > else=0A= > @@ -5484,25 +5569,25 @@ static void cmd_showportall_parsed(void *parsed_r= esult,=0A= > struct cmd_showportall_result *res =3D parsed_result;=0A= > if (!strcmp(res->show, "clear")) {=0A= > if (!strcmp(res->what, "stats"))=0A= > - for (i =3D 0; i < nb_ports; i++)=0A= > + FOREACH_PORT(i, ports)=0A= > nic_stats_clear(i);=0A= > else if (!strcmp(res->what, "xstats"))=0A= > - for (i =3D 0; i < nb_ports; i++)=0A= > + FOREACH_PORT(i, ports)=0A= > nic_xstats_clear(i);=0A= > } else if (!strcmp(res->what, "info"))=0A= > - for (i =3D 0; i < nb_ports; i++)=0A= > + FOREACH_PORT(i, ports)=0A= > port_infos_display(i);=0A= > else if (!strcmp(res->what, "stats"))=0A= > - for (i =3D 0; i < nb_ports; i++)=0A= > + FOREACH_PORT(i, ports)=0A= > nic_stats_display(i);=0A= > else if (!strcmp(res->what, "xstats"))=0A= > - for (i =3D 0; i < nb_ports; i++)=0A= > + FOREACH_PORT(i, ports)=0A= > nic_xstats_display(i);=0A= > else if (!strcmp(res->what, "fdir"))=0A= > - for (i =3D 0; i < nb_ports; i++)=0A= > + FOREACH_PORT(i, ports)=0A= > fdir_get_infos(i);=0A= > else if (!strcmp(res->what, "stat_qmap"))=0A= > - for (i =3D 0; i < nb_ports; i++)=0A= > + FOREACH_PORT(i, ports)=0A= > nic_stats_mapping_display(i);=0A= > }=0A= > =0A= > @@ -8756,6 +8841,8 @@ cmdline_parse_ctx_t main_ctx[] =3D {=0A= > (cmdline_parse_inst_t *)&cmd_set_qmap,=0A= > (cmdline_parse_inst_t *)&cmd_operate_port,=0A= > (cmdline_parse_inst_t *)&cmd_operate_specific_port,=0A= > + (cmdline_parse_inst_t *)&cmd_operate_attach_port,=0A= > + (cmdline_parse_inst_t *)&cmd_operate_detach_port,=0A= > (cmdline_parse_inst_t *)&cmd_config_speed_all,=0A= > (cmdline_parse_inst_t *)&cmd_config_speed_specific,=0A= > (cmdline_parse_inst_t *)&cmd_config_rx_tx,=0A= > @@ -8830,7 +8917,7 @@ prompt(void)=0A= > static void=0A= > cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue)=0A= > {=0A= > - if (id < nb_ports) {=0A= > + if (!port_id_is_invalid(id, DISABLED_WARN)) {=0A= > /* check if need_reconfig has been set to 1 */=0A= > if (ports[id].need_reconfig =3D=3D 0)=0A= > ports[id].need_reconfig =3D dev;=0A= > @@ -8840,7 +8927,7 @@ cmd_reconfig_device_queue(portid_t id, uint8_t dev,= uint8_t queue)=0A= > } else {=0A= > portid_t pid;=0A= > =0A= > - for (pid =3D 0; pid < nb_ports; pid++) {=0A= > + FOREACH_PORT(pid, ports) {=0A= > /* check if need_reconfig has been set to 1 */=0A= > if (ports[pid].need_reconfig =3D=3D 0)=0A= > ports[pid].need_reconfig =3D dev;=0A= > @@ -8858,10 +8945,8 @@ bypass_is_supported(portid_t port_id)=0A= > struct rte_port *port;=0A= > struct rte_pci_id *pci_id;=0A= > =0A= > - if (port_id >=3D nb_ports) {=0A= > - printf("\tPort id must be less than %d.\n", nb_ports);=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return 0;=0A= > - }=0A= > =0A= > /* Get the device id. */=0A= > port =3D &ports[port_id];=0A= > diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c=0A= > index c40f819..32d8f9a 100644=0A= > --- a/app/test-pmd/config.c=0A= > +++ b/app/test-pmd/config.c=0A= > @@ -124,11 +124,15 @@ nic_stats_display(portid_t port_id)=0A= > struct rte_eth_stats stats;=0A= > struct rte_port *port =3D &ports[port_id];=0A= > uint8_t i;=0A= > + portid_t pid;=0A= > =0A= > static const char *nic_stats_border =3D "########################";=0A= > =0A= > - if (port_id >=3D nb_ports) {=0A= > - printf("Invalid port, range is [0, %d]\n", nb_ports - 1);=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN)) {=0A= > + printf("Valid port range is [0");=0A= > + FOREACH_PORT(pid, ports)=0A= > + printf(", %d", pid);=0A= > + printf("]\n");=0A= > return;=0A= > }=0A= > rte_eth_stats_get(port_id, &stats);=0A= > @@ -201,8 +205,13 @@ nic_stats_display(portid_t port_id)=0A= > void=0A= > nic_stats_clear(portid_t port_id)=0A= > {=0A= > - if (port_id >=3D nb_ports) {=0A= > - printf("Invalid port, range is [0, %d]\n", nb_ports - 1);=0A= > + portid_t pid;=0A= > +=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN)) {=0A= > + printf("Valid port range is [0");=0A= > + FOREACH_PORT(pid, ports)=0A= > + printf(", %d", pid);=0A= > + printf("]\n");=0A= > return;=0A= > }=0A= > rte_eth_stats_reset(port_id);=0A= > @@ -249,11 +258,15 @@ nic_stats_mapping_display(portid_t port_id)=0A= > {=0A= > struct rte_port *port =3D &ports[port_id];=0A= > uint16_t i;=0A= > + portid_t pid;=0A= > =0A= > static const char *nic_stats_mapping_border =3D "######################= ##";=0A= > =0A= > - if (port_id >=3D nb_ports) {=0A= > - printf("Invalid port, range is [0, %d]\n", nb_ports - 1);=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN)) {=0A= > + printf("Valid port range is [0");=0A= > + FOREACH_PORT(pid, ports)=0A= > + printf(", %d", pid);=0A= > + printf("]\n");=0A= > return;=0A= > }=0A= > =0A= > @@ -302,9 +315,13 @@ port_infos_display(portid_t port_id)=0A= > int vlan_offload;=0A= > struct rte_mempool * mp;=0A= > static const char *info_border =3D "*********************";=0A= > + portid_t pid;=0A= > =0A= > - if (port_id >=3D nb_ports) {=0A= > - printf("Invalid port, range is [0, %d]\n", nb_ports - 1);=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN)) {=0A= > + printf("Valid port range is [0");=0A= > + FOREACH_PORT(pid, ports)=0A= > + printf(", %d", pid);=0A= > + printf("]\n");=0A= > return;=0A= > }=0A= > port =3D &ports[port_id];=0A= > @@ -362,11 +379,14 @@ port_infos_display(portid_t port_id)=0A= > }=0A= > =0A= > int=0A= > -port_id_is_invalid(portid_t port_id)=0A= > +port_id_is_invalid(portid_t port_id, enum print_warning warning)=0A= > {=0A= > - if (port_id < nb_ports)=0A= > + if (ports[port_id].enabled)=0A= =0A= Here maybe care about overflow, it could be passed a value of=0A= RTE_PORT_ALL, which is 255.=0A= =0A= Thanks,=0A= Michael=0A= > return 0;=0A= > - printf("Invalid port %d (must be < nb_ports=3D%d)\n", port_id, nb_ports= );=0A= > +=0A= > + if (warning =3D=3D ENABLED_WARN)=0A= > + printf("Invalid port %d\n", port_id);=0A= > +=0A= > return 1;=0A= > }=0A= > =0A= > @@ -425,7 +445,7 @@ port_reg_bit_display(portid_t port_id, uint32_t reg_o= ff, uint8_t bit_x)=0A= > uint32_t reg_v;=0A= > =0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (port_reg_off_is_invalid(port_id, reg_off))=0A= > return;=0A= > @@ -444,7 +464,7 @@ port_reg_bit_field_display(portid_t port_id, uint32_t= reg_off,=0A= > uint8_t l_bit;=0A= > uint8_t h_bit;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (port_reg_off_is_invalid(port_id, reg_off))=0A= > return;=0A= > @@ -471,7 +491,7 @@ port_reg_display(portid_t port_id, uint32_t reg_off)= =0A= > {=0A= > uint32_t reg_v;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (port_reg_off_is_invalid(port_id, reg_off))=0A= > return;=0A= > @@ -485,7 +505,7 @@ port_reg_bit_set(portid_t port_id, uint32_t reg_off, = uint8_t bit_pos,=0A= > {=0A= > uint32_t reg_v;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (port_reg_off_is_invalid(port_id, reg_off))=0A= > return;=0A= > @@ -513,7 +533,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg= _off,=0A= > uint8_t l_bit;=0A= > uint8_t h_bit;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (port_reg_off_is_invalid(port_id, reg_off))=0A= > return;=0A= > @@ -547,7 +567,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg= _off,=0A= > void=0A= > port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v)=0A= > {=0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (port_reg_off_is_invalid(port_id, reg_off))=0A= > return;=0A= > @@ -560,7 +580,7 @@ port_mtu_set(portid_t port_id, uint16_t mtu)=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > diag =3D rte_eth_dev_set_mtu(port_id, mtu);=0A= > if (diag =3D=3D 0)=0A= > @@ -723,7 +743,7 @@ rx_ring_desc_display(portid_t port_id, queueid_t rxq_= id, uint16_t rxd_id)=0A= > {=0A= > const struct rte_memzone *rx_mz;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (rx_queue_id_is_invalid(rxq_id))=0A= > return;=0A= > @@ -740,7 +760,7 @@ tx_ring_desc_display(portid_t port_id, queueid_t txq_= id, uint16_t txd_id)=0A= > {=0A= > const struct rte_memzone *tx_mz;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (tx_queue_id_is_invalid(txq_id))=0A= > return;=0A= > @@ -796,7 +816,7 @@ port_rss_reta_info(portid_t port_id,=0A= > uint16_t i, idx, shift;=0A= > int ret;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > ret =3D rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries);=0A= > @@ -828,7 +848,7 @@ port_rss_hash_conf_show(portid_t port_id, int show_rs= s_key)=0A= > uint8_t i;=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > /* Get RSS hash key if asked to display it */=0A= > rss_conf.rss_key =3D (show_rss_key) ? rss_key : NULL;=0A= > @@ -1406,12 +1426,8 @@ set_fwd_ports_list(unsigned int *portlist, unsigne= d int nb_pt)=0A= > again:=0A= > for (i =3D 0; i < nb_pt; i++) {=0A= > port_id =3D (portid_t) portlist[i];=0A= > - if (port_id >=3D nb_ports) {=0A= > - printf("Invalid port id %u >=3D %u\n",=0A= > - (unsigned int) port_id,=0A= > - (unsigned int) nb_ports);=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > - }=0A= > if (record_now)=0A= > fwd_ports_ids[i] =3D port_id;=0A= > }=0A= > @@ -1569,7 +1585,7 @@ vlan_extend_set(portid_t port_id, int on)=0A= > int diag;=0A= > int vlan_offload;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > vlan_offload =3D rte_eth_dev_get_vlan_offload(port_id);=0A= > @@ -1591,7 +1607,7 @@ rx_vlan_strip_set(portid_t port_id, int on)=0A= > int diag;=0A= > int vlan_offload;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > vlan_offload =3D rte_eth_dev_get_vlan_offload(port_id);=0A= > @@ -1612,7 +1628,7 @@ rx_vlan_strip_set_on_queue(portid_t port_id, uint16= _t queue_id, int on)=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > diag =3D rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on);=0A= > @@ -1627,7 +1643,7 @@ rx_vlan_filter_set(portid_t port_id, int on)=0A= > int diag;=0A= > int vlan_offload;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > vlan_offload =3D rte_eth_dev_get_vlan_offload(port_id);=0A= > @@ -1648,7 +1664,7 @@ rx_vft_set(portid_t port_id, uint16_t vlan_id, int = on)=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (vlan_id_is_invalid(vlan_id))=0A= > return;=0A= > @@ -1665,7 +1681,7 @@ rx_vlan_all_filter_set(portid_t port_id, int on)=0A= > {=0A= > uint16_t vlan_id;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > for (vlan_id =3D 0; vlan_id < 4096; vlan_id++)=0A= > rx_vft_set(port_id, vlan_id, on);=0A= > @@ -1675,7 +1691,7 @@ void=0A= > vlan_tpid_set(portid_t port_id, uint16_t tp_id)=0A= > {=0A= > int diag;=0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > diag =3D rte_eth_dev_set_vlan_ether_type(port_id, tp_id);=0A= > @@ -1690,7 +1706,7 @@ vlan_tpid_set(portid_t port_id, uint16_t tp_id)=0A= > void=0A= > tx_vlan_set(portid_t port_id, uint16_t vlan_id)=0A= > {=0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (vlan_id_is_invalid(vlan_id))=0A= > return;=0A= > @@ -1701,7 +1717,7 @@ tx_vlan_set(portid_t port_id, uint16_t vlan_id)=0A= > void=0A= > tx_vlan_reset(portid_t port_id)=0A= > {=0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > ports[port_id].tx_ol_flags &=3D ~TESTPMD_TX_OFFLOAD_INSERT_VLAN;=0A= > }=0A= > @@ -1709,7 +1725,7 @@ tx_vlan_reset(portid_t port_id)=0A= > void=0A= > tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on)=0A= > {=0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on);=0A= > @@ -1721,7 +1737,7 @@ set_qmap(portid_t port_id, uint8_t is_rx, uint16_t = queue_id, uint8_t map_value)=0A= > uint16_t i;=0A= > uint8_t existing_mapping_found =3D 0;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invali= d(queue_id)))=0A= > @@ -1773,7 +1789,7 @@ fdir_add_signature_filter(portid_t port_id, uint8_t= queue_id,=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > diag =3D rte_eth_dev_fdir_add_signature_filter(port_id, fdir_filter,=0A= > @@ -1791,7 +1807,7 @@ fdir_update_signature_filter(portid_t port_id, uint= 8_t queue_id,=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > diag =3D rte_eth_dev_fdir_update_signature_filter(port_id, fdir_filter,= =0A= > @@ -1809,7 +1825,7 @@ fdir_remove_signature_filter(portid_t port_id,=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > diag =3D rte_eth_dev_fdir_remove_signature_filter(port_id, fdir_filter)= ;=0A= > @@ -1881,7 +1897,7 @@ fdir_get_infos(portid_t port_id)=0A= > =0A= > static const char *fdir_stats_border =3D "########################";=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > ret =3D rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);=0A= > if (ret < 0) {=0A= > @@ -1955,7 +1971,7 @@ fdir_add_perfect_filter(portid_t port_id, uint16_t = soft_id, uint8_t queue_id,=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > diag =3D rte_eth_dev_fdir_add_perfect_filter(port_id, fdir_filter,=0A= > @@ -1973,7 +1989,7 @@ fdir_update_perfect_filter(portid_t port_id, uint16= _t soft_id, uint8_t queue_id,=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > diag =3D rte_eth_dev_fdir_update_perfect_filter(port_id, fdir_filter,= =0A= > @@ -1991,7 +2007,7 @@ fdir_remove_perfect_filter(portid_t port_id, uint16= _t soft_id,=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > diag =3D rte_eth_dev_fdir_remove_perfect_filter(port_id, fdir_filter,= =0A= > @@ -2008,7 +2024,7 @@ fdir_set_masks(portid_t port_id, struct rte_fdir_ma= sks *fdir_masks)=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > =0A= > diag =3D rte_eth_dev_fdir_set_masks(port_id, fdir_masks);=0A= > @@ -2085,7 +2101,7 @@ set_vf_traffic(portid_t port_id, uint8_t is_rx, uin= t16_t vf, uint8_t on)=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (is_rx)=0A= > diag =3D rte_eth_dev_set_vf_rx(port_id,vf,on);=0A= > @@ -2107,7 +2123,7 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, = uint64_t vf_mask, uint8_t on)=0A= > {=0A= > int diag;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return;=0A= > if (vlan_id_is_invalid(vlan_id))=0A= > return;=0A= > @@ -2124,7 +2140,7 @@ set_queue_rate_limit(portid_t port_id, uint16_t que= ue_idx, uint16_t rate)=0A= > int diag;=0A= > struct rte_eth_link link;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return 1;=0A= > rte_eth_link_get_nowait(port_id, &link);=0A= > if (rate > link.link_speed) {=0A= > @@ -2149,7 +2165,7 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, ui= nt16_t rate, uint64_t q_msk)=0A= > if (q_msk =3D=3D 0)=0A= > return 0;=0A= > =0A= > - if (port_id_is_invalid(port_id))=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > return 1;=0A= > rte_eth_link_get_nowait(port_id, &link);=0A= > if (rate > link.link_speed) {=0A= > diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c=0A= > index adf3203..6f2af18 100644=0A= > --- a/app/test-pmd/parameters.c=0A= > +++ b/app/test-pmd/parameters.c=0A= > @@ -376,6 +376,7 @@ parse_portnuma_config(const char *q_arg)=0A= > };=0A= > unsigned long int_fld[_NUM_FLD];=0A= > char *str_fld[_NUM_FLD];=0A= > + portid_t pid;=0A= > =0A= > /* reset from value set at definition */=0A= > while ((p =3D strchr(p0,'(')) !=3D NULL) {=0A= > @@ -397,8 +398,11 @@ parse_portnuma_config(const char *q_arg)=0A= > return -1;=0A= > }=0A= > port_id =3D (uint8_t)int_fld[FLD_PORT];=0A= > - if (port_id >=3D nb_ports) {=0A= > - printf("Invalid port, range is [0, %d]\n", nb_ports - 1);=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN)) {=0A= > + printf("Valid port range is [0");=0A= > + FOREACH_PORT(pid, ports)=0A= > + printf(", %d", pid);=0A= > + printf("]\n");=0A= > return -1;=0A= > }=0A= > socket_id =3D (uint8_t)int_fld[FLD_SOCKET];=0A= > @@ -429,6 +433,7 @@ parse_ringnuma_config(const char *q_arg)=0A= > };=0A= > unsigned long int_fld[_NUM_FLD];=0A= > char *str_fld[_NUM_FLD];=0A= > + portid_t pid;=0A= > #define RX_RING_ONLY 0x1=0A= > #define TX_RING_ONLY 0x2=0A= > #define RXTX_RING 0x3=0A= > @@ -453,8 +458,11 @@ parse_ringnuma_config(const char *q_arg)=0A= > return -1;=0A= > }=0A= > port_id =3D (uint8_t)int_fld[FLD_PORT];=0A= > - if (port_id >=3D nb_ports) {=0A= > - printf("Invalid port, range is [0, %d]\n", nb_ports - 1);=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN)) {=0A= > + printf("Valid port range is [0");=0A= > + FOREACH_PORT(pid, ports)=0A= > + printf(", %d", pid);=0A= > + printf("]\n");=0A= > return -1;=0A= > }=0A= > socket_id =3D (uint8_t)int_fld[FLD_SOCKET];=0A= > @@ -626,12 +634,12 @@ launch_args_parse(int argc, char** argv)=0A= > #endif=0A= > if (!strcmp(lgopts[opt_idx].name, "nb-ports")) {=0A= > n =3D atoi(optarg);=0A= > - if (n > 0 && n <=3D nb_ports)=0A= > + if (n > 0 &&=0A= > + !port_id_is_invalid(n, DISABLED_WARN))=0A= > nb_fwd_ports =3D (uint8_t) n;=0A= > else=0A= > rte_exit(EXIT_FAILURE,=0A= > - "nb-ports should be > 0 and <=3D %d\n",=0A= > - nb_ports);=0A= > + "Invalid port %d\n", n);=0A= > }=0A= > if (!strcmp(lgopts[opt_idx].name, "nb-cores")) {=0A= > n =3D atoi(optarg);=0A= > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c=0A= > index 773b8af..c18c1a9 100644=0A= > --- a/app/test-pmd/testpmd.c=0A= > +++ b/app/test-pmd/testpmd.c=0A= > @@ -71,6 +71,7 @@=0A= > #include =0A= > #include =0A= > #include =0A= > +#include =0A= > #include =0A= > #ifdef RTE_LIBRTE_PMD_XENVIRT=0A= > #include =0A= > @@ -315,7 +316,7 @@ uint16_t nb_rx_queue_stats_mappings =3D 0;=0A= > =0A= > /* Forward function declarations */=0A= > static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rt= e_port *port);=0A= > -static void check_all_ports_link_status(uint8_t port_num, uint32_t port_= mask);=0A= > +static void check_all_ports_link_status(uint32_t port_mask);=0A= > =0A= > /*=0A= > * Check if all the ports are started.=0A= > @@ -324,6 +325,20 @@ static void check_all_ports_link_status(uint8_t port= _num, uint32_t port_mask);=0A= > static int all_ports_started(void);=0A= > =0A= > /*=0A= > + * Find next enabled port=0A= > + */=0A= > +portid_t=0A= > +find_next_port(portid_t p, struct rte_port *ports, int size)=0A= > +{=0A= > + if (ports =3D=3D NULL)=0A= > + rte_exit(-EINVAL, "failed to find a next port id\n");=0A= > +=0A= > + while ((ports[p].enabled =3D=3D 0) && (p < size))=0A= > + p++;=0A= > + return p;=0A= > +}=0A= > +=0A= > +/*=0A= > * Setup default configuration.=0A= > */=0A= > static void=0A= > @@ -552,7 +567,8 @@ init_config(void)=0A= > + RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST;=0A= > =0A= > if (!numa_support)=0A= > - nb_mbuf_per_pool =3D (nb_mbuf_per_pool * nb_ports);=0A= > + nb_mbuf_per_pool =3D=0A= > + (nb_mbuf_per_pool * RTE_MAX_ETHPORTS);=0A= > }=0A= > =0A= > if (!numa_support) {=0A= > @@ -565,14 +581,19 @@ init_config(void)=0A= > =0A= > /* Configuration of Ethernet ports. */=0A= > ports =3D rte_zmalloc("testpmd: ports",=0A= > - sizeof(struct rte_port) * nb_ports,=0A= > + sizeof(struct rte_port) * RTE_MAX_ETHPORTS,=0A= > RTE_CACHE_LINE_SIZE);=0A= > if (ports =3D=3D NULL) {=0A= > - rte_exit(EXIT_FAILURE, "rte_zmalloc(%d struct rte_port) "=0A= > - "failed\n", nb_ports);=0A= > + rte_exit(EXIT_FAILURE,=0A= > + "rte_zmalloc(%d struct rte_port) failed\n",=0A= > + RTE_MAX_ETHPORTS);=0A= > }=0A= > =0A= > - for (pid =3D 0; pid < nb_ports; pid++) {=0A= > + /* enabled allocated ports */=0A= > + for (pid =3D 0; pid < nb_ports; pid++)=0A= > + ports[pid].enabled =3D 1;=0A= > +=0A= > + FOREACH_PORT(pid, ports) {=0A= > port =3D &ports[pid];=0A= > rte_eth_dev_info_get(pid, &port->dev_info);=0A= > =0A= > @@ -602,8 +623,7 @@ init_config(void)=0A= > nb_mbuf_per_pool =3D nb_mbuf_per_pool/nb_ports;=0A= > =0A= > for (i =3D 0; i < MAX_SOCKET; i++) {=0A= > - nb_mbuf =3D (nb_mbuf_per_pool *=0A= > - port_per_socket[i]);=0A= > + nb_mbuf =3D (nb_mbuf_per_pool * RTE_MAX_ETHPORTS);=0A= > if (nb_mbuf)=0A= > mbuf_pool_create(mbuf_data_size,=0A= > nb_mbuf,i);=0A= > @@ -635,14 +655,6 @@ reconfig(portid_t new_port_id, unsigned socket_id)= =0A= > struct rte_port *port;=0A= > =0A= > /* Reconfiguration of Ethernet ports. */=0A= > - ports =3D rte_realloc(ports,=0A= > - sizeof(struct rte_port) * nb_ports,=0A= > - RTE_CACHE_LINE_SIZE);=0A= > - if (ports =3D=3D NULL) {=0A= > - rte_exit(EXIT_FAILURE, "rte_realloc(%d struct rte_port) failed\n",=0A= > - nb_ports);=0A= > - }=0A= > -=0A= > port =3D &ports[new_port_id];=0A= > rte_eth_dev_info_get(new_port_id, &port->dev_info);=0A= > =0A= > @@ -663,7 +675,7 @@ init_fwd_streams(void)=0A= > streamid_t sm_id, nb_fwd_streams_new;=0A= > =0A= > /* set socket id according to numa or not */=0A= > - for (pid =3D 0; pid < nb_ports; pid++) {=0A= > + FOREACH_PORT(pid, ports) {=0A= > port =3D &ports[pid];=0A= > if (nb_rxq > port->dev_info.max_rx_queues) {=0A= > printf("Fail: nb_rxq(%d) is greater than "=0A= > @@ -1264,7 +1276,7 @@ all_ports_started(void)=0A= > portid_t pi;=0A= > struct rte_port *port;=0A= > =0A= > - for (pi =3D 0; pi < nb_ports; pi++) {=0A= > + FOREACH_PORT(pi, ports) {=0A= > port =3D &ports[pi];=0A= > /* Check if there is a port which is not started */=0A= > if (port->port_status !=3D RTE_PORT_STARTED)=0A= > @@ -1276,6 +1288,45 @@ all_ports_started(void)=0A= > }=0A= > =0A= > int=0A= > +all_ports_stopped(void)=0A= > +{=0A= > + portid_t pi;=0A= > + struct rte_port *port;=0A= > +=0A= > + FOREACH_PORT(pi, ports) {=0A= > + port =3D &ports[pi];=0A= > + if (port->port_status !=3D RTE_PORT_STOPPED)=0A= > + return 0;=0A= > + }=0A= > +=0A= > + return 1;=0A= > +}=0A= > +=0A= > +int=0A= > +port_is_started(portid_t port_id)=0A= > +{=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > + return 0;=0A= > +=0A= > + if (ports[port_id].port_status !=3D RTE_PORT_STARTED)=0A= > + return 0;=0A= > +=0A= > + return 1;=0A= > +}=0A= > +=0A= > +static int=0A= > +port_is_closed(portid_t port_id)=0A= > +{=0A= > + if (port_id_is_invalid(port_id, ENABLED_WARN))=0A= > + return 0;=0A= > +=0A= > + if (ports[port_id].port_status !=3D RTE_PORT_CLOSED)=0A= > + return 0;=0A= > +=0A= > + return 1;=0A= > +}=0A= > +=0A= > +int=0A= > start_port(portid_t pid)=0A= > {=0A= > int diag, need_check_link_status =3D 0;=0A= > @@ -1296,8 +1347,8 @@ start_port(portid_t pid)=0A= > =0A= > if(dcb_config)=0A= > dcb_test =3D 1;=0A= > - for (pi =3D 0; pi < nb_ports; pi++) {=0A= > - if (pid < nb_ports && pid !=3D pi)=0A= > + FOREACH_PORT(pi, ports) {=0A= > + if (!port_id_is_invalid(pid, DISABLED_WARN) && pid !=3D pi)=0A= > continue;=0A= > =0A= > port =3D &ports[pi];=0A= > @@ -1421,7 +1472,7 @@ start_port(portid_t pid)=0A= > }=0A= > =0A= > if (need_check_link_status && !no_link_check)=0A= > - check_all_ports_link_status(nb_ports, RTE_PORT_ALL);=0A= > + check_all_ports_link_status(RTE_PORT_ALL);=0A= > else=0A= > printf("Please stop the ports first\n");=0A= > =0A= > @@ -1446,8 +1497,8 @@ stop_port(portid_t pid)=0A= > }=0A= > printf("Stopping ports...\n");=0A= > =0A= > - for (pi =3D 0; pi < nb_ports; pi++) {=0A= > - if (pid < nb_ports && pid !=3D pi)=0A= > + FOREACH_PORT(pi, ports) {=0A= > + if (!port_id_is_invalid(pid, DISABLED_WARN) && pid !=3D pi)=0A= > continue;=0A= > =0A= > port =3D &ports[pi];=0A= > @@ -1463,7 +1514,7 @@ stop_port(portid_t pid)=0A= > need_check_link_status =3D 1;=0A= > }=0A= > if (need_check_link_status && !no_link_check)=0A= > - check_all_ports_link_status(nb_ports, RTE_PORT_ALL);=0A= > + check_all_ports_link_status(RTE_PORT_ALL);=0A= > =0A= > printf("Done\n");=0A= > }=0A= > @@ -1481,8 +1532,8 @@ close_port(portid_t pid)=0A= > =0A= > printf("Closing ports...\n");=0A= > =0A= > - for (pi =3D 0; pi < nb_ports; pi++) {=0A= > - if (pid < nb_ports && pid !=3D pi)=0A= > + FOREACH_PORT(pi, ports) {=0A= > + if (!port_id_is_invalid(pid, DISABLED_WARN) && pid !=3D pi)=0A= > continue;=0A= > =0A= > port =3D &ports[pi];=0A= > @@ -1502,31 +1553,83 @@ close_port(portid_t pid)=0A= > printf("Done\n");=0A= > }=0A= > =0A= > -int=0A= > -all_ports_stopped(void)=0A= > +void=0A= > +attach_port(char *identifier)=0A= > {=0A= > - portid_t pi;=0A= > - struct rte_port *port;=0A= > + portid_t i, j, pi =3D 0;=0A= > =0A= > - for (pi =3D 0; pi < nb_ports; pi++) {=0A= > - port =3D &ports[pi];=0A= > - if (port->port_status !=3D RTE_PORT_STOPPED)=0A= > - return 0;=0A= > + printf("Attaching a new port...\n");=0A= > +=0A= > + if (identifier =3D=3D NULL) {=0A= > + printf("Invalid parameters are speficied\n");=0A= > + return;=0A= > }=0A= > =0A= > - return 1;=0A= > + if (test_done =3D=3D 0) {=0A= > + printf("Please stop forwarding first\n");=0A= > + return;=0A= > + }=0A= > +=0A= > + if (rte_eal_dev_attach(identifier, &pi))=0A= > + return;=0A= > +=0A= > + ports[pi].enabled =3D 1;=0A= > + reconfig(pi, rte_eth_dev_socket_id(pi));=0A= > + rte_eth_promiscuous_enable(pi);=0A= > +=0A= > + nb_ports =3D rte_eth_dev_count();=0A= > +=0A= > + /* set_default_fwd_ports_config(); */=0A= > + bzero(fwd_ports_ids, sizeof(fwd_ports_ids));=0A= > + i =3D 0;=0A= > + FOREACH_PORT(j, ports) {=0A= > + fwd_ports_ids[i] =3D j;=0A= > + i++;=0A= > + }=0A= > + nb_cfg_ports =3D nb_ports;=0A= > + nb_fwd_ports++;=0A= > +=0A= > + ports[pi].port_status =3D RTE_PORT_STOPPED;=0A= > +=0A= > + printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);= =0A= > + printf("Done\n");=0A= > }=0A= > =0A= > -int=0A= > -port_is_started(portid_t port_id)=0A= > +void=0A= > +detach_port(uint8_t port_id)=0A= > {=0A= > - if (port_id_is_invalid(port_id))=0A= > - return -1;=0A= > + portid_t i, pi =3D 0;=0A= > + char name[RTE_ETH_NAME_MAX_LEN];=0A= > =0A= > - if (ports[port_id].port_status !=3D RTE_PORT_STARTED)=0A= > - return 0;=0A= > + printf("Detaching a port...\n");=0A= > =0A= > - return 1;=0A= > + if (!port_is_closed(port_id)) {=0A= > + printf("Please close port first\n");=0A= > + return;=0A= > + }=0A= > +=0A= > + rte_eth_promiscuous_disable(port_id);=0A= > +=0A= > + if (rte_eal_dev_detach(port_id, name))=0A= > + return;=0A= > +=0A= > + ports[port_id].enabled =3D 0;=0A= > + nb_ports =3D rte_eth_dev_count();=0A= > +=0A= > + /* set_default_fwd_ports_config(); */=0A= > + bzero(fwd_ports_ids, sizeof(fwd_ports_ids));=0A= > + i =3D 0;=0A= > + FOREACH_PORT(pi, ports) {=0A= > + fwd_ports_ids[i] =3D pi;=0A= > + i++;=0A= > + }=0A= > + nb_cfg_ports =3D nb_ports;=0A= > + nb_fwd_ports--;=0A= > +=0A= > + printf("Port '%s' is detached. Now total ports is %d\n",=0A= > + name, nb_ports);=0A= > + printf("Done\n");=0A= > + return;=0A= > }=0A= > =0A= > void=0A= > @@ -1534,7 +1637,7 @@ pmd_test_exit(void)=0A= > {=0A= > portid_t pt_id;=0A= > =0A= > - for (pt_id =3D 0; pt_id < nb_ports; pt_id++) {=0A= > + FOREACH_PORT(pt_id, ports) {=0A= > printf("Stopping port %d...", pt_id);=0A= > fflush(stdout);=0A= > rte_eth_dev_close(pt_id);=0A= > @@ -1553,7 +1656,7 @@ struct pmd_test_command {=0A= > =0A= > /* Check the link status of all ports in up to 9s, and print them finall= y */=0A= > static void=0A= > -check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)=0A= > +check_all_ports_link_status(uint32_t port_mask)=0A= > {=0A= > #define CHECK_INTERVAL 100 /* 100ms */=0A= > #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */=0A= > @@ -1564,7 +1667,7 @@ check_all_ports_link_status(uint8_t port_num, uint3= 2_t port_mask)=0A= > fflush(stdout);=0A= > for (count =3D 0; count <=3D MAX_CHECK_TIME; count++) {=0A= > all_ports_up =3D 1;=0A= > - for (portid =3D 0; portid < port_num; portid++) {=0A= > + FOREACH_PORT(portid, ports) {=0A= > if ((port_mask & (1 << portid)) =3D=3D 0)=0A= > continue;=0A= > memset(&link, 0, sizeof(link));=0A= > @@ -1688,7 +1791,7 @@ init_port_config(void)=0A= > portid_t pid;=0A= > struct rte_port *port;=0A= > =0A= > - for (pid =3D 0; pid < nb_ports; pid++) {=0A= > + FOREACH_PORT(pid, ports) {=0A= > port =3D &ports[pid];=0A= > port->dev_conf.rxmode =3D rx_mode;=0A= > port->dev_conf.fdir_conf =3D fdir_conf;=0A= > @@ -1877,7 +1980,7 @@ main(int argc, char** argv)=0A= > =0A= > nb_ports =3D (portid_t) rte_eth_dev_count();=0A= > if (nb_ports =3D=3D 0)=0A= > - rte_exit(EXIT_FAILURE, "No probed ethernet device\n");=0A= > + RTE_LOG(WARNING, EAL, "No probed ethernet devices\n");=0A= > =0A= > set_def_fwd_config();=0A= > if (nb_lcores =3D=3D 0)=0A= > @@ -1899,7 +2002,7 @@ main(int argc, char** argv)=0A= > rte_exit(EXIT_FAILURE, "Start ports failed\n");=0A= > =0A= > /* set all ports to promiscuous mode by default */=0A= > - for (port_id =3D 0; port_id < nb_ports; port_id++)=0A= > + FOREACH_PORT(port_id, ports)=0A= > rte_eth_promiscuous_enable(port_id);=0A= > =0A= > #ifdef RTE_LIBRTE_CMDLINE=0A= > diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h=0A= > index 8f5e6c7..109c670 100644=0A= > --- a/app/test-pmd/testpmd.h=0A= > +++ b/app/test-pmd/testpmd.h=0A= > @@ -134,6 +134,7 @@ struct fwd_stream {=0A= > * The data structure associated with each port.=0A= > */=0A= > struct rte_port {=0A= > + uint8_t enabled; /**< Port enabled or not */=0A= > struct rte_eth_dev_info dev_info; /**< PCI info + driver name */=0A= > struct rte_eth_conf dev_conf; /**< Port configuration. */=0A= > struct ether_addr eth_addr; /**< Port ethernet address */=0A= > @@ -159,6 +160,14 @@ struct rte_port {=0A= > struct rte_eth_txconf tx_conf; /**< tx configuration */=0A= > };=0A= > =0A= > +extern portid_t __rte_unused=0A= > +find_next_port(portid_t p, struct rte_port *ports, int size);=0A= > +=0A= > +#define FOREACH_PORT(p, ports) \=0A= > + for (p =3D find_next_port(0, ports, RTE_MAX_ETHPORTS); \=0A= > + p < RTE_MAX_ETHPORTS; \=0A= > + p =3D find_next_port(p + 1, ports, RTE_MAX_ETHPORTS))=0A= > +=0A= > /**=0A= > * The data structure associated with each forwarding logical core.=0A= > * The logical cores are internally numbered by a core index from 0 to= =0A= > @@ -515,6 +524,8 @@ int init_port_dcb_config(portid_t pid,struct dcb_conf= ig *dcb_conf);=0A= > int start_port(portid_t pid);=0A= > void stop_port(portid_t pid);=0A= > void close_port(portid_t pid);=0A= > +void attach_port(char *identifier);=0A= > +void detach_port(uint8_t port_id);=0A= > int all_ports_stopped(void);=0A= > int port_is_started(portid_t port_id);=0A= > void pmd_test_exit(void);=0A= > @@ -558,10 +569,15 @@ void get_ethertype_filter(uint8_t port_id, uint16_t= index);=0A= > void get_2tuple_filter(uint8_t port_id, uint16_t index);=0A= > void get_5tuple_filter(uint8_t port_id, uint16_t index);=0A= > void get_flex_filter(uint8_t port_id, uint16_t index);=0A= > -int port_id_is_invalid(portid_t port_id);=0A= > int rx_queue_id_is_invalid(queueid_t rxq_id);=0A= > int tx_queue_id_is_invalid(queueid_t txq_id);=0A= > =0A= > +enum print_warning {=0A= > + ENABLED_WARN =3D 0,=0A= > + DISABLED_WARN=0A= > +};=0A= > +int port_id_is_invalid(portid_t port_id, enum print_warning warning);=0A= > +=0A= > /*=0A= > * Work-around of a compilation error with ICC on invocations of the=0A= > * rte_be_to_cpu_16() function.=0A= > diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/tes= tpmd_app_ug/testpmd_funcs.rst=0A= > index 218835a..1cacbcf 100644=0A= > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst=0A= > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst=0A= > @@ -808,6 +808,63 @@ The following sections show functions for configurin= g ports.=0A= > =0A= > Port configuration changes only become active when forwarding is sta= rted/restarted.=0A= > =0A= > +port attach=0A= > +~~~~~~~~~~~=0A= > +=0A= > +Attach a port specified by pci address or virtual device args.=0A= > +=0A= > +To attach a new pci device, the device should be recognized by kernel fi= rst.=0A= > +Then it should be moved under DPDK management.=0A= > +Finally the port can be attached to testpmd.=0A= > +On the other hand, to attach a port created by virtual device, above ste= ps are not needed.=0A= > +=0A= > +port attach (identifier)=0A= > +=0A= > +For example, to attach a port that pci address is 0000:02:00.0.=0A= > +=0A= > +.. code-block:: console=0A= > +=0A= > + testpmd> port attach 0000:02:00.0=0A= > + Attaching a new port...=0A= > + ... snip ...=0A= > + Port 0 is attached. Now total ports is 1=0A= > + Done=0A= > +=0A= > +For example, to attach a port created by pcap PMD.=0A= > +=0A= > +.. code-block:: console=0A= > +=0A= > + testpmd> port attach eth_pcap0,iface=3Deth0=0A= > + Attaching a new port...=0A= > + ... snip ...=0A= > + Port 0 is attached. Now total ports is 1=0A= > + Done=0A= > +=0A= > +In this case, identifier is "eth_pcap0,iface=3Deth0".=0A= > +This identifier format is the same as "--vdev" format of DPDK applicatio= ns.=0A= > +=0A= > +port detach=0A= > +~~~~~~~~~~~=0A= > +=0A= > +Detach a specific port.=0A= > +=0A= > +Before detaching a port, the port should be closed.=0A= > +Also to remove a pci device completely from the system, first detach the= port from testpmd.=0A= > +Then the device should be moved under kernel management.=0A= > +Finally the device can be remove using kernel pci hotplug functionality.= =0A= > +On the other hand, to remove a port created by virtual device, above ste= ps are not needed.=0A= > +=0A= > +port detach (port_id)=0A= > +=0A= > +For example, to detach a port 0.=0A= > +=0A= > +.. code-block:: console=0A= > +=0A= > + testpmd> port detach 0=0A= > + Detaching a port...=0A= > + ... snip ...=0A= > + Done=0A= > +=0A= > port start=0A= > ~~~~~~~~~~=0A= > =0A= =0A=