br_sysfs_br.c 23.1 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 *	Sysfs attributes of bridge
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12 13
 *	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.
 */

14
#include <linux/capability.h>
L
Linus Torvalds 已提交
15 16
#include <linux/kernel.h>
#include <linux/netdevice.h>
17
#include <linux/etherdevice.h>
L
Linus Torvalds 已提交
18 19 20 21 22 23 24
#include <linux/if_bridge.h>
#include <linux/rtnetlink.h>
#include <linux/spinlock.h>
#include <linux/times.h>

#include "br_private.h"

25
#define to_dev(obj)	container_of(obj, struct device, kobj)
26
#define to_bridge(cd)	((struct net_bridge *)netdev_priv(to_net_dev(cd)))
L
Linus Torvalds 已提交
27 28 29 30

/*
 * Common code for storing bridge parameters.
 */
31
static ssize_t store_bridge_parm(struct device *d,
L
Linus Torvalds 已提交
32
				 const char *buf, size_t len,
33
				 int (*set)(struct net_bridge *, unsigned long))
L
Linus Torvalds 已提交
34
{
35
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
36 37
	char *endp;
	unsigned long val;
38
	int err;
L
Linus Torvalds 已提交
39

40
	if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
L
Linus Torvalds 已提交
41 42 43 44 45 46
		return -EPERM;

	val = simple_strtoul(buf, &endp, 0);
	if (endp == buf)
		return -EINVAL;

47 48
	err = (*set)(br, val);
	return err ? err : len;
L
Linus Torvalds 已提交
49 50 51
}


52
static ssize_t forward_delay_show(struct device *d,
53
				  struct device_attribute *attr, char *buf)
L
Linus Torvalds 已提交
54
{
55
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
56 57 58
	return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
}

59
static ssize_t forward_delay_store(struct device *d,
60 61
				   struct device_attribute *attr,
				   const char *buf, size_t len)
L
Linus Torvalds 已提交
62
{
63
	return store_bridge_parm(d, buf, len, br_set_forward_delay);
L
Linus Torvalds 已提交
64
}
65
static DEVICE_ATTR_RW(forward_delay);
L
Linus Torvalds 已提交
66

67
static ssize_t hello_time_show(struct device *d, struct device_attribute *attr,
68
			       char *buf)
L
Linus Torvalds 已提交
69 70
{
	return sprintf(buf, "%lu\n",
71
		       jiffies_to_clock_t(to_bridge(d)->hello_time));
L
Linus Torvalds 已提交
72 73
}

74
static ssize_t hello_time_store(struct device *d,
75
				struct device_attribute *attr, const char *buf,
L
Linus Torvalds 已提交
76 77
				size_t len)
{
78
	return store_bridge_parm(d, buf, len, br_set_hello_time);
L
Linus Torvalds 已提交
79
}
80
static DEVICE_ATTR_RW(hello_time);
L
Linus Torvalds 已提交
81

82
static ssize_t max_age_show(struct device *d, struct device_attribute *attr,
83
			    char *buf)
L
Linus Torvalds 已提交
84 85
{
	return sprintf(buf, "%lu\n",
86
		       jiffies_to_clock_t(to_bridge(d)->max_age));
L
Linus Torvalds 已提交
87 88
}

89
static ssize_t max_age_store(struct device *d, struct device_attribute *attr,
90
			     const char *buf, size_t len)
L
Linus Torvalds 已提交
91
{
92
	return store_bridge_parm(d, buf, len, br_set_max_age);
L
Linus Torvalds 已提交
93
}
94
static DEVICE_ATTR_RW(max_age);
L
Linus Torvalds 已提交
95

96
static ssize_t ageing_time_show(struct device *d,
97
				struct device_attribute *attr, char *buf)
L
Linus Torvalds 已提交
98
{
99
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
100 101 102
	return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
}

103
static int set_ageing_time(struct net_bridge *br, unsigned long val)
L
Linus Torvalds 已提交
104 105
{
	br->ageing_time = clock_t_to_jiffies(val);
106
	return 0;
L
Linus Torvalds 已提交
107 108
}

109
static ssize_t ageing_time_store(struct device *d,
110 111
				 struct device_attribute *attr,
				 const char *buf, size_t len)
