aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bonding/bond_main.c21
-rw-r--r--drivers/net/bonding/bond_netlink.c4
-rw-r--r--drivers/net/bonding/bond_options.c53
-rw-r--r--drivers/net/bonding/bond_options.h3
-rw-r--r--drivers/net/bonding/bond_sysfs.c27
-rw-r--r--drivers/net/bonding/bonding.h2
6 files changed, 48 insertions, 62 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f100bd958b88..7a04f0f8449e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -214,17 +214,6 @@ const struct bond_parm_tbl bond_lacp_tbl[] = {
214{ NULL, -1}, 214{ NULL, -1},
215}; 215};
216 216
217const struct bond_parm_tbl bond_mode_tbl[] = {
218{ "balance-rr", BOND_MODE_ROUNDROBIN},
219{ "active-backup", BOND_MODE_ACTIVEBACKUP},
220{ "balance-xor", BOND_MODE_XOR},
221{ "broadcast", BOND_MODE_BROADCAST},
222{ "802.3ad", BOND_MODE_8023AD},
223{ "balance-tlb", BOND_MODE_TLB},
224{ "balance-alb", BOND_MODE_ALB},
225{ NULL, -1},
226};
227
228const struct bond_parm_tbl xmit_hashtype_tbl[] = { 217const struct bond_parm_tbl xmit_hashtype_tbl[] = {
229{ "layer2", BOND_XMIT_POLICY_LAYER2}, 218{ "layer2", BOND_XMIT_POLICY_LAYER2},
230{ "layer3+4", BOND_XMIT_POLICY_LAYER34}, 219{ "layer3+4", BOND_XMIT_POLICY_LAYER34},
@@ -4028,18 +4017,20 @@ int bond_parse_parm(const char *buf, const struct bond_parm_tbl *tbl)
4028static int bond_check_params(struct bond_params *params) 4017static int bond_check_params(struct bond_params *params)
4029{ 4018{
4030 int arp_validate_value, fail_over_mac_value, primary_reselect_value, i; 4019 int arp_validate_value, fail_over_mac_value, primary_reselect_value, i;
4020 struct bond_opt_value newval, *valptr;
4031 int arp_all_targets_value; 4021 int arp_all_targets_value;
4032 4022
4033 /* 4023 /*
4034 * Convert string parameters. 4024 * Convert string parameters.
4035 */ 4025 */
4036 if (mode) { 4026 if (mode) {
4037 bond_mode = bond_parse_parm(mode, bond_mode_tbl); 4027 bond_opt_initstr(&newval, mode);
4038 if (bond_mode == -1) { 4028 valptr = bond_opt_parse(bond_opt_get(BOND_OPT_MODE), &newval);
4039 pr_err("Error: Invalid bonding mode \"%s\"\n", 4029 if (!valptr) {
4040 mode == NULL ? "NULL" : mode); 4030 pr_err("Error: Invalid bonding mode \"%s\"\n", mode);
4041 return -EINVAL; 4031 return -EINVAL;
4042 } 4032 }
4033 bond_mode = valptr->value;
4043 } 4034 }
4044 4035
4045 if (xmit_hash_policy) { 4036 if (xmit_hash_policy) {
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index e8526552790c..db3f672a5e2a 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -98,6 +98,7 @@ static int bond_changelink(struct net_device *bond_dev,
98 struct nlattr *tb[], struct nlattr *data[]) 98 struct nlattr *tb[], struct nlattr *data[])
99{ 99{
100 struct bonding *bond = netdev_priv(bond_dev); 100 struct bonding *bond = netdev_priv(bond_dev);
101 struct bond_opt_value newval;
101 int miimon = 0; 102 int miimon = 0;
102 int err; 103 int err;
103 104
@@ -107,7 +108,8 @@ static int bond_changelink(struct net_device *bond_dev,
107 if (data[IFLA_BOND_MODE]) { 108 if (data[IFLA_BOND_MODE]) {
108 int mode = nla_get_u8(data[IFLA_BOND_MODE]); 109 int mode = nla_get_u8(data[IFLA_BOND_MODE]);
109 110
110 err = bond_option_mode_set(bond, mode); 111 bond_opt_initval(&newval, mode);
112 err = __bond_opt_set(bond, BOND_OPT_MODE, &newval);
111 if (err) 113 if (err)
112 return err; 114 return err;
113 } 115 }
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 3ad140bfed1a..5696b2fb5cb4 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -19,7 +19,26 @@
19#include <linux/ctype.h> 19#include <linux/ctype.h>
20#include "bonding.h" 20#include "bonding.h"
21 21
22static struct bond_opt_value bond_mode_tbl[] = {
23 { "balance-rr", BOND_MODE_ROUNDROBIN, BOND_VALFLAG_DEFAULT},
24 { "active-backup", BOND_MODE_ACTIVEBACKUP, 0},
25 { "balance-xor", BOND_MODE_XOR, 0},
26 { "broadcast", BOND_MODE_BROADCAST, 0},
27 { "802.3ad", BOND_MODE_8023AD, 0},
28 { "balance-tlb", BOND_MODE_TLB, 0},
29 { "balance-alb", BOND_MODE_ALB, 0},
30 { NULL, -1, 0},
31};
32
22static struct bond_option bond_opts[] = { 33static struct bond_option bond_opts[] = {
34 [BOND_OPT_MODE] = {
35 .id = BOND_OPT_MODE,
36 .name = "mode",
37 .desc = "bond device mode",
38 .flags = BOND_OPTFLAG_NOSLAVES | BOND_OPTFLAG_IFDOWN,
39 .values = bond_mode_tbl,
40 .set = bond_option_mode_set
41 },
23 { } 42 { }
24}; 43};
25 44
@@ -160,12 +179,15 @@ static int bond_opt_check_deps(struct bonding *bond,
160static void bond_opt_dep_print(struct bonding *bond, 179static void bond_opt_dep_print(struct bonding *bond,
161 const struct bond_option *opt) 180 const struct bond_option *opt)
162{ 181{
182 struct bond_opt_value *modeval;
163 struct bond_params *params; 183 struct bond_params *params;
164 184
165 params = &bond->params; 185 params = &bond->params;
186 modeval = bond_opt_get_val(BOND_OPT_MODE, params->mode);
166 if (test_bit(params->mode, &opt->unsuppmodes)) 187 if (test_bit(params->mode, &opt->unsuppmodes))
167 pr_err("%s: option %s: mode dependency failed\n", 188 pr_err("%s: option %s: mode dependency failed, not supported in mode %s(%llu)\n",
168 bond->dev->name, opt->name); 189 bond->dev->name, opt->name,
190 modeval->string, modeval->value);
169} 191}
170 192
171static void bond_opt_error_interpret(struct bonding *bond, 193static void bond_opt_error_interpret(struct bonding *bond,
@@ -290,29 +312,11 @@ struct bond_option *bond_opt_get(unsigned int option)
290 return &bond_opts[option]; 312 return &bond_opts[option];
291} 313}
292 314
293int bond_option_mode_set(struct bonding *bond, int mode) 315int bond_option_mode_set(struct bonding *bond, struct bond_opt_value *newval)
294{ 316{
295 if (bond_parm_tbl_lookup(mode, bond_mode_tbl) < 0) { 317 if (BOND_NO_USES_ARP(newval->value) && bond->params.arp_interval) {
296 pr_err("%s: Ignoring invalid mode value %d.\n",
297 bond->dev->name, mode);
298 return -EINVAL;
299 }
300
301 if (bond->dev->flags & IFF_UP) {
302 pr_err("%s: unable to update mode because interface is up.\n",
303 bond->dev->name);
304 return -EPERM;
305 }
306
307 if (bond_has_slaves(bond)) {
308 pr_err("%s: unable to update mode because bond has slaves.\n",
309 bond->dev->name);
310 return -EPERM;
311 }
312
313 if (BOND_NO_USES_ARP(mode) && bond->params.arp_interval) {
314 pr_info("%s: %s mode is incompatible with arp monitoring, start mii monitoring\n", 318 pr_info("%s: %s mode is incompatible with arp monitoring, start mii monitoring\n",
315 bond->dev->name, bond_mode_tbl[mode].modename); 319 bond->dev->name, newval->string);
316 /* disable arp monitoring */ 320 /* disable arp monitoring */
317 bond->params.arp_interval = 0; 321 bond->params.arp_interval = 0;
318 /* set miimon to default value */ 322 /* set miimon to default value */
@@ -323,7 +327,8 @@ int bond_option_mode_set(struct bonding *bond, int mode)
323 327
324 /* don't cache arp_validate between modes */ 328 /* don't cache arp_validate between modes */
325 bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; 329 bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
326 bond->params.mode = mode; 330 bond->params.mode = newval->value;
331
327 return 0; 332 return 0;
328} 333}
329 334
diff --git a/drivers/net/bonding/bond_options.h b/drivers/net/bonding/bond_options.h
index e20f2ebaf5c3..11e6c0697aed 100644
--- a/drivers/net/bonding/bond_options.h
+++ b/drivers/net/bonding/bond_options.h
@@ -38,6 +38,7 @@ enum {
38 38
39/* Option IDs, their bit positions correspond to their IDs */ 39/* Option IDs, their bit positions correspond to their IDs */
40enum { 40enum {
41 BOND_OPT_MODE,
41 BOND_OPT_LAST 42 BOND_OPT_LAST
42}; 43};
43 44
@@ -97,4 +98,6 @@ static inline void __bond_opt_init(struct bond_opt_value *optval,
97} 98}
98#define bond_opt_initval(optval, value) __bond_opt_init(optval, NULL, value) 99#define bond_opt_initval(optval, value) __bond_opt_init(optval, NULL, value)
99#define bond_opt_initstr(optval, str) __bond_opt_init(optval, str, ULLONG_MAX) 100#define bond_opt_initstr(optval, str) __bond_opt_init(optval, str, ULLONG_MAX)
101
102int bond_option_mode_set(struct bonding *bond, struct bond_opt_value *newval);
100#endif /* _BOND_OPTIONS_H */ 103#endif /* _BOND_OPTIONS_H */
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index c083e9a66ece..3e537e7b66a5 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -263,37 +263,24 @@ static ssize_t bonding_show_mode(struct device *d,
263 struct device_attribute *attr, char *buf) 263 struct device_attribute *attr, char *buf)
264{ 264{
265 struct bonding *bond = to_bond(d); 265 struct bonding *bond = to_bond(d);
266 struct bond_opt_value *val;
266 267
267 return sprintf(buf, "%s %d\n", 268 val = bond_opt_get_val(BOND_OPT_MODE, bond->params.mode);
268 bond_mode_tbl[bond->params.mode].modename, 269
269 bond->params.mode); 270 return sprintf(buf, "%s %d\n", val->string, bond->params.mode);
270} 271}
271 272
272static ssize_t bonding_store_mode(struct device *d, 273static ssize_t bonding_store_mode(struct device *d,
273 struct device_attribute *attr, 274 struct device_attribute *attr,
274 const char *buf, size_t count) 275 const char *buf, size_t count)
275{ 276{
276 int new_value, ret;
277 struct bonding *bond = to_bond(d); 277 struct bonding *bond = to_bond(d);
278 int ret;
278 279
279 new_value = bond_parse_parm(buf, bond_mode_tbl); 280 ret = bond_opt_tryset_rtnl(bond, BOND_OPT_MODE, (char *)buf);
280 if (new_value < 0) { 281 if (!ret)
281 pr_err("%s: Ignoring invalid mode value %.*s.\n",
282 bond->dev->name, (int)strlen(buf) - 1, buf);
283 return -EINVAL;
284 }
285 if (!rtnl_trylock())
286 return restart_syscall();
287
288 ret = bond_option_mode_set(bond, new_value);
289 if (!ret) {
290 pr_info("%s: setting mode to %s (%d).\n",
291 bond->dev->name, bond_mode_tbl[new_value].modename,
292 new_value);
293 ret = count; 282 ret = count;
294 }
295 283
296 rtnl_unlock();
297 return ret; 284 return ret;
298} 285}
299static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, 286static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 8c3c94aa04d7..f8e2cab90020 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -452,7 +452,6 @@ void bond_setup(struct net_device *bond_dev);
452unsigned int bond_get_num_tx_queues(void); 452unsigned int bond_get_num_tx_queues(void);
453int bond_netlink_init(void); 453int bond_netlink_init(void);
454void bond_netlink_fini(void); 454void bond_netlink_fini(void);
455int bond_option_mode_set(struct bonding *bond, int mode);
456int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev); 455int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev);
457int bond_option_miimon_set(struct bonding *bond, int miimon); 456int bond_option_miimon_set(struct bonding *bond, int miimon);
458int bond_option_updelay_set(struct bonding *bond, int updelay); 457int bond_option_updelay_set(struct bonding *bond, int updelay);
@@ -563,7 +562,6 @@ static inline int bond_get_targets_ip(__be32 *targets, __be32 ip)
563/* exported from bond_main.c */ 562/* exported from bond_main.c */
564extern int bond_net_id; 563extern int bond_net_id;
565extern const struct bond_parm_tbl bond_lacp_tbl[]; 564extern const struct bond_parm_tbl bond_lacp_tbl[];
566extern const struct bond_parm_tbl bond_mode_tbl[];
567extern const struct bond_parm_tbl xmit_hashtype_tbl[]; 565extern const struct bond_parm_tbl xmit_hashtype_tbl[];
568extern const struct bond_parm_tbl arp_validate_tbl[]; 566extern const struct bond_parm_tbl arp_validate_tbl[];
569extern const struct bond_parm_tbl arp_all_targets_tbl[]; 567extern const struct bond_parm_tbl arp_all_targets_tbl[];