Blame view

net/bridge/br_sysfs_if.c 8.12 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   *	Sysfs attributes of bridge ports
   *	Linux ethernet bridge
   *
   *	Authors:
   *	Stephen Hemminger		<shemminger@osdl.org>
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   */
4fc268d24   Randy Dunlap   [PATCH] capable/c...
13
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
19
20
21
22
23
24
  #include <linux/kernel.h>
  #include <linux/netdevice.h>
  #include <linux/if_bridge.h>
  #include <linux/rtnetlink.h>
  #include <linux/spinlock.h>
  
  #include "br_private.h"
  
  struct brport_attribute {
  	struct attribute	attr;
  	ssize_t (*show)(struct net_bridge_port *, char *);
14f98f258   stephen hemminger   bridge: range che...
25
  	int (*store)(struct net_bridge_port *, unsigned long);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
  };
  
  #define BRPORT_ATTR(_name,_mode,_show,_store)		        \
5a0d513b6   stephen hemminger   bridge: make port...
29
  const struct brport_attribute brport_attr_##_name = { 	        \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  	.attr = {.name = __stringify(_name), 			\
7b595756e   Tejun Heo   sysfs: kill unnec...
31
  		 .mode = _mode },				\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
  	.show	= _show,					\
  	.store	= _store,					\
  };
cd7537326   stephen hemminger   bridge: add templ...
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  #define BRPORT_ATTR_FLAG(_name, _mask)				\
  static ssize_t show_##_name(struct net_bridge_port *p, char *buf) \
  {								\
  	return sprintf(buf, "%d
  ", !!(p->flags & _mask));	\
  }								\
  static int store_##_name(struct net_bridge_port *p, unsigned long v) \
  {								\
  	unsigned long flags = p->flags;				\
  	if (v)							\
  		flags |= _mask;					\
  	else							\
  		flags &= ~_mask;				\
  	if (flags != p->flags) {				\
  		p->flags = flags;				\
  		br_ifinfo_notify(RTM_NEWLINK, p);		\
  	}							\
  	return 0;						\
  }								\
  static BRPORT_ATTR(_name, S_IRUGO | S_IWUSR,			\
  		   show_##_name, store_##_name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
  static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "%d
  ", p->path_cost);
  }
14f98f258   stephen hemminger   bridge: range che...
61

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR,
14f98f258   stephen hemminger   bridge: range che...
63
  		   show_path_cost, br_stp_set_path_cost);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
  
  static ssize_t show_priority(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "%d
  ", p->priority);
  }
14f98f258   stephen hemminger   bridge: range che...
70

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR,
14f98f258   stephen hemminger   bridge: range che...
72
  			 show_priority, br_stp_set_port_priority);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  
  static ssize_t show_designated_root(struct net_bridge_port *p, char *buf)
  {
  	return br_show_bridge_id(buf, &p->designated_root);
  }
  static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL);
  
  static ssize_t show_designated_bridge(struct net_bridge_port *p, char *buf)
  {
  	return br_show_bridge_id(buf, &p->designated_bridge);
  }
  static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL);
  
  static ssize_t show_designated_port(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "%d
  ", p->designated_port);
  }
  static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL);
  
  static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "%d
  ", p->designated_cost);
  }
  static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL);
  
  static ssize_t show_port_id(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "0x%x
  ", p->port_id);
  }
  static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL);
  
  static ssize_t show_port_no(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "0x%x
  ", p->port_no);
  }
  
  static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL);
  
  static ssize_t show_change_ack(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "%d
  ", p->topology_change_ack);
  }
  static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL);
  
  static ssize_t show_config_pending(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "%d
  ", p->config_pending);
  }
  static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL);
  
  static ssize_t show_port_state(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "%d
  ", p->state);
  }
  static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL);
  
  static ssize_t show_message_age_timer(struct net_bridge_port *p,
  					    char *buf)
  {
  	return sprintf(buf, "%ld
  ", br_timer_value(&p->message_age_timer));
  }
  static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL);
  
  static ssize_t show_forward_delay_timer(struct net_bridge_port *p,
  					    char *buf)
  {
  	return sprintf(buf, "%ld
  ", br_timer_value(&p->forward_delay_timer));
  }
  static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL);
  
  static ssize_t show_hold_timer(struct net_bridge_port *p,
  					    char *buf)
  {
  	return sprintf(buf, "%ld
  ", br_timer_value(&p->hold_timer));
  }
  static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL);
14f98f258   stephen hemminger   bridge: range che...
159
  static int store_flush(struct net_bridge_port *p, unsigned long v)
9cf637473   Stephen Hemminger   bridge: add sysfs...
160
161
162
163
164
  {
  	br_fdb_delete_by_port(p->br, p, 0); // Don't delete local entry
  	return 0;
  }
  static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);
cd7537326   stephen hemminger   bridge: add templ...
165
  BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE);
a2e01a65c   stephen hemminger   bridge: implement...
166
  BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD);
1007dd1aa   stephen hemminger   bridge: add root ...
167
  BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK);
3982d3d28   Fischer, Anna   net/bridge: Add '...
168

0909e1175   Herbert Xu   bridge: Add multi...
169
170
171
172
173
174
  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "%d
  ", p->multicast_router);
  }
