br_sysfs_br.c 23.4 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_bridge(cd)	((struct net_bridge *)netdev_priv(to_net_dev(cd)))
L
Linus Torvalds 已提交
26 27 28 29

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

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

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

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


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

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

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

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

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

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

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

102
static int set_ageing_time(struct net_bridge *br, unsigned long val)
L
Linus Torvalds 已提交
103
{
104 105 106 107 108 109 110 111 112
	int ret;

	if (!rtnl_trylock())
		return restart_syscall();

	ret = br_set_ageing_time(br, val);
	rtnl_unlock();

	return ret;
L
Linus Torvalds 已提交
113 114
}

115
static ssize_t ageing_time_store(struct device *d,
116 117
				 struct device_attribute *attr,
				 const char *buf, size_t len)
L
Linus Torvalds 已提交
118
{
119
	return store_bridge_parm(d, buf, len, set_ageing_time);
L
Linus Torvalds 已提交
120
}
121
static DEVICE_ATTR_RW(ageing_time);
L
Linus Torvalds 已提交
122

123
static ssize_t stp_state_show(struct device *d,
124
			      struct device_attribute *attr, char *buf)
L
Linus Torvalds 已提交
125
{
126
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
127 128 129 130
	return sprintf(buf, "%d\n", br->stp_enabled);
}


131
static int set_stp_state(struct net_bridge *br, unsigned long val)
L
Linus Torvalds 已提交
132
{
133 134
	if (!rtnl_trylock())
		return restart_syscall();
S
Stephen Hemminger 已提交
135 136 137
	br_stp_set_enabled(br, val);
	rtnl_unlock();

138 139 140 141 142 143 144 145
	return 0;
}

static ssize_t stp_state_store(struct device *d,
			       struct device_attribute *attr, const char *buf,
			       size_t len)
{
	return store_bridge_parm(d, buf, len, set_stp_state);
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
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%#x\n", br->group_fwd_mask);
}

157
static int set_group_fwd_mask(struct net_bridge *br, unsigned long val)
158 159 160 161 162 163
{
	if (val & BR_GROUPFWD_RESTRICTED)
		return -EINVAL;

	br->group_fwd_mask = val;

164 165 166 167 168 169 170 171 172
	return 0;
}

static ssize_t group_fwd_mask_store(struct device *d,
				    struct device_attribute *attr,
				    const char *buf,
				    size_t len)
{
	return store_bridge_parm(d, buf, len, set_group_fwd_mask);
173
}
174
static DEVICE_ATTR_RW(group_fwd_mask);
175

176
static ssize_t priority_show(struct device *d, struct device_attribute *attr,
177
			     char *buf)
L
Linus Torvalds 已提交
178
{
179
	struct net_bridge *br = to_bridge(d);
L
Linus Torvalds 已提交
180 181 182 183
	return sprintf(buf, "%d\n",
		       (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
}

184
static int set_priority(struct net_bridge *br, unsigned long val)
L
Linus Torvalds 已提交
185 186
{
	br_stp_set_bridge_priority(br, (u16) val);
187
	return 0;
L
Linus Torvalds 已提交
188 189
}

190 191
static ssize_t priority_store(struct device *d, struct device_attribute *attr,
			      const char *buf, size_t len)
L
Linus Torvalds 已提交
192
{
193
	return store_bridge_parm(d, buf, len, set_priority);
L
Linus Torvalds 已提交
194
}
195
static DEVICE_ATTR_RW(priority);
L
Linus Torvalds 已提交
196

197
static ssize_t root_id_show(struct device *d, struct device_attribute *attr,
198
			    char *buf)
L
Linus Torvalds 已提交
199
{
200
	return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
L
Linus Torvalds 已提交
201
}
202
static DEVICE_ATTR_RO(root_id);
L
Linus Torvalds 已提交
203

204
static ssize_t bridge_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)->bridge_id);
L
Linus Torvalds 已提交
208
}
209
static DEVICE_ATTR_RO(bridge_id);
L
Linus Torvalds 已提交
210

211
static ssize_t root_port_show(struct device *d, struct device_attribute *attr,
212
			      char *buf)
