- assert(bond->balance != BM_AB);
- return &bond->hash[(bond_is_tcp_hash(bond)
- ? bond_hash_tcp(flow, vlan)
- : bond_hash_src(flow->dl_src, vlan)) & BOND_MASK];
+ return &bond->hash[bond_hash(bond, flow, vlan) & BOND_MASK];
+}
+
+/* This function uses Highest Random Weight hashing to choose an output slave.
+ * This approach only reassigns a minimal number of flows when slaves are
+ * enabled or disabled. Unfortunately, it has O(n) performance against the
+ * number of slaves. There exist algorithms which are O(1), but have slightly
+ * 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)
+{
+ struct bond_slave *best, *slave;
+ uint32_t best_hash, flow_hash;
+
+ best = NULL;
+ best_hash = 0;
+ flow_hash = bond_hash(bond, flow, vlan);
+ HMAP_FOR_EACH (slave, hmap_node, &bond->slaves) {
+ if (slave->enabled) {
+ uint32_t hash;
+
+ hash = hash_2words(flow_hash, slave->stb_id);
+ if (!best || hash > best_hash) {
+ best = slave;
+ best_hash = hash;
+ }
+ }
+ }
+
+ return best;