10a65089eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2b76cdba9SMitch Williams /*
3b76cdba9SMitch Williams * Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
4b76cdba9SMitch Williams */
5a4aee5c8SJoe Perches
6a4aee5c8SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7a4aee5c8SJoe Perches
8b76cdba9SMitch Williams #include <linux/kernel.h>
9b76cdba9SMitch Williams #include <linux/module.h>
10b76cdba9SMitch Williams #include <linux/device.h>
11174cd4b1SIngo Molnar #include <linux/sched/signal.h>
12b76cdba9SMitch Williams #include <linux/fs.h>
13b76cdba9SMitch Williams #include <linux/types.h>
14b76cdba9SMitch Williams #include <linux/string.h>
15b76cdba9SMitch Williams #include <linux/netdevice.h>
16b76cdba9SMitch Williams #include <linux/inetdevice.h>
17b76cdba9SMitch Williams #include <linux/in.h>
18b76cdba9SMitch Williams #include <linux/sysfs.h>
19b76cdba9SMitch Williams #include <linux/ctype.h>
20b76cdba9SMitch Williams #include <linux/inet.h>
21b76cdba9SMitch Williams #include <linux/rtnetlink.h>
225c5129b5SStephen Hemminger #include <linux/etherdevice.h>
23881d966bSEric W. Biederman #include <net/net_namespace.h>
24ec87fd3bSEric W. Biederman #include <net/netns/generic.h>
25ec87fd3bSEric W. Biederman #include <linux/nsproxy.h>
26b76cdba9SMitch Williams
271ef8019bSDavid S. Miller #include <net/bonding.h>
285a03cdb7SHolger Eitzenberger
29454d7c9bSWang Chen #define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd))))
30b76cdba9SMitch Williams
31dc3e5d18SNikolay Aleksandrov /* "show" function for the bond_masters attribute.
32b76cdba9SMitch Williams * The class parameter is ignored.
33b76cdba9SMitch Williams */
bonding_show_bonds(const struct class * cls,const struct class_attribute * attr,char * buf)3475a2d422SGreg Kroah-Hartman static ssize_t bonding_show_bonds(const struct class *cls,
3575a2d422SGreg Kroah-Hartman const struct class_attribute *attr,
3628812fe1SAndi Kleen char *buf)
37b76cdba9SMitch Williams {
3875a2d422SGreg Kroah-Hartman const struct bond_net *bn =
3975a2d422SGreg Kroah-Hartman container_of_const(attr, struct bond_net, class_attr_bonding_masters);
40b76cdba9SMitch Williams int res = 0;
41b76cdba9SMitch Williams struct bonding *bond;
42b76cdba9SMitch Williams
437e083840SStephen Hemminger rtnl_lock();
44b76cdba9SMitch Williams
45ec87fd3bSEric W. Biederman list_for_each_entry(bond, &bn->dev_list, bond_list) {
46b76cdba9SMitch Williams if (res > (PAGE_SIZE - IFNAMSIZ)) {
47b76cdba9SMitch Williams /* not enough space for another interface name */
48b76cdba9SMitch Williams if ((PAGE_SIZE - res) > 10)
49b76cdba9SMitch Williams res = PAGE_SIZE - 10;
5096e07181SWang Yufen res += sysfs_emit_at(buf, res, "++more++ ");
51b76cdba9SMitch Williams break;
52b76cdba9SMitch Williams }
5396e07181SWang Yufen res += sysfs_emit_at(buf, res, "%s ", bond->dev->name);
54b76cdba9SMitch Williams }
551dcdcd69SWagner Ferenc if (res)
561dcdcd69SWagner Ferenc buf[res-1] = '\n'; /* eat the leftover space */
577e083840SStephen Hemminger
587e083840SStephen Hemminger rtnl_unlock();
59b76cdba9SMitch Williams return res;
60b76cdba9SMitch Williams }
61b76cdba9SMitch Williams
bond_get_by_name(const struct bond_net * bn,const char * ifname)6275a2d422SGreg Kroah-Hartman static struct net_device *bond_get_by_name(const struct bond_net *bn, const char *ifname)
63373500dbSStephen Hemminger {
64373500dbSStephen Hemminger struct bonding *bond;
65373500dbSStephen Hemminger
66ec87fd3bSEric W. Biederman list_for_each_entry(bond, &bn->dev_list, bond_list) {
67373500dbSStephen Hemminger if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
68373500dbSStephen Hemminger return bond->dev;
69373500dbSStephen Hemminger }
70373500dbSStephen Hemminger return NULL;
71373500dbSStephen Hemminger }
72373500dbSStephen Hemminger
73dc3e5d18SNikolay Aleksandrov /* "store" function for the bond_masters attribute. This is what
74b76cdba9SMitch Williams * creates and deletes entire bonds.
75b76cdba9SMitch Williams *
76b76cdba9SMitch Williams * The class parameter is ignored.
77b76cdba9SMitch Williams */
bonding_store_bonds(const struct class * cls,const struct class_attribute * attr,const char * buffer,size_t count)7875a2d422SGreg Kroah-Hartman static ssize_t bonding_store_bonds(const struct class *cls,
7975a2d422SGreg Kroah-Hartman const struct class_attribute *attr,
803d632c3fSStephen Hemminger const char *buffer, size_t count)
81b76cdba9SMitch Williams {
8275a2d422SGreg Kroah-Hartman const struct bond_net *bn =
8375a2d422SGreg Kroah-Hartman container_of_const(attr, struct bond_net, class_attr_bonding_masters);
84b76cdba9SMitch Williams char command[IFNAMSIZ + 1] = {0, };
85b76cdba9SMitch Williams char *ifname;
86027ea041SJay Vosburgh int rv, res = count;
87b76cdba9SMitch Williams
88b76cdba9SMitch Williams sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
89b76cdba9SMitch Williams ifname = command + 1;
90b76cdba9SMitch Williams if ((strlen(command) <= 1) ||
91b76cdba9SMitch Williams !dev_valid_name(ifname))
92b76cdba9SMitch Williams goto err_no_cmd;
93b76cdba9SMitch Williams
94b76cdba9SMitch Williams if (command[0] == '+') {
95a4aee5c8SJoe Perches pr_info("%s is being created...\n", ifname);
964c22400aSEric W. Biederman rv = bond_create(bn->net, ifname);
97027ea041SJay Vosburgh if (rv) {
985f86cad1SPhil Oester if (rv == -EEXIST)
9990194264SJoe Perches pr_info("%s already exists\n", ifname);
1005f86cad1SPhil Oester else
10190194264SJoe Perches pr_info("%s creation failed\n", ifname);
102027ea041SJay Vosburgh res = rv;
103b76cdba9SMitch Williams }
104373500dbSStephen Hemminger } else if (command[0] == '-') {
105373500dbSStephen Hemminger struct net_device *bond_dev;
106b76cdba9SMitch Williams
107027ea041SJay Vosburgh rtnl_lock();
1084c22400aSEric W. Biederman bond_dev = bond_get_by_name(bn, ifname);
109373500dbSStephen Hemminger if (bond_dev) {
110a4aee5c8SJoe Perches pr_info("%s is being deleted...\n", ifname);
111373500dbSStephen Hemminger unregister_netdevice(bond_dev);
112373500dbSStephen Hemminger } else {
113a4aee5c8SJoe Perches pr_err("unable to delete non-existent %s\n", ifname);
114b76cdba9SMitch Williams res = -ENODEV;
115b76cdba9SMitch Williams }
116373500dbSStephen Hemminger rtnl_unlock();
117373500dbSStephen Hemminger } else
118373500dbSStephen Hemminger goto err_no_cmd;
119373500dbSStephen Hemminger
120373500dbSStephen Hemminger /* Always return either count or an error. If you return 0, you'll
121373500dbSStephen Hemminger * get called forever, which is bad.
122373500dbSStephen Hemminger */
123373500dbSStephen Hemminger return res;
124b76cdba9SMitch Williams
125b76cdba9SMitch Williams err_no_cmd:
12690194264SJoe Perches pr_err("no command found in bonding_masters - use +ifname or -ifname\n");
127c4ebc66aSJay Vosburgh return -EPERM;
128b76cdba9SMitch Williams }
129373500dbSStephen Hemminger
130b76cdba9SMitch Williams /* class attribute for bond_masters file. This ends up in /sys/class/net */
1314c22400aSEric W. Biederman static const struct class_attribute class_attr_bonding_masters = {
1324c22400aSEric W. Biederman .attr = {
1334c22400aSEric W. Biederman .name = "bonding_masters",
134d61e4038SJoe Perches .mode = 0644,
1354c22400aSEric W. Biederman },
1364c22400aSEric W. Biederman .show = bonding_show_bonds,
1374c22400aSEric W. Biederman .store = bonding_store_bonds,
1384c22400aSEric W. Biederman };
139b76cdba9SMitch Williams
140dc3e5d18SNikolay Aleksandrov /* Generic "store" method for bonding sysfs option setting */
bonding_sysfs_store_option(struct device * d,struct device_attribute * attr,const char * buffer,size_t count)141dc3e5d18SNikolay Aleksandrov static ssize_t bonding_sysfs_store_option(struct device *d,
142dc3e5d18SNikolay Aleksandrov struct device_attribute *attr,
143dc3e5d18SNikolay Aleksandrov const char *buffer, size_t count)
144dc3e5d18SNikolay Aleksandrov {
145dc3e5d18SNikolay Aleksandrov struct bonding *bond = to_bond(d);
146dc3e5d18SNikolay Aleksandrov const struct bond_option *opt;
1475b3df177SNikolay Aleksandrov char *buffer_clone;
148dc3e5d18SNikolay Aleksandrov int ret;
149dc3e5d18SNikolay Aleksandrov
150dc3e5d18SNikolay Aleksandrov opt = bond_opt_get_by_name(attr->attr.name);
151dc3e5d18SNikolay Aleksandrov if (WARN_ON(!opt))
152dc3e5d18SNikolay Aleksandrov return -ENOENT;
1535b3df177SNikolay Aleksandrov buffer_clone = kstrndup(buffer, count, GFP_KERNEL);
1545b3df177SNikolay Aleksandrov if (!buffer_clone)
1555b3df177SNikolay Aleksandrov return -ENOMEM;
1565b3df177SNikolay Aleksandrov ret = bond_opt_tryset_rtnl(bond, opt->id, buffer_clone);
157dc3e5d18SNikolay Aleksandrov if (!ret)
158dc3e5d18SNikolay Aleksandrov ret = count;
1595b3df177SNikolay Aleksandrov kfree(buffer_clone);
160dc3e5d18SNikolay Aleksandrov
161dc3e5d18SNikolay Aleksandrov return ret;
162dc3e5d18SNikolay Aleksandrov }
163dc3e5d18SNikolay Aleksandrov
164dc3e5d18SNikolay Aleksandrov /* Show the slaves in the current bond. */
bonding_show_slaves(struct device * d,struct device_attribute * attr,char * buf)16543cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_slaves(struct device *d,
16643cb76d9SGreg Kroah-Hartman struct device_attribute *attr, char *buf)
167b76cdba9SMitch Williams {
16843cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
1699caff1e7SVeaceslav Falico struct list_head *iter;
170dec1e90eSnikolay@redhat.com struct slave *slave;
171dec1e90eSnikolay@redhat.com int res = 0;
172b76cdba9SMitch Williams
1734d1ae5fbSdingtianhong if (!rtnl_trylock())
1744d1ae5fbSdingtianhong return restart_syscall();
1754d1ae5fbSdingtianhong
1769caff1e7SVeaceslav Falico bond_for_each_slave(bond, slave, iter) {
177b76cdba9SMitch Williams if (res > (PAGE_SIZE - IFNAMSIZ)) {
178b76cdba9SMitch Williams /* not enough space for another interface name */
179b76cdba9SMitch Williams if ((PAGE_SIZE - res) > 10)
180b76cdba9SMitch Williams res = PAGE_SIZE - 10;
18196e07181SWang Yufen res += sysfs_emit_at(buf, res, "++more++ ");
182b76cdba9SMitch Williams break;
183b76cdba9SMitch Williams }
18496e07181SWang Yufen res += sysfs_emit_at(buf, res, "%s ", slave->dev->name);
185b76cdba9SMitch Williams }
1864d1ae5fbSdingtianhong
1874d1ae5fbSdingtianhong rtnl_unlock();
1884d1ae5fbSdingtianhong
1891dcdcd69SWagner Ferenc if (res)
1901dcdcd69SWagner Ferenc buf[res-1] = '\n'; /* eat the leftover space */
191dec1e90eSnikolay@redhat.com
192b76cdba9SMitch Williams return res;
193b76cdba9SMitch Williams }
194d61e4038SJoe Perches static DEVICE_ATTR(slaves, 0644, bonding_show_slaves,
195dc3e5d18SNikolay Aleksandrov bonding_sysfs_store_option);
196b76cdba9SMitch Williams
197dc3e5d18SNikolay Aleksandrov /* Show the bonding mode. */
bonding_show_mode(struct device * d,struct device_attribute * attr,char * buf)19843cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_mode(struct device *d,
19943cb76d9SGreg Kroah-Hartman struct device_attribute *attr, char *buf)
200b76cdba9SMitch Williams {
20143cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
202f3253339Sstephen hemminger const struct bond_opt_value *val;
203b76cdba9SMitch Williams
20401844098SVeaceslav Falico val = bond_opt_get_val(BOND_OPT_MODE, BOND_MODE(bond));
2052b3798d5SNikolay Aleksandrov
20696e07181SWang Yufen return sysfs_emit(buf, "%s %d\n", val->string, BOND_MODE(bond));
207b76cdba9SMitch Williams }
208d61e4038SJoe Perches static DEVICE_ATTR(mode, 0644, bonding_show_mode, bonding_sysfs_store_option);
209b76cdba9SMitch Williams
210dc3e5d18SNikolay Aleksandrov /* Show the bonding transmit hash method. */
bonding_show_xmit_hash(struct device * d,struct device_attribute * attr,char * buf)21143cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_xmit_hash(struct device *d,
21243cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
21343cb76d9SGreg Kroah-Hartman char *buf)
214b76cdba9SMitch Williams {
21543cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
216f3253339Sstephen hemminger const struct bond_opt_value *val;
217b76cdba9SMitch Williams
218a4b32ce7SNikolay Aleksandrov val = bond_opt_get_val(BOND_OPT_XMIT_HASH, bond->params.xmit_policy);
219a4b32ce7SNikolay Aleksandrov
22096e07181SWang Yufen return sysfs_emit(buf, "%s %d\n", val->string, bond->params.xmit_policy);
221b76cdba9SMitch Williams }
222d61e4038SJoe Perches static DEVICE_ATTR(xmit_hash_policy, 0644,
223dc3e5d18SNikolay Aleksandrov bonding_show_xmit_hash, bonding_sysfs_store_option);
224b76cdba9SMitch Williams
225dc3e5d18SNikolay Aleksandrov /* Show arp_validate. */
bonding_show_arp_validate(struct device * d,struct device_attribute * attr,char * buf)22643cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_arp_validate(struct device *d,
22743cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
22843cb76d9SGreg Kroah-Hartman char *buf)
229f5b2b966SJay Vosburgh {
23043cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
231f3253339Sstephen hemminger const struct bond_opt_value *val;
232f5b2b966SJay Vosburgh
23316228881SNikolay Aleksandrov val = bond_opt_get_val(BOND_OPT_ARP_VALIDATE,
2347bd46508SWagner Ferenc bond->params.arp_validate);
23516228881SNikolay Aleksandrov
23696e07181SWang Yufen return sysfs_emit(buf, "%s %d\n", val->string, bond->params.arp_validate);
237f5b2b966SJay Vosburgh }
238d61e4038SJoe Perches static DEVICE_ATTR(arp_validate, 0644, bonding_show_arp_validate,
239dc3e5d18SNikolay Aleksandrov bonding_sysfs_store_option);
240dc3e5d18SNikolay Aleksandrov
241dc3e5d18SNikolay Aleksandrov /* Show arp_all_targets. */
bonding_show_arp_all_targets(struct device * d,struct device_attribute * attr,char * buf)2428599b52eSVeaceslav Falico static ssize_t bonding_show_arp_all_targets(struct device *d,
2438599b52eSVeaceslav Falico struct device_attribute *attr,
2448599b52eSVeaceslav Falico char *buf)
2458599b52eSVeaceslav Falico {
2468599b52eSVeaceslav Falico struct bonding *bond = to_bond(d);
247f3253339Sstephen hemminger const struct bond_opt_value *val;
2488599b52eSVeaceslav Falico
249edf36b24SNikolay Aleksandrov val = bond_opt_get_val(BOND_OPT_ARP_ALL_TARGETS,
250edf36b24SNikolay Aleksandrov bond->params.arp_all_targets);
25196e07181SWang Yufen return sysfs_emit(buf, "%s %d\n",
252edf36b24SNikolay Aleksandrov val->string, bond->params.arp_all_targets);
2538599b52eSVeaceslav Falico }
254d61e4038SJoe Perches static DEVICE_ATTR(arp_all_targets, 0644,
255dc3e5d18SNikolay Aleksandrov bonding_show_arp_all_targets, bonding_sysfs_store_option);
256f5b2b966SJay Vosburgh
257dc3e5d18SNikolay Aleksandrov /* Show fail_over_mac. */
bonding_show_fail_over_mac(struct device * d,struct device_attribute * attr,char * buf)2583d632c3fSStephen Hemminger static ssize_t bonding_show_fail_over_mac(struct device *d,
2593d632c3fSStephen Hemminger struct device_attribute *attr,
2603d632c3fSStephen Hemminger char *buf)
261dd957c57SJay Vosburgh {
262dd957c57SJay Vosburgh struct bonding *bond = to_bond(d);
263f3253339Sstephen hemminger const struct bond_opt_value *val;
264dd957c57SJay Vosburgh
2651df6b6aaSNikolay Aleksandrov val = bond_opt_get_val(BOND_OPT_FAIL_OVER_MAC,
2663915c1e8SJay Vosburgh bond->params.fail_over_mac);
2671df6b6aaSNikolay Aleksandrov
26896e07181SWang Yufen return sysfs_emit(buf, "%s %d\n", val->string, bond->params.fail_over_mac);
269dd957c57SJay Vosburgh }
270d61e4038SJoe Perches static DEVICE_ATTR(fail_over_mac, 0644,
271dc3e5d18SNikolay Aleksandrov bonding_show_fail_over_mac, bonding_sysfs_store_option);
272dd957c57SJay Vosburgh
273dc3e5d18SNikolay Aleksandrov /* Show the arp timer interval. */
bonding_show_arp_interval(struct device * d,struct device_attribute * attr,char * buf)27443cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_arp_interval(struct device *d,
27543cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
27643cb76d9SGreg Kroah-Hartman char *buf)
277b76cdba9SMitch Williams {
27843cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
279b76cdba9SMitch Williams
28096e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.arp_interval);
281b76cdba9SMitch Williams }
282d61e4038SJoe Perches static DEVICE_ATTR(arp_interval, 0644,
283dc3e5d18SNikolay Aleksandrov bonding_show_arp_interval, bonding_sysfs_store_option);
284b76cdba9SMitch Williams
285dc3e5d18SNikolay Aleksandrov /* Show the arp targets. */
bonding_show_arp_targets(struct device * d,struct device_attribute * attr,char * buf)28643cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_arp_targets(struct device *d,
28743cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
28843cb76d9SGreg Kroah-Hartman char *buf)
289b76cdba9SMitch Williams {
29043cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
2914fb0ef58SNikolay Aleksandrov int i, res = 0;
292b76cdba9SMitch Williams
293b76cdba9SMitch Williams for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
294b76cdba9SMitch Williams if (bond->params.arp_targets[i])
29596e07181SWang Yufen res += sysfs_emit_at(buf, res, "%pI4 ",
29663779436SHarvey Harrison &bond->params.arp_targets[i]);
297b76cdba9SMitch Williams }
2981dcdcd69SWagner Ferenc if (res)
2991dcdcd69SWagner Ferenc buf[res-1] = '\n'; /* eat the leftover space */
3004fb0ef58SNikolay Aleksandrov
301b76cdba9SMitch Williams return res;
302b76cdba9SMitch Williams }
303d61e4038SJoe Perches static DEVICE_ATTR(arp_ip_target, 0644,
304dc3e5d18SNikolay Aleksandrov bonding_show_arp_targets, bonding_sysfs_store_option);
305b76cdba9SMitch Williams
3065944b5abSHangbin Liu /* Show the arp missed max. */
bonding_show_missed_max(struct device * d,struct device_attribute * attr,char * buf)3075944b5abSHangbin Liu static ssize_t bonding_show_missed_max(struct device *d,
3085944b5abSHangbin Liu struct device_attribute *attr,
3095944b5abSHangbin Liu char *buf)
3105944b5abSHangbin Liu {
3115944b5abSHangbin Liu struct bonding *bond = to_bond(d);
3125944b5abSHangbin Liu
31396e07181SWang Yufen return sysfs_emit(buf, "%u\n", bond->params.missed_max);
3145944b5abSHangbin Liu }
3155944b5abSHangbin Liu static DEVICE_ATTR(arp_missed_max, 0644,
3165944b5abSHangbin Liu bonding_show_missed_max, bonding_sysfs_store_option);
3175944b5abSHangbin Liu
318dc3e5d18SNikolay Aleksandrov /* Show the up and down delays. */
bonding_show_downdelay(struct device * d,struct device_attribute * attr,char * buf)31943cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_downdelay(struct device *d,
32043cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
32143cb76d9SGreg Kroah-Hartman char *buf)
322b76cdba9SMitch Williams {
32343cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
324b76cdba9SMitch Williams
32596e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.downdelay * bond->params.miimon);
326b76cdba9SMitch Williams }
327d61e4038SJoe Perches static DEVICE_ATTR(downdelay, 0644,
328dc3e5d18SNikolay Aleksandrov bonding_show_downdelay, bonding_sysfs_store_option);
329b76cdba9SMitch Williams
bonding_show_updelay(struct device * d,struct device_attribute * attr,char * buf)33043cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_updelay(struct device *d,
33143cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
33243cb76d9SGreg Kroah-Hartman char *buf)
333b76cdba9SMitch Williams {
33443cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
335b76cdba9SMitch Williams
33696e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.updelay * bond->params.miimon);
337b76cdba9SMitch Williams
338b76cdba9SMitch Williams }
339d61e4038SJoe Perches static DEVICE_ATTR(updelay, 0644,
340dc3e5d18SNikolay Aleksandrov bonding_show_updelay, bonding_sysfs_store_option);
341b76cdba9SMitch Williams
bonding_show_peer_notif_delay(struct device * d,struct device_attribute * attr,char * buf)34207a4ddecSVincent Bernat static ssize_t bonding_show_peer_notif_delay(struct device *d,
34307a4ddecSVincent Bernat struct device_attribute *attr,
34407a4ddecSVincent Bernat char *buf)
34507a4ddecSVincent Bernat {
34607a4ddecSVincent Bernat struct bonding *bond = to_bond(d);
34707a4ddecSVincent Bernat
34896e07181SWang Yufen return sysfs_emit(buf, "%d\n",
34907a4ddecSVincent Bernat bond->params.peer_notif_delay * bond->params.miimon);
35007a4ddecSVincent Bernat }
35107a4ddecSVincent Bernat static DEVICE_ATTR(peer_notif_delay, 0644,
35207a4ddecSVincent Bernat bonding_show_peer_notif_delay, bonding_sysfs_store_option);
35307a4ddecSVincent Bernat
3543a755cd8SHangbin Liu /* Show the LACP activity and interval. */
bonding_show_lacp_active(struct device * d,struct device_attribute * attr,char * buf)3553a755cd8SHangbin Liu static ssize_t bonding_show_lacp_active(struct device *d,
3563a755cd8SHangbin Liu struct device_attribute *attr,
3573a755cd8SHangbin Liu char *buf)
3583a755cd8SHangbin Liu {
3593a755cd8SHangbin Liu struct bonding *bond = to_bond(d);
3603a755cd8SHangbin Liu const struct bond_opt_value *val;
3613a755cd8SHangbin Liu
3623a755cd8SHangbin Liu val = bond_opt_get_val(BOND_OPT_LACP_ACTIVE, bond->params.lacp_active);
3633a755cd8SHangbin Liu
36496e07181SWang Yufen return sysfs_emit(buf, "%s %d\n", val->string, bond->params.lacp_active);
3653a755cd8SHangbin Liu }
3663a755cd8SHangbin Liu static DEVICE_ATTR(lacp_active, 0644,
3673a755cd8SHangbin Liu bonding_show_lacp_active, bonding_sysfs_store_option);
3683a755cd8SHangbin Liu
bonding_show_lacp_rate(struct device * d,struct device_attribute * attr,char * buf)3693a755cd8SHangbin Liu static ssize_t bonding_show_lacp_rate(struct device *d,
37043cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
37143cb76d9SGreg Kroah-Hartman char *buf)
372b76cdba9SMitch Williams {
37343cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
374f3253339Sstephen hemminger const struct bond_opt_value *val;
375b76cdba9SMitch Williams
376d3131de7SNikolay Aleksandrov val = bond_opt_get_val(BOND_OPT_LACP_RATE, bond->params.lacp_fast);
377d3131de7SNikolay Aleksandrov
37896e07181SWang Yufen return sysfs_emit(buf, "%s %d\n", val->string, bond->params.lacp_fast);
379b76cdba9SMitch Williams }
380d61e4038SJoe Perches static DEVICE_ATTR(lacp_rate, 0644,
3813a755cd8SHangbin Liu bonding_show_lacp_rate, bonding_sysfs_store_option);
382b76cdba9SMitch Williams
bonding_show_min_links(struct device * d,struct device_attribute * attr,char * buf)383655f8919Sstephen hemminger static ssize_t bonding_show_min_links(struct device *d,
384655f8919Sstephen hemminger struct device_attribute *attr,
385655f8919Sstephen hemminger char *buf)
386655f8919Sstephen hemminger {
387655f8919Sstephen hemminger struct bonding *bond = to_bond(d);
388655f8919Sstephen hemminger
38996e07181SWang Yufen return sysfs_emit(buf, "%u\n", bond->params.min_links);
390655f8919Sstephen hemminger }
391d61e4038SJoe Perches static DEVICE_ATTR(min_links, 0644,
392dc3e5d18SNikolay Aleksandrov bonding_show_min_links, bonding_sysfs_store_option);
393655f8919Sstephen hemminger
bonding_show_ad_select(struct device * d,struct device_attribute * attr,char * buf)394fd989c83SJay Vosburgh static ssize_t bonding_show_ad_select(struct device *d,
395fd989c83SJay Vosburgh struct device_attribute *attr,
396fd989c83SJay Vosburgh char *buf)
397fd989c83SJay Vosburgh {
398fd989c83SJay Vosburgh struct bonding *bond = to_bond(d);
399f3253339Sstephen hemminger const struct bond_opt_value *val;
400fd989c83SJay Vosburgh
4019e5f5eebSNikolay Aleksandrov val = bond_opt_get_val(BOND_OPT_AD_SELECT, bond->params.ad_select);
4029e5f5eebSNikolay Aleksandrov
40396e07181SWang Yufen return sysfs_emit(buf, "%s %d\n", val->string, bond->params.ad_select);
404fd989c83SJay Vosburgh }
405d61e4038SJoe Perches static DEVICE_ATTR(ad_select, 0644,
406dc3e5d18SNikolay Aleksandrov bonding_show_ad_select, bonding_sysfs_store_option);
407fd989c83SJay Vosburgh
408205845a3SNikolay Aleksandrov /* Show the number of peer notifications to send after a failover event. */
bonding_show_num_peer_notif(struct device * d,struct device_attribute * attr,char * buf)409ad246c99SBen Hutchings static ssize_t bonding_show_num_peer_notif(struct device *d,
410ad246c99SBen Hutchings struct device_attribute *attr,
411ad246c99SBen Hutchings char *buf)
412ad246c99SBen Hutchings {
413ad246c99SBen Hutchings struct bonding *bond = to_bond(d);
41486a5ad0aSYufeng Mo
41596e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.num_peer_notif);
416ad246c99SBen Hutchings }
417d61e4038SJoe Perches static DEVICE_ATTR(num_grat_arp, 0644,
418205845a3SNikolay Aleksandrov bonding_show_num_peer_notif, bonding_sysfs_store_option);
419d61e4038SJoe Perches static DEVICE_ATTR(num_unsol_na, 0644,
420205845a3SNikolay Aleksandrov bonding_show_num_peer_notif, bonding_sysfs_store_option);
421ad246c99SBen Hutchings
422dc3e5d18SNikolay Aleksandrov /* Show the MII monitor interval. */
bonding_show_miimon(struct device * d,struct device_attribute * attr,char * buf)42343cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_miimon(struct device *d,
42443cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
42543cb76d9SGreg Kroah-Hartman char *buf)
426b76cdba9SMitch Williams {
42743cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
428b76cdba9SMitch Williams
42996e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.miimon);
430b76cdba9SMitch Williams }
431d61e4038SJoe Perches static DEVICE_ATTR(miimon, 0644,
432dc3e5d18SNikolay Aleksandrov bonding_show_miimon, bonding_sysfs_store_option);
433b76cdba9SMitch Williams
434dc3e5d18SNikolay Aleksandrov /* Show the primary slave. */
bonding_show_primary(struct device * d,struct device_attribute * attr,char * buf)43543cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_primary(struct device *d,
43643cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
43743cb76d9SGreg Kroah-Hartman char *buf)
438b76cdba9SMitch Williams {
43943cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
440059b47e8SNikolay Aleksandrov struct slave *primary;
441059b47e8SNikolay Aleksandrov int count = 0;
442b76cdba9SMitch Williams
443059b47e8SNikolay Aleksandrov rcu_read_lock();
444059b47e8SNikolay Aleksandrov primary = rcu_dereference(bond->primary_slave);
445059b47e8SNikolay Aleksandrov if (primary)
44696e07181SWang Yufen count = sysfs_emit(buf, "%s\n", primary->dev->name);
447059b47e8SNikolay Aleksandrov rcu_read_unlock();
448b76cdba9SMitch Williams
449b76cdba9SMitch Williams return count;
450b76cdba9SMitch Williams }
451d61e4038SJoe Perches static DEVICE_ATTR(primary, 0644,
452dc3e5d18SNikolay Aleksandrov bonding_show_primary, bonding_sysfs_store_option);
453b76cdba9SMitch Williams
454dc3e5d18SNikolay Aleksandrov /* Show the primary_reselect flag. */
bonding_show_primary_reselect(struct device * d,struct device_attribute * attr,char * buf)455a549952aSJiri Pirko static ssize_t bonding_show_primary_reselect(struct device *d,
456a549952aSJiri Pirko struct device_attribute *attr,
457a549952aSJiri Pirko char *buf)
458a549952aSJiri Pirko {
459a549952aSJiri Pirko struct bonding *bond = to_bond(d);
460f3253339Sstephen hemminger const struct bond_opt_value *val;
461388d3a6dSNikolay Aleksandrov
462388d3a6dSNikolay Aleksandrov val = bond_opt_get_val(BOND_OPT_PRIMARY_RESELECT,
463388d3a6dSNikolay Aleksandrov bond->params.primary_reselect);
464a549952aSJiri Pirko
46596e07181SWang Yufen return sysfs_emit(buf, "%s %d\n",
466388d3a6dSNikolay Aleksandrov val->string, bond->params.primary_reselect);
467a549952aSJiri Pirko }
468d61e4038SJoe Perches static DEVICE_ATTR(primary_reselect, 0644,
469dc3e5d18SNikolay Aleksandrov bonding_show_primary_reselect, bonding_sysfs_store_option);
470a549952aSJiri Pirko
471dc3e5d18SNikolay Aleksandrov /* Show the use_carrier flag. */
bonding_show_carrier(struct device * d,struct device_attribute * attr,char * buf)47243cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_carrier(struct device *d,
47343cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
47443cb76d9SGreg Kroah-Hartman char *buf)
475b76cdba9SMitch Williams {
47643cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
477b76cdba9SMitch Williams
47896e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.use_carrier);
479b76cdba9SMitch Williams }
480d61e4038SJoe Perches static DEVICE_ATTR(use_carrier, 0644,
481dc3e5d18SNikolay Aleksandrov bonding_show_carrier, bonding_sysfs_store_option);
482b76cdba9SMitch Williams
483b76cdba9SMitch Williams
484dc3e5d18SNikolay Aleksandrov /* Show currently active_slave. */
bonding_show_active_slave(struct device * d,struct device_attribute * attr,char * buf)48543cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_active_slave(struct device *d,
48643cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
48743cb76d9SGreg Kroah-Hartman char *buf)
488b76cdba9SMitch Williams {
48943cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
490752d48b5SJiri Pirko struct net_device *slave_dev;
49116cd0160SWagner Ferenc int count = 0;
492b76cdba9SMitch Williams
493278b2083Snikolay@redhat.com rcu_read_lock();
494752d48b5SJiri Pirko slave_dev = bond_option_active_slave_get_rcu(bond);
495752d48b5SJiri Pirko if (slave_dev)
49696e07181SWang Yufen count = sysfs_emit(buf, "%s\n", slave_dev->name);
497278b2083Snikolay@redhat.com rcu_read_unlock();
498278b2083Snikolay@redhat.com
499b76cdba9SMitch Williams return count;
500b76cdba9SMitch Williams }
501d61e4038SJoe Perches static DEVICE_ATTR(active_slave, 0644,
502dc3e5d18SNikolay Aleksandrov bonding_show_active_slave, bonding_sysfs_store_option);
503b76cdba9SMitch Williams
504dc3e5d18SNikolay Aleksandrov /* Show link status of the bond interface. */
bonding_show_mii_status(struct device * d,struct device_attribute * attr,char * buf)50543cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_mii_status(struct device *d,
50643cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
50743cb76d9SGreg Kroah-Hartman char *buf)
508b76cdba9SMitch Williams {
50943cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
510c8086f6dSJarod Wilson bool active = netif_carrier_ok(bond->dev);
511b76cdba9SMitch Williams
51296e07181SWang Yufen return sysfs_emit(buf, "%s\n", active ? "up" : "down");
513b76cdba9SMitch Williams }
514d61e4038SJoe Perches static DEVICE_ATTR(mii_status, 0444, bonding_show_mii_status, NULL);
515b76cdba9SMitch Williams
516dc3e5d18SNikolay Aleksandrov /* Show current 802.3ad aggregator ID. */
bonding_show_ad_aggregator(struct device * d,struct device_attribute * attr,char * buf)51743cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_ad_aggregator(struct device *d,
51843cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
51943cb76d9SGreg Kroah-Hartman char *buf)
520b76cdba9SMitch Williams {
521b76cdba9SMitch Williams int count = 0;
52243cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
523b76cdba9SMitch Williams
52401844098SVeaceslav Falico if (BOND_MODE(bond) == BOND_MODE_8023AD) {
525b76cdba9SMitch Williams struct ad_info ad_info;
52686a5ad0aSYufeng Mo
52796e07181SWang Yufen count = sysfs_emit(buf, "%d\n",
528318debd8Snikolay@redhat.com bond_3ad_get_active_agg_info(bond, &ad_info)
5293d632c3fSStephen Hemminger ? 0 : ad_info.aggregator_id);
530b76cdba9SMitch Williams }
531b76cdba9SMitch Williams
532b76cdba9SMitch Williams return count;
533b76cdba9SMitch Williams }
534d61e4038SJoe Perches static DEVICE_ATTR(ad_aggregator, 0444, bonding_show_ad_aggregator, NULL);
535b76cdba9SMitch Williams
536b76cdba9SMitch Williams
537dc3e5d18SNikolay Aleksandrov /* Show number of active 802.3ad ports. */
bonding_show_ad_num_ports(struct device * d,struct device_attribute * attr,char * buf)53843cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_ad_num_ports(struct device *d,
53943cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
54043cb76d9SGreg Kroah-Hartman char *buf)
541b76cdba9SMitch Williams {
542b76cdba9SMitch Williams int count = 0;
54343cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
544b76cdba9SMitch Williams
54501844098SVeaceslav Falico if (BOND_MODE(bond) == BOND_MODE_8023AD) {
546b76cdba9SMitch Williams struct ad_info ad_info;
54786a5ad0aSYufeng Mo
54896e07181SWang Yufen count = sysfs_emit(buf, "%d\n",
549318debd8Snikolay@redhat.com bond_3ad_get_active_agg_info(bond, &ad_info)
5503d632c3fSStephen Hemminger ? 0 : ad_info.ports);
551b76cdba9SMitch Williams }
552b76cdba9SMitch Williams
553b76cdba9SMitch Williams return count;
554b76cdba9SMitch Williams }
555d61e4038SJoe Perches static DEVICE_ATTR(ad_num_ports, 0444, bonding_show_ad_num_ports, NULL);
556b76cdba9SMitch Williams
557b76cdba9SMitch Williams
558dc3e5d18SNikolay Aleksandrov /* Show current 802.3ad actor key. */
bonding_show_ad_actor_key(struct device * d,struct device_attribute * attr,char * buf)55943cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_ad_actor_key(struct device *d,
56043cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
56143cb76d9SGreg Kroah-Hartman char *buf)
562b76cdba9SMitch Williams {
563b76cdba9SMitch Williams int count = 0;
56443cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
565b76cdba9SMitch Williams
5664cd6b475SMahesh Bandewar if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN)) {
567b76cdba9SMitch Williams struct ad_info ad_info;
56886a5ad0aSYufeng Mo
56996e07181SWang Yufen count = sysfs_emit(buf, "%d\n",
570318debd8Snikolay@redhat.com bond_3ad_get_active_agg_info(bond, &ad_info)
5713d632c3fSStephen Hemminger ? 0 : ad_info.actor_key);
572b76cdba9SMitch Williams }
573b76cdba9SMitch Williams
574b76cdba9SMitch Williams return count;
575b76cdba9SMitch Williams }
576d61e4038SJoe Perches static DEVICE_ATTR(ad_actor_key, 0444, bonding_show_ad_actor_key, NULL);
577b76cdba9SMitch Williams
578b76cdba9SMitch Williams
579dc3e5d18SNikolay Aleksandrov /* Show current 802.3ad partner key. */
bonding_show_ad_partner_key(struct device * d,struct device_attribute * attr,char * buf)58043cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_ad_partner_key(struct device *d,
58143cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
58243cb76d9SGreg Kroah-Hartman char *buf)
583b76cdba9SMitch Williams {
584b76cdba9SMitch Williams int count = 0;
58543cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
586b76cdba9SMitch Williams
5874cd6b475SMahesh Bandewar if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN)) {
588b76cdba9SMitch Williams struct ad_info ad_info;
58986a5ad0aSYufeng Mo
59096e07181SWang Yufen count = sysfs_emit(buf, "%d\n",
591318debd8Snikolay@redhat.com bond_3ad_get_active_agg_info(bond, &ad_info)
5923d632c3fSStephen Hemminger ? 0 : ad_info.partner_key);
593b76cdba9SMitch Williams }
594b76cdba9SMitch Williams
595b76cdba9SMitch Williams return count;
596b76cdba9SMitch Williams }
597d61e4038SJoe Perches static DEVICE_ATTR(ad_partner_key, 0444, bonding_show_ad_partner_key, NULL);
598b76cdba9SMitch Williams
599b76cdba9SMitch Williams
600dc3e5d18SNikolay Aleksandrov /* Show current 802.3ad partner mac. */
bonding_show_ad_partner_mac(struct device * d,struct device_attribute * attr,char * buf)60143cb76d9SGreg Kroah-Hartman static ssize_t bonding_show_ad_partner_mac(struct device *d,
60243cb76d9SGreg Kroah-Hartman struct device_attribute *attr,
60343cb76d9SGreg Kroah-Hartman char *buf)
604b76cdba9SMitch Williams {
605b76cdba9SMitch Williams int count = 0;
60643cb76d9SGreg Kroah-Hartman struct bonding *bond = to_bond(d);
607b76cdba9SMitch Williams
6084cd6b475SMahesh Bandewar if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN)) {
609b76cdba9SMitch Williams struct ad_info ad_info;
61086a5ad0aSYufeng Mo
6113d632c3fSStephen Hemminger if (!bond_3ad_get_active_agg_info(bond, &ad_info))
61296e07181SWang Yufen count = sysfs_emit(buf, "%pM\n", ad_info.partner_system);
613b76cdba9SMitch Williams }
614b76cdba9SMitch Williams
615b76cdba9SMitch Williams return count;
616b76cdba9SMitch Williams }
617d61e4038SJoe Perches static DEVICE_ATTR(ad_partner_mac, 0444, bonding_show_ad_partner_mac, NULL);
618b76cdba9SMitch Williams
619dc3e5d18SNikolay Aleksandrov /* Show the queue_ids of the slaves in the current bond. */
bonding_show_queue_id(struct device * d,struct device_attribute * attr,char * buf)620bb1d9123SAndy Gospodarek static ssize_t bonding_show_queue_id(struct device *d,
621bb1d9123SAndy Gospodarek struct device_attribute *attr,
622bb1d9123SAndy Gospodarek char *buf)
623bb1d9123SAndy Gospodarek {
624bb1d9123SAndy Gospodarek struct bonding *bond = to_bond(d);
6259caff1e7SVeaceslav Falico struct list_head *iter;
626dec1e90eSnikolay@redhat.com struct slave *slave;
627dec1e90eSnikolay@redhat.com int res = 0;
628bb1d9123SAndy Gospodarek
629bb1d9123SAndy Gospodarek if (!rtnl_trylock())
630bb1d9123SAndy Gospodarek return restart_syscall();
631bb1d9123SAndy Gospodarek
6329caff1e7SVeaceslav Falico bond_for_each_slave(bond, slave, iter) {
63379236680SNicolas de Pesloüan if (res > (PAGE_SIZE - IFNAMSIZ - 6)) {
63479236680SNicolas de Pesloüan /* not enough space for another interface_name:queue_id pair */
635bb1d9123SAndy Gospodarek if ((PAGE_SIZE - res) > 10)
636bb1d9123SAndy Gospodarek res = PAGE_SIZE - 10;
63796e07181SWang Yufen res += sysfs_emit_at(buf, res, "++more++ ");
638bb1d9123SAndy Gospodarek break;
639bb1d9123SAndy Gospodarek }
64096e07181SWang Yufen res += sysfs_emit_at(buf, res, "%s:%d ",
641bb1d9123SAndy Gospodarek slave->dev->name, slave->queue_id);
642bb1d9123SAndy Gospodarek }
643bb1d9123SAndy Gospodarek if (res)
644bb1d9123SAndy Gospodarek buf[res-1] = '\n'; /* eat the leftover space */
6454d1ae5fbSdingtianhong
646bb1d9123SAndy Gospodarek rtnl_unlock();
647dec1e90eSnikolay@redhat.com
648bb1d9123SAndy Gospodarek return res;
649bb1d9123SAndy Gospodarek }
650d61e4038SJoe Perches static DEVICE_ATTR(queue_id, 0644, bonding_show_queue_id,
651dc3e5d18SNikolay Aleksandrov bonding_sysfs_store_option);
652bb1d9123SAndy Gospodarek
653bb1d9123SAndy Gospodarek
654dc3e5d18SNikolay Aleksandrov /* Show the all_slaves_active flag. */
bonding_show_slaves_active(struct device * d,struct device_attribute * attr,char * buf)655ebd8e497SAndy Gospodarek static ssize_t bonding_show_slaves_active(struct device *d,
656ebd8e497SAndy Gospodarek struct device_attribute *attr,
657ebd8e497SAndy Gospodarek char *buf)
658ebd8e497SAndy Gospodarek {
659ebd8e497SAndy Gospodarek struct bonding *bond = to_bond(d);
660b76cdba9SMitch Williams
66196e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.all_slaves_active);
662ebd8e497SAndy Gospodarek }
663d61e4038SJoe Perches static DEVICE_ATTR(all_slaves_active, 0644,
664dc3e5d18SNikolay Aleksandrov bonding_show_slaves_active, bonding_sysfs_store_option);
665b76cdba9SMitch Williams
666dc3e5d18SNikolay Aleksandrov /* Show the number of IGMP membership reports to send on link failure */
bonding_show_resend_igmp(struct device * d,struct device_attribute * attr,char * buf)667c2952c31SFlavio Leitner static ssize_t bonding_show_resend_igmp(struct device *d,
668c2952c31SFlavio Leitner struct device_attribute *attr,
669c2952c31SFlavio Leitner char *buf)
670c2952c31SFlavio Leitner {
671c2952c31SFlavio Leitner struct bonding *bond = to_bond(d);
672c2952c31SFlavio Leitner
67396e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.resend_igmp);
674c2952c31SFlavio Leitner }
675d61e4038SJoe Perches static DEVICE_ATTR(resend_igmp, 0644,
676dc3e5d18SNikolay Aleksandrov bonding_show_resend_igmp, bonding_sysfs_store_option);
677c2952c31SFlavio Leitner
6787eacd038SNeil Horman
bonding_show_lp_interval(struct device * d,struct device_attribute * attr,char * buf)6797eacd038SNeil Horman static ssize_t bonding_show_lp_interval(struct device *d,
6807eacd038SNeil Horman struct device_attribute *attr,
6817eacd038SNeil Horman char *buf)
6827eacd038SNeil Horman {
6837eacd038SNeil Horman struct bonding *bond = to_bond(d);
684dc3e5d18SNikolay Aleksandrov
68596e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.lp_interval);
6867eacd038SNeil Horman }
687d61e4038SJoe Perches static DEVICE_ATTR(lp_interval, 0644,
688dc3e5d18SNikolay Aleksandrov bonding_show_lp_interval, bonding_sysfs_store_option);
6897eacd038SNeil Horman
bonding_show_tlb_dynamic_lb(struct device * d,struct device_attribute * attr,char * buf)690e9f0fb88SMahesh Bandewar static ssize_t bonding_show_tlb_dynamic_lb(struct device *d,
691e9f0fb88SMahesh Bandewar struct device_attribute *attr,
692e9f0fb88SMahesh Bandewar char *buf)
693e9f0fb88SMahesh Bandewar {
694e9f0fb88SMahesh Bandewar struct bonding *bond = to_bond(d);
69586a5ad0aSYufeng Mo
69696e07181SWang Yufen return sysfs_emit(buf, "%d\n", bond->params.tlb_dynamic_lb);
697e9f0fb88SMahesh Bandewar }
698d61e4038SJoe Perches static DEVICE_ATTR(tlb_dynamic_lb, 0644,
699dc3e5d18SNikolay Aleksandrov bonding_show_tlb_dynamic_lb, bonding_sysfs_store_option);
700e9f0fb88SMahesh Bandewar
bonding_show_packets_per_slave(struct device * d,struct device_attribute * attr,char * buf)70173958329SNikolay Aleksandrov static ssize_t bonding_show_packets_per_slave(struct device *d,
70273958329SNikolay Aleksandrov struct device_attribute *attr,
70373958329SNikolay Aleksandrov char *buf)
70473958329SNikolay Aleksandrov {
70573958329SNikolay Aleksandrov struct bonding *bond = to_bond(d);
706a752a8b9SNikolay Aleksandrov unsigned int packets_per_slave = bond->params.packets_per_slave;
707dc3e5d18SNikolay Aleksandrov
70896e07181SWang Yufen return sysfs_emit(buf, "%u\n", packets_per_slave);
70973958329SNikolay Aleksandrov }
710d61e4038SJoe Perches static DEVICE_ATTR(packets_per_slave, 0644,
711dc3e5d18SNikolay Aleksandrov bonding_show_packets_per_slave, bonding_sysfs_store_option);
71273958329SNikolay Aleksandrov
bonding_show_ad_actor_sys_prio(struct device * d,struct device_attribute * attr,char * buf)7136791e466SMahesh Bandewar static ssize_t bonding_show_ad_actor_sys_prio(struct device *d,
7146791e466SMahesh Bandewar struct device_attribute *attr,
7156791e466SMahesh Bandewar char *buf)
7166791e466SMahesh Bandewar {
7176791e466SMahesh Bandewar struct bonding *bond = to_bond(d);
7186791e466SMahesh Bandewar
7194cd6b475SMahesh Bandewar if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN))
72096e07181SWang Yufen return sysfs_emit(buf, "%hu\n", bond->params.ad_actor_sys_prio);
7216791e466SMahesh Bandewar
7226791e466SMahesh Bandewar return 0;
7236791e466SMahesh Bandewar }
724d61e4038SJoe Perches static DEVICE_ATTR(ad_actor_sys_prio, 0644,
7256791e466SMahesh Bandewar bonding_show_ad_actor_sys_prio, bonding_sysfs_store_option);
7266791e466SMahesh Bandewar
bonding_show_ad_actor_system(struct device * d,struct device_attribute * attr,char * buf)72774514957SMahesh Bandewar static ssize_t bonding_show_ad_actor_system(struct device *d,
72874514957SMahesh Bandewar struct device_attribute *attr,
72974514957SMahesh Bandewar char *buf)
73074514957SMahesh Bandewar {
73174514957SMahesh Bandewar struct bonding *bond = to_bond(d);
73274514957SMahesh Bandewar
7334cd6b475SMahesh Bandewar if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN))
73496e07181SWang Yufen return sysfs_emit(buf, "%pM\n", bond->params.ad_actor_system);
73574514957SMahesh Bandewar
73674514957SMahesh Bandewar return 0;
73774514957SMahesh Bandewar }
73874514957SMahesh Bandewar
739d61e4038SJoe Perches static DEVICE_ATTR(ad_actor_system, 0644,
74074514957SMahesh Bandewar bonding_show_ad_actor_system, bonding_sysfs_store_option);
74174514957SMahesh Bandewar
bonding_show_ad_user_port_key(struct device * d,struct device_attribute * attr,char * buf)742d22a5fc0SMahesh Bandewar static ssize_t bonding_show_ad_user_port_key(struct device *d,
743d22a5fc0SMahesh Bandewar struct device_attribute *attr,
744d22a5fc0SMahesh Bandewar char *buf)
745d22a5fc0SMahesh Bandewar {
746d22a5fc0SMahesh Bandewar struct bonding *bond = to_bond(d);
747d22a5fc0SMahesh Bandewar
7484cd6b475SMahesh Bandewar if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN))
74996e07181SWang Yufen return sysfs_emit(buf, "%hu\n", bond->params.ad_user_port_key);
750d22a5fc0SMahesh Bandewar
751d22a5fc0SMahesh Bandewar return 0;
752d22a5fc0SMahesh Bandewar }
753d61e4038SJoe Perches static DEVICE_ATTR(ad_user_port_key, 0644,
754d22a5fc0SMahesh Bandewar bonding_show_ad_user_port_key, bonding_sysfs_store_option);
755d22a5fc0SMahesh Bandewar
756b76cdba9SMitch Williams static struct attribute *per_bond_attrs[] = {
75743cb76d9SGreg Kroah-Hartman &dev_attr_slaves.attr,
75843cb76d9SGreg Kroah-Hartman &dev_attr_mode.attr,
759dd957c57SJay Vosburgh &dev_attr_fail_over_mac.attr,
76043cb76d9SGreg Kroah-Hartman &dev_attr_arp_validate.attr,
7618599b52eSVeaceslav Falico &dev_attr_arp_all_targets.attr,
76243cb76d9SGreg Kroah-Hartman &dev_attr_arp_interval.attr,
76343cb76d9SGreg Kroah-Hartman &dev_attr_arp_ip_target.attr,
76443cb76d9SGreg Kroah-Hartman &dev_attr_downdelay.attr,
76543cb76d9SGreg Kroah-Hartman &dev_attr_updelay.attr,
76607a4ddecSVincent Bernat &dev_attr_peer_notif_delay.attr,
7673a755cd8SHangbin Liu &dev_attr_lacp_active.attr,
76843cb76d9SGreg Kroah-Hartman &dev_attr_lacp_rate.attr,
769fd989c83SJay Vosburgh &dev_attr_ad_select.attr,
77043cb76d9SGreg Kroah-Hartman &dev_attr_xmit_hash_policy.attr,
771ad246c99SBen Hutchings &dev_attr_num_grat_arp.attr,
772ad246c99SBen Hutchings &dev_attr_num_unsol_na.attr,
77343cb76d9SGreg Kroah-Hartman &dev_attr_miimon.attr,
77443cb76d9SGreg Kroah-Hartman &dev_attr_primary.attr,
775a549952aSJiri Pirko &dev_attr_primary_reselect.attr,
77643cb76d9SGreg Kroah-Hartman &dev_attr_use_carrier.attr,
77743cb76d9SGreg Kroah-Hartman &dev_attr_active_slave.attr,
77843cb76d9SGreg Kroah-Hartman &dev_attr_mii_status.attr,
77943cb76d9SGreg Kroah-Hartman &dev_attr_ad_aggregator.attr,
78043cb76d9SGreg Kroah-Hartman &dev_attr_ad_num_ports.attr,
78143cb76d9SGreg Kroah-Hartman &dev_attr_ad_actor_key.attr,
78243cb76d9SGreg Kroah-Hartman &dev_attr_ad_partner_key.attr,
78343cb76d9SGreg Kroah-Hartman &dev_attr_ad_partner_mac.attr,
784bb1d9123SAndy Gospodarek &dev_attr_queue_id.attr,
785ebd8e497SAndy Gospodarek &dev_attr_all_slaves_active.attr,
786c2952c31SFlavio Leitner &dev_attr_resend_igmp.attr,
787655f8919Sstephen hemminger &dev_attr_min_links.attr,
7887eacd038SNeil Horman &dev_attr_lp_interval.attr,
78973958329SNikolay Aleksandrov &dev_attr_packets_per_slave.attr,
790e9f0fb88SMahesh Bandewar &dev_attr_tlb_dynamic_lb.attr,
7916791e466SMahesh Bandewar &dev_attr_ad_actor_sys_prio.attr,
79274514957SMahesh Bandewar &dev_attr_ad_actor_system.attr,
793d22a5fc0SMahesh Bandewar &dev_attr_ad_user_port_key.attr,
7945944b5abSHangbin Liu &dev_attr_arp_missed_max.attr,
795b76cdba9SMitch Williams NULL,
796b76cdba9SMitch Williams };
797b76cdba9SMitch Williams
79802dbbef0SArvind Yadav static const struct attribute_group bonding_group = {
799b76cdba9SMitch Williams .name = "bonding",
800b76cdba9SMitch Williams .attrs = per_bond_attrs,
801b76cdba9SMitch Williams };
802b76cdba9SMitch Williams
803dc3e5d18SNikolay Aleksandrov /* Initialize sysfs. This sets up the bonding_masters file in
804b76cdba9SMitch Williams * /sys/class/net.
805b76cdba9SMitch Williams */
bond_create_sysfs(struct bond_net * bn)806*e08190efSZhengchao Shao int __net_init bond_create_sysfs(struct bond_net *bn)
807b76cdba9SMitch Williams {
808b8a9787eSJay Vosburgh int ret;
809b76cdba9SMitch Williams
8104c22400aSEric W. Biederman bn->class_attr_bonding_masters = class_attr_bonding_masters;
81101718e36SEric W. Biederman sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
8124c22400aSEric W. Biederman
81358292cbeSTejun Heo ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters,
81458292cbeSTejun Heo bn->net);
815dc3e5d18SNikolay Aleksandrov /* Permit multiple loads of the module by ignoring failures to
816877cbd36SJay Vosburgh * create the bonding_masters sysfs file. Bonding devices
817877cbd36SJay Vosburgh * created by second or subsequent loads of the module will
818877cbd36SJay Vosburgh * not be listed in, or controllable by, bonding_masters, but
819877cbd36SJay Vosburgh * will have the usual "bonding" sysfs directory.
820877cbd36SJay Vosburgh *
821877cbd36SJay Vosburgh * This is done to preserve backwards compatibility for
822877cbd36SJay Vosburgh * initscripts/sysconfig, which load bonding multiple times to
823877cbd36SJay Vosburgh * configure multiple bonding devices.
824877cbd36SJay Vosburgh */
825877cbd36SJay Vosburgh if (ret == -EEXIST) {
82638d2f38bSStephen Hemminger /* Is someone being kinky and naming a device bonding_master? */
827caa9b35fSAntoine Tenart if (netdev_name_in_use(bn->net,
82838d2f38bSStephen Hemminger class_attr_bonding_masters.attr.name))
82990194264SJoe Perches pr_err("network device named %s already exists in sysfs\n",
83038d2f38bSStephen Hemminger class_attr_bonding_masters.attr.name);
831130aa61aSStephen Hemminger ret = 0;
83238d2f38bSStephen Hemminger }
833b76cdba9SMitch Williams
834b76cdba9SMitch Williams return ret;
835b76cdba9SMitch Williams
836b76cdba9SMitch Williams }
837b76cdba9SMitch Williams
838dc3e5d18SNikolay Aleksandrov /* Remove /sys/class/net/bonding_masters. */
bond_destroy_sysfs(struct bond_net * bn)839*e08190efSZhengchao Shao void __net_exit bond_destroy_sysfs(struct bond_net *bn)
840b76cdba9SMitch Williams {
84158292cbeSTejun Heo netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net);
842b76cdba9SMitch Williams }
843b76cdba9SMitch Williams
844dc3e5d18SNikolay Aleksandrov /* Initialize sysfs for each bond. This sets up and registers
845b76cdba9SMitch Williams * the 'bondctl' directory for each individual bond under /sys/class/net.
846b76cdba9SMitch Williams */
bond_prepare_sysfs_group(struct bonding * bond)8476151b3d4SEric W. Biederman void bond_prepare_sysfs_group(struct bonding *bond)
848b76cdba9SMitch Williams {
8496151b3d4SEric W. Biederman bond->dev->sysfs_groups[0] = &bonding_group;
850b76cdba9SMitch Williams }
851b76cdba9SMitch Williams
852