[ovs-dev] [PATCH v2] dpif: Return ENODEV from dpif_port_query_by_name() if there's no port.

Daniele Di Proietto diproiettod at vmware.com
Fri Jan 6 18:59:07 UTC 2017


bridge_delete_or_reconfigure() deletes every interface that's not dumped
by OFPROTO_PORT_FOR_EACH().  ofproto_dpif.c:port_dump_next(), used by
OFPROTO_PORT_FOR_EACH, checks if the ofport is in the datapath by
calling port_query_by_name().  If port_query_by_name() returns an error,
the dump is interrupted.  If port_query_by_name() returns ENODEV, the
device doesn't exist and the dump can continue.

port_query_by_name() for the userspace datapath returns ENOENT instead
of ENODEV.  This is expected by dpif_port_query_by_name(), but it's not
handled correctly by port_dump_next().

This commit fixes the problem by translating ENOENT in ENODEV in
dpif_port_query_by_name().

dpif-netdev handles reconfiguration errors for an interface by deleting
it from the datapath, so it's possible that a device is missing. When this
happens we must make sure that port_dump_next() continues to dump other
devices, otherwise they will be deleted and the two layers will have an
inconsistent view.

The problem was found while developing new code.

Signed-off-by: Daniele Di Proietto <diproiettod at vmware.com>
---
v2:
* Translate ENOENT into ENODEV in dpif_port_query_by_name(), instead of
  handling both in port_dump_next().
---
 lib/dpif.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/lib/dpif.c b/lib/dpif.c
index 53958c559..8ef0049c8 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -653,6 +653,8 @@ dpif_port_query_by_number(const struct dpif *dpif, odp_port_t port_no,
  * initializes '*port' appropriately; on failure, returns a positive errno
  * value.
  *
+ * Retuns ENODEV if the port doesn't exist.
+ *
  * The caller owns the data in 'port' and must free it with
  * dpif_port_destroy() when it is no longer needed. */
 int
@@ -666,12 +668,18 @@ dpif_port_query_by_name(const struct dpif *dpif, const char *devname,
     } else {
         memset(port, 0, sizeof *port);
 
-        /* For ENOENT or ENODEV we use DBG level because the caller is probably
+        if (error == ENOENT) {
+            /* Some dpif provider can return ENOENT if the port is not there,
+             * we want to translate that to ENODEV. */
+            error = ENODEV;
+        }
+
+        /* For ENODEV we use DBG level because the caller is probably
          * interested in whether 'dpif' actually has a port 'devname', so that
          * it's not an issue worth logging if it doesn't.  Other errors are
          * uncommon and more likely to indicate a real problem. */
         VLOG_RL(&error_rl,
-                error == ENOENT || error == ENODEV ? VLL_DBG : VLL_WARN,
+                error == ENODEV ? VLL_DBG : VLL_WARN,
                 "%s: failed to query port %s: %s",
                 dpif_name(dpif), devname, ovs_strerror(error));
     }
-- 
2.11.0



More information about the dev mailing list