L
Linus Torvalds 已提交
112
{
113
	return store_bridge_parm(d, buf, len, set_ageing_time);
L
Linus Torvalds 已提交
114
}
115
static DEVICE_ATTR_RW(ageing_time);
L
Linus Torvalds 已提交
116

117
static ssize_t stp_state_show(struct device *d,
118
			      struct device_attribute *attr, char *buf)
L
Linus Torvalds 已提交
119
{
120
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
121 122 123 124
	return sprintf(buf, "%d\n", br->stp_enabled);
}


125
static ssize_t stp_state_store(struct device *d,
126 127
			       struct device_attribute *attr, const char *buf,
			       size_t len)
L
Linus Torvalds 已提交
128
{
S
Stephen Hemminger 已提交
129 130 131 132
	struct net_bridge *br = to_bridge(d);
	char *endp;
	unsigned long val;

133
	if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
S
Stephen Hemminger 已提交
134 135 136 137 138 139
		return -EPERM;

	val = simple_strtoul(buf, &endp, 0);
	if (endp == buf)
		return -EINVAL;

140 141
	if (!rtnl_trylock())
		return restart_syscall();
S
Stephen Hemminger 已提交
142 143 144
	br_stp_set_enabled(br, val);
	rtnl_unlock();

A
Al Viro 已提交
145
	return len;
L
Linus Torvalds 已提交
146
}
147
static DEVICE_ATTR_RW(stp_state);
L
Linus Torvalds 已提交
148

149 150 151
static ssize_t group_fwd_mask_show(struct device *d,
				   struct device_attribute *attr,
				   char *buf)
152 153 154 155 156 157
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%#x\n", br->group_fwd_mask);
}


158 159 160 161
static ssize_t group_fwd_mask_store(struct device *d,
				    struct device_attribute *attr,
				    const char *buf,
				    size_t len)
162 163 164 165 166
{
	struct net_bridge *br = to_bridge(d);
	char *endp;
	unsigned long val;

167
	if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
168 169 170 171 172 173 174 175 176 177 178 179 180
		return -EPERM;

	val = simple_strtoul(buf, &endp, 0);
	if (endp == buf)
		return -EINVAL;

	if (val & BR_GROUPFWD_RESTRICTED)
		return -EINVAL;

	br->group_fwd_mask = val;

	return len;
}
181
static DEVICE_ATTR_RW(group_fwd_mask);
182

183
static ssize_t priority_show(struct device *d, struct device_attribute *attr,
184
			     char *buf)
L
Linus Torvalds 已提交
185
{
186
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
187 188 189 190
	return sprintf(buf, "%d\n",
		       (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
}

191
static int set_priority(struct net_bridge *br, unsigned long val)
L
Linus Torvalds 已提交
192 193
{
	br_stp_set_bridge_priority(br, (u16) val);
194
	return 0;
L
Linus Torvalds 已提交
195 196
}

197 198
static ssize_t priority_store(struct device *d, struct device_attribute *attr,
			      const char *buf, size_t len)
L
Linus Torvalds 已提交
199
{
200
	return store_bridge_parm(d, buf, len, set_priority);
L
Linus Torvalds 已提交
201
}
202
static DEVICE_ATTR_RW(priority);
L
Linus Torvalds 已提交
203

204
static ssize_t root_id_show(struct device *d, struct device_attribute *attr,
205
			    char *buf)
L
Linus Torvalds 已提交
206
{
207
	return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
L
Linus Torvalds 已提交
208
}
209
static DEVICE_ATTR_RO(root_id);
L
Linus Torvalds 已提交
210

211
static ssize_t bridge_id_show(struct device *d, struct device_attribute *attr,
212
			      char *buf)
L
Linus Torvalds 已提交
213
{
214
	return br_show_bridge_id(buf, &to_bridge(d)->bridge_id);
L
Linus Torvalds 已提交
215
}
216
static DEVICE_ATTR_RO(bridge_id);
L
Linus Torvalds 已提交
217

218
static ssize_t root_port_show(struct device *d, struct device_attribute *attr,
219
			      char *buf)
L
Linus Torvalds 已提交
220
{
221
	return sprintf(buf, "%d\n", to_bridge(d)->root_port);
L
Linus Torvalds 已提交
222
}
223
static DEVICE_ATTR_RO(root_port);
L
Linus Torvalds 已提交
224

225
static ssize_t root_path_cost_show(struct device *d,
226
				   struct device_attribute *attr, char *buf)
L
Linus Torvalds 已提交
227
{
228
	return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost);
L
Linus Torvalds 已提交
229
}
230
static DEVICE_ATTR_RO(root_path_cost);
L
Linus Torvalds 已提交
231

232
static ssize_t topology_change_show(struct device *d,
233
				    struct device_attribute *attr, char *buf)
L
Linus Torvalds 已提交
234
{
235
	return sprintf(buf, "%d\n", to_bridge(d)->topology_change);
L
Linus Torvalds 已提交
236
}
237
static DEVICE_ATTR_RO(topology_change);
L
Linus Torvalds 已提交
238

239
static ssize_t topology_change_detected_show(struct device *d,
240 241
					     struct device_attribute *attr,
					     char *buf)
L
Linus Torvalds 已提交
242
{
243
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
244 245
	return sprintf(buf, "%d\n", br->topology_change_detected);
}
246
static DEVICE_ATTR_RO(topology_change_detected);
L
Linus Torvalds 已提交
247

248
static ssize_t hello_timer_show(struct device *d,
249
				struct device_attribute *attr, char *buf)
L
Linus Torvalds 已提交
250
{
251
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
252 253
	return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer));
}
254
static DEVICE_ATTR_RO(hello_timer);
L
Linus Torvalds 已提交
255

