From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pa0-f45.google.com (mail-pa0-f45.google.com [209.85.220.45]) by dpdk.org (Postfix) with ESMTP id C2F4F9AB5 for ; Tue, 3 Feb 2015 11:29:53 +0100 (CET) Received: by mail-pa0-f45.google.com with SMTP id et14so94706896pad.4 for ; Tue, 03 Feb 2015 02:29:53 -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 :subject:references:in-reply-to:content-type :content-transfer-encoding; bh=KcnvzgyB+MHaLFU3Eh6gLQTZ8UKLeB2omqbLCJ1gU4U=; b=ceF2NafIo5t7TydZoh9a25gmyEVipbRLBdpTmc+Raxrb1PpIBWHmBFoP7mf9fhIWBH ttjX+muhE1h6A7meYx91EIYrx6JFODRxu3tZdmjM7ektWRCK3G7aXknkuVo8HrlNYlLP hiV4kxbBQ1FZMipox5qRAAvAoV5MBj32jlOpBFlUGbPf6lbtpuwPj8eUkQbQbl9vhGXD LtLJAsQr9q5kJeKFyyu4/fZP7Y0gUY23OEfkLJTASdzepGB/1Q4EQ0Z+Vk35eJH62GFm yq4FgWs1+ZF9aRLG4tGoLDw4tO/UnzCt6vYEiVT6N+jm6h2uuhIeFY4lYi22bIFcPvat E51A== X-Gm-Message-State: ALoCoQlo1yM1r8M0P6yD3qAvzXf117JlPBVSZiZn39XcUQHDzF6rT2qfepPMPGZHFgrbyvVtzLU+ X-Received: by 10.66.149.199 with SMTP id uc7mr36938851pab.22.1422959392864; Tue, 03 Feb 2015 02:29:52 -0800 (PST) Received: from [10.16.129.101] (napt.igel.co.jp. [219.106.231.132]) by mx.google.com with ESMTPSA id uq7sm1703491pbc.48.2015.02.03.02.29.51 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Feb 2015 02:29:52 -0800 (PST) Message-ID: <54D0A31C.2030903@igel.co.jp> Date: Tue, 03 Feb 2015 19:29:48 +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> <533710CFB86FA344BFBF2D6802E60286CD3E56@SHSMSX101.ccr.corp.intel.com> <533710CFB86FA344BFBF2D6802E60286CD3F7D@SHSMSX101.ccr.corp.intel.com> In-Reply-To: <533710CFB86FA344BFBF2D6802E60286CD3F7D@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:29:54 -0000 On 2015/02/03 18:14, Qiu, Michael wrote: > On 2/3/2015 2:16 PM, 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 > [...] > >>> +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) >> Here may it be: >> >> if (!port_id_is_invalid(pid, DISABLED_WARN) && (pid !=3D pi || pid =3D= =3D RET_PORT_ALL)) > Sorry, should be: > > if (!port_id_is_invalid(pid, DISABLED_WARN) && pid !=3D pi && pid !=3D = (portid_t)RET_PORT_ALL) > > Otherwise, should check for "RET_PORT_ALL" in function port_id_is_inval= id() Thanks for comment. I've found 2 issues. (I guess the original code has same issue.) One is that "port_id_is_invalid" should receives "pi" instead of "pid". The other is if statement is wrong as you said. I guess following statement will be good. if (port_id_is_invalid(pi, DISABLED_WARN) || (pid !=3D pi && pid !=3D (portid_t)RTE_PORT_ALL)) How about it? Thanks, Tetsuya > Thanks, > Michael > >> Otherwise no port will be start by default. >> >> >> Thanks, >> Michael >> >>> 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 fi= nally */ >>> 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, u= int32_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 = to >>> @@ -515,6 +524,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); >>> @@ -558,10 +569,15 @@ void get_ethertype_filter(uint8_t port_id, uint= 16_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 config= uring 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 kerne= l 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 applic= ations. >>> + >>> +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 functional= ity. >>> +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