1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/sched/signal.h>
12*4882a593Smuzhiyun #include <linux/fs.h>
13*4882a593Smuzhiyun #include <linux/types.h>
14*4882a593Smuzhiyun #include <linux/string.h>
15*4882a593Smuzhiyun #include <linux/netdevice.h>
16*4882a593Smuzhiyun #include <linux/inetdevice.h>
17*4882a593Smuzhiyun #include <linux/in.h>
18*4882a593Smuzhiyun #include <linux/sysfs.h>
19*4882a593Smuzhiyun #include <linux/ctype.h>
20*4882a593Smuzhiyun #include <linux/inet.h>
21*4882a593Smuzhiyun #include <linux/rtnetlink.h>
22*4882a593Smuzhiyun #include <linux/etherdevice.h>
23*4882a593Smuzhiyun #include <net/net_namespace.h>
24*4882a593Smuzhiyun #include <net/netns/generic.h>
25*4882a593Smuzhiyun #include <linux/nsproxy.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include <net/bonding.h>
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd))))
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /* "show" function for the bond_masters attribute.
32*4882a593Smuzhiyun * The class parameter is ignored.
33*4882a593Smuzhiyun */
bonding_show_bonds(struct class * cls,struct class_attribute * attr,char * buf)34*4882a593Smuzhiyun static ssize_t bonding_show_bonds(struct class *cls,
35*4882a593Smuzhiyun struct class_attribute *attr,
36*4882a593Smuzhiyun char *buf)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun struct bond_net *bn =
39*4882a593Smuzhiyun container_of(attr, struct bond_net, class_attr_bonding_masters);
40*4882a593Smuzhiyun int res = 0;
41*4882a593Smuzhiyun struct bonding *bond;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun rtnl_lock();
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun list_for_each_entry(bond, &bn->dev_list, bond_list) {
46*4882a593Smuzhiyun if (res > (PAGE_SIZE - IFNAMSIZ)) {
47*4882a593Smuzhiyun /* not enough space for another interface name */
48*4882a593Smuzhiyun if ((PAGE_SIZE - res) > 10)
49*4882a593Smuzhiyun res = PAGE_SIZE - 10;
50*4882a593Smuzhiyun res += sprintf(buf + res, "++more++ ");
51*4882a593Smuzhiyun break;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun res += sprintf(buf + res, "%s ", bond->dev->name);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun if (res)
56*4882a593Smuzhiyun buf[res-1] = '\n'; /* eat the leftover space */
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun rtnl_unlock();
59*4882a593Smuzhiyun return res;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
bond_get_by_name(struct bond_net * bn,const char * ifname)62*4882a593Smuzhiyun static struct net_device *bond_get_by_name(struct bond_net *bn, const char *ifname)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun struct bonding *bond;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun list_for_each_entry(bond, &bn->dev_list, bond_list) {
67*4882a593Smuzhiyun if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
68*4882a593Smuzhiyun return bond->dev;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun return NULL;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /* "store" function for the bond_masters attribute. This is what
74*4882a593Smuzhiyun * creates and deletes entire bonds.
75*4882a593Smuzhiyun *
76*4882a593Smuzhiyun * The class parameter is ignored.
77*4882a593Smuzhiyun */
bonding_store_bonds(struct class * cls,struct class_attribute * attr,const char * buffer,size_t count)78*4882a593Smuzhiyun static ssize_t bonding_store_bonds(struct class *cls,
79*4882a593Smuzhiyun struct class_attribute *attr,
80*4882a593Smuzhiyun const char *buffer, size_t count)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun struct bond_net *bn =
83*4882a593Smuzhiyun container_of(attr, struct bond_net, class_attr_bonding_masters);
84*4882a593Smuzhiyun char command[IFNAMSIZ + 1] = {0, };
85*4882a593Smuzhiyun char *ifname;
86*4882a593Smuzhiyun int rv, res = count;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
89*4882a593Smuzhiyun ifname = command + 1;
90*4882a593Smuzhiyun if ((strlen(command) <= 1) ||
91*4882a593Smuzhiyun !dev_valid_name(ifname))
92*4882a593Smuzhiyun goto err_no_cmd;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (command[0] == '+') {
95*4882a593Smuzhiyun pr_info("%s is being created...\n", ifname);
96*4882a593Smuzhiyun rv = bond_create(bn->net, ifname);
97*4882a593Smuzhiyun if (rv) {
98*4882a593Smuzhiyun if (rv == -EEXIST)
99*4882a593Smuzhiyun pr_info("%s already exists\n", ifname);
100*4882a593Smuzhiyun else
101*4882a593Smuzhiyun pr_info("%s creation failed\n", ifname);
102*4882a593Smuzhiyun res = rv;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun } else if (command[0] == '-') {
105*4882a593Smuzhiyun struct net_device *bond_dev;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun rtnl_lock();
108*4882a593Smuzhiyun bond_dev = bond_get_by_name(bn, ifname);
109*4882a593Smuzhiyun if (bond_dev) {
110*4882a593Smuzhiyun pr_info("%s is being deleted...\n", ifname);
111*4882a593Smuzhiyun unregister_netdevice(bond_dev);
112*4882a593Smuzhiyun } else {
113*4882a593Smuzhiyun pr_err("unable to delete non-existent %s\n", ifname);
114*4882a593Smuzhiyun res = -ENODEV;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun rtnl_unlock();
117*4882a593Smuzhiyun } else
118*4882a593Smuzhiyun goto err_no_cmd;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /* Always return either count or an error. If you return 0, you'll
121*4882a593Smuzhiyun * get called forever, which is bad.
122*4882a593Smuzhiyun */
123*4882a593Smuzhiyun return res;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun err_no_cmd:
126*4882a593Smuzhiyun pr_err("no command found in bonding_masters - use +ifname or -ifname\n");
127*4882a593Smuzhiyun return -EPERM;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /* class attribute for bond_masters file. This ends up in /sys/class/net */
131*4882a593Smuzhiyun static const struct class_attribute class_attr_bonding_masters = {
132*4882a593Smuzhiyun .attr = {
133*4882a593Smuzhiyun .name = "bonding_masters",
134*4882a593Smuzhiyun .mode = 0644,
135*4882a593Smuzhiyun },
136*4882a593Smuzhiyun .show = bonding_show_bonds,
137*4882a593Smuzhiyun .store = bonding_store_bonds,
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* 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)141*4882a593Smuzhiyun static ssize_t bonding_sysfs_store_option(struct device *d,
142*4882a593Smuzhiyun struct device_attribute *attr,
143*4882a593Smuzhiyun const char *buffer, size_t count)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
146*4882a593Smuzhiyun const struct bond_option *opt;
147*4882a593Smuzhiyun char *buffer_clone;
148*4882a593Smuzhiyun int ret;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun opt = bond_opt_get_by_name(attr->attr.name);
151*4882a593Smuzhiyun if (WARN_ON(!opt))
152*4882a593Smuzhiyun return -ENOENT;
153*4882a593Smuzhiyun buffer_clone = kstrndup(buffer, count, GFP_KERNEL);
154*4882a593Smuzhiyun if (!buffer_clone)
155*4882a593Smuzhiyun return -ENOMEM;
156*4882a593Smuzhiyun ret = bond_opt_tryset_rtnl(bond, opt->id, buffer_clone);
157*4882a593Smuzhiyun if (!ret)
158*4882a593Smuzhiyun ret = count;
159*4882a593Smuzhiyun kfree(buffer_clone);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun return ret;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* Show the slaves in the current bond. */
bonding_show_slaves(struct device * d,struct device_attribute * attr,char * buf)165*4882a593Smuzhiyun static ssize_t bonding_show_slaves(struct device *d,
166*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
169*4882a593Smuzhiyun struct list_head *iter;
170*4882a593Smuzhiyun struct slave *slave;
171*4882a593Smuzhiyun int res = 0;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun if (!rtnl_trylock())
174*4882a593Smuzhiyun return restart_syscall();
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun bond_for_each_slave(bond, slave, iter) {
177*4882a593Smuzhiyun if (res > (PAGE_SIZE - IFNAMSIZ)) {
178*4882a593Smuzhiyun /* not enough space for another interface name */
179*4882a593Smuzhiyun if ((PAGE_SIZE - res) > 10)
180*4882a593Smuzhiyun res = PAGE_SIZE - 10;
181*4882a593Smuzhiyun res += sprintf(buf + res, "++more++ ");
182*4882a593Smuzhiyun break;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun res += sprintf(buf + res, "%s ", slave->dev->name);
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun rtnl_unlock();
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (res)
190*4882a593Smuzhiyun buf[res-1] = '\n'; /* eat the leftover space */
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun return res;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun static DEVICE_ATTR(slaves, 0644, bonding_show_slaves,
195*4882a593Smuzhiyun bonding_sysfs_store_option);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* Show the bonding mode. */
bonding_show_mode(struct device * d,struct device_attribute * attr,char * buf)198*4882a593Smuzhiyun static ssize_t bonding_show_mode(struct device *d,
199*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
202*4882a593Smuzhiyun const struct bond_opt_value *val;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun val = bond_opt_get_val(BOND_OPT_MODE, BOND_MODE(bond));
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun return sprintf(buf, "%s %d\n", val->string, BOND_MODE(bond));
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun static DEVICE_ATTR(mode, 0644, bonding_show_mode, bonding_sysfs_store_option);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* Show the bonding transmit hash method. */
bonding_show_xmit_hash(struct device * d,struct device_attribute * attr,char * buf)211*4882a593Smuzhiyun static ssize_t bonding_show_xmit_hash(struct device *d,
212*4882a593Smuzhiyun struct device_attribute *attr,
213*4882a593Smuzhiyun char *buf)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
216*4882a593Smuzhiyun const struct bond_opt_value *val;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun val = bond_opt_get_val(BOND_OPT_XMIT_HASH, bond->params.xmit_policy);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun return sprintf(buf, "%s %d\n", val->string, bond->params.xmit_policy);
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun static DEVICE_ATTR(xmit_hash_policy, 0644,
223*4882a593Smuzhiyun bonding_show_xmit_hash, bonding_sysfs_store_option);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /* Show arp_validate. */
bonding_show_arp_validate(struct device * d,struct device_attribute * attr,char * buf)226*4882a593Smuzhiyun static ssize_t bonding_show_arp_validate(struct device *d,
227*4882a593Smuzhiyun struct device_attribute *attr,
228*4882a593Smuzhiyun char *buf)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
231*4882a593Smuzhiyun const struct bond_opt_value *val;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun val = bond_opt_get_val(BOND_OPT_ARP_VALIDATE,
234*4882a593Smuzhiyun bond->params.arp_validate);
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun return sprintf(buf, "%s %d\n", val->string, bond->params.arp_validate);
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun static DEVICE_ATTR(arp_validate, 0644, bonding_show_arp_validate,
239*4882a593Smuzhiyun bonding_sysfs_store_option);
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun /* Show arp_all_targets. */
bonding_show_arp_all_targets(struct device * d,struct device_attribute * attr,char * buf)242*4882a593Smuzhiyun static ssize_t bonding_show_arp_all_targets(struct device *d,
243*4882a593Smuzhiyun struct device_attribute *attr,
244*4882a593Smuzhiyun char *buf)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
247*4882a593Smuzhiyun const struct bond_opt_value *val;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun val = bond_opt_get_val(BOND_OPT_ARP_ALL_TARGETS,
250*4882a593Smuzhiyun bond->params.arp_all_targets);
251*4882a593Smuzhiyun return sprintf(buf, "%s %d\n",
252*4882a593Smuzhiyun val->string, bond->params.arp_all_targets);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun static DEVICE_ATTR(arp_all_targets, 0644,
255*4882a593Smuzhiyun bonding_show_arp_all_targets, bonding_sysfs_store_option);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun /* Show fail_over_mac. */
bonding_show_fail_over_mac(struct device * d,struct device_attribute * attr,char * buf)258*4882a593Smuzhiyun static ssize_t bonding_show_fail_over_mac(struct device *d,
259*4882a593Smuzhiyun struct device_attribute *attr,
260*4882a593Smuzhiyun char *buf)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
263*4882a593Smuzhiyun const struct bond_opt_value *val;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun val = bond_opt_get_val(BOND_OPT_FAIL_OVER_MAC,
266*4882a593Smuzhiyun bond->params.fail_over_mac);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun return sprintf(buf, "%s %d\n", val->string, bond->params.fail_over_mac);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun static DEVICE_ATTR(fail_over_mac, 0644,
271*4882a593Smuzhiyun bonding_show_fail_over_mac, bonding_sysfs_store_option);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun /* Show the arp timer interval. */
bonding_show_arp_interval(struct device * d,struct device_attribute * attr,char * buf)274*4882a593Smuzhiyun static ssize_t bonding_show_arp_interval(struct device *d,
275*4882a593Smuzhiyun struct device_attribute *attr,
276*4882a593Smuzhiyun char *buf)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.arp_interval);
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun static DEVICE_ATTR(arp_interval, 0644,
283*4882a593Smuzhiyun bonding_show_arp_interval, bonding_sysfs_store_option);
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /* Show the arp targets. */
bonding_show_arp_targets(struct device * d,struct device_attribute * attr,char * buf)286*4882a593Smuzhiyun static ssize_t bonding_show_arp_targets(struct device *d,
287*4882a593Smuzhiyun struct device_attribute *attr,
288*4882a593Smuzhiyun char *buf)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
291*4882a593Smuzhiyun int i, res = 0;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
294*4882a593Smuzhiyun if (bond->params.arp_targets[i])
295*4882a593Smuzhiyun res += sprintf(buf + res, "%pI4 ",
296*4882a593Smuzhiyun &bond->params.arp_targets[i]);
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun if (res)
299*4882a593Smuzhiyun buf[res-1] = '\n'; /* eat the leftover space */
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun return res;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun static DEVICE_ATTR(arp_ip_target, 0644,
304*4882a593Smuzhiyun bonding_show_arp_targets, bonding_sysfs_store_option);
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /* Show the up and down delays. */
bonding_show_downdelay(struct device * d,struct device_attribute * attr,char * buf)307*4882a593Smuzhiyun static ssize_t bonding_show_downdelay(struct device *d,
308*4882a593Smuzhiyun struct device_attribute *attr,
309*4882a593Smuzhiyun char *buf)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun static DEVICE_ATTR(downdelay, 0644,
316*4882a593Smuzhiyun bonding_show_downdelay, bonding_sysfs_store_option);
317*4882a593Smuzhiyun
bonding_show_updelay(struct device * d,struct device_attribute * attr,char * buf)318*4882a593Smuzhiyun static ssize_t bonding_show_updelay(struct device *d,
319*4882a593Smuzhiyun struct device_attribute *attr,
320*4882a593Smuzhiyun char *buf)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon);
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun static DEVICE_ATTR(updelay, 0644,
328*4882a593Smuzhiyun bonding_show_updelay, bonding_sysfs_store_option);
329*4882a593Smuzhiyun
bonding_show_peer_notif_delay(struct device * d,struct device_attribute * attr,char * buf)330*4882a593Smuzhiyun static ssize_t bonding_show_peer_notif_delay(struct device *d,
331*4882a593Smuzhiyun struct device_attribute *attr,
332*4882a593Smuzhiyun char *buf)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun return sprintf(buf, "%d\n",
337*4882a593Smuzhiyun bond->params.peer_notif_delay * bond->params.miimon);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun static DEVICE_ATTR(peer_notif_delay, 0644,
340*4882a593Smuzhiyun bonding_show_peer_notif_delay, bonding_sysfs_store_option);
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /* Show the LACP interval. */
bonding_show_lacp(struct device * d,struct device_attribute * attr,char * buf)343*4882a593Smuzhiyun static ssize_t bonding_show_lacp(struct device *d,
344*4882a593Smuzhiyun struct device_attribute *attr,
345*4882a593Smuzhiyun char *buf)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
348*4882a593Smuzhiyun const struct bond_opt_value *val;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun val = bond_opt_get_val(BOND_OPT_LACP_RATE, bond->params.lacp_fast);
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun return sprintf(buf, "%s %d\n", val->string, bond->params.lacp_fast);
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun static DEVICE_ATTR(lacp_rate, 0644,
355*4882a593Smuzhiyun bonding_show_lacp, bonding_sysfs_store_option);
356*4882a593Smuzhiyun
bonding_show_min_links(struct device * d,struct device_attribute * attr,char * buf)357*4882a593Smuzhiyun static ssize_t bonding_show_min_links(struct device *d,
358*4882a593Smuzhiyun struct device_attribute *attr,
359*4882a593Smuzhiyun char *buf)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun return sprintf(buf, "%u\n", bond->params.min_links);
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun static DEVICE_ATTR(min_links, 0644,
366*4882a593Smuzhiyun bonding_show_min_links, bonding_sysfs_store_option);
367*4882a593Smuzhiyun
bonding_show_ad_select(struct device * d,struct device_attribute * attr,char * buf)368*4882a593Smuzhiyun static ssize_t bonding_show_ad_select(struct device *d,
369*4882a593Smuzhiyun struct device_attribute *attr,
370*4882a593Smuzhiyun char *buf)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
373*4882a593Smuzhiyun const struct bond_opt_value *val;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun val = bond_opt_get_val(BOND_OPT_AD_SELECT, bond->params.ad_select);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun return sprintf(buf, "%s %d\n", val->string, bond->params.ad_select);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun static DEVICE_ATTR(ad_select, 0644,
380*4882a593Smuzhiyun bonding_show_ad_select, bonding_sysfs_store_option);
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun /* 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)383*4882a593Smuzhiyun static ssize_t bonding_show_num_peer_notif(struct device *d,
384*4882a593Smuzhiyun struct device_attribute *attr,
385*4882a593Smuzhiyun char *buf)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
388*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.num_peer_notif);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun static DEVICE_ATTR(num_grat_arp, 0644,
391*4882a593Smuzhiyun bonding_show_num_peer_notif, bonding_sysfs_store_option);
392*4882a593Smuzhiyun static DEVICE_ATTR(num_unsol_na, 0644,
393*4882a593Smuzhiyun bonding_show_num_peer_notif, bonding_sysfs_store_option);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun /* Show the MII monitor interval. */
bonding_show_miimon(struct device * d,struct device_attribute * attr,char * buf)396*4882a593Smuzhiyun static ssize_t bonding_show_miimon(struct device *d,
397*4882a593Smuzhiyun struct device_attribute *attr,
398*4882a593Smuzhiyun char *buf)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.miimon);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun static DEVICE_ATTR(miimon, 0644,
405*4882a593Smuzhiyun bonding_show_miimon, bonding_sysfs_store_option);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /* Show the primary slave. */
bonding_show_primary(struct device * d,struct device_attribute * attr,char * buf)408*4882a593Smuzhiyun static ssize_t bonding_show_primary(struct device *d,
409*4882a593Smuzhiyun struct device_attribute *attr,
410*4882a593Smuzhiyun char *buf)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
413*4882a593Smuzhiyun struct slave *primary;
414*4882a593Smuzhiyun int count = 0;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun rcu_read_lock();
417*4882a593Smuzhiyun primary = rcu_dereference(bond->primary_slave);
418*4882a593Smuzhiyun if (primary)
419*4882a593Smuzhiyun count = sprintf(buf, "%s\n", primary->dev->name);
420*4882a593Smuzhiyun rcu_read_unlock();
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun return count;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun static DEVICE_ATTR(primary, 0644,
425*4882a593Smuzhiyun bonding_show_primary, bonding_sysfs_store_option);
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun /* Show the primary_reselect flag. */
bonding_show_primary_reselect(struct device * d,struct device_attribute * attr,char * buf)428*4882a593Smuzhiyun static ssize_t bonding_show_primary_reselect(struct device *d,
429*4882a593Smuzhiyun struct device_attribute *attr,
430*4882a593Smuzhiyun char *buf)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
433*4882a593Smuzhiyun const struct bond_opt_value *val;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun val = bond_opt_get_val(BOND_OPT_PRIMARY_RESELECT,
436*4882a593Smuzhiyun bond->params.primary_reselect);
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun return sprintf(buf, "%s %d\n",
439*4882a593Smuzhiyun val->string, bond->params.primary_reselect);
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun static DEVICE_ATTR(primary_reselect, 0644,
442*4882a593Smuzhiyun bonding_show_primary_reselect, bonding_sysfs_store_option);
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun /* Show the use_carrier flag. */
bonding_show_carrier(struct device * d,struct device_attribute * attr,char * buf)445*4882a593Smuzhiyun static ssize_t bonding_show_carrier(struct device *d,
446*4882a593Smuzhiyun struct device_attribute *attr,
447*4882a593Smuzhiyun char *buf)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.use_carrier);
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun static DEVICE_ATTR(use_carrier, 0644,
454*4882a593Smuzhiyun bonding_show_carrier, bonding_sysfs_store_option);
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun /* Show currently active_slave. */
bonding_show_active_slave(struct device * d,struct device_attribute * attr,char * buf)458*4882a593Smuzhiyun static ssize_t bonding_show_active_slave(struct device *d,
459*4882a593Smuzhiyun struct device_attribute *attr,
460*4882a593Smuzhiyun char *buf)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
463*4882a593Smuzhiyun struct net_device *slave_dev;
464*4882a593Smuzhiyun int count = 0;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun rcu_read_lock();
467*4882a593Smuzhiyun slave_dev = bond_option_active_slave_get_rcu(bond);
468*4882a593Smuzhiyun if (slave_dev)
469*4882a593Smuzhiyun count = sprintf(buf, "%s\n", slave_dev->name);
470*4882a593Smuzhiyun rcu_read_unlock();
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun return count;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun static DEVICE_ATTR(active_slave, 0644,
475*4882a593Smuzhiyun bonding_show_active_slave, bonding_sysfs_store_option);
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun /* Show link status of the bond interface. */
bonding_show_mii_status(struct device * d,struct device_attribute * attr,char * buf)478*4882a593Smuzhiyun static ssize_t bonding_show_mii_status(struct device *d,
479*4882a593Smuzhiyun struct device_attribute *attr,
480*4882a593Smuzhiyun char *buf)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
483*4882a593Smuzhiyun bool active = netif_carrier_ok(bond->dev);
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun return sprintf(buf, "%s\n", active ? "up" : "down");
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun static DEVICE_ATTR(mii_status, 0444, bonding_show_mii_status, NULL);
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun /* Show current 802.3ad aggregator ID. */
bonding_show_ad_aggregator(struct device * d,struct device_attribute * attr,char * buf)490*4882a593Smuzhiyun static ssize_t bonding_show_ad_aggregator(struct device *d,
491*4882a593Smuzhiyun struct device_attribute *attr,
492*4882a593Smuzhiyun char *buf)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun int count = 0;
495*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun if (BOND_MODE(bond) == BOND_MODE_8023AD) {
498*4882a593Smuzhiyun struct ad_info ad_info;
499*4882a593Smuzhiyun count = sprintf(buf, "%d\n",
500*4882a593Smuzhiyun bond_3ad_get_active_agg_info(bond, &ad_info)
501*4882a593Smuzhiyun ? 0 : ad_info.aggregator_id);
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun return count;
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun static DEVICE_ATTR(ad_aggregator, 0444, bonding_show_ad_aggregator, NULL);
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun /* Show number of active 802.3ad ports. */
bonding_show_ad_num_ports(struct device * d,struct device_attribute * attr,char * buf)510*4882a593Smuzhiyun static ssize_t bonding_show_ad_num_ports(struct device *d,
511*4882a593Smuzhiyun struct device_attribute *attr,
512*4882a593Smuzhiyun char *buf)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun int count = 0;
515*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun if (BOND_MODE(bond) == BOND_MODE_8023AD) {
518*4882a593Smuzhiyun struct ad_info ad_info;
519*4882a593Smuzhiyun count = sprintf(buf, "%d\n",
520*4882a593Smuzhiyun bond_3ad_get_active_agg_info(bond, &ad_info)
521*4882a593Smuzhiyun ? 0 : ad_info.ports);
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun return count;
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun static DEVICE_ATTR(ad_num_ports, 0444, bonding_show_ad_num_ports, NULL);
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /* Show current 802.3ad actor key. */
bonding_show_ad_actor_key(struct device * d,struct device_attribute * attr,char * buf)530*4882a593Smuzhiyun static ssize_t bonding_show_ad_actor_key(struct device *d,
531*4882a593Smuzhiyun struct device_attribute *attr,
532*4882a593Smuzhiyun char *buf)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun int count = 0;
535*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN)) {
538*4882a593Smuzhiyun struct ad_info ad_info;
539*4882a593Smuzhiyun count = sprintf(buf, "%d\n",
540*4882a593Smuzhiyun bond_3ad_get_active_agg_info(bond, &ad_info)
541*4882a593Smuzhiyun ? 0 : ad_info.actor_key);
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun return count;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun static DEVICE_ATTR(ad_actor_key, 0444, bonding_show_ad_actor_key, NULL);
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun /* Show current 802.3ad partner key. */
bonding_show_ad_partner_key(struct device * d,struct device_attribute * attr,char * buf)550*4882a593Smuzhiyun static ssize_t bonding_show_ad_partner_key(struct device *d,
551*4882a593Smuzhiyun struct device_attribute *attr,
552*4882a593Smuzhiyun char *buf)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun int count = 0;
555*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN)) {
558*4882a593Smuzhiyun struct ad_info ad_info;
559*4882a593Smuzhiyun count = sprintf(buf, "%d\n",
560*4882a593Smuzhiyun bond_3ad_get_active_agg_info(bond, &ad_info)
561*4882a593Smuzhiyun ? 0 : ad_info.partner_key);
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun return count;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun static DEVICE_ATTR(ad_partner_key, 0444, bonding_show_ad_partner_key, NULL);
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun /* Show current 802.3ad partner mac. */
bonding_show_ad_partner_mac(struct device * d,struct device_attribute * attr,char * buf)570*4882a593Smuzhiyun static ssize_t bonding_show_ad_partner_mac(struct device *d,
571*4882a593Smuzhiyun struct device_attribute *attr,
572*4882a593Smuzhiyun char *buf)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun int count = 0;
575*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN)) {
578*4882a593Smuzhiyun struct ad_info ad_info;
579*4882a593Smuzhiyun if (!bond_3ad_get_active_agg_info(bond, &ad_info))
580*4882a593Smuzhiyun count = sprintf(buf, "%pM\n", ad_info.partner_system);
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun return count;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun static DEVICE_ATTR(ad_partner_mac, 0444, bonding_show_ad_partner_mac, NULL);
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun /* Show the queue_ids of the slaves in the current bond. */
bonding_show_queue_id(struct device * d,struct device_attribute * attr,char * buf)588*4882a593Smuzhiyun static ssize_t bonding_show_queue_id(struct device *d,
589*4882a593Smuzhiyun struct device_attribute *attr,
590*4882a593Smuzhiyun char *buf)
591*4882a593Smuzhiyun {
592*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
593*4882a593Smuzhiyun struct list_head *iter;
594*4882a593Smuzhiyun struct slave *slave;
595*4882a593Smuzhiyun int res = 0;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun if (!rtnl_trylock())
598*4882a593Smuzhiyun return restart_syscall();
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun bond_for_each_slave(bond, slave, iter) {
601*4882a593Smuzhiyun if (res > (PAGE_SIZE - IFNAMSIZ - 6)) {
602*4882a593Smuzhiyun /* not enough space for another interface_name:queue_id pair */
603*4882a593Smuzhiyun if ((PAGE_SIZE - res) > 10)
604*4882a593Smuzhiyun res = PAGE_SIZE - 10;
605*4882a593Smuzhiyun res += sprintf(buf + res, "++more++ ");
606*4882a593Smuzhiyun break;
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun res += sprintf(buf + res, "%s:%d ",
609*4882a593Smuzhiyun slave->dev->name, slave->queue_id);
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun if (res)
612*4882a593Smuzhiyun buf[res-1] = '\n'; /* eat the leftover space */
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun rtnl_unlock();
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun return res;
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun static DEVICE_ATTR(queue_id, 0644, bonding_show_queue_id,
619*4882a593Smuzhiyun bonding_sysfs_store_option);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun /* Show the all_slaves_active flag. */
bonding_show_slaves_active(struct device * d,struct device_attribute * attr,char * buf)623*4882a593Smuzhiyun static ssize_t bonding_show_slaves_active(struct device *d,
624*4882a593Smuzhiyun struct device_attribute *attr,
625*4882a593Smuzhiyun char *buf)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.all_slaves_active);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun static DEVICE_ATTR(all_slaves_active, 0644,
632*4882a593Smuzhiyun bonding_show_slaves_active, bonding_sysfs_store_option);
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun /* 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)635*4882a593Smuzhiyun static ssize_t bonding_show_resend_igmp(struct device *d,
636*4882a593Smuzhiyun struct device_attribute *attr,
637*4882a593Smuzhiyun char *buf)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.resend_igmp);
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun static DEVICE_ATTR(resend_igmp, 0644,
644*4882a593Smuzhiyun bonding_show_resend_igmp, bonding_sysfs_store_option);
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun
bonding_show_lp_interval(struct device * d,struct device_attribute * attr,char * buf)647*4882a593Smuzhiyun static ssize_t bonding_show_lp_interval(struct device *d,
648*4882a593Smuzhiyun struct device_attribute *attr,
649*4882a593Smuzhiyun char *buf)
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.lp_interval);
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun static DEVICE_ATTR(lp_interval, 0644,
656*4882a593Smuzhiyun bonding_show_lp_interval, bonding_sysfs_store_option);
657*4882a593Smuzhiyun
bonding_show_tlb_dynamic_lb(struct device * d,struct device_attribute * attr,char * buf)658*4882a593Smuzhiyun static ssize_t bonding_show_tlb_dynamic_lb(struct device *d,
659*4882a593Smuzhiyun struct device_attribute *attr,
660*4882a593Smuzhiyun char *buf)
661*4882a593Smuzhiyun {
662*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
663*4882a593Smuzhiyun return sprintf(buf, "%d\n", bond->params.tlb_dynamic_lb);
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun static DEVICE_ATTR(tlb_dynamic_lb, 0644,
666*4882a593Smuzhiyun bonding_show_tlb_dynamic_lb, bonding_sysfs_store_option);
667*4882a593Smuzhiyun
bonding_show_packets_per_slave(struct device * d,struct device_attribute * attr,char * buf)668*4882a593Smuzhiyun static ssize_t bonding_show_packets_per_slave(struct device *d,
669*4882a593Smuzhiyun struct device_attribute *attr,
670*4882a593Smuzhiyun char *buf)
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
673*4882a593Smuzhiyun unsigned int packets_per_slave = bond->params.packets_per_slave;
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun return sprintf(buf, "%u\n", packets_per_slave);
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun static DEVICE_ATTR(packets_per_slave, 0644,
678*4882a593Smuzhiyun bonding_show_packets_per_slave, bonding_sysfs_store_option);
679*4882a593Smuzhiyun
bonding_show_ad_actor_sys_prio(struct device * d,struct device_attribute * attr,char * buf)680*4882a593Smuzhiyun static ssize_t bonding_show_ad_actor_sys_prio(struct device *d,
681*4882a593Smuzhiyun struct device_attribute *attr,
682*4882a593Smuzhiyun char *buf)
683*4882a593Smuzhiyun {
684*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN))
687*4882a593Smuzhiyun return sprintf(buf, "%hu\n", bond->params.ad_actor_sys_prio);
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun return 0;
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun static DEVICE_ATTR(ad_actor_sys_prio, 0644,
692*4882a593Smuzhiyun bonding_show_ad_actor_sys_prio, bonding_sysfs_store_option);
693*4882a593Smuzhiyun
bonding_show_ad_actor_system(struct device * d,struct device_attribute * attr,char * buf)694*4882a593Smuzhiyun static ssize_t bonding_show_ad_actor_system(struct device *d,
695*4882a593Smuzhiyun struct device_attribute *attr,
696*4882a593Smuzhiyun char *buf)
697*4882a593Smuzhiyun {
698*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN))
701*4882a593Smuzhiyun return sprintf(buf, "%pM\n", bond->params.ad_actor_system);
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun return 0;
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun static DEVICE_ATTR(ad_actor_system, 0644,
707*4882a593Smuzhiyun bonding_show_ad_actor_system, bonding_sysfs_store_option);
708*4882a593Smuzhiyun
bonding_show_ad_user_port_key(struct device * d,struct device_attribute * attr,char * buf)709*4882a593Smuzhiyun static ssize_t bonding_show_ad_user_port_key(struct device *d,
710*4882a593Smuzhiyun struct device_attribute *attr,
711*4882a593Smuzhiyun char *buf)
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun struct bonding *bond = to_bond(d);
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun if (BOND_MODE(bond) == BOND_MODE_8023AD && capable(CAP_NET_ADMIN))
716*4882a593Smuzhiyun return sprintf(buf, "%hu\n", bond->params.ad_user_port_key);
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun return 0;
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun static DEVICE_ATTR(ad_user_port_key, 0644,
721*4882a593Smuzhiyun bonding_show_ad_user_port_key, bonding_sysfs_store_option);
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun static struct attribute *per_bond_attrs[] = {
724*4882a593Smuzhiyun &dev_attr_slaves.attr,
725*4882a593Smuzhiyun &dev_attr_mode.attr,
726*4882a593Smuzhiyun &dev_attr_fail_over_mac.attr,
727*4882a593Smuzhiyun &dev_attr_arp_validate.attr,
728*4882a593Smuzhiyun &dev_attr_arp_all_targets.attr,
729*4882a593Smuzhiyun &dev_attr_arp_interval.attr,
730*4882a593Smuzhiyun &dev_attr_arp_ip_target.attr,
731*4882a593Smuzhiyun &dev_attr_downdelay.attr,
732*4882a593Smuzhiyun &dev_attr_updelay.attr,
733*4882a593Smuzhiyun &dev_attr_peer_notif_delay.attr,
734*4882a593Smuzhiyun &dev_attr_lacp_rate.attr,
735*4882a593Smuzhiyun &dev_attr_ad_select.attr,
736*4882a593Smuzhiyun &dev_attr_xmit_hash_policy.attr,
737*4882a593Smuzhiyun &dev_attr_num_grat_arp.attr,
738*4882a593Smuzhiyun &dev_attr_num_unsol_na.attr,
739*4882a593Smuzhiyun &dev_attr_miimon.attr,
740*4882a593Smuzhiyun &dev_attr_primary.attr,
741*4882a593Smuzhiyun &dev_attr_primary_reselect.attr,
742*4882a593Smuzhiyun &dev_attr_use_carrier.attr,
743*4882a593Smuzhiyun &dev_attr_active_slave.attr,
744*4882a593Smuzhiyun &dev_attr_mii_status.attr,
745*4882a593Smuzhiyun &dev_attr_ad_aggregator.attr,
746*4882a593Smuzhiyun &dev_attr_ad_num_ports.attr,
747*4882a593Smuzhiyun &dev_attr_ad_actor_key.attr,
748*4882a593Smuzhiyun &dev_attr_ad_partner_key.attr,
749*4882a593Smuzhiyun &dev_attr_ad_partner_mac.attr,
750*4882a593Smuzhiyun &dev_attr_queue_id.attr,
751*4882a593Smuzhiyun &dev_attr_all_slaves_active.attr,
752*4882a593Smuzhiyun &dev_attr_resend_igmp.attr,
753*4882a593Smuzhiyun &dev_attr_min_links.attr,
754*4882a593Smuzhiyun &dev_attr_lp_interval.attr,
755*4882a593Smuzhiyun &dev_attr_packets_per_slave.attr,
756*4882a593Smuzhiyun &dev_attr_tlb_dynamic_lb.attr,
757*4882a593Smuzhiyun &dev_attr_ad_actor_sys_prio.attr,
758*4882a593Smuzhiyun &dev_attr_ad_actor_system.attr,
759*4882a593Smuzhiyun &dev_attr_ad_user_port_key.attr,
760*4882a593Smuzhiyun NULL,
761*4882a593Smuzhiyun };
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun static const struct attribute_group bonding_group = {
764*4882a593Smuzhiyun .name = "bonding",
765*4882a593Smuzhiyun .attrs = per_bond_attrs,
766*4882a593Smuzhiyun };
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun /* Initialize sysfs. This sets up the bonding_masters file in
769*4882a593Smuzhiyun * /sys/class/net.
770*4882a593Smuzhiyun */
bond_create_sysfs(struct bond_net * bn)771*4882a593Smuzhiyun int bond_create_sysfs(struct bond_net *bn)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun int ret;
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun bn->class_attr_bonding_masters = class_attr_bonding_masters;
776*4882a593Smuzhiyun sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters,
779*4882a593Smuzhiyun bn->net);
780*4882a593Smuzhiyun /* Permit multiple loads of the module by ignoring failures to
781*4882a593Smuzhiyun * create the bonding_masters sysfs file. Bonding devices
782*4882a593Smuzhiyun * created by second or subsequent loads of the module will
783*4882a593Smuzhiyun * not be listed in, or controllable by, bonding_masters, but
784*4882a593Smuzhiyun * will have the usual "bonding" sysfs directory.
785*4882a593Smuzhiyun *
786*4882a593Smuzhiyun * This is done to preserve backwards compatibility for
787*4882a593Smuzhiyun * initscripts/sysconfig, which load bonding multiple times to
788*4882a593Smuzhiyun * configure multiple bonding devices.
789*4882a593Smuzhiyun */
790*4882a593Smuzhiyun if (ret == -EEXIST) {
791*4882a593Smuzhiyun /* Is someone being kinky and naming a device bonding_master? */
792*4882a593Smuzhiyun if (__dev_get_by_name(bn->net,
793*4882a593Smuzhiyun class_attr_bonding_masters.attr.name))
794*4882a593Smuzhiyun pr_err("network device named %s already exists in sysfs\n",
795*4882a593Smuzhiyun class_attr_bonding_masters.attr.name);
796*4882a593Smuzhiyun ret = 0;
797*4882a593Smuzhiyun }
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun return ret;
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun /* Remove /sys/class/net/bonding_masters. */
bond_destroy_sysfs(struct bond_net * bn)804*4882a593Smuzhiyun void bond_destroy_sysfs(struct bond_net *bn)
805*4882a593Smuzhiyun {
806*4882a593Smuzhiyun netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net);
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun /* Initialize sysfs for each bond. This sets up and registers
810*4882a593Smuzhiyun * the 'bondctl' directory for each individual bond under /sys/class/net.
811*4882a593Smuzhiyun */
bond_prepare_sysfs_group(struct bonding * bond)812*4882a593Smuzhiyun void bond_prepare_sysfs_group(struct bonding *bond)
813*4882a593Smuzhiyun {
814*4882a593Smuzhiyun bond->dev->sysfs_groups[0] = &bonding_group;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun
817