Blame view

net/bridge/br_sysfs_if.c 7.63 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
29
30
  };
  
  #define BRPORT_ATTR(_name,_mode,_show,_store)		        \
  struct brport_attribute brport_attr_##_name = { 	        \
  	.attr = {.name = __stringify(_name), 			\
7b595756e   Tejun Heo   sysfs: kill unnec...
31
  		 .mode = _mode },				\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
38
39
40
  	.show	= _show,					\
  	.store	= _store,					\
  };
  
  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...
41

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR,
14f98f258   stephen hemminger   bridge: range che...
43
  		   show_path_cost, br_stp_set_path_cost);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
47
48
49
  
  static ssize_t show_priority(struct net_bridge_port *p, char *buf)
  {
  	return sprintf(buf, "%d
  ", p->priority);
  }
14f98f258   stephen hemminger   bridge: range che...
50

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR,
14f98f258   stephen hemminger   bridge: range che...
52
  			 show_priority, br_stp_set_port_priority);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
  
  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...
139
  static int store_flush(struct net_bridge_port *p, unsigned long v)
9cf637473   Stephen Hemminger   bridge: add sysfs...
140
141
142
143
144
  {
  	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);
3982d3d28   Fischer, Anna   net/bridge: Add '...
145
146
147
148
149
150
  static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf)
  {
  	int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0;
  	return sprintf(buf, "%d
  ", hairpin_mode);
  }
14f98f258   stephen hemminger   bridge: range che...
151
  static int store_hairpin_mode(struct net_bridge_port *p, unsigned long v)
3982d3d28   Fischer, Anna   net/bridge: Add '...
152
153
154
155
156
157
158
159
160
  {
  	if (v)
  		p->flags |= BR_HAIRPIN_MODE;
  	else
  		p->flags &= ~BR_HAIRPIN_MODE;
  	return 0;
  }
  static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
  		   show_hairpin_mode, store_hairpin_mode);
0909e1175   Herbert Xu   bridge: Add multi...
161
162
163
164
165
166
  #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...
167
  static int store_multicast_router(struct net_bridge_port *p,
0909e1175   Herbert Xu   bridge: Add multi...
168
169
170
171
172
173
174
  				      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);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  static struct brport_attribute *brport_attrs[] = {
  	&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...
190
  	&brport_attr_flush,
3982d3d28   Fischer, Anna   net/bridge: Add '...
191
  	&brport_attr_hairpin_mode,
0909e1175   Herbert Xu   bridge: Add multi...
192
193
194
  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  	&brport_attr_multicast_router,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  	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;
  
  	if (!capable(CAP_NET_ADMIN))
  		return -EPERM;
  
  	val = simple_strtoul(buf, &endp, 0);
  	if (endp != buf) {
af38f2989   Eric W. Biederman   net: Fix bridgein...
225
226
  		if (!rtnl_trylock())
  			return restart_syscall();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
231
232
233
234
235
236
237
  		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...
238
  const struct sysfs_ops brport_sysfs_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
  	.show = brport_show,
  	.store = brport_store,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
  /*
   * Add sysfs entries to ethernet device added to a bridge.
   * Creates a brport subdirectory with bridge attributes.
e0f43752a   Simon Arlott   bridge: update sy...
245
   * Puts symlink in bridge's brif subdirectory
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
248
249
250
251
   */
  int br_sysfs_addif(struct net_bridge_port *p)
  {
  	struct net_bridge *br = p->br;
  	struct brport_attribute **a;
  	int err;
43cb76d91   Greg Kroah-Hartman   Network: convert ...
252
  	err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
  				SYSFS_BRIDGE_PORT_LINK);
  	if (err)
e0f43752a   Simon Arlott   bridge: update sy...
255
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
258
259
  
  	for (a = brport_attrs; *a; ++a) {
  		err = sysfs_create_file(&p->kobj, &((*a)->attr));
  		if (err)
e0f43752a   Simon Arlott   bridge: update sy...
260
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
  	}
e0f43752a   Simon Arlott   bridge: update sy...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
  	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
285
286
  	return err;
  }