Add functions to determine how port should be opened based on type.
authorJustin Pettit <jpettit@nicira.com>
Wed, 14 Nov 2012 23:50:20 +0000 (15:50 -0800)
committerJustin Pettit <jpettit@nicira.com>
Fri, 16 Nov 2012 20:35:55 +0000 (12:35 -0800)
Depending on the port and type of datapath, a port may need to be opened
as a different type of device than it's configured.  For example, an
"internal" port on a "dummy" datapath should opened as a "dummy" port.
This commit adds the ability for a dpif to provide this information to a
caller.  It will be used in a future commit.

Signed-off-by: Justin Pettit <jpettit@nicira.com>
lib/dpif-linux.c
lib/dpif-netdev.c
lib/dpif-provider.h
lib/dpif.c
lib/dpif.h
ofproto/ofproto-dpif.c
ofproto/ofproto-provider.h
ofproto/ofproto.c
ofproto/ofproto.h

index 67ff805be983741cd29858ff681e1ad983d126af..496230e0365d2b461f39d523b43e8b1ba785e289 100644 (file)
@@ -1281,6 +1281,7 @@ dpif_linux_recv_purge(struct dpif *dpif_)
 const struct dpif_class dpif_linux_class = {
     "system",
     dpif_linux_enumerate,
+    NULL,
     dpif_linux_open,
     dpif_linux_close,
     dpif_linux_destroy,
index a294ffc845d4a6cca6ed9baa74edac9348234527..cd4ab2827acae1852010980ea615fd2e4e1413fc 100644 (file)
@@ -181,6 +181,14 @@ dpif_netdev_enumerate(struct sset *all_dps)
     return 0;
 }
 
