Bond rebalances come with a risk of packet reordering which some
users may find unacceptable.

Requested-by: Ben Basler <bbas...@nicira.com>
Signed-off-by: Ethan Jackson <et...@nicira.com>
---
 AUTHORS              |    1 +
 lib/bond.c           |   20 +++++++++++++-------
 lib/bond.h           |    3 ++-
 vswitchd/bridge.c    |    2 +-
 vswitchd/vswitch.xml |   12 +++++++-----
 5 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 4479aeb..e81f563 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -65,6 +65,7 @@ Ahmed Bilal             numan...@gmail.com
 Alban Browaeys          pra...@yahoo.com
 Alex Yip                a...@nicira.com
 Alexey I. Froloff       ra...@altlinux.org
+Ben Basler              bbas...@nicira.com
 Bob Ball                bob.b...@citrix.com
 Brad Hall               b...@nicira.com
 Brandon Heller          brand...@stanford.edu
diff --git a/lib/bond.c b/lib/bond.c
index 50a1d5d..157e988 100644
--- a/lib/bond.c
+++ b/lib/bond.c
@@ -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),
diff --git a/lib/bond.h b/lib/bond.h
index 9eb1b8f..6d8161d 100644
--- a/lib/bond.h
+++ b/lib/bond.h
@@ -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. */
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 06e9088..a00d4cf 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -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;
     }
 
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index b720f05..71fee39 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -918,11 +918,13 @@
         </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 an 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.  If less than 1000ms, the rebalance interval will be
+          1000ms.
         </column>
       </group>
 
-- 
1.7.8.3

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to