256
static ssize_t tcn_timer_show(struct device *d, struct device_attribute *attr,
257
			      char *buf)
L
Linus Torvalds 已提交
258
{
259
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
260 261
	return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer));
}
262
static DEVICE_ATTR_RO(tcn_timer);
L
Linus Torvalds 已提交
263

264
static ssize_t topology_change_timer_show(struct device *d,
265 266
					  struct device_attribute *attr,
					  char *buf)
L
Linus Torvalds 已提交
267
{
268
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
269 270
	return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer));
}
271
static DEVICE_ATTR_RO(topology_change_timer);
L
Linus Torvalds 已提交
272

273
static ssize_t gc_timer_show(struct device *d, struct device_attribute *attr,
274
			     char *buf)
L
Linus Torvalds 已提交
275
{
276
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
277 278
	return sprintf(buf, "%ld\n", br_timer_value(&br->gc_timer));
}
279
static DEVICE_ATTR_RO(gc_timer);
L
Linus Torvalds 已提交
280

281
static ssize_t group_addr_show(struct device *d,
282
			       struct device_attribute *attr, char *buf)
283
{
284
	struct net_bridge *br = to_bridge(d);
285 286 287 288 289 290
	return sprintf(buf, "%x:%x:%x:%x:%x:%x\n",
		       br->group_addr[0], br->group_addr[1],
		       br->group_addr[2], br->group_addr[3],
		       br->group_addr[4], br->group_addr[5]);
}

291
static ssize_t group_addr_store(struct device *d,
292 293
				struct device_attribute *attr,
				const char *buf, size_t len)
294
{
295
	struct net_bridge *br = to_bridge(d);
296
	u8 new_addr[6];
297 298
	int i;

299
	if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
300 301
		return -EPERM;

302
	if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
303 304 305 306
		   &new_addr[0], &new_addr[1], &new_addr[2],
		   &new_addr[3], &new_addr[4], &new_addr[5]) != 6)
		return -EINVAL;

307
	if (!is_link_local_ether_addr(new_addr))
308 309
		return -EINVAL;

310 311 312
	if (new_addr[5] == 1 ||		/* 802.3x Pause address */
	    new_addr[5] == 2 ||		/* 802.3ad Slow protocols */
	    new_addr[5] == 3)		/* 802.1X PAE address */
313 314
		return -EINVAL;

315 316 317
	if (!rtnl_trylock())
		return restart_syscall();

318 319 320 321
	spin_lock_bh(&br->lock);
	for (i = 0; i < 6; i++)
		br->group_addr[i] = new_addr[i];
	spin_unlock_bh(&br->lock);
