aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahesh Bandewar <maheshb@google.com>2014-04-22 19:30:22 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-24 13:04:34 -0400
commite9f0fb88493570200b8dc1cc02d3e676412d25bc (patch)
treeedd781d8c00772c53e0736a95cf26f0ef2e620dc
parentf05b42eaa22cd7c6736d31316e6046c5127f8721 (diff)
bonding: Add tlb_dynamic_lb parameter for tlb mode
The aggresive load balancing causes packet re-ordering as active flows are moved from a slave to another within the group. Sometime this aggresive lb is not necessary if the preference is for less re-ordering. This parameter if used with value "0" disables this dynamic flow shuffling minimizing packet re-ordering. Of course the side effect is that it has to live with the static load balancing that the hashing distribution provides. This impact is less severe if the correct xmit-hashing-policy is used for the tlb setup. The default value of the parameter is set to "1" mimicing the earlier behavior. Ran the netperf test with 200 stream for 1 min between two hosts with 4x1G trunk (xmit-lb mode with xmit-policy L3+4) before and after these changes. Following was the command used for those 200 instances - netperf -t TCP_RR -l 60 -s 5 -H <host> -- -r81920,81920 Transactions per second: Before change: 1,367.11 After change: 1,470.65 Change-Id: Ie3f75c77282cf602e83a6e833c6eb164e72a0990 Signed-off-by: Mahesh Bandewar <maheshb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/networking/bonding.txt42
-rw-r--r--drivers/net/bonding/bond_alb.c19
-rw-r--r--drivers/net/bonding/bond_main.c4
-rw-r--r--drivers/net/bonding/bond_options.c27
-rw-r--r--drivers/net/bonding/bond_options.h1
-rw-r--r--drivers/net/bonding/bond_sysfs.c29
-rw-r--r--drivers/net/bonding/bonding.h1
7 files changed, 111 insertions, 12 deletions
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index a97c567f24e8..9c723ecd0025 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -585,13 +585,19 @@ mode
585 balance-tlb or 5 585 balance-tlb or 5
586 586
587 Adaptive transmit load balancing: channel bonding that 587 Adaptive transmit load balancing: channel bonding that
588 does not require any special switch support. The 588 does not require any special switch support.
589 outgoing traffic is distributed according to the 589
590 current load (computed relative to the speed) on each 590 In tlb_dynamic_lb=1 mode; the outgoing traffic is
591 slave. Incoming traffic is received by the current 591 distributed according to the current load (computed
592 slave. If the receiving slave fails, another slave 592 relative to the speed) on each slave.
593 takes over the MAC address of the failed receiving 593
594 slave. 594 In tlb_dynamic_lb=0 mode; the load balancing based on
595 current load is disabled and the load is distributed
596 only using the hash distribution.
597
598 Incoming traffic is received by the current slave.
599 If the receiving slave fails, another slave takes over
600 the MAC address of the failed receiving slave.
595 601
596 Prerequisite: 602 Prerequisite:
597 603
@@ -736,6 +742,28 @@ primary_reselect
736 742
737 This option was added for bonding version 3.6.0. 743 This option was added for bonding version 3.6.0.
738 744
745tlb_dynamic_lb
746
747 Specifies if dynamic shuffling of flows is enabled in tlb
748 mode. The value has no effect on any other modes.
749
750 The default behavior of tlb mode is to shuffle active flows across
751 slaves based on the load in that interval. This gives nice lb
752 characteristics but can cause packet reordering. If re-ordering is
753 a concern use this variable to disable flow shuffling and rely on
754 load balancing provided solely by the hash distribution.
755 xmit-hash-policy can be used to select the appropriate hashing for
756 the setup.
757
758 The sysfs entry can be used to change the setting per bond device
759 and the initial value is derived from the module parameter. The
760 sysfs entry is allowed to be changed only if the bond device is
761 down.
762
763 The default value is "1" that enables flow shuffling while value "0"
764 disables it. This option was added in bonding driver 3.7.1
765
766
739updelay 767updelay
740 768
741 Specifies the time, in milliseconds, to wait before enabling a 769 Specifies the time, in milliseconds, to wait before enabling a
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 153232ed4b3f..70de039dad2e 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1356,7 +1356,8 @@ static int bond_do_alb_xmit(struct sk_buff *skb, struct bonding *bond,
1356 if (!tx_slave) { 1356 if (!tx_slave) {
1357 /* unbalanced or unassigned, send through primary */ 1357 /* unbalanced or unassigned, send through primary */
1358 tx_slave = rcu_dereference(bond->curr_active_slave); 1358 tx_slave = rcu_dereference(bond->curr_active_slave);
1359 bond_info->unbalanced_load += skb->len; 1359 if (bond->params.tlb_dynamic_lb)
1360 bond_info->unbalanced_load += skb->len;
1360 } 1361 }
1361 1362
1362 if (tx_slave && SLAVE_IS_OK(tx_slave)) { 1363 if (tx_slave && SLAVE_IS_OK(tx_slave)) {
@@ -1369,7 +1370,7 @@ static int bond_do_alb_xmit(struct sk_buff *skb, struct bonding *bond,
1369 goto out; 1370 goto out;
1370 } 1371 }
1371 1372
1372 if (tx_slave) { 1373 if (tx_slave && bond->params.tlb_dynamic_lb) {
1373 _lock_tx_hashtbl(bond); 1374 _lock_tx_hashtbl(bond);
1374 __tlb_clear_slave(bond, tx_slave, 0); 1375 __tlb_clear_slave(bond, tx_slave, 0);
1375 _unlock_tx_hashtbl(bond); 1376 _unlock_tx_hashtbl(bond);
@@ -1399,11 +1400,21 @@ int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
1399 /* In case of IPX, it will falback to L2 hash */ 1400 /* In case of IPX, it will falback to L2 hash */
1400 case htons(ETH_P_IPV6): 1401 case htons(ETH_P_IPV6):
1401 hash_index = bond_xmit_hash(bond, skb); 1402 hash_index = bond_xmit_hash(bond, skb);
1402 tx_slave = tlb_choose_channel(bond, hash_index & 0xFF, skb->len); 1403 if (bond->params.tlb_dynamic_lb) {
1404 tx_slave = tlb_choose_channel(bond,
1405 hash_index & 0xFF,
1406 skb->len);
1407 } else {
1408 struct list_head *iter;
1409 int idx = hash_index % bond->slave_cnt;
1410
1411 bond_for_each_slave_rcu(bond, tx_slave, iter)
1412 if (--idx < 0)
1413 break;
1414 }
1403 break; 1415 break;
1404 } 1416 }
1405 } 1417 }
1406
1407 return bond_do_alb_xmit(skb, bond, tx_slave); 1418 return bond_do_alb_xmit(skb, bond, tx_slave);
1408} 1419}
1409 1420
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 1fd32a16cbc5..9d08e007d853 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3096,7 +3096,8 @@ static int bond_open(struct net_device *bond_dev)
3096 */ 3096 */
3097 if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) 3097 if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB)))
3098 return -ENOMEM; 3098 return -ENOMEM;
3099 queue_delayed_work(bond->wq, &bond->alb_work, 0); 3099 if (bond->params.tlb_dynamic_lb)
3100 queue_delayed_work(bond->wq, &bond->alb_work, 0);
3100 } 3101 }
3101 3102
3102 if (bond->params.miimon) /* link check interval, in milliseconds. */ 3103 if (bond->params.miimon) /* link check interval, in milliseconds. */
@@ -4304,6 +4305,7 @@ static int bond_check_params(struct bond_params *params)
4304 params->min_links = min_links; 4305 params->min_links = min_links;
4305 params->lp_interval = lp_interval; 4306 params->lp_interval = lp_interval;
4306 params->packets_per_slave = packets_per_slave; 4307 params->packets_per_slave = packets_per_slave;
4308 params->tlb_dynamic_lb = 1; /* Default value */
4307 if (packets_per_slave > 0) { 4309 if (packets_per_slave > 0) {
4308 params->reciprocal_packets_per_slave = 4310 params->reciprocal_packets_per_slave =
4309 reciprocal_value(packets_per_slave); 4311 reciprocal_value(packets_per_slave);
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index dc3893841752..9fba7a1e6d51 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -70,6 +70,8 @@ static int bond_option_mode_set(struct bonding *bond,
70 const struct bond_opt_value *newval); 70 const struct bond_opt_value *newval);
71static int bond_option_slaves_set(struct bonding *bond, 71static int bond_option_slaves_set(struct bonding *bond,
72 const struct bond_opt_value *newval); 72 const struct bond_opt_value *newval);
73static int bond_option_tlb_dynamic_lb_set(struct bonding *bond,
74 const struct bond_opt_value *newval);
73 75
74 76
75static const struct bond_opt_value bond_mode_tbl[] = { 77static const struct bond_opt_value bond_mode_tbl[] = {
@@ -179,6 +181,12 @@ static const struct bond_opt_value bond_lp_interval_tbl[] = {
179 { NULL, -1, 0}, 181 { NULL, -1, 0},
180}; 182};
181 183
184static const struct bond_opt_value bond_tlb_dynamic_lb_tbl[] = {
185 { "off", 0, 0},
186 { "on", 1, BOND_VALFLAG_DEFAULT},
187 { NULL, -1, 0}
188};
189
182static const struct bond_option bond_opts[] = { 190static const struct bond_option bond_opts[] = {
183 [BOND_OPT_MODE] = { 191 [BOND_OPT_MODE] = {
184 .id = BOND_OPT_MODE, 192 .id = BOND_OPT_MODE,
@@ -364,6 +372,15 @@ static const struct bond_option bond_opts[] = {
364 .flags = BOND_OPTFLAG_RAWVAL, 372 .flags = BOND_OPTFLAG_RAWVAL,
365 .set = bond_option_slaves_set 373 .set = bond_option_slaves_set
366 }, 374 },
375 [BOND_OPT_TLB_DYNAMIC_LB] = {
376 .id = BOND_OPT_TLB_DYNAMIC_LB,
377 .name = "dynamic_lb",
378 .desc = "Enable dynamic flow shuffling",
379 .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_TLB)),
380 .values = bond_tlb_dynamic_lb_tbl,
381 .flags = BOND_OPTFLAG_IFDOWN,
382 .set = bond_option_tlb_dynamic_lb_set,
383 },
367 { } 384 { }
368}; 385};
369 386
@@ -1337,3 +1354,13 @@ err_no_cmd:
1337 ret = -EPERM; 1354 ret = -EPERM;
1338 goto out; 1355 goto out;
1339} 1356}
1357
1358static int bond_option_tlb_dynamic_lb_set(struct bonding *bond,
1359 const struct bond_opt_value *newval)
1360{
1361 pr_info("%s: Setting dynamic-lb to %s (%llu)\n",
1362 bond->dev->name, newval->string, newval->value);
1363 bond->params.tlb_dynamic_lb = newval->value;
1364
1365 return 0;
1366}
diff --git a/drivers/net/bonding/bond_options.h b/drivers/net/bonding/bond_options.h
index 12be9e1bfb0c..c1860f06145a 100644
--- a/drivers/net/bonding/bond_options.h
+++ b/drivers/net/bonding/bond_options.h
@@ -62,6 +62,7 @@ enum {
62 BOND_OPT_RESEND_IGMP, 62 BOND_OPT_RESEND_IGMP,
63 BOND_OPT_LP_INTERVAL, 63 BOND_OPT_LP_INTERVAL,
64 BOND_OPT_SLAVES, 64 BOND_OPT_SLAVES,
65 BOND_OPT_TLB_DYNAMIC_LB,
65 BOND_OPT_LAST 66 BOND_OPT_LAST
66}; 67};
67 68
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 0e8b268da0a0..431892f1a4ce 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1039,6 +1039,34 @@ static ssize_t bonding_store_lp_interval(struct device *d,
1039static DEVICE_ATTR(lp_interval, S_IRUGO | S_IWUSR, 1039static DEVICE_ATTR(lp_interval, S_IRUGO | S_IWUSR,
1040 bonding_show_lp_interval, bonding_store_lp_interval); 1040 bonding_show_lp_interval, bonding_store_lp_interval);
1041 1041
1042static ssize_t bonding_show_tlb_dynamic_lb(struct device *d,
1043 struct device_attribute *attr,
1044 char *buf)
1045{
1046 struct bonding *bond = to_bond(d);
1047 return sprintf(buf, "%d\n", bond->params.tlb_dynamic_lb);
1048}
1049
1050static ssize_t bonding_store_tlb_dynamic_lb(struct device *d,
1051 struct device_attribute *attr,
1052 const char *buf,
1053 size_t count)
1054{
1055 struct bonding *bond = to_bond(d);
1056 int ret;
1057
1058 ret = bond_opt_tryset_rtnl(bond, BOND_OPT_TLB_DYNAMIC_LB,
1059 (char *)buf);
1060 if (!ret)
1061 ret = count;
1062
1063 return ret;
1064}
1065
1066static DEVICE_ATTR(tlb_dynamic_lb, S_IRUGO | S_IWUSR,
1067 bonding_show_tlb_dynamic_lb,
1068 bonding_store_tlb_dynamic_lb);
1069
1042static ssize_t bonding_show_packets_per_slave(struct device *d, 1070static ssize_t bonding_show_packets_per_slave(struct device *d,
1043 struct device_attribute *attr, 1071 struct device_attribute *attr,
1044 char *buf) 1072 char *buf)
@@ -1099,6 +1127,7 @@ static struct attribute *per_bond_attrs[] = {
1099 &dev_attr_min_links.attr, 1127 &dev_attr_min_links.attr,
1100 &dev_attr_lp_interval.attr, 1128 &dev_attr_lp_interval.attr,
1101 &dev_attr_packets_per_slave.attr, 1129 &dev_attr_packets_per_slave.attr,
1130 &dev_attr_tlb_dynamic_lb.attr,
1102 NULL, 1131 NULL,
1103}; 1132};
1104 1133
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index c0948ca26389..c1c7c2f12ac4 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -174,6 +174,7 @@ struct bond_params {
174 int resend_igmp; 174 int resend_igmp;
175 int lp_interval; 175 int lp_interval;
176 int packets_per_slave; 176 int packets_per_slave;
177 int tlb_dynamic_lb;
177 struct reciprocal_value reciprocal_packets_per_slave; 178 struct reciprocal_value reciprocal_packets_per_slave;
178}; 179};
179 180