dummy: Make --enable-dummy=override replace all dpifs, netdevs by dummies.
authorBen Pfaff <blp@nicira.com>
Thu, 19 Jan 2012 18:24:46 +0000 (10:24 -0800)
committerBen Pfaff <blp@nicira.com>
Thu, 19 Jan 2012 18:24:46 +0000 (10:24 -0800)
Plain "--enable-dummy" just creates new dummy dpif and netdev classes.
This commit makes "--enable-dummy=override" go a step farther and actually
delete and replace all the existing dpif and netdev classes by copies of
the dummy class.

This is useful for testing in an environment where changing the classes in
Bridge or Interface records is challenging.

Requested-by: Andrew Lambeth <wal@nicira.com>
Tested-by: Andrew Lambeth <wal@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/dpif-netdev.c
lib/dummy.c
lib/dummy.h
lib/netdev-dummy.c
vswitchd/ovs-vswitchd.c

index d7c3da028f2d44776845eb89ab5436cbdf98f6c1..e1dc725dd8874b58c1af44ac87f33178bca462c1 100644 (file)
@@ -49,6 +49,7 @@
 #include "poll-loop.h"
 #include "random.h"
 #include "shash.h"
+#include "sset.h"
 #include "timeval.h"
 #include "util.h"
 #include "vlog.h"
@@ -100,7 +101,7 @@ struct dp_netdev_port {
     int port_no;                /* Index into dp_netdev's 'ports'. */
     struct list node;           /* Element in dp_netdev's 'port_list'. */
     struct netdev *netdev;
-    bool internal;              /* Internal port? */
+    char *type;                 /* Port type as requested by user. */
 };
 
 /* A flow in dp_netdev's 'flow_table'. */
@@ -151,8 +152,6 @@ static void dp_netdev_execute_actions(struct dp_netdev *,
                                       const struct nlattr *actions,
                                       size_t actions_len);
 
