vswitch: Consistently set Nicira OUI.
[sliver-openvswitch.git] / vswitchd / bridge.c
index d7f1979..e945ca8 100644 (file)
@@ -61,6 +61,7 @@
 #include "vswitchd/vswitch-idl.h"
 #include "xenserver.h"
 #include "xtoxll.h"
+#include "sflow_api.h"
 
 #define THIS_MODULE VLM_bridge
 #include "vlog.h"
@@ -193,11 +194,14 @@ 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;
 static int bridge_run_one(struct bridge *);
+static const struct ovsrec_controller *bridge_get_controller(
+                      const struct ovsrec_open_vswitch *ovs_cfg,
+                      const struct bridge *br);
 static void bridge_reconfigure_one(const struct ovsrec_open_vswitch *,
                                    struct bridge *);
 static void bridge_reconfigure_controller(const struct ovsrec_open_vswitch *,
@@ -285,7 +289,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 +301,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);
@@ -530,6 +540,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
     struct shash_node *node;
     struct bridge *br, *next;
     size_t i;
+    int sflow_bridge_number;
 
     COVERAGE_INC(bridge_reconfigure);
 
@@ -560,11 +571,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);
@@ -658,6 +674,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
         shash_destroy(&cur_ifaces);
         shash_destroy(&want_ifaces);
     }
+    sflow_bridge_number = 0;
     LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
         uint8_t ea[8];
         uint64_t dpid;
@@ -699,10 +716,10 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
 
             dpif_get_netflow_ids(br->dpif, &opts.engine_type, &opts.engine_id);
             if (nf_cfg->engine_type) {
-                opts.engine_type = nf_cfg->engine_type;
+                opts.engine_type = *nf_cfg->engine_type;
             }
             if (nf_cfg->engine_id) {
-                opts.engine_id = nf_cfg->engine_id;
+                opts.engine_id = *nf_cfg->engine_id;
             }
 
             opts.active_timeout = nf_cfg->active_timeout;
@@ -739,6 +756,44 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
             ofproto_set_netflow(br->ofproto, NULL);
         }
 
+        /* Set sFlow configuration on this bridge. */
+        if (br->cfg->sflow) {
+            const struct ovsrec_sflow *sflow_cfg = br->cfg->sflow;
+            const struct ovsrec_controller *ctrl;
+            struct ofproto_sflow_options oso;
+
+            memset(&oso, 0, sizeof oso);
+
+            oso.targets.n = sflow_cfg->n_targets;
+            oso.targets.names = sflow_cfg->targets;
+
+            oso.sampling_rate = SFL_DEFAULT_SAMPLING_RATE;
+            if (sflow_cfg->sampling) {
+                oso.sampling_rate = *sflow_cfg->sampling;
+            }
+
+            oso.polling_interval = SFL_DEFAULT_POLLING_INTERVAL;
+            if (sflow_cfg->polling) {
+                oso.polling_interval = *sflow_cfg->polling;
+            }
+
+            oso.header_len = SFL_DEFAULT_HEADER_SIZE;
+            if (sflow_cfg->header) {
+                oso.header_len = *sflow_cfg->header;
+            }
+
+            oso.sub_id = sflow_bridge_number++;
+            oso.agent_device = sflow_cfg->agent;
+
+            ctrl = bridge_get_controller(ovs_cfg, br);
+            oso.control_ip = ctrl ? ctrl->local_ip : NULL;
+            ofproto_set_sflow(br->ofproto, &oso);
+
+            svec_destroy(&oso.targets);
+        } else {
+            ofproto_set_sflow(br->ofproto, NULL);
+        }
+
         /* Update the controller and related settings.  It would be more
          * straightforward to call this from bridge_reconfigure_one(), but we
          * can't do it there for two reasons.  First, and most importantly, at
@@ -1071,34 +1126,38 @@ 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);
+    eth_addr_nicira_random(br->default_ea);
 
     port_array_init(&br->ifaces);
 
@@ -1247,7 +1306,6 @@ bridge_reconfigure_one(const struct ovsrec_open_vswitch *ovs_cfg,
     struct svec listeners, old_listeners;
     struct svec snoops, old_snoops;
     struct shash_node *node;
-    uint64_t mgmt_id;
     size_t i;
 
     /* Collect old ports. */
@@ -1283,9 +1341,6 @@ bridge_reconfigure_one(const struct ovsrec_open_vswitch *ovs_cfg,
         }
     }
 
-    dpid_from_string(ovs_cfg->management_id, &mgmt_id);
-    ofproto_set_mgmt_id(br->ofproto, mgmt_id);
-
     /* Get rid of deleted ports and add new ports. */
     SHASH_FOR_EACH (node, &old_ports) {
         if (!shash_find(&new_ports, node->name)) {
@@ -3522,7 +3577,7 @@ mirror_reconfigure(struct bridge *br)
         }
     }
 
-    /* Update learning disabled vlans (for RSPAN). */
+    /* Update flooded vlans (for RSPAN). */
     rspan_vlans = NULL;
     if (br->cfg->n_flood_vlans) {
         rspan_vlans = bitmap_allocate(4096);
@@ -3539,7 +3594,7 @@ mirror_reconfigure(struct bridge *br)
             }
         }
     }
-    if (mac_learning_set_disabled_vlans(br->ml, rspan_vlans)) {
+    if (mac_learning_set_flood_vlans(br->ml, rspan_vlans)) {
         bridge_flush(br);
     }
 }