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=eth0)
>>  - port_id: port identifier
>>
>> v5:
>> - Add testpmd documentation.
>>   (Thanks to Iremonger, Bernard)
>> v4:
>>  - Fix strings of command help.
>>
>> Signed-off-by: Tetsuya Mukawa <mukawa at igel.co.jp>

[...]

>> +static int
>> +port_is_closed(portid_t port_id)
>> +{
>> +    if (port_id_is_invalid(port_id, ENABLED_WARN))
>> +            return 0;
>> +
>> +    if (ports[port_id].port_status != RTE_PORT_CLOSED)
>> +            return 0;
>> +
>> +    return 1;
>> +}
>> +
>> +int
>>  start_port(portid_t pid)
>>  {
>>      int diag, need_check_link_status = 0;
>> @@ -1296,8 +1347,8 @@ start_port(portid_t pid)
>>  
>>      if(dcb_config)
>>              dcb_test = 1;
>> -    for (pi = 0; pi < nb_ports; pi++) {
>> -            if (pid < nb_ports && pid != pi)
>> +    FOREACH_PORT(pi, ports) {
>> +            if (!port_id_is_invalid(pid, DISABLED_WARN) && pid != pi)
> Here may it be:
>
> if (!port_id_is_invalid(pid, DISABLED_WARN) && (pid != pi || pid == 
> RET_PORT_ALL))

Sorry, should be:

if (!port_id_is_invalid(pid, DISABLED_WARN) && pid != pi && pid != 
(portid_t)RET_PORT_ALL)

Otherwise, should check for "RET_PORT_ALL" in function port_id_is_invalid()

Thanks,
Michael

> Otherwise no port will be start by default.
>
>
> Thanks,
> Michael
>
>>                      continue;
>>  
>>              port = &ports[pi];
>> @@ -1421,7 +1472,7 @@ start_port(portid_t pid)
>>      }
>>  
>>      if (need_check_link_status && !no_link_check)
>> -            check_all_ports_link_status(nb_ports, RTE_PORT_ALL);
>> +            check_all_ports_link_status(RTE_PORT_ALL);
>>      else
>>              printf("Please stop the ports first\n");
>>  
>> @@ -1446,8 +1497,8 @@ stop_port(portid_t pid)
>>      }
>>      printf("Stopping ports...\n");
>>  
>> -    for (pi = 0; pi < nb_ports; pi++) {
>> -            if (pid < nb_ports && pid != pi)
>> +    FOREACH_PORT(pi, ports) {
>> +            if (!port_id_is_invalid(pid, DISABLED_WARN) && pid != pi)
>>                      continue;
>>  
>>              port = &ports[pi];
>> @@ -1463,7 +1514,7 @@ stop_port(portid_t pid)
>>              need_check_link_status = 1;
>>      }
>>      if (need_check_link_status && !no_link_check)
>> -            check_all_ports_link_status(nb_ports, RTE_PORT_ALL);
>> +            check_all_ports_link_status(RTE_PORT_ALL);
>>  
>>      printf("Done\n");
>>  }
>> @@ -1481,8 +1532,8 @@ close_port(portid_t pid)
>>  
>>      printf("Closing ports...\n");
>>  
>> -    for (pi = 0; pi < nb_ports; pi++) {
>> -            if (pid < nb_ports && pid != pi)
>> +    FOREACH_PORT(pi, ports) {
>> +            if (!port_id_is_invalid(pid, DISABLED_WARN) && pid != pi)
>>                      continue;
>>  
>>              port = &ports[pi];
>> @@ -1502,31 +1553,83 @@ close_port(portid_t pid)
>>      printf("Done\n");
>>  }
>>  
>> -int
>> -all_ports_stopped(void)
>> +void
>> +attach_port(char *identifier)
>>  {
>> -    portid_t pi;
>> -    struct rte_port *port;
>> +    portid_t i, j, pi = 0;
>>  
>> -    for (pi = 0; pi < nb_ports; pi++) {
>> -            port = &ports[pi];
>> -            if (port->port_status != RTE_PORT_STOPPED)
>> -                    return 0;
>> +    printf("Attaching a new port...\n");
>> +
>> +    if (identifier == NULL) {
>> +            printf("Invalid parameters are speficied\n");
>> +            return;
>>      }
>>  
>> -    return 1;
>> +    if (test_done == 0) {
>> +            printf("Please stop forwarding first\n");
>> +            return;
>> +    }
>> +
>> +    if (rte_eal_dev_attach(identifier, &pi))
>> +            return;
>> +
>> +    ports[pi].enabled = 1;
>> +    reconfig(pi, rte_eth_dev_socket_id(pi));
>> +    rte_eth_promiscuous_enable(pi);
>> +
>> +    nb_ports = rte_eth_dev_count();
>> +
>> +    /* set_default_fwd_ports_config(); */
>> +    bzero(fwd_ports_ids, sizeof(fwd_ports_ids));
>> +    i = 0;
>> +    FOREACH_PORT(j, ports) {
>> +            fwd_ports_ids[i] = j;
>> +            i++;
>> +    }
>> +    nb_cfg_ports = nb_ports;
>> +    nb_fwd_ports++;
>> +
>> +    ports[pi].port_status = RTE_PORT_STOPPED;
>> +
>> +    printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);
>> +    printf("Done\n");
>>  }
>>  
>> -int
>> -port_is_started(portid_t port_id)
>> +void
>> +detach_port(uint8_t port_id)
>>  {
>> -    if (port_id_is_invalid(port_id))
>> -            return -1;
>> +    portid_t i, pi = 0;
>> +    char name[RTE_ETH_NAME_MAX_LEN];
>>  
>> -    if (ports[port_id].port_status != RTE_PORT_STARTED)
>> -            return 0;
>> +    printf("Detaching a port...\n");
>>  
>> -    return 1;
>> +    if (!port_is_closed(port_id)) {
>> +            printf("Please close port first\n");
>> +            return;
>> +    }
>> +
>> +    rte_eth_promiscuous_disable(port_id);
>> +
>> +    if (rte_eal_dev_detach(port_id, name))
>> +            return;
>> +
>> +    ports[port_id].enabled = 0;
>> +    nb_ports = rte_eth_dev_count();
>> +
>> +    /* set_default_fwd_ports_config(); */
>> +    bzero(fwd_ports_ids, sizeof(fwd_ports_ids));
>> +    i = 0;
>> +    FOREACH_PORT(pi, ports) {
>> +            fwd_ports_ids[i] = pi;
>> +            i++;
>> +    }
>> +    nb_cfg_ports = nb_ports;
>> +    nb_fwd_ports--;
>> +
>> +    printf("Port '%s' is detached. Now total ports is %d\n",
>> +                    name, nb_ports);
>> +    printf("Done\n");
>> +    return;
>>  }
>>  
>>  void
>> @@ -1534,7 +1637,7 @@ pmd_test_exit(void)
>>  {
>>      portid_t pt_id;
>>  
>> -    for (pt_id = 0; pt_id < nb_ports; pt_id++) {
>> +    FOREACH_PORT(pt_id, ports) {
>>              printf("Stopping port %d...", pt_id);
>>              fflush(stdout);
>>              rte_eth_dev_close(pt_id);
>> @@ -1553,7 +1656,7 @@ struct pmd_test_command {
>>  
>>  /* Check the link status of all ports in up to 9s, and print them finally */
>>  static void
>> -check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
>> +check_all_ports_link_status(uint32_t port_mask)
>>  {
>>  #define CHECK_INTERVAL 100 /* 100ms */
>>  #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
>> @@ -1564,7 +1667,7 @@ check_all_ports_link_status(uint8_t port_num, uint32_t 
>> port_mask)
>>      fflush(stdout);
>>      for (count = 0; count <= MAX_CHECK_TIME; count++) {
>>              all_ports_up = 1;
>> -            for (portid = 0; portid < port_num; portid++) {
>> +            FOREACH_PORT(portid, ports) {
>>                      if ((port_mask & (1 << portid)) == 0)
>>                              continue;
>>                      memset(&link, 0, sizeof(link));
>> @@ -1688,7 +1791,7 @@ init_port_config(void)
>>      portid_t pid;
>>      struct rte_port *port;
>>  
>> -    for (pid = 0; pid < nb_ports; pid++) {
>> +    FOREACH_PORT(pid, ports) {
>>              port = &ports[pid];
>>              port->dev_conf.rxmode = rx_mode;
>>              port->dev_conf.fdir_conf = fdir_conf;
>> @@ -1877,7 +1980,7 @@ main(int argc, char** argv)
>>  
>>      nb_ports = (portid_t) rte_eth_dev_count();
>>      if (nb_ports == 0)
>> -            rte_exit(EXIT_FAILURE, "No probed ethernet device\n");
>> +            RTE_LOG(WARNING, EAL, "No probed ethernet devices\n");
>>  
>>      set_def_fwd_config();
>>      if (nb_lcores == 0)
>> @@ -1899,7 +2002,7 @@ main(int argc, char** argv)
>>              rte_exit(EXIT_FAILURE, "Start ports failed\n");
>>  
>>      /* set all ports to promiscuous mode by default */
>> -    for (port_id = 0; port_id < nb_ports; port_id++)
>> +    FOREACH_PORT(port_id, ports)
>>              rte_eth_promiscuous_enable(port_id);
>>  
>>  #ifdef RTE_LIBRTE_CMDLINE
>> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
>> index 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 */
>>  };
>>  
>> +extern portid_t __rte_unused
>> +find_next_port(portid_t p, struct rte_port *ports, int size);
>> +
>> +#define FOREACH_PORT(p, ports) \
>> +    for (p = find_next_port(0, ports, RTE_MAX_ETHPORTS); \
>> +        p < RTE_MAX_ETHPORTS; \
>> +        p = find_next_port(p + 1, ports, RTE_MAX_ETHPORTS))
>> +
>>  /**
>>   * The data structure associated with each forwarding logical core.
>>   * The logical cores are internally numbered by a core index from 0 to
>> @@ -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, uint16_t 
>> index);
>>  void get_2tuple_filter(uint8_t port_id, uint16_t index);
>>  void get_5tuple_filter(uint8_t port_id, uint16_t index);
>>  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);
>>  
>> +enum print_warning {
>> +    ENABLED_WARN = 0,
>> +    DISABLED_WARN
>> +};
>> +int port_id_is_invalid(portid_t port_id, enum print_warning warning);
>> +
>>  /*
>>   * Work-around of a compilation error with ICC on invocations of the
>>   * rte_be_to_cpu_16() function.
>> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst 
>> b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>> index 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 configuring 
>> ports.
>>  
>>      Port configuration changes only become active when forwarding is 
>> started/restarted.
>>  
>> +port attach
>> +~~~~~~~~~~~
>> +
>> +Attach a port specified by pci address or virtual device args.
>> +
>> +To attach a new pci device, the device should be recognized by kernel first.
>> +Then it should be moved under DPDK management.
>> +Finally the port can be attached to testpmd.
>> +On the other hand, to attach a port created by virtual device, above steps 
>> are not needed.
>> +
>> +port attach (identifier)
>> +
>> +For example, to attach a port 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=eth0
>> +    Attaching a new port...
>> +    ... snip ...
>> +    Port 0 is attached. Now total ports is 1
>> +    Done
>> +
>> +In this case, identifier is "eth_pcap0,iface=eth0".
>> +This identifier format is the same as "--vdev" format of DPDK applications.
>> +
>> +port detach
>> +~~~~~~~~~~~
>> +
>> +Detach a specific port.
>> +
>> +Before detaching a port, the port should be closed.
>> +Also to remove a pci device completely from the system, first detach the 
>> port from testpmd.
>> +Then the device should be moved under kernel management.
>> +Finally the device can be remove using kernel pci hotplug functionality.
>> +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
>>  ~~~~~~~~~~
>>  
>

Reply via email to