blob: bda00a01393adccb951c654bc33da2ed711f9c8c [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
Jeff Kirsheradf8d3f2013-12-06 06:28:47 -080015 * with this program; if not, see <http://www.gnu.org/licenses/>.
Mitch Williamsb76cdba2005-11-09 10:36:41 -080016 *
17 * The full GNU General Public License is included in this distribution in the
18 * file called LICENSE.
19 *
Mitch Williamsb76cdba2005-11-09 10:36:41 -080020 */
Joe Perchesa4aee5c2009-12-13 20:06:07 -080021
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
Mitch Williamsb76cdba2005-11-09 10:36:41 -080024#include <linux/kernel.h>
25#include <linux/module.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080026#include <linux/device.h>
Alexey Dobriyand43c36d2009-10-07 17:09:06 +040027#include <linux/sched.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080028#include <linux/fs.h>
29#include <linux/types.h>
30#include <linux/string.h>
31#include <linux/netdevice.h>
32#include <linux/inetdevice.h>
33#include <linux/in.h>
34#include <linux/sysfs.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080035#include <linux/ctype.h>
36#include <linux/inet.h>
37#include <linux/rtnetlink.h>
Stephen Hemminger5c5129b2009-06-12 19:02:51 +000038#include <linux/etherdevice.h>
Eric W. Biederman881d9662007-09-17 11:56:21 -070039#include <net/net_namespace.h>
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000040#include <net/netns/generic.h>
41#include <linux/nsproxy.h>
Nikolay Aleksandrov73958322013-11-05 13:51:41 +010042#include <linux/reciprocal_div.h>
Mitch Williamsb76cdba2005-11-09 10:36:41 -080043
Mitch Williamsb76cdba2005-11-09 10:36:41 -080044#include "bonding.h"
Holger Eitzenberger5a03cdb2008-12-09 23:09:22 -080045
Stephen Hemminger3d632c32009-06-12 19:02:48 +000046#define to_dev(obj) container_of(obj, struct device, kobj)
Wang Chen454d7c92008-11-12 23:37:49 -080047#define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd))))
Mitch Williamsb76cdba2005-11-09 10:36:41 -080048
Mitch Williamsb76cdba2005-11-09 10:36:41 -080049/*
50 * "show" function for the bond_masters attribute.
51 * The class parameter is ignored.
52 */
Andi Kleen28812fe2010-01-05 12:48:07 +010053static ssize_t bonding_show_bonds(struct class *cls,
54 struct class_attribute *attr,
55 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -080056{
Eric W. Biederman4c224002011-10-12 21:56:25 +000057 struct bond_net *bn =
58 container_of(attr, struct bond_net, class_attr_bonding_masters);
Mitch Williamsb76cdba2005-11-09 10:36:41 -080059 int res = 0;
60 struct bonding *bond;
61
Stephen Hemminger7e083842009-06-12 19:02:46 +000062 rtnl_lock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -080063
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000064 list_for_each_entry(bond, &bn->dev_list, bond_list) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -080065 if (res > (PAGE_SIZE - IFNAMSIZ)) {
66 /* not enough space for another interface name */
67 if ((PAGE_SIZE - res) > 10)
68 res = PAGE_SIZE - 10;
Wagner Ferencb8843662007-12-06 23:40:30 -080069 res += sprintf(buf + res, "++more++ ");
Mitch Williamsb76cdba2005-11-09 10:36:41 -080070 break;
71 }
Wagner Ferencb8843662007-12-06 23:40:30 -080072 res += sprintf(buf + res, "%s ", bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -080073 }
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -080074 if (res)
75 buf[res-1] = '\n'; /* eat the leftover space */
Stephen Hemminger7e083842009-06-12 19:02:46 +000076
77 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -080078 return res;
79}
80
Eric W. Biederman4c224002011-10-12 21:56:25 +000081static struct net_device *bond_get_by_name(struct bond_net *bn, const char *ifname)
Stephen Hemminger373500d2009-06-12 19:02:50 +000082{
83 struct bonding *bond;
84
Eric W. Biedermanec87fd32009-10-29 14:18:26 +000085 list_for_each_entry(bond, &bn->dev_list, bond_list) {
Stephen Hemminger373500d2009-06-12 19:02:50 +000086 if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
87 return bond->dev;
88 }
89 return NULL;
90}
91
Mitch Williamsb76cdba2005-11-09 10:36:41 -080092/*
93 * "store" function for the bond_masters attribute. This is what
94 * creates and deletes entire bonds.
95 *
96 * The class parameter is ignored.
97 *
98 */
99
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000100static ssize_t bonding_store_bonds(struct class *cls,
Andi Kleen28812fe2010-01-05 12:48:07 +0100101 struct class_attribute *attr,
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000102 const char *buffer, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800103{
Eric W. Biederman4c224002011-10-12 21:56:25 +0000104 struct bond_net *bn =
105 container_of(attr, struct bond_net, class_attr_bonding_masters);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800106 char command[IFNAMSIZ + 1] = {0, };
107 char *ifname;
Jay Vosburgh027ea042008-01-17 16:25:02 -0800108 int rv, res = count;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800109
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800110 sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
111 ifname = command + 1;
112 if ((strlen(command) <= 1) ||
113 !dev_valid_name(ifname))
114 goto err_no_cmd;
115
116 if (command[0] == '+') {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800117 pr_info("%s is being created...\n", ifname);
Eric W. Biederman4c224002011-10-12 21:56:25 +0000118 rv = bond_create(bn->net, ifname);
Jay Vosburgh027ea042008-01-17 16:25:02 -0800119 if (rv) {
Phil Oester5f86cad12011-03-14 06:22:06 +0000120 if (rv == -EEXIST)
121 pr_info("%s already exists.\n", ifname);
122 else
123 pr_info("%s creation failed.\n", ifname);
Jay Vosburgh027ea042008-01-17 16:25:02 -0800124 res = rv;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800125 }
Stephen Hemminger373500d2009-06-12 19:02:50 +0000126 } else if (command[0] == '-') {
127 struct net_device *bond_dev;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800128
Jay Vosburgh027ea042008-01-17 16:25:02 -0800129 rtnl_lock();
Eric W. Biederman4c224002011-10-12 21:56:25 +0000130 bond_dev = bond_get_by_name(bn, ifname);
Stephen Hemminger373500d2009-06-12 19:02:50 +0000131 if (bond_dev) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800132 pr_info("%s is being deleted...\n", ifname);
Stephen Hemminger373500d2009-06-12 19:02:50 +0000133 unregister_netdevice(bond_dev);
134 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800135 pr_err("unable to delete non-existent %s\n", ifname);
Stephen Hemminger373500d2009-06-12 19:02:50 +0000136 res = -ENODEV;
137 }
138 rtnl_unlock();
139 } else
140 goto err_no_cmd;
Jay Vosburgh027ea042008-01-17 16:25:02 -0800141
Stephen Hemminger373500d2009-06-12 19:02:50 +0000142 /* Always return either count or an error. If you return 0, you'll
143 * get called forever, which is bad.
144 */
145 return res;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800146
147err_no_cmd:
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800148 pr_err("no command found in bonding_masters. Use +ifname or -ifname.\n");
Jay Vosburghc4ebc662008-05-02 17:49:38 -0700149 return -EPERM;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800150}
Stephen Hemminger373500d2009-06-12 19:02:50 +0000151
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800152/* class attribute for bond_masters file. This ends up in /sys/class/net */
Eric W. Biederman4c224002011-10-12 21:56:25 +0000153static const struct class_attribute class_attr_bonding_masters = {
154 .attr = {
155 .name = "bonding_masters",
156 .mode = S_IWUSR | S_IRUGO,
157 },
158 .show = bonding_show_bonds,
159 .store = bonding_store_bonds,
Eric W. Biederman4c224002011-10-12 21:56:25 +0000160};
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800161
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800162/*
163 * Show the slaves in the current bond.
164 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700165static ssize_t bonding_show_slaves(struct device *d,
166 struct device_attribute *attr, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800167{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700168 struct bonding *bond = to_bond(d);
Veaceslav Falico9caff1e2013-09-25 09:20:14 +0200169 struct list_head *iter;
nikolay@redhat.comdec1e902013-08-01 16:54:47 +0200170 struct slave *slave;
171 int res = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800172
dingtianhong4d1ae5f2013-10-15 16:28:42 +0800173 if (!rtnl_trylock())
174 return restart_syscall();
175
Veaceslav Falico9caff1e2013-09-25 09:20:14 +0200176 bond_for_each_slave(bond, slave, iter) {
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800177 if (res > (PAGE_SIZE - IFNAMSIZ)) {
178 /* not enough space for another interface name */
179 if ((PAGE_SIZE - res) > 10)
180 res = PAGE_SIZE - 10;
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800181 res += sprintf(buf + res, "++more++ ");
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800182 break;
183 }
184 res += sprintf(buf + res, "%s ", slave->dev->name);
185 }
dingtianhong4d1ae5f2013-10-15 16:28:42 +0800186
187 rtnl_unlock();
188
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -0800189 if (res)
190 buf[res-1] = '\n'; /* eat the leftover space */
nikolay@redhat.comdec1e902013-08-01 16:54:47 +0200191
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800192 return res;
193}
194
195/*
Veaceslav Falicod6641cc2013-05-28 01:26:13 +0000196 * Set the slaves in the current bond.
Jiri Pirkof9f35452010-05-18 05:46:39 +0000197 * This is supposed to be only thin wrapper for bond_enslave and bond_release.
198 * All hard work should be done there.
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800199 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700200static ssize_t bonding_store_slaves(struct device *d,
201 struct device_attribute *attr,
202 const char *buffer, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800203{
204 char command[IFNAMSIZ + 1] = { 0, };
205 char *ifname;
Jiri Pirkof9f35452010-05-18 05:46:39 +0000206 int res, ret = count;
207 struct net_device *dev;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700208 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800209
Eric W. Biederman496a60c2009-05-13 17:02:50 +0000210 if (!rtnl_trylock())
211 return restart_syscall();
Jay Vosburgh027ea042008-01-17 16:25:02 -0800212
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800213 sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
214 ifname = command + 1;
215 if ((strlen(command) <= 1) ||
216 !dev_valid_name(ifname))
217 goto err_no_cmd;
218
Jiri Pirkof9f35452010-05-18 05:46:39 +0000219 dev = __dev_get_by_name(dev_net(bond->dev), ifname);
220 if (!dev) {
221 pr_info("%s: Interface %s does not exist!\n",
222 bond->dev->name, ifname);
223 ret = -ENODEV;
224 goto out;
225 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800226
Jiri Pirkof9f35452010-05-18 05:46:39 +0000227 switch (command[0]) {
228 case '+':
229 pr_info("%s: Adding slave %s.\n", bond->dev->name, dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800230 res = bond_enslave(bond->dev, dev);
Jiri Pirkof9f35452010-05-18 05:46:39 +0000231 break;
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000232
Jiri Pirkof9f35452010-05-18 05:46:39 +0000233 case '-':
234 pr_info("%s: Removing slave %s.\n", bond->dev->name, dev->name);
235 res = bond_release(bond->dev, dev);
236 break;
237
238 default:
239 goto err_no_cmd;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800240 }
241
Jiri Pirkof9f35452010-05-18 05:46:39 +0000242 if (res)
243 ret = res;
244 goto out;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800245
246err_no_cmd:
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800247 pr_err("no command found in slaves file for bond %s. Use +ifname or -ifname.\n",
248 bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800249 ret = -EPERM;
250
251out:
Jay Vosburgh027ea042008-01-17 16:25:02 -0800252 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800253 return ret;
254}
255
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000256static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves,
257 bonding_store_slaves);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800258
259/*
260 * Show and set the bonding mode. The bond interface must be down to
261 * change the mode.
262 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700263static ssize_t bonding_show_mode(struct device *d,
264 struct device_attribute *attr, char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800265{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700266 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800267
268 return sprintf(buf, "%s %d\n",
269 bond_mode_tbl[bond->params.mode].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800270 bond->params.mode);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800271}
272
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700273static ssize_t bonding_store_mode(struct device *d,
274 struct device_attribute *attr,
275 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800276{
Jiri Pirko72be35f2013-10-18 17:43:34 +0200277 int new_value, ret;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700278 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800279
Jay Vosburghece95f72008-01-17 16:25:01 -0800280 new_value = bond_parse_parm(buf, bond_mode_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800281 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800282 pr_err("%s: Ignoring invalid mode value %.*s.\n",
283 bond->dev->name, (int)strlen(buf) - 1, buf);
Jiri Pirko72be35f2013-10-18 17:43:34 +0200284 return -EINVAL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800285 }
Jiri Pirko72be35f2013-10-18 17:43:34 +0200286 if (!rtnl_trylock())
287 return restart_syscall();
288
289 ret = bond_option_mode_set(bond, new_value);
290 if (!ret) {
291 pr_info("%s: setting mode to %s (%d).\n",
292 bond->dev->name, bond_mode_tbl[new_value].modename,
293 new_value);
294 ret = count;
Andy Gospodarekc5cb0022010-07-28 15:13:56 +0000295 }
Andy Gospodarekc5cb0022010-07-28 15:13:56 +0000296
nikolay@redhat.comea6836d2013-05-18 01:18:28 +0000297 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800298 return ret;
299}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000300static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
301 bonding_show_mode, bonding_store_mode);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800302
303/*
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000304 * Show and set the bonding transmit hash method.
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800305 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700306static ssize_t bonding_show_xmit_hash(struct device *d,
307 struct device_attribute *attr,
308 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800309{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700310 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800311
Wagner Ferenc8e4b9322007-12-06 23:40:32 -0800312 return sprintf(buf, "%s %d\n",
313 xmit_hashtype_tbl[bond->params.xmit_policy].modename,
314 bond->params.xmit_policy);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800315}
316
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700317static ssize_t bonding_store_xmit_hash(struct device *d,
318 struct device_attribute *attr,
319 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800320{
321 int new_value, ret = count;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700322 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800323
Jay Vosburghece95f72008-01-17 16:25:01 -0800324 new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800325 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800326 pr_err("%s: Ignoring invalid xmit hash policy value %.*s.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800327 bond->dev->name,
328 (int)strlen(buf) - 1, buf);
329 ret = -EINVAL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800330 } else {
331 bond->params.xmit_policy = new_value;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800332 pr_info("%s: setting xmit hash policy to %s (%d).\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000333 bond->dev->name,
334 xmit_hashtype_tbl[new_value].modename, new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800335 }
Nikolay Aleksandrov53edee22013-05-24 00:59:47 +0000336
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800337 return ret;
338}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000339static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR,
340 bonding_show_xmit_hash, bonding_store_xmit_hash);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800341
342/*
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700343 * Show and set arp_validate.
344 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700345static ssize_t bonding_show_arp_validate(struct device *d,
346 struct device_attribute *attr,
347 char *buf)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700348{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700349 struct bonding *bond = to_bond(d);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700350
351 return sprintf(buf, "%s %d\n",
352 arp_validate_tbl[bond->params.arp_validate].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800353 bond->params.arp_validate);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700354}
355
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700356static ssize_t bonding_store_arp_validate(struct device *d,
357 struct device_attribute *attr,
358 const char *buf, size_t count)
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700359{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700360 struct bonding *bond = to_bond(d);
sfeldma@cumulusnetworks.com29c49482013-12-12 14:10:38 -0800361 int new_value, ret;
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700362
Jay Vosburghece95f72008-01-17 16:25:01 -0800363 new_value = bond_parse_parm(buf, arp_validate_tbl);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700364 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800365 pr_err("%s: Ignoring invalid arp_validate value %s\n",
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700366 bond->dev->name, buf);
sfeldma@cumulusnetworks.com29c49482013-12-12 14:10:38 -0800367 return -EINVAL;
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700368 }
sfeldma@cumulusnetworks.com29c49482013-12-12 14:10:38 -0800369 if (!rtnl_trylock())
370 return restart_syscall();
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700371
sfeldma@cumulusnetworks.com29c49482013-12-12 14:10:38 -0800372 ret = bond_option_arp_validate_set(bond, new_value);
373 if (!ret)
374 ret = count;
375
nikolay@redhat.com5c5038d2013-09-07 00:00:25 +0200376 rtnl_unlock();
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700377
nikolay@redhat.com5c5038d2013-09-07 00:00:25 +0200378 return ret;
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700379}
380
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000381static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate,
382 bonding_store_arp_validate);
Veaceslav Falico8599b522013-06-24 11:49:34 +0200383/*
384 * Show and set arp_all_targets.
385 */
386static ssize_t bonding_show_arp_all_targets(struct device *d,
387 struct device_attribute *attr,
388 char *buf)
389{
390 struct bonding *bond = to_bond(d);
391 int value = bond->params.arp_all_targets;
392
393 return sprintf(buf, "%s %d\n", arp_all_targets_tbl[value].modename,
394 value);
395}
396
397static ssize_t bonding_store_arp_all_targets(struct device *d,
398 struct device_attribute *attr,
399 const char *buf, size_t count)
400{
401 struct bonding *bond = to_bond(d);
402 int new_value;
403
404 new_value = bond_parse_parm(buf, arp_all_targets_tbl);
405 if (new_value < 0) {
406 pr_err("%s: Ignoring invalid arp_all_targets value %s\n",
407 bond->dev->name, buf);
408 return -EINVAL;
409 }
410 pr_info("%s: setting arp_all_targets to %s (%d).\n",
411 bond->dev->name, arp_all_targets_tbl[new_value].modename,
412 new_value);
413
414 bond->params.arp_all_targets = new_value;
415
416 return count;
417}
418
419static DEVICE_ATTR(arp_all_targets, S_IRUGO | S_IWUSR,
420 bonding_show_arp_all_targets, bonding_store_arp_all_targets);
Jay Vosburghf5b2b962006-09-22 21:54:53 -0700421
422/*
Jay Vosburghdd957c52007-10-09 19:57:24 -0700423 * Show and store fail_over_mac. User only allowed to change the
424 * value when there are no slaves.
425 */
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000426static ssize_t bonding_show_fail_over_mac(struct device *d,
427 struct device_attribute *attr,
428 char *buf)
Jay Vosburghdd957c52007-10-09 19:57:24 -0700429{
430 struct bonding *bond = to_bond(d);
431
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700432 return sprintf(buf, "%s %d\n",
433 fail_over_mac_tbl[bond->params.fail_over_mac].modename,
434 bond->params.fail_over_mac);
Jay Vosburghdd957c52007-10-09 19:57:24 -0700435}
436
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000437static ssize_t bonding_store_fail_over_mac(struct device *d,
438 struct device_attribute *attr,
439 const char *buf, size_t count)
Jay Vosburghdd957c52007-10-09 19:57:24 -0700440{
dingtianhong9402b742013-07-23 15:25:39 +0800441 int new_value, ret = count;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700442 struct bonding *bond = to_bond(d);
443
dingtianhong9402b742013-07-23 15:25:39 +0800444 if (!rtnl_trylock())
445 return restart_syscall();
446
Veaceslav Falico0965a1f2013-09-25 09:20:21 +0200447 if (bond_has_slaves(bond)) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800448 pr_err("%s: Can't alter fail_over_mac with slaves in bond.\n",
Jay Vosburghdd957c52007-10-09 19:57:24 -0700449 bond->dev->name);
dingtianhong9402b742013-07-23 15:25:39 +0800450 ret = -EPERM;
451 goto out;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700452 }
453
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700454 new_value = bond_parse_parm(buf, fail_over_mac_tbl);
455 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800456 pr_err("%s: Ignoring invalid fail_over_mac value %s.\n",
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700457 bond->dev->name, buf);
dingtianhong9402b742013-07-23 15:25:39 +0800458 ret = -EINVAL;
459 goto out;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700460 }
461
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700462 bond->params.fail_over_mac = new_value;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800463 pr_info("%s: Setting fail_over_mac to %s (%d).\n",
464 bond->dev->name, fail_over_mac_tbl[new_value].modename,
465 new_value);
Jay Vosburgh3915c1e82008-05-17 21:10:14 -0700466
dingtianhong9402b742013-07-23 15:25:39 +0800467out:
468 rtnl_unlock();
469 return ret;
Jay Vosburghdd957c52007-10-09 19:57:24 -0700470}
471
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000472static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR,
473 bonding_show_fail_over_mac, bonding_store_fail_over_mac);
Jay Vosburghdd957c52007-10-09 19:57:24 -0700474
475/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800476 * Show and set the arp timer interval. There are two tricky bits
477 * here. First, if ARP monitoring is activated, then we must disable
478 * MII monitoring. Second, if the ARP timer isn't running, we must
479 * start it.
480 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700481static ssize_t bonding_show_arp_interval(struct device *d,
482 struct device_attribute *attr,
483 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800484{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700485 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800486
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800487 return sprintf(buf, "%d\n", bond->params.arp_interval);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800488}
489
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700490static ssize_t bonding_store_arp_interval(struct device *d,
491 struct device_attribute *attr,
492 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800493{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700494 struct bonding *bond = to_bond(d);
sfeldma@cumulusnetworks.com06151db2013-12-12 14:10:24 -0800495 int new_value, ret;
496
497 if (sscanf(buf, "%d", &new_value) != 1) {
498 pr_err("%s: no arp_interval value specified.\n",
499 bond->dev->name);
500 return -EINVAL;
501 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800502
nikolay@redhat.comfbb0c412012-11-29 01:31:31 +0000503 if (!rtnl_trylock())
504 return restart_syscall();
sfeldma@cumulusnetworks.com06151db2013-12-12 14:10:24 -0800505
506 ret = bond_option_arp_interval_set(bond, new_value);
507 if (!ret)
508 ret = count;
509
nikolay@redhat.comfbb0c412012-11-29 01:31:31 +0000510 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800511 return ret;
512}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000513static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR,
514 bonding_show_arp_interval, bonding_store_arp_interval);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800515
516/*
517 * Show and set the arp targets.
518 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700519static ssize_t bonding_show_arp_targets(struct device *d,
520 struct device_attribute *attr,
521 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800522{
523 int i, res = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700524 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800525
526 for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
527 if (bond->params.arp_targets[i])
Harvey Harrison63779432008-10-31 00:56:00 -0700528 res += sprintf(buf + res, "%pI4 ",
529 &bond->params.arp_targets[i]);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800530 }
Wagner Ferenc1dcdcd62007-12-06 23:40:31 -0800531 if (res)
532 buf[res-1] = '\n'; /* eat the leftover space */
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800533 return res;
534}
535
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700536static ssize_t bonding_store_arp_targets(struct device *d,
537 struct device_attribute *attr,
538 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800539{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700540 struct bonding *bond = to_bond(d);
sfeldma@cumulusnetworks.com7f28fa12013-12-12 14:10:31 -0800541 __be32 target;
542 int ret = -EPERM;
543
544 if (!in4_pton(buf + 1, -1, (u8 *)&target, -1, NULL)) {
545 pr_err("%s: invalid ARP target %pI4 specified\n",
546 bond->dev->name, &target);
547 return -EPERM;
548 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800549
dingtianhong4d1ae5f2013-10-15 16:28:42 +0800550 if (!rtnl_trylock())
551 return restart_syscall();
552
sfeldma@cumulusnetworks.com7f28fa12013-12-12 14:10:31 -0800553 if (buf[0] == '+')
554 ret = bond_option_arp_ip_target_add(bond, target);
555 else if (buf[0] == '-')
556 ret = bond_option_arp_ip_target_rem(bond, target);
557 else
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800558 pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
559 bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800560
sfeldma@cumulusnetworks.com7f28fa12013-12-12 14:10:31 -0800561 if (!ret)
562 ret = count;
563
dingtianhong4d1ae5f2013-10-15 16:28:42 +0800564 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800565 return ret;
566}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700567static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800568
569/*
570 * Show and set the up and down delays. These must be multiples of the
571 * MII monitoring value, and are stored internally as the multiplier.
572 * Thus, we must translate to MS for the real world.
573 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700574static ssize_t bonding_show_downdelay(struct device *d,
575 struct device_attribute *attr,
576 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800577{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700578 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800579
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800580 return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800581}
582
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700583static ssize_t bonding_store_downdelay(struct device *d,
584 struct device_attribute *attr,
585 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800586{
sfeldma@cumulusnetworks.comc7461f92013-12-12 14:10:09 -0800587 int new_value, ret;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700588 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800589
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800590 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800591 pr_err("%s: no down delay value specified.\n", bond->dev->name);
sfeldma@cumulusnetworks.comc7461f92013-12-12 14:10:09 -0800592 return -EINVAL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800593 }
594
sfeldma@cumulusnetworks.comc7461f92013-12-12 14:10:09 -0800595 if (!rtnl_trylock())
596 return restart_syscall();
597
598 ret = bond_option_downdelay_set(bond, new_value);
599 if (!ret)
600 ret = count;
601
Nikolay Aleksandrovb869ccf2013-11-13 17:07:46 +0100602 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800603 return ret;
604}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000605static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR,
606 bonding_show_downdelay, bonding_store_downdelay);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800607
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700608static ssize_t bonding_show_updelay(struct device *d,
609 struct device_attribute *attr,
610 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800611{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700612 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800613
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800614 return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800615
616}
617
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700618static ssize_t bonding_store_updelay(struct device *d,
619 struct device_attribute *attr,
620 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800621{
sfeldma@cumulusnetworks.com25852e22013-12-12 14:10:02 -0800622 int new_value, ret;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700623 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800624
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800625 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800626 pr_err("%s: no up delay value specified.\n",
sfeldma@cumulusnetworks.com25852e22013-12-12 14:10:02 -0800627 bond->dev->name);
628 return -EINVAL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800629 }
630
sfeldma@cumulusnetworks.com25852e22013-12-12 14:10:02 -0800631 if (!rtnl_trylock())
632 return restart_syscall();
633
634 ret = bond_option_updelay_set(bond, new_value);
635 if (!ret)
636 ret = count;
637
Nikolay Aleksandrovb869ccf2013-11-13 17:07:46 +0100638 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800639 return ret;
640}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000641static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR,
642 bonding_show_updelay, bonding_store_updelay);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800643
644/*
645 * Show and set the LACP interval. Interface must be down, and the mode
646 * must be set to 802.3ad mode.
647 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700648static ssize_t bonding_show_lacp(struct device *d,
649 struct device_attribute *attr,
650 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800651{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700652 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800653
654 return sprintf(buf, "%s %d\n",
655 bond_lacp_tbl[bond->params.lacp_fast].modename,
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800656 bond->params.lacp_fast);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800657}
658
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700659static ssize_t bonding_store_lacp(struct device *d,
660 struct device_attribute *attr,
661 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800662{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700663 struct bonding *bond = to_bond(d);
nikolay@redhat.comc5093162013-09-02 13:51:40 +0200664 int new_value, ret = count;
665
666 if (!rtnl_trylock())
667 return restart_syscall();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800668
669 if (bond->dev->flags & IFF_UP) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800670 pr_err("%s: Unable to update LACP rate because interface is up.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800671 bond->dev->name);
672 ret = -EPERM;
673 goto out;
674 }
675
676 if (bond->params.mode != BOND_MODE_8023AD) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800677 pr_err("%s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800678 bond->dev->name);
679 ret = -EPERM;
680 goto out;
681 }
682
Jay Vosburghece95f72008-01-17 16:25:01 -0800683 new_value = bond_parse_parm(buf, bond_lacp_tbl);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800684
685 if ((new_value == 1) || (new_value == 0)) {
686 bond->params.lacp_fast = new_value;
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +0000687 bond_3ad_update_lacp_rate(bond);
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800688 pr_info("%s: Setting LACP rate to %s (%d).\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000689 bond->dev->name, bond_lacp_tbl[new_value].modename,
690 new_value);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800691 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800692 pr_err("%s: Ignoring invalid LACP rate value %.*s.\n",
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000693 bond->dev->name, (int)strlen(buf) - 1, buf);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800694 ret = -EINVAL;
695 }
696out:
nikolay@redhat.comc5093162013-09-02 13:51:40 +0200697 rtnl_unlock();
698
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800699 return ret;
700}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000701static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR,
702 bonding_show_lacp, bonding_store_lacp);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800703
stephen hemminger655f8912011-06-22 09:54:39 +0000704static ssize_t bonding_show_min_links(struct device *d,
705 struct device_attribute *attr,
706 char *buf)
707{
708 struct bonding *bond = to_bond(d);
709
710 return sprintf(buf, "%d\n", bond->params.min_links);
711}
712
713static ssize_t bonding_store_min_links(struct device *d,
714 struct device_attribute *attr,
715 const char *buf, size_t count)
716{
717 struct bonding *bond = to_bond(d);
718 int ret;
719 unsigned int new_value;
720
721 ret = kstrtouint(buf, 0, &new_value);
722 if (ret < 0) {
723 pr_err("%s: Ignoring invalid min links value %s.\n",
724 bond->dev->name, buf);
725 return ret;
726 }
727
728 pr_info("%s: Setting min links value to %u\n",
729 bond->dev->name, new_value);
730 bond->params.min_links = new_value;
731 return count;
732}
733static DEVICE_ATTR(min_links, S_IRUGO | S_IWUSR,
734 bonding_show_min_links, bonding_store_min_links);
735
Jay Vosburghfd989c82008-11-04 17:51:16 -0800736static ssize_t bonding_show_ad_select(struct device *d,
737 struct device_attribute *attr,
738 char *buf)
739{
740 struct bonding *bond = to_bond(d);
741
742 return sprintf(buf, "%s %d\n",
743 ad_select_tbl[bond->params.ad_select].modename,
744 bond->params.ad_select);
745}
746
747
748static ssize_t bonding_store_ad_select(struct device *d,
749 struct device_attribute *attr,
750 const char *buf, size_t count)
751{
752 int new_value, ret = count;
753 struct bonding *bond = to_bond(d);
754
755 if (bond->dev->flags & IFF_UP) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800756 pr_err("%s: Unable to update ad_select because interface is up.\n",
757 bond->dev->name);
Jay Vosburghfd989c82008-11-04 17:51:16 -0800758 ret = -EPERM;
759 goto out;
760 }
761
762 new_value = bond_parse_parm(buf, ad_select_tbl);
763
764 if (new_value != -1) {
765 bond->params.ad_select = new_value;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800766 pr_info("%s: Setting ad_select to %s (%d).\n",
767 bond->dev->name, ad_select_tbl[new_value].modename,
768 new_value);
Jay Vosburghfd989c82008-11-04 17:51:16 -0800769 } else {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800770 pr_err("%s: Ignoring invalid ad_select value %.*s.\n",
Jay Vosburghfd989c82008-11-04 17:51:16 -0800771 bond->dev->name, (int)strlen(buf) - 1, buf);
772 ret = -EINVAL;
773 }
774out:
775 return ret;
776}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000777static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR,
778 bonding_show_ad_select, bonding_store_ad_select);
Jay Vosburghfd989c82008-11-04 17:51:16 -0800779
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800780/*
Ben Hutchingsad246c92011-04-26 15:25:52 +0000781 * Show and set the number of peer notifications to send after a failover event.
782 */
783static ssize_t bonding_show_num_peer_notif(struct device *d,
784 struct device_attribute *attr,
785 char *buf)
786{
787 struct bonding *bond = to_bond(d);
788 return sprintf(buf, "%d\n", bond->params.num_peer_notif);
789}
790
791static ssize_t bonding_store_num_peer_notif(struct device *d,
792 struct device_attribute *attr,
793 const char *buf, size_t count)
794{
795 struct bonding *bond = to_bond(d);
796 int err = kstrtou8(buf, 10, &bond->params.num_peer_notif);
797 return err ? err : count;
798}
799static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR,
800 bonding_show_num_peer_notif, bonding_store_num_peer_notif);
801static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR,
802 bonding_show_num_peer_notif, bonding_store_num_peer_notif);
803
804/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800805 * Show and set the MII monitor interval. There are two tricky bits
806 * here. First, if MII monitoring is activated, then we must disable
807 * ARP monitoring. Second, if the timer isn't running, we must
808 * start it.
809 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700810static ssize_t bonding_show_miimon(struct device *d,
811 struct device_attribute *attr,
812 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800813{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700814 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800815
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800816 return sprintf(buf, "%d\n", bond->params.miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800817}
818
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700819static ssize_t bonding_store_miimon(struct device *d,
820 struct device_attribute *attr,
821 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800822{
sfeldma@cumulusnetworks.comeecdaa62013-12-12 14:09:55 -0800823 int new_value, ret;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700824 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800825
826 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800827 pr_err("%s: no miimon value specified.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800828 bond->dev->name);
sfeldma@cumulusnetworks.comeecdaa62013-12-12 14:09:55 -0800829 return -EINVAL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800830 }
sfeldma@cumulusnetworks.comeecdaa62013-12-12 14:09:55 -0800831
832 if (!rtnl_trylock())
833 return restart_syscall();
834
835 ret = bond_option_miimon_set(bond, new_value);
836 if (!ret)
837 ret = count;
838
nikolay@redhat.comfbb0c412012-11-29 01:31:31 +0000839 rtnl_unlock();
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800840 return ret;
841}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000842static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR,
843 bonding_show_miimon, bonding_store_miimon);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800844
845/*
846 * Show and set the primary slave. The store function is much
847 * simpler than bonding_store_slaves function because it only needs to
848 * handle one interface name.
849 * The bond must be a mode that supports a primary for this be
850 * set.
851 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700852static ssize_t bonding_show_primary(struct device *d,
853 struct device_attribute *attr,
854 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800855{
856 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700857 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800858
859 if (bond->primary_slave)
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800860 count = sprintf(buf, "%s\n", bond->primary_slave->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800861
862 return count;
863}
864
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700865static ssize_t bonding_store_primary(struct device *d,
866 struct device_attribute *attr,
867 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800868{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700869 struct bonding *bond = to_bond(d);
Veaceslav Falico9caff1e2013-09-25 09:20:14 +0200870 struct list_head *iter;
Andy Gospodarekf4bb2e92011-07-26 11:12:27 +0000871 char ifname[IFNAMSIZ];
nikolay@redhat.comdec1e902013-08-01 16:54:47 +0200872 struct slave *slave;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800873
Eric W. Biederman496a60c2009-05-13 17:02:50 +0000874 if (!rtnl_trylock())
875 return restart_syscall();
Neil Hormane843fa52010-10-13 16:01:50 +0000876 block_netpoll_tx();
Jay Vosburghe934dd72008-01-17 16:24:57 -0800877 read_lock(&bond->lock);
878 write_lock_bh(&bond->curr_slave_lock);
879
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800880 if (!USES_PRIMARY(bond->params.mode)) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800881 pr_info("%s: Unable to set primary slave; %s is in mode %d\n",
882 bond->dev->name, bond->dev->name, bond->params.mode);
Andy Gospodarekf4bb2e92011-07-26 11:12:27 +0000883 goto out;
884 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800885
nikolay@redhat.comeb6e98a2012-10-31 04:42:51 +0000886 sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800887
Andy Gospodarekf4bb2e92011-07-26 11:12:27 +0000888 /* check to see if we are clearing primary */
889 if (!strlen(ifname) || buf[0] == '\n') {
890 pr_info("%s: Setting primary slave to None.\n",
891 bond->dev->name);
892 bond->primary_slave = NULL;
Milos Vyleteleb492f72013-01-29 09:59:00 +0000893 memset(bond->params.primary, 0, sizeof(bond->params.primary));
Andy Gospodarekf4bb2e92011-07-26 11:12:27 +0000894 bond_select_active_slave(bond);
895 goto out;
896 }
897
Veaceslav Falico9caff1e2013-09-25 09:20:14 +0200898 bond_for_each_slave(bond, slave, iter) {
Andy Gospodarekf4bb2e92011-07-26 11:12:27 +0000899 if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
900 pr_info("%s: Setting %s as primary slave.\n",
901 bond->dev->name, slave->dev->name);
902 bond->primary_slave = slave;
903 strcpy(bond->params.primary, slave->dev->name);
904 bond_select_active_slave(bond);
905 goto out;
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800906 }
907 }
Andy Gospodarekf4bb2e92011-07-26 11:12:27 +0000908
Weiping Pan8a936642012-06-10 23:00:20 +0000909 strncpy(bond->params.primary, ifname, IFNAMSIZ);
910 bond->params.primary[IFNAMSIZ - 1] = 0;
911
912 pr_info("%s: Recording %s as primary, "
913 "but it has not been enslaved to %s yet.\n",
914 bond->dev->name, ifname, bond->dev->name);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800915out:
Jay Vosburghe934dd72008-01-17 16:24:57 -0800916 write_unlock_bh(&bond->curr_slave_lock);
917 read_unlock(&bond->lock);
Neil Hormane843fa52010-10-13 16:01:50 +0000918 unblock_netpoll_tx();
Jay Vosburgh6603a6f2007-10-17 17:37:50 -0700919 rtnl_unlock();
920
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800921 return count;
922}
Stephen Hemminger3d632c32009-06-12 19:02:48 +0000923static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR,
924 bonding_show_primary, bonding_store_primary);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800925
926/*
Jiri Pirkoa5499522009-09-25 03:28:09 +0000927 * Show and set the primary_reselect flag.
928 */
929static ssize_t bonding_show_primary_reselect(struct device *d,
930 struct device_attribute *attr,
931 char *buf)
932{
933 struct bonding *bond = to_bond(d);
934
935 return sprintf(buf, "%s %d\n",
936 pri_reselect_tbl[bond->params.primary_reselect].modename,
937 bond->params.primary_reselect);
938}
939
940static ssize_t bonding_store_primary_reselect(struct device *d,
941 struct device_attribute *attr,
942 const char *buf, size_t count)
943{
944 int new_value, ret = count;
945 struct bonding *bond = to_bond(d);
946
947 if (!rtnl_trylock())
948 return restart_syscall();
949
950 new_value = bond_parse_parm(buf, pri_reselect_tbl);
951 if (new_value < 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800952 pr_err("%s: Ignoring invalid primary_reselect value %.*s.\n",
Jiri Pirkoa5499522009-09-25 03:28:09 +0000953 bond->dev->name,
954 (int) strlen(buf) - 1, buf);
955 ret = -EINVAL;
956 goto out;
957 }
958
959 bond->params.primary_reselect = new_value;
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800960 pr_info("%s: setting primary_reselect to %s (%d).\n",
Jiri Pirkoa5499522009-09-25 03:28:09 +0000961 bond->dev->name, pri_reselect_tbl[new_value].modename,
962 new_value);
963
Neil Hormane843fa52010-10-13 16:01:50 +0000964 block_netpoll_tx();
Jiri Pirkoa5499522009-09-25 03:28:09 +0000965 read_lock(&bond->lock);
966 write_lock_bh(&bond->curr_slave_lock);
967 bond_select_active_slave(bond);
968 write_unlock_bh(&bond->curr_slave_lock);
969 read_unlock(&bond->lock);
Neil Hormane843fa52010-10-13 16:01:50 +0000970 unblock_netpoll_tx();
Jiri Pirkoa5499522009-09-25 03:28:09 +0000971out:
972 rtnl_unlock();
973 return ret;
974}
975static DEVICE_ATTR(primary_reselect, S_IRUGO | S_IWUSR,
976 bonding_show_primary_reselect,
977 bonding_store_primary_reselect);
978
979/*
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800980 * Show and set the use_carrier flag.
981 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700982static ssize_t bonding_show_carrier(struct device *d,
983 struct device_attribute *attr,
984 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800985{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700986 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800987
Wagner Ferenc7bd46502007-12-06 23:40:28 -0800988 return sprintf(buf, "%d\n", bond->params.use_carrier);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800989}
990
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700991static ssize_t bonding_store_carrier(struct device *d,
992 struct device_attribute *attr,
993 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800994{
sfeldma@cumulusnetworks.com9f53e142013-12-12 14:10:16 -0800995 int new_value, ret;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -0700996 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800997
Mitch Williamsb76cdba2005-11-09 10:36:41 -0800998 if (sscanf(buf, "%d", &new_value) != 1) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800999 pr_err("%s: no use_carrier value specified.\n",
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001000 bond->dev->name);
sfeldma@cumulusnetworks.com9f53e142013-12-12 14:10:16 -08001001 return -EINVAL;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001002 }
sfeldma@cumulusnetworks.com9f53e142013-12-12 14:10:16 -08001003
1004 if (!rtnl_trylock())
1005 return restart_syscall();
1006
1007 ret = bond_option_use_carrier_set(bond, new_value);
1008 if (!ret)
1009 ret = count;
1010
1011 rtnl_unlock();
Jiri Pirko672bda32011-01-25 11:03:25 +00001012 return ret;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001013}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001014static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR,
1015 bonding_show_carrier, bonding_store_carrier);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001016
1017
1018/*
1019 * Show and set currently active_slave.
1020 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001021static ssize_t bonding_show_active_slave(struct device *d,
1022 struct device_attribute *attr,
1023 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001024{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001025 struct bonding *bond = to_bond(d);
Jiri Pirko752d48b2013-10-18 17:43:37 +02001026 struct net_device *slave_dev;
Wagner Ferenc16cd0162007-12-06 23:40:29 -08001027 int count = 0;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001028
nikolay@redhat.com278b2082013-08-01 16:54:51 +02001029 rcu_read_lock();
Jiri Pirko752d48b2013-10-18 17:43:37 +02001030 slave_dev = bond_option_active_slave_get_rcu(bond);
1031 if (slave_dev)
1032 count = sprintf(buf, "%s\n", slave_dev->name);
nikolay@redhat.com278b2082013-08-01 16:54:51 +02001033 rcu_read_unlock();
1034
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001035 return count;
1036}
1037
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001038static ssize_t bonding_store_active_slave(struct device *d,
1039 struct device_attribute *attr,
1040 const char *buf, size_t count)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001041{
Jiri Pirkod9e32b22013-10-18 17:43:35 +02001042 int ret;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001043 struct bonding *bond = to_bond(d);
Andy Gospodarekf4bb2e92011-07-26 11:12:27 +00001044 char ifname[IFNAMSIZ];
Jiri Pirkod9e32b22013-10-18 17:43:35 +02001045 struct net_device *dev;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001046
Eric W. Biederman496a60c2009-05-13 17:02:50 +00001047 if (!rtnl_trylock())
1048 return restart_syscall();
Neil Hormane843fa52010-10-13 16:01:50 +00001049
nikolay@redhat.comc84e1592012-10-31 06:03:52 +00001050 sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
Andy Gospodarekf4bb2e92011-07-26 11:12:27 +00001051 if (!strlen(ifname) || buf[0] == '\n') {
Jiri Pirkod9e32b22013-10-18 17:43:35 +02001052 dev = NULL;
1053 } else {
1054 dev = __dev_get_by_name(dev_net(bond->dev), ifname);
1055 if (!dev) {
1056 ret = -ENODEV;
1057 goto out;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001058 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001059 }
Andy Gospodarekf4bb2e92011-07-26 11:12:27 +00001060
Jiri Pirkod9e32b22013-10-18 17:43:35 +02001061 ret = bond_option_active_slave_set(bond, dev);
1062 if (!ret)
1063 ret = count;
Neil Hormane843fa52010-10-13 16:01:50 +00001064
Jiri Pirkod9e32b22013-10-18 17:43:35 +02001065 out:
Jay Vosburgh6603a6f2007-10-17 17:37:50 -07001066 rtnl_unlock();
1067
Jiri Pirkod9e32b22013-10-18 17:43:35 +02001068 return ret;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001069
1070}
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001071static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR,
1072 bonding_show_active_slave, bonding_store_active_slave);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001073
1074
1075/*
1076 * Show link status of the bond interface.
1077 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001078static ssize_t bonding_show_mii_status(struct device *d,
1079 struct device_attribute *attr,
1080 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001081{
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001082 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001083
nikolay@redhat.com278b2082013-08-01 16:54:51 +02001084 return sprintf(buf, "%s\n", bond->curr_active_slave ? "up" : "down");
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001085}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001086static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001087
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001088/*
1089 * Show current 802.3ad aggregator ID.
1090 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001091static ssize_t bonding_show_ad_aggregator(struct device *d,
1092 struct device_attribute *attr,
1093 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001094{
1095 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001096 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001097
1098 if (bond->params.mode == BOND_MODE_8023AD) {
1099 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001100 count = sprintf(buf, "%d\n",
nikolay@redhat.com318debd2013-05-18 01:18:31 +00001101 bond_3ad_get_active_agg_info(bond, &ad_info)
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001102 ? 0 : ad_info.aggregator_id);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001103 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001104
1105 return count;
1106}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001107static DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001108
1109
1110/*
1111 * Show number of active 802.3ad ports.
1112 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001113static ssize_t bonding_show_ad_num_ports(struct device *d,
1114 struct device_attribute *attr,
1115 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001116{
1117 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001118 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001119
1120 if (bond->params.mode == BOND_MODE_8023AD) {
1121 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001122 count = sprintf(buf, "%d\n",
nikolay@redhat.com318debd2013-05-18 01:18:31 +00001123 bond_3ad_get_active_agg_info(bond, &ad_info)
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001124 ? 0 : ad_info.ports);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001125 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001126
1127 return count;
1128}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001129static DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001130
1131
1132/*
1133 * Show current 802.3ad actor key.
1134 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001135static ssize_t bonding_show_ad_actor_key(struct device *d,
1136 struct device_attribute *attr,
1137 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001138{
1139 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001140 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001141
1142 if (bond->params.mode == BOND_MODE_8023AD) {
1143 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001144 count = sprintf(buf, "%d\n",
nikolay@redhat.com318debd2013-05-18 01:18:31 +00001145 bond_3ad_get_active_agg_info(bond, &ad_info)
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001146 ? 0 : ad_info.actor_key);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001147 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001148
1149 return count;
1150}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001151static DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001152
1153
1154/*
1155 * Show current 802.3ad partner key.
1156 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001157static ssize_t bonding_show_ad_partner_key(struct device *d,
1158 struct device_attribute *attr,
1159 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001160{
1161 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001162 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001163
1164 if (bond->params.mode == BOND_MODE_8023AD) {
1165 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001166 count = sprintf(buf, "%d\n",
nikolay@redhat.com318debd2013-05-18 01:18:31 +00001167 bond_3ad_get_active_agg_info(bond, &ad_info)
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001168 ? 0 : ad_info.partner_key);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001169 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001170
1171 return count;
1172}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001173static DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001174
1175
1176/*
1177 * Show current 802.3ad partner mac.
1178 */
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001179static ssize_t bonding_show_ad_partner_mac(struct device *d,
1180 struct device_attribute *attr,
1181 char *buf)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001182{
1183 int count = 0;
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001184 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001185
1186 if (bond->params.mode == BOND_MODE_8023AD) {
1187 struct ad_info ad_info;
Stephen Hemminger3d632c32009-06-12 19:02:48 +00001188 if (!bond_3ad_get_active_agg_info(bond, &ad_info))
Johannes Berge1749612008-10-27 15:59:26 -07001189 count = sprintf(buf, "%pM\n", ad_info.partner_system);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001190 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001191
1192 return count;
1193}
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001194static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001195
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001196/*
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001197 * Show the queue_ids of the slaves in the current bond.
1198 */
1199static ssize_t bonding_show_queue_id(struct device *d,
1200 struct device_attribute *attr,
1201 char *buf)
1202{
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001203 struct bonding *bond = to_bond(d);
Veaceslav Falico9caff1e2013-09-25 09:20:14 +02001204 struct list_head *iter;
nikolay@redhat.comdec1e902013-08-01 16:54:47 +02001205 struct slave *slave;
1206 int res = 0;
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001207
1208 if (!rtnl_trylock())
1209 return restart_syscall();
1210
Veaceslav Falico9caff1e2013-09-25 09:20:14 +02001211 bond_for_each_slave(bond, slave, iter) {
Nicolas de Pesloüan79236682010-07-14 18:24:54 -07001212 if (res > (PAGE_SIZE - IFNAMSIZ - 6)) {
1213 /* not enough space for another interface_name:queue_id pair */
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001214 if ((PAGE_SIZE - res) > 10)
1215 res = PAGE_SIZE - 10;
1216 res += sprintf(buf + res, "++more++ ");
1217 break;
1218 }
1219 res += sprintf(buf + res, "%s:%d ",
1220 slave->dev->name, slave->queue_id);
1221 }
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001222 if (res)
1223 buf[res-1] = '\n'; /* eat the leftover space */
dingtianhong4d1ae5f2013-10-15 16:28:42 +08001224
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001225 rtnl_unlock();
nikolay@redhat.comdec1e902013-08-01 16:54:47 +02001226
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001227 return res;
1228}
1229
1230/*
1231 * Set the queue_ids of the slaves in the current bond. The bond
1232 * interface must be enslaved for this to work.
1233 */
1234static ssize_t bonding_store_queue_id(struct device *d,
1235 struct device_attribute *attr,
1236 const char *buffer, size_t count)
1237{
1238 struct slave *slave, *update_slave;
1239 struct bonding *bond = to_bond(d);
Veaceslav Falico9caff1e2013-09-25 09:20:14 +02001240 struct list_head *iter;
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001241 u16 qid;
nikolay@redhat.comdec1e902013-08-01 16:54:47 +02001242 int ret = count;
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001243 char *delim;
1244 struct net_device *sdev = NULL;
1245
1246 if (!rtnl_trylock())
1247 return restart_syscall();
1248
1249 /* delim will point to queue id if successful */
1250 delim = strchr(buffer, ':');
1251 if (!delim)
1252 goto err_no_cmd;
1253
1254 /*
1255 * Terminate string that points to device name and bump it
1256 * up one, so we can read the queue id there.
1257 */
1258 *delim = '\0';
1259 if (sscanf(++delim, "%hd\n", &qid) != 1)
1260 goto err_no_cmd;
1261
1262 /* Check buffer length, valid ifname and queue id */
1263 if (strlen(buffer) > IFNAMSIZ ||
1264 !dev_valid_name(buffer) ||
Jiri Pirko8a540ff2012-07-20 02:28:50 +00001265 qid > bond->dev->real_num_tx_queues)
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001266 goto err_no_cmd;
1267
1268 /* Get the pointer to that interface if it exists */
1269 sdev = __dev_get_by_name(dev_net(bond->dev), buffer);
1270 if (!sdev)
1271 goto err_no_cmd;
1272
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001273 /* Search for thes slave and check for duplicate qids */
1274 update_slave = NULL;
Veaceslav Falico9caff1e2013-09-25 09:20:14 +02001275 bond_for_each_slave(bond, slave, iter) {
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001276 if (sdev == slave->dev)
1277 /*
1278 * We don't need to check the matching
1279 * slave for dups, since we're overwriting it
1280 */
1281 update_slave = slave;
1282 else if (qid && qid == slave->queue_id) {
dingtianhong4d1ae5f2013-10-15 16:28:42 +08001283 goto err_no_cmd;
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001284 }
1285 }
1286
1287 if (!update_slave)
dingtianhong4d1ae5f2013-10-15 16:28:42 +08001288 goto err_no_cmd;
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001289
1290 /* Actually set the qids for the slave */
1291 update_slave->queue_id = qid;
1292
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001293out:
1294 rtnl_unlock();
1295 return ret;
1296
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001297err_no_cmd:
1298 pr_info("invalid input for queue_id set for %s.\n",
1299 bond->dev->name);
1300 ret = -EPERM;
1301 goto out;
1302}
1303
1304static DEVICE_ATTR(queue_id, S_IRUGO | S_IWUSR, bonding_show_queue_id,
1305 bonding_store_queue_id);
1306
1307
1308/*
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001309 * Show and set the all_slaves_active flag.
1310 */
1311static ssize_t bonding_show_slaves_active(struct device *d,
1312 struct device_attribute *attr,
1313 char *buf)
1314{
1315 struct bonding *bond = to_bond(d);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001316
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001317 return sprintf(buf, "%d\n", bond->params.all_slaves_active);
1318}
1319
1320static ssize_t bonding_store_slaves_active(struct device *d,
1321 struct device_attribute *attr,
1322 const char *buf, size_t count)
1323{
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001324 struct bonding *bond = to_bond(d);
nikolay@redhat.comdec1e902013-08-01 16:54:47 +02001325 int new_value, ret = count;
Veaceslav Falico9caff1e2013-09-25 09:20:14 +02001326 struct list_head *iter;
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001327 struct slave *slave;
1328
dingtianhong4d1ae5f2013-10-15 16:28:42 +08001329 if (!rtnl_trylock())
1330 return restart_syscall();
1331
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001332 if (sscanf(buf, "%d", &new_value) != 1) {
1333 pr_err("%s: no all_slaves_active value specified.\n",
1334 bond->dev->name);
1335 ret = -EINVAL;
1336 goto out;
1337 }
1338
1339 if (new_value == bond->params.all_slaves_active)
1340 goto out;
1341
1342 if ((new_value == 0) || (new_value == 1)) {
1343 bond->params.all_slaves_active = new_value;
1344 } else {
1345 pr_info("%s: Ignoring invalid all_slaves_active value %d.\n",
1346 bond->dev->name, new_value);
1347 ret = -EINVAL;
1348 goto out;
1349 }
1350
Veaceslav Falico9caff1e2013-09-25 09:20:14 +02001351 bond_for_each_slave(bond, slave, iter) {
Jiri Pirkoe30bc062011-03-12 03:14:37 +00001352 if (!bond_is_active_slave(slave)) {
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001353 if (new_value)
Jiri Pirko2d7011c2011-03-16 08:46:43 +00001354 slave->inactive = 0;
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001355 else
Jiri Pirko2d7011c2011-03-16 08:46:43 +00001356 slave->inactive = 1;
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001357 }
1358 }
1359out:
dingtianhong4d1ae5f2013-10-15 16:28:42 +08001360 rtnl_unlock();
Jiri Pirko672bda32011-01-25 11:03:25 +00001361 return ret;
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001362}
1363static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR,
1364 bonding_show_slaves_active, bonding_store_slaves_active);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001365
Flavio Leitnerc2952c32010-10-05 14:23:59 +00001366/*
1367 * Show and set the number of IGMP membership reports to send on link failure
1368 */
1369static ssize_t bonding_show_resend_igmp(struct device *d,
Flavio Leitner94265cf2011-05-25 08:38:58 +00001370 struct device_attribute *attr,
1371 char *buf)
Flavio Leitnerc2952c32010-10-05 14:23:59 +00001372{
1373 struct bonding *bond = to_bond(d);
1374
1375 return sprintf(buf, "%d\n", bond->params.resend_igmp);
1376}
1377
1378static ssize_t bonding_store_resend_igmp(struct device *d,
Flavio Leitner94265cf2011-05-25 08:38:58 +00001379 struct device_attribute *attr,
1380 const char *buf, size_t count)
Flavio Leitnerc2952c32010-10-05 14:23:59 +00001381{
1382 int new_value, ret = count;
1383 struct bonding *bond = to_bond(d);
1384
1385 if (sscanf(buf, "%d", &new_value) != 1) {
1386 pr_err("%s: no resend_igmp value specified.\n",
1387 bond->dev->name);
1388 ret = -EINVAL;
1389 goto out;
1390 }
1391
Flavio Leitner94265cf2011-05-25 08:38:58 +00001392 if (new_value < 0 || new_value > 255) {
Flavio Leitnerc2952c32010-10-05 14:23:59 +00001393 pr_err("%s: Invalid resend_igmp value %d not in range 0-255; rejected.\n",
1394 bond->dev->name, new_value);
1395 ret = -EINVAL;
1396 goto out;
1397 }
1398
1399 pr_info("%s: Setting resend_igmp to %d.\n",
1400 bond->dev->name, new_value);
1401 bond->params.resend_igmp = new_value;
1402out:
1403 return ret;
1404}
1405
1406static DEVICE_ATTR(resend_igmp, S_IRUGO | S_IWUSR,
1407 bonding_show_resend_igmp, bonding_store_resend_igmp);
1408
Neil Horman7eacd032013-09-13 11:05:33 -04001409
1410static ssize_t bonding_show_lp_interval(struct device *d,
1411 struct device_attribute *attr,
1412 char *buf)
1413{
1414 struct bonding *bond = to_bond(d);
1415 return sprintf(buf, "%d\n", bond->params.lp_interval);
1416}
1417
1418static ssize_t bonding_store_lp_interval(struct device *d,
1419 struct device_attribute *attr,
1420 const char *buf, size_t count)
1421{
1422 struct bonding *bond = to_bond(d);
1423 int new_value, ret = count;
1424
1425 if (sscanf(buf, "%d", &new_value) != 1) {
1426 pr_err("%s: no lp interval value specified.\n",
1427 bond->dev->name);
1428 ret = -EINVAL;
1429 goto out;
1430 }
1431
1432 if (new_value <= 0) {
1433 pr_err ("%s: lp_interval must be between 1 and %d\n",
1434 bond->dev->name, INT_MAX);
1435 ret = -EINVAL;
1436 goto out;
1437 }
1438
1439 bond->params.lp_interval = new_value;
1440out:
1441 return ret;
1442}
1443
1444static DEVICE_ATTR(lp_interval, S_IRUGO | S_IWUSR,
1445 bonding_show_lp_interval, bonding_store_lp_interval);
1446
Nikolay Aleksandrov73958322013-11-05 13:51:41 +01001447static ssize_t bonding_show_packets_per_slave(struct device *d,
1448 struct device_attribute *attr,
1449 char *buf)
1450{
1451 struct bonding *bond = to_bond(d);
Nikolay Aleksandrova752a8b2013-12-05 11:36:58 +01001452 unsigned int packets_per_slave = bond->params.packets_per_slave;
Nikolay Aleksandrov73958322013-11-05 13:51:41 +01001453
1454 if (packets_per_slave > 1)
1455 packets_per_slave = reciprocal_value(packets_per_slave);
1456
Nikolay Aleksandrova752a8b2013-12-05 11:36:58 +01001457 return sprintf(buf, "%u\n", packets_per_slave);
Nikolay Aleksandrov73958322013-11-05 13:51:41 +01001458}
1459
1460static ssize_t bonding_store_packets_per_slave(struct device *d,
1461 struct device_attribute *attr,
1462 const char *buf, size_t count)
1463{
1464 struct bonding *bond = to_bond(d);
1465 int new_value, ret = count;
1466
1467 if (sscanf(buf, "%d", &new_value) != 1) {
1468 pr_err("%s: no packets_per_slave value specified.\n",
1469 bond->dev->name);
1470 ret = -EINVAL;
1471 goto out;
1472 }
1473 if (new_value < 0 || new_value > USHRT_MAX) {
1474 pr_err("%s: packets_per_slave must be between 0 and %u\n",
1475 bond->dev->name, USHRT_MAX);
1476 ret = -EINVAL;
1477 goto out;
1478 }
1479 if (bond->params.mode != BOND_MODE_ROUNDROBIN)
1480 pr_warn("%s: Warning: packets_per_slave has effect only in balance-rr mode\n",
1481 bond->dev->name);
1482 if (new_value > 1)
1483 bond->params.packets_per_slave = reciprocal_value(new_value);
1484 else
1485 bond->params.packets_per_slave = new_value;
1486out:
1487 return ret;
1488}
1489
1490static DEVICE_ATTR(packets_per_slave, S_IRUGO | S_IWUSR,
1491 bonding_show_packets_per_slave,
1492 bonding_store_packets_per_slave);
1493
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001494static struct attribute *per_bond_attrs[] = {
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001495 &dev_attr_slaves.attr,
1496 &dev_attr_mode.attr,
Jay Vosburghdd957c52007-10-09 19:57:24 -07001497 &dev_attr_fail_over_mac.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001498 &dev_attr_arp_validate.attr,
Veaceslav Falico8599b522013-06-24 11:49:34 +02001499 &dev_attr_arp_all_targets.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001500 &dev_attr_arp_interval.attr,
1501 &dev_attr_arp_ip_target.attr,
1502 &dev_attr_downdelay.attr,
1503 &dev_attr_updelay.attr,
1504 &dev_attr_lacp_rate.attr,
Jay Vosburghfd989c82008-11-04 17:51:16 -08001505 &dev_attr_ad_select.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001506 &dev_attr_xmit_hash_policy.attr,
Ben Hutchingsad246c92011-04-26 15:25:52 +00001507 &dev_attr_num_grat_arp.attr,
1508 &dev_attr_num_unsol_na.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001509 &dev_attr_miimon.attr,
1510 &dev_attr_primary.attr,
Jiri Pirkoa5499522009-09-25 03:28:09 +00001511 &dev_attr_primary_reselect.attr,
Greg Kroah-Hartman43cb76d2002-04-09 12:14:34 -07001512 &dev_attr_use_carrier.attr,
1513 &dev_attr_active_slave.attr,
1514 &dev_attr_mii_status.attr,
1515 &dev_attr_ad_aggregator.attr,
1516 &dev_attr_ad_num_ports.attr,
1517 &dev_attr_ad_actor_key.attr,
1518 &dev_attr_ad_partner_key.attr,
1519 &dev_attr_ad_partner_mac.attr,
Andy Gospodarekbb1d9122010-06-02 08:40:18 +00001520 &dev_attr_queue_id.attr,
Andy Gospodarekebd8e492010-06-02 08:39:21 +00001521 &dev_attr_all_slaves_active.attr,
Flavio Leitnerc2952c32010-10-05 14:23:59 +00001522 &dev_attr_resend_igmp.attr,
stephen hemminger655f8912011-06-22 09:54:39 +00001523 &dev_attr_min_links.attr,
Neil Horman7eacd032013-09-13 11:05:33 -04001524 &dev_attr_lp_interval.attr,
Nikolay Aleksandrov73958322013-11-05 13:51:41 +01001525 &dev_attr_packets_per_slave.attr,
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001526 NULL,
1527};
1528
1529static struct attribute_group bonding_group = {
1530 .name = "bonding",
1531 .attrs = per_bond_attrs,
1532};
1533
1534/*
1535 * Initialize sysfs. This sets up the bonding_masters file in
1536 * /sys/class/net.
1537 */
Eric W. Biederman4c224002011-10-12 21:56:25 +00001538int bond_create_sysfs(struct bond_net *bn)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001539{
Jay Vosburghb8a97872008-06-13 18:12:04 -07001540 int ret;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001541
Eric W. Biederman4c224002011-10-12 21:56:25 +00001542 bn->class_attr_bonding_masters = class_attr_bonding_masters;
Eric W. Biederman01718e32011-10-21 22:43:07 +00001543 sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
Eric W. Biederman4c224002011-10-12 21:56:25 +00001544
Tejun Heo58292cbe2013-09-11 22:29:04 -04001545 ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters,
1546 bn->net);
Jay Vosburgh877cbd32007-01-19 18:15:47 -08001547 /*
1548 * Permit multiple loads of the module by ignoring failures to
1549 * create the bonding_masters sysfs file. Bonding devices
1550 * created by second or subsequent loads of the module will
1551 * not be listed in, or controllable by, bonding_masters, but
1552 * will have the usual "bonding" sysfs directory.
1553 *
1554 * This is done to preserve backwards compatibility for
1555 * initscripts/sysconfig, which load bonding multiple times to
1556 * configure multiple bonding devices.
1557 */
1558 if (ret == -EEXIST) {
Stephen Hemminger38d2f382008-05-14 22:35:04 -07001559 /* Is someone being kinky and naming a device bonding_master? */
Eric W. Biederman4c224002011-10-12 21:56:25 +00001560 if (__dev_get_by_name(bn->net,
Stephen Hemminger38d2f382008-05-14 22:35:04 -07001561 class_attr_bonding_masters.attr.name))
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001562 pr_err("network device named %s already exists in sysfs",
Stephen Hemminger38d2f382008-05-14 22:35:04 -07001563 class_attr_bonding_masters.attr.name);
Stephen Hemminger130aa612009-06-11 05:46:04 -07001564 ret = 0;
Jay Vosburgh877cbd32007-01-19 18:15:47 -08001565 }
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001566
1567 return ret;
1568
1569}
1570
1571/*
1572 * Remove /sys/class/net/bonding_masters.
1573 */
Eric W. Biederman4c224002011-10-12 21:56:25 +00001574void bond_destroy_sysfs(struct bond_net *bn)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001575{
Tejun Heo58292cbe2013-09-11 22:29:04 -04001576 netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net);
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001577}
1578
1579/*
1580 * Initialize sysfs for each bond. This sets up and registers
1581 * the 'bondctl' directory for each individual bond under /sys/class/net.
1582 */
Eric W. Biederman6151b3d2009-10-29 14:18:22 +00001583void bond_prepare_sysfs_group(struct bonding *bond)
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001584{
Eric W. Biederman6151b3d2009-10-29 14:18:22 +00001585 bond->dev->sysfs_groups[0] = &bonding_group;
Mitch Williamsb76cdba2005-11-09 10:36:41 -08001586}
1587