tests: Add ovs-openflowd to programs that need valgrind wrappers.
[openvswitch] / utilities / ovs-vsctl.c
index 80c9048b1b8e1fd6cf4c2ef34d9ad63349ac88ba..2c1ba6df229bfa76cc04fb2609ca8c88be2d8885 100644 (file)
@@ -38,6 +38,7 @@
 #include "process.h"
 #include "stream.h"
 #include "stream-ssl.h"
+#include "sset.h"
 #include "svec.h"
 #include "vswitchd/vswitch-idl.h"
 #include "table.h"
@@ -757,7 +758,7 @@ static void
 get_info(struct vsctl_context *ctx, struct vsctl_info *info)
 {
     const struct ovsrec_open_vswitch *ovs = ctx->ovs;
-    struct shash bridges, ports;
+    struct sset bridges, ports;
     size_t i;
 
     info->ctx = ctx;
@@ -765,14 +766,14 @@ get_info(struct vsctl_context *ctx, struct vsctl_info *info)
     shash_init(&info->ports);
     shash_init(&info->ifaces);
 
-    shash_init(&bridges);
-    shash_init(&ports);
+    sset_init(&bridges);
+    sset_init(&ports);
     for (i = 0; i < ovs->n_bridges; i++) {
         struct ovsrec_bridge *br_cfg = ovs->bridges[i];
         struct vsctl_bridge *br;
         size_t j;
 
-        if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
+        if (!sset_add(&bridges, br_cfg->name)) {
             VLOG_WARN("%s: database contains duplicate bridge name",
                       br_cfg->name);
             continue;
@@ -785,29 +786,29 @@ get_info(struct vsctl_context *ctx, struct vsctl_info *info)
         for (j = 0; j < br_cfg->n_ports; j++) {
             struct ovsrec_port *port_cfg = br_cfg->ports[j];
 
-            if (!shash_add_once(&ports, port_cfg->name, NULL)) {
+            if (!sset_add(&ports, port_cfg->name)) {
                 VLOG_WARN("%s: database contains duplicate port name",
                           port_cfg->name);
                 continue;
             }
 
             if (port_is_fake_bridge(port_cfg)
-                && shash_add_once(&bridges, port_cfg->name, NULL)) {
+                && sset_add(&bridges, port_cfg->name)) {
                 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
             }
         }
     }
-    shash_destroy(&bridges);
-    shash_destroy(&ports);
+    sset_destroy(&bridges);
+    sset_destroy(&ports);
 
-    shash_init(&bridges);
-    shash_init(&ports);
+    sset_init(&bridges);
+    sset_init(&ports);
     for (i = 0; i < ovs->n_bridges; i++) {
         struct ovsrec_bridge *br_cfg = ovs->bridges[i];
         struct vsctl_bridge *br;
         size_t j;
 
-        if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
+        if (!sset_add(&bridges, br_cfg->name)) {
             continue;
         }
         br = shash_find_data(&info->bridges, br_cfg->name);
@@ -816,12 +817,12 @@ get_info(struct vsctl_context *ctx, struct vsctl_info *info)
             struct vsctl_port *port;
             size_t k;
 
-            if (!shash_add_once(&ports, port_cfg->name, NULL)) {
+            if (!sset_add(&ports, port_cfg->name)) {
                 continue;
             }
 
             if (port_is_fake_bridge(port_cfg)
-                && !shash_add_once(&bridges, port_cfg->name, NULL)) {
+                && !sset_add(&bridges, port_cfg->name)) {
                 continue;
             }
 
@@ -855,8 +856,8 @@ get_info(struct vsctl_context *ctx, struct vsctl_info *info)
             }
         }
     }
-    shash_destroy(&bridges);
-    shash_destroy(&ports);
+    sset_destroy(&bridges);
+    sset_destroy(&ports);
 }
 
 static void
@@ -1035,6 +1036,12 @@ cmd_emer_reset(struct vsctl_context *ctx)
     const struct ovsrec_bridge *br;
     const struct ovsrec_port *port;
     const struct ovsrec_interface *iface;
+    const struct ovsrec_mirror *mirror, *next_mirror;
+    const struct ovsrec_controller *ctrl, *next_ctrl;
+    const struct ovsrec_manager *mgr, *next_mgr;
+    const struct ovsrec_netflow *nf, *next_nf;
+    const struct ovsrec_ssl *ssl, *next_ssl;
+    const struct ovsrec_sflow *sflow, *next_sflow;
 
     /* Reset the Open_vSwitch table. */
     ovsrec_open_vswitch_set_manager_options(ctx->ovs, NULL, 0);
@@ -1078,6 +1085,30 @@ cmd_emer_reset(struct vsctl_context *ctx)
         ovsrec_interface_set_ingress_policing_rate(iface, 0);
         ovsrec_interface_set_ingress_policing_burst(iface, 0);
     }
