blob: a59094f8bb6b501a4b977df0fa799886ad67d45f [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 */
Mitch Williamsb76cdba2005-11-09 10:36:41 -080022#include <linux/kernel.h>
23#include <linux/module.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080024#include <linux/device.h>
25#include <linux/sysdev.h>
26#include <linux/fs.h>
27#include <linux/types.h>
28#include <linux/string.h>
29#include <linux/netdevice.h>
30#include <linux/inetdevice.h>
31#include <linux/in.h>
32#include <linux/sysfs.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080033#include <linux/ctype.h>
34#include <linux/inet.h>
35#include <linux/rtnetlink.h>
Stephen Hemminger5c5129b2009-06-12 19:02:51 +000036#include <linux/etherdevice.h>
Eric W. Biederman881d9662007-09-17 11:56:21 -070037#include <net/net_namespace.h>
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000038#include <net/netns/generic.h>
39#include <linux/nsproxy.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080040
Mitch Williamsb76cdba2005-11-09 10:36:41 -080041#include "bonding.h"
Holger Eitzenberger5a03cdb2008-12-09 23:09:22 -080042
Stephen Hemminger3d632c32009-06-12 19:02:48 +000043#define to_dev(obj) container_of(obj, struct device, kobj)
Wang Chen454d7c92008-11-12 23:37:49 -080044#define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd))))
Mitch Williamsb76cdba2005-11-09 10:36:41 -080045
Mitch Williamsb76cdba2005-11-09 10:36:41 -080046/*
47 * "show" function for the bond_masters attribute.
48 * The class parameter is ignored.
49 */
Wagner Ferencb8843662007-12-06 23:40:30 -080050static ssize_t bonding_show_bonds(struct class *cls, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -080051{
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000052 struct net *net = current->nsproxy->net_ns;
53 struct bond_net *bn = net_generic(net, bond_net_id);
Mitch Williamsb76cdba2005-11-09 10:36:41 -080054 int res = 0;
55 struct bonding *bond;
56
Stephen Hemminger7e083842009-06-12 19:02:46 +000057 rtnl_lock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -080058
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000059 list_for_each_entry(bond, &bn->dev_list, bond_list) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -080060 if (res > (PAGE_SIZE - IFNAMSIZ)) {
61 /* not enough space for another interface name */
62 if ((PAGE_SIZE - res) > 10)
63 res = PAGE_SIZE - 10;
Wagner Ferencb8843662007-12-06 23:40:30 -080064 res += sprintf(buf + res, "++more++ ");
Mitch Williamsb76cdba2005-11-09 10:36:41 -080065 break;
66 }
Wagner Ferencb8843662007-12-06 23:40:30 -080067 res += sprintf(buf + res, "%s ", bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -080068 }
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -080069 if (res)
70 buf[res-1] = '\n'; /* eat the leftover space */
Stephen Hemminger7e083842009-06-12 19:02:46 +000071
72 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -080073 return res;
74}
75
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000076static struct net_device *bond_get_by_name(struct net *net, const char *ifname)
Stephen Hemminger373500d2009-06-12 19:02:50 +000077{
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000078 struct bond_net *bn = net_generic(net, bond_net_id);
Stephen Hemminger373500d2009-06-12 19:02:50 +000079 struct bonding *bond;
80
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000081 list_for_each_entry(bond, &bn->dev_list, bond_list) {
Stephen Hemminger373500d2009-06-12 19:02:50 +000082 if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
83 return bond->dev;
84 }
85 return NULL;
86}
87
Mitch Williamsb76cdba2005-11-09 10:36:41 -080088/*
89 * "store" function for the bond_masters attribute. This is what
90 * creates and deletes entire bonds.
91 *
92 * The class parameter is ignored.
93 *
94 */
95
Stephen Hemminger3d632c32009-06-12 19:02:48 +000096static ssize_t bonding_store_bonds(struct class *cls,
97 const char *buffer, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -080098{
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000099 struct net *net = current->nsproxy->net_ns;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800100 char command[IFNAMSIZ + 1] = {0, };
101 char *ifname;
Jay Vosburgh027ea042008-01-17 16:25:02 -0800102 int rv, res = count;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800103
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800104 sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
105 ifname = command + 1;
106 if ((strlen(command) <= 1) ||
107 !dev_valid_name(ifname))
108 goto err_no_cmd;
109
110 if (command[0] == '+') {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000111 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800112 ": %s is being created...\n", ifname);
Eric W. Biedermanec87fd32009-10-29 14:18:26 +0000113 rv = bond_create(net, ifname);
Jay Vosburgh027ea042008-01-17 16:25:02 -0800114 if (rv) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000115 pr_info(DRV_NAME ": Bond creation failed.\n");
Jay Vosburgh027ea042008-01-17 16:25:02 -0800116 res = rv;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800117 }
Stephen Hemminger373500d2009-06-12 19:02:50 +0000118 } else if (command[0] == '-') {
119 struct net_device *bond_dev;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800120
Jay Vosburgh027ea042008-01-17 16:25:02 -0800121 rtnl_lock();
Eric W. Biedermanec87fd32009-10-29 14:18:26 +0000122 bond_dev = bond_get_by_name(net, ifname);
Stephen Hemminger373500d2009-06-12 19:02:50 +0000123 if (bond_dev) {
124 pr_info(DRV_NAME ": %s is being deleted...\n",
125 ifname);
126 unregister_netdevice(bond_dev);
127 } else {
128 pr_err(DRV_NAME ": unable to delete non-existent %s\n",
129 ifname);
130 res = -ENODEV;
131 }
132 rtnl_unlock();
133 } else
134 goto err_no_cmd;
Jay Vosburgh027ea042008-01-17 16:25:02 -0800135
Stephen Hemminger373500d2009-06-12 19:02:50 +0000136 /* Always return either count or an error. If you return 0, you'll
137 * get called forever, which is bad.
138 */
139 return res;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800140
141err_no_cmd:
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000142 pr_err(DRV_NAME ": no command found in bonding_masters."
143 " Use +ifname or -ifname.\n");
Jay Vosburghc4ebc662008-05-02 17:49:38 -0700144 return -EPERM;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800145}
Stephen Hemminger373500d2009-06-12 19:02:50 +0000146
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800147/* class attribute for bond_masters file. This ends up in /sys/class/net */
148static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
149 bonding_show_bonds, bonding_store_bonds);
150
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000151int bond_create_slave_symlinks(struct net_device *master,
152 struct net_device *slave)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800153{
154 char linkname[IFNAMSIZ+7];
155 int ret = 0;
156
157 /* first, create a link from the slave back to the master */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700158 ret = sysfs_create_link(&(slave->dev.kobj), &(master->dev.kobj),
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800159 "master");
160 if (ret)
161 return ret;
162 /* next, create a link from the master to the slave */
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000163 sprintf(linkname, "slave_%s", slave->name);
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700164 ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800165 linkname);
166 return ret;
167
168}
169
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000170void bond_destroy_slave_symlinks(struct net_device *master,
171 struct net_device *slave)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800172{
173 char linkname[IFNAMSIZ+7];
174
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700175 sysfs_remove_link(&(slave->dev.kobj), "master");
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000176 sprintf(linkname, "slave_%s", slave->name);
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700177 sysfs_remove_link(&(master->dev.kobj), linkname);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800178}
179
180
181/*
182 * Show the slaves in the current bond.
183 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700184static ssize_t bonding_show_slaves(struct device *d,
185 struct device_attribute *attr, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800186{
187 struct slave *slave;
188 int i, res = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700189 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800190
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700191 read_lock(&bond->lock);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800192 bond_for_each_slave(bond, slave, i) {
193 if (res > (PAGE_SIZE - IFNAMSIZ)) {
194 /* not enough space for another interface name */
195 if ((PAGE_SIZE - res) > 10)
196 res = PAGE_SIZE - 10;
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800197 res += sprintf(buf + res, "++more++ ");
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800198 break;
199 }
200 res += sprintf(buf + res, "%s ", slave->dev->name);
201 }
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700202 read_unlock(&bond->lock);
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -0800203 if (res)
204 buf[res-1] = '\n'; /* eat the leftover space */
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800205 return res;
206}
207
208/*
209 * Set the slaves in the current bond. The bond interface must be
210 * up for this to succeed.
211 * This function is largely the same flow as bonding_update_bonds().
212 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700213static ssize_t bonding_store_slaves(struct device *d,
214 struct device_attribute *attr,
215 const char *buffer, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800216{
217 char command[IFNAMSIZ + 1] = { 0, };
218 char *ifname;
219 int i, res, found, ret = count;
Moni Shoua3158bf72007-10-09 19:43:41 -0700220 u32 original_mtu;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800221 struct slave *slave;
Luiz Fernando Capitulino3418db72006-02-01 00:54:34 -0800222 struct net_device *dev = NULL;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700223 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800224
225 /* Quick sanity check -- is the bond interface up? */
226 if (!(bond->dev->flags & IFF_UP)) {
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +0000227 pr_warning(DRV_NAME ": %s: doing slave updates when "
228 "interface is down.\n", bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800229 }
230
231 /* Note: We can't hold bond->lock here, as bond_create grabs it. */
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
242 if (command[0] == '+') {
243
244 /* Got a slave name in ifname. Is it already in the list? */
245 found = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800246
Eric W. Biedermanec87fd32009-10-29 14:18:26 +0000247 dev = __dev_get_by_name(dev_net(bond->dev), ifname);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800248 if (!dev) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000249 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800250 ": %s: Interface %s does not exist!\n",
251 bond->dev->name, ifname);
Stephen Hemminger373500d2009-06-12 19:02:50 +0000252 ret = -ENODEV;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800253 goto out;
Stephen Hemminger373500d2009-06-12 19:02:50 +0000254 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800255
256 if (dev->flags & IFF_UP) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000257 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800258 ": %s: Error: Unable to enslave %s "
259 "because it is already up.\n",
260 bond->dev->name, dev->name);
261 ret = -EPERM;
262 goto out;
263 }
Stephen Hemminger373500d2009-06-12 19:02:50 +0000264
265 read_lock(&bond->lock);
266 bond_for_each_slave(bond, slave, i)
267 if (slave->dev == dev) {
268 pr_err(DRV_NAME
269 ": %s: Interface %s is already enslaved!\n",
270 bond->dev->name, ifname);
271 ret = -EPERM;
272 read_unlock(&bond->lock);
273 goto out;
274 }
275 read_unlock(&bond->lock);
276
277 pr_info(DRV_NAME ": %s: Adding slave %s.\n",
278 bond->dev->name, ifname);
279
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800280 /* If this is the first slave, then we need to set
281 the master's hardware address to be the same as the
282 slave's. */
Stephen Hemminger5c5129b2009-06-12 19:02:51 +0000283 if (is_zero_ether_addr(bond->dev->dev_addr))
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800284 memcpy(bond->dev->dev_addr, dev->dev_addr,
285 dev->addr_len);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800286
287 /* Set the slave's MTU to match the bond */
Moni Shoua3158bf72007-10-09 19:43:41 -0700288 original_mtu = dev->mtu;
Stephen Hemmingereb7cc592008-11-19 21:56:05 -0800289 res = dev_set_mtu(dev, bond->dev->mtu);
290 if (res) {
291 ret = res;
292 goto out;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800293 }
Stephen Hemmingereb7cc592008-11-19 21:56:05 -0800294
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800295 res = bond_enslave(bond->dev, dev);
Moni Shoua3158bf72007-10-09 19:43:41 -0700296 bond_for_each_slave(bond, slave, i)
297 if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0)
298 slave->original_mtu = original_mtu;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000299 if (res)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800300 ret = res;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000301
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800302 goto out;
303 }
304
305 if (command[0] == '-') {
306 dev = NULL;
David S. Miller6952d8922008-03-28 16:15:38 -0700307 original_mtu = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800308 bond_for_each_slave(bond, slave, i)
309 if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
310 dev = slave->dev;
Moni Shoua3158bf72007-10-09 19:43:41 -0700311 original_mtu = slave->original_mtu;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800312 break;
313 }
314 if (dev) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000315 pr_info(DRV_NAME ": %s: Removing slave %s\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800316 bond->dev->name, dev->name);
Moni Shouad90a1622007-10-09 19:43:43 -0700317 res = bond_release(bond->dev, dev);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800318 if (res) {
319 ret = res;
320 goto out;
321 }
322 /* set the slave MTU to the default */
Stephen Hemmingereb7cc592008-11-19 21:56:05 -0800323 dev_set_mtu(dev, original_mtu);
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000324 } else {
325 pr_err(DRV_NAME ": unable to remove non-existent"
326 " slave %s for bond %s.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800327 ifname, bond->dev->name);
328 ret = -ENODEV;
329 }
330 goto out;
331 }
332
333err_no_cmd:
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000334 pr_err(DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800335 ret = -EPERM;
336
337out:
Jay Vosburgh027ea042008-01-17 16:25:02 -0800338 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800339 return ret;
340}
341
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000342static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves,
343 bonding_store_slaves);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800344
345/*
346 * Show and set the bonding mode. The bond interface must be down to
347 * change the mode.
348 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700349static ssize_t bonding_show_mode(struct device *d,
350 struct device_attribute *attr, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800351{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700352 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800353
354 return sprintf(buf, "%s %d\n",
355 bond_mode_tbl[bond->params.mode].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800356 bond->params.mode);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800357}
358
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700359static ssize_t bonding_store_mode(struct device *d,
360 struct device_attribute *attr,
361 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800362{
363 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700364 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800365
366 if (bond->dev->flags & IFF_UP) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000367 pr_err(DRV_NAME ": unable to update mode of %s"
368 " because interface is up.\n", bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800369 ret = -EPERM;
370 goto out;
371 }
372
Jay Vosburghece95f72008-01-17 16:25:01 -0800373 new_value = bond_parse_parm(buf, bond_mode_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800374 if (new_value < 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000375 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800376 ": %s: Ignoring invalid mode value %.*s.\n",
377 bond->dev->name,
378 (int)strlen(buf) - 1, buf);
379 ret = -EINVAL;
380 goto out;
381 } else {
Jay Vosburgh8f903c72006-02-21 16:36:44 -0800382 if (bond->params.mode == BOND_MODE_8023AD)
383 bond_unset_master_3ad_flags(bond);
384
385 if (bond->params.mode == BOND_MODE_ALB)
386 bond_unset_master_alb_flags(bond);
387
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800388 bond->params.mode = new_value;
389 bond_set_mode_ops(bond, bond->params.mode);
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000390 pr_info(DRV_NAME ": %s: setting mode to %s (%d).\n",
391 bond->dev->name, bond_mode_tbl[new_value].modename,
392 new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800393 }
394out:
395 return ret;
396}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000397static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
398 bonding_show_mode, bonding_store_mode);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800399
400/*
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000401 * Show and set the bonding transmit hash method.
402 * The bond interface must be down to change the xmit hash policy.
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800403 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700404static ssize_t bonding_show_xmit_hash(struct device *d,
405 struct device_attribute *attr,
406 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800407{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700408 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800409
Wagner Ferenc8e4b9322007-12-06 23:40:32 -0800410 return sprintf(buf, "%s %d\n",
411 xmit_hashtype_tbl[bond->params.xmit_policy].modename,
412 bond->params.xmit_policy);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800413}
414
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700415static ssize_t bonding_store_xmit_hash(struct device *d,
416 struct device_attribute *attr,
417 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800418{
419 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700420 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800421
422 if (bond->dev->flags & IFF_UP) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000423 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800424 "%s: Interface is up. Unable to update xmit policy.\n",
425 bond->dev->name);
426 ret = -EPERM;
427 goto out;
428 }
429
Jay Vosburghece95f72008-01-17 16:25:01 -0800430 new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800431 if (new_value < 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000432 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800433 ": %s: Ignoring invalid xmit hash policy value %.*s.\n",
434 bond->dev->name,
435 (int)strlen(buf) - 1, buf);
436 ret = -EINVAL;
437 goto out;
438 } else {
439 bond->params.xmit_policy = new_value;
440 bond_set_mode_ops(bond, bond->params.mode);
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000441 pr_info(DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n",
442 bond->dev->name,
443 xmit_hashtype_tbl[new_value].modename, new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800444 }
445out:
446 return ret;
447}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000448static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR,
449 bonding_show_xmit_hash, bonding_store_xmit_hash);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800450
451/*
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700452 * Show and set arp_validate.
453 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700454static ssize_t bonding_show_arp_validate(struct device *d,
455 struct device_attribute *attr,
456 char *buf)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700457{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700458 struct bonding *bond = to_bond(d);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700459
460 return sprintf(buf, "%s %d\n",
461 arp_validate_tbl[bond->params.arp_validate].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800462 bond->params.arp_validate);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700463}
464
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700465static ssize_t bonding_store_arp_validate(struct device *d,
466 struct device_attribute *attr,
467 const char *buf, size_t count)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700468{
469 int new_value;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700470 struct bonding *bond = to_bond(d);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700471
Jay Vosburghece95f72008-01-17 16:25:01 -0800472 new_value = bond_parse_parm(buf, arp_validate_tbl);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700473 if (new_value < 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000474 pr_err(DRV_NAME
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700475 ": %s: Ignoring invalid arp_validate value %s\n",
476 bond->dev->name, buf);
477 return -EINVAL;
478 }
479 if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000480 pr_err(DRV_NAME
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700481 ": %s: arp_validate only supported in active-backup mode.\n",
482 bond->dev->name);
483 return -EINVAL;
484 }
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000485 pr_info(DRV_NAME ": %s: setting arp_validate to %s (%d).\n",
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700486 bond->dev->name, arp_validate_tbl[new_value].modename,
487 new_value);
488
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000489 if (!bond->params.arp_validate && new_value)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700490 bond_register_arp(bond);
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000491 else if (bond->params.arp_validate && !new_value)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700492 bond_unregister_arp(bond);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700493
494 bond->params.arp_validate = new_value;
495
496 return count;
497}
498
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000499static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate,
500 bonding_store_arp_validate);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700501
502/*
Jay Vosburghdd957c52007-10-09 19:57:24 -0700503 * Show and store fail_over_mac. User only allowed to change the
504 * value when there are no slaves.
505 */
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000506static ssize_t bonding_show_fail_over_mac(struct device *d,
507 struct device_attribute *attr,
508 char *buf)
Jay Vosburghdd957c52007-10-09 19:57:24 -0700509{
510 struct bonding *bond = to_bond(d);
511
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700512 return sprintf(buf, "%s %d\n",
513 fail_over_mac_tbl[bond->params.fail_over_mac].modename,
514 bond->params.fail_over_mac);
Jay Vosburghdd957c52007-10-09 19:57:24 -0700515}
516
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000517static ssize_t bonding_store_fail_over_mac(struct device *d,
518 struct device_attribute *attr,
519 const char *buf, size_t count)
Jay Vosburghdd957c52007-10-09 19:57:24 -0700520{
521 int new_value;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700522 struct bonding *bond = to_bond(d);
523
524 if (bond->slave_cnt != 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000525 pr_err(DRV_NAME
Jay Vosburghdd957c52007-10-09 19:57:24 -0700526 ": %s: Can't alter fail_over_mac with slaves in bond.\n",
527 bond->dev->name);
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700528 return -EPERM;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700529 }
530
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700531 new_value = bond_parse_parm(buf, fail_over_mac_tbl);
532 if (new_value < 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000533 pr_err(DRV_NAME
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700534 ": %s: Ignoring invalid fail_over_mac value %s.\n",
535 bond->dev->name, buf);
536 return -EINVAL;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700537 }
538
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700539 bond->params.fail_over_mac = new_value;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000540 pr_info(DRV_NAME ": %s: Setting fail_over_mac to %s (%d).\n",
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700541 bond->dev->name, fail_over_mac_tbl[new_value].modename,
542 new_value);
543
544 return count;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700545}
546
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000547static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR,
548 bonding_show_fail_over_mac, bonding_store_fail_over_mac);
Jay Vosburghdd957c52007-10-09 19:57:24 -0700549
550/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800551 * Show and set the arp timer interval. There are two tricky bits
552 * here. First, if ARP monitoring is activated, then we must disable
553 * MII monitoring. Second, if the ARP timer isn't running, we must
554 * start it.
555 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700556static ssize_t bonding_show_arp_interval(struct device *d,
557 struct device_attribute *attr,
558 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800559{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700560 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800561
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800562 return sprintf(buf, "%d\n", bond->params.arp_interval);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800563}
564
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700565static ssize_t bonding_store_arp_interval(struct device *d,
566 struct device_attribute *attr,
567 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800568{
569 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700570 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800571
572 if (sscanf(buf, "%d", &new_value) != 1) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000573 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800574 ": %s: no arp_interval value specified.\n",
575 bond->dev->name);
576 ret = -EINVAL;
577 goto out;
578 }
579 if (new_value < 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000580 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800581 ": %s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
582 bond->dev->name, new_value, INT_MAX);
583 ret = -EINVAL;
584 goto out;
585 }
586
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000587 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800588 ": %s: Setting ARP monitoring interval to %d.\n",
589 bond->dev->name, new_value);
590 bond->params.arp_interval = new_value;
Jay Vosburgh6cf3f412008-11-03 18:16:50 -0800591 if (bond->params.arp_interval)
592 bond->dev->priv_flags |= IFF_MASTER_ARPMON;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800593 if (bond->params.miimon) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000594 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800595 ": %s: ARP monitoring cannot be used with MII monitoring. "
596 "%s Disabling MII monitoring.\n",
597 bond->dev->name, bond->dev->name);
598 bond->params.miimon = 0;
Jay Vosburgh1b76b312007-10-17 17:37:45 -0700599 if (delayed_work_pending(&bond->mii_work)) {
600 cancel_delayed_work(&bond->mii_work);
601 flush_workqueue(bond->wq);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800602 }
603 }
604 if (!bond->params.arp_targets[0]) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000605 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800606 ": %s: ARP monitoring has been set up, "
607 "but no ARP targets have been specified.\n",
608 bond->dev->name);
609 }
610 if (bond->dev->flags & IFF_UP) {
611 /* If the interface is up, we may need to fire off
612 * the ARP timer. If the interface is down, the
613 * timer will get fired off when the open function
614 * is called.
615 */
Jay Vosburgh1b76b312007-10-17 17:37:45 -0700616 if (!delayed_work_pending(&bond->arp_work)) {
617 if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
618 INIT_DELAYED_WORK(&bond->arp_work,
619 bond_activebackup_arp_mon);
620 else
621 INIT_DELAYED_WORK(&bond->arp_work,
622 bond_loadbalance_arp_mon);
623
624 queue_delayed_work(bond->wq, &bond->arp_work, 0);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800625 }
626 }
627
628out:
629 return ret;
630}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000631static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR,
632 bonding_show_arp_interval, bonding_store_arp_interval);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800633
634/*
635 * Show and set the arp targets.
636 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700637static ssize_t bonding_show_arp_targets(struct device *d,
638 struct device_attribute *attr,
639 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800640{
641 int i, res = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700642 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800643
644 for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
645 if (bond->params.arp_targets[i])
Harvey Harrison63779432008-10-31 00:56:00 -0700646 res += sprintf(buf + res, "%pI4 ",
647 &bond->params.arp_targets[i]);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800648 }
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -0800649 if (res)
650 buf[res-1] = '\n'; /* eat the leftover space */
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800651 return res;
652}
653
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700654static ssize_t bonding_store_arp_targets(struct device *d,
655 struct device_attribute *attr,
656 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800657{
Al Virod3bb52b2007-08-22 20:06:58 -0400658 __be32 newtarget;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800659 int i = 0, done = 0, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700660 struct bonding *bond = to_bond(d);
Al Virod3bb52b2007-08-22 20:06:58 -0400661 __be32 *targets;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800662
663 targets = bond->params.arp_targets;
664 newtarget = in_aton(buf + 1);
665 /* look for adds */
666 if (buf[0] == '+') {
Al Virod3bb52b2007-08-22 20:06:58 -0400667 if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000668 pr_err(DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700669 ": %s: invalid ARP target %pI4 specified for addition\n",
670 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800671 ret = -EINVAL;
672 goto out;
673 }
674 /* look for an empty slot to put the target in, and check for dupes */
Brian Haley5a31bec2009-04-13 00:11:30 -0700675 for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800676 if (targets[i] == newtarget) { /* duplicate */
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000677 pr_err(DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700678 ": %s: ARP target %pI4 is already present\n",
679 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800680 ret = -EINVAL;
681 goto out;
682 }
Brian Haley5a31bec2009-04-13 00:11:30 -0700683 if (targets[i] == 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000684 pr_info(DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700685 ": %s: adding ARP target %pI4.\n",
686 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800687 done = 1;
688 targets[i] = newtarget;
689 }
690 }
691 if (!done) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000692 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800693 ": %s: ARP target table is full!\n",
694 bond->dev->name);
695 ret = -EINVAL;
696 goto out;
697 }
698
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000699 } else if (buf[0] == '-') {
Al Virod3bb52b2007-08-22 20:06:58 -0400700 if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000701 pr_err(DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700702 ": %s: invalid ARP target %pI4 specified for removal\n",
703 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800704 ret = -EINVAL;
705 goto out;
706 }
707
Brian Haley5a31bec2009-04-13 00:11:30 -0700708 for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800709 if (targets[i] == newtarget) {
Brian Haley5a31bec2009-04-13 00:11:30 -0700710 int j;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000711 pr_info(DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700712 ": %s: removing ARP target %pI4.\n",
713 bond->dev->name, &newtarget);
Brian Haley5a31bec2009-04-13 00:11:30 -0700714 for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j+1]; j++)
715 targets[j] = targets[j+1];
716
717 targets[j] = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800718 done = 1;
719 }
720 }
721 if (!done) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000722 pr_info(DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700723 ": %s: unable to remove nonexistent ARP target %pI4.\n",
724 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800725 ret = -EINVAL;
726 goto out;
727 }
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000728 } else {
729 pr_err(DRV_NAME ": no command found in arp_ip_targets file"
730 " for bond %s. Use +<addr> or -<addr>.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800731 bond->dev->name);
732 ret = -EPERM;
733 goto out;
734 }
735
736out:
737 return ret;
738}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700739static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800740
741/*
742 * Show and set the up and down delays. These must be multiples of the
743 * MII monitoring value, and are stored internally as the multiplier.
744 * Thus, we must translate to MS for the real world.
745 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700746static ssize_t bonding_show_downdelay(struct device *d,
747 struct device_attribute *attr,
748 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800749{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700750 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800751
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800752 return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800753}
754
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700755static ssize_t bonding_store_downdelay(struct device *d,
756 struct device_attribute *attr,
757 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800758{
759 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700760 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800761
762 if (!(bond->params.miimon)) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000763 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800764 ": %s: Unable to set down delay as MII monitoring is disabled\n",
765 bond->dev->name);
766 ret = -EPERM;
767 goto out;
768 }
769
770 if (sscanf(buf, "%d", &new_value) != 1) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000771 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800772 ": %s: no down delay value specified.\n",
773 bond->dev->name);
774 ret = -EINVAL;
775 goto out;
776 }
777 if (new_value < 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000778 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800779 ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
780 bond->dev->name, new_value, 1, INT_MAX);
781 ret = -EINVAL;
782 goto out;
783 } else {
784 if ((new_value % bond->params.miimon) != 0) {
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +0000785 pr_warning(DRV_NAME
786 ": %s: Warning: down delay (%d) is not a "
787 "multiple of miimon (%d), delay rounded "
788 "to %d ms\n",
789 bond->dev->name, new_value,
790 bond->params.miimon,
791 (new_value / bond->params.miimon) *
792 bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800793 }
794 bond->params.downdelay = new_value / bond->params.miimon;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000795 pr_info(DRV_NAME ": %s: Setting down delay to %d.\n",
796 bond->dev->name,
797 bond->params.downdelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800798
799 }
800
801out:
802 return ret;
803}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000804static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR,
805 bonding_show_downdelay, bonding_store_downdelay);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800806
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700807static ssize_t bonding_show_updelay(struct device *d,
808 struct device_attribute *attr,
809 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800810{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700811 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800812
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800813 return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800814
815}
816
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700817static ssize_t bonding_store_updelay(struct device *d,
818 struct device_attribute *attr,
819 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800820{
821 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700822 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800823
824 if (!(bond->params.miimon)) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000825 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800826 ": %s: Unable to set up delay as MII monitoring is disabled\n",
827 bond->dev->name);
828 ret = -EPERM;
829 goto out;
830 }
831
832 if (sscanf(buf, "%d", &new_value) != 1) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000833 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800834 ": %s: no up delay value specified.\n",
835 bond->dev->name);
836 ret = -EINVAL;
837 goto out;
838 }
839 if (new_value < 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000840 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800841 ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
842 bond->dev->name, new_value, 1, INT_MAX);
843 ret = -EINVAL;
844 goto out;
845 } else {
846 if ((new_value % bond->params.miimon) != 0) {
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +0000847 pr_warning(DRV_NAME
848 ": %s: Warning: up delay (%d) is not a "
849 "multiple of miimon (%d), updelay rounded "
850 "to %d ms\n",
851 bond->dev->name, new_value,
852 bond->params.miimon,
853 (new_value / bond->params.miimon) *
854 bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800855 }
856 bond->params.updelay = new_value / bond->params.miimon;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000857 pr_info(DRV_NAME ": %s: Setting up delay to %d.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800858 bond->dev->name, bond->params.updelay * bond->params.miimon);
859
860 }
861
862out:
863 return ret;
864}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000865static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR,
866 bonding_show_updelay, bonding_store_updelay);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800867
868/*
869 * Show and set the LACP interval. Interface must be down, and the mode
870 * must be set to 802.3ad mode.
871 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700872static ssize_t bonding_show_lacp(struct device *d,
873 struct device_attribute *attr,
874 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800875{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700876 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800877
878 return sprintf(buf, "%s %d\n",
879 bond_lacp_tbl[bond->params.lacp_fast].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800880 bond->params.lacp_fast);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800881}
882
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700883static ssize_t bonding_store_lacp(struct device *d,
884 struct device_attribute *attr,
885 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800886{
887 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700888 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800889
890 if (bond->dev->flags & IFF_UP) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000891 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800892 ": %s: Unable to update LACP rate because interface is up.\n",
893 bond->dev->name);
894 ret = -EPERM;
895 goto out;
896 }
897
898 if (bond->params.mode != BOND_MODE_8023AD) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000899 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800900 ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
901 bond->dev->name);
902 ret = -EPERM;
903 goto out;
904 }
905
Jay Vosburghece95f72008-01-17 16:25:01 -0800906 new_value = bond_parse_parm(buf, bond_lacp_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800907
908 if ((new_value == 1) || (new_value == 0)) {
909 bond->params.lacp_fast = new_value;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000910 pr_info(DRV_NAME ": %s: Setting LACP rate to %s (%d).\n",
911 bond->dev->name, bond_lacp_tbl[new_value].modename,
912 new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800913 } else {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000914 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800915 ": %s: Ignoring invalid LACP rate value %.*s.\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000916 bond->dev->name, (int)strlen(buf) - 1, buf);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800917 ret = -EINVAL;
918 }
919out:
920 return ret;
921}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000922static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR,
923 bonding_show_lacp, bonding_store_lacp);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800924
Jay Vosburghfd989c82008-11-04 17:51:16 -0800925static ssize_t bonding_show_ad_select(struct device *d,
926 struct device_attribute *attr,
927 char *buf)
928{
929 struct bonding *bond = to_bond(d);
930
931 return sprintf(buf, "%s %d\n",
932 ad_select_tbl[bond->params.ad_select].modename,
933 bond->params.ad_select);
934}
935
936
937static ssize_t bonding_store_ad_select(struct device *d,
938 struct device_attribute *attr,
939 const char *buf, size_t count)
940{
941 int new_value, ret = count;
942 struct bonding *bond = to_bond(d);
943
944 if (bond->dev->flags & IFF_UP) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000945 pr_err(DRV_NAME
Jay Vosburghfd989c82008-11-04 17:51:16 -0800946 ": %s: Unable to update ad_select because interface "
947 "is up.\n", bond->dev->name);
948 ret = -EPERM;
949 goto out;
950 }
951
952 new_value = bond_parse_parm(buf, ad_select_tbl);
953
954 if (new_value != -1) {
955 bond->params.ad_select = new_value;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000956 pr_info(DRV_NAME
Jay Vosburghfd989c82008-11-04 17:51:16 -0800957 ": %s: Setting ad_select to %s (%d).\n",
958 bond->dev->name, ad_select_tbl[new_value].modename,
959 new_value);
960 } else {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000961 pr_err(DRV_NAME
Jay Vosburghfd989c82008-11-04 17:51:16 -0800962 ": %s: Ignoring invalid ad_select value %.*s.\n",
963 bond->dev->name, (int)strlen(buf) - 1, buf);
964 ret = -EINVAL;
965 }
966out:
967 return ret;
968}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000969static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR,
970 bonding_show_ad_select, bonding_store_ad_select);
Jay Vosburghfd989c82008-11-04 17:51:16 -0800971
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800972/*
Moni Shoua7893b242008-05-17 21:10:12 -0700973 * Show and set the number of grat ARP to send after a failover event.
974 */
975static ssize_t bonding_show_n_grat_arp(struct device *d,
976 struct device_attribute *attr,
977 char *buf)
978{
979 struct bonding *bond = to_bond(d);
980
981 return sprintf(buf, "%d\n", bond->params.num_grat_arp);
982}
983
984static ssize_t bonding_store_n_grat_arp(struct device *d,
985 struct device_attribute *attr,
986 const char *buf, size_t count)
987{
988 int new_value, ret = count;
989 struct bonding *bond = to_bond(d);
990
991 if (sscanf(buf, "%d", &new_value) != 1) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000992 pr_err(DRV_NAME
Moni Shoua7893b242008-05-17 21:10:12 -0700993 ": %s: no num_grat_arp value specified.\n",
994 bond->dev->name);
995 ret = -EINVAL;
996 goto out;
997 }
998 if (new_value < 0 || new_value > 255) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000999 pr_err(DRV_NAME
Moni Shoua7893b242008-05-17 21:10:12 -07001000 ": %s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n",
1001 bond->dev->name, new_value);
1002 ret = -EINVAL;
1003 goto out;
1004 } else {
1005 bond->params.num_grat_arp = new_value;
1006 }
1007out:
1008 return ret;
1009}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001010static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR,
1011 bonding_show_n_grat_arp, bonding_store_n_grat_arp);
Brian Haley305d5522008-11-04 17:51:14 -08001012
1013/*
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001014 * Show and set the number of unsolicited NA's to send after a failover event.
Brian Haley305d5522008-11-04 17:51:14 -08001015 */
1016static ssize_t bonding_show_n_unsol_na(struct device *d,
1017 struct device_attribute *attr,
1018 char *buf)
1019{
1020 struct bonding *bond = to_bond(d);
1021
1022 return sprintf(buf, "%d\n", bond->params.num_unsol_na);
1023}
1024
1025static ssize_t bonding_store_n_unsol_na(struct device *d,
1026 struct device_attribute *attr,
1027 const char *buf, size_t count)
1028{
1029 int new_value, ret = count;
1030 struct bonding *bond = to_bond(d);
1031
1032 if (sscanf(buf, "%d", &new_value) != 1) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001033 pr_err(DRV_NAME
Brian Haley305d5522008-11-04 17:51:14 -08001034 ": %s: no num_unsol_na value specified.\n",
1035 bond->dev->name);
1036 ret = -EINVAL;
1037 goto out;
1038 }
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001039
Brian Haley305d5522008-11-04 17:51:14 -08001040 if (new_value < 0 || new_value > 255) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001041 pr_err(DRV_NAME
Brian Haley305d5522008-11-04 17:51:14 -08001042 ": %s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
1043 bond->dev->name, new_value);
1044 ret = -EINVAL;
1045 goto out;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001046 } else
Brian Haley305d5522008-11-04 17:51:14 -08001047 bond->params.num_unsol_na = new_value;
Brian Haley305d5522008-11-04 17:51:14 -08001048out:
1049 return ret;
1050}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001051static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR,
1052 bonding_show_n_unsol_na, bonding_store_n_unsol_na);
Brian Haley305d5522008-11-04 17:51:14 -08001053
Moni Shoua7893b242008-05-17 21:10:12 -07001054/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001055 * Show and set the MII monitor interval. There are two tricky bits
1056 * here. First, if MII monitoring is activated, then we must disable
1057 * ARP monitoring. Second, if the timer isn't running, we must
1058 * start it.
1059 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001060static ssize_t bonding_show_miimon(struct device *d,
1061 struct device_attribute *attr,
1062 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001063{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001064 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001065
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001066 return sprintf(buf, "%d\n", bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001067}
1068
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001069static ssize_t bonding_store_miimon(struct device *d,
1070 struct device_attribute *attr,
1071 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001072{
1073 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001074 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001075
1076 if (sscanf(buf, "%d", &new_value) != 1) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001077 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001078 ": %s: no miimon value specified.\n",
1079 bond->dev->name);
1080 ret = -EINVAL;
1081 goto out;
1082 }
1083 if (new_value < 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001084 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001085 ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n",
1086 bond->dev->name, new_value, 1, INT_MAX);
1087 ret = -EINVAL;
1088 goto out;
1089 } else {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001090 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001091 ": %s: Setting MII monitoring interval to %d.\n",
1092 bond->dev->name, new_value);
1093 bond->params.miimon = new_value;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001094 if (bond->params.updelay)
1095 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001096 ": %s: Note: Updating updelay (to %d) "
1097 "since it is a multiple of the miimon value.\n",
1098 bond->dev->name,
1099 bond->params.updelay * bond->params.miimon);
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001100 if (bond->params.downdelay)
1101 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001102 ": %s: Note: Updating downdelay (to %d) "
1103 "since it is a multiple of the miimon value.\n",
1104 bond->dev->name,
1105 bond->params.downdelay * bond->params.miimon);
1106 if (bond->params.arp_interval) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001107 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001108 ": %s: MII monitoring cannot be used with "
1109 "ARP monitoring. Disabling ARP monitoring...\n",
1110 bond->dev->name);
1111 bond->params.arp_interval = 0;
Jay Vosburgh6cf3f412008-11-03 18:16:50 -08001112 bond->dev->priv_flags &= ~IFF_MASTER_ARPMON;
Jay Vosburghf5b2b962006-09-22 21:54:53 -07001113 if (bond->params.arp_validate) {
1114 bond_unregister_arp(bond);
1115 bond->params.arp_validate =
1116 BOND_ARP_VALIDATE_NONE;
1117 }
Jay Vosburgh1b76b312007-10-17 17:37:45 -07001118 if (delayed_work_pending(&bond->arp_work)) {
1119 cancel_delayed_work(&bond->arp_work);
1120 flush_workqueue(bond->wq);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001121 }
1122 }
1123
1124 if (bond->dev->flags & IFF_UP) {
1125 /* If the interface is up, we may need to fire off
1126 * the MII timer. If the interface is down, the
1127 * timer will get fired off when the open function
1128 * is called.
1129 */
Jay Vosburgh1b76b312007-10-17 17:37:45 -07001130 if (!delayed_work_pending(&bond->mii_work)) {
1131 INIT_DELAYED_WORK(&bond->mii_work,
1132 bond_mii_monitor);
1133 queue_delayed_work(bond->wq,
1134 &bond->mii_work, 0);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001135 }
1136 }
1137 }
1138out:
1139 return ret;
1140}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001141static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR,
1142 bonding_show_miimon, bonding_store_miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001143
1144/*
1145 * Show and set the primary slave. The store function is much
1146 * simpler than bonding_store_slaves function because it only needs to
1147 * handle one interface name.
1148 * The bond must be a mode that supports a primary for this be
1149 * set.
1150 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001151static ssize_t bonding_show_primary(struct device *d,
1152 struct device_attribute *attr,
1153 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001154{
1155 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001156 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001157
1158 if (bond->primary_slave)
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001159 count = sprintf(buf, "%s\n", bond->primary_slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001160
1161 return count;
1162}
1163
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001164static ssize_t bonding_store_primary(struct device *d,
1165 struct device_attribute *attr,
1166 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001167{
1168 int i;
1169 struct slave *slave;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001170 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001171
Eric W. Biederman496a60c2009-05-13 17:02:50 +00001172 if (!rtnl_trylock())
1173 return restart_syscall();
Jay Vosburghe934dd72008-01-17 16:24:57 -08001174 read_lock(&bond->lock);
1175 write_lock_bh(&bond->curr_slave_lock);
1176
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001177 if (!USES_PRIMARY(bond->params.mode)) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001178 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001179 ": %s: Unable to set primary slave; %s is in mode %d\n",
1180 bond->dev->name, bond->dev->name, bond->params.mode);
1181 } else {
1182 bond_for_each_slave(bond, slave, i) {
1183 if (strnicmp
1184 (slave->dev->name, buf,
1185 strlen(slave->dev->name)) == 0) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001186 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001187 ": %s: Setting %s as primary slave.\n",
1188 bond->dev->name, slave->dev->name);
1189 bond->primary_slave = slave;
Jiri Pirkoce501ca2009-09-18 02:13:22 +00001190 strcpy(bond->params.primary, slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001191 bond_select_active_slave(bond);
1192 goto out;
1193 }
1194 }
1195
1196 /* if we got here, then we didn't match the name of any slave */
1197
1198 if (strlen(buf) == 0 || buf[0] == '\n') {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001199 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001200 ": %s: Setting primary slave to None.\n",
1201 bond->dev->name);
Luiz Fernando Capitulino3418db72006-02-01 00:54:34 -08001202 bond->primary_slave = NULL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001203 bond_select_active_slave(bond);
1204 } else {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001205 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001206 ": %s: Unable to set %.*s as primary slave as it is not a slave.\n",
1207 bond->dev->name, (int)strlen(buf) - 1, buf);
1208 }
1209 }
1210out:
Jay Vosburghe934dd72008-01-17 16:24:57 -08001211 write_unlock_bh(&bond->curr_slave_lock);
1212 read_unlock(&bond->lock);
Jay Vosburgh6603a6f2007-10-17 17:37:50 -07001213 rtnl_unlock();
1214
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001215 return count;
1216}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001217static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR,
1218 bonding_show_primary, bonding_store_primary);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001219
1220/*
Jiri Pirkoa5499522009-09-25 03:28:09 +00001221 * Show and set the primary_reselect flag.
1222 */
1223static ssize_t bonding_show_primary_reselect(struct device *d,
1224 struct device_attribute *attr,
1225 char *buf)
1226{
1227 struct bonding *bond = to_bond(d);
1228
1229 return sprintf(buf, "%s %d\n",
1230 pri_reselect_tbl[bond->params.primary_reselect].modename,
1231 bond->params.primary_reselect);
1232}
1233
1234static ssize_t bonding_store_primary_reselect(struct device *d,
1235 struct device_attribute *attr,
1236 const char *buf, size_t count)
1237{
1238 int new_value, ret = count;
1239 struct bonding *bond = to_bond(d);
1240
1241 if (!rtnl_trylock())
1242 return restart_syscall();
1243
1244 new_value = bond_parse_parm(buf, pri_reselect_tbl);
1245 if (new_value < 0) {
1246 pr_err(DRV_NAME
1247 ": %s: Ignoring invalid primary_reselect value %.*s.\n",
1248 bond->dev->name,
1249 (int) strlen(buf) - 1, buf);
1250 ret = -EINVAL;
1251 goto out;
1252 }
1253
1254 bond->params.primary_reselect = new_value;
1255 pr_info(DRV_NAME ": %s: setting primary_reselect to %s (%d).\n",
1256 bond->dev->name, pri_reselect_tbl[new_value].modename,
1257 new_value);
1258
1259 read_lock(&bond->lock);
1260 write_lock_bh(&bond->curr_slave_lock);
1261 bond_select_active_slave(bond);
1262 write_unlock_bh(&bond->curr_slave_lock);
1263 read_unlock(&bond->lock);
1264out:
1265 rtnl_unlock();
1266 return ret;
1267}
1268static DEVICE_ATTR(primary_reselect, S_IRUGO | S_IWUSR,
1269 bonding_show_primary_reselect,
1270 bonding_store_primary_reselect);
1271
1272/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001273 * Show and set the use_carrier flag.
1274 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001275static ssize_t bonding_show_carrier(struct device *d,
1276 struct device_attribute *attr,
1277 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001278{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001279 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001280
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001281 return sprintf(buf, "%d\n", bond->params.use_carrier);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001282}
1283
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001284static ssize_t bonding_store_carrier(struct device *d,
1285 struct device_attribute *attr,
1286 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001287{
1288 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001289 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001290
1291
1292 if (sscanf(buf, "%d", &new_value) != 1) {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001293 pr_err(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001294 ": %s: no use_carrier value specified.\n",
1295 bond->dev->name);
1296 ret = -EINVAL;
1297 goto out;
1298 }
1299 if ((new_value == 0) || (new_value == 1)) {
1300 bond->params.use_carrier = new_value;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001301 pr_info(DRV_NAME ": %s: Setting use_carrier to %d.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001302 bond->dev->name, new_value);
1303 } else {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001304 pr_info(DRV_NAME
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001305 ": %s: Ignoring invalid use_carrier value %d.\n",
1306 bond->dev->name, new_value);
1307 }
1308out:
1309 return count;
1310}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001311static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR,
1312 bonding_show_carrier, bonding_store_carrier);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001313
1314
1315/*
1316 * Show and set currently active_slave.
1317 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001318static ssize_t bonding_show_active_slave(struct device *d,
1319 struct device_attribute *attr,
1320 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001321{
1322 struct slave *curr;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001323 struct bonding *bond = to_bond(d);
Wagner Ferenc16cd0162007-12-06 23:40:29 -08001324 int count = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001325
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001326 read_lock(&bond->curr_slave_lock);
1327 curr = bond->curr_active_slave;
1328 read_unlock(&bond->curr_slave_lock);
1329
1330 if (USES_PRIMARY(bond->params.mode) && curr)
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001331 count = sprintf(buf, "%s\n", curr->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001332 return count;
1333}
1334
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001335static ssize_t bonding_store_active_slave(struct device *d,
1336 struct device_attribute *attr,
1337 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001338{
1339 int i;
1340 struct slave *slave;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001341 struct slave *old_active = NULL;
1342 struct slave *new_active = NULL;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001343 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001344
Eric W. Biederman496a60c2009-05-13 17:02:50 +00001345 if (!rtnl_trylock())
1346 return restart_syscall();
Jay Vosburghe934dd72008-01-17 16:24:57 -08001347 read_lock(&bond->lock);
1348 write_lock_bh(&bond->curr_slave_lock);
Jay Vosburgh1466a212007-11-06 13:33:28 -08001349
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001350 if (!USES_PRIMARY(bond->params.mode))
1351 pr_info(DRV_NAME ": %s: Unable to change active slave;"
1352 " %s is in mode %d\n",
1353 bond->dev->name, bond->dev->name, bond->params.mode);
1354 else {
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001355 bond_for_each_slave(bond, slave, i) {
1356 if (strnicmp
1357 (slave->dev->name, buf,
1358 strlen(slave->dev->name)) == 0) {
1359 old_active = bond->curr_active_slave;
1360 new_active = slave;
Jay Vosburgha50d8de2006-09-22 21:53:25 -07001361 if (new_active == old_active) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001362 /* do nothing */
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +00001363 pr_info(DRV_NAME
1364 ": %s: %s is already the current active slave.\n",
1365 bond->dev->name, slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001366 goto out;
1367 }
1368 else {
1369 if ((new_active) &&
1370 (old_active) &&
1371 (new_active->link == BOND_LINK_UP) &&
1372 IS_UP(new_active->dev)) {
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +00001373 pr_info(DRV_NAME
1374 ": %s: Setting %s as active slave.\n",
1375 bond->dev->name, slave->dev->name);
1376 bond_change_active_slave(bond, new_active);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001377 }
1378 else {
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +00001379 pr_info(DRV_NAME
1380 ": %s: Could not set %s as active slave; "
1381 "either %s is down or the link is down.\n",
1382 bond->dev->name, slave->dev->name,
1383 slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001384 }
1385 goto out;
1386 }
1387 }
1388 }
1389
1390 /* if we got here, then we didn't match the name of any slave */
1391
1392 if (strlen(buf) == 0 || buf[0] == '\n') {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001393 pr_info(DRV_NAME
1394 ": %s: Setting active slave to None.\n",
1395 bond->dev->name);
Luiz Fernando Capitulino3418db72006-02-01 00:54:34 -08001396 bond->primary_slave = NULL;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001397 bond_select_active_slave(bond);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001398 } else {
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001399 pr_info(DRV_NAME ": %s: Unable to set %.*s"
1400 " as active slave as it is not a slave.\n",
1401 bond->dev->name, (int)strlen(buf) - 1, buf);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001402 }
1403 }
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001404 out:
Jay Vosburghe934dd72008-01-17 16:24:57 -08001405 write_unlock_bh(&bond->curr_slave_lock);
1406 read_unlock(&bond->lock);
Jay Vosburgh6603a6f2007-10-17 17:37:50 -07001407 rtnl_unlock();
1408
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001409 return count;
1410
1411}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001412static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR,
1413 bonding_show_active_slave, bonding_store_active_slave);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001414
1415
1416/*
1417 * Show link status of the bond interface.
1418 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001419static ssize_t bonding_show_mii_status(struct device *d,
1420 struct device_attribute *attr,
1421 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001422{
1423 struct slave *curr;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001424 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001425
1426 read_lock(&bond->curr_slave_lock);
1427 curr = bond->curr_active_slave;
1428 read_unlock(&bond->curr_slave_lock);
1429
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001430 return sprintf(buf, "%s\n", curr ? "up" : "down");
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001431}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001432static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001433
1434
1435/*
1436 * Show current 802.3ad aggregator ID.
1437 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001438static ssize_t bonding_show_ad_aggregator(struct device *d,
1439 struct device_attribute *attr,
1440 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001441{
1442 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001443 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001444
1445 if (bond->params.mode == BOND_MODE_8023AD) {
1446 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001447 count = sprintf(buf, "%d\n",
1448 (bond_3ad_get_active_agg_info(bond, &ad_info))
1449 ? 0 : ad_info.aggregator_id);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001450 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001451
1452 return count;
1453}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001454static DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001455
1456
1457/*
1458 * Show number of active 802.3ad ports.
1459 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001460static ssize_t bonding_show_ad_num_ports(struct device *d,
1461 struct device_attribute *attr,
1462 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001463{
1464 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001465 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001466
1467 if (bond->params.mode == BOND_MODE_8023AD) {
1468 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001469 count = sprintf(buf, "%d\n",
1470 (bond_3ad_get_active_agg_info(bond, &ad_info))
1471 ? 0 : ad_info.ports);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001472 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001473
1474 return count;
1475}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001476static DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001477
1478
1479/*
1480 * Show current 802.3ad actor key.
1481 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001482static ssize_t bonding_show_ad_actor_key(struct device *d,
1483 struct device_attribute *attr,
1484 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001485{
1486 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001487 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001488
1489 if (bond->params.mode == BOND_MODE_8023AD) {
1490 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001491 count = sprintf(buf, "%d\n",
1492 (bond_3ad_get_active_agg_info(bond, &ad_info))
1493 ? 0 : ad_info.actor_key);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001494 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001495
1496 return count;
1497}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001498static DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001499
1500
1501/*
1502 * Show current 802.3ad partner key.
1503 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001504static ssize_t bonding_show_ad_partner_key(struct device *d,
1505 struct device_attribute *attr,
1506 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001507{
1508 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001509 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001510
1511 if (bond->params.mode == BOND_MODE_8023AD) {
1512 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001513 count = sprintf(buf, "%d\n",
1514 (bond_3ad_get_active_agg_info(bond, &ad_info))
1515 ? 0 : ad_info.partner_key);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001516 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001517
1518 return count;
1519}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001520static DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001521
1522
1523/*
1524 * Show current 802.3ad partner mac.
1525 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001526static ssize_t bonding_show_ad_partner_mac(struct device *d,
1527 struct device_attribute *attr,
1528 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001529{
1530 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001531 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001532
1533 if (bond->params.mode == BOND_MODE_8023AD) {
1534 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001535 if (!bond_3ad_get_active_agg_info(bond, &ad_info))
Johannes Berge1749612008-10-27 15:59:26 -07001536 count = sprintf(buf, "%pM\n", ad_info.partner_system);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001537 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001538
1539 return count;
1540}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001541static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001542
1543
1544
1545static struct attribute *per_bond_attrs[] = {
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001546 &dev_attr_slaves.attr,
1547 &dev_attr_mode.attr,
Jay Vosburghdd957c52007-10-09 19:57:24 -07001548 &dev_attr_fail_over_mac.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001549 &dev_attr_arp_validate.attr,
1550 &dev_attr_arp_interval.attr,
1551 &dev_attr_arp_ip_target.attr,
1552 &dev_attr_downdelay.attr,
1553 &dev_attr_updelay.attr,
1554 &dev_attr_lacp_rate.attr,
Jay Vosburghfd989c82008-11-04 17:51:16 -08001555 &dev_attr_ad_select.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001556 &dev_attr_xmit_hash_policy.attr,
Moni Shoua7893b242008-05-17 21:10:12 -07001557 &dev_attr_num_grat_arp.attr,
Brian Haley305d5522008-11-04 17:51:14 -08001558 &dev_attr_num_unsol_na.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001559 &dev_attr_miimon.attr,
1560 &dev_attr_primary.attr,
Jiri Pirkoa5499522009-09-25 03:28:09 +00001561 &dev_attr_primary_reselect.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001562 &dev_attr_use_carrier.attr,
1563 &dev_attr_active_slave.attr,
1564 &dev_attr_mii_status.attr,
1565 &dev_attr_ad_aggregator.attr,
1566 &dev_attr_ad_num_ports.attr,
1567 &dev_attr_ad_actor_key.attr,
1568 &dev_attr_ad_partner_key.attr,
1569 &dev_attr_ad_partner_mac.attr,
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001570 NULL,
1571};
1572
1573static struct attribute_group bonding_group = {
1574 .name = "bonding",
1575 .attrs = per_bond_attrs,
1576};
1577
1578/*
1579 * Initialize sysfs. This sets up the bonding_masters file in
1580 * /sys/class/net.
1581 */
1582int bond_create_sysfs(void)
1583{
Jay Vosburghb8a97872008-06-13 18:12:04 -07001584 int ret;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001585
Jay Vosburghb8a97872008-06-13 18:12:04 -07001586 ret = netdev_class_create_file(&class_attr_bonding_masters);
Jay Vosburgh877cbd32007-01-19 18:15:47 -08001587 /*
1588 * Permit multiple loads of the module by ignoring failures to
1589 * create the bonding_masters sysfs file. Bonding devices
1590 * created by second or subsequent loads of the module will
1591 * not be listed in, or controllable by, bonding_masters, but
1592 * will have the usual "bonding" sysfs directory.
1593 *
1594 * This is done to preserve backwards compatibility for
1595 * initscripts/sysconfig, which load bonding multiple times to
1596 * configure multiple bonding devices.
1597 */
1598 if (ret == -EEXIST) {
Stephen Hemminger38d2f382008-05-14 22:35:04 -07001599 /* Is someone being kinky and naming a device bonding_master? */
1600 if (__dev_get_by_name(&init_net,
1601 class_attr_bonding_masters.attr.name))
Jiri Pirkoe5e2a8f2009-08-13 04:11:52 +00001602 pr_err("network device named %s already "
1603 "exists in sysfs",
Stephen Hemminger38d2f382008-05-14 22:35:04 -07001604 class_attr_bonding_masters.attr.name);
Stephen Hemminger130aa612009-06-11 05:46:04 -07001605 ret = 0;
Jay Vosburgh877cbd32007-01-19 18:15:47 -08001606 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001607
1608 return ret;
1609
1610}
1611
1612/*
1613 * Remove /sys/class/net/bonding_masters.
1614 */
1615void bond_destroy_sysfs(void)
1616{
Jay Vosburghb8a97872008-06-13 18:12:04 -07001617 netdev_class_remove_file(&class_attr_bonding_masters);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001618}
1619
1620/*
1621 * Initialize sysfs for each bond. This sets up and registers
1622 * the 'bondctl' directory for each individual bond under /sys/class/net.
1623 */
Eric W. Biederman6151b3d2009-10-29 14:18:22 +00001624void bond_prepare_sysfs_group(struct bonding *bond)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001625{
Eric W. Biederman6151b3d2009-10-29 14:18:22 +00001626 bond->dev->sysfs_groups[0] = &bonding_group;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001627}
1628