[ovs-dev] [PATCH v4 2/2] ovs-vsctl: Improve error reporting

Ben Pfaff blp at nicira.com
Fri Mar 28 15:09:18 UTC 2014


Great.  Thanks Andy and Thomas, I applied these two patches to master.

I added a NEWS item:

   - ovs-vsctl now reports when ovs-vswitchd fails to create a new port or
     bridge.

On Fri, Mar 28, 2014 at 12:13:45AM -0700, Andy Zhou wrote:
> Not sure if I suppose to ack this patch since I am one of authors.
> 
> I did review v4 in detail  and tested it .
> 
> Just in case it is useful, here is my ack.
> 
> Acked-by: Andy Zhou <azhou at nicira.com>
> 
> On Thu, Mar 27, 2014 at 9:02 PM, Ben Pfaff <blp at nicira.com> wrote:
> > From: Andy Zhou <azhou at nicira.com>
> >
> > ovs-vsctl is a command-line interface to the Open vSwitch database,
> > and as such it just modifies the desired Open vSwitch configuration in
> > the database.  ovs-vswitchd, on the other hand, monitors the database
> > and implements the actual configuration specified in the database.
> > This can lead to surprises when the user makes a change to the
> > database, with ovs-vsctl, that ovs-vswitchd cannot actually
> > implement. In such a case, the ovs-vsctl command silently succeeds
> > (because the database was successfully updated) but its desired
> > effects don't actually take place. One good example of such a change
> > is attempting to add a port with a misspelled name (e.g. ``ovs-vsctl
> > add-port br0 fth0'', where fth0 should be eth0); another is creating
> > a bridge or a port whose name is longer than supported
> > (e.g. ``ovs-vsctl add-br'' with a 16-character bridge name on
> > Linux). It can take users a long time to realize the error, because it
> > requires looking through the ovs-vswitchd log.
> >
> > The patch improves the situation by checking whether operations that
> > ovs executes succeed and report an error when
> > they do not.  This patch only report add-br and add-port
> > operation errors by examining the `ofport' value that
> > ovs-vswitchd stores into the database record for the newly created
> > interface.  Until ovs-vswitchd finishes implementing the new
> > configuration, this column is empty, and after it finishes it is
> > either -1 (on failure) or a positive number (on success).
> >
> > Signed-off-by: Andy Zhou <azhou at nicira.com>
> > Co-authored-by: Thomas Graf <tgraf at redhat.com>
> > Signed-off-by: Thomas Graf <tgraf at redhat.com>
> > Co-authored-by: Ben Pfaff <blp at nicira.com>
> > Signed-off-by: Ben Pfaff <blp at nicira.com>
> > ---
> > v3->v4: See http://openvswitch.org/pipermail/dev/2014-March/038164.html for
> > changes.
> >
> >  tests/ovs-vsctl.at    |  8 +++--
> >  utilities/ovs-vsctl.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++---
> >  2 files changed, 88 insertions(+), 7 deletions(-)
> >
> > diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
> > index 851e4d8..440bf1a 100644
> > --- a/tests/ovs-vsctl.at
> > +++ b/tests/ovs-vsctl.at
> > @@ -1209,7 +1209,9 @@ m4_foreach(
> >  [vxlan_system]],
> >  [
> >  # Try creating the port
> > -AT_CHECK([ovs-vsctl add-port br0 reserved_name], [0], [], [])
> > +AT_CHECK([ovs-vsctl add-port br0 reserved_name], [0], [], [dnl
> > +ovs-vsctl: Error detected while setting up 'reserved_name'.  See ovs-vswitchd log for details.
> > +])
> >  # Detect the warning log message
> >  AT_CHECK([sed -n "s/^.*\(|bridge|WARN|.*\)$/\1/p" ovs-vswitchd.log], [0], [dnl
> >  |bridge|WARN|could not create interface reserved_name, name is reserved
> > @@ -1242,7 +1244,9 @@ m4_foreach(
> >  [vxlan_system]],
> >  [
> >  # Try creating the port
> > -AT_CHECK([ovs-vsctl add-port br0 reserved_name], [0], [], [])
> > +AT_CHECK([ovs-vsctl add-port br0 reserved_name], [0], [], [dnl
> > +ovs-vsctl: Error detected while setting up 'reserved_name'.  See ovs-vswitchd log for details.
> > +])
> >  # Detect the warning log message
> >  AT_CHECK([sed -n "s/^.*\(|bridge|WARN|.*\)$/\1/p" ovs-vswitchd.log], [0], [dnl
> >  |bridge|WARN|could not create interface reserved_name, name is reserved
> > diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
> > index 21ac777..4fcee77 100644
> > --- a/utilities/ovs-vsctl.c
> > +++ b/utilities/ovs-vsctl.c
> > @@ -1,5 +1,5 @@
> >  /*
> > - * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
> > + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
> >   *
> >   * Licensed under the Apache License, Version 2.0 (the "License");
> >   * you may not use this file except in compliance with the License.
> > @@ -165,6 +165,34 @@ static bool is_condition_satisfied(const struct vsctl_table_class *,
> >                                     const char *arg,
> >                                     struct ovsdb_symbol_table *);
> >
> > +/* Post_db_reload_check frame work is to allow ovs-vsctl to do additional
> > + * checks after OVSDB transactions are successfully recorded and reload by
> > + * ovs-vswitchd.
> > + *
> > + * For example, When a new interface is added to OVSDB, ovs-vswitchd will
> > + * either store a positive values on successful implementing the new
> > + * interface, or -1 on failure.
> > + *
> > + * Unless -no-wait command line option is specified,
> > + * post_db_reload_do_checks() is called right after any configuration
> > + * changes is picked up (i.e. reload) by ovs-vswitchd. Any error detected
> > + * post OVSDB reload is reported as ovs-vsctl errors. OVS-vswitchd logs
> > + * more detailed messages about those errors.
> > + *
> > + * Current implementation only check for Post OVSDB reload failures on new
> > + * interface additions with 'add-br' and 'add-port' commands.
> > + *
> > + * post_db_reload_expect_iface()
> > + *
> > + * keep track of interfaces to be checked post OVSDB reload. */
> > +static void post_db_reload_check_init(void);
> > +static void post_db_reload_do_checks(const struct vsctl_context *);
> > +static void post_db_reload_expect_iface(const struct ovsrec_interface *);
> > +
> > +static struct uuid *neoteric_ifaces;
> > +static size_t n_neoteric_ifaces;
> > +static size_t allocated_neoteric_ifaces;
> > +
> >  int
> >  main(int argc, char *argv[])
> >  {
> > @@ -1004,6 +1032,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
> > @@ -1561,6 +1590,7 @@ cmd_add_br(struct vsctl_context *ctx)
> >  {
> >      bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
> >      const char *br_name, *parent_name;
> > +    struct ovsrec_interface *iface;
> >      int vlan;
> >
> >      br_name = ctx->argv[1];
> > @@ -1614,7 +1644,6 @@ cmd_add_br(struct vsctl_context *ctx)
> >
> >      if (!parent_name) {
> >          struct ovsrec_port *port;
> > -        struct ovsrec_interface *iface;
> >          struct ovsrec_bridge *br;
> >
> >          iface = ovsrec_interface_insert(ctx->txn);
> > @@ -1633,7 +1662,6 @@ cmd_add_br(struct vsctl_context *ctx)
> >      } else {
> >          struct vsctl_bridge *parent;
> >          struct ovsrec_port *port;
> > -        struct ovsrec_interface *iface;
> >          struct ovsrec_bridge *br;
> >          int64_t tag = vlan;
> >
> > @@ -1659,6 +1687,7 @@ cmd_add_br(struct vsctl_context *ctx)
> >          bridge_insert_port(br, port);
> >      }
> >
> > +    post_db_reload_expect_iface(iface);
> >      vsctl_context_invalidate_cache(ctx);
> >  }
> >
> > @@ -1952,6 +1981,7 @@ add_port(struct vsctl_context *ctx,
> >      for (i = 0; i < n_ifaces; i++) {
> >          ifaces[i] = ovsrec_interface_insert(ctx->txn);
> >          ovsrec_interface_set_name(ifaces[i], iface_names[i]);
> > +        post_db_reload_expect_iface(ifaces[i]);
> >      }
> >
> >      port = ovsrec_port_insert(ctx->txn);
> > @@ -3644,6 +3674,52 @@ post_create(struct vsctl_context *ctx)
> >  }
> >
> >  static void
> > +post_db_reload_check_init(void)
> > +{
> > +    n_neoteric_ifaces = 0;
> > +}
> > +
> > +static void
> > +post_db_reload_expect_iface(const struct ovsrec_interface *iface)
> > +{
> > +    if (n_neoteric_ifaces >= allocated_neoteric_ifaces) {
> > +        neoteric_ifaces = x2nrealloc(neoteric_ifaces,
> > +                                     &allocated_neoteric_ifaces,
> > +                                     sizeof *neoteric_ifaces);
> > +    }
> > +    neoteric_ifaces[n_neoteric_ifaces++] = iface->header_.uuid;
> > +}
> > +
> > +static void
> > +post_db_reload_do_checks(const struct vsctl_context *ctx)
> > +{
> > +    struct ds dead_ifaces = DS_EMPTY_INITIALIZER;
> > +    size_t i;
> > +
> > +    for (i = 0; i < n_neoteric_ifaces; i++) {
> > +        const struct uuid *uuid;
> > +
> > +        uuid = ovsdb_idl_txn_get_insert_uuid(ctx->txn, &neoteric_ifaces[i]);
> > +        if (uuid) {
> > +            const struct ovsrec_interface *iface;
> > +
> > +            iface = ovsrec_interface_get_for_uuid(ctx->idl, uuid);
> > +            if (iface && (!iface->ofport || *iface->ofport == -1)) {
> > +                ds_put_format(&dead_ifaces, "'%s', ", iface->name);
> > +            }
> > +        }
> > +    }
> > +
> > +    if (dead_ifaces.length) {
> > +        dead_ifaces.length -= 2; /* Strip off trailing comma and space. */
> > +        ovs_error(0, "Error detected while setting up %s.  See ovs-vswitchd "
> > +                  "log for details.", ds_cstr(&dead_ifaces));
> > +    }
> > +
> > +    ds_destroy(&dead_ifaces);
> > +}
> > +
> > +static void
> >  pre_cmd_destroy(struct vsctl_context *ctx)
> >  {
> >      const char *table_name = ctx->argv[1];
> > @@ -3999,6 +4075,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
> >                                  &ovsrec_open_vswitch_col_next_cfg);
> >      }
> >
> > +    post_db_reload_check_init();
> >      symtab = ovsdb_symbol_table_create();
> >      for (c = commands; c < &commands[n_commands]; c++) {
> >          ds_init(&c->output);
> > @@ -4055,8 +4132,6 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
> >          }
> >      }
> >      error = xstrdup(ovsdb_idl_txn_get_error(txn));
> > -    ovsdb_idl_txn_destroy(txn);
> > -    txn = the_idl_txn = NULL;
> >
> >      switch (status) {
> >      case TXN_UNCOMMITTED:
> > @@ -4134,6 +4209,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
> >              ovsdb_idl_run(idl);
> >              OVSREC_OPEN_VSWITCH_FOR_EACH (ovs, idl) {
> >                  if (ovs->cur_cfg >= next_cfg) {
> > +                    post_db_reload_do_checks(&ctx);
> >                      goto done;
> >                  }
> >              }
> > @@ -4142,6 +4218,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
> >          }
> >      done: ;
> >      }
> > +    ovsdb_idl_txn_destroy(txn);
> >      ovsdb_idl_destroy(idl);
> >
> >      exit(EXIT_SUCCESS);
> > --
> > 1.8.5.3
> >



More information about the dev mailing list