14f98f258   stephen hemminger   bridge: range che...
175
  static int store_multicast_router(struct net_bridge_port *p,
0909e1175   Herbert Xu   bridge: Add multi...
176
177
178
179
180
181
  				      unsigned long v)
  {
  	return br_multicast_set_port_router(p, v);
  }
  static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
  		   store_multicast_router);
50426b592   Amerigo Wang   bridge: implement...
182

c2d3babfa   David S. Miller   bridge: implement...
183
  BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
0909e1175   Herbert Xu   bridge: Add multi...
184
  #endif
5a0d513b6   stephen hemminger   bridge: make port...
185
  static const struct brport_attribute *brport_attrs[] = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  	&brport_attr_path_cost,
  	&brport_attr_priority,
  	&brport_attr_port_id,
  	&brport_attr_port_no,
  	&brport_attr_designated_root,
  	&brport_attr_designated_bridge,
  	&brport_attr_designated_port,
  	&brport_attr_designated_cost,
  	&brport_attr_state,
  	&brport_attr_change_ack,
  	&brport_attr_config_pending,
  	&brport_attr_message_age_timer,
  	&brport_attr_forward_delay_timer,
  	&brport_attr_hold_timer,
9cf637473   Stephen Hemminger   bridge: add sysfs...
200
  	&brport_attr_flush,
3982d3d28   Fischer, Anna   net/bridge: Add '...
201
  	&brport_attr_hairpin_mode,
a2e01a65c   stephen hemminger   bridge: implement...
202
  	&brport_attr_bpdu_guard,
1007dd1aa   stephen hemminger   bridge: add root ...
203
  	&brport_attr_root_block,
0909e1175   Herbert Xu   bridge: Add multi...
204
205
  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  	&brport_attr_multicast_router,
50426b592   Amerigo Wang   bridge: implement...
206
  	&brport_attr_multicast_fast_leave,
0909e1175   Herbert Xu   bridge: Add multi...
207
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  	NULL
  };
  
  #define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr)
  #define to_brport(obj)	container_of(obj, struct net_bridge_port, kobj)
  
  static ssize_t brport_show(struct kobject * kobj,
  			   struct attribute * attr, char * buf)
  {
  	struct brport_attribute * brport_attr = to_brport_attr(attr);
  	struct net_bridge_port * p = to_brport(kobj);
  
  	return brport_attr->show(p, buf);
  }
  
  static ssize_t brport_store(struct kobject * kobj,
  			    struct attribute * attr,
  			    const char * buf, size_t count)
  {
  	struct brport_attribute * brport_attr = to_brport_attr(attr);
  	struct net_bridge_port * p = to_brport(kobj);
  	ssize_t ret = -EINVAL;
  	char *endp;
  	unsigned long val;
cb9905030   Eric W. Biederman   net: Allow userns...
232
  	if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
236
  		return -EPERM;
  
  	val = simple_strtoul(buf, &endp, 0);
  	if (endp != buf) {
af38f2989   Eric W. Biederman   net: Fix bridgein...
237
238
  		if (!rtnl_trylock())
  			return restart_syscall();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
242
243
244
245
246
247
248
249
  		if (p->dev && p->br && brport_attr->store) {
  			spin_lock_bh(&p->br->lock);
  			ret = brport_attr->store(p, val);
  			spin_unlock_bh(&p->br->lock);
  			if (ret == 0)
  				ret = count;
  		}
  		rtnl_unlock();
  	}
  	return ret;
  }
52cf25d0a   Emese Revfy   Driver core: Cons...
250
  const struct sysfs_ops brport_sysfs_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
253
  	.show = brport_show,
  	.store = brport_store,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
256
  /*
   * Add sysfs entries to ethernet device added to a bridge.
   * Creates a brport subdirectory with bridge attributes.
e0f43752a   Simon Arlott   bridge: update sy...
257
   * Puts symlink in bridge's brif subdirectory
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
261
   */
  int br_sysfs_addif(struct net_bridge_port *p)
  {
  	struct net_bridge *br = p->br;
5a0d513b6   stephen hemminger   bridge: make port...
262
  	const struct brport_attribute **a;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	int err;
43cb76d91   Greg Kroah-Hartman   Network: convert ...
264
  	err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
  				SYSFS_BRIDGE_PORT_LINK);
  	if (err)
e0f43752a   Simon Arlott   bridge: update sy...
267
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
271
  
  	for (a = brport_attrs; *a; ++a) {
  		err = sysfs_create_file(&p->kobj, &((*a)->attr));
  		if (err)
e0f43752a   Simon Arlott   bridge: update sy...
272
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  	}
e0f43752a   Simon Arlott   bridge: update sy...
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  	strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ);
  	return sysfs_create_link(br->ifobj, &p->kobj, p->sysfs_name);
  }
  
  /* Rename bridge's brif symlink */
  int br_sysfs_renameif(struct net_bridge_port *p)
  {
  	struct net_bridge *br = p->br;
  	int err;
  
  	/* If a rename fails, the rollback will cause another
  	 * rename call with the existing name.
  	 */
  	if (!strncmp(p->sysfs_name, p->dev->name, IFNAMSIZ))
  		return 0;
  
  	err = sysfs_rename_link(br->ifobj, &p->kobj,
  				p->sysfs_name, p->dev->name);
  	if (err)
  		netdev_notice(br->dev, "unable to rename link %s to %s",
  			      p->sysfs_name, p->dev->name);
  	else
  		strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
  	return err;
  }