[ovs-dev] [PATCH 1/2] dpif: Update dpif interface to match netdev.

Jesse Gross jesse at nicira.com
Fri Jan 22 19:52:41 UTC 2010


This brings over some features that were added to the netdev interface,
most notably the separation between the name and the type.  In addition
being cleaner, this also avoids problems where it is expected that the
local port has the same name as the datapth.
---
 lib/dpif-linux.c            |   15 +++---
 lib/dpif-netdev.c           |   15 +++---
 lib/dpif-provider.h         |   29 +++++-------
 lib/dpif.c                  |  110 ++++++++++++++++++++++++-------------------
 lib/dpif.h                  |   15 ++----
 lib/dpif.man                |   10 ++--
 ofproto/ofproto.c           |    5 +-
 ofproto/ofproto.h           |    5 +-
 utilities/ovs-dpctl.c       |   59 +++++++++++++++++------
 utilities/ovs-ofctl.8.in    |    6 +-
 utilities/ovs-ofctl.c       |   52 +++++++-------------
 utilities/ovs-openflowd.c   |    4 +-
 vswitchd/bridge.c           |   40 ++++++++++------
 vswitchd/vswitch-idl.ovsidl |    3 +
 14 files changed, 201 insertions(+), 167 deletions(-)

diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index 2bf329f..db69589 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -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,
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 1d49617..e9fb216 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -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;
@@ -1304,7 +1304,6 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
 
 const struct dpif_class dpif_netdev_class = {
     "netdev",
-    "netdev",
     dp_netdev_run,
     dp_netdev_wait,
     NULL,                       /* enumerate */
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index 020e017..9a49544 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -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. */
diff --git a/lib/dpif.c b/lib/dpif.c
index 793eaa1..319756a 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -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,26 +95,33 @@ 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 'names' and 'types' and enumerates the names and types of all known
+ * created datapaths, where possible, into them respectively.  The caller must
+ * first initialize both svecs. 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(struct svec *names, struct svec *types)
 {
     int error;
-    int i;
+    int i, j;
 
-    svec_clear(all_dps);
+    svec_clear(names);
+    svec_clear(types);
     error = 0;
+
     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) {
+        int retval = class->enumerate ? class->enumerate(names) : 0;
+        if (!retval) {
+            for (j = 0; j < names->n - types->n; j++) {
+                svec_add(types, class->type);
+            }
+        } else {
             VLOG_WARN("failed to enumerate %s datapaths: %s",
-                      class->name, strerror(retval));
+                      class->type, strerror(retval));
             if (!error) {
                 error = retval;
             }
@@ -124,28 +131,20 @@ dp_enumerate(struct svec *all_dps)
 }
 
 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 || !strlen(type)) {
+        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 +155,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 +206,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 +251,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 +940,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;
 }
diff --git a/lib/dpif.h b/lib/dpif.h
index 1d109c2..7e040b1 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -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.
@@ -18,10 +18,6 @@
 #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,15 @@ struct svec;
 
 void dp_run(void);
 void dp_wait(void);
-int dp_enumerate(struct svec *);
+int dp_enumerate(struct svec *names, struct svec *types);
 
-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 *);
diff --git a/lib/dpif.man b/lib/dpif.man
index 3a58caf..31f126a 100644
--- a/lib/dpif.man
+++ b/lib/dpif.man
@@ -1,11 +1,13 @@
 .RS
 .TP
-\fBdp\fIN\fR
+[\fItype\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\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
+\fBname\fR, otherwise the default provider \fBsystem\fR is assumed.
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 46b577a..941803d 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -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;
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index 5fe8d77..cf99a39 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -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 *);
diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c
index ee545a6..1a8569f 100644
--- a/utilities/ovs-dpctl.c
+++ b/utilities/ovs-dpctl.c
@@ -174,11 +174,38 @@ static int if_up(const char *netdev_name)
     return retval;
 }
 