+static const char *
+dpif_netdev_port_open_type(const struct dpif_class *class, const char *type)
+{
+    return strcmp(type, "internal") ? type
+                  : class != &dpif_netdev_class ? "dummy"
+                  : "tap";
+}
+
 static struct dpif *
 create_dpif_netdev(struct dp_netdev *dp)
 {
@@ -369,9 +377,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
     /* XXX reject devices already in some dp_netdev. */
 
     /* Open and validate network device. */
-    open_type = (strcmp(type, "internal") ? type
-                 : dp->class != &dpif_netdev_class ? "dummy"
-                 : "tap");
+    open_type = dpif_netdev_port_open_type(dp->class, type);
     error = netdev_open(devname, open_type, &netdev);
     if (error) {
         return error;
@@ -1282,6 +1288,7 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
 const struct dpif_class dpif_netdev_class = {
     "netdev",
     dpif_netdev_enumerate,
+    dpif_netdev_port_open_type,
     dpif_netdev_open,
     dpif_netdev_close,
     dpif_netdev_destroy,
index bc1894292135f567d45909c098af52252a8d3980..74120cda82e822be54a09c894e2ed206d3870611 100644 (file)
@@ -80,6 +80,17 @@ struct dpif_class {
      * case this function may be a null pointer. */
     int (*enumerate)(struct sset *all_dps);
 
+    /* Returns the type to pass to netdev_open() when a dpif of class
+     * 'dpif_class' has a port of type 'type', for a few special cases
+     * when a netdev type differs from a port type.  For example, when
+     * using the userspace datapath, a port of type "internal" needs to
+     * be opened as "tap".
+     *
+     * Returns either 'type' itself or a string literal, which must not
+     * be freed. */
+    const char *(*port_open_type)(const struct dpif_class *dpif_class,
+                                  const char *type);
+
     /* 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.
      *
index 0093f6142479e8d58b97e4977282af05bcaba30f..9577e4faa7719decc75811cf5350f5837f0f2c90 100644 (file)
@@ -417,6 +417,23 @@ dpif_get_dp_stats(const struct dpif *dpif, struct dpif_dp_stats *stats)
     return error;
 }
 
+const char *
+dpif_port_open_type(const char *datapath_type, const char *port_type)
+{
+    struct registered_dpif_class *registered_class;
+
+    datapath_type = dpif_normalize_type(datapath_type);
+
+    registered_class = shash_find_data(&dpif_classes, datapath_type);
+    if (!registered_class
+            || !registered_class->dpif_class->port_open_type) {
+        return port_type;
+    }
+
+    return registered_class->dpif_class->port_open_type(
+                          registered_class->dpif_class, port_type);
+}
+
 /* Attempts to add 'netdev' as a port on 'dpif'.  If 'port_nop' is
  * non-null and its value is not UINT32_MAX, then attempts to use the
  * value as the port number.
index 7d0881fab3127640fc9fcc0b275c0daa636a7381..893338b2b4ffb357e4980521af5ea3da83d85c8b 100644 (file)
@@ -73,6 +73,8 @@ int dpif_get_dp_stats(const struct dpif *, struct dpif_dp_stats *);
 \f
 /* Port operations. */
 
+const char *dpif_port_open_type(const char *datapath_type,
+                                const char *port_type);
 int dpif_port_add(struct dpif *, struct netdev *, uint32_t *port_nop);
 int dpif_port_del(struct dpif *, uint32_t port_no);
 
index 283aea98d58989103c60d359f2867384a20ead66..fe0aae3b8a7e0a9ff2b100f6f9f4e40cee05a566 100644 (file)
@@ -780,6 +780,12 @@ del(const char *type, const char *name)
     return error;
 }
 \f
+static const char *
+port_open_type(const char *datapath_type, const char *port_type)
+{
+    return dpif_port_open_type(datapath_type, port_type);
+}
+
 /* Type functions. */
 
 static int
@@ -7865,6 +7871,7 @@ const struct ofproto_class ofproto_dpif_class = {
     enumerate_types,
     enumerate_names,
     del,
+    port_open_type,
     type_run,
     type_run_fast,
     type_wait,
index 26343cf0e126c8232d6f31e6fcd802c75fe94e8f..8f6f6b1a829ae79fc1b54957058291115e38b47f 100644 (file)
@@ -382,6 +382,17 @@ struct ofproto_class {
      */
     int (*del)(const char *type, const char *name);
 
+    /* Returns the type to pass to netdev_open() when a datapath of type
+     * 'datapath_type' has a port of type 'port_type', for a few special
+     * cases when a netdev type differs from a port type.  For example,
+     * when using the userspace datapath, a port of type "internal"
+     * needs to be opened as "tap".
+     *
+     * Returns either 'type' itself or a string literal, which must not
+     * be freed. */
+    const char *(*port_open_type)(const char *datapath_type,
+                                  const char *port_type);
+
 /* ## ------------------------ ## */
 /* ## Top-Level type Functions ## */
 /* ## ------------------------ ## */
index 0aeb07e2fa17cd97c5465b6dc5e2da16193a8e56..182da63363e3fc952783d535f581ab9d2993ce78 100644 (file)
@@ -1433,6 +1433,30 @@ ofproto_port_dump_done(struct ofproto_port_dump *dump)
     return dump->error == EOF ? 0 : dump->error;
 }
 
+/* Returns the type to pass to netdev_open() when a datapath of type
+ * 'datapath_type' has a port of type 'port_type', for a few special
+ * cases when a netdev type differs from a port type.  For example, when
+ * using the userspace datapath, a port of type "internal" needs to be
+ * opened as "tap".
+ *
+ * Returns either 'type' itself or a string literal, which must not be
+ * freed. */
+const char *
+ofproto_port_open_type(const char *datapath_type, const char *port_type)
+{
+    const struct ofproto_class *class;
+
+    datapath_type = ofproto_normalize_type(datapath_type);
+    class = ofproto_class_find__(datapath_type);
+    if (!class) {
+        return port_type;
+    }
+
+    return (class->port_open_type
+            ? class->port_open_type(datapath_type, port_type)
+            : port_type);
+}
+
 /* Attempts to add 'netdev' as a port on 'ofproto'.  If 'ofp_portp' is
  * non-null and '*ofp_portp' is not OFPP_NONE, attempts to use that as
  * the port's OpenFlow port number.
index 0366c89f0772e1e9b3a2997619970122cc6ed2b5..e4abe523d4873f5389dbdf31a4ef0e23d042c88a 100644 (file)
@@ -207,6 +207,8 @@ int ofproto_port_dump_done(struct ofproto_port_dump *);
 #define OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT  1000
 #define OFPROTO_FLOW_EVICTION_THRESHOLD_MIN 100
 
+const char *ofproto_port_open_type(const char *datapath_type,
+                                   const char *port_type);
 int ofproto_port_add(struct ofproto *, struct netdev *, uint16_t *ofp_portp);
 int ofproto_port_del(struct ofproto *, uint16_t ofp_port);
 int ofproto_port_get_stats(const struct ofport *, struct netdev_stats *stats);