+
+    OVSREC_MIRROR_FOR_EACH_SAFE (mirror, next_mirror, idl) {
+        ovsrec_mirror_delete(mirror);
+    }
+
+    OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl, next_ctrl, idl) {
+        ovsrec_controller_delete(ctrl);
+    }
+
+    OVSREC_MANAGER_FOR_EACH_SAFE (mgr, next_mgr, idl) {
+        ovsrec_manager_delete(mgr);
+    }
+
+    OVSREC_NETFLOW_FOR_EACH_SAFE (nf, next_nf, idl) {
+        ovsrec_netflow_delete(nf);
+    }
+
+    OVSREC_SSL_FOR_EACH_SAFE (ssl, next_ssl, idl) {
+        ovsrec_ssl_delete(ssl);
+    }
+
+    OVSREC_SFLOW_FOR_EACH_SAFE (sflow, next_sflow, idl) {
+        ovsrec_sflow_delete(sflow);
+    }
 }
 
 static void
@@ -1188,8 +1219,18 @@ cmd_add_br(struct vsctl_context *ctx)
 }
 
 static void
-del_port(struct vsctl_port *port)
+del_port(struct vsctl_info *info, struct vsctl_port *port)
 {
+    struct shash_node *node;
+
+    SHASH_FOR_EACH (node, &info->ifaces) {
+        struct vsctl_iface *iface = node->data;
+        if (iface->port == port) {
+            ovsrec_interface_delete(iface->iface_cfg);
+        }
+    }
+    ovsrec_port_delete(port->port_cfg);
+
     bridge_delete_port((port->bridge->parent
                         ? port->bridge->parent->br_cfg
                         : port->bridge->br_cfg), port->port_cfg);
@@ -1205,19 +1246,19 @@ cmd_del_br(struct vsctl_context *ctx)
     get_info(ctx, &info);
     bridge = find_bridge(&info, ctx->argv[1], must_exist);
     if (bridge) {
-        if (bridge->br_cfg) {
-            ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
-        } else {
-            struct shash_node *node;
+        struct shash_node *node;
 
-            SHASH_FOR_EACH (node, &info.ports) {
-                struct vsctl_port *port = node->data;
-                if (port->bridge == bridge || port->bridge->parent == bridge
-                    || !strcmp(port->port_cfg->name, bridge->name)) {
-                    del_port(port);
-                }
+        SHASH_FOR_EACH (node, &info.ports) {
+            struct vsctl_port *port = node->data;
+            if (port->bridge == bridge || port->bridge->parent == bridge
+                || !strcmp(port->port_cfg->name, bridge->name)) {
+                del_port(&info, port);
             }
         }
+        if (bridge->br_cfg) {
+            ovsrec_bridge_delete(bridge->br_cfg);
+            ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
+        }
     }
     free_info(&info);
 }
@@ -1601,7 +1642,7 @@ cmd_del_port(struct vsctl_context *ctx)
             }
         }
 
-        del_port(port);
+        del_port(&info, port);
     }
 
     free_info(&info);
@@ -1733,6 +1774,17 @@ cmd_get_controller(struct vsctl_context *ctx)
     free_info(&info);
 }
 
+static void
+delete_controllers(struct ovsrec_controller **controllers,
+                   size_t n_controllers)
+{
+    size_t i;
+
+    for (i = 0; i < n_controllers; i++) {
+        ovsrec_controller_delete(controllers[i]);
+    }
+}
+
 static void
 cmd_del_controller(struct vsctl_context *ctx)
 {
@@ -1742,7 +1794,12 @@ cmd_del_controller(struct vsctl_context *ctx)
     get_info(ctx, &info);
 
     br = find_real_bridge(&info, ctx->argv[1], true);
-    ovsrec_bridge_set_controller(br->br_cfg, NULL, 0);
+    verify_controllers(br->br_cfg);
+
+    if (br->ctrl) {
+        delete_controllers(br->ctrl, br->n_ctrl);
+        ovsrec_bridge_set_controller(br->br_cfg, NULL, 0);
+    }
 
     free_info(&info);
 }
