ovs-ofctl: New command "ofp-parse-pcap" to dump OpenFlow from PCAP files.
[sliver-openvswitch.git] / utilities / ovs-vsctl.c
index bbaaa1b..528b40c 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <config.h>
 
-#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <float.h>
@@ -115,11 +114,21 @@ static bool wait_for_reload = true;
 /* --timeout: Time to wait for a connection to 'db'. */
 static int timeout;
 
+/* --retry: If true, ovs-vsctl will retry connecting to the database forever.
+ * If false and --db says to use an active connection method (e.g. "unix:",
+ * "tcp:", "ssl:"), then ovs-vsctl will try to connect once and exit with an
+ * error if the database server cannot be contacted (e.g. ovsdb-server is not
+ * running).
+ *
+ * Regardless of this setting, --timeout always limits how long ovs-vsctl will
+ * wait. */
+static bool retry;
+
 /* Format for table output. */
 static struct table_style table_style = TABLE_STYLE_DEFAULT;
 
 /* All supported commands. */
-static const struct vsctl_command_syntax all_commands[];
+static const struct vsctl_command_syntax *get_all_commands(void);
 
 /* The IDL we're using and the current transaction, if any.
  * This is for use by vsctl_exit() only, to allow it to clean up.
@@ -187,7 +196,7 @@ main(int argc, char *argv[])
     }
 
     /* Initialize IDL. */
-    idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class, false);
+    idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class, false, retry);
     run_prerequisites(commands, n_commands, idl);
 
     /* Execute the commands.
@@ -200,6 +209,11 @@ main(int argc, char *argv[])
     seqno = ovsdb_idl_get_seqno(idl);
     for (;;) {
         ovsdb_idl_run(idl);
+        if (!ovsdb_idl_is_alive(idl)) {
+            int retval = ovsdb_idl_get_last_error(idl);
+            vsctl_fatal("%s: database connection failed (%s)",
+                        db, ovs_retval_to_string(retval));
+        }
 
         if (seqno != ovsdb_idl_get_seqno(idl)) {
             seqno = ovsdb_idl_get_seqno(idl);
@@ -248,6 +262,7 @@ parse_options(int argc, char *argv[], struct shash *local_options)
         OPT_DRY_RUN,
         OPT_PEER_CA_CERT,
         OPT_LOCAL,
+        OPT_RETRY,
         VLOG_OPTION_ENUMS,
         TABLE_OPTION_ENUMS
     };
@@ -258,6 +273,7 @@ parse_options(int argc, char *argv[], struct shash *local_options)
         {"dry-run", no_argument, NULL, OPT_DRY_RUN},
         {"oneline", no_argument, NULL, OPT_ONELINE},
         {"timeout", required_argument, NULL, 't'},
+        {"retry", no_argument, NULL, OPT_RETRY},
         {"help", no_argument, NULL, 'h'},
         {"version", no_argument, NULL, 'V'},
         VLOG_LONG_OPTIONS,
@@ -286,7 +302,7 @@ parse_options(int argc, char *argv[], struct shash *local_options)
     options = xmemdup(global_long_options, sizeof global_long_options);
     allocated_options = ARRAY_SIZE(global_long_options);
     n_options = n_global_long_options;
-    for (p = all_commands; p->name; p++) {
+    for (p = get_all_commands(); p->name; p++) {
         if (p->options[0]) {
             char *save_ptr = NULL;
             char *name;
@@ -298,7 +314,7 @@ parse_options(int argc, char *argv[], struct shash *local_options)
                 char *equals;
                 int has_arg;
 
-                assert(name[0] == '-' && name[1] == '-' && name[2]);
+                ovs_assert(name[0] == '-' && name[1] == '-' && name[2]);
                 name += 2;
 
                 equals = strchr(name, '=');
@@ -311,8 +327,8 @@ parse_options(int argc, char *argv[], struct shash *local_options)
 
                 o = find_option(name, options, n_options);
                 if (o) {
-                    assert(o - options >= n_global_long_options);
-                    assert(o->has_arg == has_arg);
+                    ovs_assert(o - options >= n_global_long_options);
+                    ovs_assert(o->has_arg == has_arg);
                 } else {
                     o = add_option(&options, &n_options, &allocated_options);
                     o->name = xstrdup(name);
@@ -385,6 +401,10 @@ parse_options(int argc, char *argv[], struct shash *local_options)
             }
             break;
 
+        case OPT_RETRY:
+            retry = true;
+            break;
+
         VLOG_OPTION_HANDLERS
         TABLE_OPTION_HANDLERS(&table_style)
 
@@ -548,7 +568,7 @@ find_command(const char *name)
     if (shash_is_empty(&commands)) {
         const struct vsctl_command_syntax *p;
 
-        for (p = all_commands; p->name; p++) {
+        for (p = get_all_commands(); p->name; p++) {
             shash_add_assert(&commands, p->name, p);
         }
     }
@@ -663,6 +683,7 @@ Options:\n\
   --db=DATABASE               connect to DATABASE\n\
                               (default: %s)\n\
   --no-wait                   do not wait for ovs-vswitchd to reconfigure\n\
+  --retry                     keep trying to connect to server forever\n\
   -t, --timeout=SECS          wait at most SECS seconds for ovs-vswitchd\n\
   --dry-run                   do not commit changes to database\n\
   --oneline                   print exactly one line of output per command\n",
@@ -845,8 +866,8 @@ ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
 static void
 del_cached_bridge(struct vsctl_context *ctx, struct vsctl_bridge *br)
 {
-    assert(list_is_empty(&br->ports));
-    assert(hmap_is_empty(&br->children));
+    ovs_assert(list_is_empty(&br->ports));
+    ovs_assert(hmap_is_empty(&br->children));
     if (br->parent) {
         hmap_remove(&br->parent->children, &br->children_node);
     }
@@ -912,7 +933,7 @@ add_port_to_cache(struct vsctl_context *ctx, struct vsctl_bridge *parent,
 static void
 del_cached_port(struct vsctl_context *ctx, struct vsctl_port *port)
 {
-    assert(list_is_empty(&port->ifaces));
+    ovs_assert(list_is_empty(&port->ifaces));
     list_remove(&port->ports_node);
     shash_find_and_delete(&ctx->ports, port->port_cfg->name);
     ovsrec_port_delete(port->port_cfg);
@@ -1133,7 +1154,7 @@ find_bridge(struct vsctl_context *ctx, const char *name, bool must_exist)
 {
     struct vsctl_bridge *br;
 
-    assert(ctx->cache_valid);
+    ovs_assert(ctx->cache_valid);
 
     br = shash_find_data(&ctx->bridges, name);
     if (must_exist && !br) {
@@ -1158,7 +1179,7 @@ find_port(struct vsctl_context *ctx, const char *name, bool must_exist)
 {
     struct vsctl_port *port;
 
-    assert(ctx->cache_valid);
+    ovs_assert(ctx->cache_valid);
 
     port = shash_find_data(&ctx->ports, name);
     if (port && !strcmp(name, port->bridge->name)) {
@@ -1176,7 +1197,7 @@ find_iface(struct vsctl_context *ctx, const char *name, bool must_exist)
 {
     struct vsctl_iface *iface;
 
-    assert(ctx->cache_valid);
+    ovs_assert(ctx->cache_valid);
 
     iface = shash_find_data(&ctx->ifaces, name);
     if (iface && !strcmp(name, iface->port->bridge->name)) {
@@ -1432,6 +1453,7 @@ pre_cmd_emer_reset(struct vsctl_context *ctx)
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_mirrors);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_netflow);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_sflow);
+    ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_ipfix);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_flood_vlans);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_other_config);
 
@@ -1456,6 +1478,8 @@ cmd_emer_reset(struct vsctl_context *ctx)
     const struct ovsrec_netflow *nf, *next_nf;
     const struct ovsrec_ssl *ssl, *next_ssl;
     const struct ovsrec_sflow *sflow, *next_sflow;
+    const struct ovsrec_ipfix *ipfix, *next_ipfix;
+    const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
 
     /* Reset the Open_vSwitch table. */
     ovsrec_open_vswitch_set_manager_options(ctx->ovs, NULL, 0);