322 323 324 325 326 327

	br->group_addr_set = true;
	br_recalculate_fwd_mask(br);

	rtnl_unlock();

328 329 330
	return len;
}

331
static DEVICE_ATTR_RW(group_addr);
332

333
static ssize_t flush_store(struct device *d,
334 335 336 337 338
			   struct device_attribute *attr,
			   const char *buf, size_t len)
{
	struct net_bridge *br = to_bridge(d);

339
	if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
340 341 342 343 344
		return -EPERM;

	br_fdb_flush(br);
	return len;
}
345
static DEVICE_ATTR_WO(flush);
346

347
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
348
static ssize_t multicast_router_show(struct device *d,
349 350 351 352 353 354
				     struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->multicast_router);
}

355
static ssize_t multicast_router_store(struct device *d,
356 357 358 359 360
				      struct device_attribute *attr,
				      const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_multicast_set_router);
}
361
static DEVICE_ATTR_RW(multicast_router);
362

363
static ssize_t multicast_snooping_show(struct device *d,
364 365 366 367 368 369 370
				       struct device_attribute *attr,
				       char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", !br->multicast_disabled);
}

371
static ssize_t multicast_snooping_store(struct device *d,
372 373 374 375 376
					struct device_attribute *attr,
					const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_multicast_toggle);
}
377
static DEVICE_ATTR_RW(multicast_snooping);
378

379 380 381
static ssize_t multicast_query_use_ifaddr_show(struct device *d,
					       struct device_attribute *attr,
					       char *buf)
382 383 384 385 386 387 388 389 390 391 392 393
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->multicast_query_use_ifaddr);
}

static int set_query_use_ifaddr(struct net_bridge *br, unsigned long val)
{
	br->multicast_query_use_ifaddr = !!val;
	return 0;
}

static ssize_t
394
multicast_query_use_ifaddr_store(struct device *d,
395 396 397 398 399
				 struct device_attribute *attr,
				 const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_query_use_ifaddr);
}
400
static DEVICE_ATTR_RW(multicast_query_use_ifaddr);
401

402
static ssize_t multicast_querier_show(struct device *d,
403 404 405 406 407 408 409
				      struct device_attribute *attr,
				      char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->multicast_querier);
}

410
static ssize_t multicast_querier_store(struct device *d,
411 412 413 414 415
				       struct device_attribute *attr,
				       const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_multicast_set_querier);
}
416
static DEVICE_ATTR_RW(multicast_querier);
417

418
static ssize_t hash_elasticity_show(struct device *d,
419 420 421 422 423 424 425 426 427 428 429 430
				    struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%u\n", br->hash_elasticity);
}

static int set_elasticity(struct net_bridge *br, unsigned long val)
{
	br->hash_elasticity = val;
	return 0;
}

431
static ssize_t hash_elasticity_store(struct device *d,
432 433 434 435 436
				     struct device_attribute *attr,
				     const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_elasticity);
}
437
static DEVICE_ATTR_RW(hash_elasticity);
438

439
static ssize_t hash_max_show(struct device *d, struct device_attribute *attr,
440 441 442 443 444 445
			     char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%u\n", br->hash_max);
}

446
static ssize_t hash_max_store(struct device *d, struct device_attribute *attr,
447 448 449 450
			      const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_multicast_set_hash_max);
}
451
static DEVICE_ATTR_RW(hash_max);
452

453
static ssize_t multicast_last_member_count_show(struct device *d,
454 455 456 457 458 459 460 461 462 463 464 465 466
						struct device_attribute *attr,
						char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%u\n", br->multicast_last_member_count);
}

static int set_last_member_count(struct net_bridge *br, unsigned long val)
{
	br->multicast_last_member_count = val;
	return 0;
}

467
static ssize_t multicast_last_member_count_store(struct device *d,
468 469 470 471 472
						 struct device_attribute *attr,
						 const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_last_member_count);
}
473
static DEVICE_ATTR_RW(multicast_last_member_count);
474

475
static ssize_t multicast_startup_query_count_show(
476 477 478 479 480 481 482 483 484 485 486 487
	struct device *d, struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%u\n", br->multicast_startup_query_count);
}

static int set_startup_query_count(struct net_bridge *br, unsigned long val)
{
	br->multicast_startup_query_count = val;
	return 0;
}

