bond: Reset bond_entry's during massive flow revalidations.
authorEthan Jackson <ethan@nicira.com>
Wed, 13 Apr 2011 20:56:37 +0000 (13:56 -0700)
committerEthan Jackson <ethan@nicira.com>
Wed, 13 Apr 2011 21:14:57 +0000 (14:14 -0700)
When all flows in a bond are revalidated, stale bond_entry's can
cause incorrect load balancing.  These issues will naturally
resolve themselves overtime.  However, it's better to deal with
them immediately.

lib/bond.c

index 343c334..ee0e68c 100644 (file)
@@ -117,6 +117,7 @@ struct bond {
 
 static struct hmap all_bonds = HMAP_INITIALIZER(&all_bonds);
 
+static void bond_entry_reset(struct bond *);
 static struct bond_slave *bond_slave_lookup(struct bond *, const void *slave_);
 static bool bond_is_link_up(struct bond *, struct netdev *);
 static void bond_enable_slave(struct bond_slave *, bool enable,
@@ -286,18 +287,6 @@ bond_reconfigure(struct bond *bond, const struct bond_settings *s)
         revalidate = true;
     }
 
-    if (bond->balance != BM_AB) {
-        if (!bond->hash) {
-            bond->hash = xcalloc(BOND_MASK + 1, sizeof *bond->hash);
-            bond->next_rebalance = time_msec() + bond->rebalance_interval;
-        }
-    } else {
-        if (bond->hash) {
-            free(bond->hash);
-            bond->hash = NULL;
-        }
-    }
-
     if (bond->detect == BLSM_CARRIER) {
         struct bond_slave *slave;
 
@@ -335,6 +324,10 @@ bond_reconfigure(struct bond *bond, const struct bond_settings *s)
         bond->next_fake_iface_update = LLONG_MAX;
     }
 
+    if (bond->balance == BM_AB || !bond->hash || revalidate) {
+        bond_entry_reset(bond);
+    }
+
     return revalidate;
 }
 
@@ -494,6 +487,7 @@ bond_run(struct bond *bond, struct tag_set *tags)
     if (is_tcp_hash != bond_is_tcp_hash(bond)) {
         struct bond_slave *slave;
 
+        bond_entry_reset(bond);
         HMAP_FOR_EACH (slave, hmap_node, &bond->slaves) {
             tag_set_add(tags, slave->tag);
         }
@@ -1278,6 +1272,24 @@ bond_init(void)
     unixctl_command_register("bond/hash", bond_unixctl_hash, NULL);
 }
 \f
+static void
+bond_entry_reset(struct bond *bond)
+{
+    if (bond->balance != BM_AB) {
+        size_t hash_len = (BOND_MASK + 1) * sizeof *bond->hash;
+
+        if (!bond->hash) {
+            bond->hash = xmalloc(hash_len);
+        }
+        memset(bond->hash, 0, hash_len);
+
+        bond->next_rebalance = time_msec() + bond->rebalance_interval;
+    } else {
+        free(bond->hash);
+        bond->hash = NULL;
+    }
+}
+
 static struct bond_slave *
 bond_slave_lookup(struct bond *bond, const void *slave_)
 {