-static struct dpif_class dpif_dummy_class;
-
 static struct dpif_netdev *
 dpif_netdev_cast(const struct dpif *dpif)
 {
@@ -309,28 +308,17 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
 {
     struct dp_netdev_port *port;
     struct netdev *netdev;
-    bool internal;
+    const char *open_type;
     int mtu;
     int error;
 
     /* XXX reject devices already in some dp_netdev. */
-    if (type[0] == '\0' || !strcmp(type, "system") || !strcmp(type, "dummy")) {
-        internal = false;
-    } else if (!strcmp(type, "internal")) {
-        internal = true;
-    } else {
-        VLOG_WARN("%s: unsupported port type %s", devname, type);
-        return EINVAL;
-    }
 
     /* Open and validate network device. */
-    if (dp->class == &dpif_dummy_class) {
-        type = "dummy";
-    } else if (internal) {
-        type = "tap";
-    }
-
-    error = netdev_open(devname, type, &netdev);
+    open_type = (strcmp(type, "internal") ? type
+                 : dp->class != &dpif_netdev_class ? "dummy"
+                 : "tap");
+    error = netdev_open(devname, open_type, &netdev);
     if (error) {
         return error;
     }
@@ -354,7 +342,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
     port = xmalloc(sizeof *port);
     port->port_no = port_no;
     port->netdev = netdev;
-    port->internal = internal;
+    port->type = xstrdup(type);
 
     error = netdev_get_mtu(netdev, &mtu);
     if (!error) {
@@ -374,7 +362,7 @@ choose_port(struct dpif *dpif, struct netdev *netdev)
     struct dp_netdev *dp = get_dp_netdev(dpif);
     int port_no;
 
-    if (dpif->dpif_class == &dpif_dummy_class) {
+    if (dpif->dpif_class != &dpif_netdev_class) {
         /* If the port name contains a number, try to assign that port number.
          * This can make writing unit tests easier because port numbers are
          * predictable. */
@@ -476,6 +464,7 @@ do_del_port(struct dp_netdev *dp, uint16_t port_no)
 
     name = xstrdup(netdev_get_name(port->netdev));
     netdev_close(port->netdev);
+    free(port->type);
 
     free(name);
     free(port);
@@ -488,8 +477,7 @@ answer_port_query(const struct dp_netdev_port *port,
                   struct dpif_port *dpif_port)
 {
     dpif_port->name = xstrdup(netdev_get_name(port->netdev));
-    dpif_port->type = xstrdup(port->internal ? "internal"
-                              : netdev_get_type(port->netdev));
+    dpif_port->type = xstrdup(port->type);
     dpif_port->port_no = port->port_no;
 }
 
@@ -581,8 +569,7 @@ dpif_netdev_port_dump_next(const struct dpif *dpif, void *state_,
             free(state->name);
             state->name = xstrdup(netdev_get_name(port->netdev));
             dpif_port->name = state->name;
-            dpif_port->type = (char *) (port->internal ? "internal"
-                                        : netdev_get_type(port->netdev));
+            dpif_port->type = port->type;
             dpif_port->port_no = port->port_no;
             state->port_no = port_no + 1;
             return 0;
@@ -1289,12 +1276,33 @@ const struct dpif_class dpif_netdev_class = {
     dpif_netdev_recv_purge,
 };
 
+static void
+dpif_dummy_register__(const char *type)
+{
+    struct dpif_class *class;
+
+    class = xmalloc(sizeof *class);
+    *class = dpif_netdev_class;
+    class->type = xstrdup(type);
+    dp_register_provider(class);
+}
+
 void
-dpif_dummy_register(void)
+dpif_dummy_register(bool override)
 {
-    if (!dpif_dummy_class.type) {
-        dpif_dummy_class = dpif_netdev_class;
-        dpif_dummy_class.type = "dummy";
-        dp_register_provider(&dpif_dummy_class);
+    if (override) {
+        struct sset types;
+        const char *type;
+
+        sset_init(&types);
+        dp_enumerate_types(&types);
+        SSET_FOR_EACH (type, &types) {
+            if (!dp_unregister_provider(type)) {
+                dpif_dummy_register__(type);
+            }
+        }
+        sset_destroy(&types);
     }
+
+    dpif_dummy_register__("dummy");
 }
index fe2fa621847a79d845604ea421471eee17afd164..a07830a6aa8aa7d7f5012d3fc6dec72c7fa4c957 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011 Nicira Networks.
+ * Copyright (c) 2010, 2011, 2012 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * testing.  A client program might call this function if it is designed
  * specifically for testing or the user enables it on the command line.
  *
+ * If 'override' is false, then "dummy" dpif and netdev classes will be
+ * created.  If 'override' is true, then in addition all existing dpif and
+ * netdev classes will be deleted and replaced by dummy classes.
+ *
  * There is no strong reason why dummy devices shouldn't always be enabled. */
 void
-dummy_enable(void)
+dummy_enable(bool override)
 {
-    netdev_dummy_register();
-    dpif_dummy_register();
+    netdev_dummy_register(override);
+    dpif_dummy_register(override);
     timeval_dummy_register();
 }
+
index efc1696ddebaea8dc9458deb705956391104d0a7..abbb36387005fc6c714d54f0c8b3e40eba5f3b35 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011 Nicira Networks.
+ * Copyright (c) 2010, 2011, 2012 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #ifndef DUMMY_H
 #define DUMMY_H 1
 
+#include <stdbool.h>
+
 /* For client programs to call directly to enable dummy support. */
-void dummy_enable(void);
+void dummy_enable(bool override);
 
 /* Implementation details. */
-void dpif_dummy_register(void);
-void netdev_dummy_register(void);
+void dpif_dummy_register(bool override);
+void netdev_dummy_register(bool override);
 void timeval_dummy_register(void);
 
 #endif /* dummy.h */
index d94af415669f9b37470eedaa7ecfd0cbc91bb25b..57962d10e273242d7a5af7421fb6920c425fe7e9 100644 (file)
@@ -29,6 +29,7 @@
 #include "packets.h"
 #include "poll-loop.h"
 #include "shash.h"
+#include "sset.h"
 #include "unixctl.h"
 #include "vlog.h"
 
@@ -443,9 +444,28 @@ netdev_dummy_receive(struct unixctl_conn *conn,
 }
 
 void
-netdev_dummy_register(void)
+netdev_dummy_register(bool override)
 {
-    netdev_register_provider(&dummy_class);
     unixctl_command_register("netdev-dummy/receive", "NAME PACKET|FLOW...",
                              2, INT_MAX, netdev_dummy_receive, NULL);
+
+    if (override) {
+        struct sset types;
+        const char *type;
+
+        sset_init(&types);
+        netdev_enumerate_types(&types);
+        SSET_FOR_EACH (type, &types) {
+            if (!netdev_unregister_provider(type)) {
+                struct netdev_class *class;
+
+                class = xmalloc(sizeof *class);
+                *class = dummy_class;
+                class->type = xstrdup(type);
+                netdev_register_provider(class);
+            }
+        }
+        sset_destroy(&types);
+    }
+    netdev_register_provider(&dummy_class);
 }
index 2a86972657af4636dd53757a5ca0a2c1ebd6344d..1b9e26c57dca5945452b9c4d4e7e9e5c20602b0f 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks
+/* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -137,7 +137,7 @@ parse_options(int argc, char *argv[])
         STREAM_SSL_LONG_OPTIONS,
         {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
         {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
-        {"enable-dummy", no_argument, NULL, OPT_ENABLE_DUMMY},
+        {"enable-dummy", optional_argument, NULL, OPT_ENABLE_DUMMY},
         {"disable-system", no_argument, NULL, OPT_DISABLE_SYSTEM},
         {NULL, 0, NULL, 0},
     };
@@ -183,7 +183,7 @@ parse_options(int argc, char *argv[])
             break;
 
         case OPT_ENABLE_DUMMY:
-            dummy_enable();
+            dummy_enable(optarg && !strcmp(optarg, "override"));
             break;
 
         case OPT_DISABLE_SYSTEM: