bond: New bond-hash-basis setting.
authorEthan Jackson <ethan@nicira.com>
Thu, 21 Apr 2011 20:55:45 +0000 (13:55 -0700)
committerEthan Jackson <ethan@nicira.com>
Tue, 26 Apr 2011 18:05:28 +0000 (11:05 -0700)
lib/bond.c
lib/bond.h
vswitchd/bridge.c
vswitchd/ovs-vswitchd.8.in
vswitchd/vswitch.xml

index ed6ed89b887f17ba2300e116c18c6c4f5e240914..d7242fae2e625507b9b521415c0d0f68945d123d 100644 (file)
@@ -93,6 +93,7 @@ struct bond {
     int updelay, downdelay;     /* Delay before slave goes up/down, in ms. */
     bool lacp_negotiated;       /* LACP negotiations were successful. */
     bool bond_revalidate;       /* True if flows need revalidation. */
+    uint32_t basis;             /* Basis for flow hash function. */
 
     /* SLB specific bonding info. */
     struct bond_entry *hash;     /* An array of (BOND_MASK + 1) elements. */
@@ -129,8 +130,9 @@ static void bond_link_status_update(struct bond_slave *, struct tag_set *);
 static void bond_choose_active_slave(struct bond *, struct tag_set *);
 static bool bond_is_tcp_hash(const struct bond *);
 static unsigned int bond_hash_src(const uint8_t mac[ETH_ADDR_LEN],
-                                  uint16_t vlan);
-static unsigned int bond_hash_tcp(const struct flow *, uint16_t vlan);
+                                  uint16_t vlan, uint32_t basis);
+static unsigned int bond_hash_tcp(const struct flow *, uint16_t vlan,
+                                  uint32_t basis);
 static struct bond_entry *lookup_bond_entry(const struct bond *,
                                             const struct flow *,
                                             uint16_t vlan);
@@ -291,6 +293,11 @@ bond_reconfigure(struct bond *bond, const struct bond_settings *s)
         revalidate = true;
     }
 
+    if (bond->basis != s->basis) {
+        bond->basis = s->basis;
+        revalidate = true;
+    }
+
     if (bond->detect == BLSM_CARRIER) {
         struct bond_slave *slave;
 
@@ -978,6 +985,8 @@ bond_unixctl_show(struct unixctl_conn *conn,
                       bond_is_tcp_hash(bond) ? "balance-tcp" : "balance-slb");
     }
 
+    ds_put_format(&ds, "bond-hash-basis: %"PRIu32"\n", bond->basis);
+
     ds_put_format(&ds, "bond-detect-mode: %s\n",
                   bond->monitor ? "carrier" : "miimon");
 
@@ -1206,11 +1215,13 @@ bond_unixctl_hash(struct unixctl_conn *conn, const char *args_,
     uint8_t hash;
     char *hash_cstr;
     unsigned int vlan;
-    char *mac_s, *vlan_s;
+    uint32_t basis;
+    char *mac_s, *vlan_s, *basis_s;
     char *save_ptr = NULL;
 
     mac_s  = strtok_r(args, " ", &save_ptr);
     vlan_s = strtok_r(NULL, " ", &save_ptr);
+    basis_s = strtok_r(NULL, " ", &save_ptr);
 
     if (vlan_s) {
         if (sscanf(vlan_s, "%u", &vlan) != 1) {
@@ -1221,9 +1232,18 @@ bond_unixctl_hash(struct unixctl_conn *conn, const char *args_,
         vlan = OFP_VLAN_NONE;
     }
 
+    if (basis_s) {
+        if (sscanf(basis_s, "%"PRIu32, &basis) != 1) {
+            unixctl_command_reply(conn, 501, "invalid basis");
+            return;
+        }
+    } else {
+        basis = 0;
+    }
+
     if (sscanf(mac_s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
         == ETH_ADDR_SCAN_COUNT) {
-        hash = bond_hash_src(mac, vlan) & BOND_MASK;
+        hash = bond_hash_src(mac, vlan, basis) & BOND_MASK;
 
         hash_cstr = xasprintf("%u", hash);
         unixctl_command_reply(conn, 200, hash_cstr);
@@ -1355,13 +1375,13 @@ bond_is_tcp_hash(const struct bond *bond)
 }
 
 static unsigned int
-bond_hash_src(const uint8_t mac[ETH_ADDR_LEN], uint16_t vlan)
+bond_hash_src(const uint8_t mac[ETH_ADDR_LEN], uint16_t vlan, uint32_t basis)
 {
-    return hash_bytes(mac, ETH_ADDR_LEN, vlan);
+    return hash_3words(hash_bytes(mac, ETH_ADDR_LEN, 0), vlan, basis);
 }
 
 static unsigned int
-bond_hash_tcp(const struct flow *flow, uint16_t vlan)
+bond_hash_tcp(const struct flow *flow, uint16_t vlan, uint32_t basis)
 {
     struct flow hash_flow = *flow;
     hash_flow.vlan_tci = vlan;
@@ -1369,7 +1389,7 @@ bond_hash_tcp(const struct flow *flow, uint16_t vlan)
     /* The symmetric quality of this hash function is not required, but
      * flow_hash_symmetric_l4 already exists, and is sufficient for our
      * purposes, so we use it out of convenience. */
-    return flow_hash_symmetric_l4(&hash_flow, 0);
+    return flow_hash_symmetric_l4(&hash_flow, basis);
 }
 
 static unsigned int
@@ -1378,8 +1398,8 @@ bond_hash(const struct bond *bond, const struct flow *flow, uint16_t vlan)
     assert(bond->balance != BM_AB);
 
     return (bond_is_tcp_hash(bond)
-            ? bond_hash_tcp(flow, vlan)
-            : bond_hash_src(flow->dl_src, vlan));
+            ? bond_hash_tcp(flow, vlan, bond->basis)
+            : bond_hash_src(flow->dl_src, vlan, bond->basis));
 }
 
 static struct bond_entry *
index b2ab89cd850b05f92352083b9e01d152d6fb5ec9..5847abc102b9fc899cf9a6a74ff4d956cf5ca9dd 100644 (file)
@@ -50,6 +50,7 @@ const char *bond_detect_mode_to_string(enum bond_detect_mode);
 /* Configuration for a bond as a whole. */
 struct bond_settings {
     char *name;                 /* Bond's name, for log messages. */
+    uint32_t basis;             /* Flow hashing basis. */
 
     /* Balancing configuration. */
     enum bond_mode balance;
index 84ed03e80122008ce3f38fe055dfa9f7b5b55f81..dee19a9bbf699a063dc6000ded8c45204cb9349d 100644 (file)
@@ -3258,6 +3258,8 @@ port_reconfigure_bond(struct port *port)
 
     s.up_delay = MAX(0, port->cfg->bond_updelay);
     s.down_delay = MAX(0, port->cfg->bond_downdelay);
+    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) {
index 4c02f8a4b995b2e62eb3d2239c7407392126e221..48825740382952aec0835b4f40802407692126ea 100644 (file)
@@ -182,9 +182,9 @@ updelay (or downdelay).
 .IP
 This setting is not permanent: it persists only until the carrier
 status of \fIslave\fR changes.
-.IP "\fBbond/hash\fR \fImac\fR [\fIvlan\fR]"
+.IP "\fBbond/hash\fR \fImac\fR [\fIvlan\fR] [\fIbasis\fR]"
 Returns the hash value which would be used for \fImac\fR with \fIvlan\fR
-if specified.
+and \fIbasis\fR if specified.
 .
 .IP "\fBlacp/show\fR \fIport\fR"
 Lists all of the LACP related information about the given \fIport\fR:
index ce00cbd70adf90de88e151575e7aa1d1fa0376ff..99f4fc40fbf77231862db8bc6795928f261b599f 100644 (file)
           <dd> The number of milliseconds between successive attempts to
             poll each interface's MII.  Only relevant on ports which use
             <code>miimon</code> to detect failures. </dd>
+          <dt><code>bond-hash-basis</code></dt>
+          <dd> An integer hashed along with flows when choosing output slaves.
+            When changed, all flows will be assigned different hash values
+            possibly causing slave selection decisions to change.</dd>
           <dt><code>lacp-system-id</code></dt>
           <dd> The LACP system ID of this <ref table="Port"/>.  The system ID
             of a LACP bond is used to identify itself to its partners.  Must