1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Sysfs attributes of bridge
4*4882a593Smuzhiyun * Linux ethernet bridge
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Authors:
7*4882a593Smuzhiyun * Stephen Hemminger <shemminger@osdl.org>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/capability.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/netdevice.h>
13*4882a593Smuzhiyun #include <linux/etherdevice.h>
14*4882a593Smuzhiyun #include <linux/if_bridge.h>
15*4882a593Smuzhiyun #include <linux/rtnetlink.h>
16*4882a593Smuzhiyun #include <linux/spinlock.h>
17*4882a593Smuzhiyun #include <linux/times.h>
18*4882a593Smuzhiyun #include <linux/sched/signal.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include "br_private.h"
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define to_bridge(cd) ((struct net_bridge *)netdev_priv(to_net_dev(cd)))
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun * Common code for storing bridge parameters.
26*4882a593Smuzhiyun */
store_bridge_parm(struct device * d,const char * buf,size_t len,int (* set)(struct net_bridge *,unsigned long))27*4882a593Smuzhiyun static ssize_t store_bridge_parm(struct device *d,
28*4882a593Smuzhiyun const char *buf, size_t len,
29*4882a593Smuzhiyun int (*set)(struct net_bridge *, unsigned long))
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
32*4882a593Smuzhiyun char *endp;
33*4882a593Smuzhiyun unsigned long val;
34*4882a593Smuzhiyun int err;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
37*4882a593Smuzhiyun return -EPERM;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun val = simple_strtoul(buf, &endp, 0);
40*4882a593Smuzhiyun if (endp == buf)
41*4882a593Smuzhiyun return -EINVAL;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun if (!rtnl_trylock())
44*4882a593Smuzhiyun return restart_syscall();
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun err = (*set)(br, val);
47*4882a593Smuzhiyun if (!err)
48*4882a593Smuzhiyun netdev_state_change(br->dev);
49*4882a593Smuzhiyun rtnl_unlock();
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun return err ? err : len;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun
forward_delay_show(struct device * d,struct device_attribute * attr,char * buf)55*4882a593Smuzhiyun static ssize_t forward_delay_show(struct device *d,
56*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
59*4882a593Smuzhiyun return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
forward_delay_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)62*4882a593Smuzhiyun static ssize_t forward_delay_store(struct device *d,
63*4882a593Smuzhiyun struct device_attribute *attr,
64*4882a593Smuzhiyun const char *buf, size_t len)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_set_forward_delay);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun static DEVICE_ATTR_RW(forward_delay);
69*4882a593Smuzhiyun
hello_time_show(struct device * d,struct device_attribute * attr,char * buf)70*4882a593Smuzhiyun static ssize_t hello_time_show(struct device *d, struct device_attribute *attr,
71*4882a593Smuzhiyun char *buf)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun return sprintf(buf, "%lu\n",
74*4882a593Smuzhiyun jiffies_to_clock_t(to_bridge(d)->hello_time));
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
hello_time_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)77*4882a593Smuzhiyun static ssize_t hello_time_store(struct device *d,
78*4882a593Smuzhiyun struct device_attribute *attr, const char *buf,
79*4882a593Smuzhiyun size_t len)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_set_hello_time);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun static DEVICE_ATTR_RW(hello_time);
84*4882a593Smuzhiyun
max_age_show(struct device * d,struct device_attribute * attr,char * buf)85*4882a593Smuzhiyun static ssize_t max_age_show(struct device *d, struct device_attribute *attr,
86*4882a593Smuzhiyun char *buf)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun return sprintf(buf, "%lu\n",
89*4882a593Smuzhiyun jiffies_to_clock_t(to_bridge(d)->max_age));
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
max_age_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)92*4882a593Smuzhiyun static ssize_t max_age_store(struct device *d, struct device_attribute *attr,
93*4882a593Smuzhiyun const char *buf, size_t len)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_set_max_age);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun static DEVICE_ATTR_RW(max_age);
98*4882a593Smuzhiyun
ageing_time_show(struct device * d,struct device_attribute * attr,char * buf)99*4882a593Smuzhiyun static ssize_t ageing_time_show(struct device *d,
100*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
103*4882a593Smuzhiyun return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
set_ageing_time(struct net_bridge * br,unsigned long val)106*4882a593Smuzhiyun static int set_ageing_time(struct net_bridge *br, unsigned long val)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun return br_set_ageing_time(br, val);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
ageing_time_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)111*4882a593Smuzhiyun static ssize_t ageing_time_store(struct device *d,
112*4882a593Smuzhiyun struct device_attribute *attr,
113*4882a593Smuzhiyun const char *buf, size_t len)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_ageing_time);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun static DEVICE_ATTR_RW(ageing_time);
118*4882a593Smuzhiyun
stp_state_show(struct device * d,struct device_attribute * attr,char * buf)119*4882a593Smuzhiyun static ssize_t stp_state_show(struct device *d,
120*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
123*4882a593Smuzhiyun return sprintf(buf, "%d\n", br->stp_enabled);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun
set_stp_state(struct net_bridge * br,unsigned long val)127*4882a593Smuzhiyun static int set_stp_state(struct net_bridge *br, unsigned long val)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun return br_stp_set_enabled(br, val, NULL);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
stp_state_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)132*4882a593Smuzhiyun static ssize_t stp_state_store(struct device *d,
133*4882a593Smuzhiyun struct device_attribute *attr, const char *buf,
134*4882a593Smuzhiyun size_t len)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_stp_state);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun static DEVICE_ATTR_RW(stp_state);
139*4882a593Smuzhiyun
group_fwd_mask_show(struct device * d,struct device_attribute * attr,char * buf)140*4882a593Smuzhiyun static ssize_t group_fwd_mask_show(struct device *d,
141*4882a593Smuzhiyun struct device_attribute *attr,
142*4882a593Smuzhiyun char *buf)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
145*4882a593Smuzhiyun return sprintf(buf, "%#x\n", br->group_fwd_mask);
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
set_group_fwd_mask(struct net_bridge * br,unsigned long val)148*4882a593Smuzhiyun static int set_group_fwd_mask(struct net_bridge *br, unsigned long val)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun if (val & BR_GROUPFWD_RESTRICTED)
151*4882a593Smuzhiyun return -EINVAL;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun br->group_fwd_mask = val;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
group_fwd_mask_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)158*4882a593Smuzhiyun static ssize_t group_fwd_mask_store(struct device *d,
159*4882a593Smuzhiyun struct device_attribute *attr,
160*4882a593Smuzhiyun const char *buf,
161*4882a593Smuzhiyun size_t len)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_group_fwd_mask);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun static DEVICE_ATTR_RW(group_fwd_mask);
166*4882a593Smuzhiyun
priority_show(struct device * d,struct device_attribute * attr,char * buf)167*4882a593Smuzhiyun static ssize_t priority_show(struct device *d, struct device_attribute *attr,
168*4882a593Smuzhiyun char *buf)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
171*4882a593Smuzhiyun return sprintf(buf, "%d\n",
172*4882a593Smuzhiyun (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
set_priority(struct net_bridge * br,unsigned long val)175*4882a593Smuzhiyun static int set_priority(struct net_bridge *br, unsigned long val)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun br_stp_set_bridge_priority(br, (u16) val);
178*4882a593Smuzhiyun return 0;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
priority_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)181*4882a593Smuzhiyun static ssize_t priority_store(struct device *d, struct device_attribute *attr,
182*4882a593Smuzhiyun const char *buf, size_t len)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_priority);
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun static DEVICE_ATTR_RW(priority);
187*4882a593Smuzhiyun
root_id_show(struct device * d,struct device_attribute * attr,char * buf)188*4882a593Smuzhiyun static ssize_t root_id_show(struct device *d, struct device_attribute *attr,
189*4882a593Smuzhiyun char *buf)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun static DEVICE_ATTR_RO(root_id);
194*4882a593Smuzhiyun
bridge_id_show(struct device * d,struct device_attribute * attr,char * buf)195*4882a593Smuzhiyun static ssize_t bridge_id_show(struct device *d, struct device_attribute *attr,
196*4882a593Smuzhiyun char *buf)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun return br_show_bridge_id(buf, &to_bridge(d)->bridge_id);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun static DEVICE_ATTR_RO(bridge_id);
201*4882a593Smuzhiyun
root_port_show(struct device * d,struct device_attribute * attr,char * buf)202*4882a593Smuzhiyun static ssize_t root_port_show(struct device *d, struct device_attribute *attr,
203*4882a593Smuzhiyun char *buf)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun return sprintf(buf, "%d\n", to_bridge(d)->root_port);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun static DEVICE_ATTR_RO(root_port);
208*4882a593Smuzhiyun
root_path_cost_show(struct device * d,struct device_attribute * attr,char * buf)209*4882a593Smuzhiyun static ssize_t root_path_cost_show(struct device *d,
210*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost);
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun static DEVICE_ATTR_RO(root_path_cost);
215*4882a593Smuzhiyun
topology_change_show(struct device * d,struct device_attribute * attr,char * buf)216*4882a593Smuzhiyun static ssize_t topology_change_show(struct device *d,
217*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun return sprintf(buf, "%d\n", to_bridge(d)->topology_change);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun static DEVICE_ATTR_RO(topology_change);
222*4882a593Smuzhiyun
topology_change_detected_show(struct device * d,struct device_attribute * attr,char * buf)223*4882a593Smuzhiyun static ssize_t topology_change_detected_show(struct device *d,
224*4882a593Smuzhiyun struct device_attribute *attr,
225*4882a593Smuzhiyun char *buf)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
228*4882a593Smuzhiyun return sprintf(buf, "%d\n", br->topology_change_detected);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun static DEVICE_ATTR_RO(topology_change_detected);
231*4882a593Smuzhiyun
hello_timer_show(struct device * d,struct device_attribute * attr,char * buf)232*4882a593Smuzhiyun static ssize_t hello_timer_show(struct device *d,
233*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
236*4882a593Smuzhiyun return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer));
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun static DEVICE_ATTR_RO(hello_timer);
239*4882a593Smuzhiyun
tcn_timer_show(struct device * d,struct device_attribute * attr,char * buf)240*4882a593Smuzhiyun static ssize_t tcn_timer_show(struct device *d, struct device_attribute *attr,
241*4882a593Smuzhiyun char *buf)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
244*4882a593Smuzhiyun return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer));
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun static DEVICE_ATTR_RO(tcn_timer);
247*4882a593Smuzhiyun
topology_change_timer_show(struct device * d,struct device_attribute * attr,char * buf)248*4882a593Smuzhiyun static ssize_t topology_change_timer_show(struct device *d,
249*4882a593Smuzhiyun struct device_attribute *attr,
250*4882a593Smuzhiyun char *buf)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
253*4882a593Smuzhiyun return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer));
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun static DEVICE_ATTR_RO(topology_change_timer);
256*4882a593Smuzhiyun
gc_timer_show(struct device * d,struct device_attribute * attr,char * buf)257*4882a593Smuzhiyun static ssize_t gc_timer_show(struct device *d, struct device_attribute *attr,
258*4882a593Smuzhiyun char *buf)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
261*4882a593Smuzhiyun return sprintf(buf, "%ld\n", br_timer_value(&br->gc_work.timer));
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun static DEVICE_ATTR_RO(gc_timer);
264*4882a593Smuzhiyun
group_addr_show(struct device * d,struct device_attribute * attr,char * buf)265*4882a593Smuzhiyun static ssize_t group_addr_show(struct device *d,
266*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
269*4882a593Smuzhiyun return sprintf(buf, "%pM\n", br->group_addr);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
group_addr_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)272*4882a593Smuzhiyun static ssize_t group_addr_store(struct device *d,
273*4882a593Smuzhiyun struct device_attribute *attr,
274*4882a593Smuzhiyun const char *buf, size_t len)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
277*4882a593Smuzhiyun u8 new_addr[6];
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
280*4882a593Smuzhiyun return -EPERM;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun if (!mac_pton(buf, new_addr))
283*4882a593Smuzhiyun return -EINVAL;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun if (!is_link_local_ether_addr(new_addr))
286*4882a593Smuzhiyun return -EINVAL;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun if (new_addr[5] == 1 || /* 802.3x Pause address */
289*4882a593Smuzhiyun new_addr[5] == 2 || /* 802.3ad Slow protocols */
290*4882a593Smuzhiyun new_addr[5] == 3) /* 802.1X PAE address */
291*4882a593Smuzhiyun return -EINVAL;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun if (!rtnl_trylock())
294*4882a593Smuzhiyun return restart_syscall();
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun spin_lock_bh(&br->lock);
297*4882a593Smuzhiyun ether_addr_copy(br->group_addr, new_addr);
298*4882a593Smuzhiyun spin_unlock_bh(&br->lock);
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun br_opt_toggle(br, BROPT_GROUP_ADDR_SET, true);
301*4882a593Smuzhiyun br_recalculate_fwd_mask(br);
302*4882a593Smuzhiyun netdev_state_change(br->dev);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun rtnl_unlock();
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun return len;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun static DEVICE_ATTR_RW(group_addr);
310*4882a593Smuzhiyun
set_flush(struct net_bridge * br,unsigned long val)311*4882a593Smuzhiyun static int set_flush(struct net_bridge *br, unsigned long val)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun br_fdb_flush(br);
314*4882a593Smuzhiyun return 0;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
flush_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)317*4882a593Smuzhiyun static ssize_t flush_store(struct device *d,
318*4882a593Smuzhiyun struct device_attribute *attr,
319*4882a593Smuzhiyun const char *buf, size_t len)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_flush);
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun static DEVICE_ATTR_WO(flush);
324*4882a593Smuzhiyun
no_linklocal_learn_show(struct device * d,struct device_attribute * attr,char * buf)325*4882a593Smuzhiyun static ssize_t no_linklocal_learn_show(struct device *d,
326*4882a593Smuzhiyun struct device_attribute *attr,
327*4882a593Smuzhiyun char *buf)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
330*4882a593Smuzhiyun return sprintf(buf, "%d\n", br_boolopt_get(br, BR_BOOLOPT_NO_LL_LEARN));
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
set_no_linklocal_learn(struct net_bridge * br,unsigned long val)333*4882a593Smuzhiyun static int set_no_linklocal_learn(struct net_bridge *br, unsigned long val)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val, NULL);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
no_linklocal_learn_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)338*4882a593Smuzhiyun static ssize_t no_linklocal_learn_store(struct device *d,
339*4882a593Smuzhiyun struct device_attribute *attr,
340*4882a593Smuzhiyun const char *buf, size_t len)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_no_linklocal_learn);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun static DEVICE_ATTR_RW(no_linklocal_learn);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
multicast_router_show(struct device * d,struct device_attribute * attr,char * buf)347*4882a593Smuzhiyun static ssize_t multicast_router_show(struct device *d,
348*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
351*4882a593Smuzhiyun return sprintf(buf, "%d\n", br->multicast_router);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
multicast_router_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)354*4882a593Smuzhiyun static ssize_t multicast_router_store(struct device *d,
355*4882a593Smuzhiyun struct device_attribute *attr,
356*4882a593Smuzhiyun const char *buf, size_t len)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_multicast_set_router);
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_router);
361*4882a593Smuzhiyun
multicast_snooping_show(struct device * d,struct device_attribute * attr,char * buf)362*4882a593Smuzhiyun static ssize_t multicast_snooping_show(struct device *d,
363*4882a593Smuzhiyun struct device_attribute *attr,
364*4882a593Smuzhiyun char *buf)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
367*4882a593Smuzhiyun return sprintf(buf, "%d\n", br_opt_get(br, BROPT_MULTICAST_ENABLED));
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
multicast_snooping_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)370*4882a593Smuzhiyun static ssize_t multicast_snooping_store(struct device *d,
371*4882a593Smuzhiyun struct device_attribute *attr,
372*4882a593Smuzhiyun const char *buf, size_t len)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_multicast_toggle);
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_snooping);
377*4882a593Smuzhiyun
multicast_query_use_ifaddr_show(struct device * d,struct device_attribute * attr,char * buf)378*4882a593Smuzhiyun static ssize_t multicast_query_use_ifaddr_show(struct device *d,
379*4882a593Smuzhiyun struct device_attribute *attr,
380*4882a593Smuzhiyun char *buf)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
383*4882a593Smuzhiyun return sprintf(buf, "%d\n",
384*4882a593Smuzhiyun br_opt_get(br, BROPT_MULTICAST_QUERY_USE_IFADDR));
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
set_query_use_ifaddr(struct net_bridge * br,unsigned long val)387*4882a593Smuzhiyun static int set_query_use_ifaddr(struct net_bridge *br, unsigned long val)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun br_opt_toggle(br, BROPT_MULTICAST_QUERY_USE_IFADDR, !!val);
390*4882a593Smuzhiyun return 0;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun static ssize_t
multicast_query_use_ifaddr_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)394*4882a593Smuzhiyun multicast_query_use_ifaddr_store(struct device *d,
395*4882a593Smuzhiyun struct device_attribute *attr,
396*4882a593Smuzhiyun const char *buf, size_t len)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_query_use_ifaddr);
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_query_use_ifaddr);
401*4882a593Smuzhiyun
multicast_querier_show(struct device * d,struct device_attribute * attr,char * buf)402*4882a593Smuzhiyun static ssize_t multicast_querier_show(struct device *d,
403*4882a593Smuzhiyun struct device_attribute *attr,
404*4882a593Smuzhiyun char *buf)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
407*4882a593Smuzhiyun return sprintf(buf, "%d\n", br_opt_get(br, BROPT_MULTICAST_QUERIER));
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
multicast_querier_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)410*4882a593Smuzhiyun static ssize_t multicast_querier_store(struct device *d,
411*4882a593Smuzhiyun struct device_attribute *attr,
412*4882a593Smuzhiyun const char *buf, size_t len)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_multicast_set_querier);
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_querier);
417*4882a593Smuzhiyun
hash_elasticity_show(struct device * d,struct device_attribute * attr,char * buf)418*4882a593Smuzhiyun static ssize_t hash_elasticity_show(struct device *d,
419*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun return sprintf(buf, "%u\n", RHT_ELASTICITY);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
set_elasticity(struct net_bridge * br,unsigned long val)424*4882a593Smuzhiyun static int set_elasticity(struct net_bridge *br, unsigned long val)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun br_warn(br, "the hash_elasticity option has been deprecated and is always %u\n",
427*4882a593Smuzhiyun RHT_ELASTICITY);
428*4882a593Smuzhiyun return 0;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
hash_elasticity_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)431*4882a593Smuzhiyun static ssize_t hash_elasticity_store(struct device *d,
432*4882a593Smuzhiyun struct device_attribute *attr,
433*4882a593Smuzhiyun const char *buf, size_t len)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_elasticity);
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun static DEVICE_ATTR_RW(hash_elasticity);
438*4882a593Smuzhiyun
hash_max_show(struct device * d,struct device_attribute * attr,char * buf)439*4882a593Smuzhiyun static ssize_t hash_max_show(struct device *d, struct device_attribute *attr,
440*4882a593Smuzhiyun char *buf)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
443*4882a593Smuzhiyun return sprintf(buf, "%u\n", br->hash_max);
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
set_hash_max(struct net_bridge * br,unsigned long val)446*4882a593Smuzhiyun static int set_hash_max(struct net_bridge *br, unsigned long val)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun br->hash_max = val;
449*4882a593Smuzhiyun return 0;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
hash_max_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)452*4882a593Smuzhiyun static ssize_t hash_max_store(struct device *d, struct device_attribute *attr,
453*4882a593Smuzhiyun const char *buf, size_t len)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_hash_max);
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun static DEVICE_ATTR_RW(hash_max);
458*4882a593Smuzhiyun
multicast_igmp_version_show(struct device * d,struct device_attribute * attr,char * buf)459*4882a593Smuzhiyun static ssize_t multicast_igmp_version_show(struct device *d,
460*4882a593Smuzhiyun struct device_attribute *attr,
461*4882a593Smuzhiyun char *buf)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun return sprintf(buf, "%u\n", br->multicast_igmp_version);
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
multicast_igmp_version_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)468*4882a593Smuzhiyun static ssize_t multicast_igmp_version_store(struct device *d,
469*4882a593Smuzhiyun struct device_attribute *attr,
470*4882a593Smuzhiyun const char *buf, size_t len)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_multicast_set_igmp_version);
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_igmp_version);
475*4882a593Smuzhiyun
multicast_last_member_count_show(struct device * d,struct device_attribute * attr,char * buf)476*4882a593Smuzhiyun static ssize_t multicast_last_member_count_show(struct device *d,
477*4882a593Smuzhiyun struct device_attribute *attr,
478*4882a593Smuzhiyun char *buf)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
481*4882a593Smuzhiyun return sprintf(buf, "%u\n", br->multicast_last_member_count);
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
set_last_member_count(struct net_bridge * br,unsigned long val)484*4882a593Smuzhiyun static int set_last_member_count(struct net_bridge *br, unsigned long val)
485*4882a593Smuzhiyun {
486*4882a593Smuzhiyun br->multicast_last_member_count = val;
487*4882a593Smuzhiyun return 0;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
multicast_last_member_count_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)490*4882a593Smuzhiyun static ssize_t multicast_last_member_count_store(struct device *d,
491*4882a593Smuzhiyun struct device_attribute *attr,
492*4882a593Smuzhiyun const char *buf, size_t len)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_last_member_count);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_last_member_count);
497*4882a593Smuzhiyun
multicast_startup_query_count_show(struct device * d,struct device_attribute * attr,char * buf)498*4882a593Smuzhiyun static ssize_t multicast_startup_query_count_show(
499*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, char *buf)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
502*4882a593Smuzhiyun return sprintf(buf, "%u\n", br->multicast_startup_query_count);
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
set_startup_query_count(struct net_bridge * br,unsigned long val)505*4882a593Smuzhiyun static int set_startup_query_count(struct net_bridge *br, unsigned long val)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun br->multicast_startup_query_count = val;
508*4882a593Smuzhiyun return 0;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
multicast_startup_query_count_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)511*4882a593Smuzhiyun static ssize_t multicast_startup_query_count_store(
512*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, const char *buf,
513*4882a593Smuzhiyun size_t len)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_startup_query_count);
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_startup_query_count);
518*4882a593Smuzhiyun
multicast_last_member_interval_show(struct device * d,struct device_attribute * attr,char * buf)519*4882a593Smuzhiyun static ssize_t multicast_last_member_interval_show(
520*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, char *buf)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
523*4882a593Smuzhiyun return sprintf(buf, "%lu\n",
524*4882a593Smuzhiyun jiffies_to_clock_t(br->multicast_last_member_interval));
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun
set_last_member_interval(struct net_bridge * br,unsigned long val)527*4882a593Smuzhiyun static int set_last_member_interval(struct net_bridge *br, unsigned long val)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun br->multicast_last_member_interval = clock_t_to_jiffies(val);
530*4882a593Smuzhiyun return 0;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
multicast_last_member_interval_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)533*4882a593Smuzhiyun static ssize_t multicast_last_member_interval_store(
534*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, const char *buf,
535*4882a593Smuzhiyun size_t len)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_last_member_interval);
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_last_member_interval);
540*4882a593Smuzhiyun
multicast_membership_interval_show(struct device * d,struct device_attribute * attr,char * buf)541*4882a593Smuzhiyun static ssize_t multicast_membership_interval_show(
542*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, char *buf)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
545*4882a593Smuzhiyun return sprintf(buf, "%lu\n",
546*4882a593Smuzhiyun jiffies_to_clock_t(br->multicast_membership_interval));
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
set_membership_interval(struct net_bridge * br,unsigned long val)549*4882a593Smuzhiyun static int set_membership_interval(struct net_bridge *br, unsigned long val)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun br->multicast_membership_interval = clock_t_to_jiffies(val);
552*4882a593Smuzhiyun return 0;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
multicast_membership_interval_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)555*4882a593Smuzhiyun static ssize_t multicast_membership_interval_store(
556*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, const char *buf,
557*4882a593Smuzhiyun size_t len)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_membership_interval);
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_membership_interval);
562*4882a593Smuzhiyun
multicast_querier_interval_show(struct device * d,struct device_attribute * attr,char * buf)563*4882a593Smuzhiyun static ssize_t multicast_querier_interval_show(struct device *d,
564*4882a593Smuzhiyun struct device_attribute *attr,
565*4882a593Smuzhiyun char *buf)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
568*4882a593Smuzhiyun return sprintf(buf, "%lu\n",
569*4882a593Smuzhiyun jiffies_to_clock_t(br->multicast_querier_interval));
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun
set_querier_interval(struct net_bridge * br,unsigned long val)572*4882a593Smuzhiyun static int set_querier_interval(struct net_bridge *br, unsigned long val)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun br->multicast_querier_interval = clock_t_to_jiffies(val);
575*4882a593Smuzhiyun return 0;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
multicast_querier_interval_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)578*4882a593Smuzhiyun static ssize_t multicast_querier_interval_store(struct device *d,
579*4882a593Smuzhiyun struct device_attribute *attr,
580*4882a593Smuzhiyun const char *buf, size_t len)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_querier_interval);
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_querier_interval);
585*4882a593Smuzhiyun
multicast_query_interval_show(struct device * d,struct device_attribute * attr,char * buf)586*4882a593Smuzhiyun static ssize_t multicast_query_interval_show(struct device *d,
587*4882a593Smuzhiyun struct device_attribute *attr,
588*4882a593Smuzhiyun char *buf)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
591*4882a593Smuzhiyun return sprintf(buf, "%lu\n",
592*4882a593Smuzhiyun jiffies_to_clock_t(br->multicast_query_interval));
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
set_query_interval(struct net_bridge * br,unsigned long val)595*4882a593Smuzhiyun static int set_query_interval(struct net_bridge *br, unsigned long val)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun br->multicast_query_interval = clock_t_to_jiffies(val);
598*4882a593Smuzhiyun return 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
multicast_query_interval_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)601*4882a593Smuzhiyun static ssize_t multicast_query_interval_store(struct device *d,
602*4882a593Smuzhiyun struct device_attribute *attr,
603*4882a593Smuzhiyun const char *buf, size_t len)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_query_interval);
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_query_interval);
608*4882a593Smuzhiyun
multicast_query_response_interval_show(struct device * d,struct device_attribute * attr,char * buf)609*4882a593Smuzhiyun static ssize_t multicast_query_response_interval_show(
610*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, char *buf)
611*4882a593Smuzhiyun {
612*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
613*4882a593Smuzhiyun return sprintf(
614*4882a593Smuzhiyun buf, "%lu\n",
615*4882a593Smuzhiyun jiffies_to_clock_t(br->multicast_query_response_interval));
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun
set_query_response_interval(struct net_bridge * br,unsigned long val)618*4882a593Smuzhiyun static int set_query_response_interval(struct net_bridge *br, unsigned long val)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun br->multicast_query_response_interval = clock_t_to_jiffies(val);
621*4882a593Smuzhiyun return 0;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
multicast_query_response_interval_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)624*4882a593Smuzhiyun static ssize_t multicast_query_response_interval_store(
625*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, const char *buf,
626*4882a593Smuzhiyun size_t len)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_query_response_interval);
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_query_response_interval);
631*4882a593Smuzhiyun
multicast_startup_query_interval_show(struct device * d,struct device_attribute * attr,char * buf)632*4882a593Smuzhiyun static ssize_t multicast_startup_query_interval_show(
633*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, char *buf)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
636*4882a593Smuzhiyun return sprintf(
637*4882a593Smuzhiyun buf, "%lu\n",
638*4882a593Smuzhiyun jiffies_to_clock_t(br->multicast_startup_query_interval));
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun
set_startup_query_interval(struct net_bridge * br,unsigned long val)641*4882a593Smuzhiyun static int set_startup_query_interval(struct net_bridge *br, unsigned long val)
642*4882a593Smuzhiyun {
643*4882a593Smuzhiyun br->multicast_startup_query_interval = clock_t_to_jiffies(val);
644*4882a593Smuzhiyun return 0;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
multicast_startup_query_interval_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)647*4882a593Smuzhiyun static ssize_t multicast_startup_query_interval_store(
648*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, const char *buf,
649*4882a593Smuzhiyun size_t len)
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_startup_query_interval);
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_startup_query_interval);
654*4882a593Smuzhiyun
multicast_stats_enabled_show(struct device * d,struct device_attribute * attr,char * buf)655*4882a593Smuzhiyun static ssize_t multicast_stats_enabled_show(struct device *d,
656*4882a593Smuzhiyun struct device_attribute *attr,
657*4882a593Smuzhiyun char *buf)
658*4882a593Smuzhiyun {
659*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun return sprintf(buf, "%d\n",
662*4882a593Smuzhiyun br_opt_get(br, BROPT_MULTICAST_STATS_ENABLED));
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun
set_stats_enabled(struct net_bridge * br,unsigned long val)665*4882a593Smuzhiyun static int set_stats_enabled(struct net_bridge *br, unsigned long val)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun br_opt_toggle(br, BROPT_MULTICAST_STATS_ENABLED, !!val);
668*4882a593Smuzhiyun return 0;
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun
multicast_stats_enabled_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)671*4882a593Smuzhiyun static ssize_t multicast_stats_enabled_store(struct device *d,
672*4882a593Smuzhiyun struct device_attribute *attr,
673*4882a593Smuzhiyun const char *buf,
674*4882a593Smuzhiyun size_t len)
675*4882a593Smuzhiyun {
676*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_stats_enabled);
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_stats_enabled);
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
multicast_mld_version_show(struct device * d,struct device_attribute * attr,char * buf)681*4882a593Smuzhiyun static ssize_t multicast_mld_version_show(struct device *d,
682*4882a593Smuzhiyun struct device_attribute *attr,
683*4882a593Smuzhiyun char *buf)
684*4882a593Smuzhiyun {
685*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun return sprintf(buf, "%u\n", br->multicast_mld_version);
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun
multicast_mld_version_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)690*4882a593Smuzhiyun static ssize_t multicast_mld_version_store(struct device *d,
691*4882a593Smuzhiyun struct device_attribute *attr,
692*4882a593Smuzhiyun const char *buf, size_t len)
693*4882a593Smuzhiyun {
694*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_multicast_set_mld_version);
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun static DEVICE_ATTR_RW(multicast_mld_version);
697*4882a593Smuzhiyun #endif
698*4882a593Smuzhiyun #endif
699*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
nf_call_iptables_show(struct device * d,struct device_attribute * attr,char * buf)700*4882a593Smuzhiyun static ssize_t nf_call_iptables_show(
701*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, char *buf)
702*4882a593Smuzhiyun {
703*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
704*4882a593Smuzhiyun return sprintf(buf, "%u\n", br_opt_get(br, BROPT_NF_CALL_IPTABLES));
705*4882a593Smuzhiyun }
706*4882a593Smuzhiyun
set_nf_call_iptables(struct net_bridge * br,unsigned long val)707*4882a593Smuzhiyun static int set_nf_call_iptables(struct net_bridge *br, unsigned long val)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun br_opt_toggle(br, BROPT_NF_CALL_IPTABLES, !!val);
710*4882a593Smuzhiyun return 0;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun
nf_call_iptables_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)713*4882a593Smuzhiyun static ssize_t nf_call_iptables_store(
714*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, const char *buf,
715*4882a593Smuzhiyun size_t len)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_nf_call_iptables);
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun static DEVICE_ATTR_RW(nf_call_iptables);
720*4882a593Smuzhiyun
nf_call_ip6tables_show(struct device * d,struct device_attribute * attr,char * buf)721*4882a593Smuzhiyun static ssize_t nf_call_ip6tables_show(
722*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, char *buf)
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
725*4882a593Smuzhiyun return sprintf(buf, "%u\n", br_opt_get(br, BROPT_NF_CALL_IP6TABLES));
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
set_nf_call_ip6tables(struct net_bridge * br,unsigned long val)728*4882a593Smuzhiyun static int set_nf_call_ip6tables(struct net_bridge *br, unsigned long val)
729*4882a593Smuzhiyun {
730*4882a593Smuzhiyun br_opt_toggle(br, BROPT_NF_CALL_IP6TABLES, !!val);
731*4882a593Smuzhiyun return 0;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
nf_call_ip6tables_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)734*4882a593Smuzhiyun static ssize_t nf_call_ip6tables_store(
735*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, const char *buf,
736*4882a593Smuzhiyun size_t len)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_nf_call_ip6tables);
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun static DEVICE_ATTR_RW(nf_call_ip6tables);
741*4882a593Smuzhiyun
nf_call_arptables_show(struct device * d,struct device_attribute * attr,char * buf)742*4882a593Smuzhiyun static ssize_t nf_call_arptables_show(
743*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, char *buf)
744*4882a593Smuzhiyun {
745*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
746*4882a593Smuzhiyun return sprintf(buf, "%u\n", br_opt_get(br, BROPT_NF_CALL_ARPTABLES));
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
set_nf_call_arptables(struct net_bridge * br,unsigned long val)749*4882a593Smuzhiyun static int set_nf_call_arptables(struct net_bridge *br, unsigned long val)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun br_opt_toggle(br, BROPT_NF_CALL_ARPTABLES, !!val);
752*4882a593Smuzhiyun return 0;
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun
nf_call_arptables_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)755*4882a593Smuzhiyun static ssize_t nf_call_arptables_store(
756*4882a593Smuzhiyun struct device *d, struct device_attribute *attr, const char *buf,
757*4882a593Smuzhiyun size_t len)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, set_nf_call_arptables);
760*4882a593Smuzhiyun }
761*4882a593Smuzhiyun static DEVICE_ATTR_RW(nf_call_arptables);
762*4882a593Smuzhiyun #endif
763*4882a593Smuzhiyun #ifdef CONFIG_BRIDGE_VLAN_FILTERING
vlan_filtering_show(struct device * d,struct device_attribute * attr,char * buf)764*4882a593Smuzhiyun static ssize_t vlan_filtering_show(struct device *d,
765*4882a593Smuzhiyun struct device_attribute *attr,
766*4882a593Smuzhiyun char *buf)
767*4882a593Smuzhiyun {
768*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
769*4882a593Smuzhiyun return sprintf(buf, "%d\n", br_opt_get(br, BROPT_VLAN_ENABLED));
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun
vlan_filtering_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)772*4882a593Smuzhiyun static ssize_t vlan_filtering_store(struct device *d,
773*4882a593Smuzhiyun struct device_attribute *attr,
774*4882a593Smuzhiyun const char *buf, size_t len)
775*4882a593Smuzhiyun {
776*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_vlan_filter_toggle);
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun static DEVICE_ATTR_RW(vlan_filtering);
779*4882a593Smuzhiyun
vlan_protocol_show(struct device * d,struct device_attribute * attr,char * buf)780*4882a593Smuzhiyun static ssize_t vlan_protocol_show(struct device *d,
781*4882a593Smuzhiyun struct device_attribute *attr,
782*4882a593Smuzhiyun char *buf)
783*4882a593Smuzhiyun {
784*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
785*4882a593Smuzhiyun return sprintf(buf, "%#06x\n", ntohs(br->vlan_proto));
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun
vlan_protocol_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)788*4882a593Smuzhiyun static ssize_t vlan_protocol_store(struct device *d,
789*4882a593Smuzhiyun struct device_attribute *attr,
790*4882a593Smuzhiyun const char *buf, size_t len)
791*4882a593Smuzhiyun {
792*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_vlan_set_proto);
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun static DEVICE_ATTR_RW(vlan_protocol);
795*4882a593Smuzhiyun
default_pvid_show(struct device * d,struct device_attribute * attr,char * buf)796*4882a593Smuzhiyun static ssize_t default_pvid_show(struct device *d,
797*4882a593Smuzhiyun struct device_attribute *attr,
798*4882a593Smuzhiyun char *buf)
799*4882a593Smuzhiyun {
800*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
801*4882a593Smuzhiyun return sprintf(buf, "%d\n", br->default_pvid);
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun
default_pvid_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)804*4882a593Smuzhiyun static ssize_t default_pvid_store(struct device *d,
805*4882a593Smuzhiyun struct device_attribute *attr,
806*4882a593Smuzhiyun const char *buf, size_t len)
807*4882a593Smuzhiyun {
808*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_vlan_set_default_pvid);
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun static DEVICE_ATTR_RW(default_pvid);
811*4882a593Smuzhiyun
vlan_stats_enabled_show(struct device * d,struct device_attribute * attr,char * buf)812*4882a593Smuzhiyun static ssize_t vlan_stats_enabled_show(struct device *d,
813*4882a593Smuzhiyun struct device_attribute *attr,
814*4882a593Smuzhiyun char *buf)
815*4882a593Smuzhiyun {
816*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
817*4882a593Smuzhiyun return sprintf(buf, "%u\n", br_opt_get(br, BROPT_VLAN_STATS_ENABLED));
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
vlan_stats_enabled_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)820*4882a593Smuzhiyun static ssize_t vlan_stats_enabled_store(struct device *d,
821*4882a593Smuzhiyun struct device_attribute *attr,
822*4882a593Smuzhiyun const char *buf, size_t len)
823*4882a593Smuzhiyun {
824*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_vlan_set_stats);
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun static DEVICE_ATTR_RW(vlan_stats_enabled);
827*4882a593Smuzhiyun
vlan_stats_per_port_show(struct device * d,struct device_attribute * attr,char * buf)828*4882a593Smuzhiyun static ssize_t vlan_stats_per_port_show(struct device *d,
829*4882a593Smuzhiyun struct device_attribute *attr,
830*4882a593Smuzhiyun char *buf)
831*4882a593Smuzhiyun {
832*4882a593Smuzhiyun struct net_bridge *br = to_bridge(d);
833*4882a593Smuzhiyun return sprintf(buf, "%u\n", br_opt_get(br, BROPT_VLAN_STATS_PER_PORT));
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun
vlan_stats_per_port_store(struct device * d,struct device_attribute * attr,const char * buf,size_t len)836*4882a593Smuzhiyun static ssize_t vlan_stats_per_port_store(struct device *d,
837*4882a593Smuzhiyun struct device_attribute *attr,
838*4882a593Smuzhiyun const char *buf, size_t len)
839*4882a593Smuzhiyun {
840*4882a593Smuzhiyun return store_bridge_parm(d, buf, len, br_vlan_set_stats_per_port);
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun static DEVICE_ATTR_RW(vlan_stats_per_port);
843*4882a593Smuzhiyun #endif
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun static struct attribute *bridge_attrs[] = {
846*4882a593Smuzhiyun &dev_attr_forward_delay.attr,
847*4882a593Smuzhiyun &dev_attr_hello_time.attr,
848*4882a593Smuzhiyun &dev_attr_max_age.attr,
849*4882a593Smuzhiyun &dev_attr_ageing_time.attr,
850*4882a593Smuzhiyun &dev_attr_stp_state.attr,
851*4882a593Smuzhiyun &dev_attr_group_fwd_mask.attr,
852*4882a593Smuzhiyun &dev_attr_priority.attr,
853*4882a593Smuzhiyun &dev_attr_bridge_id.attr,
854*4882a593Smuzhiyun &dev_attr_root_id.attr,
855*4882a593Smuzhiyun &dev_attr_root_path_cost.attr,
856*4882a593Smuzhiyun &dev_attr_root_port.attr,
857*4882a593Smuzhiyun &dev_attr_topology_change.attr,
858*4882a593Smuzhiyun &dev_attr_topology_change_detected.attr,
859*4882a593Smuzhiyun &dev_attr_hello_timer.attr,
860*4882a593Smuzhiyun &dev_attr_tcn_timer.attr,
861*4882a593Smuzhiyun &dev_attr_topology_change_timer.attr,
862*4882a593Smuzhiyun &dev_attr_gc_timer.attr,
863*4882a593Smuzhiyun &dev_attr_group_addr.attr,
864*4882a593Smuzhiyun &dev_attr_flush.attr,
865*4882a593Smuzhiyun &dev_attr_no_linklocal_learn.attr,
866*4882a593Smuzhiyun #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
867*4882a593Smuzhiyun &dev_attr_multicast_router.attr,
868*4882a593Smuzhiyun &dev_attr_multicast_snooping.attr,
869*4882a593Smuzhiyun &dev_attr_multicast_querier.attr,
870*4882a593Smuzhiyun &dev_attr_multicast_query_use_ifaddr.attr,
871*4882a593Smuzhiyun &dev_attr_hash_elasticity.attr,
872*4882a593Smuzhiyun &dev_attr_hash_max.attr,
873*4882a593Smuzhiyun &dev_attr_multicast_last_member_count.attr,
874*4882a593Smuzhiyun &dev_attr_multicast_startup_query_count.attr,
875*4882a593Smuzhiyun &dev_attr_multicast_last_member_interval.attr,
876*4882a593Smuzhiyun &dev_attr_multicast_membership_interval.attr,
877*4882a593Smuzhiyun &dev_attr_multicast_querier_interval.attr,
878*4882a593Smuzhiyun &dev_attr_multicast_query_interval.attr,
879*4882a593Smuzhiyun &dev_attr_multicast_query_response_interval.attr,
880*4882a593Smuzhiyun &dev_attr_multicast_startup_query_interval.attr,
881*4882a593Smuzhiyun &dev_attr_multicast_stats_enabled.attr,
882*4882a593Smuzhiyun &dev_attr_multicast_igmp_version.attr,
883*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
884*4882a593Smuzhiyun &dev_attr_multicast_mld_version.attr,
885*4882a593Smuzhiyun #endif
886*4882a593Smuzhiyun #endif
887*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
888*4882a593Smuzhiyun &dev_attr_nf_call_iptables.attr,
889*4882a593Smuzhiyun &dev_attr_nf_call_ip6tables.attr,
890*4882a593Smuzhiyun &dev_attr_nf_call_arptables.attr,
891*4882a593Smuzhiyun #endif
892*4882a593Smuzhiyun #ifdef CONFIG_BRIDGE_VLAN_FILTERING
893*4882a593Smuzhiyun &dev_attr_vlan_filtering.attr,
894*4882a593Smuzhiyun &dev_attr_vlan_protocol.attr,
895*4882a593Smuzhiyun &dev_attr_default_pvid.attr,
896*4882a593Smuzhiyun &dev_attr_vlan_stats_enabled.attr,
897*4882a593Smuzhiyun &dev_attr_vlan_stats_per_port.attr,
898*4882a593Smuzhiyun #endif
899*4882a593Smuzhiyun NULL
900*4882a593Smuzhiyun };
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun static const struct attribute_group bridge_group = {
903*4882a593Smuzhiyun .name = SYSFS_BRIDGE_ATTR,
904*4882a593Smuzhiyun .attrs = bridge_attrs,
905*4882a593Smuzhiyun };
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun /*
908*4882a593Smuzhiyun * Export the forwarding information table as a binary file
909*4882a593Smuzhiyun * The records are struct __fdb_entry.
910*4882a593Smuzhiyun *
911*4882a593Smuzhiyun * Returns the number of bytes read.
912*4882a593Smuzhiyun */
brforward_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)913*4882a593Smuzhiyun static ssize_t brforward_read(struct file *filp, struct kobject *kobj,
914*4882a593Smuzhiyun struct bin_attribute *bin_attr,
915*4882a593Smuzhiyun char *buf, loff_t off, size_t count)
916*4882a593Smuzhiyun {
917*4882a593Smuzhiyun struct device *dev = kobj_to_dev(kobj);
918*4882a593Smuzhiyun struct net_bridge *br = to_bridge(dev);
919*4882a593Smuzhiyun int n;
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun /* must read whole records */
922*4882a593Smuzhiyun if (off % sizeof(struct __fdb_entry) != 0)
923*4882a593Smuzhiyun return -EINVAL;
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun n = br_fdb_fillbuf(br, buf,
926*4882a593Smuzhiyun count / sizeof(struct __fdb_entry),
927*4882a593Smuzhiyun off / sizeof(struct __fdb_entry));
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun if (n > 0)
930*4882a593Smuzhiyun n *= sizeof(struct __fdb_entry);
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun return n;
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun static struct bin_attribute bridge_forward = {
936*4882a593Smuzhiyun .attr = { .name = SYSFS_BRIDGE_FDB,
937*4882a593Smuzhiyun .mode = 0444, },
938*4882a593Smuzhiyun .read = brforward_read,
939*4882a593Smuzhiyun };
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun /*
942*4882a593Smuzhiyun * Add entries in sysfs onto the existing network class device
943*4882a593Smuzhiyun * for the bridge.
944*4882a593Smuzhiyun * Adds a attribute group "bridge" containing tuning parameters.
945*4882a593Smuzhiyun * Binary attribute containing the forward table
946*4882a593Smuzhiyun * Sub directory to hold links to interfaces.
947*4882a593Smuzhiyun *
948*4882a593Smuzhiyun * Note: the ifobj exists only to be a subdirectory
949*4882a593Smuzhiyun * to hold links. The ifobj exists in same data structure
950*4882a593Smuzhiyun * as it's parent the bridge so reference counting works.
951*4882a593Smuzhiyun */
br_sysfs_addbr(struct net_device * dev)952*4882a593Smuzhiyun int br_sysfs_addbr(struct net_device *dev)
953*4882a593Smuzhiyun {
954*4882a593Smuzhiyun struct kobject *brobj = &dev->dev.kobj;
955*4882a593Smuzhiyun struct net_bridge *br = netdev_priv(dev);
956*4882a593Smuzhiyun int err;
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun err = sysfs_create_group(brobj, &bridge_group);
959*4882a593Smuzhiyun if (err) {
960*4882a593Smuzhiyun pr_info("%s: can't create group %s/%s\n",
961*4882a593Smuzhiyun __func__, dev->name, bridge_group.name);
962*4882a593Smuzhiyun goto out1;
963*4882a593Smuzhiyun }
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun err = sysfs_create_bin_file(brobj, &bridge_forward);
966*4882a593Smuzhiyun if (err) {
967*4882a593Smuzhiyun pr_info("%s: can't create attribute file %s/%s\n",
968*4882a593Smuzhiyun __func__, dev->name, bridge_forward.attr.name);
969*4882a593Smuzhiyun goto out2;
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, brobj);
973*4882a593Smuzhiyun if (!br->ifobj) {
974*4882a593Smuzhiyun pr_info("%s: can't add kobject (directory) %s/%s\n",
975*4882a593Smuzhiyun __func__, dev->name, SYSFS_BRIDGE_PORT_SUBDIR);
976*4882a593Smuzhiyun err = -ENOMEM;
977*4882a593Smuzhiyun goto out3;
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun return 0;
980*4882a593Smuzhiyun out3:
981*4882a593Smuzhiyun sysfs_remove_bin_file(&dev->dev.kobj, &bridge_forward);
982*4882a593Smuzhiyun out2:
983*4882a593Smuzhiyun sysfs_remove_group(&dev->dev.kobj, &bridge_group);
984*4882a593Smuzhiyun out1:
985*4882a593Smuzhiyun return err;
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun
br_sysfs_delbr(struct net_device * dev)989*4882a593Smuzhiyun void br_sysfs_delbr(struct net_device *dev)
990*4882a593Smuzhiyun {
991*4882a593Smuzhiyun struct kobject *kobj = &dev->dev.kobj;
992*4882a593Smuzhiyun struct net_bridge *br = netdev_priv(dev);
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun kobject_put(br->ifobj);
995*4882a593Smuzhiyun sysfs_remove_bin_file(kobj, &bridge_forward);
996*4882a593Smuzhiyun sysfs_remove_group(kobj, &bridge_group);
997*4882a593Smuzhiyun }
998