@@ -1469,6 +1493,7 @@ cmd_emer_reset(struct vsctl_context *ctx)
         ovsrec_bridge_set_mirrors(br, NULL, 0);
         ovsrec_bridge_set_netflow(br, NULL);
         ovsrec_bridge_set_sflow(br, NULL);
+        ovsrec_bridge_set_ipfix(br, NULL);
         ovsrec_bridge_set_flood_vlans(br, NULL, 0);
 
         /* We only want to save the "hwaddr" key from other_config. */
@@ -1518,6 +1543,14 @@ cmd_emer_reset(struct vsctl_context *ctx)
         ovsrec_sflow_delete(sflow);
     }
 
+    OVSREC_IPFIX_FOR_EACH_SAFE (ipfix, next_ipfix, idl) {
+        ovsrec_ipfix_delete(ipfix);
+    }
+
+    OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH_SAFE (fscset, next_fscset, idl) {
+        ovsrec_flow_sample_collector_set_delete(fscset);
+    }
+
     vsctl_context_invalidate_cache(ctx);
 }
 
@@ -1647,6 +1680,7 @@ del_bridge(struct vsctl_context *ctx, struct vsctl_bridge *br)
 {
     struct vsctl_bridge *child, *next_child;
     struct vsctl_port *port, *next_port;
+    const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
 
     HMAP_FOR_EACH_SAFE (child, next_child, children_node, &br->children) {
         del_bridge(ctx, child);
@@ -1656,6 +1690,13 @@ del_bridge(struct vsctl_context *ctx, struct vsctl_bridge *br)
         del_port(ctx, port);
     }
 
+    OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH_SAFE (fscset, next_fscset,
+                                                    ctx->idl) {
+        if (fscset->bridge == br->br_cfg) {
+            ovsrec_flow_sample_collector_set_delete(fscset);
+        }
+    }
+
     del_cached_bridge(ctx, br);
 }
 
