vswitch: Choose the datapath ID more intelligently.
authorBen Pfaff <blp@nicira.com>
Wed, 11 Mar 2009 00:01:52 +0000 (17:01 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 11 Mar 2009 00:02:28 +0000 (17:02 -0700)
The new algorithm needs to be documented (along with a lot of new vswitch
settings).

vswitchd/bridge.c

index 6d0d69111076b0f1ab0c165d1707c69ef5a19fbc..fc46d021203b22d5ef152c2e23f0df97a635bfa9 100644 (file)
@@ -201,7 +201,7 @@ static void bridge_get_all_ifaces(const struct bridge *, struct svec *ifaces);
 static void bridge_fetch_dp_ifaces(struct bridge *);
 static void bridge_flush(struct bridge *);
 static void bridge_pick_local_hw_addr(struct bridge *,
-                                      struct iface *local_iface);
+                                      uint8_t ea[ETH_ADDR_LEN]);
 
 static void bond_run(struct bridge *);
 static void bond_wait(struct bridge *);
@@ -417,6 +417,10 @@ bridge_reconfigure(void)
         bridge_fetch_dp_ifaces(br);
         for (i = 0; i < br->n_ports; ) {
             struct port *port = br->ports[i];
+            struct iface *local_iface = NULL;
+            uint8_t ea[8];
+            uint64_t dpid;
+
             for (j = 0; j < port->n_ifaces; ) {
                 struct iface *iface = port->ifaces[j];
                 if (iface->dp_ifidx < 0) {
@@ -424,20 +428,47 @@ bridge_reconfigure(void)
                              iface->name, dpif_id(&br->dpif));
                     iface_destroy(iface);
                 } else {
+                    if (iface->dp_ifidx == ODPP_LOCAL) {
+                        local_iface = iface;
+                    }
                     VLOG_DBG("dp%u has interface %s on port %d",
                              dpif_id(&br->dpif), iface->name, iface->dp_ifidx);
                     j++;
                 }
-                if (!strcmp(iface->name, br->name)) {
-                    bridge_pick_local_hw_addr(br, iface);
-                }
             }
             if (!port->n_ifaces) {
                 VLOG_ERR("%s port has no interfaces, dropping", port->name);
                 port_destroy(port);
-            } else {
-                i++;
+                continue;
+            }
+
+            /* Pick local port hardware address. */
+            bridge_pick_local_hw_addr(br, ea);
+            if (local_iface) {
+                int error = netdev_nodev_set_etheraddr(local_iface->name, ea);
+                if (error) {
+                    static struct vlog_rate_limit rl
+                        = VLOG_RATE_LIMIT_INIT(1, 5);
+                    VLOG_ERR_RL(&rl, "bridge %s: failed to set bridge "
+                                "Ethernet address: %s",
+                                br->name, strerror(error));
+                }
+            }
+
+            /* Pick datapath ID. */
+            dpid = cfg_get_dpid(0, "bridge.%s.datapath-id", br->name);
+            if (!dpid) {
+                dpid = eth_addr_to_uint64(ea);
             }
+            ofproto_set_datapath_id(br->ofproto, dpid);
+
+            /* Set the controller.  (It would be more straightforward to do
+             * this in bridge_reconfigure_one(), but then the
+             * ofproto_set_datapath_id() above would disconnect right away, and
+             * we can't call ofproto_set_datapath_id() until we know the set of
+             * ports actually in the bridge, hence not until now.) */
+            ofproto_set_controller(br->ofproto, br->controller);
+            i++;
         }
     }
     LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
@@ -446,21 +477,8 @@ bridge_reconfigure(void)
 }
 
 static void
-bridge_set_local_hw_addr(struct bridge *br, struct iface *local_iface,
-                         const uint8_t ea[ETH_ADDR_LEN])
+bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN])
 {
-    int error = netdev_nodev_set_etheraddr(local_iface->name, ea);
-    if (error) {
-        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
-        VLOG_ERR_RL(&rl, "bridge %s: failed to set bridge Ethernet "
-                    "address: %s", br->name, strerror(error));
-    }
-}
-
-static void
-bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface)
-{
-    uint8_t ea[ETH_ADDR_LEN];
     uint64_t requested_ea;
     size_t i, j;
     int error;
@@ -475,7 +493,6 @@ bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface)
         } else if (eth_addr_is_zero(ea)) {
             VLOG_ERR("bridge %s: cannot set MAC address to zero", br->name);
         } else {
-            bridge_set_local_hw_addr(br, local_iface, ea);
             return;
         }
     }
@@ -492,13 +509,14 @@ bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface)
         for (j = 0; j < port->n_ifaces; j++) {
             struct iface *iface = port->ifaces[j];
             uint8_t iface_ea[ETH_ADDR_LEN];
-            if (iface == local_iface) {
+            if (iface->dp_ifidx == ODPP_LOCAL) {
                 continue;
             }
             error = netdev_nodev_get_etheraddr(iface->name, iface_ea);
             if (!error) {
                 if (!eth_addr_is_multicast(iface_ea) &&
                     !eth_addr_is_reserved(iface_ea) &&
+                    !eth_addr_is_zero(iface_ea) &&
                     memcmp(iface_ea, ea, ETH_ADDR_LEN) < 0) {
                     memcpy(ea, iface_ea, ETH_ADDR_LEN);
                 }
@@ -509,7 +527,7 @@ bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface)
             }
         }
     }
-    if (eth_addr_is_broadcast(ea)) {
+    if (eth_addr_is_multicast(ea)) {
         memcpy(ea, br->default_ea, ETH_ADDR_LEN);
         VLOG_WARN("bridge %s: using default bridge Ethernet "
                   "address "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(ea));
@@ -517,7 +535,6 @@ bridge_pick_local_hw_addr(struct bridge *br, struct iface *local_iface)
         VLOG_DBG("bridge %s: using bridge Ethernet address "ETH_ADDR_FMT,
                  br->name, ETH_ADDR_ARGS(ea));
     }
-    bridge_set_local_hw_addr(br, local_iface, ea);
 }
 
 int
@@ -809,9 +826,6 @@ bridge_reconfigure_one(struct bridge *br)
                        || cfg_get_bool(0, "%s.in-band", pfx));
             ofproto_set_discovery(br->ofproto, false, NULL, NULL);
             ofproto_set_in_band(br->ofproto, in_band);
-            if (!br->controller || strcmp(ctl, br->controller)) {
-                ofproto_set_controller(br->ofproto, ctl);
-            }
 
             error = netdev_open(br->name, NETDEV_ETH_TYPE_NONE, &netdev);
             if (!error) {
@@ -891,7 +905,6 @@ bridge_reconfigure_one(struct bridge *br)
         ofproto_add_flow(br->ofproto, &flow, OFPFW_ALL, 0,
                          &action, 1, NULL, 0);
 
-        ofproto_set_controller(br->ofproto, NULL);
         ofproto_set_in_band(br->ofproto, false);
         ofproto_set_max_backoff(br->ofproto, 1);
         ofproto_set_probe_interval(br->ofproto, 5);