488
static ssize_t multicast_startup_query_count_store(
489 490 491 492 493
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_startup_query_count);
}
494
static DEVICE_ATTR_RW(multicast_startup_query_count);
495

496
static ssize_t multicast_last_member_interval_show(
497 498 499 500 501 502 503 504 505 506 507 508 509
	struct device *d, struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%lu\n",
		       jiffies_to_clock_t(br->multicast_last_member_interval));
}

static int set_last_member_interval(struct net_bridge *br, unsigned long val)
{
	br->multicast_last_member_interval = clock_t_to_jiffies(val);
	return 0;
}

510
static ssize_t multicast_last_member_interval_store(
511 512 513 514 515
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_last_member_interval);
}
516
static DEVICE_ATTR_RW(multicast_last_member_interval);
517

518
static ssize_t multicast_membership_interval_show(
519 520 521 522 523 524 525 526 527 528 529 530 531
	struct device *d, struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%lu\n",
		       jiffies_to_clock_t(br->multicast_membership_interval));
}

static int set_membership_interval(struct net_bridge *br, unsigned long val)
{
	br->multicast_membership_interval = clock_t_to_jiffies(val);
	return 0;
}

532
static ssize_t multicast_membership_interval_store(
533 534 535 536 537
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_membership_interval);
}
538
static DEVICE_ATTR_RW(multicast_membership_interval);
539

540
static ssize_t multicast_querier_interval_show(struct device *d,
541 542 543 544 545 546 547 548 549 550 551 552 553 554
					       struct device_attribute *attr,
					       char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%lu\n",
		       jiffies_to_clock_t(br->multicast_querier_interval));
}

static int set_querier_interval(struct net_bridge *br, unsigned long val)
{
	br->multicast_querier_interval = clock_t_to_jiffies(val);
	return 0;
}

555
static ssize_t multicast_querier_interval_store(struct device *d,
556 557 558 559 560
						struct device_attribute *attr,
						const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_querier_interval);
}
561
static DEVICE_ATTR_RW(multicast_querier_interval);
562

563
static ssize_t multicast_query_interval_show(struct device *d,
564 565 566 567 568 569 570 571 572 573 574 575 576 577
					     struct device_attribute *attr,
					     char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%lu\n",
		       jiffies_to_clock_t(br->multicast_query_interval));
}

static int set_query_interval(struct net_bridge *br, unsigned long val)
{
	br->multicast_query_interval = clock_t_to_jiffies(val);
	return 0;
}

578
static ssize_t multicast_query_interval_store(struct device *d,
579 580 581 582 583
					      struct device_attribute *attr,
					      const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_query_interval);
}
584
static DEVICE_ATTR_RW(multicast_query_interval);
585

586
static ssize_t multicast_query_response_interval_show(
587 588 589 590 591 592 593 594 595 596 597 598 599 600
	struct device *d, struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(
		buf, "%lu\n",
		jiffies_to_clock_t(br->multicast_query_response_interval));
}

static int set_query_response_interval(struct net_bridge *br, unsigned long val)
{
	br->multicast_query_response_interval = clock_t_to_jiffies(val);
	return 0;
}

601
static ssize_t multicast_query_response_interval_store(
602 603 604 605 606
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_query_response_interval);
}
607
static DEVICE_ATTR_RW(multicast_query_response_interval);
608

609
static ssize_t multicast_startup_query_interval_show(
610 611 612 613 614 615 616 617 618 619 620 621 622 623
	struct device *d, struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(
		buf, "%lu\n",
		jiffies_to_clock_t(br->multicast_startup_query_interval));
}

static int set_startup_query_interval(struct net_bridge *br, unsigned long val)
{
	br->multicast_startup_query_interval = clock_t_to_jiffies(val);
	return 0;
}

624
static ssize_t multicast_startup_query_interval_store(
625 626 627 628 629
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_startup_query_interval);
}
630
static DEVICE_ATTR_RW(multicast_startup_query_interval);
631
#endif
632
#ifdef CONFIG_BRIDGE_NETFILTER
633
static ssize_t nf_call_iptables_show(
634 635 636 637 638 639 640 641 642 643 644 645
	struct device *d, struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%u\n", br->nf_call_iptables);
}