+static int
+parsed_dpif_open(const char *arg_, bool create, struct dpif **dpifp)
+{
+    char *arg = xstrdup(arg_);
+    char *separator, *name, *type;
+    int result;
+
+    separator = strchr(arg, ':');
+    if (separator) {
+        *separator = '\0';
+        type = arg;
+        name = separator + 1;
+    } else {
+        name = arg;
+        type = NULL;
+    }
+
+    if (create) {
+        result = dpif_create(name, type, dpifp);
+    } else {
+        result = dpif_open(name, type, dpifp);
+    }
+
+    free(arg);
+    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 +216,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 +243,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 +321,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 +393,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 +409,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 +426,24 @@ 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;
 
-    svec_init(&all_dps);
-    error = dp_enumerate(&all_dps);
+    svec_init(&dpif_names);
+    svec_init(&dpif_types);
+    error = dp_enumerate(&dpif_names, &dpif_types);
 
-    for (i = 0; i < all_dps.n; i++) {
+    for (i = 0; i < dpif_names.n; i++) {
         struct dpif *dpif;
-        if (!dpif_open(all_dps.names[i], &dpif)) {
+        if (!dpif_open(dpif_names.names[i], 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 +458,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 +484,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 +496,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;
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index cf4ead9..db35721 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -32,9 +32,9 @@ 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.
 .RE
 
 .TP
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 61ca23e..f40bdcd 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -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.
@@ -32,7 +32,6 @@
 #include "command-line.h"
 #include "compiler.h"
 #include "dirs.h"
-#include "dpif.h"
 #include "dynamic-string.h"
 #include "netdev.h"
 #include "netlink.h"
@@ -205,50 +204,35 @@ static void run(int retval, const char *message, ...)
 /* 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 = xasprintf("%s/%s.mgmt", ovs_rundir, name);
+
     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)) {
-        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);
-        dpif_close(dpif);
-        if (strcmp(dpif_name, name)) {
-            VLOG_INFO("datapath %s is named %s", name, dpif_name);
-        }
-
-        socket_name = xasprintf("%s/%s.mgmt", ovs_rundir, dpif_name);
-        if (stat(socket_name, &s)) {
-            ovs_fatal(errno, "cannot connect to %s: stat failed on %s",
-                      name, socket_name);
-        } else if (!S_ISSOCK(s.st_mode)) {
-            ovs_fatal(0, "cannot connect to %s: %s is not a socket",
-                      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);
-        free(socket_name);
-        free(vconn_name);
+        open_vconn_socket(name, vconnp);
+    } else if (!stat(bridge_path, &s) && S_ISSOCK(s.st_mode)) {
+        open_vconn_socket(bridge_path, vconnp);
     } else {
         ovs_fatal(0, "%s is not a valid connection method", name);
     }
+
+    free(bridge_path);
 }
 
 static void *
diff --git a/utilities/ovs-openflowd.c b/utilities/ovs-openflowd.c
index 43cbd6e..2c688cb 100644
--- a/utilities/ovs-openflowd.c
+++ b/utilities/ovs-openflowd.c
@@ -136,7 +136,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");
         }
@@ -151,7 +151,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");
     }
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index a09f343..f5c939e 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -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,13 +297,13 @@ bridge_init(const struct ovsrec_open_vswitch *cfg)
     svec_sort(&bridge_names);
 
     svec_init(&dpif_names);
-    dp_enumerate(&dpif_names);
+    svec_init(&dpif_types);
+    dp_enumerate(&dpif_names, &dpif_types);
     for (i = 0; i < dpif_names.n; i++) {
-        const char *dpif_name = dpif_names.names[i];
         struct dpif *dpif;
         int retval;
 
-        retval = dpif_open(dpif_name, &dpif);
+        retval = dpif_open(dpif_names.names[i], dpif_types.names[i], &dpif);
         if (!retval) {
             struct svec all_names;
             size_t j;
@@ -322,6 +322,7 @@ bridge_init(const struct ovsrec_open_vswitch *cfg)
         }
     }
     svec_destroy(&dpif_names);
+    svec_destroy(&dpif_types);
 
     unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows,
                              NULL);
@@ -560,11 +561,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 +1077,35 @@ bridge_unixctl_fdb_show(struct unixctl_conn *conn,
 
 /* 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);
diff --git a/vswitchd/vswitch-idl.ovsidl b/vswitchd/vswitch-idl.ovsidl
index 27804d4..77583a0 100644
--- a/vswitchd/vswitch-idl.ovsidl
+++ b/vswitchd/vswitch-idl.ovsidl
@@ -41,6 +41,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},
-- 
1.6.3.3





More information about the dev mailing list