blob: a4cbaf78ad1c41be4a641ccfdc38108d2afe2f38 [file] [log] [blame]
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001/*
2 * Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
20 *
Mitch Williamsb76cdba2005-11-09 10:36:41 -080021 */
Joe Perchesa4aee5c2009-12-13 20:06:07 -080022
23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
Mitch Williamsb76cdba2005-11-09 10:36:41 -080025#include <linux/kernel.h>
26#include <linux/module.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080027#include <linux/device.h>
Alexey Dobriyand43c36d2009-10-07 17:09:06 +040028#include <linux/sched.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080029#include <linux/sysdev.h>
30#include <linux/fs.h>
31#include <linux/types.h>
32#include <linux/string.h>
33#include <linux/netdevice.h>
34#include <linux/inetdevice.h>
35#include <linux/in.h>
36#include <linux/sysfs.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080037#include <linux/ctype.h>
38#include <linux/inet.h>
39#include <linux/rtnetlink.h>
Stephen Hemminger5c5129b2009-06-12 19:02:51 +000040#include <linux/etherdevice.h>
Eric W. Biederman881d9662007-09-17 11:56:21 -070041#include <net/net_namespace.h>
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000042#include <net/netns/generic.h>
43#include <linux/nsproxy.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080044
Mitch Williamsb76cdba2005-11-09 10:36:41 -080045#include "bonding.h"
Holger Eitzenberger5a03cdb2008-12-09 23:09:22 -080046
Stephen Hemminger3d632c32009-06-12 19:02:48 +000047#define to_dev(obj) container_of(obj, struct device, kobj)
Wang Chen454d7c92008-11-12 23:37:49 -080048#define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd))))
Mitch Williamsb76cdba2005-11-09 10:36:41 -080049
Mitch Williamsb76cdba2005-11-09 10:36:41 -080050/*
51 * "show" function for the bond_masters attribute.
52 * The class parameter is ignored.
53 */
Andi Kleen28812fe2010-01-05 12:48:07 +010054static ssize_t bonding_show_bonds(struct class *cls,
55 struct class_attribute *attr,
56 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -080057{
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000058 struct net *net = current->nsproxy->net_ns;
59 struct bond_net *bn = net_generic(net, bond_net_id);
Mitch Williamsb76cdba2005-11-09 10:36:41 -080060 int res = 0;
61 struct bonding *bond;
62
Stephen Hemminger7e083842009-06-12 19:02:46 +000063 rtnl_lock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -080064
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000065 list_for_each_entry(bond, &bn->dev_list, bond_list) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -080066 if (res > (PAGE_SIZE - IFNAMSIZ)) {
67 /* not enough space for another interface name */
68 if ((PAGE_SIZE - res) > 10)
69 res = PAGE_SIZE - 10;
Wagner Ferencb8843662007-12-06 23:40:30 -080070 res += sprintf(buf + res, "++more++ ");
Mitch Williamsb76cdba2005-11-09 10:36:41 -080071 break;
72 }
Wagner Ferencb8843662007-12-06 23:40:30 -080073 res += sprintf(buf + res, "%s ", bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -080074 }
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -080075 if (res)
76 buf[res-1] = '\n'; /* eat the leftover space */
Stephen Hemminger7e083842009-06-12 19:02:46 +000077
78 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -080079 return res;
80}
81
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000082static struct net_device *bond_get_by_name(struct net *net, const char *ifname)
Stephen Hemminger373500d2009-06-12 19:02:50 +000083{
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000084 struct bond_net *bn = net_generic(net, bond_net_id);
Stephen Hemminger373500d2009-06-12 19:02:50 +000085 struct bonding *bond;
86
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000087 list_for_each_entry(bond, &bn->dev_list, bond_list) {
Stephen Hemminger373500d2009-06-12 19:02:50 +000088 if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
89 return bond->dev;
90 }
91 return NULL;
92}
93
Mitch Williamsb76cdba2005-11-09 10:36:41 -080094/*
95 * "store" function for the bond_masters attribute. This is what
96 * creates and deletes entire bonds.
97 *
98 * The class parameter is ignored.
99 *
100 */
101
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000102static ssize_t bonding_store_bonds(struct class *cls,
Andi Kleen28812fe2010-01-05 12:48:07 +0100103 struct class_attribute *attr,
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000104 const char *buffer, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800105{
Eric W. Biedermanec87fd32009-10-29 14:18:26 +0000106 struct net *net = current->nsproxy->net_ns;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800107 char command[IFNAMSIZ + 1] = {0, };
108 char *ifname;
Jay Vosburgh027ea042008-01-17 16:25:02 -0800109 int rv, res = count;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800110
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800111 sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
112 ifname = command + 1;
113 if ((strlen(command) <= 1) ||
114 !dev_valid_name(ifname))
115 goto err_no_cmd;
116
117 if (command[0] == '+') {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800118 pr_info("%s is being created...\n", ifname);
Eric W. Biedermanec87fd32009-10-29 14:18:26 +0000119 rv = bond_create(net, ifname);
Jay Vosburgh027ea042008-01-17 16:25:02 -0800120 if (rv) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800121 pr_info("Bond creation failed.\n");
Jay Vosburgh027ea042008-01-17 16:25:02 -0800122 res = rv;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800123 }
Stephen Hemminger373500d2009-06-12 19:02:50 +0000124 } else if (command[0] == '-') {
125 struct net_device *bond_dev;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800126
Jay Vosburgh027ea042008-01-17 16:25:02 -0800127 rtnl_lock();
Eric W. Biedermanec87fd32009-10-29 14:18:26 +0000128 bond_dev = bond_get_by_name(net, ifname);
Stephen Hemminger373500d2009-06-12 19:02:50 +0000129 if (bond_dev) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800130 pr_info("%s is being deleted...\n", ifname);
Stephen Hemminger373500d2009-06-12 19:02:50 +0000131 unregister_netdevice(bond_dev);
132 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800133 pr_err("unable to delete non-existent %s\n", ifname);
Stephen Hemminger373500d2009-06-12 19:02:50 +0000134 res = -ENODEV;
135 }
136 rtnl_unlock();
137 } else
138 goto err_no_cmd;
Jay Vosburgh027ea042008-01-17 16:25:02 -0800139
Stephen Hemminger373500d2009-06-12 19:02:50 +0000140 /* Always return either count or an error. If you return 0, you'll
141 * get called forever, which is bad.
142 */
143 return res;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800144
145err_no_cmd:
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800146 pr_err("no command found in bonding_masters. Use +ifname or -ifname.\n");
Jay Vosburghc4ebc662008-05-02 17:49:38 -0700147 return -EPERM;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800148}
Stephen Hemminger373500d2009-06-12 19:02:50 +0000149
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800150/* class attribute for bond_masters file. This ends up in /sys/class/net */
151static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
152 bonding_show_bonds, bonding_store_bonds);
153
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000154int bond_create_slave_symlinks(struct net_device *master,
155 struct net_device *slave)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800156{
157 char linkname[IFNAMSIZ+7];
158 int ret = 0;
159
160 /* first, create a link from the slave back to the master */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700161 ret = sysfs_create_link(&(slave->dev.kobj), &(master->dev.kobj),
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800162 "master");
163 if (ret)
164 return ret;
165 /* next, create a link from the master to the slave */
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000166 sprintf(linkname, "slave_%s", slave->name);
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700167 ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800168 linkname);
169 return ret;
170
171}
172
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000173void bond_destroy_slave_symlinks(struct net_device *master,
174 struct net_device *slave)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800175{
176 char linkname[IFNAMSIZ+7];
177
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700178 sysfs_remove_link(&(slave->dev.kobj), "master");
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000179 sprintf(linkname, "slave_%s", slave->name);
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700180 sysfs_remove_link(&(master->dev.kobj), linkname);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800181}
182
183
184/*
185 * Show the slaves in the current bond.
186 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700187static ssize_t bonding_show_slaves(struct device *d,
188 struct device_attribute *attr, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800189{
190 struct slave *slave;
191 int i, res = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700192 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800193
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700194 read_lock(&bond->lock);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800195 bond_for_each_slave(bond, slave, i) {
196 if (res > (PAGE_SIZE - IFNAMSIZ)) {
197 /* not enough space for another interface name */
198 if ((PAGE_SIZE - res) > 10)
199 res = PAGE_SIZE - 10;
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800200 res += sprintf(buf + res, "++more++ ");
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800201 break;
202 }
203 res += sprintf(buf + res, "%s ", slave->dev->name);
204 }
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700205 read_unlock(&bond->lock);
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -0800206 if (res)
207 buf[res-1] = '\n'; /* eat the leftover space */
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800208 return res;
209}
210
211/*
212 * Set the slaves in the current bond. The bond interface must be
213 * up for this to succeed.
Jiri Pirkof9f35452010-05-18 05:46:39 +0000214 * This is supposed to be only thin wrapper for bond_enslave and bond_release.
215 * All hard work should be done there.
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800216 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700217static ssize_t bonding_store_slaves(struct device *d,
218 struct device_attribute *attr,
219 const char *buffer, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800220{
221 char command[IFNAMSIZ + 1] = { 0, };
222 char *ifname;
Jiri Pirkof9f35452010-05-18 05:46:39 +0000223 int res, ret = count;
224 struct net_device *dev;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700225 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800226
227 /* Quick sanity check -- is the bond interface up? */
228 if (!(bond->dev->flags & IFF_UP)) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800229 pr_warning("%s: doing slave updates when interface is down.\n",
230 bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800231 }
232
Eric W. Biederman496a60c2009-05-13 17:02:50 +0000233 if (!rtnl_trylock())
234 return restart_syscall();
Jay Vosburgh027ea042008-01-17 16:25:02 -0800235
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800236 sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
237 ifname = command + 1;
238 if ((strlen(command) <= 1) ||
239 !dev_valid_name(ifname))
240 goto err_no_cmd;
241
Jiri Pirkof9f35452010-05-18 05:46:39 +0000242 dev = __dev_get_by_name(dev_net(bond->dev), ifname);
243 if (!dev) {
244 pr_info("%s: Interface %s does not exist!\n",
245 bond->dev->name, ifname);
246 ret = -ENODEV;
247 goto out;
248 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800249
Jiri Pirkof9f35452010-05-18 05:46:39 +0000250 switch (command[0]) {
251 case '+':
252 pr_info("%s: Adding slave %s.\n", bond->dev->name, dev->name);
Stephen Hemminger373500d2009-06-12 19:02:50 +0000253
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800254 /* If this is the first slave, then we need to set
255 the master's hardware address to be the same as the
256 slave's. */
Stephen Hemminger5c5129b2009-06-12 19:02:51 +0000257 if (is_zero_ether_addr(bond->dev->dev_addr))
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800258 memcpy(bond->dev->dev_addr, dev->dev_addr,
259 dev->addr_len);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800260
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800261 res = bond_enslave(bond->dev, dev);
Jiri Pirkof9f35452010-05-18 05:46:39 +0000262 break;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000263
Jiri Pirkof9f35452010-05-18 05:46:39 +0000264 case '-':
265 pr_info("%s: Removing slave %s.\n", bond->dev->name, dev->name);
266 res = bond_release(bond->dev, dev);
267 break;
268
269 default:
270 goto err_no_cmd;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800271 }
272
Jiri Pirkof9f35452010-05-18 05:46:39 +0000273 if (res)
274 ret = res;
275 goto out;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800276
277err_no_cmd:
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800278 pr_err("no command found in slaves file for bond %s. Use +ifname or -ifname.\n",
279 bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800280 ret = -EPERM;
281
282out:
Jay Vosburgh027ea042008-01-17 16:25:02 -0800283 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800284 return ret;
285}
286
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000287static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves,
288 bonding_store_slaves);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800289
290/*
291 * Show and set the bonding mode. The bond interface must be down to
292 * change the mode.
293 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700294static ssize_t bonding_show_mode(struct device *d,
295 struct device_attribute *attr, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800296{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700297 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800298
299 return sprintf(buf, "%s %d\n",
300 bond_mode_tbl[bond->params.mode].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800301 bond->params.mode);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800302}
303
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700304static ssize_t bonding_store_mode(struct device *d,
305 struct device_attribute *attr,
306 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800307{
308 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700309 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800310
311 if (bond->dev->flags & IFF_UP) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800312 pr_err("unable to update mode of %s because interface is up.\n",
313 bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800314 ret = -EPERM;
315 goto out;
316 }
317
Jay Vosburghece95f72008-01-17 16:25:01 -0800318 new_value = bond_parse_parm(buf, bond_mode_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800319 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800320 pr_err("%s: Ignoring invalid mode value %.*s.\n",
321 bond->dev->name, (int)strlen(buf) - 1, buf);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800322 ret = -EINVAL;
323 goto out;
324 } else {
Jay Vosburgh8f903c72006-02-21 16:36:44 -0800325 if (bond->params.mode == BOND_MODE_8023AD)
326 bond_unset_master_3ad_flags(bond);
327
328 if (bond->params.mode == BOND_MODE_ALB)
329 bond_unset_master_alb_flags(bond);
330
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800331 bond->params.mode = new_value;
332 bond_set_mode_ops(bond, bond->params.mode);
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800333 pr_info("%s: setting mode to %s (%d).\n",
334 bond->dev->name, bond_mode_tbl[new_value].modename,
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000335 new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800336 }
337out:
338 return ret;
339}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000340static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
341 bonding_show_mode, bonding_store_mode);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800342
343/*
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000344 * Show and set the bonding transmit hash method.
345 * The bond interface must be down to change the xmit hash policy.
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800346 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700347static ssize_t bonding_show_xmit_hash(struct device *d,
348 struct device_attribute *attr,
349 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800350{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700351 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800352
Wagner Ferenc8e4b9322007-12-06 23:40:32 -0800353 return sprintf(buf, "%s %d\n",
354 xmit_hashtype_tbl[bond->params.xmit_policy].modename,
355 bond->params.xmit_policy);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800356}
357
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700358static ssize_t bonding_store_xmit_hash(struct device *d,
359 struct device_attribute *attr,
360 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800361{
362 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700363 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800364
365 if (bond->dev->flags & IFF_UP) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800366 pr_err("%s: Interface is up. Unable to update xmit policy.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800367 bond->dev->name);
368 ret = -EPERM;
369 goto out;
370 }
371
Jay Vosburghece95f72008-01-17 16:25:01 -0800372 new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800373 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800374 pr_err("%s: Ignoring invalid xmit hash policy value %.*s.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800375 bond->dev->name,
376 (int)strlen(buf) - 1, buf);
377 ret = -EINVAL;
378 goto out;
379 } else {
380 bond->params.xmit_policy = new_value;
381 bond_set_mode_ops(bond, bond->params.mode);
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800382 pr_info("%s: setting xmit hash policy to %s (%d).\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000383 bond->dev->name,
384 xmit_hashtype_tbl[new_value].modename, new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800385 }
386out:
387 return ret;
388}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000389static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR,
390 bonding_show_xmit_hash, bonding_store_xmit_hash);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800391
392/*
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700393 * Show and set arp_validate.
394 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700395static ssize_t bonding_show_arp_validate(struct device *d,
396 struct device_attribute *attr,
397 char *buf)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700398{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700399 struct bonding *bond = to_bond(d);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700400
401 return sprintf(buf, "%s %d\n",
402 arp_validate_tbl[bond->params.arp_validate].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800403 bond->params.arp_validate);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700404}
405
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700406static ssize_t bonding_store_arp_validate(struct device *d,
407 struct device_attribute *attr,
408 const char *buf, size_t count)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700409{
410 int new_value;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700411 struct bonding *bond = to_bond(d);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700412
Jay Vosburghece95f72008-01-17 16:25:01 -0800413 new_value = bond_parse_parm(buf, arp_validate_tbl);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700414 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800415 pr_err("%s: Ignoring invalid arp_validate value %s\n",
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700416 bond->dev->name, buf);
417 return -EINVAL;
418 }
419 if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800420 pr_err("%s: arp_validate only supported in active-backup mode.\n",
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700421 bond->dev->name);
422 return -EINVAL;
423 }
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800424 pr_info("%s: setting arp_validate to %s (%d).\n",
425 bond->dev->name, arp_validate_tbl[new_value].modename,
426 new_value);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700427
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000428 if (!bond->params.arp_validate && new_value)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700429 bond_register_arp(bond);
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000430 else if (bond->params.arp_validate && !new_value)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700431 bond_unregister_arp(bond);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700432
433 bond->params.arp_validate = new_value;
434
435 return count;
436}
437
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000438static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate,
439 bonding_store_arp_validate);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700440
441/*
Jay Vosburghdd957c52007-10-09 19:57:24 -0700442 * Show and store fail_over_mac. User only allowed to change the
443 * value when there are no slaves.
444 */
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000445static ssize_t bonding_show_fail_over_mac(struct device *d,
446 struct device_attribute *attr,
447 char *buf)
Jay Vosburghdd957c52007-10-09 19:57:24 -0700448{
449 struct bonding *bond = to_bond(d);
450
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700451 return sprintf(buf, "%s %d\n",
452 fail_over_mac_tbl[bond->params.fail_over_mac].modename,
453 bond->params.fail_over_mac);
Jay Vosburghdd957c52007-10-09 19:57:24 -0700454}
455
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000456static ssize_t bonding_store_fail_over_mac(struct device *d,
457 struct device_attribute *attr,
458 const char *buf, size_t count)
Jay Vosburghdd957c52007-10-09 19:57:24 -0700459{
460 int new_value;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700461 struct bonding *bond = to_bond(d);
462
463 if (bond->slave_cnt != 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800464 pr_err("%s: Can't alter fail_over_mac with slaves in bond.\n",
Jay Vosburghdd957c52007-10-09 19:57:24 -0700465 bond->dev->name);
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700466 return -EPERM;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700467 }
468
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700469 new_value = bond_parse_parm(buf, fail_over_mac_tbl);
470 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800471 pr_err("%s: Ignoring invalid fail_over_mac value %s.\n",
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700472 bond->dev->name, buf);
473 return -EINVAL;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700474 }
475
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700476 bond->params.fail_over_mac = new_value;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800477 pr_info("%s: Setting fail_over_mac to %s (%d).\n",
478 bond->dev->name, fail_over_mac_tbl[new_value].modename,
479 new_value);
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700480
481 return count;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700482}
483
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000484static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR,
485 bonding_show_fail_over_mac, bonding_store_fail_over_mac);
Jay Vosburghdd957c52007-10-09 19:57:24 -0700486
487/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800488 * Show and set the arp timer interval. There are two tricky bits
489 * here. First, if ARP monitoring is activated, then we must disable
490 * MII monitoring. Second, if the ARP timer isn't running, we must
491 * start it.
492 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700493static ssize_t bonding_show_arp_interval(struct device *d,
494 struct device_attribute *attr,
495 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800496{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700497 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800498
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800499 return sprintf(buf, "%d\n", bond->params.arp_interval);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800500}
501
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700502static ssize_t bonding_store_arp_interval(struct device *d,
503 struct device_attribute *attr,
504 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800505{
506 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700507 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800508
509 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800510 pr_err("%s: no arp_interval value specified.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800511 bond->dev->name);
512 ret = -EINVAL;
513 goto out;
514 }
515 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800516 pr_err("%s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800517 bond->dev->name, new_value, INT_MAX);
518 ret = -EINVAL;
519 goto out;
520 }
521
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800522 pr_info("%s: Setting ARP monitoring interval to %d.\n",
523 bond->dev->name, new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800524 bond->params.arp_interval = new_value;
Jay Vosburgh6cf3f412008-11-03 18:16:50 -0800525 if (bond->params.arp_interval)
526 bond->dev->priv_flags |= IFF_MASTER_ARPMON;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800527 if (bond->params.miimon) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800528 pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
529 bond->dev->name, bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800530 bond->params.miimon = 0;
Jay Vosburgh1b76b312007-10-17 17:37:45 -0700531 if (delayed_work_pending(&bond->mii_work)) {
532 cancel_delayed_work(&bond->mii_work);
533 flush_workqueue(bond->wq);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800534 }
535 }
536 if (!bond->params.arp_targets[0]) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800537 pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
538 bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800539 }
540 if (bond->dev->flags & IFF_UP) {
541 /* If the interface is up, we may need to fire off
542 * the ARP timer. If the interface is down, the
543 * timer will get fired off when the open function
544 * is called.
545 */
Jay Vosburgh1b76b312007-10-17 17:37:45 -0700546 if (!delayed_work_pending(&bond->arp_work)) {
547 if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
548 INIT_DELAYED_WORK(&bond->arp_work,
549 bond_activebackup_arp_mon);
550 else
551 INIT_DELAYED_WORK(&bond->arp_work,
552 bond_loadbalance_arp_mon);
553
554 queue_delayed_work(bond->wq, &bond->arp_work, 0);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800555 }
556 }
557
558out:
559 return ret;
560}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000561static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR,
562 bonding_show_arp_interval, bonding_store_arp_interval);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800563
564/*
565 * Show and set the arp targets.
566 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700567static ssize_t bonding_show_arp_targets(struct device *d,
568 struct device_attribute *attr,
569 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800570{
571 int i, res = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700572 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800573
574 for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
575 if (bond->params.arp_targets[i])
Harvey Harrison63779432008-10-31 00:56:00 -0700576 res += sprintf(buf + res, "%pI4 ",
577 &bond->params.arp_targets[i]);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800578 }
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -0800579 if (res)
580 buf[res-1] = '\n'; /* eat the leftover space */
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800581 return res;
582}
583
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700584static ssize_t bonding_store_arp_targets(struct device *d,
585 struct device_attribute *attr,
586 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800587{
Al Virod3bb52b2007-08-22 20:06:58 -0400588 __be32 newtarget;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800589 int i = 0, done = 0, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700590 struct bonding *bond = to_bond(d);
Al Virod3bb52b2007-08-22 20:06:58 -0400591 __be32 *targets;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800592
593 targets = bond->params.arp_targets;
594 newtarget = in_aton(buf + 1);
595 /* look for adds */
596 if (buf[0] == '+') {
Al Virod3bb52b2007-08-22 20:06:58 -0400597 if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800598 pr_err("%s: invalid ARP target %pI4 specified for addition\n",
Harvey Harrison63779432008-10-31 00:56:00 -0700599 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800600 ret = -EINVAL;
601 goto out;
602 }
603 /* look for an empty slot to put the target in, and check for dupes */
Brian Haley5a31bec2009-04-13 00:11:30 -0700604 for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800605 if (targets[i] == newtarget) { /* duplicate */
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800606 pr_err("%s: ARP target %pI4 is already present\n",
Harvey Harrison63779432008-10-31 00:56:00 -0700607 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800608 ret = -EINVAL;
609 goto out;
610 }
Brian Haley5a31bec2009-04-13 00:11:30 -0700611 if (targets[i] == 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800612 pr_info("%s: adding ARP target %pI4.\n",
613 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800614 done = 1;
615 targets[i] = newtarget;
616 }
617 }
618 if (!done) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800619 pr_err("%s: ARP target table is full!\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800620 bond->dev->name);
621 ret = -EINVAL;
622 goto out;
623 }
624
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000625 } else if (buf[0] == '-') {
Al Virod3bb52b2007-08-22 20:06:58 -0400626 if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800627 pr_err("%s: invalid ARP target %pI4 specified for removal\n",
Harvey Harrison63779432008-10-31 00:56:00 -0700628 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800629 ret = -EINVAL;
630 goto out;
631 }
632
Brian Haley5a31bec2009-04-13 00:11:30 -0700633 for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800634 if (targets[i] == newtarget) {
Brian Haley5a31bec2009-04-13 00:11:30 -0700635 int j;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800636 pr_info("%s: removing ARP target %pI4.\n",
637 bond->dev->name, &newtarget);
Brian Haley5a31bec2009-04-13 00:11:30 -0700638 for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j+1]; j++)
639 targets[j] = targets[j+1];
640
641 targets[j] = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800642 done = 1;
643 }
644 }
645 if (!done) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800646 pr_info("%s: unable to remove nonexistent ARP target %pI4.\n",
647 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800648 ret = -EINVAL;
649 goto out;
650 }
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000651 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800652 pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
653 bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800654 ret = -EPERM;
655 goto out;
656 }
657
658out:
659 return ret;
660}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700661static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800662
663/*
664 * Show and set the up and down delays. These must be multiples of the
665 * MII monitoring value, and are stored internally as the multiplier.
666 * Thus, we must translate to MS for the real world.
667 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700668static ssize_t bonding_show_downdelay(struct device *d,
669 struct device_attribute *attr,
670 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800671{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700672 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800673
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800674 return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800675}
676
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700677static ssize_t bonding_store_downdelay(struct device *d,
678 struct device_attribute *attr,
679 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800680{
681 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700682 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800683
684 if (!(bond->params.miimon)) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800685 pr_err("%s: Unable to set down delay as MII monitoring is disabled\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800686 bond->dev->name);
687 ret = -EPERM;
688 goto out;
689 }
690
691 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800692 pr_err("%s: no down delay value specified.\n", bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800693 ret = -EINVAL;
694 goto out;
695 }
696 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800697 pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800698 bond->dev->name, new_value, 1, INT_MAX);
699 ret = -EINVAL;
700 goto out;
701 } else {
702 if ((new_value % bond->params.miimon) != 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800703 pr_warning("%s: Warning: down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n",
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +0000704 bond->dev->name, new_value,
705 bond->params.miimon,
706 (new_value / bond->params.miimon) *
707 bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800708 }
709 bond->params.downdelay = new_value / bond->params.miimon;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800710 pr_info("%s: Setting down delay to %d.\n",
711 bond->dev->name,
712 bond->params.downdelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800713
714 }
715
716out:
717 return ret;
718}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000719static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR,
720 bonding_show_downdelay, bonding_store_downdelay);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800721
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700722static ssize_t bonding_show_updelay(struct device *d,
723 struct device_attribute *attr,
724 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800725{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700726 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800727
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800728 return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800729
730}
731
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700732static ssize_t bonding_store_updelay(struct device *d,
733 struct device_attribute *attr,
734 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800735{
736 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700737 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800738
739 if (!(bond->params.miimon)) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800740 pr_err("%s: Unable to set up delay as MII monitoring is disabled\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800741 bond->dev->name);
742 ret = -EPERM;
743 goto out;
744 }
745
746 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800747 pr_err("%s: no up delay value specified.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800748 bond->dev->name);
749 ret = -EINVAL;
750 goto out;
751 }
752 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800753 pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800754 bond->dev->name, new_value, 1, INT_MAX);
755 ret = -EINVAL;
756 goto out;
757 } else {
758 if ((new_value % bond->params.miimon) != 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800759 pr_warning("%s: Warning: up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +0000760 bond->dev->name, new_value,
761 bond->params.miimon,
762 (new_value / bond->params.miimon) *
763 bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800764 }
765 bond->params.updelay = new_value / bond->params.miimon;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800766 pr_info("%s: Setting up delay to %d.\n",
767 bond->dev->name,
768 bond->params.updelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800769 }
770
771out:
772 return ret;
773}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000774static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR,
775 bonding_show_updelay, bonding_store_updelay);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800776
777/*
778 * Show and set the LACP interval. Interface must be down, and the mode
779 * must be set to 802.3ad mode.
780 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700781static ssize_t bonding_show_lacp(struct device *d,
782 struct device_attribute *attr,
783 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800784{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700785 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800786
787 return sprintf(buf, "%s %d\n",
788 bond_lacp_tbl[bond->params.lacp_fast].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800789 bond->params.lacp_fast);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800790}
791
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700792static ssize_t bonding_store_lacp(struct device *d,
793 struct device_attribute *attr,
794 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800795{
796 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700797 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800798
799 if (bond->dev->flags & IFF_UP) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800800 pr_err("%s: Unable to update LACP rate because interface is up.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800801 bond->dev->name);
802 ret = -EPERM;
803 goto out;
804 }
805
806 if (bond->params.mode != BOND_MODE_8023AD) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800807 pr_err("%s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800808 bond->dev->name);
809 ret = -EPERM;
810 goto out;
811 }
812
Jay Vosburghece95f72008-01-17 16:25:01 -0800813 new_value = bond_parse_parm(buf, bond_lacp_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800814
815 if ((new_value == 1) || (new_value == 0)) {
816 bond->params.lacp_fast = new_value;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800817 pr_info("%s: Setting LACP rate to %s (%d).\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000818 bond->dev->name, bond_lacp_tbl[new_value].modename,
819 new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800820 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800821 pr_err("%s: Ignoring invalid LACP rate value %.*s.\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000822 bond->dev->name, (int)strlen(buf) - 1, buf);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800823 ret = -EINVAL;
824 }
825out:
826 return ret;
827}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000828static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR,
829 bonding_show_lacp, bonding_store_lacp);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800830
Jay Vosburghfd989c82008-11-04 17:51:16 -0800831static ssize_t bonding_show_ad_select(struct device *d,
832 struct device_attribute *attr,
833 char *buf)
834{
835 struct bonding *bond = to_bond(d);
836
837 return sprintf(buf, "%s %d\n",
838 ad_select_tbl[bond->params.ad_select].modename,
839 bond->params.ad_select);
840}
841
842
843static ssize_t bonding_store_ad_select(struct device *d,
844 struct device_attribute *attr,
845 const char *buf, size_t count)
846{
847 int new_value, ret = count;
848 struct bonding *bond = to_bond(d);
849
850 if (bond->dev->flags & IFF_UP) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800851 pr_err("%s: Unable to update ad_select because interface is up.\n",
852 bond->dev->name);
Jay Vosburghfd989c82008-11-04 17:51:16 -0800853 ret = -EPERM;
854 goto out;
855 }
856
857 new_value = bond_parse_parm(buf, ad_select_tbl);
858
859 if (new_value != -1) {
860 bond->params.ad_select = new_value;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800861 pr_info("%s: Setting ad_select to %s (%d).\n",
862 bond->dev->name, ad_select_tbl[new_value].modename,
863 new_value);
Jay Vosburghfd989c82008-11-04 17:51:16 -0800864 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800865 pr_err("%s: Ignoring invalid ad_select value %.*s.\n",
Jay Vosburghfd989c82008-11-04 17:51:16 -0800866 bond->dev->name, (int)strlen(buf) - 1, buf);
867 ret = -EINVAL;
868 }
869out:
870 return ret;
871}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000872static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR,
873 bonding_show_ad_select, bonding_store_ad_select);
Jay Vosburghfd989c82008-11-04 17:51:16 -0800874
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800875/*
Moni Shoua7893b242008-05-17 21:10:12 -0700876 * Show and set the number of grat ARP to send after a failover event.
877 */
878static ssize_t bonding_show_n_grat_arp(struct device *d,
879 struct device_attribute *attr,
880 char *buf)
881{
882 struct bonding *bond = to_bond(d);
883
884 return sprintf(buf, "%d\n", bond->params.num_grat_arp);
885}
886
887static ssize_t bonding_store_n_grat_arp(struct device *d,
888 struct device_attribute *attr,
889 const char *buf, size_t count)
890{
891 int new_value, ret = count;
892 struct bonding *bond = to_bond(d);
893
894 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800895 pr_err("%s: no num_grat_arp value specified.\n",
Moni Shoua7893b242008-05-17 21:10:12 -0700896 bond->dev->name);
897 ret = -EINVAL;
898 goto out;
899 }
900 if (new_value < 0 || new_value > 255) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800901 pr_err("%s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n",
Moni Shoua7893b242008-05-17 21:10:12 -0700902 bond->dev->name, new_value);
903 ret = -EINVAL;
904 goto out;
905 } else {
906 bond->params.num_grat_arp = new_value;
907 }
908out:
909 return ret;
910}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000911static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR,
912 bonding_show_n_grat_arp, bonding_store_n_grat_arp);
Brian Haley305d5522008-11-04 17:51:14 -0800913
914/*
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000915 * Show and set the number of unsolicited NA's to send after a failover event.
Brian Haley305d5522008-11-04 17:51:14 -0800916 */
917static ssize_t bonding_show_n_unsol_na(struct device *d,
918 struct device_attribute *attr,
919 char *buf)
920{
921 struct bonding *bond = to_bond(d);
922
923 return sprintf(buf, "%d\n", bond->params.num_unsol_na);
924}
925
926static ssize_t bonding_store_n_unsol_na(struct device *d,
927 struct device_attribute *attr,
928 const char *buf, size_t count)
929{
930 int new_value, ret = count;
931 struct bonding *bond = to_bond(d);
932
933 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800934 pr_err("%s: no num_unsol_na value specified.\n",
Brian Haley305d5522008-11-04 17:51:14 -0800935 bond->dev->name);
936 ret = -EINVAL;
937 goto out;
938 }
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000939
Brian Haley305d5522008-11-04 17:51:14 -0800940 if (new_value < 0 || new_value > 255) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800941 pr_err("%s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
Brian Haley305d5522008-11-04 17:51:14 -0800942 bond->dev->name, new_value);
943 ret = -EINVAL;
944 goto out;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000945 } else
Brian Haley305d5522008-11-04 17:51:14 -0800946 bond->params.num_unsol_na = new_value;
Brian Haley305d5522008-11-04 17:51:14 -0800947out:
948 return ret;
949}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000950static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR,
951 bonding_show_n_unsol_na, bonding_store_n_unsol_na);
Brian Haley305d5522008-11-04 17:51:14 -0800952
Moni Shoua7893b242008-05-17 21:10:12 -0700953/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800954 * Show and set the MII monitor interval. There are two tricky bits
955 * here. First, if MII monitoring is activated, then we must disable
956 * ARP monitoring. Second, if the timer isn't running, we must
957 * start it.
958 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700959static ssize_t bonding_show_miimon(struct device *d,
960 struct device_attribute *attr,
961 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800962{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700963 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800964
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800965 return sprintf(buf, "%d\n", bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800966}
967
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700968static ssize_t bonding_store_miimon(struct device *d,
969 struct device_attribute *attr,
970 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800971{
972 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700973 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800974
975 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800976 pr_err("%s: no miimon value specified.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800977 bond->dev->name);
978 ret = -EINVAL;
979 goto out;
980 }
981 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800982 pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800983 bond->dev->name, new_value, 1, INT_MAX);
984 ret = -EINVAL;
985 goto out;
986 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800987 pr_info("%s: Setting MII monitoring interval to %d.\n",
988 bond->dev->name, new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800989 bond->params.miimon = new_value;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000990 if (bond->params.updelay)
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800991 pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
992 bond->dev->name,
993 bond->params.updelay * bond->params.miimon);
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000994 if (bond->params.downdelay)
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800995 pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
996 bond->dev->name,
997 bond->params.downdelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800998 if (bond->params.arp_interval) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800999 pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
1000 bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001001 bond->params.arp_interval = 0;
Jay Vosburgh6cf3f412008-11-03 18:16:50 -08001002 bond->dev->priv_flags &= ~IFF_MASTER_ARPMON;
Jay Vosburghf5b2b962006-09-22 21:54:53 -07001003 if (bond->params.arp_validate) {
1004 bond_unregister_arp(bond);
1005 bond->params.arp_validate =
1006 BOND_ARP_VALIDATE_NONE;
1007 }
Jay Vosburgh1b76b312007-10-17 17:37:45 -07001008 if (delayed_work_pending(&bond->arp_work)) {
1009 cancel_delayed_work(&bond->arp_work);
1010 flush_workqueue(bond->wq);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001011 }
1012 }
1013
1014 if (bond->dev->flags & IFF_UP) {
1015 /* If the interface is up, we may need to fire off
1016 * the MII timer. If the interface is down, the
1017 * timer will get fired off when the open function
1018 * is called.
1019 */
Jay Vosburgh1b76b312007-10-17 17:37:45 -07001020 if (!delayed_work_pending(&bond->mii_work)) {
1021 INIT_DELAYED_WORK(&bond->mii_work,
1022 bond_mii_monitor);
1023 queue_delayed_work(bond->wq,
1024 &bond->mii_work, 0);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001025 }
1026 }
1027 }
1028out:
1029 return ret;
1030}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001031static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR,
1032 bonding_show_miimon, bonding_store_miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001033
1034/*
1035 * Show and set the primary slave. The store function is much
1036 * simpler than bonding_store_slaves function because it only needs to
1037 * handle one interface name.
1038 * The bond must be a mode that supports a primary for this be
1039 * set.
1040 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001041static ssize_t bonding_show_primary(struct device *d,
1042 struct device_attribute *attr,
1043 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001044{
1045 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001046 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001047
1048 if (bond->primary_slave)
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001049 count = sprintf(buf, "%s\n", bond->primary_slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001050
1051 return count;
1052}
1053
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001054static ssize_t bonding_store_primary(struct device *d,
1055 struct device_attribute *attr,
1056 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001057{
1058 int i;
1059 struct slave *slave;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001060 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001061
Eric W. Biederman496a60c2009-05-13 17:02:50 +00001062 if (!rtnl_trylock())
1063 return restart_syscall();
Jay Vosburghe934dd72008-01-17 16:24:57 -08001064 read_lock(&bond->lock);
1065 write_lock_bh(&bond->curr_slave_lock);
1066
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001067 if (!USES_PRIMARY(bond->params.mode)) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001068 pr_info("%s: Unable to set primary slave; %s is in mode %d\n",
1069 bond->dev->name, bond->dev->name, bond->params.mode);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001070 } else {
1071 bond_for_each_slave(bond, slave, i) {
1072 if (strnicmp
1073 (slave->dev->name, buf,
1074 strlen(slave->dev->name)) == 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001075 pr_info("%s: Setting %s as primary slave.\n",
1076 bond->dev->name, slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001077 bond->primary_slave = slave;
Jiri Pirkoce501ca2009-09-18 02:13:22 +00001078 strcpy(bond->params.primary, slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001079 bond_select_active_slave(bond);
1080 goto out;
1081 }
1082 }
1083
1084 /* if we got here, then we didn't match the name of any slave */
1085
1086 if (strlen(buf) == 0 || buf[0] == '\n') {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001087 pr_info("%s: Setting primary slave to None.\n",
1088 bond->dev->name);
Luiz Fernando Capitulino3418db72006-02-01 00:54:34 -08001089 bond->primary_slave = NULL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001090 bond_select_active_slave(bond);
1091 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001092 pr_info("%s: Unable to set %.*s as primary slave as it is not a slave.\n",
1093 bond->dev->name, (int)strlen(buf) - 1, buf);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001094 }
1095 }
1096out:
Jay Vosburghe934dd72008-01-17 16:24:57 -08001097 write_unlock_bh(&bond->curr_slave_lock);
1098 read_unlock(&bond->lock);
Jay Vosburgh6603a6f2007-10-17 17:37:50 -07001099 rtnl_unlock();
1100
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001101 return count;
1102}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001103static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR,
1104 bonding_show_primary, bonding_store_primary);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001105
1106/*
Jiri Pirkoa5499522009-09-25 03:28:09 +00001107 * Show and set the primary_reselect flag.
1108 */
1109static ssize_t bonding_show_primary_reselect(struct device *d,
1110 struct device_attribute *attr,
1111 char *buf)
1112{
1113 struct bonding *bond = to_bond(d);
1114
1115 return sprintf(buf, "%s %d\n",
1116 pri_reselect_tbl[bond->params.primary_reselect].modename,
1117 bond->params.primary_reselect);
1118}
1119
1120static ssize_t bonding_store_primary_reselect(struct device *d,
1121 struct device_attribute *attr,
1122 const char *buf, size_t count)
1123{
1124 int new_value, ret = count;
1125 struct bonding *bond = to_bond(d);
1126
1127 if (!rtnl_trylock())
1128 return restart_syscall();
1129
1130 new_value = bond_parse_parm(buf, pri_reselect_tbl);
1131 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001132 pr_err("%s: Ignoring invalid primary_reselect value %.*s.\n",
Jiri Pirkoa5499522009-09-25 03:28:09 +00001133 bond->dev->name,
1134 (int) strlen(buf) - 1, buf);
1135 ret = -EINVAL;
1136 goto out;
1137 }
1138
1139 bond->params.primary_reselect = new_value;
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001140 pr_info("%s: setting primary_reselect to %s (%d).\n",
Jiri Pirkoa5499522009-09-25 03:28:09 +00001141 bond->dev->name, pri_reselect_tbl[new_value].modename,
1142 new_value);
1143
1144 read_lock(&bond->lock);
1145 write_lock_bh(&bond->curr_slave_lock);
1146 bond_select_active_slave(bond);
1147 write_unlock_bh(&bond->curr_slave_lock);
1148 read_unlock(&bond->lock);
1149out:
1150 rtnl_unlock();
1151 return ret;
1152}
1153static DEVICE_ATTR(primary_reselect, S_IRUGO | S_IWUSR,
1154 bonding_show_primary_reselect,
1155 bonding_store_primary_reselect);
1156
1157/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001158 * Show and set the use_carrier flag.
1159 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001160static ssize_t bonding_show_carrier(struct device *d,
1161 struct device_attribute *attr,
1162 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001163{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001164 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001165
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001166 return sprintf(buf, "%d\n", bond->params.use_carrier);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001167}
1168
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001169static ssize_t bonding_store_carrier(struct device *d,
1170 struct device_attribute *attr,
1171 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001172{
1173 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001174 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001175
1176
1177 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001178 pr_err("%s: no use_carrier value specified.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001179 bond->dev->name);
1180 ret = -EINVAL;
1181 goto out;
1182 }
1183 if ((new_value == 0) || (new_value == 1)) {
1184 bond->params.use_carrier = new_value;
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001185 pr_info("%s: Setting use_carrier to %d.\n",
1186 bond->dev->name, new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001187 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001188 pr_info("%s: Ignoring invalid use_carrier value %d.\n",
1189 bond->dev->name, new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001190 }
1191out:
1192 return count;
1193}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001194static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR,
1195 bonding_show_carrier, bonding_store_carrier);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001196
1197
1198/*
1199 * Show and set currently active_slave.
1200 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001201static ssize_t bonding_show_active_slave(struct device *d,
1202 struct device_attribute *attr,
1203 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001204{
1205 struct slave *curr;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001206 struct bonding *bond = to_bond(d);
Wagner Ferenc16cd0162007-12-06 23:40:29 -08001207 int count = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001208
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001209 read_lock(&bond->curr_slave_lock);
1210 curr = bond->curr_active_slave;
1211 read_unlock(&bond->curr_slave_lock);
1212
1213 if (USES_PRIMARY(bond->params.mode) && curr)
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001214 count = sprintf(buf, "%s\n", curr->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001215 return count;
1216}
1217
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001218static ssize_t bonding_store_active_slave(struct device *d,
1219 struct device_attribute *attr,
1220 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001221{
1222 int i;
1223 struct slave *slave;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001224 struct slave *old_active = NULL;
1225 struct slave *new_active = NULL;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001226 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001227
Eric W. Biederman496a60c2009-05-13 17:02:50 +00001228 if (!rtnl_trylock())
1229 return restart_syscall();
Jay Vosburghe934dd72008-01-17 16:24:57 -08001230 read_lock(&bond->lock);
1231 write_lock_bh(&bond->curr_slave_lock);
Jay Vosburgh1466a212007-11-06 13:33:28 -08001232
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001233 if (!USES_PRIMARY(bond->params.mode))
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001234 pr_info("%s: Unable to change active slave; %s is in mode %d\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001235 bond->dev->name, bond->dev->name, bond->params.mode);
1236 else {
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001237 bond_for_each_slave(bond, slave, i) {
1238 if (strnicmp
1239 (slave->dev->name, buf,
1240 strlen(slave->dev->name)) == 0) {
1241 old_active = bond->curr_active_slave;
1242 new_active = slave;
Jay Vosburgha50d8de2006-09-22 21:53:25 -07001243 if (new_active == old_active) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001244 /* do nothing */
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001245 pr_info("%s: %s is already the current active slave.\n",
1246 bond->dev->name,
1247 slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001248 goto out;
1249 }
1250 else {
1251 if ((new_active) &&
1252 (old_active) &&
1253 (new_active->link == BOND_LINK_UP) &&
1254 IS_UP(new_active->dev)) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001255 pr_info("%s: Setting %s as active slave.\n",
1256 bond->dev->name,
1257 slave->dev->name);
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +00001258 bond_change_active_slave(bond, new_active);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001259 }
1260 else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001261 pr_info("%s: Could not set %s as active slave; either %s is down or the link is down.\n",
1262 bond->dev->name,
1263 slave->dev->name,
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +00001264 slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001265 }
1266 goto out;
1267 }
1268 }
1269 }
1270
1271 /* if we got here, then we didn't match the name of any slave */
1272
1273 if (strlen(buf) == 0 || buf[0] == '\n') {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001274 pr_info("%s: Setting active slave to None.\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001275 bond->dev->name);
Luiz Fernando Capitulino3418db72006-02-01 00:54:34 -08001276 bond->primary_slave = NULL;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001277 bond_select_active_slave(bond);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001278 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001279 pr_info("%s: Unable to set %.*s as active slave as it is not a slave.\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001280 bond->dev->name, (int)strlen(buf) - 1, buf);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001281 }
1282 }
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001283 out:
Jay Vosburghe934dd72008-01-17 16:24:57 -08001284 write_unlock_bh(&bond->curr_slave_lock);
1285 read_unlock(&bond->lock);
Jay Vosburgh6603a6f2007-10-17 17:37:50 -07001286 rtnl_unlock();
1287
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001288 return count;
1289
1290}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001291static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR,
1292 bonding_show_active_slave, bonding_store_active_slave);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001293
1294
1295/*
1296 * Show link status of the bond interface.
1297 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001298static ssize_t bonding_show_mii_status(struct device *d,
1299 struct device_attribute *attr,
1300 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001301{
1302 struct slave *curr;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001303 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001304
1305 read_lock(&bond->curr_slave_lock);
1306 curr = bond->curr_active_slave;
1307 read_unlock(&bond->curr_slave_lock);
1308
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001309 return sprintf(buf, "%s\n", curr ? "up" : "down");
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001310}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001311static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001312
1313
1314/*
1315 * Show current 802.3ad aggregator ID.
1316 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001317static ssize_t bonding_show_ad_aggregator(struct device *d,
1318 struct device_attribute *attr,
1319 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001320{
1321 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001322 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001323
1324 if (bond->params.mode == BOND_MODE_8023AD) {
1325 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001326 count = sprintf(buf, "%d\n",
1327 (bond_3ad_get_active_agg_info(bond, &ad_info))
1328 ? 0 : ad_info.aggregator_id);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001329 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001330
1331 return count;
1332}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001333static DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001334
1335
1336/*
1337 * Show number of active 802.3ad ports.
1338 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001339static ssize_t bonding_show_ad_num_ports(struct device *d,
1340 struct device_attribute *attr,
1341 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001342{
1343 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001344 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001345
1346 if (bond->params.mode == BOND_MODE_8023AD) {
1347 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001348 count = sprintf(buf, "%d\n",
1349 (bond_3ad_get_active_agg_info(bond, &ad_info))
1350 ? 0 : ad_info.ports);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001351 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001352
1353 return count;
1354}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001355static DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001356
1357
1358/*
1359 * Show current 802.3ad actor key.
1360 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001361static ssize_t bonding_show_ad_actor_key(struct device *d,
1362 struct device_attribute *attr,
1363 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001364{
1365 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001366 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001367
1368 if (bond->params.mode == BOND_MODE_8023AD) {
1369 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001370 count = sprintf(buf, "%d\n",
1371 (bond_3ad_get_active_agg_info(bond, &ad_info))
1372 ? 0 : ad_info.actor_key);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001373 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001374
1375 return count;
1376}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001377static DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001378
1379
1380/*
1381 * Show current 802.3ad partner key.
1382 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001383static ssize_t bonding_show_ad_partner_key(struct device *d,
1384 struct device_attribute *attr,
1385 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001386{
1387 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001388 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001389
1390 if (bond->params.mode == BOND_MODE_8023AD) {
1391 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001392 count = sprintf(buf, "%d\n",
1393 (bond_3ad_get_active_agg_info(bond, &ad_info))
1394 ? 0 : ad_info.partner_key);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001395 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001396
1397 return count;
1398}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001399static DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001400
1401
1402/*
1403 * Show current 802.3ad partner mac.
1404 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001405static ssize_t bonding_show_ad_partner_mac(struct device *d,
1406 struct device_attribute *attr,
1407 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001408{
1409 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001410 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001411
1412 if (bond->params.mode == BOND_MODE_8023AD) {
1413 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001414 if (!bond_3ad_get_active_agg_info(bond, &ad_info))
Johannes Berge1749612008-10-27 15:59:26 -07001415 count = sprintf(buf, "%pM\n", ad_info.partner_system);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001416 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001417
1418 return count;
1419}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001420static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001421
1422
1423
1424static struct attribute *per_bond_attrs[] = {
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001425 &dev_attr_slaves.attr,
1426 &dev_attr_mode.attr,
Jay Vosburghdd957c52007-10-09 19:57:24 -07001427 &dev_attr_fail_over_mac.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001428 &dev_attr_arp_validate.attr,
1429 &dev_attr_arp_interval.attr,
1430 &dev_attr_arp_ip_target.attr,
1431 &dev_attr_downdelay.attr,
1432 &dev_attr_updelay.attr,
1433 &dev_attr_lacp_rate.attr,
Jay Vosburghfd989c82008-11-04 17:51:16 -08001434 &dev_attr_ad_select.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001435 &dev_attr_xmit_hash_policy.attr,
Moni Shoua7893b242008-05-17 21:10:12 -07001436 &dev_attr_num_grat_arp.attr,
Brian Haley305d5522008-11-04 17:51:14 -08001437 &dev_attr_num_unsol_na.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001438 &dev_attr_miimon.attr,
1439 &dev_attr_primary.attr,
Jiri Pirkoa5499522009-09-25 03:28:09 +00001440 &dev_attr_primary_reselect.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001441 &dev_attr_use_carrier.attr,
1442 &dev_attr_active_slave.attr,
1443 &dev_attr_mii_status.attr,
1444 &dev_attr_ad_aggregator.attr,
1445 &dev_attr_ad_num_ports.attr,
1446 &dev_attr_ad_actor_key.attr,
1447 &dev_attr_ad_partner_key.attr,
1448 &dev_attr_ad_partner_mac.attr,
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001449 NULL,
1450};
1451
1452static struct attribute_group bonding_group = {
1453 .name = "bonding",
1454 .attrs = per_bond_attrs,
1455};
1456
1457/*
1458 * Initialize sysfs. This sets up the bonding_masters file in
1459 * /sys/class/net.
1460 */
1461int bond_create_sysfs(void)
1462{
Jay Vosburghb8a97872008-06-13 18:12:04 -07001463 int ret;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001464
Jay Vosburghb8a97872008-06-13 18:12:04 -07001465 ret = netdev_class_create_file(&class_attr_bonding_masters);
Jay Vosburgh877cbd32007-01-19 18:15:47 -08001466 /*
1467 * Permit multiple loads of the module by ignoring failures to
1468 * create the bonding_masters sysfs file. Bonding devices
1469 * created by second or subsequent loads of the module will
1470 * not be listed in, or controllable by, bonding_masters, but
1471 * will have the usual "bonding" sysfs directory.
1472 *
1473 * This is done to preserve backwards compatibility for
1474 * initscripts/sysconfig, which load bonding multiple times to
1475 * configure multiple bonding devices.
1476 */
1477 if (ret == -EEXIST) {
Stephen Hemminger38d2f382008-05-14 22:35:04 -07001478 /* Is someone being kinky and naming a device bonding_master? */
1479 if (__dev_get_by_name(&init_net,
1480 class_attr_bonding_masters.attr.name))
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001481 pr_err("network device named %s already exists in sysfs",
Stephen Hemminger38d2f382008-05-14 22:35:04 -07001482 class_attr_bonding_masters.attr.name);
Stephen Hemminger130aa612009-06-11 05:46:04 -07001483 ret = 0;
Jay Vosburgh877cbd32007-01-19 18:15:47 -08001484 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001485
1486 return ret;
1487
1488}
1489
1490/*
1491 * Remove /sys/class/net/bonding_masters.
1492 */
1493void bond_destroy_sysfs(void)
1494{
Jay Vosburghb8a97872008-06-13 18:12:04 -07001495 netdev_class_remove_file(&class_attr_bonding_masters);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001496}
1497
1498/*
1499 * Initialize sysfs for each bond. This sets up and registers
1500 * the 'bondctl' directory for each individual bond under /sys/class/net.
1501 */
Eric W. Biederman6151b3d2009-10-29 14:18:22 +00001502void bond_prepare_sysfs_group(struct bonding *bond)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001503{
Eric W. Biederman6151b3d2009-10-29 14:18:22 +00001504 bond->dev->sysfs_groups[0] = &bonding_group;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001505}
1506