L
Linus Torvalds 已提交
213
{
214
	return sprintf(buf, "%d\n", to_bridge(d)->root_port);
L
Linus Torvalds 已提交
215
}
216
static DEVICE_ATTR_RO(root_port);
L
Linus Torvalds 已提交
217

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

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

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

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

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

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

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

274
static ssize_t group_addr_show(struct device *d,
275
			       struct device_attribute *attr, char *buf)
276
{
277
	struct net_bridge *br = to_bridge(d);
278 279 280 281 282 283
	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]);
}

284
static ssize_t group_addr_store(struct device *d,
285 286
				struct device_attribute *attr,
				const char *buf, size_t len)
287
{
288
	struct net_bridge *br = to_bridge(d);
289
	u8 new_addr[6];
290 291
	int i;

292
	if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
293 294
		return -EPERM;

295
	if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
296 297 298 299
		   &new_addr[0], &new_addr[1], &new_addr[2],
		   &new_addr[3], &new_addr[4], &new_addr[5]) != 6)
		return -EINVAL;

300
	if (!is_link_local_ether_addr(new_addr))
301 302
		return -EINVAL;

303 304 305
	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 */
306 307
		return -EINVAL;

308 309 310
	if (!rtnl_trylock())
		return restart_syscall();

311 312 313 314
	spin_lock_bh(&br->lock);
	for (i = 0; i < 6; i++)
		br->group_addr[i] = new_addr[i];
	spin_unlock_bh(&br->lock);
315 316 317 318 319 320

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

	rtnl_unlock();

321 322 323
	return len;
}

324
static DEVICE_ATTR_RW(group_addr);
325

326 327 328 329 330 331
static int set_flush(struct net_bridge *br, unsigned long val)
{
	br_fdb_flush(br);
	return 0;
}

332
static ssize_t flush_store(struct device *d,
333 334 335
			   struct device_attribute *attr,
			   const char *buf, size_t len)
{
336
	return store_bridge_parm(d, buf, len, set_flush);
337
}
338
static DEVICE_ATTR_WO(flush);
339

340
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
341
static ssize_t multicast_router_show(struct device *d,
342 343 344 345 346 347
				     struct device_attribute *attr, char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->multicast_router);
}

348
static ssize_t multicast_router_store(struct device *d,
349 350 351 352 353
				      struct device_attribute *attr,
				      const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_multicast_set_router);
}
354
static DEVICE_ATTR_RW(multicast_router);
355

356
static ssize_t multicast_snooping_show(struct device *d,
357 358 359 360 361 362 363
				       struct device_attribute *attr,
				       char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", !br->multicast_disabled);
}

364
static ssize_t multicast_snooping_store(struct device *d,
365 366 367 368 369
					struct device_attribute *attr,
					const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_multicast_toggle);
}
370
static DEVICE_ATTR_RW(multicast_snooping);
371

372 373 374
static ssize_t multicast_query_use_ifaddr_show(struct device *d,
					       struct device_attribute *attr,
					       char *buf)
375 376 377 378 379 380 381 382 383 384 385 386
{
	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
387
multicast_query_use_ifaddr_store(struct device *d,
388 389 390 391 392
				 struct device_attribute *attr,
				 const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_query_use_ifaddr);
}
393
static DEVICE_ATTR_RW(multicast_query_use_ifaddr);
394

395
static ssize_t multicast_querier_show(struct device *d,
396 397 398 399 400 401 402
				      struct device_attribute *attr,
				      char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->multicast_querier);
}

403
static ssize_t multicast_querier_store(struct device *d,
404 405 406 407 408
				       struct device_attribute *attr,
				       const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_multicast_set_querier);
}
409
static DEVICE_ATTR_RW(multicast_querier);
410

411
static ssize_t hash_elasticity_show(struct device *d,
412 413 414 415 416 417 418 419 420 421 422 423
				    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;
}

424
static ssize_t hash_elasticity_store(struct device *d,
425 426 427 428 429
				     struct device_attribute *attr,
				     const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_elasticity);
}
430
static DEVICE_ATTR_RW(hash_elasticity);
431

432
static ssize_t hash_max_show(struct device *d, struct device_attribute *attr,
433 434 435 436 437 438
			     char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%u\n", br->hash_max);
}

