dpif: Update dpif interface to match netdev.
authorJesse Gross <jesse@nicira.com>
Fri, 22 Jan 2010 19:37:10 +0000 (14:37 -0500)
committerJesse Gross <jesse@nicira.com>
Thu, 28 Jan 2010 01:03:38 +0000 (20:03 -0500)
This brings over some features that were added to the netdev interface,
most notably the separation between the name and the type.  In addition
to being cleaner, this also avoids problems where it is expected that
the local port has the same name as the datapath.

15 files changed:
lib/dpif-linux.c
lib/dpif-netdev.c
lib/dpif-provider.h
lib/dpif.c
lib/dpif.h
lib/dpif.man
ofproto/ofproto.c
ofproto/ofproto.h
utilities/ovs-dpctl.c
utilities/ovs-ofctl.8.in
utilities/ovs-ofctl.c
utilities/ovs-openflowd.c
utilities/ovs-vsctl.c
vswitchd/bridge.c
vswitchd/vswitch.ovsschema

index 2bf329f453732137c1d08c936ecae7c5e151ee4e..db69589a9a419f3ddbb9fcc14d60aa603ba47234 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -95,7 +95,7 @@ dpif_linux_enumerate(struct svec *all_dps)
         int retval;
 
         sprintf(devname, "dp%d", i);
-        retval = dpif_open(devname, &dpif);
+        retval = dpif_open(devname, "system", &dpif);
         if (!retval) {
             svec_add(all_dps, devname);
             dpif_close(dpif);
@@ -107,7 +107,7 @@ dpif_linux_enumerate(struct svec *all_dps)
 }
 
 static int