@@ -1772,6 +1829,9 @@ cmd_set_controller(struct vsctl_context *ctx)
 
     get_info(ctx, &info);
     br = find_real_bridge(&info, ctx->argv[1], true);
+    verify_controllers(br->br_cfg);
+
+    delete_controllers(br->ctrl, br->n_ctrl);
 
     n = ctx->argc - 2;
     controllers = insert_controllers(ctx->txn, &ctx->argv[2], n);
@@ -1878,13 +1938,29 @@ cmd_get_manager(struct vsctl_context *ctx)
 }
 
 static void
-cmd_del_manager(struct vsctl_context *ctx)
+delete_managers(const struct vsctl_context *ctx)
 {
     const struct ovsrec_open_vswitch *ovs = ctx->ovs;
+    size_t i;
 
+    /* Delete Manager rows pointed to by 'manager_options' column. */
+    for (i = 0; i < ovs->n_manager_options; i++) {
+        ovsrec_manager_delete(ovs->manager_options[i]);
+    }
+
+    /* Delete 'Manager' row refs in 'manager_options' column. */
     ovsrec_open_vswitch_set_manager_options(ovs, NULL, 0);
 }
 
+static void
+cmd_del_manager(struct vsctl_context *ctx)
+{
+    const struct ovsrec_open_vswitch *ovs = ctx->ovs;
+
+    verify_managers(ovs);
+    delete_managers(ctx);
+}
+
 static void
 insert_managers(struct vsctl_context *ctx, char *targets[], size_t n)
 {
@@ -1908,6 +1984,8 @@ cmd_set_manager(struct vsctl_context *ctx)
 {
     const size_t n = ctx->argc - 1;
 
+    verify_managers(ctx->ovs);
+    delete_managers(ctx);
     insert_managers(ctx, &ctx->argv[1], n);
 }
 
@@ -1951,7 +2029,13 @@ pre_cmd_del_ssl(struct vsctl_context *ctx)
 static void
 cmd_del_ssl(struct vsctl_context *ctx)
 {
-    ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
+    struct ovsrec_ssl *ssl = ctx->ovs->ssl;
+
+    if (ssl) {
+        ovsrec_open_vswitch_verify_ssl(ctx->ovs);
+        ovsrec_ssl_delete(ssl);
+        ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
+    }
 }
 
 static void
@@ -1964,8 +2048,12 @@ static void
 cmd_set_ssl(struct vsctl_context *ctx)
 {
     bool bootstrap = shash_find(&ctx->options, "--bootstrap");
-    struct ovsrec_ssl *ssl;
+    struct ovsrec_ssl *ssl = ctx->ovs->ssl;
 
+    ovsrec_open_vswitch_verify_ssl(ctx->ovs);
+    if (ssl) {
+        ovsrec_ssl_delete(ssl);
+    }
     ssl = ovsrec_ssl_insert(ctx->txn);
 
     ovsrec_ssl_set_private_key(ssl, ctx->argv[1]);
@@ -2415,9 +2503,6 @@ parse_column_key_value(const char *arg,
         }
         *valuep = xstrdup(p + best_len);
     } else {
-        if (valuep) {
-            *valuep = NULL;
-        }
         if (*p != '\0') {
             error = xasprintf("%s: trailing garbage \"%s\" in argument",
                               arg, p);
@@ -2715,11 +2800,9 @@ cmd_list(struct vsctl_context *ctx)
         }
     } else {
         const struct ovsdb_idl_row *row;
-        bool first;
 
-        for (row = ovsdb_idl_first_row(ctx->idl, table->class), first = true;
-             row != NULL;
-             row = ovsdb_idl_next_row(row), first = false) {
+        for (row = ovsdb_idl_first_row(ctx->idl, table->class); row != NULL;
+             row = ovsdb_idl_next_row(row)) {
             list_record(row, columns, n_columns, out);
         }
     }