439
static ssize_t hash_max_store(struct device *d, struct device_attribute *attr,
440 441 442 443
			      const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_multicast_set_hash_max);
}
444
static DEVICE_ATTR_RW(hash_max);
445

446
static ssize_t multicast_last_member_count_show(struct device *d,
447 448 449 450 451 452 453 454 455 456 457 458 459
						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;
}

460
static ssize_t multicast_last_member_count_store(struct device *d,
461 462 463 464 465
						 struct device_attribute *attr,
						 const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_last_member_count);
}
466
static DEVICE_ATTR_RW(multicast_last_member_count);
467

468
static ssize_t multicast_startup_query_count_show(
469 470 471 472 473 474 475 476 477 478 479 480
	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;
}

481
static ssize_t multicast_startup_query_count_store(
482 483 484 485 486
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_startup_query_count);
}
487
static DEVICE_ATTR_RW(multicast_startup_query_count);
488

489
static ssize_t multicast_last_member_interval_show(
490 491 492 493 494 495 496 497 498 499 500 501 502
	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;
}

503
static ssize_t multicast_last_member_interval_store(
504 505 506 507 508
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_last_member_interval);
}
509
static DEVICE_ATTR_RW(multicast_last_member_interval);
510

511
static ssize_t multicast_membership_interval_show(
512 513 514 515 516 517 518 519 520 521 522 523 524
	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;
}

525
static ssize_t multicast_membership_interval_store(
526 527 528 529 530
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_membership_interval);
}
531
static DEVICE_ATTR_RW(multicast_membership_interval);
532

533
static ssize_t multicast_querier_interval_show(struct device *d,
534 535 536 537 538 539 540 541 542 543 544 545 546 547
					       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;
}

548
static ssize_t multicast_querier_interval_store(struct device *d,
549 550 551 552 553
						struct device_attribute *attr,
						const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_querier_interval);
}
554
static DEVICE_ATTR_RW(multicast_querier_interval);
555

556
static ssize_t multicast_query_interval_show(struct device *d,
557 558 559 560 561 562 563 564 565 566 567 568 569 570
					     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;
}

571
static ssize_t multicast_query_interval_store(struct device *d,
572 573 574 575 576
					      struct device_attribute *attr,
					      const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, set_query_interval);
}
577
static DEVICE_ATTR_RW(multicast_query_interval);
578

579
static ssize_t multicast_query_response_interval_show(
580 581 582 583 584 585 586 587 588 589 590 591 592 593
	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;
}

594
static ssize_t multicast_query_response_interval_store(
595 596 597 598 599
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_query_response_interval);
}
600
static DEVICE_ATTR_RW(multicast_query_response_interval);
601

602
static ssize_t multicast_startup_query_interval_show(
603 604 605 606 607 608 609 610 611 612 613 614 615 616
	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;
}

617
static ssize_t multicast_startup_query_interval_store(
618 619 620 621 622
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_startup_query_interval);
}
623
static DEVICE_ATTR_RW(multicast_startup_query_interval);
624
#endif
625
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
626
static ssize_t nf_call_iptables_show(
627 628 629 630 631 632 633 634 635 636 637 638
	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;
}

639
static ssize_t nf_call_iptables_store(
640 641 642 643 644
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_nf_call_iptables);
}
645
static DEVICE_ATTR_RW(nf_call_iptables);
646

647
static ssize_t nf_call_ip6tables_show(
648 649 650 651 652 653 654 655 656 657 658 659
	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;
}

660
static ssize_t nf_call_ip6tables_store(
661 662 663 664 665
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_nf_call_ip6tables);
}
666
static DEVICE_ATTR_RW(nf_call_ip6tables);
667

668
static ssize_t nf_call_arptables_show(
669 670 671 672 673 674 675 676 677 678 679 680
	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;
}

681
static ssize_t nf_call_arptables_store(
682 683 684 685 686
	struct device *d, struct device_attribute *attr, const char *buf,
	size_t len)
{
	return store_bridge_parm(d, buf, len, set_nf_call_arptables);
}
687
static DEVICE_ATTR_RW(nf_call_arptables);
688
#endif
689
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
690
static ssize_t vlan_filtering_show(struct device *d,
691 692 693 694 695 696 697
				   struct device_attribute *attr,
				   char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->vlan_enabled);
}

