This source file includes following definitions.
- transmit_config
- root_bridge
- supersedes_port_info
- record_config_information
- record_config_timeout_values
- config_bpdu_generation
- designated_port
- reply
- transmit_tcn
- configuration_update
- root_selection
- designated_port_selection
- become_designated_port
- port_state_selection
- make_forwarding
- topology_change_detection
- topology_change_acknowledged
- acknowledge_topology_change
- make_blocking
- set_port_state
- received_config_bpdu
- received_tcn_bpdu
- hello_timer_expiry
- message_age_timer_expiry
- forward_delay_timer_expiry
- designated_for_some_port
- tcn_timer_expiry
- topology_change_timer_expiry
- hold_timer_expiry
- br_init
- br_init_port
- enable_port
- disable_port
- set_bridge_priority
- set_port_priority
- set_path_cost
- br_tick
- start_hello_timer
- stop_hello_timer
- hello_timer_expired
- start_tcn_timer
- stop_tcn_timer
- tcn_timer_expired
- start_topology_change_timer
- stop_topology_change_timer
- topology_change_timer_expired
- start_message_age_timer
- stop_message_age_timer
- message_age_timer_expired
- start_forward_delay_timer
- stop_forward_delay_timer
- forward_delay_timer_expired
- start_hold_timer
- stop_hold_timer
- hold_timer_expired
- send_config_bpdu
- send_tcn_bpdu
- br_device_event
- br_receive_frame
- br_tx_frame
- br_learn
- br_drop
- br_forward
- br_flood
- find_port
- br_port_cost
- br_bpdu
- br_ioctl
- br_cmp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <linux/errno.h>
25 #include <linux/types.h>
26 #include <linux/socket.h>
27 #include <linux/in.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/timer.h>
31 #include <linux/string.h>
32 #include <linux/net.h>
33 #include <linux/inet.h>
34 #include <linux/netdevice.h>
35 #include <linux/string.h>
36 #include <linux/skbuff.h>
37 #include <linux/if_arp.h>
38 #include <asm/segment.h>
39 #include <asm/system.h>
40 #include <net/br.h>
41
42 static int br_device_event(struct notifier_block *dnot, unsigned long event, void *ptr);
43 static void br_tick(unsigned long arg);
44 int br_forward(struct sk_buff *skb, int port);
45 int br_port_cost(struct device *dev);
46 void br_bpdu(struct sk_buff *skb);
47 int br_tx_frame(struct sk_buff *skb);
48 int br_cmp(unsigned int *a, unsigned int *b);
49
50 unsigned char bridge_ula[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
51
52 Bridge_data bridge_info;
53 Port_data port_info[All_ports];
54 Config_bpdu config_bpdu[All_ports];
55 Tcn_bpdu tcn_bpdu[All_ports];
56 Timer hello_timer;
57 Timer tcn_timer;
58 Timer topology_change_timer;
59 Timer message_age_timer[All_ports];
60 Timer forward_delay_timer[All_ports];
61 Timer hold_timer[All_ports];
62
63
64 unsigned int fdb_aging_time = FDB_TIMEOUT;
65
66 struct br_stat br_stats;
67
68 static struct timer_list tl;
69
70
71
72
73
74
75 static struct notifier_block br_dev_notifier={
76 br_device_event,
77 NULL,
78 0
79 };
80
81
82
83
84
85
86
87
88
89
90
91 void
92 transmit_config(int port_no)
93 {
94 if (hold_timer[port_no].active) {
95 port_info[port_no].config_pending = TRUE;
96 } else {
97 config_bpdu[port_no].type = BPDU_TYPE_CONFIG;
98 config_bpdu[port_no].root_id = bridge_info.designated_root;
99
100 config_bpdu[port_no].root_path_cost = bridge_info.root_path_cost;
101
102 config_bpdu[port_no].bridge_id = bridge_info.bridge_id;
103
104 config_bpdu[port_no].port_id = port_info[port_no].port_id;
105
106
107
108 if (root_bridge()) {
109 config_bpdu[port_no].message_age = Zero;
110 } else {
111 config_bpdu[port_no].message_age
112 = message_age_timer[bridge_info.root_port].value
113 + Message_age_increment;
114 }
115
116 config_bpdu[port_no].max_age = bridge_info.max_age;
117 config_bpdu[port_no].hello_time = bridge_info.hello_time;
118 config_bpdu[port_no].forward_delay = bridge_info.forward_delay;
119 config_bpdu[port_no].flags = 0;
120 config_bpdu[port_no].flags |=
121 port_info[port_no].top_change_ack ? TOPOLOGY_CHANGE_ACK : 0;
122
123 port_info[port_no].top_change_ack = 0;
124
125 config_bpdu[port_no].flags |=
126 bridge_info.top_change ? TOPOLOGY_CHANGE : 0;
127
128
129 send_config_bpdu(port_no, &config_bpdu[port_no]);
130 port_info[port_no].config_pending = FALSE;
131 start_hold_timer(port_no);
132 }
133 }
134
135 int
136 root_bridge(void)
137 {
138 return (br_cmp(bridge_info.designated_root.BRIDGE_ID,
139 bridge_info.bridge_id.BRIDGE_ID)?FALSE:TRUE);
140 }
141
142 int
143 supersedes_port_info(int port_no, Config_bpdu *config)
144 {
145 return (
146 (br_cmp(config->root_id.BRIDGE_ID,
147 port_info[port_no].designated_root.BRIDGE_ID) < 0)
148 ||
149 ((br_cmp(config->root_id.BRIDGE_ID,
150 port_info[port_no].designated_root.BRIDGE_ID) == 0
151 )
152 &&
153 ((config->root_path_cost
154 < port_info[port_no].designated_cost
155 )
156 ||
157 ((config->root_path_cost
158 == port_info[port_no].designated_cost
159 )
160 &&
161 ((br_cmp(config->bridge_id.BRIDGE_ID,
162 port_info[port_no].designated_bridge.BRIDGE_ID) < 0
163 )
164 ||
165 ((br_cmp(config->bridge_id.BRIDGE_ID,
166 port_info[port_no].designated_bridge.BRIDGE_ID) == 0
167 )
168 &&
169 ((br_cmp(config->bridge_id.BRIDGE_ID,
170 bridge_info.bridge_id.BRIDGE_ID) != 0
171 )
172 ||
173 (config->port_id <=
174 port_info[port_no].designated_port
175 )
176 ))))))
177 );
178 }
179
180 void
181 record_config_information(int port_no, Config_bpdu *config)
182 {
183 port_info[port_no].designated_root = config->root_id;
184 port_info[port_no].designated_cost = config->root_path_cost;
185 port_info[port_no].designated_bridge = config->bridge_id;
186 port_info[port_no].designated_port = config->port_id;
187 start_message_age_timer(port_no, config->message_age);
188 }
189
190 void
191 record_config_timeout_values(Config_bpdu *config)
192 {
193 bridge_info.max_age = config->max_age;
194 bridge_info.hello_time = config->hello_time;
195 bridge_info.forward_delay = config->forward_delay;
196 if (config->flags & TOPOLOGY_CHANGE)
197 bridge_info.top_change = 1;
198 }
199
200 void
201 config_bpdu_generation(void)
202 {
203 int port_no;
204 for (port_no = One; port_no <= No_of_ports; port_no++) {
205 if (designated_port(port_no)
206 &&
207 (port_info[port_no].state != Disabled)
208 ) {
209 transmit_config(port_no);
210 }
211 }
212 }
213
214 int
215 designated_port(int port_no)
216 {
217 return ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
218 bridge_info.bridge_id.BRIDGE_ID) == 0
219 )
220 &&
221 (port_info[port_no].designated_port
222 == port_info[port_no].port_id
223 )
224 );
225 }
226
227 void
228 reply(int port_no)
229 {
230 transmit_config(port_no);
231 }
232
233 void
234 transmit_tcn(void)
235 {
236 int port_no;
237
238 port_no = bridge_info.root_port;
239 tcn_bpdu[port_no].type = BPDU_TYPE_TOPO_CHANGE;
240 send_tcn_bpdu(port_no, &tcn_bpdu[bridge_info.root_port]);
241 }
242
243 void
244 configuration_update(void)
245 {
246 root_selection();
247
248 designated_port_selection();
249
250 }
251
252 void
253 root_selection(void)
254 {
255 int root_port;
256 int port_no;
257 root_port = No_port;
258 for (port_no = One; port_no <= No_of_ports; port_no++) {
259 if (((!designated_port(port_no))
260 &&
261 (port_info[port_no].state != Disabled)
262 &&
263 (br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
264 bridge_info.bridge_id.BRIDGE_ID) < 0)
265 )
266 &&
267 ((root_port == No_port)
268 ||
269 (br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
270 port_info[root_port].designated_root.BRIDGE_ID) < 0
271 )
272 ||
273 ((br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
274 port_info[root_port].designated_root.BRIDGE_ID) == 0
275 )
276 &&
277 (((port_info[port_no].designated_cost
278 + port_info[port_no].path_cost
279 )
280 ==
281 (port_info[root_port].designated_cost
282 + port_info[root_port].path_cost
283 )
284 )
285 ||
286 (((port_info[port_no].designated_cost
287 + port_info[port_no].path_cost
288 )
289 ==
290 (port_info[root_port].designated_cost
291 + port_info[root_port].path_cost
292 )
293 )
294 &&
295 ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
296 port_info[root_port].designated_bridge.BRIDGE_ID) < 0
297 )
298 ||
299 ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
300 port_info[root_port].designated_bridge.BRIDGE_ID) == 0
301 )
302 &&
303 ((port_info[port_no].designated_port
304 < port_info[root_port].designated_port
305 )
306 ||
307 ((port_info[port_no].designated_port
308 = port_info[root_port].designated_port
309 )
310 &&
311 (port_info[port_no].port_id
312 < port_info[root_port].port_id
313 )
314 ))))))))) {
315 root_port = port_no;
316 }
317 }
318 bridge_info.root_port = root_port;
319
320 if (root_port == No_port) {
321 bridge_info.designated_root = bridge_info.bridge_id;
322
323 bridge_info.root_path_cost = Zero;
324 } else {
325 bridge_info.designated_root = port_info[root_port].designated_root;
326
327 bridge_info.root_path_cost = (port_info[root_port].designated_cost
328 + port_info[root_port].path_cost
329 );
330 }
331 }
332
333 void
334 designated_port_selection(void)
335 {
336 int port_no;
337
338 for (port_no = One; port_no <= No_of_ports; port_no++) {
339 if (designated_port(port_no)
340 ||
341 (
342 br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
343 bridge_info.designated_root.BRIDGE_ID) != 0
344 )
345 ||
346 (bridge_info.root_path_cost
347 < port_info[port_no].designated_cost
348 )
349 ||
350 ((bridge_info.root_path_cost
351 == port_info[port_no].designated_cost
352 )
353 &&
354 ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
355 port_info[port_no].designated_bridge.BRIDGE_ID) < 0
356 )
357 ||
358 ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
359 port_info[port_no].designated_bridge.BRIDGE_ID) == 0
360 )
361 &&
362 (port_info[port_no].port_id
363 <= port_info[port_no].designated_port
364 )
365 )))) {
366 become_designated_port(port_no);
367 }
368 }
369 }
370
371 void
372 become_designated_port(int port_no)
373 {
374
375
376 port_info[port_no].designated_root = bridge_info.designated_root;
377
378 port_info[port_no].designated_cost = bridge_info.root_path_cost;
379
380 port_info[port_no].designated_bridge = bridge_info.bridge_id;
381
382 port_info[port_no].designated_port = port_info[port_no].port_id;
383 }
384
385 void
386 port_state_selection(void)
387 {
388 int port_no;
389 for (port_no = One; port_no <= No_of_ports; port_no++) {
390 if (port_no == bridge_info.root_port) {
391 port_info[port_no].config_pending = FALSE;
392 port_info[port_no].top_change_ack = 0;
393 make_forwarding(port_no);
394 } else if (designated_port(port_no)) {
395 stop_message_age_timer(port_no);
396 make_forwarding(port_no);
397 } else {
398 port_info[port_no].config_pending = FALSE;
399 port_info[port_no].top_change_ack = 0;
400 make_blocking(port_no);
401 }
402 }
403
404 }
405
406 void
407 make_forwarding(int port_no)
408 {
409 if (port_info[port_no].state == Blocking) {
410 set_port_state(port_no, Listening);
411 start_forward_delay_timer(port_no);
412 }
413 }
414
415 void
416 topology_change_detection(void)
417 {
418 if (root_bridge()) {
419 bridge_info.top_change = 1;
420 start_topology_change_timer();
421 } else if (!(bridge_info.top_change_detected)) {
422 transmit_tcn();
423 start_tcn_timer();
424 }
425 bridge_info.top_change = 1;
426 }
427
428 void
429 topology_change_acknowledged(void)
430 {
431 bridge_info.top_change_detected = 0;
432 stop_tcn_timer();
433 }
434
435 void
436 acknowledge_topology_change(int port_no)
437 {
438 port_info[port_no].top_change_ack = 1;
439 transmit_config(port_no);
440 }
441
442 void
443 make_blocking(int port_no)
444 {
445
446 if ((port_info[port_no].state != Disabled)
447 &&
448 (port_info[port_no].state != Blocking)
449
450 ) {
451 if ((port_info[port_no].state == Forwarding)
452 ||
453 (port_info[port_no].state == Learning)
454 ) {
455 topology_change_detection();
456
457 }
458 set_port_state(port_no, Blocking);
459 stop_forward_delay_timer(port_no);
460 }
461 }
462
463 void
464 set_port_state(int port_no, int state)
465 {
466 port_info[port_no].state = state;
467 }
468
469 void
470 received_config_bpdu(int port_no, Config_bpdu *config)
471 {
472 int root;
473
474 root = root_bridge();
475 if (port_info[port_no].state != Disabled) {
476 if (supersedes_port_info(port_no, config)) {
477
478 record_config_information(port_no, config);
479
480 configuration_update();
481
482 port_state_selection();
483
484 if ((!root_bridge()) && root) {
485 stop_hello_timer();
486 if (bridge_info.top_change_detected) {
487 stop_topology_change_timer();
488 transmit_tcn();
489 start_tcn_timer();
490 }
491 }
492 if (port_no == bridge_info.root_port) {
493 record_config_timeout_values(config);
494
495 config_bpdu_generation();
496 if (config->flags & TOPOLOGY_CHANGE_ACK) {
497 topology_change_acknowledged();
498 }
499 }
500 } else if (designated_port(port_no)) {
501 reply(port_no);
502
503 }
504 }
505 }
506
507 void
508 received_tcn_bpdu(int port_no, Tcn_bpdu *tcn)
509 {
510 if (port_info[port_no].state != Disabled) {
511 if (designated_port(port_no)) {
512 topology_change_detection();
513
514 acknowledge_topology_change(port_no);
515 }
516 }
517 }
518
519 void
520 hello_timer_expiry(void)
521 {
522 config_bpdu_generation();
523 start_hello_timer();
524 }
525
526 void
527 message_age_timer_expiry(int port_no)
528 {
529 int root;
530 root = root_bridge();
531
532 become_designated_port(port_no);
533
534 configuration_update();
535
536 port_state_selection();
537
538 if ((root_bridge()) && (!root)) {
539
540 bridge_info.max_age = bridge_info.bridge_max_age;
541 bridge_info.hello_time = bridge_info.bridge_hello_time;
542 bridge_info.forward_delay = bridge_info.bridge_forward_delay;
543 topology_change_detection();
544
545 stop_tcn_timer();
546 config_bpdu_generation();
547
548 start_hello_timer();
549 }
550 }
551
552 void
553 forward_delay_timer_expiry(int port_no)
554 {
555 if (port_info[port_no].state == Listening) {
556 set_port_state(port_no, Learning);
557 start_forward_delay_timer(port_no);
558 } else if (port_info[port_no].state == Learning) {
559 set_port_state(port_no, Forwarding);
560 if (designated_for_some_port()) {
561 topology_change_detection();
562
563 }
564 }
565 }
566
567 int
568 designated_for_some_port(void)
569 {
570 int port_no;
571
572
573 for (port_no = One; port_no <= No_of_ports; port_no++) {
574 if ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
575 bridge_info.bridge_id.BRIDGE_ID) == 0)
576 ) {
577 return (TRUE);
578 }
579 }
580 return (FALSE);
581 }
582
583 void
584 tcn_timer_expiry(void)
585 {
586 transmit_tcn();
587 start_tcn_timer();
588 }
589
590 void
591 topology_change_timer_expiry(void)
592 {
593 bridge_info.top_change_detected = 0;
594 bridge_info.top_change = 0;
595
596 }
597
598 void
599 hold_timer_expiry(int port_no)
600 {
601 if (port_info[port_no].config_pending) {
602 transmit_config(port_no);
603 }
604 }
605
606 void
607 br_init(void)
608 {
609 int port_no;
610
611 bridge_info.designated_root = bridge_info.bridge_id;
612 bridge_info.root_path_cost = Zero;
613 bridge_info.root_port = No_port;
614
615 bridge_info.bridge_max_age = BRIDGE_MAX_AGE;
616 bridge_info.bridge_hello_time = BRIDGE_HELLO_TIME;
617 bridge_info.bridge_forward_delay = BRIDGE_FORWARD_DELAY;
618 bridge_info.hold_time = HOLD_TIME;
619
620 bridge_info.max_age = bridge_info.bridge_max_age;
621 bridge_info.hello_time = bridge_info.bridge_hello_time;
622 bridge_info.forward_delay = bridge_info.bridge_forward_delay;
623
624 bridge_info.top_change_detected = 0;
625 bridge_info.top_change = 0;
626 stop_tcn_timer();
627 stop_topology_change_timer();
628 for (port_no = One; port_no <= No_of_ports; port_no++) {
629 br_init_port(port_no);
630 disable_port(port_no);
631 }
632 port_state_selection();
633 config_bpdu_generation();
634
635
636 tl.expires = HZ;
637 tl.function = br_tick;
638 add_timer(&tl);
639
640 register_netdevice_notifier(&br_dev_notifier);
641 br_stats.flags = BR_UP | BR_DEBUG;
642 start_hello_timer();
643 }
644
645 void
646 br_init_port(int port_no)
647 {
648 become_designated_port(port_no);
649 set_port_state(port_no, Blocking);
650 port_info[port_no].top_change_ack = 0;
651 port_info[port_no].config_pending = FALSE;
652 stop_message_age_timer(port_no);
653 stop_forward_delay_timer(port_no);
654 stop_hold_timer(port_no);
655 }
656
657 void
658 enable_port(int port_no)
659 {
660 br_init_port(port_no);
661 port_state_selection();
662 }
663
664 void
665 disable_port(int port_no)
666 {
667 int root;
668
669 root = root_bridge();
670 become_designated_port(port_no);
671 set_port_state(port_no, Disabled);
672 port_info[port_no].top_change_ack = 0;
673 port_info[port_no].config_pending = FALSE;
674 stop_message_age_timer(port_no);
675 stop_forward_delay_timer(port_no);
676 configuration_update();
677 port_state_selection();
678 if ((root_bridge()) && (!root)) {
679 bridge_info.max_age = bridge_info.bridge_max_age;
680 bridge_info.hello_time = bridge_info.bridge_hello_time;
681 bridge_info.forward_delay = bridge_info.bridge_forward_delay;
682 topology_change_detection();
683 stop_tcn_timer();
684 config_bpdu_generation();
685 start_hello_timer();
686 }
687 }
688
689
690 void
691 set_bridge_priority(bridge_id_t *new_bridge_id)
692 {
693
694 int root;
695 int port_no;
696 root = root_bridge();
697 for (port_no = One; port_no <= No_of_ports; port_no++) {
698 if (designated_port(port_no)) {
699 port_info[port_no].designated_bridge = *new_bridge_id;
700 }
701 }
702
703 bridge_info.bridge_id = *new_bridge_id;
704 configuration_update();
705 port_state_selection();
706 if ((root_bridge()) && (!root)) {
707 bridge_info.max_age = bridge_info.bridge_max_age;
708 bridge_info.hello_time = bridge_info.bridge_hello_time;
709 bridge_info.forward_delay = bridge_info.bridge_forward_delay;
710 topology_change_detection();
711 stop_tcn_timer();
712 config_bpdu_generation(),
713 start_hello_timer();
714 }
715 }
716
717 void
718 set_port_priority(int port_no, unsigned short new_port_id)
719 {
720 if (designated_port(port_no)) {
721 port_info[port_no].designated_port = new_port_id;
722 }
723 port_info[port_no].port_id = new_port_id;
724 if ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
725 port_info[port_no].designated_bridge.BRIDGE_ID) == 0
726 )
727 &&
728 (port_info[port_no].port_id
729 < port_info[port_no].designated_port
730
731 )
732 ) {
733 become_designated_port(port_no);
734 port_state_selection();
735 }
736 }
737
738 void
739 set_path_cost(int port_no, unsigned short path_cost)
740 {
741 port_info[port_no].path_cost = path_cost;
742 configuration_update();
743 port_state_selection();
744 }
745
746 static void
747 br_tick(unsigned long arg)
748 {
749 int port_no;
750
751 if (hello_timer_expired()) {
752 hello_timer_expiry();
753 }
754 if (tcn_timer_expired()) {
755 tcn_timer_expiry();
756 }
757 if (topology_change_timer_expired()) {
758 topology_change_timer_expiry();
759 }
760 for (port_no = One; port_no <= No_of_ports; port_no++) {
761 if (forward_delay_timer_expired(port_no)) {
762 forward_delay_timer_expiry(port_no);
763 }
764 if (message_age_timer_expired(port_no)) {
765 message_age_timer_expiry(port_no);
766 }
767 if (hold_timer_expired(port_no)) {
768 hold_timer_expiry(port_no);
769 }
770 }
771
772 tl.expires = HZ;
773 tl.function = br_tick;
774 add_timer(&tl);
775 }
776
777 void
778 start_hello_timer(void)
779 {
780 hello_timer.value = 0;
781 hello_timer.active = TRUE;
782 }
783
784 void
785 stop_hello_timer(void)
786 {
787 hello_timer.active = FALSE;
788 }
789
790 int
791 hello_timer_expired(void)
792 {
793 if (hello_timer.active && (++hello_timer.value >= bridge_info.hello_time)) {
794 hello_timer.active = FALSE;
795 return (TRUE);
796 }
797 return (FALSE);
798 }
799
800 void
801 start_tcn_timer(void)
802 {
803 tcn_timer.value = 0;
804 tcn_timer.active = TRUE;
805 }
806
807 void
808 stop_tcn_timer(void)
809 {
810 tcn_timer.active = FALSE;
811 }
812
813 int
814 tcn_timer_expired(void)
815 {
816 if (tcn_timer.active && (++tcn_timer.value >=
817 bridge_info.bridge_hello_time)) {
818 tcn_timer.active = FALSE;
819 return (TRUE);
820 }
821 return (FALSE);
822
823 }
824
825 void
826 start_topology_change_timer(void)
827 {
828 topology_change_timer.value = 0;
829 topology_change_timer.active = TRUE;
830 }
831
832 void
833 stop_topology_change_timer(void)
834 {
835 topology_change_timer.active = FALSE;
836 }
837
838 int
839 topology_change_timer_expired(void)
840 {
841 if (topology_change_timer.active
842 && (++topology_change_timer.value
843 >= bridge_info.topology_change_time
844 )) {
845 topology_change_timer.active = FALSE;
846 return (TRUE);
847 }
848 return (FALSE);
849 }
850
851 void
852 start_message_age_timer(int port_no, unsigned short message_age)
853 {
854 message_age_timer[port_no].value = message_age;
855 message_age_timer[port_no].active = TRUE;
856 }
857
858 void
859 stop_message_age_timer(int port_no)
860 {
861 message_age_timer[port_no].active = FALSE;
862 }
863
864 int
865 message_age_timer_expired(int port_no)
866 {
867 if (message_age_timer[port_no].active &&
868 (++message_age_timer[port_no].value >= bridge_info.max_age)) {
869 message_age_timer[port_no].active = FALSE;
870 return (TRUE);
871 }
872 return (FALSE);
873 }
874
875 void
876 start_forward_delay_timer(int port_no)
877 {
878 forward_delay_timer[port_no].value = 0;
879 forward_delay_timer[port_no].active = TRUE;
880 }
881
882 void
883 stop_forward_delay_timer(int port_no)
884 {
885 forward_delay_timer[port_no].active = FALSE;
886 }
887
888 int
889 forward_delay_timer_expired(int port_no)
890 {
891 if (forward_delay_timer[port_no].active &&
892 (++forward_delay_timer[port_no].value >= bridge_info.forward_delay)) {
893 forward_delay_timer[port_no].active = FALSE;
894 return (TRUE);
895 }
896 return (FALSE);
897 }
898
899 void
900 start_hold_timer(int port_no)
901 {
902 hold_timer[port_no].value = 0;
903 hold_timer[port_no].active = TRUE;
904 }
905
906 void
907 stop_hold_timer(int port_no)
908 {
909 hold_timer[port_no].active = FALSE;
910 }
911
912
913 int
914 hold_timer_expired(int port_no)
915 {
916 if (hold_timer[port_no].active &&
917 (++hold_timer[port_no].value >= bridge_info.hold_time)) {
918 hold_timer[port_no].active = FALSE;
919 return (TRUE);
920 }
921 return (FALSE);
922
923 }
924
925 int
926 send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
927 {
928 struct sk_buff *skb;
929 struct device *dev = port_info[port_no].dev;
930 int size;
931 unsigned long flags;
932
933 if (port_info[port_no].state == Disabled) {
934 printk("send_config_bpdu: port %i not valid\n",port_no);
935 return(-1);
936 }
937 if (br_stats.flags & BR_DEBUG)
938 printk("send_config_bpdu: ");
939
940
941
942 size = sizeof(Config_bpdu) + dev->hard_header_len;
943 skb = alloc_skb(size, GFP_ATOMIC);
944 if (skb == NULL) {
945 printk("send_config_bpdu: no skb available\n");
946 return(-1);
947 }
948 skb->dev = dev;
949 skb->free = 1;
950 skb->h.eth = (struct ethhdr *)skb_put(skb, size);
951 memcpy(skb->h.eth->h_dest, bridge_ula, ETH_ALEN);
952 memcpy(skb->h.eth->h_source, dev->dev_addr, ETH_ALEN);
953 if (br_stats.flags & BR_DEBUG)
954 printk("port %i src %02x:%02x:%02x:%02x:%02x:%02x\
955 dest %02x:%02x:%02x:%02x:%02x:%02x\n",
956 port_no,
957 skb->h.eth->h_source[0],
958 skb->h.eth->h_source[1],
959 skb->h.eth->h_source[2],
960 skb->h.eth->h_source[3],
961 skb->h.eth->h_source[4],
962 skb->h.eth->h_source[5],
963 skb->h.eth->h_dest[0],
964 skb->h.eth->h_dest[1],
965 skb->h.eth->h_dest[2],
966 skb->h.eth->h_dest[3],
967 skb->h.eth->h_dest[4],
968 skb->h.eth->h_dest[5]);
969 skb->h.eth->h_proto = htonl(0x8038);
970
971 skb->h.raw += skb->dev->hard_header_len;
972 memcpy(skb->h.raw, config_bpdu, sizeof(Config_bpdu));
973
974
975 skb->pkt_bridged = IS_BRIDGED;
976 skb->arp = 1;
977 skb->h.raw = skb->data + ETH_HLEN;
978 save_flags(flags);
979 cli();
980 skb_queue_tail(dev->buffs, skb);
981 restore_flags(flags);
982 return(0);
983 }
984
985 int
986 send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
987 {
988 struct sk_buff *skb;
989 struct device *dev = port_info[port_no].dev;
990 int size;
991 unsigned long flags;
992
993 if (port_info[port_no].state == Disabled) {
994 printk("send_tcn_bpdu: port %i not valid\n",port_no);
995 return(-1);
996 }
997 if (br_stats.flags & BR_DEBUG)
998 printk("send_tcn_bpdu: ");
999 size = sizeof(Tcn_bpdu) + dev->hard_header_len;
1000 skb = alloc_skb(size, GFP_ATOMIC);
1001 if (skb == NULL) {
1002 printk("send_tcn_bpdu: no skb available\n");
1003 return(-1);
1004 }
1005 skb->dev = dev;
1006 skb->free = 1;
1007 skb->h.eth = (struct ethhdr *)skb_put(skb,size);
1008 memcpy(skb->h.eth->h_dest, bridge_ula, ETH_ALEN);
1009 memcpy(skb->h.eth->h_source, dev->dev_addr, ETH_ALEN);
1010 if (br_stats.flags & BR_DEBUG)
1011 printk("port %i src %02x:%02x:%02x:%02x:%02x:%02x\
1012 dest %02x:%02x:%02x:%02x:%02x:%02x\n",
1013 port_no,
1014 skb->h.eth->h_source[0],
1015 skb->h.eth->h_source[1],
1016 skb->h.eth->h_source[2],
1017 skb->h.eth->h_source[3],
1018 skb->h.eth->h_source[4],
1019 skb->h.eth->h_source[5],
1020 skb->h.eth->h_dest[0],
1021 skb->h.eth->h_dest[1],
1022 skb->h.eth->h_dest[2],
1023 skb->h.eth->h_dest[3],
1024 skb->h.eth->h_dest[4],
1025 skb->h.eth->h_dest[5]);
1026 skb->h.eth->h_proto = 0x8038;
1027
1028 skb->h.raw += skb->dev->hard_header_len;
1029 memcpy(skb->h.raw, bpdu, sizeof(Tcn_bpdu));
1030
1031
1032 skb->pkt_bridged = IS_BRIDGED;
1033 skb->arp = 1;
1034 skb->h.raw = skb->data + ETH_HLEN;
1035 save_flags(flags);
1036 cli();
1037 skb_queue_tail(dev->buffs, skb);
1038 restore_flags(flags);
1039 return(0);
1040 }
1041
1042 static int
1043 br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
1044 {
1045 struct device *dev = ptr;
1046 int i;
1047
1048
1049 if (dev->flags & IFF_LOOPBACK)
1050 return(NOTIFY_DONE);
1051
1052 switch (event) {
1053 case NETDEV_DOWN:
1054 if (br_stats.flags & BR_DEBUG)
1055 printk("br_device_event: NETDEV_DOWN...\n");
1056
1057 for (i = One; i <= No_of_ports; i++) {
1058 if (port_info[i].dev == dev) {
1059 disable_port(i);
1060 return NOTIFY_DONE;
1061 break;
1062 }
1063 }
1064 break;
1065 case NETDEV_UP:
1066 if (br_stats.flags & BR_DEBUG)
1067 printk("br_device_event: NETDEV_UP...\n");
1068
1069 if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_LOOPBACK)
1070 return NOTIFY_DONE;
1071
1072 for (i = One; i <= No_of_ports; i++) {
1073 if ((port_info[i].dev == (struct device *)0) ||
1074 (port_info[i].dev == dev)) {
1075 port_info[i].dev = dev;
1076 enable_port(i);
1077 set_path_cost(i, br_port_cost(dev));
1078 set_port_priority(i, 128);
1079 port_info[i].port_id = i;
1080
1081 if ((bridge_info.bridge_id.BRIDGE_ID[0] == 0) &&
1082 (bridge_info.bridge_id.BRIDGE_ID[1] == 0)) {
1083 memcpy(bridge_info.bridge_id.BRIDGE_ID_ULA, dev->dev_addr, 6);
1084 bridge_info.bridge_id.BRIDGE_PRIORITY = port_info[i].port_id;
1085 set_bridge_priority(&bridge_info.bridge_id);
1086 }
1087 make_forwarding(i);
1088 return NOTIFY_DONE;
1089 break;
1090 }
1091 }
1092 break;
1093 default:
1094 printk("br_device_event: unknown event [%x]\n",
1095 (unsigned int)event);
1096 }
1097 return NOTIFY_DONE;
1098 }
1099
1100
1101
1102
1103
1104
1105
1106 int
1107 br_receive_frame(struct sk_buff *skb)
1108 {
1109 int port;
1110
1111 if (br_stats.flags & BR_DEBUG)
1112 printk("br_receive_frame: ");
1113
1114 if (!skb) {
1115 printk("no skb!\n");
1116 return(1);
1117 }
1118
1119 if (skb->dev->flags & IFF_LOOPBACK)
1120 return(0);
1121
1122 port = find_port(skb->dev);
1123 skb->h.raw = skb->data;
1124 if (br_stats.flags & BR_DEBUG)
1125 printk("port %i src %02x:%02x:%02x:%02x:%02x:%02x\
1126 dest %02x:%02x:%02x:%02x:%02x:%02x\n",
1127 port,
1128 skb->h.eth->h_source[0],
1129 skb->h.eth->h_source[1],
1130 skb->h.eth->h_source[2],
1131 skb->h.eth->h_source[3],
1132 skb->h.eth->h_source[4],
1133 skb->h.eth->h_source[5],
1134 skb->h.eth->h_dest[0],
1135 skb->h.eth->h_dest[1],
1136 skb->h.eth->h_dest[2],
1137 skb->h.eth->h_dest[3],
1138 skb->h.eth->h_dest[4],
1139 skb->h.eth->h_dest[5]);
1140
1141 if (!port) {
1142 printk("\nbr_receive_frame: no port!\n");
1143 return(0);
1144 }
1145
1146 switch (port_info[port].state) {
1147 case Learning:
1148 (void) br_learn(skb, port);
1149
1150 case Listening:
1151
1152 if (memcmp(skb->h.eth->h_dest, bridge_ula, 6) == 0) {
1153 br_bpdu(skb);
1154 return(1);
1155 }
1156
1157 case Blocking:
1158
1159 case Disabled:
1160
1161
1162
1163
1164 return(0);
1165 break;
1166 case Forwarding:
1167 (void) br_learn(skb, port);
1168
1169 if (memcmp(skb->h.eth->h_dest, bridge_ula,
1170 ETH_ALEN) == 0) {
1171 printk("frame bpdu processor for me!!!\n");
1172 br_bpdu(skb);
1173 return(1);
1174 }
1175
1176 if (memcmp(skb->h.eth->h_dest,
1177 port_info[port].dev->dev_addr,
1178 ETH_ALEN) == 0) {
1179 return(0);
1180
1181 }
1182
1183 return(br_forward(skb, port));
1184 default:
1185 printk("br_receive_frame: port [%i] unknown state [%i]\n",
1186 port, port_info[port].state);
1187 return(0);
1188 }
1189 }
1190
1191
1192
1193
1194
1195
1196
1197 int
1198 br_tx_frame(struct sk_buff *skb)
1199 {
1200 int port;
1201
1202
1203 if (!skb) {
1204 printk("br_tx_frame: no skb!\n");
1205 return(0);
1206 }
1207
1208 if (skb->dev->flags & IFF_LOOPBACK)
1209 return(0);
1210
1211 skb->h.raw = skb->data;
1212 port = 0;
1213 if (br_stats.flags & BR_DEBUG)
1214 printk("br_tx_fr : port %i src %02x:%02x:%02x:%02x:%02x:%02x\
1215 dest %02x:%02x:%02x:%02x:%02x:%02x\n",
1216 port,
1217 skb->h.eth->h_source[0],
1218 skb->h.eth->h_source[1],
1219 skb->h.eth->h_source[2],
1220 skb->h.eth->h_source[3],
1221 skb->h.eth->h_source[4],
1222 skb->h.eth->h_source[5],
1223 skb->h.eth->h_dest[0],
1224 skb->h.eth->h_dest[1],
1225 skb->h.eth->h_dest[2],
1226 skb->h.eth->h_dest[3],
1227 skb->h.eth->h_dest[4],
1228 skb->h.eth->h_dest[5]);
1229 return(br_forward(skb, port));
1230 }
1231
1232
1233
1234
1235
1236
1237
1238 int
1239 br_learn(struct sk_buff *skb, int port)
1240 {
1241 struct fdb *f;
1242
1243 switch (port_info[port].state) {
1244 case Listening:
1245 case Blocking:
1246 case Disabled:
1247 default:
1248 return(-1);
1249
1250 case Learning:
1251 case Forwarding:
1252
1253 if (skb->h.eth->h_source[0] & 0x01)
1254 return(-1);
1255
1256 f = (struct fdb *)kmalloc(sizeof(struct fdb),
1257 GFP_ATOMIC);
1258
1259 if (!f) {
1260 printk("br_learn: unable to malloc fdb\n");
1261 return(-1);
1262 }
1263 f->port = port;
1264 memcpy(f->ula, skb->h.eth->h_source, 6);
1265 f->timer = CURRENT_TIME;
1266 f->flags = FDB_ENT_VALID;
1267
1268
1269
1270
1271
1272 if (br_avl_insert(f) == 0) {
1273 kfree(f);
1274 return(0);
1275 }
1276
1277 f->fdb_next = port_info[port].fdb;
1278 port_info[port].fdb = f;
1279 return(0);
1280
1281 }
1282 }
1283
1284
1285
1286
1287
1288 int
1289 br_drop(struct sk_buff *skb)
1290 {
1291 kfree_skb(skb, 0);
1292 return(1);
1293 }
1294
1295
1296
1297
1298
1299
1300 int
1301 br_forward(struct sk_buff *skb, int port)
1302 {
1303 struct fdb *f;
1304 unsigned long flags;
1305
1306
1307
1308
1309
1310
1311
1312
1313 if (skb->h.eth->h_dest[0] & 0x01) {
1314 br_flood(skb, port);
1315 if (port == 0)
1316 return(br_drop(skb));
1317 return(0);
1318 } else {
1319
1320 f = br_avl_find_addr(skb->h.eth->h_dest);
1321 if (!f | !(f->flags & FDB_ENT_VALID)) {
1322
1323 br_flood(skb, port);
1324 return(br_drop(skb));
1325 }
1326 if (port_info[f->port].state == Forwarding) {
1327
1328 if (f->timer + fdb_aging_time < CURRENT_TIME) {
1329
1330 f->flags &= ~FDB_ENT_VALID;
1331 if (br_stats.flags & BR_DEBUG)
1332 printk("fdb entry expired...\n");
1333 br_flood(skb, port);
1334 return(br_drop(skb));
1335 }
1336
1337 skb->pkt_bridged = IS_BRIDGED;
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347 skb->h.raw = skb->data + ETH_HLEN;
1348
1349
1350 if (skb_device_locked(skb))
1351 skb_device_unlock(skb);
1352
1353 save_flags(flags);
1354 cli();
1355 skb_queue_head(port_info[f->port].dev->buffs, skb);
1356 restore_flags(flags);
1357 return(1);
1358 } else {
1359 return(br_drop(skb));
1360 }
1361 }
1362 }
1363
1364
1365
1366
1367
1368
1369
1370 int
1371 br_flood(struct sk_buff *skb, int port)
1372 {
1373 int i;
1374 struct sk_buff *nskb;
1375 unsigned long flags;
1376
1377 for (i = One; i <= No_of_ports; i++) {
1378 if (i == port)
1379 continue;
1380 if (port_info[i].state == Forwarding) {
1381 nskb = skb_clone(skb, GFP_ATOMIC);
1382
1383 nskb->pkt_bridged = IS_BRIDGED;
1384
1385
1386
1387
1388
1389
1390 nskb->h.raw = nskb->data + ETH_HLEN;
1391 save_flags(flags);
1392 cli();
1393 skb_queue_tail(port_info[i].dev->buffs, nskb);
1394 restore_flags(flags);
1395 }
1396 }
1397 return(0);
1398 }
1399
1400 int
1401 find_port(struct device *dev)
1402 {
1403 int i;
1404
1405 for (i = One; i <= No_of_ports; i++)
1406 if ((port_info[i].dev == dev) &&
1407 (port_info[i].state != Disabled))
1408 return(i);
1409 return(0);
1410 }
1411
1412 int
1413 br_port_cost(struct device *dev)
1414 {
1415 if (strncmp(dev->name, "eth", 3) == 0)
1416 return(100);
1417 if (strncmp(dev->name, "wic", 3) == 0)
1418 return(1600);
1419 if (strncmp(dev->name, "plip",4) == 0)
1420 return (1600);
1421 return(100);
1422 }
1423
1424
1425
1426
1427
1428 void
1429 br_bpdu(struct sk_buff *skb)
1430 {
1431 Tcn_bpdu *bpdu;
1432 int port;
1433
1434 port = find_port(skb->dev);
1435 if (port == 0) {
1436 br_drop(skb);
1437 return;
1438 }
1439
1440 bpdu = (Tcn_bpdu *)skb->data + ETH_HLEN;
1441 switch (bpdu->type) {
1442 case BPDU_TYPE_CONFIG:
1443 received_config_bpdu(port, (Config_bpdu *)bpdu);
1444 break;
1445 case BPDU_TYPE_TOPO_CHANGE:
1446 received_tcn_bpdu(port, bpdu);
1447 break;
1448 default:
1449 printk("br_bpdu: received unknown bpdu, type = %i\n",
1450 bpdu->type);
1451
1452 }
1453 br_drop(skb);
1454 }
1455
1456 int
1457 br_ioctl(unsigned int cmd, void *arg)
1458 {
1459 int err;
1460 struct br_cf bcf;
1461 int i;
1462
1463 switch(cmd)
1464 {
1465 case SIOCGIFBR:
1466 err = verify_area(VERIFY_WRITE, arg,
1467 sizeof(struct br_stat));
1468 if(err)
1469 return err;
1470 memcpy(&br_stats.bridge_data, &bridge_info, sizeof(Bridge_data));
1471 memcpy(&br_stats.port_data, &port_info, sizeof(Port_data)*No_of_ports);
1472 memcpy_tofs(arg, &br_stats, sizeof(struct br_stat));
1473 return(0);
1474 case SIOCSIFBR:
1475 if (!suser())
1476 return -EPERM;
1477 err = verify_area(VERIFY_READ, arg,
1478 sizeof(struct br_cf));
1479 if(err)
1480 return err;
1481 memcpy_fromfs(&bcf, arg, sizeof(struct br_cf));
1482 switch (bcf.cmd) {
1483 case BRCMD_BRIDGE_ENABLE:
1484 if (br_stats.flags & BR_UP)
1485 return(-EALREADY);
1486 printk("br: enabling bridging function\n");
1487 register_netdevice_notifier(&br_dev_notifier);
1488 br_stats.flags |= BR_UP;
1489 start_hello_timer();
1490 break;
1491 case BRCMD_BRIDGE_DISABLE:
1492 if (!(br_stats.flags & BR_UP))
1493 return(-EALREADY);
1494 printk("br: disabling bridging function\n");
1495 unregister_netdevice_notifier(&br_dev_notifier);
1496 br_stats.flags &= ~BR_UP;
1497 stop_hello_timer();
1498 for (i = One; i <= No_of_ports; i++)
1499 if (port_info[i].state != Disabled)
1500 disable_port(i);
1501 break;
1502 case BRCMD_PORT_ENABLE:
1503 if (port_info[bcf.arg1].dev == 0)
1504 return(-EINVAL);
1505 if (port_info[bcf.arg1].state != Disabled)
1506 return(-EALREADY);
1507 printk("br: enabling port %i\n",bcf.arg1);
1508 enable_port(bcf.arg1);
1509 break;
1510 case BRCMD_PORT_DISABLE:
1511 if (port_info[bcf.arg1].dev == 0)
1512 return(-EINVAL);
1513 if (port_info[bcf.arg1].state == Disabled)
1514 return(-EALREADY);
1515 printk("br: disabling port %i\n",bcf.arg1);
1516 disable_port(bcf.arg1);
1517 break;
1518 case BRCMD_SET_BRIDGE_PRIORITY:
1519 set_bridge_priority((bridge_id_t *)&bcf.arg1);
1520 break;
1521 case BRCMD_SET_PORT_PRIORITY:
1522 if (port_info[bcf.arg1].dev == 0)
1523 return(-EINVAL);
1524 set_port_priority(bcf.arg1, bcf.arg2);
1525 break;
1526 case BRCMD_SET_PATH_COST:
1527 if (port_info[bcf.arg1].dev == 0)
1528 return(-EINVAL);
1529 set_path_cost(bcf.arg1, bcf.arg2);
1530 break;
1531 case BRCMD_ENABLE_DEBUG:
1532 br_stats.flags |= BR_DEBUG;
1533 break;
1534 case BRCMD_DISABLE_DEBUG:
1535 br_stats.flags &= ~BR_DEBUG;
1536 break;
1537 default:
1538 return -EINVAL;
1539 }
1540 return(0);
1541 default:
1542 return -EINVAL;
1543 }
1544
1545 return 0;
1546 }
1547
1548 int br_cmp(unsigned int *a, unsigned int *b)
1549 {
1550 int i;
1551 for (i=0; i<2; i++) {
1552 if (a[i] == b[i])
1553 continue;
1554 if (a[i] < b[i])
1555 return(1);
1556 if (a[i] > b[i])
1557 return(-1);
1558 }
1559 return(0);
1560 }
1561