static int set_nf_call_iptables(struct net_bridge *br, unsigned long val)
{
	br->nf_call_iptables = val ? true : false;
	return 0;
}

646
static ssize_t nf_call_iptables_store(
647 648 649 650 651
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_nf_call_iptables);
}
652
static DEVICE_ATTR_RW(nf_call_iptables);
653

654
static ssize_t nf_call_ip6tables_show(
655 656 657 658 659 660 661 662 663 664 665 666
	struct device *d, struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%u\n", br->nf_call_ip6tables);
}

static int set_nf_call_ip6tables(struct net_bridge *br, unsigned long val)
{
	br->nf_call_ip6tables = val ? true : false;
	return 0;
}

667
static ssize_t nf_call_ip6tables_store(
668 669 670 671 672
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_nf_call_ip6tables);
}
673
static DEVICE_ATTR_RW(nf_call_ip6tables);
674

675
static ssize_t nf_call_arptables_show(
676 677 678 679 680 681 682 683 684 685 686 687
	struct device *d, struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%u\n", br->nf_call_arptables);
}

static int set_nf_call_arptables(struct net_bridge *br, unsigned long val)
{
	br->nf_call_arptables = val ? true : false;
	return 0;
}

688
static ssize_t nf_call_arptables_store(
689 690 691 692 693
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_nf_call_arptables);
}
694
static DEVICE_ATTR_RW(nf_call_arptables);
695
#endif
696
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
697
static ssize_t vlan_filtering_show(struct device *d,
698 699 700 701 702 703 704
				   struct device_attribute *attr,
				   char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->vlan_enabled);
}

705
static ssize_t vlan_filtering_store(struct device *d,
706 707 708 709 710
				    struct device_attribute *attr,
				    const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_vlan_filter_toggle);
}
711
static DEVICE_ATTR_RW(vlan_filtering);
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727

static ssize_t vlan_protocol_show(struct device *d,
				  struct device_attribute *attr,
				  char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%#06x\n", ntohs(br->vlan_proto));
}

static ssize_t vlan_protocol_store(struct device *d,
				   struct device_attribute *attr,
				   const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_vlan_set_proto);
}
static DEVICE_ATTR_RW(vlan_protocol);
728
#endif
729

L
Linus Torvalds 已提交
730
static struct attribute *bridge_attrs[] = {
731 732 733 734 735
	&dev_attr_forward_delay.attr,
	&dev_attr_hello_time.attr,
	&dev_attr_max_age.attr,
	&dev_attr_ageing_time.attr,
	&dev_attr_stp_state.attr,
736
	&dev_attr_group_fwd_mask.attr,
737 738 739 740 741 742 743 744 745 746 747 748
	&dev_attr_priority.attr,
	&dev_attr_bridge_id.attr,
	&dev_attr_root_id.attr,
	&dev_attr_root_path_cost.attr,
	&dev_attr_root_port.attr,
	&dev_attr_topology_change.attr,
	&dev_attr_topology_change_detected.attr,
	&dev_attr_hello_timer.attr,
	&dev_attr_tcn_timer.attr,
	&dev_attr_topology_change_timer.attr,
	&dev_attr_gc_timer.attr,
	&dev_attr_group_addr.attr,
749
	&dev_attr_flush.attr,
750 751
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
	&dev_attr_multicast_router.attr,
752
	&dev_attr_multicast_snooping.attr,
753
	&dev_attr_multicast_querier.attr,
754
	&dev_attr_multicast_query_use_ifaddr.attr,
755 756
	&dev_attr_hash_elasticity.attr,
	&dev_attr_hash_max.attr,
757 758 759 760 761 762 763 764
	&dev_attr_multicast_last_member_count.attr,
	&dev_attr_multicast_startup_query_count.attr,
	&dev_attr_multicast_last_member_interval.attr,
	&dev_attr_multicast_membership_interval.attr,
	&dev_attr_multicast_querier_interval.attr,
	&dev_attr_multicast_query_interval.attr,
	&dev_attr_multicast_query_response_interval.attr,
	&dev_attr_multicast_startup_query_interval.attr,
765 766 767 768 769
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
	&dev_attr_nf_call_iptables.attr,
	&dev_attr_nf_call_ip6tables.attr,
	&dev_attr_nf_call_arptables.attr,
770 771 772
#endif
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
	&dev_attr_vlan_filtering.attr,
773
	&dev_attr_vlan_protocol.attr,
774
#endif
L
Linus Torvalds 已提交
775 776 777 778 779 780 781 782 783 784 785 786 787 788
	NULL
};

