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