-dpif_linux_open(const char *name UNUSED, char *suffix, bool create,
+dpif_linux_open(const char *name, const char *type UNUSED, bool create,
                 struct dpif **dpifp)
 {
     int minor;
@@ -116,11 +116,11 @@ dpif_linux_open(const char *name UNUSED, char *suffix, bool create,
             && isdigit((unsigned char)name[2]) ? atoi(name + 2) : -1;
     if (create) {
         if (minor >= 0) {
-            return create_minor(suffix, minor, dpifp);
+            return create_minor(name, minor, dpifp);
         } else {
             /* Scan for unused minor number. */
             for (minor = 0; minor < ODP_MAX; minor++) {
-                int error = create_minor(suffix, minor, dpifp);
+                int error = create_minor(name, minor, dpifp);
                 if (error != EBUSY) {
                     return error;
                 }
@@ -135,7 +135,7 @@ dpif_linux_open(const char *name UNUSED, char *suffix, bool create,
         int error;
 
         if (minor < 0) {
-            error = lookup_minor(suffix, &minor);
+            error = lookup_minor(name, &minor);
             if (error) {
                 return error;
             }
@@ -446,8 +446,7 @@ dpif_linux_recv_wait(struct dpif *dpif_)
 }
 
 const struct dpif_class dpif_linux_class = {
-    "",                         /* This is the default class. */
-    "linux",
+    "system",
     NULL,
     NULL,
     dpif_linux_enumerate,
index 1d496177e22a337a204cffdf7101e1adc1839b8c..e9fb216feff3eb3083b4f837353c095d41e678bd 100644 (file)
@@ -196,7 +196,7 @@ create_dpif_netdev(struct dp_netdev *dp)
 
     dp->open_cnt++;
 
-    dpname = xasprintf("netdev:dp%d", dp->dp_idx);
+    dpname = xasprintf("dp%d", dp->dp_idx);
     dpif = xmalloc(sizeof *dpif);
     dpif_init(&dpif->dpif, &dpif_netdev_class, dpname, dp->dp_idx, dp->dp_idx);
     dpif->dp = dp;
@@ -245,20 +245,20 @@ create_dp_netdev(const char *name, int dp_idx, struct dpif **dpifp)
 }
 
 static int
-dpif_netdev_open(const char *name UNUSED, char *suffix, bool create,
+dpif_netdev_open(const char *name, const char *type UNUSED, bool create,
                  struct dpif **dpifp)
 {
     if (create) {
-        if (find_dp_netdev(suffix)) {
+        if (find_dp_netdev(name)) {
             return EEXIST;
         } else {
-            int dp_idx = name_to_dp_idx(suffix);
+            int dp_idx = name_to_dp_idx(name);
             if (dp_idx >= 0) {
-                return create_dp_netdev(suffix, dp_idx, dpifp);
+                return create_dp_netdev(name, dp_idx, dpifp);
             } else {
                 /* Scan for unused dp_idx number. */
                 for (dp_idx = 0; dp_idx < N_DP_NETDEVS; dp_idx++) {
-                    int error = create_dp_netdev(suffix, dp_idx, dpifp);
+                    int error = create_dp_netdev(name, dp_idx, dpifp);
                     if (error != EBUSY) {
                         return error;
                     }
@@ -269,7 +269,7 @@ dpif_netdev_open(const char *name UNUSED, char *suffix, bool create,
             }
         }
     } else {
-        struct dp_netdev *dp = find_dp_netdev(suffix);
+        struct dp_netdev *dp = find_dp_netdev(name);
         if (dp) {
             *dpifp = create_dpif_netdev(dp);
             return 0;
@@ -1303,7 +1303,6 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
 }
 
 const struct dpif_class dpif_netdev_class = {
-    "netdev",
     "netdev",
     dp_netdev_run,
     dp_netdev_wait,
index 020e017cda7d9325c18662618f6d4b6e10f7104d..9a495443bf463b504da5c97f38ad8aa07bc328bd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,7 +28,8 @@
  * This structure should be treated as opaque by dpif implementations. */
 struct dpif {
     const struct dpif_class *class;
-    char *name;
+    char *base_name;
+    char *full_name;
     uint8_t netflow_engine_type;
     uint8_t netflow_engine_id;
 };
@@ -52,15 +53,11 @@ static inline void dpif_assert_class(const struct dpif *dpif,
  * EWOULDBLOCK or EINPROGRESS.  We may relax this requirement in the future if
  * and when we encounter performance problems. */
 struct dpif_class {
-    /* Prefix for names of dpifs in this class, e.g. "netdev:".
+    /* Type of dpif in this class, e.g. "system", "netdev", etc.
      *
-     * One dpif class may have the empty string "" as its prefix, in which case
-     * that dpif class is associated with dpif names that don't match any other
-     * class name. */
-    const char *prefix;
-
-    /* Class name, for use in error messages. */
-    const char *name;
+     * One of the providers should supply a "system" type, since this is
+     * the type assumed if no type is specified when opening a dpif. */
+    const char *type;
 
     /* Performs periodic work needed by dpifs of this class, if any is
      * necessary. */
@@ -81,16 +78,14 @@ struct dpif_class {
      * case this function may be a null pointer. */
     int (*enumerate)(struct svec *all_dps);
 
-    /* Attempts to open an existing dpif, if 'create' is false, or to open an
-     * existing dpif or create a new one, if 'create' is true.  'name' is the
-     * full dpif name provided by the user, e.g. "udatapath:/var/run/mypath".
-     * This name is useful for error messages but must not be modified.
-     *
-     * 'suffix' is a copy of 'name' following the dpif's 'prefix'.
+    /* Attempts to open an existing dpif called 'name', if 'create' is false,
+     * or to open an existing dpif or create a new one, if 'create' is true.
+     * 'type' corresponds to the 'type' field used in the dpif_class
+     * structure.
      *
      * If successful, stores a pointer to the new dpif in '*dpifp'.  On failure
      * there are no requirements on what is stored in '*dpifp'. */
-    int (*open)(const char *name, char *suffix, bool create,
+    int (*open)(const char *name, const char *type, bool create,
                 struct dpif **dpifp);
 
     /* Closes 'dpif' and frees associated memory. */
index 793eaa1189a9533ce7f469a8d720107165660af2..5947179b00d693934348ae3aad0424971283d7e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -95,57 +95,86 @@ dp_wait(void)
     }
 }
 
-/* Clears 'all_dps' and enumerates the names of all known created datapaths, 
- * where possible, into it.  The caller must first initialize 'all_dps'.
- * Returns 0 if successful, otherwise a positive errno value.
+
+/* Clears 'types' and enumerates the types of all known datapath providers,
+ * into it.  The caller must first initialize the svec. */
+void
+dp_enumerate_types(struct svec *types)
+{
+    int i;
+
+    svec_clear(types);
+
+    for (i = 0; i < N_DPIF_CLASSES; i++) {
+        svec_add(types, dpif_classes[i]->type);
+    }
+}
+
+/* Clears 'names' and enumerates the names of all known created datapaths with
+ * the given 'type'.  The caller must first initialize the svec. Returns 0 if
+ * successful, otherwise a positive errno value.
  *
  * Some kinds of datapaths might not be practically enumerable.  This is not
  * considered an error. */
 int
-dp_enumerate(struct svec *all_dps)
+dp_enumerate_names(const char *type, struct svec *names)
 {
-    int error;
     int i;
 
-    svec_clear(all_dps);
-    error = 0;
+    svec_clear(names);
+
     for (i = 0; i < N_DPIF_CLASSES; i++) {
         const struct dpif_class *class = dpif_classes[i];
-        int retval = class->enumerate ? class->enumerate(all_dps) : 0;
-        if (retval) {
-            VLOG_WARN("failed to enumerate %s datapaths: %s",
-                      class->name, strerror(retval));
-            if (!error) {
-                error = retval;
+
+        if (!strcmp(type, class->type)) {
+            int error = class->enumerate ? class->enumerate(names) : 0;
+
+            if (error) {
+                VLOG_WARN("failed to enumerate %s datapaths: %s",
+                          class->type, strerror(error));
             }
+
+            return error;
         }
     }
-    return error;
+
+    return EAFNOSUPPORT;
+}
+
+/* Parses 'datapath name', which is of the form type@name into its
+ * component pieces.  'name' and 'type' must be freed by the caller. */
+void
+dp_parse_name(const char *datapath_name_, char **name, char **type)
+{
+    char *datapath_name = xstrdup(datapath_name_);
+    char *separator;
+
+    separator = strchr(datapath_name, '@');
+    if (separator) {
+        *separator = '\0';
+        *type = datapath_name;
+        *name = xstrdup(separator + 1);
+    } else {
+        *name = datapath_name;
+        *type = NULL;
+    }
 }
 
 static int
-do_open(const char *name_, bool create, struct dpif **dpifp)
+do_open(const char *name, const char *type, bool create, struct dpif **dpifp)
 {
-    char *name = xstrdup(name_);
-    char *prefix, *suffix, *colon;
     struct dpif *dpif = NULL;
     int error;
     int i;
 
-    colon = strchr(name, ':');
-    if (colon) {
-        *colon = '\0';
-        prefix = name;
-        suffix = colon + 1;
-    } else {
-        prefix = "";
-        suffix = name;
+    if (!type || *type == '\0') {
+        type = "system";
     }
 
     for (i = 0; i < N_DPIF_CLASSES; i++) {
         const struct dpif_class *class = dpif_classes[i];
-        if (!strcmp(prefix, class->prefix)) {
-            error = class->open(name_, suffix, create, &dpif);
+        if (!strcmp(type, class->type)) {
+            error = class->open(name, type, create, &dpif);
             goto exit;
         }
     }
@@ -156,38 +185,41 @@ exit:
     return error;
 }
 
-/* Tries to open an existing datapath named 'name'.  Will fail if no datapath
- * named 'name' exists.  Returns 0 if successful, otherwise a positive errno
- * value.  On success stores a pointer to the datapath in '*dpifp', otherwise a
- * null pointer. */
+/* Tries to open an existing datapath named 'name' and type 'type'.  Will fail
+ * if no datapath with 'name' and 'type' exists.  'type' may be either NULL or
+ * the empty string to specify the default system type.  Returns 0 if
+ * successful, otherwise a positive errno value.  On success stores a pointer
+ * to the datapath in '*dpifp', otherwise a null pointer. */
 int
-dpif_open(const char *name, struct dpif **dpifp)
+dpif_open(const char *name, const char *type, struct dpif **dpifp)
 {
-    return do_open(name, false, dpifp);
+    return do_open(name, type, false, dpifp);
 }
 
-/* Tries to create and open a new datapath with the given 'name'.  Will fail if
- * a datapath named 'name' already exists.  Returns 0 if successful, otherwise
- * a positive errno value.  On success stores a pointer to the datapath in
- * '*dpifp', otherwise a null pointer. */
+/* Tries to create and open a new datapath with the given 'name' and 'type'.
+ * 'type' may be either NULL or the empty string to specify the default system
+ * type.  Will fail if a datapath with 'name' and 'type' already exists.
+ * Returns 0 if successful, otherwise a positive errno value.  On success
+ * stores a pointer to the datapath in '*dpifp', otherwise a null pointer. */
 int
-dpif_create(const char *name, struct dpif **dpifp)
+dpif_create(const char *name, const char *type, struct dpif **dpifp)
 {
-    return do_open(name, true, dpifp);
+    return do_open(name, type, true, dpifp);
 }
 
-/* Tries to open a datapath with the given 'name', creating it if it does not
- * exist.  Returns 0 if successful, otherwise a positive errno value.  On
- * success stores a pointer to the datapath in '*dpifp', otherwise a null
- * pointer. */
+/* Tries to open a datapath with the given 'name' and 'type', creating it if it
+ * does not exist.  'type' may be either NULL or the empty string to specify
+ * the default system type.  Returns 0 if successful, otherwise a positive
+ * errno value. On success stores a pointer to the datapath in '*dpifp',
+ * otherwise a null pointer. */
 int
-dpif_create_and_open(const char *name, struct dpif **dpifp)
+dpif_create_and_open(const char *name, const char *type, struct dpif **dpifp)
 {
     int error;
 
-    error = dpif_create(name, dpifp);
+    error = dpif_create(name, type, dpifp);
     if (error == EEXIST || error == EBUSY) {
-        error = dpif_open(name, dpifp);
+        error = dpif_open(name, type, dpifp);
         if (error) {
             VLOG_WARN("datapath %s already exists but cannot be opened: %s",
                       name, strerror(error));
@@ -204,17 +236,28 @@ void
 dpif_close(struct dpif *dpif)
 {
     if (dpif) {
-        char *name = dpif->name;
+        char *base_name = dpif->base_name;
+        char *full_name = dpif->full_name;
         dpif->class->close(dpif);
-        free(name);
+        free(base_name);
+        free(full_name);
     }
 }
 
-/* Returns the name of datapath 'dpif' (for use in log messages). */
+/* Returns the name of datapath 'dpif' prefixed with the type
+ * (for use in log messages). */
 const char *
 dpif_name(const struct dpif *dpif)
 {
-    return dpif->name;
+    return dpif->full_name;
+}
+
+/* Returns the name of datapath 'dpif' without the type
+ * (for use in device names). */
+const char *
+dpif_base_name(const struct dpif *dpif)
+{
+    return dpif->base_name;
 }
 
 /* Enumerates all names that may be used to open 'dpif' into 'all_names'.  The
@@ -238,7 +281,7 @@ dpif_get_all_names(const struct dpif *dpif, struct svec *all_names)
         }
         return error;
     } else {
-        svec_add(all_names, dpif_name(dpif));
+        svec_add(all_names, dpif_base_name(dpif));
         return 0;
     }
 }
@@ -927,7 +970,8 @@ dpif_init(struct dpif *dpif, const struct dpif_class *class, const char *name,
           uint8_t netflow_engine_type, uint8_t netflow_engine_id)
 {
     dpif->class = class;
-    dpif->name = xstrdup(name);
+    dpif->base_name = xstrdup(name);
+    dpif->full_name = xasprintf("%s@%s", class->type, name);
     dpif->netflow_engine_type = netflow_engine_type;
     dpif->netflow_engine_id = netflow_engine_id;
 }
index 1d109c2d256ef168fccc956471ef3515bc062ad1..aa54a387d8b7259349a354ce9929c41ac1e25d5c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 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 DPIF_H
 #define DPIF_H 1
 
-/* Operations for the datapath running in the local kernel.  The interface can
- * generalize to multiple types of local datapaths, but the implementation only
- * supports the openflow kernel module. */
-
 #include "openvswitch/datapath-protocol.h"
 #include <stdbool.h>
 #include <stddef.h>
@@ -33,14 +29,17 @@ struct svec;
 
 void dp_run(void);
 void dp_wait(void);
-int dp_enumerate(struct svec *);
+void dp_enumerate_types(struct svec *types);
+int dp_enumerate_names(const char *type, struct svec *names);
+void dp_parse_name(const char *datapath_name, char **name, char **type);
 
-int dpif_open(const char *name, struct dpif **);
-int dpif_create(const char *name, struct dpif **);
-int dpif_create_and_open(const char *name, struct dpif **);
+int dpif_open(const char *name, const char *type, struct dpif **);
+int dpif_create(const char *name, const char *type, struct dpif **);
+int dpif_create_and_open(const char *name, const char *type, struct dpif **);
 void dpif_close(struct dpif *);
 
 const char *dpif_name(const struct dpif *);
+const char *dpif_base_name(const struct dpif *);
 int dpif_get_all_names(const struct dpif *, struct svec *);
 
 int dpif_delete(struct dpif *);
index 3a58cafb61ef0d8d712f02b20ae5c3ef943dc71c..63e172fca1809afa636bd1d233526cda63b7001c 100644 (file)
@@ -1,11 +1,13 @@
 .RS
 .TP
-\fBdp\fIN\fR
+[\fItype\fB@\fR]\fBdp\fIN\fR
 Datapath number \fIN\fR, where \fIN\fR is a number between 0 and 255,
-inclusive.
+inclusive.  If \fItype\fR is given, it specifies the datapath provider of
+\fBdp\fIN\fR, otherwise the default provider \fBsystem\fR is assumed.
 
 .TP
-\fIname\fR
+[\fItype\fB@\fR]\fIname\fR
 The name of the network device associated with the datapath's local
 port.  (\fB\*(PN\fR internally converts this into a datapath number,
-as above.)
+as above.)  If \fItype\fR is given, it specifies the datapath provider of
+\fIname\fR, otherwise the default provider \fBsystem\fR is assumed.
index 46b577afbf2414fe06789f146fe98ea078f03343..941803d79f2b94ed60ca18306dca60c32c7ea9fe 100644 (file)
@@ -257,7 +257,8 @@ static int init_ports(struct ofproto *);
 static void reinit_ports(struct ofproto *);
 
 int
-ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux,
+ofproto_create(const char *datapath, const char *datapath_type,
+               const struct ofhooks *ofhooks, void *aux,
                struct ofproto **ofprotop)
 {
     struct odp_stats stats;
@@ -268,7 +269,7 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux,
     *ofprotop = NULL;
 
     /* Connect to datapath and start listening for messages. */
-    error = dpif_open(datapath, &dpif);
+    error = dpif_open(datapath, datapath_type, &dpif);
     if (error) {
         VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error));
         return error;
index 5fe8d774bb9a0ee74237d70d3518ea5ac282d242..cf99a3992fabfb8b1be133cdcd78c55e18f80f14 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -36,7 +36,8 @@ struct ofexpired {
     long long int used;         /* Last-used time (0 if never used). */
 };
 
-int ofproto_create(const char *datapath, const struct ofhooks *, void *aux,
+int ofproto_create(const char *datapath, const char *datapath_type,
+                   const struct ofhooks *, void *aux,
                    struct ofproto **ofprotop);
 void ofproto_destroy(struct ofproto *);
 int ofproto_run(struct ofproto *);
index ee545a61ac5273e611929ffe4a47f1682afbde27..fceab4c1aafa78e5cd4e75c7f5accfe0813ddde4 100644 (file)
@@ -174,11 +174,30 @@ static int if_up(const char *netdev_name)
     return retval;
 }
 
+static int
+parsed_dpif_open(const char *arg_, bool create, struct dpif **dpifp)
+{
+    int result;
+    char *name, *type;
+
+    dp_parse_name(arg_, &name, &type);
+
+    if (create) {
+        result = dpif_create(name, type, dpifp);
+    } else {
+        result = dpif_open(name, type, dpifp);
+    }
+
+    free(name);
+    free(type);
+    return result;
+}
+
 static void
 do_add_dp(int argc UNUSED, char *argv[])
 {
     struct dpif *dpif;
-    run(dpif_create(argv[1], &dpif), "add_dp");
+    run(parsed_dpif_open(argv[1], true, &dpif), "add_dp");
     dpif_close(dpif);
     if (argc > 2) {
         do_add_if(argc, argv);
@@ -189,7 +208,7 @@ static void
 do_del_dp(int argc UNUSED, char *argv[])
 {
     struct dpif *dpif;
-    run(dpif_open(argv[1], &dpif), "opening datapath");
+    run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
     run(dpif_delete(dpif), "del_dp");
     dpif_close(dpif);
 }
@@ -216,7 +235,7 @@ do_add_if(int argc UNUSED, char *argv[])
     struct dpif *dpif;
     int i;
 
-    run(dpif_open(argv[1], &dpif), "opening datapath");
+    run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
     for (i = 2; i < argc; i++) {
         char *save_ptr = NULL;
         char *devname, *suboptions;
@@ -294,7 +313,7 @@ do_del_if(int argc UNUSED, char *argv[])
     struct dpif *dpif;
     int i;
 
-    run(dpif_open(argv[1], &dpif), "opening datapath");
+    run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
     for (i = 2; i < argc; i++) {
         const char *name = argv[i];
         uint16_t port;
@@ -366,7 +385,7 @@ do_show(int argc, char *argv[])
             struct dpif *dpif;
             int error;
 
-            error = dpif_open(name, &dpif);
+            error = parsed_dpif_open(name, false, &dpif);
             if (!error) {
                 show_dpif(dpif);
             } else {
@@ -382,7 +401,7 @@ do_show(int argc, char *argv[])
             int error;
 
             sprintf(name, "dp%u", i);
-            error = dpif_open(name, &dpif);
+            error = parsed_dpif_open(name, false, &dpif);
             if (!error) {
                 show_dpif(dpif);
             } else if (error != ENODEV) {
@@ -399,22 +418,34 @@ do_show(int argc, char *argv[])
 static void
 do_dump_dps(int argc UNUSED, char *argv[] UNUSED)
 {
-    struct svec all_dps;
+    struct svec dpif_names, dpif_types;
     unsigned int i;
-    int error;
+    int error = 0;
 
-    svec_init(&all_dps);
-    error = dp_enumerate(&all_dps);
+    svec_init(&dpif_names);
+    svec_init(&dpif_types);
+    dp_enumerate_types(&dpif_types);
 
-    for (i = 0; i < all_dps.n; i++) {
-        struct dpif *dpif;
-        if (!dpif_open(all_dps.names[i], &dpif)) {
-            printf("%s\n", dpif_name(dpif));
-            dpif_close(dpif);
+    for (i = 0; i < dpif_types.n; i++) {
+        unsigned int j;
+        int retval;
+
+        retval = dp_enumerate_names(dpif_types.names[i], &dpif_names);
+        if (retval) {
+            error = retval;
+        }
+
+        for (j = 0; j < dpif_names.n; j++) {
+            struct dpif *dpif;
+            if (!dpif_open(dpif_names.names[j], dpif_types.names[i], &dpif)) {
+                printf("%s\n", dpif_name(dpif));
+                dpif_close(dpif);
+            }
         }
     }
 
-    svec_destroy(&all_dps);
+    svec_destroy(&dpif_names);
+    svec_destroy(&dpif_types);
     if (error) {
         exit(EXIT_FAILURE);
     }
@@ -429,7 +460,7 @@ do_dump_flows(int argc UNUSED, char *argv[])
     struct ds ds;
     size_t i;
 
-    run(dpif_open(argv[1], &dpif), "opening datapath");
+    run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
     run(dpif_flow_list_all(dpif, &flows, &n_flows), "listing all flows");
 
     ds_init(&ds);
@@ -455,7 +486,7 @@ do_del_flows(int argc UNUSED, char *argv[])
 {
     struct dpif *dpif;
 
-    run(dpif_open(argv[1], &dpif), "opening datapath");
+    run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
     run(dpif_flow_flush(dpif), "deleting all flows");
     dpif_close(dpif);
 }
@@ -467,7 +498,7 @@ do_dump_groups(int argc UNUSED, char *argv[])
     struct dpif *dpif;
     unsigned int i;
 
-    run(dpif_open(argv[1], &dpif), "opening datapath");
+    run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
     run(dpif_get_dp_stats(dpif, &stats), "get datapath stats");
     for (i = 0; i < stats.max_groups; i++) {
         uint16_t *ports;
index cf4ead96da605849d43aeb7fd1d796d1a1b2a328..17b5a4006f3b9e5d5dd3540bbdb3979575b7bd45 100644 (file)
@@ -32,9 +32,14 @@ are supported:
 This is short for \fBunix:\fIfile\fR, as long as \fIfile\fR does not
 contain a colon.
 .
-.IP \fIdp\fR
-This is short for \fBunix:@RUNDIR@/\fIdp\fB.mgmt\fR, as long as
-\fIdp\fR does not contain a colon.
+.IP \fIbridge\fR
+This is short for \fBunix:@RUNDIR@/\fIbridge\fB.mgmt\fR, as long as
+\fIbridge\fR does not contain a colon.
+.
+.IP [\fItype\fB@\fR]\fIdp\fR
+Attempts to look up the bridge associated with \fIdp\fR and open as
+above.  If \fItype\fR is given, it specifies the datapath provider of
+\fIdp\fR, otherwise the default provider \fBsystem\fR is assumed.
 .RE
 
 .TP
index 61ca23e3b3c0c1dd7b97b81aff9ae1587f69495e..52ec0b6b32d09151188f249e2eb71c0b0a6a3cbf 100644 (file)
@@ -204,25 +204,36 @@ static void run(int retval, const char *message, ...)
 \f
 /* Generic commands. */
 
+static void
+open_vconn_socket(const char *name, struct vconn **vconnp)
+{
+    char *vconn_name = xasprintf("unix:%s", name);
+    VLOG_INFO("connecting to %s", vconn_name);
+    run(vconn_open_block(vconn_name, OFP_VERSION, vconnp),
+        "connecting to %s", vconn_name);
+    free(vconn_name);
+}
+
 static void
 open_vconn(const char *name, struct vconn **vconnp)
 {
     struct dpif *dpif;
     struct stat s;
+    char *bridge_path, *datapath_name, *datapath_type;
+
+    bridge_path = xasprintf("%s/%s.mgmt", ovs_rundir, name);
+    dp_parse_name(name, &datapath_name, &datapath_type);
 
     if (strstr(name, ":")) {
         run(vconn_open_block(name, OFP_VERSION, vconnp),
             "connecting to %s", name);
     } else if (!stat(name, &s) && S_ISSOCK(s.st_mode)) {
-        char *vconn_name = xasprintf("unix:%s", name);
-        VLOG_INFO("connecting to %s", vconn_name);
-        run(vconn_open_block(vconn_name, OFP_VERSION, vconnp),
-            "connecting to %s", vconn_name);
-        free(vconn_name);
-    } else if (!dpif_open(name, &dpif)) {
+        open_vconn_socket(name, vconnp);
+    } else if (!stat(bridge_path, &s) && S_ISSOCK(s.st_mode)) {
+        open_vconn_socket(bridge_path, vconnp);
+    } else if (!dpif_open(datapath_name, datapath_type, &dpif)) {
         char dpif_name[IF_NAMESIZE + 1];
         char *socket_name;
-        char *vconn_name;
 
         run(dpif_port_get_name(dpif, ODPP_LOCAL, dpif_name, sizeof dpif_name),
             "obtaining name of %s", dpif_name);
@@ -240,15 +251,15 @@ open_vconn(const char *name, struct vconn **vconnp)
                       name, socket_name);
         }
 
-        vconn_name = xasprintf("unix:%s", socket_name);
-        VLOG_INFO("connecting to %s", vconn_name);
-        run(vconn_open_block(vconn_name, OFP_VERSION, vconnp),
-            "connecting to %s", vconn_name);
+        open_vconn_socket(socket_name, vconnp);
         free(socket_name);
-        free(vconn_name);
     } else {
         ovs_fatal(0, "%s is not a valid connection method", name);
     }
+
+    free(datapath_name);
+    free(datapath_type);
+    free(bridge_path);
 }
 
 static void *
index e0cfdc957bca741cf1ceaed93e90cc16347085b0..5e63f1b24fd9850a3e4c320756b1eb091f088b34 100644 (file)
@@ -137,7 +137,7 @@ main(int argc, char *argv[])
         const char *port;
         size_t i;
 
-        error = dpif_create_and_open(s.dp_name, &dpif);
+        error = dpif_create_and_open(s.dp_name, NULL, &dpif);
         if (error) {
             ovs_fatal(error, "could not create datapath");
         }
@@ -152,7 +152,7 @@ main(int argc, char *argv[])
     }
 
     /* Start OpenFlow processing. */
-    error = ofproto_create(s.dp_name, NULL, NULL, &ofproto);
+    error = ofproto_create(s.dp_name, NULL, NULL, NULL, &ofproto);
     if (error) {
         ovs_fatal(error, "could not initialize openflow switch");
     }
index 318f42937ae41fe55fa87380006bc671ac6bfe0a..07d9ae2ca887e6eebd693bcfe1bd5144181c51b2 100644 (file)
@@ -1394,6 +1394,7 @@ struct vsctl_column {
 
 static const struct vsctl_column bridge_columns[] = {
     {&ovsrec_bridge_col_datapath_id, VSCF_READONLY, NULL},
+    {&ovsrec_bridge_col_datapath_type, VSCF_READONLY, NULL},
     {&ovsrec_bridge_col_name, VSCF_READONLY, NULL},
     {&ovsrec_bridge_col_mirrors, VSCF_READONLY, NULL},
     {&ovsrec_bridge_col_other_config, 0, NULL},
index 726d759bebf17b8c4cf9afe91335bfb70f7f596a..6fc24414cb1292522aa3f2d7a47a50d7b11848a6 100644 (file)
@@ -193,7 +193,7 @@ static struct list all_bridges = LIST_INITIALIZER(&all_bridges);
 /* Maximum number of datapaths. */
 enum { DP_MAX = 256 };
 
-static struct bridge *bridge_create(const char *name);
+static struct bridge *bridge_create(const struct ovsrec_bridge *br_cfg);
 static void bridge_destroy(struct bridge *);
 static struct bridge *bridge_lookup(const char *name);
 static unixctl_cb_func bridge_unixctl_dump_flows;
@@ -285,7 +285,7 @@ void
 bridge_init(const struct ovsrec_open_vswitch *cfg)
 {
     struct svec bridge_names;
-    struct svec dpif_names;
+    struct svec dpif_names, dpif_types;
     size_t i;
 
     unixctl_command_register("fdb/show", bridge_unixctl_fdb_show, NULL);
@@ -297,31 +297,37 @@ bridge_init(const struct ovsrec_open_vswitch *cfg)
     svec_sort(&bridge_names);
 
     svec_init(&dpif_names);
-    dp_enumerate(&dpif_names);
-    for (i = 0; i < dpif_names.n; i++) {
-        const char *dpif_name = dpif_names.names[i];
+    svec_init(&dpif_types);
+    dp_enumerate_types(&dpif_types);
+    for (i = 0; i < dpif_types.n; i++) {
         struct dpif *dpif;
         int retval;
+        size_t j;
 
-        retval = dpif_open(dpif_name, &dpif);
-        if (!retval) {
-            struct svec all_names;
-            size_t j;
+        dp_enumerate_names(dpif_types.names[i], &dpif_names);
 
-            svec_init(&all_names);
-            dpif_get_all_names(dpif, &all_names);
-            for (j = 0; j < all_names.n; j++) {
-                if (svec_contains(&bridge_names, all_names.names[j])) {
-                    goto found;
+        for (j = 0; j < dpif_names.n; j++) {
+            retval = dpif_open(dpif_names.names[j], dpif_types.names[i], &dpif);
+            if (!retval) {
+                struct svec all_names;
+                size_t k;
+
+                svec_init(&all_names);
+                dpif_get_all_names(dpif, &all_names);
+                for (k = 0; k < all_names.n; k++) {
+                    if (svec_contains(&bridge_names, all_names.names[k])) {
+                        goto found;
+                    }
                 }
+                dpif_delete(dpif);
+            found:
+                svec_destroy(&all_names);
+                dpif_close(dpif);
             }
-            dpif_delete(dpif);
-        found:
-            svec_destroy(&all_names);
-            dpif_close(dpif);
         }
     }
     svec_destroy(&dpif_names);
+    svec_destroy(&dpif_types);
 
     unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows,
                              NULL);
@@ -560,11 +566,16 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
     SHASH_FOR_EACH (node, &new_br) {
         const char *br_name = node->name;
         const struct ovsrec_bridge *br_cfg = node->data;
-        if (!shash_find_data(&old_br, br_name)) {
-            br = bridge_create(br_name);
-            if (br) {
-                br->cfg = br_cfg;
+        br = shash_find_data(&old_br, br_name);
+        if (br) {
+            /* If the bridge datapath type has changed, we need to tear it
+             * down and recreate. */
+            if (strcmp(br->cfg->datapath_type, br_cfg->datapath_type)) {
+                bridge_destroy(br);
+                bridge_create(br_cfg);
             }
+        } else {
+            bridge_create(br_cfg);
         }
     }
     shash_destroy(&old_br);
@@ -1071,31 +1082,35 @@ bridge_unixctl_fdb_show(struct unixctl_conn *conn,
 \f
 /* Bridge reconfiguration functions. */
 static struct bridge *
-bridge_create(const char *name)
+bridge_create(const struct ovsrec_bridge *br_cfg)
 {
     struct bridge *br;
     int error;
 
-    assert(!bridge_lookup(name));
+    assert(!bridge_lookup(br_cfg->name));
     br = xzalloc(sizeof *br);
 
-    error = dpif_create_and_open(name, &br->dpif);
+    error = dpif_create_and_open(br_cfg->name, br_cfg->datapath_type,
+                                 &br->dpif);
     if (error) {
         free(br);
         return NULL;
     }
     dpif_flow_flush(br->dpif);
 
-    error = ofproto_create(name, &bridge_ofhooks, br, &br->ofproto);
+    error = ofproto_create(br_cfg->name, br_cfg->datapath_type, &bridge_ofhooks,
+                           br, &br->ofproto);
     if (error) {
-        VLOG_ERR("failed to create switch %s: %s", name, strerror(error));
+        VLOG_ERR("failed to create switch %s: %s", br_cfg->name,
+                 strerror(error));
         dpif_delete(br->dpif);
         dpif_close(br->dpif);
         free(br);
         return NULL;
     }
 
-    br->name = xstrdup(name);
+    br->name = xstrdup(br_cfg->name);
+    br->cfg = br_cfg;
     br->ml = mac_learning_create();
     br->sent_config_request = false;
     eth_addr_random(br->default_ea);
index 2c7fdf18ebd7531947044331d163512e59cefd24..e9f615b687a8be2334a439f8dc4b36aa8cda5c6a 100644 (file)
@@ -31,6 +31,9 @@
        "name": {
          "comment": "Bridge identifier.  Should be alphanumeric and no more than about 8 bytes long.  Must be unique among the names of ports, interfaces, and bridges on a host.",
          "type": "string"},
+       "datapath_type": {
+         "comment": "Name of datapath provider.  The kernel datapath has type \"system\".  The userspace datapath has type \"netdev\".",
+         "type": "string"},
        "datapath_id": {
          "comment": "Reports the OpenFlow datapath ID in use.  Exactly 12 hex digits.",
          "type": {"key": "string", "min": 0, "max": 1},