1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Spanning tree protocol; generic parts
4 * Linux ethernet bridge
5 *
6 * Authors:
7 * Lennert Buytenhek <buytenh@gnu.org>
8 */
9 #include <linux/kernel.h>
10 #include <linux/rculist.h>
11 #include <net/switchdev.h>
12
13 #include "br_private.h"
14 #include "br_private_stp.h"
15
16 /* since time values in bpdu are in jiffies and then scaled (1/256)
17 * before sending, make sure that is at least one STP tick.
18 */
19 #define MESSAGE_AGE_INCR ((HZ / 256) + 1)
20
21 static const char *const br_port_state_names[] = {
22 [BR_STATE_DISABLED] = "disabled",
23 [BR_STATE_LISTENING] = "listening",
24 [BR_STATE_LEARNING] = "learning",
25 [BR_STATE_FORWARDING] = "forwarding",
26 [BR_STATE_BLOCKING] = "blocking",
27 };
28
br_set_state(struct net_bridge_port * p,unsigned int state)29 void br_set_state(struct net_bridge_port *p, unsigned int state)
30 {
31 struct switchdev_attr attr = {
32 .orig_dev = p->dev,
33 .id = SWITCHDEV_ATTR_ID_PORT_STP_STATE,
34 .flags = SWITCHDEV_F_DEFER,
35 .u.stp_state = state,
36 };
37 int err;
38
39 /* Don't change the state of the ports if they are driven by a different
40 * protocol.
41 */
42 if (test_bit(BR_MRP_AWARE_BIT, &p->flags))
43 return;
44
45 p->state = state;
46 if (br_opt_get(p->br, BROPT_MST_ENABLED)) {
47 err = br_mst_set_state(p, 0, state, NULL);
48 if (err)
49 br_warn(p->br, "error setting MST state on port %u(%s)\n",
50 p->port_no, netdev_name(p->dev));
51 }
52 err = switchdev_port_attr_set(p->dev, &attr, NULL);
53 if (err && err != -EOPNOTSUPP)
54 br_warn(p->br, "error setting offload STP state on port %u(%s)\n",
55 (unsigned int) p->port_no, p->dev->name);
56 else
57 br_info(p->br, "port %u(%s) entered %s state\n",
58 (unsigned int) p->port_no, p->dev->name,
59 br_port_state_names[p->state]);
60
61 if (p->br->stp_enabled == BR_KERNEL_STP) {
62 switch (p->state) {
63 case BR_STATE_BLOCKING:
64 p->stp_xstats.transition_blk++;
65 break;
66 case BR_STATE_FORWARDING:
67 p->stp_xstats.transition_fwd++;
68 break;
69 }
70 }
71 }
72
br_port_get_stp_state(const struct net_device * dev)73 u8 br_port_get_stp_state(const struct net_device *dev)
74 {
75 struct net_bridge_port *p;
76
77 ASSERT_RTNL();
78
79 p = br_port_get_rtnl(dev);
80 if (!p)
81 return BR_STATE_DISABLED;
82
83 return p->state;
84 }
85 EXPORT_SYMBOL_GPL(br_port_get_stp_state);
86
87 /* called under bridge lock */
br_get_port(struct net_bridge * br,u16 port_no)88 struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no)
89 {
90 struct net_bridge_port *p;
91
92 list_for_each_entry_rcu(p, &br->port_list, list,
93 lockdep_is_held(&br->lock)) {
94 if (p->port_no == port_no)
95 return p;
96 }
97
98 return NULL;
99 }
100
101 /* called under bridge lock */
br_should_become_root_port(const struct net_bridge_port * p,u16 root_port)102 static int br_should_become_root_port(const struct net_bridge_port *p,
103 u16 root_port)
104 {
105 u32 p_path_cost, rp_path_cost, p_designated_cost, rp_designated_cost;
106 struct net_bridge_port *rp;
107 struct net_bridge *br;
108 int t;
109
110 br = p->br;
111 if (p->state == BR_STATE_DISABLED ||
112 br_is_designated_port(p))
113 return 0;
114
115 if (memcmp(&br->bridge_id, &p->designated_root, 8) <= 0)
116 return 0;
117
118 if (!root_port)
119 return 1;
120
121 rp = br_get_port(br, root_port);
122
123 t = memcmp(&p->designated_root, &rp->designated_root, 8);
124 if (t < 0)
125 return 1;
126 else if (t > 0)
127 return 0;
128
129 p_path_cost = READ_ONCE(p->path_cost);
130 rp_path_cost = READ_ONCE(rp->path_cost);
131 p_designated_cost = READ_ONCE(p->designated_cost);
132 rp_designated_cost = READ_ONCE(rp->designated_cost);
133
134 if (p_designated_cost + p_path_cost <
135 rp_designated_cost + rp_path_cost)
136 return 1;
137 else if (p_designated_cost + p_path_cost >
138 rp_designated_cost + rp_path_cost)
139 return 0;
140
141 t = memcmp(&p->designated_bridge, &rp->designated_bridge, 8);
142 if (t < 0)
143 return 1;
144 else if (t > 0)
145 return 0;
146
147 if (p->designated_port < rp->designated_port)
148 return 1;
149 else if (p->designated_port > rp->designated_port)
150 return 0;
151
152 if (p->port_id < rp->port_id)
153 return 1;
154
155 return 0;
156 }
157
br_root_port_block(const struct net_bridge * br,struct net_bridge_port * p)158 static void br_root_port_block(const struct net_bridge *br,
159 struct net_bridge_port *p)
160 {
161
162 br_notice(br, "port %u(%s) tried to become root port (blocked)",
163 (unsigned int) p->port_no, p->dev->name);
164
165 br_set_state(p, BR_STATE_LISTENING);
166 br_ifinfo_notify(RTM_NEWLINK, NULL, p);
167
168 if (br->forward_delay > 0)
169 mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay);
170 }
171
172 /* called under bridge lock */
br_root_selection(struct net_bridge * br)173 static void br_root_selection(struct net_bridge *br)
174 {
175 struct net_bridge_port *p;
176 u16 root_port = 0;
177
178 list_for_each_entry(p, &br->port_list, list) {
179 if (!br_should_become_root_port(p, root_port))
180 continue;
181
182 if (test_bit(BR_ROOT_BLOCK_BIT, &p->flags))
183 br_root_port_block(br, p);
184 else
185 root_port = p->port_no;
186 }
187
188 br->root_port = root_port;
189
190 if (!root_port) {
191 br->designated_root = br->bridge_id;
192 br->root_path_cost = 0;
193 } else {
194 p = br_get_port(br, root_port);
195 br->designated_root = p->designated_root;
196 br->root_path_cost = READ_ONCE(p->designated_cost) +
197 READ_ONCE(p->path_cost);
198 }
199 }
200
201 /* called under bridge lock */
br_become_root_bridge(struct net_bridge * br)202 void br_become_root_bridge(struct net_bridge *br)
203 {
204 br->max_age = br->bridge_max_age;
205 br->hello_time = br->bridge_hello_time;
206 br->forward_delay = br->bridge_forward_delay;
207 br_topology_change_detection(br);
208 timer_delete(&br->tcn_timer);
209
210 if (br->dev->flags & IFF_UP) {
211 br_config_bpdu_generation(br);
212 mod_timer(&br->hello_timer, jiffies + br->hello_time);
213 }
214 }
215
216 /* called under bridge lock */
br_transmit_config(struct net_bridge_port * p)217 void br_transmit_config(struct net_bridge_port *p)
218 {
219 struct br_config_bpdu bpdu;
220 struct net_bridge *br;
221
222 if (timer_pending(&p->hold_timer)) {
223 WRITE_ONCE(p->config_pending, 1);
224 return;
225 }
226
227 br = p->br;
228
229 bpdu.topology_change = br->topology_change;
230 bpdu.topology_change_ack = p->topology_change_ack;
231 bpdu.root = br->designated_root;
232 bpdu.root_path_cost = br->root_path_cost;
233 bpdu.bridge_id = br->bridge_id;
234 bpdu.port_id = p->port_id;
235 if (br_is_root_bridge(br))
236 bpdu.message_age = 0;
237 else {
238 struct net_bridge_port *root
239 = br_get_port(br, br->root_port);
240 bpdu.message_age = (jiffies - root->designated_age)
241 + MESSAGE_AGE_INCR;
242 }
243 bpdu.max_age = br->max_age;
244 bpdu.hello_time = br->hello_time;
245 bpdu.forward_delay = br->forward_delay;
246
247 if (bpdu.message_age < br->max_age) {
248 br_send_config_bpdu(p, &bpdu);
249 p->topology_change_ack = 0;
250 WRITE_ONCE(p->config_pending, 0);
251 if (p->br->stp_enabled == BR_KERNEL_STP)
252 mod_timer(&p->hold_timer,
253 round_jiffies(jiffies + BR_HOLD_TIME));
254 }
255 }
256
257 /* called under bridge lock */
br_record_config_information(struct net_bridge_port * p,const struct br_config_bpdu * bpdu)258 static void br_record_config_information(struct net_bridge_port *p,
259 const struct br_config_bpdu *bpdu)
260 {
261 p->designated_root = bpdu->root;
262 WRITE_ONCE(p->designated_cost, bpdu->root_path_cost);
263 p->designated_bridge = bpdu->bridge_id;
264 WRITE_ONCE(p->designated_port, bpdu->port_id);
265 p->designated_age = jiffies - bpdu->message_age;
266
267 mod_timer(&p->message_age_timer, jiffies
268 + (bpdu->max_age - bpdu->message_age));
269 }
270
271 /* called under bridge lock */
br_record_config_timeout_values(struct net_bridge * br,const struct br_config_bpdu * bpdu)272 static void br_record_config_timeout_values(struct net_bridge *br,
273 const struct br_config_bpdu *bpdu)
274 {
275 br->max_age = bpdu->max_age;
276 br->hello_time = bpdu->hello_time;
277 br->forward_delay = bpdu->forward_delay;
278 __br_set_topology_change(br, bpdu->topology_change);
279 }
280
281 /* called under bridge lock */
br_transmit_tcn(struct net_bridge * br)282 void br_transmit_tcn(struct net_bridge *br)
283 {
284 struct net_bridge_port *p;
285
286 p = br_get_port(br, br->root_port);
287 if (p)
288 br_send_tcn_bpdu(p);
289 else
290 br_notice(br, "root port %u not found for topology notice\n",
291 br->root_port);
292 }
293
294 /* called under bridge lock */
br_should_become_designated_port(const struct net_bridge_port * p)295 static int br_should_become_designated_port(const struct net_bridge_port *p)
296 {
297 struct net_bridge *br;
298 u32 p_designated_cost;
299 int t;
300
301 br = p->br;
302 if (br_is_designated_port(p))
303 return 1;
304
305 if (memcmp(&p->designated_root, &br->designated_root, 8))
306 return 1;
307
308 p_designated_cost = READ_ONCE(p->designated_cost);
309 if (br->root_path_cost < p_designated_cost)
310 return 1;
311 else if (br->root_path_cost > p_designated_cost)
312 return 0;
313
314 t = memcmp(&br->bridge_id, &p->designated_bridge, 8);
315 if (t < 0)
316 return 1;
317 else if (t > 0)
318 return 0;
319
320 if (p->port_id < p->designated_port)
321 return 1;
322
323 return 0;
324 }
325
326 /* called under bridge lock */
br_designated_port_selection(struct net_bridge * br)327 static void br_designated_port_selection(struct net_bridge *br)
328 {
329 struct net_bridge_port *p;
330
331 list_for_each_entry(p, &br->port_list, list) {
332 if (p->state != BR_STATE_DISABLED &&
333 br_should_become_designated_port(p))
334 br_become_designated_port(p);
335
336 }
337 }
338
339 /* called under bridge lock */
br_supersedes_port_info(const struct net_bridge_port * p,const struct br_config_bpdu * bpdu)340 static int br_supersedes_port_info(const struct net_bridge_port *p,
341 const struct br_config_bpdu *bpdu)
342 {
343 u32 p_designated_cost;
344 int t;
345
346 t = memcmp(&bpdu->root, &p->designated_root, 8);
347 if (t < 0)
348 return 1;
349 else if (t > 0)
350 return 0;
351
352 p_designated_cost = READ_ONCE(p->designated_cost);
353 if (bpdu->root_path_cost < p_designated_cost)
354 return 1;
355 else if (bpdu->root_path_cost > p_designated_cost)
356 return 0;
357
358 t = memcmp(&bpdu->bridge_id, &p->designated_bridge, 8);
359 if (t < 0)
360 return 1;
361 else if (t > 0)
362 return 0;
363
364 if (memcmp(&bpdu->bridge_id, &p->br->bridge_id, 8))
365 return 1;
366
367 if (bpdu->port_id <= p->designated_port)
368 return 1;
369
370 return 0;
371 }
372
373 /* called under bridge lock */
br_topology_change_acknowledged(struct net_bridge * br)374 static void br_topology_change_acknowledged(struct net_bridge *br)
375 {
376 br->topology_change_detected = 0;
377 timer_delete(&br->tcn_timer);
378 }
379
380 /* called under bridge lock */
br_topology_change_detection(struct net_bridge * br)381 void br_topology_change_detection(struct net_bridge *br)
382 {
383 int isroot = br_is_root_bridge(br);
384
385 if (br->stp_enabled != BR_KERNEL_STP ||
386 !(br->dev->flags & IFF_UP))
387 return;
388
389 br_info(br, "topology change detected, %s\n",
390 isroot ? "propagating" : "sending tcn bpdu");
391
392 if (isroot) {
393 __br_set_topology_change(br, 1);
394 mod_timer(&br->topology_change_timer, jiffies
395 + br->bridge_forward_delay + br->bridge_max_age);
396 } else if (!br->topology_change_detected) {
397 br_transmit_tcn(br);
398 mod_timer(&br->tcn_timer, jiffies + br->bridge_hello_time);
399 }
400
401 br->topology_change_detected = 1;
402 }
403
404 /* called under bridge lock */
br_config_bpdu_generation(struct net_bridge * br)405 void br_config_bpdu_generation(struct net_bridge *br)
406 {
407 struct net_bridge_port *p;
408
409 list_for_each_entry(p, &br->port_list, list) {
410 if (p->state != BR_STATE_DISABLED &&
411 br_is_designated_port(p))
412 br_transmit_config(p);
413 }
414 }
415
416 /* called under bridge lock */
br_reply(struct net_bridge_port * p)417 static void br_reply(struct net_bridge_port *p)
418 {
419 br_transmit_config(p);
420 }
421
422 /* called under bridge lock */
br_configuration_update(struct net_bridge * br)423 void br_configuration_update(struct net_bridge *br)
424 {
425 br_root_selection(br);
426 br_designated_port_selection(br);
427 }
428
429 /* called under bridge lock */
br_become_designated_port(struct net_bridge_port * p)430 void br_become_designated_port(struct net_bridge_port *p)
431 {
432 struct net_bridge *br;
433
434 br = p->br;
435 p->designated_root = br->designated_root;
436 WRITE_ONCE(p->designated_cost, br->root_path_cost);
437 p->designated_bridge = br->bridge_id;
438 WRITE_ONCE(p->designated_port, p->port_id);
439 }
440
441
442 /* called under bridge lock */
br_make_blocking(struct net_bridge_port * p)443 static void br_make_blocking(struct net_bridge_port *p)
444 {
445 if (p->state != BR_STATE_DISABLED &&
446 p->state != BR_STATE_BLOCKING) {
447 if (p->state == BR_STATE_FORWARDING ||
448 p->state == BR_STATE_LEARNING)
449 br_topology_change_detection(p->br);
450
451 br_set_state(p, BR_STATE_BLOCKING);
452 br_ifinfo_notify(RTM_NEWLINK, NULL, p);
453
454 timer_delete(&p->forward_delay_timer);
455 }
456 }
457
458 /* called under bridge lock */
br_make_forwarding(struct net_bridge_port * p)459 static void br_make_forwarding(struct net_bridge_port *p)
460 {
461 struct net_bridge *br = p->br;
462
463 if (p->state != BR_STATE_BLOCKING)
464 return;
465
466 if (br->stp_enabled == BR_NO_STP || br->forward_delay == 0) {
467 br_set_state(p, BR_STATE_FORWARDING);
468 br_topology_change_detection(br);
469 timer_delete(&p->forward_delay_timer);
470 } else if (br->stp_enabled == BR_KERNEL_STP)
471 br_set_state(p, BR_STATE_LISTENING);
472 else
473 br_set_state(p, BR_STATE_LEARNING);
474
475 br_ifinfo_notify(RTM_NEWLINK, NULL, p);
476
477 if (br->forward_delay != 0)
478 mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay);
479 }
480
481 /* called under bridge lock */
br_port_state_selection(struct net_bridge * br)482 void br_port_state_selection(struct net_bridge *br)
483 {
484 struct net_bridge_port *p;
485 unsigned int liveports = 0;
486
487 list_for_each_entry(p, &br->port_list, list) {
488 if (p->state == BR_STATE_DISABLED)
489 continue;
490
491 /* Don't change port states if userspace is handling STP */
492 if (br->stp_enabled != BR_USER_STP) {
493 if (p->port_no == br->root_port) {
494 WRITE_ONCE(p->config_pending, 0);
495 p->topology_change_ack = 0;
496 br_make_forwarding(p);
497 } else if (br_is_designated_port(p)) {
498 timer_delete(&p->message_age_timer);
499 br_make_forwarding(p);
500 } else {
501 WRITE_ONCE(p->config_pending, 0);
502 p->topology_change_ack = 0;
503 br_make_blocking(p);
504 }
505 }
506
507 if (p->state != BR_STATE_BLOCKING)
508 br_multicast_enable_port(p);
509 /* Multicast is not disabled for the port when it goes in
510 * blocking state because the timers will expire and stop by
511 * themselves without sending more queries.
512 */
513 if (p->state == BR_STATE_FORWARDING)
514 ++liveports;
515 }
516
517 if (liveports == 0)
518 netif_carrier_off(br->dev);
519 else
520 netif_carrier_on(br->dev);
521 }
522
523 /* called under bridge lock */
br_topology_change_acknowledge(struct net_bridge_port * p)524 static void br_topology_change_acknowledge(struct net_bridge_port *p)
525 {
526 p->topology_change_ack = 1;
527 br_transmit_config(p);
528 }
529
530 /* called under bridge lock */
br_received_config_bpdu(struct net_bridge_port * p,const struct br_config_bpdu * bpdu)531 void br_received_config_bpdu(struct net_bridge_port *p,
532 const struct br_config_bpdu *bpdu)
533 {
534 struct net_bridge *br;
535 int was_root;
536
537 p->stp_xstats.rx_bpdu++;
538
539 br = p->br;
540 was_root = br_is_root_bridge(br);
541
542 if (br_supersedes_port_info(p, bpdu)) {
543 br_record_config_information(p, bpdu);
544 br_configuration_update(br);
545 br_port_state_selection(br);
546
547 if (!br_is_root_bridge(br) && was_root) {
548 timer_delete(&br->hello_timer);
549 if (br->topology_change_detected) {
550 timer_delete(&br->topology_change_timer);
551 br_transmit_tcn(br);
552
553 mod_timer(&br->tcn_timer,
554 jiffies + br->bridge_hello_time);
555 }
556 }
557
558 if (p->port_no == br->root_port) {
559 br_record_config_timeout_values(br, bpdu);
560 br_config_bpdu_generation(br);
561 if (bpdu->topology_change_ack)
562 br_topology_change_acknowledged(br);
563 }
564 } else if (br_is_designated_port(p)) {
565 br_reply(p);
566 }
567 }
568
569 /* called under bridge lock */
br_received_tcn_bpdu(struct net_bridge_port * p)570 void br_received_tcn_bpdu(struct net_bridge_port *p)
571 {
572 p->stp_xstats.rx_tcn++;
573
574 if (br_is_designated_port(p)) {
575 br_info(p->br, "port %u(%s) received tcn bpdu\n",
576 (unsigned int) p->port_no, p->dev->name);
577
578 br_topology_change_detection(p->br);
579 br_topology_change_acknowledge(p);
580 }
581 }
582
583 /* Change bridge STP parameter */
br_set_hello_time(struct net_bridge * br,unsigned long val)584 int br_set_hello_time(struct net_bridge *br, unsigned long val)
585 {
586 unsigned long t = clock_t_to_jiffies(val);
587
588 if (t < BR_MIN_HELLO_TIME || t > BR_MAX_HELLO_TIME)
589 return -ERANGE;
590
591 spin_lock_bh(&br->lock);
592 br->bridge_hello_time = t;
593 if (br_is_root_bridge(br))
594 br->hello_time = br->bridge_hello_time;
595 spin_unlock_bh(&br->lock);
596 return 0;
597 }
598
br_set_max_age(struct net_bridge * br,unsigned long val)599 int br_set_max_age(struct net_bridge *br, unsigned long val)
600 {
601 unsigned long t = clock_t_to_jiffies(val);
602
603 if (t < BR_MIN_MAX_AGE || t > BR_MAX_MAX_AGE)
604 return -ERANGE;
605
606 spin_lock_bh(&br->lock);
607 br->bridge_max_age = t;
608 if (br_is_root_bridge(br))
609 br->max_age = br->bridge_max_age;
610 spin_unlock_bh(&br->lock);
611 return 0;
612
613 }
614
615 /* called under bridge lock */
__set_ageing_time(struct net_device * dev,unsigned long t)616 int __set_ageing_time(struct net_device *dev, unsigned long t)
617 {
618 struct switchdev_attr attr = {
619 .orig_dev = dev,
620 .id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
621 .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP | SWITCHDEV_F_DEFER,
622 .u.ageing_time = jiffies_to_clock_t(t),
623 };
624 int err;
625
626 err = switchdev_port_attr_set(dev, &attr, NULL);
627 if (err && err != -EOPNOTSUPP)
628 return err;
629
630 return 0;
631 }
632
633 /* Set time interval that dynamic forwarding entries live
634 * For pure software bridge, allow values outside the 802.1
635 * standard specification for special cases:
636 * 0 - entry never ages (all permanent)
637 * 1 - entry disappears (no persistence)
638 *
639 * Offloaded switch entries maybe more restrictive
640 */
br_set_ageing_time(struct net_bridge * br,clock_t ageing_time)641 int br_set_ageing_time(struct net_bridge *br, clock_t ageing_time)
642 {
643 unsigned long t = clock_t_to_jiffies(ageing_time);
644 int err;
645
646 err = __set_ageing_time(br->dev, t);
647 if (err)
648 return err;
649
650 spin_lock_bh(&br->lock);
651 br->bridge_ageing_time = t;
652 br->ageing_time = t;
653 spin_unlock_bh(&br->lock);
654
655 mod_delayed_work(system_long_wq, &br->gc_work, 0);
656
657 return 0;
658 }
659
br_get_ageing_time(const struct net_device * br_dev)660 clock_t br_get_ageing_time(const struct net_device *br_dev)
661 {
662 const struct net_bridge *br;
663
664 if (!netif_is_bridge_master(br_dev))
665 return 0;
666
667 br = netdev_priv(br_dev);
668
669 return jiffies_to_clock_t(br->ageing_time);
670 }
671 EXPORT_SYMBOL_GPL(br_get_ageing_time);
672
673 /* called under bridge lock */
__br_set_topology_change(struct net_bridge * br,unsigned char val)674 void __br_set_topology_change(struct net_bridge *br, unsigned char val)
675 {
676 unsigned long t;
677 int err;
678
679 if (br->stp_enabled == BR_KERNEL_STP && br->topology_change != val) {
680 /* On topology change, set the bridge ageing time to twice the
681 * forward delay. Otherwise, restore its default ageing time.
682 */
683
684 if (val) {
685 t = 2 * br->forward_delay;
686 br_debug(br, "decreasing ageing time to %lu\n", t);
687 } else {
688 t = br->bridge_ageing_time;
689 br_debug(br, "restoring ageing time to %lu\n", t);
690 }
691
692 err = __set_ageing_time(br->dev, t);
693 if (err)
694 br_warn(br, "error offloading ageing time\n");
695 else
696 br->ageing_time = t;
697 }
698
699 br->topology_change = val;
700 }
701
__br_set_forward_delay(struct net_bridge * br,unsigned long t)702 void __br_set_forward_delay(struct net_bridge *br, unsigned long t)
703 {
704 br->bridge_forward_delay = t;
705 if (br_is_root_bridge(br))
706 br->forward_delay = br->bridge_forward_delay;
707 }
708
br_set_forward_delay(struct net_bridge * br,unsigned long val)709 int br_set_forward_delay(struct net_bridge *br, unsigned long val)
710 {
711 unsigned long t = clock_t_to_jiffies(val);
712 int err = -ERANGE;
713
714 spin_lock_bh(&br->lock);
715 if (br->stp_enabled != BR_NO_STP &&
716 (t < BR_MIN_FORWARD_DELAY || t > BR_MAX_FORWARD_DELAY))
717 goto unlock;
718
719 __br_set_forward_delay(br, t);
720 err = 0;
721
722 unlock:
723 spin_unlock_bh(&br->lock);
724 return err;
725 }
726