static struct attribute_group bridge_group = {
	.name = SYSFS_BRIDGE_ATTR,
	.attrs = bridge_attrs,
};

/*
 * Export the forwarding information table as a binary file
 * The records are struct __fdb_entry.
 *
 * Returns the number of bytes read.
 */
789
static ssize_t brforward_read(struct file *filp, struct kobject *kobj,
790 791
			      struct bin_attribute *bin_attr,
			      char *buf, loff_t off, size_t count)
L
Linus Torvalds 已提交
792
{
793 794
	struct device *dev = to_dev(kobj);
	struct net_bridge *br = to_bridge(dev);
L
Linus Torvalds 已提交
795 796 797 798 799 800
	int n;

	/* must read whole records */
	if (off % sizeof(struct __fdb_entry) != 0)
		return -EINVAL;

801
	n =  br_fdb_fillbuf(br, buf,
L
Linus Torvalds 已提交
802 803 804 805 806
			    count / sizeof(struct __fdb_entry),
			    off / sizeof(struct __fdb_entry));

	if (n > 0)
		n *= sizeof(struct __fdb_entry);
807

L
Linus Torvalds 已提交
808 809 810 811 812
	return n;
}

static struct bin_attribute bridge_forward = {
	.attr = { .name = SYSFS_BRIDGE_FDB,
813
		  .mode = S_IRUGO, },
L
Linus Torvalds 已提交
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
	.read = brforward_read,
};

/*
 * Add entries in sysfs onto the existing network class device
 * for the bridge.
 *   Adds a attribute group "bridge" containing tuning parameters.
 *   Binary attribute containing the forward table
 *   Sub directory to hold links to interfaces.
 *
 * Note: the ifobj exists only to be a subdirectory
 *   to hold links.  The ifobj exists in same data structure
 *   as it's parent the bridge so reference counting works.
 */
int br_sysfs_addbr(struct net_device *dev)
{
830
	struct kobject *brobj = &dev->dev.kobj;
L
Linus Torvalds 已提交
831 832 833 834 835 836
	struct net_bridge *br = netdev_priv(dev);
	int err;

	err = sysfs_create_group(brobj, &bridge_group);
	if (err) {
		pr_info("%s: can't create group %s/%s\n",
837
			__func__, dev->name, bridge_group.name);
L
Linus Torvalds 已提交
838 839 840 841 842
		goto out1;
	}

	err = sysfs_create_bin_file(brobj, &bridge_forward);
	if (err) {
843
		pr_info("%s: can't create attribute file %s/%s\n",
844
			__func__, dev->name, bridge_forward.attr.name);
L
Linus Torvalds 已提交
845 846 847
		goto out2;
	}

848 849
	br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, brobj);
	if (!br->ifobj) {
L
Linus Torvalds 已提交
850
		pr_info("%s: can't add kobject (directory) %s/%s\n",
851
			__func__, dev->name, SYSFS_BRIDGE_PORT_SUBDIR);
L
Linus Torvalds 已提交
852 853 854 855
		goto out3;
	}
	return 0;
 out3:
856
	sysfs_remove_bin_file(&dev->dev.kobj, &bridge_forward);
L
Linus Torvalds 已提交
857
 out2:
858
	sysfs_remove_group(&dev->dev.kobj, &bridge_group);
L
Linus Torvalds 已提交
859 860 861 862 863 864 865
 out1:
	return err;

}

void br_sysfs_delbr(struct net_device *dev)
{
866
	struct kobject *kobj = &dev->dev.kobj;
L
Linus Torvalds 已提交
867 868
	struct net_bridge *br = netdev_priv(dev);

869
	kobject_put(br->ifobj);
L
Linus Torvalds 已提交
870 871 872
	sysfs_remove_bin_file(kobj, &bridge_forward);
	sysfs_remove_group(kobj, &bridge_group);
}