bond: Allow users to disable rebalancing.
authorEthan Jackson <ethan@nicira.com>
Thu, 26 Jan 2012 01:41:44 +0000 (17:41 -0800)
committerEthan Jackson <ethan@nicira.com>
Mon, 30 Jan 2012 21:04:41 +0000 (13:04 -0800)
Bond rebalances come with a risk of packet reordering which some
users may find unacceptable.

Requested-by: Ben Basler <bbasler@nicira.com>
Signed-off-by: Ethan Jackson <ethan@nicira.com>
AUTHORS
NEWS
lib/bond.c
lib/bond.h
vswitchd/bridge.c
vswitchd/vswitch.xml

diff --git a/AUTHORS b/AUTHORS
index a24f9707280a7ec6d6960c8137392e603dc38b3e..87bb7212bcd9f36859f932f79d2743c2c12bd89c 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -66,6 +66,7 @@ Alan Shieh              ashieh@nicira.com
 Alban Browaeys          prahal@yahoo.com
 Alex Yip                alex@nicira.com
 Alexey I. Froloff       raorn@altlinux.org
+Ben Basler              bbasler@nicira.com
 Bob Ball                bob.ball@citrix.com
 Brad Hall               brad@nicira.com
 Brandon Heller          brandonh@stanford.edu
diff --git a/NEWS b/NEWS
index e015739d06b7abb750964aab552137f04e8d68d7..aa28eeb977630ab290f6ad53f5eeb8a7e16808ac 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ post-v1.5.0
         - The default bond_mode changed from SLB to active-backup, to protect
           unsuspecting users from the significant risks of SLB bonds (which are
           documented in vswitchd/INTERNALS).
+        - Load balancing can be disabled by setting the bond-rebalance-interval
+          to zero.
     - Logging to console and file will have UTC timestamp as a default for all
       the daemons. An example of the default format is 2012-01-27T16:35:17Z.
       ovs-appctl can be used to change the default format as before.
index 50a1d5d0d88904edd7a7b9ed484258d507f9bcd1..157e9889ed014a34119ed33b59414dd61d36e009 100644 (file)
@@ -246,7 +246,11 @@ bond_reconfigure(struct bond *bond, const struct bond_settings *s)
 
     bond->updelay = s->up_delay;
     bond->downdelay = s->down_delay;
-    bond->rebalance_interval = s->rebalance_interval;
+
+    if (bond->rebalance_interval != s->rebalance_interval) {
+        bond->rebalance_interval = s->rebalance_interval;
+        revalidate = true;
+    }
 
     if (bond->balance != s->balance) {
         bond->balance = s->balance;
@@ -648,7 +652,8 @@ bond_choose_output_slave(struct bond *bond, const struct flow *flow,
 static bool
 bond_is_balanced(const struct bond *bond)
 {
-    return bond->balance == BM_SLB || bond->balance == BM_TCP;
+    return bond->rebalance_interval
+        && (bond->balance == BM_SLB || bond->balance == BM_TCP);
 }
 
 /* Notifies 'bond' that 'n_bytes' bytes were sent in 'flow' within 'vlan'. */
@@ -1376,15 +1381,13 @@ lookup_bond_entry(const struct bond *bond, const struct flow *flow,
  * more complex implementations and require the use of memory.  This may need
  * to be reimplemented if it becomes a performance bottleneck. */
 static struct bond_slave *
-choose_stb_slave(const struct bond *bond, const struct flow *flow,
-                 uint16_t vlan)
+choose_stb_slave(const struct bond *bond, uint32_t flow_hash)
 {
     struct bond_slave *best, *slave;
-    uint32_t best_hash, flow_hash;
+    uint32_t best_hash;
 
     best = NULL;
     best_hash = 0;
-    flow_hash = bond_hash_tcp(flow, vlan, bond->basis);
     HMAP_FOR_EACH (slave, hmap_node, &bond->slaves) {
         if (slave->enabled) {
             uint32_t hash;
@@ -1417,7 +1420,7 @@ choose_output_slave(const struct bond *bond, const struct flow *flow,
         return bond->active_slave;
 
     case BM_STABLE:
-        return choose_stb_slave(bond, flow, vlan);
+        return choose_stb_slave(bond, bond_hash_tcp(flow, vlan, bond->basis));
 
     case BM_TCP:
         if (bond->lacp_status != LACP_NEGOTIATED) {
@@ -1426,6 +1429,9 @@ choose_output_slave(const struct bond *bond, const struct flow *flow,
         }
         /* Fall Through. */
     case BM_SLB:
+        if (!bond_is_balanced(bond)) {
+            return choose_stb_slave(bond, bond_hash(bond, flow, vlan));
+        }
         e = lookup_bond_entry(bond, flow, vlan);
         if (!e->slave || !e->slave->enabled) {
             e->slave = CONTAINER_OF(hmap_random_node(&bond->slaves),
index 9eb1b8fb8bfb8fab7d477551f037dd653dbbee86..6d8161d82ff6820a5a21749a5ca3606529a1c8ec 100644 (file)
@@ -46,7 +46,8 @@ struct bond_settings {
 
     /* Balancing configuration. */
     enum bond_mode balance;
-    int rebalance_interval;     /* Milliseconds between rebalances. */
+    int rebalance_interval;     /* Milliseconds between rebalances.
+                                   Zero to disable rebalancing. */
 
     /* Link status detection. */
     int up_delay;               /* ms before enabling an up slave. */
index 06e9088e2f4f2e6fce66665dcaa80adde75804b6..a00d4cfa8fbc4a364f08bf2150cfc24b6a166978 100644 (file)
@@ -2790,7 +2790,7 @@ port_configure_bond(struct port *port, struct bond_settings *s,
     s->basis = atoi(get_port_other_config(port->cfg, "bond-hash-basis", "0"));
     s->rebalance_interval = atoi(
         get_port_other_config(port->cfg, "bond-rebalance-interval", "10000"));
-    if (s->rebalance_interval < 1000) {
+    if (s->rebalance_interval && s->rebalance_interval < 1000) {
         s->rebalance_interval = 1000;
     }
 
index b720f059c11b1911f1291fa9ed525ac578f495d6..d04a3a2a7d37e2f63a43e16dc116742d924cae1c 100644 (file)
         </p>
 
         <column name="other_config" key="bond-rebalance-interval"
-                type='{"type": "integer", "minInteger": 1000, "maxInteger": 10000}'>
-          For an SLB bonded port, the number of milliseconds between successive
-          attempts to rebalance the bond, that is, to move source MACs and
-          their flows from one interface on the bond to another in an attempt
-          to keep usage of each interface roughly equal.
+                type='{"type": "integer", "minInteger": 0, "maxInteger": 10000}'>
+          For a load balanced bonded port, the number of milliseconds between
+          successive attempts to rebalance the bond, that is, to move flows
+          from one interface on the bond to another in an attempt to keep usage
+          of each interface roughly equal.  If zero, load balancing is disabled
+          on the bond (carrier status changes still cause flows to move).  If
+          less than 1000ms, the rebalance interval will be 1000ms.
         </column>
       </group>