698
static ssize_t vlan_filtering_store(struct device *d,
699 700 701 702 703
				    struct device_attribute *attr,
				    const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_vlan_filter_toggle);
}
704
static DEVICE_ATTR_RW(vlan_filtering);
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720

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);
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736

static ssize_t default_pvid_show(struct device *d,
				 struct device_attribute *attr,
				 char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->default_pvid);
}

static ssize_t default_pvid_store(struct device *d,
				  struct device_attribute *attr,
				  const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_vlan_set_default_pvid);
}
static DEVICE_ATTR_RW(default_pvid);
737
#endif
738

L
Linus Torvalds 已提交
739
static struct attribute *bridge_attrs[] = {
740 741 742 743 744
	&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,
745
	&dev_attr_group_fwd_mask.attr,
746 747 748 749 750 751 752 753 754 755 756 757
	&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,
758
	&dev_attr_flush.attr,
759 760
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
	&dev_attr_multicast_router.attr,
761
	&dev_attr_multicast_snooping.attr,
762
	&dev_attr_multicast_querier.attr,
763
	&dev_attr_multicast_query_use_ifaddr.attr,
764 765
	&dev_attr_hash_elasticity.attr,
	&dev_attr_hash_max.attr,
766 767 768 769 770 771 772 773
	&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,
774
#endif
775
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
776 777 778
	&dev_attr_nf_call_iptables.attr,
	&dev_attr_nf_call_ip6tables.attr,
	&dev_attr_nf_call_arptables.attr,
779 780 781
#endif
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
	&dev_attr_vlan_filtering.attr,
782
	&dev_attr_vlan_protocol.attr,
783
	&dev_attr_default_pvid.attr,
784
#endif
L
Linus Torvalds 已提交
785 786 787 788 789 790 791 792 793 794 795 796 797 798
	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.
 */
799
static ssize_t brforward_read(struct file *filp, struct kobject *kobj,
800 801
			      struct bin_attribute *bin_attr,
			      char *buf, loff_t off, size_t count)
L
Linus Torvalds 已提交
802
{
803
	struct device *dev = kobj_to_dev(kobj);
804
	struct net_bridge *br = to_bridge(dev);
L
Linus Torvalds 已提交
805 806 807 808 809 810
	int n;

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

811
	n =  br_fdb_fillbuf(br, buf,
L
Linus Torvalds 已提交
812 813 814 815 816
			    count / sizeof(struct __fdb_entry),
			    off / sizeof(struct __fdb_entry));

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

L
Linus Torvalds 已提交
818 819 820 821 822
	return n;
}

static struct bin_attribute bridge_forward = {
	.attr = { .name = SYSFS_BRIDGE_FDB,
823
		  .mode = S_IRUGO, },
L
Linus Torvalds 已提交
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
	.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)
{
840
	struct kobject *brobj = &dev->dev.kobj;
L
Linus Torvalds 已提交
841 842 843 844 845 846
	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",
847
			__func__, dev->name, bridge_group.name);
L
Linus Torvalds 已提交
848 849 850 851 852
		goto out1;
	}

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

858 859
	br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, brobj);
	if (!br->ifobj) {
L
Linus Torvalds 已提交
860
		pr_info("%s: can't add kobject (directory) %s/%s\n",
861
			__func__, dev->name, SYSFS_BRIDGE_PORT_SUBDIR);
L
Linus Torvalds 已提交
862 863 864 865
		goto out3;
	}
	return 0;
 out3:
866
	sysfs_remove_bin_file(&dev->dev.kobj, &bridge_forward);
L
Linus Torvalds 已提交
867
 out2:
868
	sysfs_remove_group(&dev->dev.kobj, &bridge_group);
L
Linus Torvalds 已提交
869 870 871 872 873 874 875
 out1:
	return err;

}

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

879
	kobject_put(br->ifobj);
L
Linus Torvalds 已提交
880 881 882
	sysfs_remove_bin_file(kobj, &bridge_forward);
	sysfs_remove_group(kobj, &bridge_group);
}