[ovs-dev] [PATCH] ovs-vsctl: Check "ofport" column after adding a new port

Thomas Graf tgraf at redhat.com
Tue Dec 11 23:48:44 UTC 2012


When adding a new port or bond, save the port name and check
the "ofport" column of that port after the database has been
reloaded. It will contain OFPP_NONE (-1) if the addition
process failed inside the bridge. Print an error message and
exit ovs-vsctl with -EFAULT in that case.

Note that this is not 100% reliable. Another user may have
modified the database which may have caused the port addition
to fail.

Cc: Ben Pfaff <blp at nicira.com>
Signed-off-by: Thomas Graf <tgraf at redhat.com>
---
 utilities/ovs-vsctl.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 2 deletions(-)

diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index bccb2c9..ead635b 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -733,6 +733,11 @@ struct vsctl_context {
     /* A command may set this member to true if some prerequisite is not met
      * and the caller should wait for something to change and then retry. */
     bool try_again;
+
+    /* A command may set this member to a port name to trigger checking the
+     * "ofport" column after the database reload for OFPP_NONE and indicate
+     * an error. */
+    char *check_ofport;
 };
 
 struct vsctl_bridge {
@@ -981,6 +986,7 @@ pre_get_info(struct vsctl_context *ctx)
     ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_interfaces);
 
     ovsdb_idl_add_column(ctx->idl, &ovsrec_interface_col_name);
+    ovsdb_idl_add_column(ctx->idl, &ovsrec_interface_col_ofport);
 }
 
 static void
@@ -1934,6 +1940,8 @@ add_port(struct vsctl_context *ctx,
         add_iface_to_cache(ctx, vsctl_port, ifaces[i]);
     }
     free(ifaces);
+
+    ctx->check_ofport = xstrdup(port_name);
 }
 
 static void
@@ -3880,6 +3888,50 @@ run_prerequisites(struct vsctl_command *commands, size_t n_commands,
     }
 }
 
+static struct ovsrec_interface *
+find_failed_interface(const struct ovsrec_open_vswitch *ovs, const char *name)
+{
+    int i, j, k;
+
+    for (i = 0; i < ovs->n_bridges; i++) {
+        struct ovsrec_bridge *br = ovs->bridges[i];
+
+        for (j = 0; j < br->n_ports; j++) {
+            struct ovsrec_port *port = br->ports[j];
+
+            if (strcmp(port->name, name))
+                continue;
+
+            for (k = 0; k < port->n_interfaces; k++) {
+                struct ovsrec_interface *iface = port->interfaces[k];
+
+                if (iface->n_ofport &&
+                    *((uint16_t *) iface->ofport) == OFPP_NONE)
+                    return iface;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+static int
+post_db_reload_checks(struct vsctl_context *ctx)
+{
+    int err = EXIT_SUCCESS;
+
+    if (ctx->check_ofport) {
+        if (find_failed_interface(ctx->ovs, ctx->check_ofport)) {
+            vsctl_fatal("Unable to add port '%s'", ctx->check_ofport);
+            err = -EFAULT;
+        }
+    }
+
+    free(ctx->check_ofport);
+
+    return err;
+}
+
 static void
 do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
          struct ovsdb_idl *idl)
@@ -3893,6 +3945,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
     struct shash_node *node;
     int64_t next_cfg = 0;
     char *error = NULL;
+    int ret = EXIT_SUCCESS;
 
     txn = the_idl_txn = ovsdb_idl_txn_create(idl);
     if (dry_run) {
@@ -4048,11 +4101,12 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
             ovsdb_idl_wait(idl);
             poll_block();
         }
-    done: ;
+    done:
+        ret = post_db_reload_checks(&ctx);
     }
     ovsdb_idl_destroy(idl);
 
-    exit(EXIT_SUCCESS);
+    exit(ret);
 
 try_again:
     /* Our transaction needs to be rerun, or a prerequisite was not met.  Free
-- 
1.7.11.7




More information about the dev mailing list