@@ -1975,13 +2016,20 @@ cmd_del_port(struct vsctl_context *ctx)
 {
     bool must_exist = !shash_find(&ctx->options, "--if-exists");
     bool with_iface = shash_find(&ctx->options, "--with-iface") != NULL;
+    const char *target = ctx->argv[ctx->argc - 1];
     struct vsctl_port *port;
 
     vsctl_context_populate_cache(ctx);
-    if (!with_iface) {
-        port = find_port(ctx, ctx->argv[ctx->argc - 1], must_exist);
+    if (find_bridge(ctx, target, false)) {
+        if (must_exist) {
+            vsctl_fatal("cannot delete port %s because it is the local port "
+                        "for bridge %s (deleting this port requires deleting "
+                        "the entire bridge)", target, target);
+        }
+        port = NULL;
+    } else if (!with_iface) {
+        port = find_port(ctx, target, must_exist);
     } else {
-        const char *target = ctx->argv[ctx->argc - 1];
         struct vsctl_iface *iface;
 
         port = find_port(ctx, target, false);
@@ -2443,7 +2491,8 @@ struct vsctl_table_class {
 static const struct vsctl_table_class tables[] = {
     {&ovsrec_table_bridge,
      {{&ovsrec_table_bridge, &ovsrec_bridge_col_name, NULL},
-      {NULL, NULL, NULL}}},
+      {&ovsrec_table_flow_sample_collector_set, NULL,
+       &ovsrec_flow_sample_collector_set_col_bridge}}},
 
     {&ovsrec_table_controller,
      {{&ovsrec_table_bridge,
@@ -2497,6 +2546,17 @@ static const struct vsctl_table_class tables[] = {
      {{&ovsrec_table_flow_table, &ovsrec_flow_table_col_name, NULL},
       {NULL, NULL, NULL}}},
 
+    {&ovsrec_table_ipfix,
+     {{&ovsrec_table_bridge,
+       &ovsrec_bridge_col_name,
+       &ovsrec_bridge_col_ipfix},
+      {&ovsrec_table_flow_sample_collector_set, NULL,
+       &ovsrec_flow_sample_collector_set_col_ipfix}}},
+
+    {&ovsrec_table_flow_sample_collector_set,
+     {{NULL, NULL, NULL},
+      {NULL, NULL, NULL}}},
+
     {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
 };
 
@@ -2787,7 +2847,7 @@ parse_column_key_value(const char *arg,
     char *column_name;
     char *error;
 
-    assert(!(operatorp && !valuep));
+    ovs_assert(!(operatorp && !valuep));
     *keyp = NULL;
     if (valuep) {
         *valuep = NULL;
@@ -3570,7 +3630,7 @@ post_create(struct vsctl_context *ctx)
     struct uuid dummy;
 
     if (!uuid_from_string(&dummy, ds_cstr(&ctx->output))) {
-        NOT_REACHED();
+        OVS_NOT_REACHED();
     }
     real = ovsdb_idl_txn_get_insert_uuid(ctx->txn, &dummy);
     if (real) {
@@ -3688,7 +3748,7 @@ evaluate_relop(const struct ovsdb_datum *a, const struct ovsdb_datum *b,
         return ovsdb_datum_includes_all(b, a, type);
 
     default:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
     }
 }
 
@@ -3898,8 +3958,8 @@ run_prerequisites(struct vsctl_command *commands, size_t n_commands,
             (c->syntax->prerequisites)(&ctx);
             vsctl_context_done(&ctx, c);
 
-            assert(!c->output.string);
-            assert(!c->table);
+            ovs_assert(!c->output.string);
+            ovs_assert(!c->table);
         }
     }
 }
@@ -3998,7 +4058,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
     switch (status) {
     case TXN_UNCOMMITTED:
     case TXN_INCOMPLETE:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
 
     case TXN_ABORTED:
         /* Should not happen--we never call ovsdb_idl_txn_abort(). */
@@ -4019,7 +4079,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
         vsctl_fatal("database not locked");
 
     default:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
     }
     free(error);
 
@@ -4084,6 +4144,7 @@ try_again:
     if (txn) {
         ovsdb_idl_txn_abort(txn);
         ovsdb_idl_txn_destroy(txn);
+        the_idl_txn = NULL;
     }
     ovsdb_symbol_table_destroy(symtab);
     for (c = commands; c < &commands[n_commands]; c++) {
@@ -4167,3 +4228,7 @@ static const struct vsctl_command_syntax all_commands[] = {
     {NULL, 0, 0, NULL, NULL, NULL, NULL, RO},
 };
 
+static const struct vsctl_command_syntax *get_all_commands(void)
+{
+    return all_commands;
+}