blob: 8041b67935327c11b45ee9458a45e6c62f8c5be9 [file] [log] [blame]
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001
2/*
3 * Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 * The full GNU General Public License is included in this distribution in the
20 * file called LICENSE.
21 *
Mitch Williamsb76cdba2005-11-09 10:36:41 -080022 */
Mitch Williamsb76cdba2005-11-09 10:36:41 -080023#include <linux/kernel.h>
24#include <linux/module.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080025#include <linux/device.h>
26#include <linux/sysdev.h>
27#include <linux/fs.h>
28#include <linux/types.h>
29#include <linux/string.h>
30#include <linux/netdevice.h>
31#include <linux/inetdevice.h>
32#include <linux/in.h>
33#include <linux/sysfs.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080034#include <linux/ctype.h>
35#include <linux/inet.h>
36#include <linux/rtnetlink.h>
Eric W. Biederman881d9662007-09-17 11:56:21 -070037#include <net/net_namespace.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080038
Mitch Williamsb76cdba2005-11-09 10:36:41 -080039#include "bonding.h"
Holger Eitzenberger5a03cdb2008-12-09 23:09:22 -080040
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -070041#define to_dev(obj) container_of(obj,struct device,kobj)
Wang Chen454d7c92008-11-12 23:37:49 -080042#define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd))))
Mitch Williamsb76cdba2005-11-09 10:36:41 -080043
44/*---------------------------- Declarations -------------------------------*/
45
Mitch Williamsb76cdba2005-11-09 10:36:41 -080046static int expected_refcount = -1;
Mitch Williamsb76cdba2005-11-09 10:36:41 -080047
48/*------------------------------ Functions --------------------------------*/
49
50/*
51 * "show" function for the bond_masters attribute.
52 * The class parameter is ignored.
53 */
Wagner Ferencb8843662007-12-06 23:40:30 -080054static ssize_t bonding_show_bonds(struct class *cls, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -080055{
56 int res = 0;
57 struct bonding *bond;
58
Stephen Hemminger7e083842009-06-12 19:02:46 +000059 rtnl_lock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -080060
61 list_for_each_entry(bond, &bond_dev_list, bond_list) {
62 if (res > (PAGE_SIZE - IFNAMSIZ)) {
63 /* not enough space for another interface name */
64 if ((PAGE_SIZE - res) > 10)
65 res = PAGE_SIZE - 10;
Wagner Ferencb8843662007-12-06 23:40:30 -080066 res += sprintf(buf + res, "++more++ ");
Mitch Williamsb76cdba2005-11-09 10:36:41 -080067 break;
68 }
Wagner Ferencb8843662007-12-06 23:40:30 -080069 res += sprintf(buf + res, "%s ", bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -080070 }
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -080071 if (res)
72 buf[res-1] = '\n'; /* eat the leftover space */
Stephen Hemminger7e083842009-06-12 19:02:46 +000073
74 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -080075 return res;
76}
77
78/*
79 * "store" function for the bond_masters attribute. This is what
80 * creates and deletes entire bonds.
81 *
82 * The class parameter is ignored.
83 *
84 */
85
86static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t count)
87{
88 char command[IFNAMSIZ + 1] = {0, };
89 char *ifname;
Jay Vosburgh027ea042008-01-17 16:25:02 -080090 int rv, res = count;
Mitch Williamsb76cdba2005-11-09 10:36:41 -080091 struct bonding *bond;
Mitch Williamsb76cdba2005-11-09 10:36:41 -080092
Mitch Williamsb76cdba2005-11-09 10:36:41 -080093 sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
94 ifname = command + 1;
95 if ((strlen(command) <= 1) ||
96 !dev_valid_name(ifname))
97 goto err_no_cmd;
98
99 if (command[0] == '+') {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800100 printk(KERN_INFO DRV_NAME
101 ": %s is being created...\n", ifname);
Stephen Hemmingerd2991f72009-06-12 19:02:44 +0000102 rv = bond_create(ifname);
Jay Vosburgh027ea042008-01-17 16:25:02 -0800103 if (rv) {
104 printk(KERN_INFO DRV_NAME ": Bond creation failed.\n");
105 res = rv;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800106 }
107 goto out;
108 }
109
110 if (command[0] == '-') {
Jay Vosburgh027ea042008-01-17 16:25:02 -0800111 rtnl_lock();
Jay Vosburgh027ea042008-01-17 16:25:02 -0800112
Pavel Emelyanov0883bec2008-05-17 21:10:10 -0700113 list_for_each_entry(bond, &bond_dev_list, bond_list)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800114 if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800115 /* check the ref count on the bond's kobject.
116 * If it's > expected, then there's a file open,
117 * and we have to fail.
118 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700119 if (atomic_read(&bond->dev->dev.kobj.kref.refcount)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800120 > expected_refcount){
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800121 printk(KERN_INFO DRV_NAME
122 ": Unable remove bond %s due to open references.\n",
123 ifname);
124 res = -EPERM;
Jay Vosburghc4ebc662008-05-02 17:49:38 -0700125 goto out_unlock;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800126 }
127 printk(KERN_INFO DRV_NAME
128 ": %s is being deleted...\n",
129 bond->dev->name);
Moni Shouad90a1622007-10-09 19:43:43 -0700130 bond_destroy(bond);
Jay Vosburghc4ebc662008-05-02 17:49:38 -0700131 goto out_unlock;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800132 }
133
134 printk(KERN_ERR DRV_NAME
135 ": unable to delete non-existent bond %s\n", ifname);
136 res = -ENODEV;
Jay Vosburghc4ebc662008-05-02 17:49:38 -0700137 goto out_unlock;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800138 }
139
140err_no_cmd:
141 printk(KERN_ERR DRV_NAME
142 ": no command found in bonding_masters. Use +ifname or -ifname.\n");
Jay Vosburghc4ebc662008-05-02 17:49:38 -0700143 return -EPERM;
144
145out_unlock:
Jay Vosburghc4ebc662008-05-02 17:49:38 -0700146 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800147
148 /* Always return either count or an error. If you return 0, you'll
149 * get called forever, which is bad.
150 */
151out:
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800152 return res;
153}
154/* class attribute for bond_masters file. This ends up in /sys/class/net */
155static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
156 bonding_show_bonds, bonding_store_bonds);
157
158int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave)
159{
160 char linkname[IFNAMSIZ+7];
161 int ret = 0;
162
163 /* first, create a link from the slave back to the master */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700164 ret = sysfs_create_link(&(slave->dev.kobj), &(master->dev.kobj),
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800165 "master");
166 if (ret)
167 return ret;
168 /* next, create a link from the master to the slave */
169 sprintf(linkname,"slave_%s",slave->name);
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700170 ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800171 linkname);
172 return ret;
173
174}
175
176void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave)
177{
178 char linkname[IFNAMSIZ+7];
179
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700180 sysfs_remove_link(&(slave->dev.kobj), "master");
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800181 sprintf(linkname,"slave_%s",slave->name);
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700182 sysfs_remove_link(&(master->dev.kobj), linkname);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800183}
184
185
186/*
187 * Show the slaves in the current bond.
188 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700189static ssize_t bonding_show_slaves(struct device *d,
190 struct device_attribute *attr, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800191{
192 struct slave *slave;
193 int i, res = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700194 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800195
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700196 read_lock(&bond->lock);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800197 bond_for_each_slave(bond, slave, i) {
198 if (res > (PAGE_SIZE - IFNAMSIZ)) {
199 /* not enough space for another interface name */
200 if ((PAGE_SIZE - res) > 10)
201 res = PAGE_SIZE - 10;
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800202 res += sprintf(buf + res, "++more++ ");
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800203 break;
204 }
205 res += sprintf(buf + res, "%s ", slave->dev->name);
206 }
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700207 read_unlock(&bond->lock);
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -0800208 if (res)
209 buf[res-1] = '\n'; /* eat the leftover space */
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800210 return res;
211}
212
213/*
214 * Set the slaves in the current bond. The bond interface must be
215 * up for this to succeed.
216 * This function is largely the same flow as bonding_update_bonds().
217 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700218static ssize_t bonding_store_slaves(struct device *d,
219 struct device_attribute *attr,
220 const char *buffer, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800221{
222 char command[IFNAMSIZ + 1] = { 0, };
223 char *ifname;
224 int i, res, found, ret = count;
Moni Shoua3158bf72007-10-09 19:43:41 -0700225 u32 original_mtu;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800226 struct slave *slave;
Luiz Fernando Capitulino3418db72006-02-01 00:54:34 -0800227 struct net_device *dev = NULL;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700228 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800229
230 /* Quick sanity check -- is the bond interface up? */
231 if (!(bond->dev->flags & IFF_UP)) {
Moni Shoua6b1bf092007-10-09 19:43:40 -0700232 printk(KERN_WARNING DRV_NAME
233 ": %s: doing slave updates when interface is down.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800234 bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800235 }
236
237 /* Note: We can't hold bond->lock here, as bond_create grabs it. */
238
Eric W. Biederman496a60c2009-05-13 17:02:50 +0000239 if (!rtnl_trylock())
240 return restart_syscall();
Jay Vosburgh027ea042008-01-17 16:25:02 -0800241
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800242 sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
243 ifname = command + 1;
244 if ((strlen(command) <= 1) ||
245 !dev_valid_name(ifname))
246 goto err_no_cmd;
247
248 if (command[0] == '+') {
249
250 /* Got a slave name in ifname. Is it already in the list? */
251 found = 0;
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700252 read_lock(&bond->lock);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800253 bond_for_each_slave(bond, slave, i)
254 if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
255 printk(KERN_ERR DRV_NAME
256 ": %s: Interface %s is already enslaved!\n",
257 bond->dev->name, ifname);
258 ret = -EPERM;
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700259 read_unlock(&bond->lock);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800260 goto out;
261 }
262
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700263 read_unlock(&bond->lock);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800264 printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
265 bond->dev->name, ifname);
Eric W. Biederman881d9662007-09-17 11:56:21 -0700266 dev = dev_get_by_name(&init_net, ifname);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800267 if (!dev) {
268 printk(KERN_INFO DRV_NAME
269 ": %s: Interface %s does not exist!\n",
270 bond->dev->name, ifname);
271 ret = -EPERM;
272 goto out;
273 }
274 else
275 dev_put(dev);
276
277 if (dev->flags & IFF_UP) {
278 printk(KERN_ERR DRV_NAME
279 ": %s: Error: Unable to enslave %s "
280 "because it is already up.\n",
281 bond->dev->name, dev->name);
282 ret = -EPERM;
283 goto out;
284 }
285 /* If this is the first slave, then we need to set
286 the master's hardware address to be the same as the
287 slave's. */
288 if (!(*((u32 *) & (bond->dev->dev_addr[0])))) {
289 memcpy(bond->dev->dev_addr, dev->dev_addr,
290 dev->addr_len);
291 }
292
293 /* Set the slave's MTU to match the bond */
Moni Shoua3158bf72007-10-09 19:43:41 -0700294 original_mtu = dev->mtu;
Stephen Hemmingereb7cc592008-11-19 21:56:05 -0800295 res = dev_set_mtu(dev, bond->dev->mtu);
296 if (res) {
297 ret = res;
298 goto out;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800299 }
Stephen Hemmingereb7cc592008-11-19 21:56:05 -0800300
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800301 res = bond_enslave(bond->dev, dev);
Moni Shoua3158bf72007-10-09 19:43:41 -0700302 bond_for_each_slave(bond, slave, i)
303 if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0)
304 slave->original_mtu = original_mtu;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800305 if (res) {
306 ret = res;
307 }
308 goto out;
309 }
310
311 if (command[0] == '-') {
312 dev = NULL;
David S. Miller6952d8922008-03-28 16:15:38 -0700313 original_mtu = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800314 bond_for_each_slave(bond, slave, i)
315 if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
316 dev = slave->dev;
Moni Shoua3158bf72007-10-09 19:43:41 -0700317 original_mtu = slave->original_mtu;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800318 break;
319 }
320 if (dev) {
321 printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n",
322 bond->dev->name, dev->name);
Moni Shouad90a1622007-10-09 19:43:43 -0700323 res = bond_release(bond->dev, dev);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800324 if (res) {
325 ret = res;
326 goto out;
327 }
328 /* set the slave MTU to the default */
Stephen Hemmingereb7cc592008-11-19 21:56:05 -0800329 dev_set_mtu(dev, original_mtu);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800330 }
331 else {
332 printk(KERN_ERR DRV_NAME ": unable to remove non-existent slave %s for bond %s.\n",
333 ifname, bond->dev->name);
334 ret = -ENODEV;
335 }
336 goto out;
337 }
338
339err_no_cmd:
340 printk(KERN_ERR DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name);
341 ret = -EPERM;
342
343out:
Jay Vosburgh027ea042008-01-17 16:25:02 -0800344 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800345 return ret;
346}
347
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700348static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800349
350/*
351 * Show and set the bonding mode. The bond interface must be down to
352 * change the mode.
353 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700354static ssize_t bonding_show_mode(struct device *d,
355 struct device_attribute *attr, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800356{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700357 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800358
359 return sprintf(buf, "%s %d\n",
360 bond_mode_tbl[bond->params.mode].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800361 bond->params.mode);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800362}
363
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700364static ssize_t bonding_store_mode(struct device *d,
365 struct device_attribute *attr,
366 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800367{
368 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700369 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800370
371 if (bond->dev->flags & IFF_UP) {
372 printk(KERN_ERR DRV_NAME
373 ": unable to update mode of %s because interface is up.\n",
374 bond->dev->name);
375 ret = -EPERM;
376 goto out;
377 }
378
Jay Vosburghece95f72008-01-17 16:25:01 -0800379 new_value = bond_parse_parm(buf, bond_mode_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800380 if (new_value < 0) {
381 printk(KERN_ERR DRV_NAME
382 ": %s: Ignoring invalid mode value %.*s.\n",
383 bond->dev->name,
384 (int)strlen(buf) - 1, buf);
385 ret = -EINVAL;
386 goto out;
387 } else {
Jay Vosburgh8f903c72006-02-21 16:36:44 -0800388 if (bond->params.mode == BOND_MODE_8023AD)
389 bond_unset_master_3ad_flags(bond);
390
391 if (bond->params.mode == BOND_MODE_ALB)
392 bond_unset_master_alb_flags(bond);
393
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800394 bond->params.mode = new_value;
395 bond_set_mode_ops(bond, bond->params.mode);
396 printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n",
397 bond->dev->name, bond_mode_tbl[new_value].modename, new_value);
398 }
399out:
400 return ret;
401}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700402static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800403
404/*
405 * Show and set the bonding transmit hash method. The bond interface must be down to
406 * change the xmit hash policy.
407 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700408static ssize_t bonding_show_xmit_hash(struct device *d,
409 struct device_attribute *attr,
410 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800411{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700412 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800413
Wagner Ferenc8e4b9322007-12-06 23:40:32 -0800414 return sprintf(buf, "%s %d\n",
415 xmit_hashtype_tbl[bond->params.xmit_policy].modename,
416 bond->params.xmit_policy);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800417}
418
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700419static ssize_t bonding_store_xmit_hash(struct device *d,
420 struct device_attribute *attr,
421 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800422{
423 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700424 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800425
426 if (bond->dev->flags & IFF_UP) {
427 printk(KERN_ERR DRV_NAME
428 "%s: Interface is up. Unable to update xmit policy.\n",
429 bond->dev->name);
430 ret = -EPERM;
431 goto out;
432 }
433
Jay Vosburghece95f72008-01-17 16:25:01 -0800434 new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800435 if (new_value < 0) {
436 printk(KERN_ERR DRV_NAME
437 ": %s: Ignoring invalid xmit hash policy value %.*s.\n",
438 bond->dev->name,
439 (int)strlen(buf) - 1, buf);
440 ret = -EINVAL;
441 goto out;
442 } else {
443 bond->params.xmit_policy = new_value;
444 bond_set_mode_ops(bond, bond->params.mode);
445 printk(KERN_INFO DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n",
446 bond->dev->name, xmit_hashtype_tbl[new_value].modename, new_value);
447 }
448out:
449 return ret;
450}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700451static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800452
453/*
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700454 * Show and set arp_validate.
455 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700456static ssize_t bonding_show_arp_validate(struct device *d,
457 struct device_attribute *attr,
458 char *buf)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700459{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700460 struct bonding *bond = to_bond(d);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700461
462 return sprintf(buf, "%s %d\n",
463 arp_validate_tbl[bond->params.arp_validate].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800464 bond->params.arp_validate);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700465}
466
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700467static ssize_t bonding_store_arp_validate(struct device *d,
468 struct device_attribute *attr,
469 const char *buf, size_t count)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700470{
471 int new_value;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700472 struct bonding *bond = to_bond(d);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700473
Jay Vosburghece95f72008-01-17 16:25:01 -0800474 new_value = bond_parse_parm(buf, arp_validate_tbl);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700475 if (new_value < 0) {
476 printk(KERN_ERR DRV_NAME
477 ": %s: Ignoring invalid arp_validate value %s\n",
478 bond->dev->name, buf);
479 return -EINVAL;
480 }
481 if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
482 printk(KERN_ERR DRV_NAME
483 ": %s: arp_validate only supported in active-backup mode.\n",
484 bond->dev->name);
485 return -EINVAL;
486 }
487 printk(KERN_INFO DRV_NAME ": %s: setting arp_validate to %s (%d).\n",
488 bond->dev->name, arp_validate_tbl[new_value].modename,
489 new_value);
490
491 if (!bond->params.arp_validate && new_value) {
492 bond_register_arp(bond);
493 } else if (bond->params.arp_validate && !new_value) {
494 bond_unregister_arp(bond);
495 }
496
497 bond->params.arp_validate = new_value;
498
499 return count;
500}
501
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700502static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700503
504/*
Jay Vosburghdd957c52007-10-09 19:57:24 -0700505 * Show and store fail_over_mac. User only allowed to change the
506 * value when there are no slaves.
507 */
508static ssize_t bonding_show_fail_over_mac(struct device *d, struct device_attribute *attr, char *buf)
509{
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
517static ssize_t bonding_store_fail_over_mac(struct device *d, struct device_attribute *attr, const char *buf, size_t count)
518{
519 int new_value;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700520 struct bonding *bond = to_bond(d);
521
522 if (bond->slave_cnt != 0) {
523 printk(KERN_ERR DRV_NAME
524 ": %s: Can't alter fail_over_mac with slaves in bond.\n",
525 bond->dev->name);
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700526 return -EPERM;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700527 }
528
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700529 new_value = bond_parse_parm(buf, fail_over_mac_tbl);
530 if (new_value < 0) {
Jay Vosburghdd957c52007-10-09 19:57:24 -0700531 printk(KERN_ERR DRV_NAME
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700532 ": %s: Ignoring invalid fail_over_mac value %s.\n",
533 bond->dev->name, buf);
534 return -EINVAL;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700535 }
536
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700537 bond->params.fail_over_mac = new_value;
538 printk(KERN_INFO DRV_NAME ": %s: Setting fail_over_mac to %s (%d).\n",
539 bond->dev->name, fail_over_mac_tbl[new_value].modename,
540 new_value);
541
542 return count;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700543}
544
545static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR, bonding_show_fail_over_mac, bonding_store_fail_over_mac);
546
547/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800548 * Show and set the arp timer interval. There are two tricky bits
549 * here. First, if ARP monitoring is activated, then we must disable
550 * MII monitoring. Second, if the ARP timer isn't running, we must
551 * start it.
552 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700553static ssize_t bonding_show_arp_interval(struct device *d,
554 struct device_attribute *attr,
555 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800556{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700557 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800558
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800559 return sprintf(buf, "%d\n", bond->params.arp_interval);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800560}
561
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700562static ssize_t bonding_store_arp_interval(struct device *d,
563 struct device_attribute *attr,
564 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800565{
566 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700567 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800568
569 if (sscanf(buf, "%d", &new_value) != 1) {
570 printk(KERN_ERR DRV_NAME
571 ": %s: no arp_interval value specified.\n",
572 bond->dev->name);
573 ret = -EINVAL;
574 goto out;
575 }
576 if (new_value < 0) {
577 printk(KERN_ERR DRV_NAME
578 ": %s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
579 bond->dev->name, new_value, INT_MAX);
580 ret = -EINVAL;
581 goto out;
582 }
583
584 printk(KERN_INFO DRV_NAME
585 ": %s: Setting ARP monitoring interval to %d.\n",
586 bond->dev->name, new_value);
587 bond->params.arp_interval = new_value;
Jay Vosburgh6cf3f412008-11-03 18:16:50 -0800588 if (bond->params.arp_interval)
589 bond->dev->priv_flags |= IFF_MASTER_ARPMON;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800590 if (bond->params.miimon) {
591 printk(KERN_INFO DRV_NAME
592 ": %s: ARP monitoring cannot be used with MII monitoring. "
593 "%s Disabling MII monitoring.\n",
594 bond->dev->name, bond->dev->name);
595 bond->params.miimon = 0;
Jay Vosburgh1b76b312007-10-17 17:37:45 -0700596 if (delayed_work_pending(&bond->mii_work)) {
597 cancel_delayed_work(&bond->mii_work);
598 flush_workqueue(bond->wq);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800599 }
600 }
601 if (!bond->params.arp_targets[0]) {
602 printk(KERN_INFO DRV_NAME
603 ": %s: ARP monitoring has been set up, "
604 "but no ARP targets have been specified.\n",
605 bond->dev->name);
606 }
607 if (bond->dev->flags & IFF_UP) {
608 /* If the interface is up, we may need to fire off
609 * the ARP timer. If the interface is down, the
610 * timer will get fired off when the open function
611 * is called.
612 */
Jay Vosburgh1b76b312007-10-17 17:37:45 -0700613 if (!delayed_work_pending(&bond->arp_work)) {
614 if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
615 INIT_DELAYED_WORK(&bond->arp_work,
616 bond_activebackup_arp_mon);
617 else
618 INIT_DELAYED_WORK(&bond->arp_work,
619 bond_loadbalance_arp_mon);
620
621 queue_delayed_work(bond->wq, &bond->arp_work, 0);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800622 }
623 }
624
625out:
626 return ret;
627}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700628static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800629
630/*
631 * Show and set the arp targets.
632 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700633static ssize_t bonding_show_arp_targets(struct device *d,
634 struct device_attribute *attr,
635 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800636{
637 int i, res = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700638 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800639
640 for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
641 if (bond->params.arp_targets[i])
Harvey Harrison63779432008-10-31 00:56:00 -0700642 res += sprintf(buf + res, "%pI4 ",
643 &bond->params.arp_targets[i]);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800644 }
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -0800645 if (res)
646 buf[res-1] = '\n'; /* eat the leftover space */
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800647 return res;
648}
649
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700650static ssize_t bonding_store_arp_targets(struct device *d,
651 struct device_attribute *attr,
652 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800653{
Al Virod3bb52b2007-08-22 20:06:58 -0400654 __be32 newtarget;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800655 int i = 0, done = 0, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700656 struct bonding *bond = to_bond(d);
Al Virod3bb52b2007-08-22 20:06:58 -0400657 __be32 *targets;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800658
659 targets = bond->params.arp_targets;
660 newtarget = in_aton(buf + 1);
661 /* look for adds */
662 if (buf[0] == '+') {
Al Virod3bb52b2007-08-22 20:06:58 -0400663 if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800664 printk(KERN_ERR DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700665 ": %s: invalid ARP target %pI4 specified for addition\n",
666 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800667 ret = -EINVAL;
668 goto out;
669 }
670 /* look for an empty slot to put the target in, and check for dupes */
Brian Haley5a31bec2009-04-13 00:11:30 -0700671 for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800672 if (targets[i] == newtarget) { /* duplicate */
673 printk(KERN_ERR DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700674 ": %s: ARP target %pI4 is already present\n",
675 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800676 ret = -EINVAL;
677 goto out;
678 }
Brian Haley5a31bec2009-04-13 00:11:30 -0700679 if (targets[i] == 0) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800680 printk(KERN_INFO DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700681 ": %s: adding ARP target %pI4.\n",
682 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800683 done = 1;
684 targets[i] = newtarget;
685 }
686 }
687 if (!done) {
688 printk(KERN_ERR DRV_NAME
689 ": %s: ARP target table is full!\n",
690 bond->dev->name);
691 ret = -EINVAL;
692 goto out;
693 }
694
695 }
696 else if (buf[0] == '-') {
Al Virod3bb52b2007-08-22 20:06:58 -0400697 if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800698 printk(KERN_ERR DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700699 ": %s: invalid ARP target %pI4 specified for removal\n",
700 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800701 ret = -EINVAL;
702 goto out;
703 }
704
Brian Haley5a31bec2009-04-13 00:11:30 -0700705 for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800706 if (targets[i] == newtarget) {
Brian Haley5a31bec2009-04-13 00:11:30 -0700707 int j;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800708 printk(KERN_INFO DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700709 ": %s: removing ARP target %pI4.\n",
710 bond->dev->name, &newtarget);
Brian Haley5a31bec2009-04-13 00:11:30 -0700711 for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j+1]; j++)
712 targets[j] = targets[j+1];
713
714 targets[j] = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800715 done = 1;
716 }
717 }
718 if (!done) {
719 printk(KERN_INFO DRV_NAME
Harvey Harrison63779432008-10-31 00:56:00 -0700720 ": %s: unable to remove nonexistent ARP target %pI4.\n",
721 bond->dev->name, &newtarget);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800722 ret = -EINVAL;
723 goto out;
724 }
725 }
726 else {
727 printk(KERN_ERR DRV_NAME ": no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
728 bond->dev->name);
729 ret = -EPERM;
730 goto out;
731 }
732
733out:
734 return ret;
735}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700736static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800737
738/*
739 * Show and set the up and down delays. These must be multiples of the
740 * MII monitoring value, and are stored internally as the multiplier.
741 * Thus, we must translate to MS for the real world.
742 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700743static ssize_t bonding_show_downdelay(struct device *d,
744 struct device_attribute *attr,
745 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800746{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700747 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800748
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800749 return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800750}
751
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700752static ssize_t bonding_store_downdelay(struct device *d,
753 struct device_attribute *attr,
754 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800755{
756 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700757 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800758
759 if (!(bond->params.miimon)) {
760 printk(KERN_ERR DRV_NAME
761 ": %s: Unable to set down delay as MII monitoring is disabled\n",
762 bond->dev->name);
763 ret = -EPERM;
764 goto out;
765 }
766
767 if (sscanf(buf, "%d", &new_value) != 1) {
768 printk(KERN_ERR DRV_NAME
769 ": %s: no down delay value specified.\n",
770 bond->dev->name);
771 ret = -EINVAL;
772 goto out;
773 }
774 if (new_value < 0) {
775 printk(KERN_ERR DRV_NAME
776 ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
777 bond->dev->name, new_value, 1, INT_MAX);
778 ret = -EINVAL;
779 goto out;
780 } else {
781 if ((new_value % bond->params.miimon) != 0) {
782 printk(KERN_WARNING DRV_NAME
783 ": %s: Warning: down delay (%d) is not a multiple "
784 "of miimon (%d), delay rounded to %d ms\n",
785 bond->dev->name, new_value, bond->params.miimon,
786 (new_value / bond->params.miimon) *
787 bond->params.miimon);
788 }
789 bond->params.downdelay = new_value / bond->params.miimon;
790 printk(KERN_INFO DRV_NAME ": %s: Setting down delay to %d.\n",
791 bond->dev->name, bond->params.downdelay * bond->params.miimon);
792
793 }
794
795out:
796 return ret;
797}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700798static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800799
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700800static ssize_t bonding_show_updelay(struct device *d,
801 struct device_attribute *attr,
802 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800803{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700804 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800805
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800806 return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800807
808}
809
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700810static ssize_t bonding_store_updelay(struct device *d,
811 struct device_attribute *attr,
812 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800813{
814 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700815 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800816
817 if (!(bond->params.miimon)) {
818 printk(KERN_ERR DRV_NAME
819 ": %s: Unable to set up delay as MII monitoring is disabled\n",
820 bond->dev->name);
821 ret = -EPERM;
822 goto out;
823 }
824
825 if (sscanf(buf, "%d", &new_value) != 1) {
826 printk(KERN_ERR DRV_NAME
827 ": %s: no up delay value specified.\n",
828 bond->dev->name);
829 ret = -EINVAL;
830 goto out;
831 }
832 if (new_value < 0) {
833 printk(KERN_ERR DRV_NAME
834 ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
835 bond->dev->name, new_value, 1, INT_MAX);
836 ret = -EINVAL;
837 goto out;
838 } else {
839 if ((new_value % bond->params.miimon) != 0) {
840 printk(KERN_WARNING DRV_NAME
841 ": %s: Warning: up delay (%d) is not a multiple "
842 "of miimon (%d), updelay rounded to %d ms\n",
843 bond->dev->name, new_value, bond->params.miimon,
844 (new_value / bond->params.miimon) *
845 bond->params.miimon);
846 }
847 bond->params.updelay = new_value / bond->params.miimon;
848 printk(KERN_INFO DRV_NAME ": %s: Setting up delay to %d.\n",
849 bond->dev->name, bond->params.updelay * bond->params.miimon);
850
851 }
852
853out:
854 return ret;
855}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700856static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800857
858/*
859 * Show and set the LACP interval. Interface must be down, and the mode
860 * must be set to 802.3ad mode.
861 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700862static ssize_t bonding_show_lacp(struct device *d,
863 struct device_attribute *attr,
864 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800865{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700866 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800867
868 return sprintf(buf, "%s %d\n",
869 bond_lacp_tbl[bond->params.lacp_fast].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800870 bond->params.lacp_fast);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800871}
872
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700873static ssize_t bonding_store_lacp(struct device *d,
874 struct device_attribute *attr,
875 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800876{
877 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700878 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800879
880 if (bond->dev->flags & IFF_UP) {
881 printk(KERN_ERR DRV_NAME
882 ": %s: Unable to update LACP rate because interface is up.\n",
883 bond->dev->name);
884 ret = -EPERM;
885 goto out;
886 }
887
888 if (bond->params.mode != BOND_MODE_8023AD) {
889 printk(KERN_ERR DRV_NAME
890 ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
891 bond->dev->name);
892 ret = -EPERM;
893 goto out;
894 }
895
Jay Vosburghece95f72008-01-17 16:25:01 -0800896 new_value = bond_parse_parm(buf, bond_lacp_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800897
898 if ((new_value == 1) || (new_value == 0)) {
899 bond->params.lacp_fast = new_value;
900 printk(KERN_INFO DRV_NAME
901 ": %s: Setting LACP rate to %s (%d).\n",
902 bond->dev->name, bond_lacp_tbl[new_value].modename, new_value);
903 } else {
904 printk(KERN_ERR DRV_NAME
905 ": %s: Ignoring invalid LACP rate value %.*s.\n",
906 bond->dev->name, (int)strlen(buf) - 1, buf);
907 ret = -EINVAL;
908 }
909out:
910 return ret;
911}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700912static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800913
Jay Vosburghfd989c82008-11-04 17:51:16 -0800914static ssize_t bonding_show_ad_select(struct device *d,
915 struct device_attribute *attr,
916 char *buf)
917{
918 struct bonding *bond = to_bond(d);
919
920 return sprintf(buf, "%s %d\n",
921 ad_select_tbl[bond->params.ad_select].modename,
922 bond->params.ad_select);
923}
924
925
926static ssize_t bonding_store_ad_select(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 (bond->dev->flags & IFF_UP) {
934 printk(KERN_ERR DRV_NAME
935 ": %s: Unable to update ad_select because interface "
936 "is up.\n", bond->dev->name);
937 ret = -EPERM;
938 goto out;
939 }
940
941 new_value = bond_parse_parm(buf, ad_select_tbl);
942
943 if (new_value != -1) {
944 bond->params.ad_select = new_value;
945 printk(KERN_INFO DRV_NAME
946 ": %s: Setting ad_select to %s (%d).\n",
947 bond->dev->name, ad_select_tbl[new_value].modename,
948 new_value);
949 } else {
950 printk(KERN_ERR DRV_NAME
951 ": %s: Ignoring invalid ad_select value %.*s.\n",
952 bond->dev->name, (int)strlen(buf) - 1, buf);
953 ret = -EINVAL;
954 }
955out:
956 return ret;
957}
958
959static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, bonding_show_ad_select, bonding_store_ad_select);
960
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800961/*
Moni Shoua7893b242008-05-17 21:10:12 -0700962 * Show and set the number of grat ARP to send after a failover event.
963 */
964static ssize_t bonding_show_n_grat_arp(struct device *d,
965 struct device_attribute *attr,
966 char *buf)
967{
968 struct bonding *bond = to_bond(d);
969
970 return sprintf(buf, "%d\n", bond->params.num_grat_arp);
971}
972
973static ssize_t bonding_store_n_grat_arp(struct device *d,
974 struct device_attribute *attr,
975 const char *buf, size_t count)
976{
977 int new_value, ret = count;
978 struct bonding *bond = to_bond(d);
979
980 if (sscanf(buf, "%d", &new_value) != 1) {
981 printk(KERN_ERR DRV_NAME
982 ": %s: no num_grat_arp value specified.\n",
983 bond->dev->name);
984 ret = -EINVAL;
985 goto out;
986 }
987 if (new_value < 0 || new_value > 255) {
988 printk(KERN_ERR DRV_NAME
989 ": %s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n",
990 bond->dev->name, new_value);
991 ret = -EINVAL;
992 goto out;
993 } else {
994 bond->params.num_grat_arp = new_value;
995 }
996out:
997 return ret;
998}
999static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, bonding_show_n_grat_arp, bonding_store_n_grat_arp);
Brian Haley305d5522008-11-04 17:51:14 -08001000
1001/*
1002 * Show and set the number of unsolicted NA's to send after a failover event.
1003 */
1004static ssize_t bonding_show_n_unsol_na(struct device *d,
1005 struct device_attribute *attr,
1006 char *buf)
1007{
1008 struct bonding *bond = to_bond(d);
1009
1010 return sprintf(buf, "%d\n", bond->params.num_unsol_na);
1011}
1012
1013static ssize_t bonding_store_n_unsol_na(struct device *d,
1014 struct device_attribute *attr,
1015 const char *buf, size_t count)
1016{
1017 int new_value, ret = count;
1018 struct bonding *bond = to_bond(d);
1019
1020 if (sscanf(buf, "%d", &new_value) != 1) {
1021 printk(KERN_ERR DRV_NAME
1022 ": %s: no num_unsol_na value specified.\n",
1023 bond->dev->name);
1024 ret = -EINVAL;
1025 goto out;
1026 }
1027 if (new_value < 0 || new_value > 255) {
1028 printk(KERN_ERR DRV_NAME
1029 ": %s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
1030 bond->dev->name, new_value);
1031 ret = -EINVAL;
1032 goto out;
1033 } else {
1034 bond->params.num_unsol_na = new_value;
1035 }
1036out:
1037 return ret;
1038}
1039static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, bonding_show_n_unsol_na, bonding_store_n_unsol_na);
1040
Moni Shoua7893b242008-05-17 21:10:12 -07001041/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001042 * Show and set the MII monitor interval. There are two tricky bits
1043 * here. First, if MII monitoring is activated, then we must disable
1044 * ARP monitoring. Second, if the timer isn't running, we must
1045 * start it.
1046 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001047static ssize_t bonding_show_miimon(struct device *d,
1048 struct device_attribute *attr,
1049 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001050{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001051 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001052
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001053 return sprintf(buf, "%d\n", bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001054}
1055
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001056static ssize_t bonding_store_miimon(struct device *d,
1057 struct device_attribute *attr,
1058 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001059{
1060 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001061 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001062
1063 if (sscanf(buf, "%d", &new_value) != 1) {
1064 printk(KERN_ERR DRV_NAME
1065 ": %s: no miimon value specified.\n",
1066 bond->dev->name);
1067 ret = -EINVAL;
1068 goto out;
1069 }
1070 if (new_value < 0) {
1071 printk(KERN_ERR DRV_NAME
1072 ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n",
1073 bond->dev->name, new_value, 1, INT_MAX);
1074 ret = -EINVAL;
1075 goto out;
1076 } else {
1077 printk(KERN_INFO DRV_NAME
1078 ": %s: Setting MII monitoring interval to %d.\n",
1079 bond->dev->name, new_value);
1080 bond->params.miimon = new_value;
1081 if(bond->params.updelay)
1082 printk(KERN_INFO DRV_NAME
1083 ": %s: Note: Updating updelay (to %d) "
1084 "since it is a multiple of the miimon value.\n",
1085 bond->dev->name,
1086 bond->params.updelay * bond->params.miimon);
1087 if(bond->params.downdelay)
1088 printk(KERN_INFO DRV_NAME
1089 ": %s: Note: Updating downdelay (to %d) "
1090 "since it is a multiple of the miimon value.\n",
1091 bond->dev->name,
1092 bond->params.downdelay * bond->params.miimon);
1093 if (bond->params.arp_interval) {
1094 printk(KERN_INFO DRV_NAME
1095 ": %s: MII monitoring cannot be used with "
1096 "ARP monitoring. Disabling ARP monitoring...\n",
1097 bond->dev->name);
1098 bond->params.arp_interval = 0;
Jay Vosburgh6cf3f412008-11-03 18:16:50 -08001099 bond->dev->priv_flags &= ~IFF_MASTER_ARPMON;
Jay Vosburghf5b2b962006-09-22 21:54:53 -07001100 if (bond->params.arp_validate) {
1101 bond_unregister_arp(bond);
1102 bond->params.arp_validate =
1103 BOND_ARP_VALIDATE_NONE;
1104 }
Jay Vosburgh1b76b312007-10-17 17:37:45 -07001105 if (delayed_work_pending(&bond->arp_work)) {
1106 cancel_delayed_work(&bond->arp_work);
1107 flush_workqueue(bond->wq);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001108 }
1109 }
1110
1111 if (bond->dev->flags & IFF_UP) {
1112 /* If the interface is up, we may need to fire off
1113 * the MII timer. If the interface is down, the
1114 * timer will get fired off when the open function
1115 * is called.
1116 */
Jay Vosburgh1b76b312007-10-17 17:37:45 -07001117 if (!delayed_work_pending(&bond->mii_work)) {
1118 INIT_DELAYED_WORK(&bond->mii_work,
1119 bond_mii_monitor);
1120 queue_delayed_work(bond->wq,
1121 &bond->mii_work, 0);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001122 }
1123 }
1124 }
1125out:
1126 return ret;
1127}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001128static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001129
1130/*
1131 * Show and set the primary slave. The store function is much
1132 * simpler than bonding_store_slaves function because it only needs to
1133 * handle one interface name.
1134 * The bond must be a mode that supports a primary for this be
1135 * set.
1136 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001137static ssize_t bonding_show_primary(struct device *d,
1138 struct device_attribute *attr,
1139 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001140{
1141 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001142 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001143
1144 if (bond->primary_slave)
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001145 count = sprintf(buf, "%s\n", bond->primary_slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001146
1147 return count;
1148}
1149
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001150static ssize_t bonding_store_primary(struct device *d,
1151 struct device_attribute *attr,
1152 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001153{
1154 int i;
1155 struct slave *slave;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001156 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001157
Eric W. Biederman496a60c2009-05-13 17:02:50 +00001158 if (!rtnl_trylock())
1159 return restart_syscall();
Jay Vosburghe934dd72008-01-17 16:24:57 -08001160 read_lock(&bond->lock);
1161 write_lock_bh(&bond->curr_slave_lock);
1162
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001163 if (!USES_PRIMARY(bond->params.mode)) {
1164 printk(KERN_INFO DRV_NAME
1165 ": %s: Unable to set primary slave; %s is in mode %d\n",
1166 bond->dev->name, bond->dev->name, bond->params.mode);
1167 } else {
1168 bond_for_each_slave(bond, slave, i) {
1169 if (strnicmp
1170 (slave->dev->name, buf,
1171 strlen(slave->dev->name)) == 0) {
1172 printk(KERN_INFO DRV_NAME
1173 ": %s: Setting %s as primary slave.\n",
1174 bond->dev->name, slave->dev->name);
1175 bond->primary_slave = slave;
1176 bond_select_active_slave(bond);
1177 goto out;
1178 }
1179 }
1180
1181 /* if we got here, then we didn't match the name of any slave */
1182
1183 if (strlen(buf) == 0 || buf[0] == '\n') {
1184 printk(KERN_INFO DRV_NAME
1185 ": %s: Setting primary slave to None.\n",
1186 bond->dev->name);
Luiz Fernando Capitulino3418db72006-02-01 00:54:34 -08001187 bond->primary_slave = NULL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001188 bond_select_active_slave(bond);
1189 } else {
1190 printk(KERN_INFO DRV_NAME
1191 ": %s: Unable to set %.*s as primary slave as it is not a slave.\n",
1192 bond->dev->name, (int)strlen(buf) - 1, buf);
1193 }
1194 }
1195out:
Jay Vosburghe934dd72008-01-17 16:24:57 -08001196 write_unlock_bh(&bond->curr_slave_lock);
1197 read_unlock(&bond->lock);
Jay Vosburgh6603a6f2007-10-17 17:37:50 -07001198 rtnl_unlock();
1199
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001200 return count;
1201}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001202static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001203
1204/*
1205 * Show and set the use_carrier flag.
1206 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001207static ssize_t bonding_show_carrier(struct device *d,
1208 struct device_attribute *attr,
1209 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001210{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001211 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001212
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001213 return sprintf(buf, "%d\n", bond->params.use_carrier);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001214}
1215
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001216static ssize_t bonding_store_carrier(struct device *d,
1217 struct device_attribute *attr,
1218 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001219{
1220 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001221 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001222
1223
1224 if (sscanf(buf, "%d", &new_value) != 1) {
1225 printk(KERN_ERR DRV_NAME
1226 ": %s: no use_carrier value specified.\n",
1227 bond->dev->name);
1228 ret = -EINVAL;
1229 goto out;
1230 }
1231 if ((new_value == 0) || (new_value == 1)) {
1232 bond->params.use_carrier = new_value;
1233 printk(KERN_INFO DRV_NAME ": %s: Setting use_carrier to %d.\n",
1234 bond->dev->name, new_value);
1235 } else {
1236 printk(KERN_INFO DRV_NAME
1237 ": %s: Ignoring invalid use_carrier value %d.\n",
1238 bond->dev->name, new_value);
1239 }
1240out:
1241 return count;
1242}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001243static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001244
1245
1246/*
1247 * Show and set currently active_slave.
1248 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001249static ssize_t bonding_show_active_slave(struct device *d,
1250 struct device_attribute *attr,
1251 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001252{
1253 struct slave *curr;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001254 struct bonding *bond = to_bond(d);
Wagner Ferenc16cd0162007-12-06 23:40:29 -08001255 int count = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001256
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001257 read_lock(&bond->curr_slave_lock);
1258 curr = bond->curr_active_slave;
1259 read_unlock(&bond->curr_slave_lock);
1260
1261 if (USES_PRIMARY(bond->params.mode) && curr)
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001262 count = sprintf(buf, "%s\n", curr->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001263 return count;
1264}
1265
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001266static ssize_t bonding_store_active_slave(struct device *d,
1267 struct device_attribute *attr,
1268 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001269{
1270 int i;
1271 struct slave *slave;
1272 struct slave *old_active = NULL;
1273 struct slave *new_active = NULL;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001274 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001275
Eric W. Biederman496a60c2009-05-13 17:02:50 +00001276 if (!rtnl_trylock())
1277 return restart_syscall();
Jay Vosburghe934dd72008-01-17 16:24:57 -08001278 read_lock(&bond->lock);
1279 write_lock_bh(&bond->curr_slave_lock);
Jay Vosburgh1466a212007-11-06 13:33:28 -08001280
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001281 if (!USES_PRIMARY(bond->params.mode)) {
1282 printk(KERN_INFO DRV_NAME
1283 ": %s: Unable to change active slave; %s is in mode %d\n",
1284 bond->dev->name, bond->dev->name, bond->params.mode);
1285 } else {
1286 bond_for_each_slave(bond, slave, i) {
1287 if (strnicmp
1288 (slave->dev->name, buf,
1289 strlen(slave->dev->name)) == 0) {
1290 old_active = bond->curr_active_slave;
1291 new_active = slave;
Jay Vosburgha50d8de2006-09-22 21:53:25 -07001292 if (new_active == old_active) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001293 /* do nothing */
1294 printk(KERN_INFO DRV_NAME
1295 ": %s: %s is already the current active slave.\n",
1296 bond->dev->name, slave->dev->name);
1297 goto out;
1298 }
1299 else {
1300 if ((new_active) &&
1301 (old_active) &&
1302 (new_active->link == BOND_LINK_UP) &&
1303 IS_UP(new_active->dev)) {
1304 printk(KERN_INFO DRV_NAME
1305 ": %s: Setting %s as active slave.\n",
1306 bond->dev->name, slave->dev->name);
1307 bond_change_active_slave(bond, new_active);
1308 }
1309 else {
1310 printk(KERN_INFO DRV_NAME
1311 ": %s: Could not set %s as active slave; "
1312 "either %s is down or the link is down.\n",
1313 bond->dev->name, slave->dev->name,
1314 slave->dev->name);
1315 }
1316 goto out;
1317 }
1318 }
1319 }
1320
1321 /* if we got here, then we didn't match the name of any slave */
1322
1323 if (strlen(buf) == 0 || buf[0] == '\n') {
1324 printk(KERN_INFO DRV_NAME
1325 ": %s: Setting active slave to None.\n",
1326 bond->dev->name);
Luiz Fernando Capitulino3418db72006-02-01 00:54:34 -08001327 bond->primary_slave = NULL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001328 bond_select_active_slave(bond);
1329 } else {
1330 printk(KERN_INFO DRV_NAME
1331 ": %s: Unable to set %.*s as active slave as it is not a slave.\n",
1332 bond->dev->name, (int)strlen(buf) - 1, buf);
1333 }
1334 }
1335out:
Jay Vosburghe934dd72008-01-17 16:24:57 -08001336 write_unlock_bh(&bond->curr_slave_lock);
1337 read_unlock(&bond->lock);
Jay Vosburgh6603a6f2007-10-17 17:37:50 -07001338 rtnl_unlock();
1339
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001340 return count;
1341
1342}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001343static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001344
1345
1346/*
1347 * Show link status of the bond interface.
1348 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001349static ssize_t bonding_show_mii_status(struct device *d,
1350 struct device_attribute *attr,
1351 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001352{
1353 struct slave *curr;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001354 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001355
1356 read_lock(&bond->curr_slave_lock);
1357 curr = bond->curr_active_slave;
1358 read_unlock(&bond->curr_slave_lock);
1359
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001360 return sprintf(buf, "%s\n", (curr) ? "up" : "down");
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001361}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001362static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001363
1364
1365/*
1366 * Show current 802.3ad aggregator ID.
1367 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001368static ssize_t bonding_show_ad_aggregator(struct device *d,
1369 struct device_attribute *attr,
1370 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001371{
1372 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001373 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001374
1375 if (bond->params.mode == BOND_MODE_8023AD) {
1376 struct ad_info ad_info;
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001377 count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.aggregator_id);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001378 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001379
1380 return count;
1381}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001382static DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001383
1384
1385/*
1386 * Show number of active 802.3ad ports.
1387 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001388static ssize_t bonding_show_ad_num_ports(struct device *d,
1389 struct device_attribute *attr,
1390 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001391{
1392 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001393 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001394
1395 if (bond->params.mode == BOND_MODE_8023AD) {
1396 struct ad_info ad_info;
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001397 count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0: ad_info.ports);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001398 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001399
1400 return count;
1401}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001402static DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001403
1404
1405/*
1406 * Show current 802.3ad actor key.
1407 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001408static ssize_t bonding_show_ad_actor_key(struct device *d,
1409 struct device_attribute *attr,
1410 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001411{
1412 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001413 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001414
1415 if (bond->params.mode == BOND_MODE_8023AD) {
1416 struct ad_info ad_info;
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001417 count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.actor_key);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001418 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001419
1420 return count;
1421}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001422static DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001423
1424
1425/*
1426 * Show current 802.3ad partner key.
1427 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001428static ssize_t bonding_show_ad_partner_key(struct device *d,
1429 struct device_attribute *attr,
1430 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001431{
1432 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001433 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001434
1435 if (bond->params.mode == BOND_MODE_8023AD) {
1436 struct ad_info ad_info;
Wagner Ferenc7bd46502007-12-06 23:40:28 -08001437 count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.partner_key);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001438 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001439
1440 return count;
1441}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001442static DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001443
1444
1445/*
1446 * Show current 802.3ad partner mac.
1447 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001448static ssize_t bonding_show_ad_partner_mac(struct device *d,
1449 struct device_attribute *attr,
1450 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001451{
1452 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001453 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001454
1455 if (bond->params.mode == BOND_MODE_8023AD) {
1456 struct ad_info ad_info;
1457 if (!bond_3ad_get_active_agg_info(bond, &ad_info)) {
Johannes Berge1749612008-10-27 15:59:26 -07001458 count = sprintf(buf, "%pM\n", ad_info.partner_system);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001459 }
1460 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001461
1462 return count;
1463}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001464static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001465
1466
1467
1468static struct attribute *per_bond_attrs[] = {
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001469 &dev_attr_slaves.attr,
1470 &dev_attr_mode.attr,
Jay Vosburghdd957c52007-10-09 19:57:24 -07001471 &dev_attr_fail_over_mac.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001472 &dev_attr_arp_validate.attr,
1473 &dev_attr_arp_interval.attr,
1474 &dev_attr_arp_ip_target.attr,
1475 &dev_attr_downdelay.attr,
1476 &dev_attr_updelay.attr,
1477 &dev_attr_lacp_rate.attr,
Jay Vosburghfd989c82008-11-04 17:51:16 -08001478 &dev_attr_ad_select.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001479 &dev_attr_xmit_hash_policy.attr,
Moni Shoua7893b242008-05-17 21:10:12 -07001480 &dev_attr_num_grat_arp.attr,
Brian Haley305d5522008-11-04 17:51:14 -08001481 &dev_attr_num_unsol_na.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001482 &dev_attr_miimon.attr,
1483 &dev_attr_primary.attr,
1484 &dev_attr_use_carrier.attr,
1485 &dev_attr_active_slave.attr,
1486 &dev_attr_mii_status.attr,
1487 &dev_attr_ad_aggregator.attr,
1488 &dev_attr_ad_num_ports.attr,
1489 &dev_attr_ad_actor_key.attr,
1490 &dev_attr_ad_partner_key.attr,
1491 &dev_attr_ad_partner_mac.attr,
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001492 NULL,
1493};
1494
1495static struct attribute_group bonding_group = {
1496 .name = "bonding",
1497 .attrs = per_bond_attrs,
1498};
1499
1500/*
1501 * Initialize sysfs. This sets up the bonding_masters file in
1502 * /sys/class/net.
1503 */
1504int bond_create_sysfs(void)
1505{
Jay Vosburghb8a97872008-06-13 18:12:04 -07001506 int ret;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001507
Jay Vosburghb8a97872008-06-13 18:12:04 -07001508 ret = netdev_class_create_file(&class_attr_bonding_masters);
Jay Vosburgh877cbd32007-01-19 18:15:47 -08001509 /*
1510 * Permit multiple loads of the module by ignoring failures to
1511 * create the bonding_masters sysfs file. Bonding devices
1512 * created by second or subsequent loads of the module will
1513 * not be listed in, or controllable by, bonding_masters, but
1514 * will have the usual "bonding" sysfs directory.
1515 *
1516 * This is done to preserve backwards compatibility for
1517 * initscripts/sysconfig, which load bonding multiple times to
1518 * configure multiple bonding devices.
1519 */
1520 if (ret == -EEXIST) {
Stephen Hemminger38d2f382008-05-14 22:35:04 -07001521 /* Is someone being kinky and naming a device bonding_master? */
1522 if (__dev_get_by_name(&init_net,
1523 class_attr_bonding_masters.attr.name))
1524 printk(KERN_ERR
1525 "network device named %s already exists in sysfs",
1526 class_attr_bonding_masters.attr.name);
Stephen Hemminger130aa612009-06-11 05:46:04 -07001527 ret = 0;
Jay Vosburgh877cbd32007-01-19 18:15:47 -08001528 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001529
1530 return ret;
1531
1532}
1533
1534/*
1535 * Remove /sys/class/net/bonding_masters.
1536 */
1537void bond_destroy_sysfs(void)
1538{
Jay Vosburghb8a97872008-06-13 18:12:04 -07001539 netdev_class_remove_file(&class_attr_bonding_masters);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001540}
1541
1542/*
1543 * Initialize sysfs for each bond. This sets up and registers
1544 * the 'bondctl' directory for each individual bond under /sys/class/net.
1545 */
1546int bond_create_sysfs_entry(struct bonding *bond)
1547{
1548 struct net_device *dev = bond->dev;
1549 int err;
1550
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001551 err = sysfs_create_group(&(dev->dev.kobj), &bonding_group);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001552 if (err) {
1553 printk(KERN_EMERG "eek! didn't create group!\n");
1554 }
1555
1556 if (expected_refcount < 1)
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001557 expected_refcount = atomic_read(&bond->dev->dev.kobj.kref.refcount);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001558
1559 return err;
1560}
1561/*
1562 * Remove sysfs entries for each bond.
1563 */
1564void bond_destroy_sysfs_entry(struct bonding *bond)
1565{
1566 struct net_device *dev = bond->dev;
1567
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001568 sysfs_remove_group(&(dev->dev.kobj), &bonding_group);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001569}
1570