aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2009-09-24 23:28:09 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-07 04:07:39 -0400
commita549952ad323d68daf5b50bf716db895479af84c (patch)
treec819e8c33701696115c3d60b12ca95a0cd792291 /drivers/net/bonding
parent2d37a186cedc51502dbee71c16ae0fbd9114d62c (diff)
bonding: introduce primary_reselect option
In some cases there is not desirable to switch back to primary interface when it's link recovers and rather stay with currently active one. We need to avoid packetloss as much as we can in some cases. This is solved by introducing primary_reselect option. Note that enslaved primary slave is set as current active no matter what. Patch modified by Jay Vosburgh as follows: fixed bug in action after change of option setting via sysfs, revised the documentation update, and bumped the bonding version number. Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_main.c66
-rw-r--r--drivers/net/bonding/bond_sysfs.c53
-rw-r--r--drivers/net/bonding/bonding.h11
3 files changed, 123 insertions, 7 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 69c5b15e22da..19d57d537ec1 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -94,6 +94,7 @@ static int downdelay;
94static int use_carrier = 1; 94static int use_carrier = 1;
95static char *mode; 95static char *mode;
96static char *primary; 96static char *primary;
97static char *primary_reselect;
97static char *lacp_rate; 98static char *lacp_rate;
98static char *ad_select; 99static char *ad_select;
99static char *xmit_hash_policy; 100static char *xmit_hash_policy;
@@ -126,6 +127,14 @@ MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, "
126 "6 for balance-alb"); 127 "6 for balance-alb");
127module_param(primary, charp, 0); 128module_param(primary, charp, 0);
128MODULE_PARM_DESC(primary, "Primary network device to use"); 129MODULE_PARM_DESC(primary, "Primary network device to use");
130module_param(primary_reselect, charp, 0);
131MODULE_PARM_DESC(primary_reselect, "Reselect primary slave "
132 "once it comes up; "
133 "0 for always (default), "
134 "1 for only if speed of primary is "
135 "better, "
136 "2 for only on active slave "
137 "failure");
129module_param(lacp_rate, charp, 0); 138module_param(lacp_rate, charp, 0);
130MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner " 139MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
131 "(slow/fast)"); 140 "(slow/fast)");
@@ -200,6 +209,13 @@ const struct bond_parm_tbl fail_over_mac_tbl[] = {
200{ NULL, -1}, 209{ NULL, -1},
201}; 210};
202 211
212const struct bond_parm_tbl pri_reselect_tbl[] = {
213{ "always", BOND_PRI_RESELECT_ALWAYS},
214{ "better", BOND_PRI_RESELECT_BETTER},
215{ "failure", BOND_PRI_RESELECT_FAILURE},
216{ NULL, -1},
217};
218
203struct bond_parm_tbl ad_select_tbl[] = { 219struct bond_parm_tbl ad_select_tbl[] = {
204{ "stable", BOND_AD_STABLE}, 220{ "stable", BOND_AD_STABLE},
205{ "bandwidth", BOND_AD_BANDWIDTH}, 221{ "bandwidth", BOND_AD_BANDWIDTH},
@@ -1070,6 +1086,25 @@ out:
1070 1086
1071} 1087}
1072 1088
1089static bool bond_should_change_active(struct bonding *bond)
1090{
1091 struct slave *prim = bond->primary_slave;
1092 struct slave *curr = bond->curr_active_slave;
1093
1094 if (!prim || !curr || curr->link != BOND_LINK_UP)
1095 return true;
1096 if (bond->force_primary) {
1097 bond->force_primary = false;
1098 return true;
1099 }
1100 if (bond->params.primary_reselect == BOND_PRI_RESELECT_BETTER &&
1101 (prim->speed < curr->speed ||
1102 (prim->speed == curr->speed && prim->duplex <= curr->duplex)))
1103 return false;
1104 if (bond->params.primary_reselect == BOND_PRI_RESELECT_FAILURE)
1105 return false;
1106 return true;
1107}
1073 1108
1074/** 1109/**
1075 * find_best_interface - select the best available slave to be the active one 1110 * find_best_interface - select the best available slave to be the active one
@@ -1094,7 +1129,8 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
1094 } 1129 }
1095 1130
1096 if ((bond->primary_slave) && 1131 if ((bond->primary_slave) &&
1097 bond->primary_slave->link == BOND_LINK_UP) { 1132 bond->primary_slave->link == BOND_LINK_UP &&
1133 bond_should_change_active(bond)) {
1098 new_active = bond->primary_slave; 1134 new_active = bond->primary_slave;
1099 } 1135 }
1100 1136
@@ -1678,8 +1714,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
1678 1714
1679 if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { 1715 if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
1680 /* if there is a primary slave, remember it */ 1716 /* if there is a primary slave, remember it */
1681 if (strcmp(bond->params.primary, new_slave->dev->name) == 0) 1717 if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
1682 bond->primary_slave = new_slave; 1718 bond->primary_slave = new_slave;
1719 bond->force_primary = true;
1720 }
1683 } 1721 }
1684 1722
1685 write_lock_bh(&bond->curr_slave_lock); 1723 write_lock_bh(&bond->curr_slave_lock);
@@ -3201,11 +3239,14 @@ static void bond_info_show_master(struct seq_file *seq)
3201 } 3239 }
3202 3240
3203 if (USES_PRIMARY(bond->params.mode)) { 3241 if (USES_PRIMARY(bond->params.mode)) {
3204 seq_printf(seq, "Primary Slave: %s\n", 3242 seq_printf(seq, "Primary Slave: %s",
3205 (bond->primary_slave) ? 3243 (bond->primary_slave) ?
3206 bond->primary_slave->dev->name : "None"); 3244 bond->primary_slave->dev->name : "None");
3245 if (bond->primary_slave)
3246 seq_printf(seq, " (primary_reselect %s)",
3247 pri_reselect_tbl[bond->params.primary_reselect].modename);
3207 3248
3208 seq_printf(seq, "Currently Active Slave: %s\n", 3249 seq_printf(seq, "\nCurrently Active Slave: %s\n",
3209 (curr) ? curr->dev->name : "None"); 3250 (curr) ? curr->dev->name : "None");
3210 } 3251 }
3211 3252
@@ -4646,7 +4687,7 @@ int bond_parse_parm(const char *buf, const struct bond_parm_tbl *tbl)
4646 4687
4647static int bond_check_params(struct bond_params *params) 4688static int bond_check_params(struct bond_params *params)
4648{ 4689{
4649 int arp_validate_value, fail_over_mac_value; 4690 int arp_validate_value, fail_over_mac_value, primary_reselect_value;
4650 4691
4651 /* 4692 /*
4652 * Convert string parameters. 4693 * Convert string parameters.
@@ -4945,6 +4986,20 @@ static int bond_check_params(struct bond_params *params)
4945 primary = NULL; 4986 primary = NULL;
4946 } 4987 }
4947 4988
4989 if (primary && primary_reselect) {
4990 primary_reselect_value = bond_parse_parm(primary_reselect,
4991 pri_reselect_tbl);
4992 if (primary_reselect_value == -1) {
4993 pr_err(DRV_NAME
4994 ": Error: Invalid primary_reselect \"%s\"\n",
4995 primary_reselect ==
4996 NULL ? "NULL" : primary_reselect);
4997 return -EINVAL;
4998 }
4999 } else {
5000 primary_reselect_value = BOND_PRI_RESELECT_ALWAYS;
5001 }
5002
4948 if (fail_over_mac) { 5003 if (fail_over_mac) {
4949 fail_over_mac_value = bond_parse_parm(fail_over_mac, 5004 fail_over_mac_value = bond_parse_parm(fail_over_mac,
4950 fail_over_mac_tbl); 5005 fail_over_mac_tbl);
@@ -4976,6 +5031,7 @@ static int bond_check_params(struct bond_params *params)
4976 params->use_carrier = use_carrier; 5031 params->use_carrier = use_carrier;
4977 params->lacp_fast = lacp_fast; 5032 params->lacp_fast = lacp_fast;
4978 params->primary[0] = 0; 5033 params->primary[0] = 0;
5034 params->primary_reselect = primary_reselect_value;
4979 params->fail_over_mac = fail_over_mac_value; 5035 params->fail_over_mac = fail_over_mac_value;
4980 5036
4981 if (primary) { 5037 if (primary) {
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index ff449de6f3c0..dca7d82f7b97 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1213,6 +1213,58 @@ static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR,
1213 bonding_show_primary, bonding_store_primary); 1213 bonding_show_primary, bonding_store_primary);
1214 1214
1215/* 1215/*
1216 * Show and set the primary_reselect flag.
1217 */
1218static ssize_t bonding_show_primary_reselect(struct device *d,
1219 struct device_attribute *attr,
1220 char *buf)
1221{
1222 struct bonding *bond = to_bond(d);
1223
1224 return sprintf(buf, "%s %d\n",
1225 pri_reselect_tbl[bond->params.primary_reselect].modename,
1226 bond->params.primary_reselect);
1227}
1228
1229static ssize_t bonding_store_primary_reselect(struct device *d,
1230 struct device_attribute *attr,
1231 const char *buf, size_t count)
1232{
1233 int new_value, ret = count;
1234 struct bonding *bond = to_bond(d);
1235
1236 if (!rtnl_trylock())
1237 return restart_syscall();
1238
1239 new_value = bond_parse_parm(buf, pri_reselect_tbl);
1240 if (new_value < 0) {
1241 pr_err(DRV_NAME
1242 ": %s: Ignoring invalid primary_reselect value %.*s.\n",
1243 bond->dev->name,
1244 (int) strlen(buf) - 1, buf);
1245 ret = -EINVAL;
1246 goto out;
1247 }
1248
1249 bond->params.primary_reselect = new_value;
1250 pr_info(DRV_NAME ": %s: setting primary_reselect to %s (%d).\n",
1251 bond->dev->name, pri_reselect_tbl[new_value].modename,
1252 new_value);
1253
1254 read_lock(&bond->lock);
1255 write_lock_bh(&bond->curr_slave_lock);
1256 bond_select_active_slave(bond);
1257 write_unlock_bh(&bond->curr_slave_lock);
1258 read_unlock(&bond->lock);
1259out:
1260 rtnl_unlock();
1261 return ret;
1262}
1263static DEVICE_ATTR(primary_reselect, S_IRUGO | S_IWUSR,
1264 bonding_show_primary_reselect,
1265 bonding_store_primary_reselect);
1266
1267/*
1216 * Show and set the use_carrier flag. 1268 * Show and set the use_carrier flag.
1217 */ 1269 */
1218static ssize_t bonding_show_carrier(struct device *d, 1270static ssize_t bonding_show_carrier(struct device *d,
@@ -1501,6 +1553,7 @@ static struct attribute *per_bond_attrs[] = {
1501 &dev_attr_num_unsol_na.attr, 1553 &dev_attr_num_unsol_na.attr,
1502 &dev_attr_miimon.attr, 1554 &dev_attr_miimon.attr,
1503 &dev_attr_primary.attr, 1555 &dev_attr_primary.attr,
1556 &dev_attr_primary_reselect.attr,
1504 &dev_attr_use_carrier.attr, 1557 &dev_attr_use_carrier.attr,
1505 &dev_attr_active_slave.attr, 1558 &dev_attr_active_slave.attr,
1506 &dev_attr_mii_status.attr, 1559 &dev_attr_mii_status.attr,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 68247714466f..9c03c2ee074d 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -23,8 +23,8 @@
23#include "bond_3ad.h" 23#include "bond_3ad.h"
24#include "bond_alb.h" 24#include "bond_alb.h"
25 25
26#define DRV_VERSION "3.5.0" 26#define DRV_VERSION "3.6.0"
27#define DRV_RELDATE "November 4, 2008" 27#define DRV_RELDATE "September 26, 2009"
28#define DRV_NAME "bonding" 28#define DRV_NAME "bonding"
29#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" 29#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
30 30
@@ -131,6 +131,7 @@ struct bond_params {
131 int lacp_fast; 131 int lacp_fast;
132 int ad_select; 132 int ad_select;
133 char primary[IFNAMSIZ]; 133 char primary[IFNAMSIZ];
134 int primary_reselect;
134 __be32 arp_targets[BOND_MAX_ARP_TARGETS]; 135 __be32 arp_targets[BOND_MAX_ARP_TARGETS];
135}; 136};
136 137
@@ -190,6 +191,7 @@ struct bonding {
190 struct slave *curr_active_slave; 191 struct slave *curr_active_slave;
191 struct slave *current_arp_slave; 192 struct slave *current_arp_slave;
192 struct slave *primary_slave; 193 struct slave *primary_slave;
194 bool force_primary;
193 s32 slave_cnt; /* never change this value outside the attach/detach wrappers */ 195 s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
194 rwlock_t lock; 196 rwlock_t lock;
195 rwlock_t curr_slave_lock; 197 rwlock_t curr_slave_lock;
@@ -258,6 +260,10 @@ static inline bool bond_is_lb(const struct bonding *bond)
258 || bond->params.mode == BOND_MODE_ALB; 260 || bond->params.mode == BOND_MODE_ALB;
259} 261}
260 262
263#define BOND_PRI_RESELECT_ALWAYS 0
264#define BOND_PRI_RESELECT_BETTER 1
265#define BOND_PRI_RESELECT_FAILURE 2
266
261#define BOND_FOM_NONE 0 267#define BOND_FOM_NONE 0
262#define BOND_FOM_ACTIVE 1 268#define BOND_FOM_ACTIVE 1
263#define BOND_FOM_FOLLOW 2 269#define BOND_FOM_FOLLOW 2
@@ -348,6 +354,7 @@ extern const struct bond_parm_tbl bond_mode_tbl[];
348extern const struct bond_parm_tbl xmit_hashtype_tbl[]; 354extern const struct bond_parm_tbl xmit_hashtype_tbl[];
349extern const struct bond_parm_tbl arp_validate_tbl[]; 355extern const struct bond_parm_tbl arp_validate_tbl[];
350extern const struct bond_parm_tbl fail_over_mac_tbl[]; 356extern const struct bond_parm_tbl fail_over_mac_tbl[];
357extern const struct bond_parm_tbl pri_reselect_tbl[];
351extern struct bond_parm_tbl ad_select_tbl[]; 358extern struct bond_parm_tbl ad_select_tbl[];
352 359
353#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 360#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)