app/testpmd: align behaviour of multi-port detach
authorThomas Monjalon <thomas@monjalon.net>
Mon, 28 Sep 2020 23:14:34 +0000 (01:14 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 30 Sep 2020 17:19:14 +0000 (19:19 +0200)
A port can be closed in multiple situations:
- close command calling close_port() -> rte_eth_dev_close()
- exit calling close_port() -> rte_eth_dev_close()
- hotplug calling close_port() -> rte_eth_dev_close()
- hotplug calling detach_device() -> rte_dev_remove()
- port detach command, detach_device() -> rte_dev_remove()
- device detach command, detach_devargs() -> rte_eal_hotplug_remove()

The flow rules are flushed before each close.
It was already done in close_port(), detach_devargs() and
detach_port_device() which calls detach_device(),
but not in detach_device(). As a consequence, it was missing for siblings
of port detach command and unplugged device.
The check before calling port_flow_flush() is moved inside the function.

The state of the port to close is checked to be stopped.
As above, this check was missing in detach_device(),
impacting the cases of a multi-port device unplugged or detached
with the port detach command.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Acked-by: Stephen Hemminger <stephen@networkplumber.org>
app/test-pmd/config.c
app/test-pmd/testpmd.c

index 470c685..418ea6d 100644 (file)
@@ -1707,9 +1707,12 @@ int
 port_flow_flush(portid_t port_id)
 {
        struct rte_flow_error error;
-       struct rte_port *port;
+       struct rte_port *port = &ports[port_id];
        int ret = 0;
 
+       if (port->flow_list == NULL)
+               return ret;
+
        /* Poisoning to make sure PMDs update it in case of error. */
        memset(&error, 0x44, sizeof(error));
        if (rte_flow_flush(port_id, &error)) {
@@ -1718,7 +1721,7 @@ port_flow_flush(portid_t port_id)
                    port_id == (portid_t)RTE_PORT_ALL)
                        return ret;
        }
-       port = &ports[port_id];
+
        while (port->flow_list) {
                struct port_flow *pf = port->flow_list->next;
 
index 1e10d2e..ccba71c 100644 (file)
@@ -2695,8 +2695,7 @@ close_port(portid_t pid)
                        continue;
                }
 
-               if (port->flow_list)
-                       port_flow_flush(pi);
+               port_flow_flush(pi);
                rte_eth_dev_close(pi);
        }
 
@@ -2826,15 +2825,20 @@ detach_device(struct rte_device *dev)
 
        printf("Removing a device...\n");
 
-       if (rte_dev_remove(dev) < 0) {
-               TESTPMD_LOG(ERR, "Failed to detach device %s\n", dev->name);
-               return;
-       }
        RTE_ETH_FOREACH_DEV_OF(sibling, dev) {
                if (ports[sibling].port_status != RTE_PORT_CLOSED) {
+                       if (ports[sibling].port_status != RTE_PORT_STOPPED) {
+                               printf("Port %u not stopped\n", sibling);
+                               return;
+                       }
+                       port_flow_flush(sibling);
                }
        }
 
+       if (rte_dev_remove(dev) < 0) {
+               TESTPMD_LOG(ERR, "Failed to detach device %s\n", dev->name);
+               return;
+       }
        remove_invalid_ports();
 
        printf("Device is detached\n");
@@ -2855,8 +2859,6 @@ detach_port_device(portid_t port_id)
                        return;
                }
                printf("Port was not closed\n");
-               if (ports[port_id].flow_list)
-                       port_flow_flush(port_id);
        }
 
        detach_device(rte_eth_devices[port_id].device);
@@ -2886,9 +2888,7 @@ detach_devargs(char *identifier)
                                rte_eth_iterator_cleanup(&iterator);
                                return;
                        }
-
-                       if (ports[port_id].flow_list)
-                               port_flow_flush(port_id);
+                       port_flow_flush(port_id);
                }
        }