ofproto-dpif: Use a single underlying datapath across multiple bridges.
[openvswitch] / vswitchd / bridge.c
index 8240d2503a9c3921435e0044f22803c0a028f373..27d40a87519f252d3ac4f5525bf94195f9af77b8 100644 (file)
@@ -262,6 +262,48 @@ static void configure_splinter_port(struct port *);
 static void add_vlan_splinter_ports(struct bridge *,
                                     const unsigned long int *splinter_vlans,
                                     struct shash *ports);
+
+static void
+bridge_init_ofproto(const struct ovsrec_open_vswitch *cfg)
+{
+    struct shash iface_hints;
+    static bool initialized = false;
+    int i;
+
+    if (initialized) {
+        return;
+    }
+
+    shash_init(&iface_hints);
+
+    for (i = 0; i < cfg->n_bridges; i++) {
+        const struct ovsrec_bridge *br_cfg = cfg->bridges[i];
+        int j;
+
+        for (j = 0; j < br_cfg->n_ports; j++) {
+            struct ovsrec_port *port_cfg = br_cfg->ports[j];
+            int k;
+
+            for (k = 0; k < port_cfg->n_interfaces; k++) {
+                struct ovsrec_interface *if_cfg = port_cfg->interfaces[k];
+                struct iface_hint *iface_hint;
+
+                iface_hint = xmalloc(sizeof *iface_hint);
+                iface_hint->br_name = br_cfg->name;
+                iface_hint->br_type = br_cfg->datapath_type;
+                iface_hint->ofp_port = if_cfg->n_ofport_request ?
+                                       *if_cfg->ofport_request : OFPP_NONE;
+
+                shash_add(&iface_hints, if_cfg->name, iface_hint);
+            }
+        }
+    }
+
+    ofproto_init(&iface_hints);
+
+    shash_destroy_free_data(&iface_hints);
+    initialized = true;
+}
 \f
 /* Public functions. */
 
@@ -2036,8 +2078,17 @@ refresh_instant_stats(void)
 void
 bridge_run_fast(void)
 {
+    struct sset types;
+    const char *type;
     struct bridge *br;
 
+    sset_init(&types);
+    ofproto_enumerate_types(&types);
+    SSET_FOR_EACH (type, &types) {
+        ofproto_type_run_fast(type);
+    }
+    sset_destroy(&types);
+
     HMAP_FOR_EACH (br, node, &all_bridges) {
         ofproto_run_fast(br->ofproto);
     }
@@ -2049,6 +2100,8 @@ bridge_run(void)
     static const struct ovsrec_open_vswitch null_cfg;
     const struct ovsrec_open_vswitch *cfg;
     struct ovsdb_idl_txn *reconf_txn = NULL;
+    struct sset types;
+    const char *type;
 
     bool vlan_splinters_changed;
     struct bridge *br;
@@ -2076,6 +2129,20 @@ bridge_run(void)
     }
     cfg = ovsrec_open_vswitch_first(idl);
 
+    /* Initialize the ofproto library.  This only needs to run once, but
+     * it must be done after the configuration is set.  If the
+     * initialization has already occurred, bridge_init_ofproto()
+     * returns immediately. */
+    bridge_init_ofproto(cfg);
+
+    /* Let each datapath type do the work that it needs to do. */
+    sset_init(&types);
+    ofproto_enumerate_types(&types);
+    SSET_FOR_EACH (type, &types) {
+        ofproto_type_run(type);
+    }
+    sset_destroy(&types);
+
     /* Let each bridge do the work that it needs to do. */
     HMAP_FOR_EACH (br, node, &all_bridges) {
         ofproto_run(br->ofproto);
@@ -2178,12 +2245,22 @@ bridge_run(void)
 void
 bridge_wait(void)
 {
+    struct sset types;
+    const char *type;
+
     ovsdb_idl_wait(idl);
 
     if (reconfiguring) {
         poll_immediate_wake();
     }
 
+    sset_init(&types);
+    ofproto_enumerate_types(&types);
+    SSET_FOR_EACH (type, &types) {
+        ofproto_type_wait(type);
+    }
+    sset_destroy(&types);
+
     if (!hmap_is_empty(&all_bridges)) {
         struct bridge *br;
 
@@ -3068,11 +3145,14 @@ static const char *
 iface_get_type(const struct ovsrec_interface *iface,
                const struct ovsrec_bridge *br)
 {
-    /* The local port always has type "internal".  Other ports take their type
-     * from the database and default to "system" if none is specified. */
-    return (!strcmp(iface->name, br->name) ? "internal"
-            : iface->type[0] ? iface->type
-            : "system");
+    /* The local port always has type "internal" unless the bridge is of
+     * type "dummy".  Other ports take their type from the database and
+     * default to "system" if none is specified. */
+    if (!strcmp(iface->name, br->name)) {
+        return !strcmp(br->datapath_type, "dummy") ? "dummy" : "internal";
+    } else {
+        return iface->type[0] ? iface->type : "system";
+    }
 }
 
 static void