diff options
author | Jiri Pirko <jpirko@redhat.com> | 2009-09-24 23:28:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-07 04:07:39 -0400 |
commit | a549952ad323d68daf5b50bf716db895479af84c (patch) | |
tree | c819e8c33701696115c3d60b12ca95a0cd792291 /drivers/net/bonding/bond_main.c | |
parent | 2d37a186cedc51502dbee71c16ae0fbd9114d62c (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/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 66 |
1 files changed, 61 insertions, 5 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; | |||
94 | static int use_carrier = 1; | 94 | static int use_carrier = 1; |
95 | static char *mode; | 95 | static char *mode; |
96 | static char *primary; | 96 | static char *primary; |
97 | static char *primary_reselect; | ||
97 | static char *lacp_rate; | 98 | static char *lacp_rate; |
98 | static char *ad_select; | 99 | static char *ad_select; |
99 | static char *xmit_hash_policy; | 100 | static 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"); |
127 | module_param(primary, charp, 0); | 128 | module_param(primary, charp, 0); |
128 | MODULE_PARM_DESC(primary, "Primary network device to use"); | 129 | MODULE_PARM_DESC(primary, "Primary network device to use"); |
130 | module_param(primary_reselect, charp, 0); | ||
131 | MODULE_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"); | ||
129 | module_param(lacp_rate, charp, 0); | 138 | module_param(lacp_rate, charp, 0); |
130 | MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner " | 139 | MODULE_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 | ||
212 | const 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 | |||
203 | struct bond_parm_tbl ad_select_tbl[] = { | 219 | struct 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 | ||
1089 | static 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 | ||
4647 | static int bond_check_params(struct bond_params *params) | 4688 | static 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) { |