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 skb->h.raw = skb->mac.raw;
1069 if (br_stats.flags & BR_DEBUG)
1070 printk("port %i src %02x:%02x:%02x:%02x:%02x:%02x\
1071 dest %02x:%02x:%02x:%02x:%02x:%02x\n",
1072 port,
1073 skb->h.eth->h_source[0],
1074 skb->h.eth->h_source[1],
1075 skb->h.eth->h_source[2],
1076 skb->h.eth->h_source[3],
1077 skb->h.eth->h_source[4],
1078 skb->h.eth->h_source[5],
1079 skb->h.eth->h_dest[0],
1080 skb->h.eth->h_dest[1],
1081 skb->h.eth->h_dest[2],
1082 skb->h.eth->h_dest[3],
1083 skb->h.eth->h_dest[4],
1084 skb->h.eth->h_dest[5]);
1085
1086 if (!port) {
1087 if(br_stats.flags&BR_DEBUG)
1088 printk("\nbr_receive_frame: no port!\n");
1089 return(0);
1090 }
1091
1092 switch (port_info[port].state)
1093 {
1094 case Learning:
1095 (void) br_learn(skb, port);
1096
1097 case Listening:
1098
1099 if (memcmp(skb->h.eth->h_dest, bridge_ula, 6) == 0) {
1100 br_bpdu(skb);
1101 return(1);
1102 }
1103
1104 case Blocking:
1105
1106 case Disabled:
1107
1108
1109
1110
1111 return(0);
1112 break;
1113 case Forwarding:
1114 (void) br_learn(skb, port);
1115
1116 if (memcmp(skb->h.eth->h_dest, bridge_ula,
1117 ETH_ALEN) == 0)
1118 {
1119
1120 br_bpdu(skb);
1121 return(1);
1122 }
1123
1124 if (memcmp(skb->h.eth->h_dest,
1125 port_info[port].dev->dev_addr,
1126 ETH_ALEN) == 0)
1127 {
1128 return(0);
1129
1130 }
1131
1132 skb_device_lock(skb);
1133 return(br_forward(skb, port));
1134 default:
1135 printk("br_receive_frame: port [%i] unknown state [%i]\n",
1136 port, port_info[port].state);
1137 return(0);
1138 }
1139 }
1140
1141
1142
1143
1144
1145
1146
1147 int br_tx_frame(struct sk_buff *skb)
1148 {
1149 int port;
1150
1151
1152 if (!skb)
1153 {
1154 printk("br_tx_frame: no skb!\n");
1155 return(0);
1156 }
1157
1158 if (skb->dev->flags & IFF_LOOPBACK)
1159 return(0);
1160
1161 skb->h.raw = skb->data;
1162 port = 0;
1163 if (br_stats.flags & BR_DEBUG)
1164 printk("br_tx_fr : port %i src %02x:%02x:%02x:%02x:%02x:%02x\
1165 dest %02x:%02x:%02x:%02x:%02x:%02x\n",
1166 port,
1167 skb->h.eth->h_source[0],
1168 skb->h.eth->h_source[1],
1169 skb->h.eth->h_source[2],
1170 skb->h.eth->h_source[3],
1171 skb->h.eth->h_source[4],
1172 skb->h.eth->h_source[5],
1173 skb->h.eth->h_dest[0],
1174 skb->h.eth->h_dest[1],
1175 skb->h.eth->h_dest[2],
1176 skb->h.eth->h_dest[3],
1177 skb->h.eth->h_dest[4],
1178 skb->h.eth->h_dest[5]);
1179 return(br_forward(skb, port));
1180 }
1181
1182
1183
1184
1185
1186
1187
1188 int br_learn(struct sk_buff *skb, int port)
1189 {
1190 struct fdb *f;
1191
1192 switch (port_info[port].state) {
1193 case Listening:
1194 case Blocking:
1195 case Disabled:
1196 default:
1197 return(-1);
1198
1199 case Learning:
1200 case Forwarding:
1201
1202 if (skb->h.eth->h_source[0] & 0x01)
1203 return(-1);
1204
1205 f = (struct fdb *)kmalloc(sizeof(struct fdb),
1206 GFP_ATOMIC);
1207
1208 if (!f) {
1209 printk("br_learn: unable to malloc fdb\n");
1210 return(-1);
1211 }
1212 f->port = port;
1213 memcpy(f->ula, skb->h.eth->h_source, 6);
1214 f->timer = CURRENT_TIME;
1215 f->flags = FDB_ENT_VALID;
1216
1217
1218
1219
1220
1221 if (br_avl_insert(f) == 0) {
1222 kfree(f);
1223 return(0);
1224 }
1225
1226 f->fdb_next = port_info[port].fdb;
1227 port_info[port].fdb = f;
1228 return(0);
1229
1230 }
1231 }
1232
1233
1234
1235
1236
1237 int br_drop(struct sk_buff *skb)
1238 {
1239 kfree_skb(skb, 0);
1240 return(1);
1241 }
1242
1243
1244
1245
1246
1247 int br_dev_drop(struct sk_buff *skb)
1248 {
1249 dev_kfree_skb(skb, 0);
1250 return(1);
1251 }
1252
1253
1254
1255
1256
1257
1258 int br_forward(struct sk_buff *skb, int port)
1259 {
1260 struct fdb *f;
1261 unsigned long flags;
1262
1263
1264
1265
1266
1267
1268
1269
1270 if (skb->h.eth->h_dest[0] & 0x01)
1271 {
1272
1273 br_flood(skb, port);
1274
1275
1276
1277
1278
1279 if (port == 0)
1280 return(br_dev_drop(skb));
1281 return(0);
1282 } else {
1283
1284 f = br_avl_find_addr(skb->h.eth->h_dest);
1285
1286
1287
1288 if (!f | !(f->flags & FDB_ENT_VALID)) {
1289
1290 br_flood(skb, port);
1291 return(br_dev_drop(skb));
1292 }
1293
1294
1295
1296 if (port_info[f->port].state == Forwarding) {
1297
1298 if (f->timer + fdb_aging_time < CURRENT_TIME) {
1299
1300 f->flags &= ~FDB_ENT_VALID;
1301 if (br_stats.flags & BR_DEBUG)
1302 printk("fdb entry expired...\n");
1303
1304
1305
1306 br_flood(skb, port);
1307 return(br_dev_drop(skb));
1308 }
1309
1310 skb->pkt_bridged = IS_BRIDGED;
1311
1312
1313 skb->h.raw = skb->data + ETH_HLEN;
1314
1315
1316
1317
1318
1319 skb->dev=port_info[f->port].dev;
1320
1321
1322
1323
1324 dev_queue_xmit(skb, skb->dev,1);
1325 return(1);
1326 } else {
1327
1328
1329
1330 return(br_dev_drop(skb));
1331 }
1332 }
1333 }
1334
1335
1336
1337
1338
1339
1340
1341 int br_flood(struct sk_buff *skb, int port)
1342 {
1343 int i;
1344 struct sk_buff *nskb;
1345 unsigned long flags;
1346
1347 for (i = One; i <= No_of_ports; i++)
1348 {
1349 if (i == port)
1350 continue;
1351 if (port_info[i].state == Forwarding)
1352 {
1353 nskb = skb_clone(skb, GFP_ATOMIC);
1354
1355 nskb->pkt_bridged = IS_BRIDGED;
1356 nskb->arp = skb->arp;
1357
1358
1359 nskb->h.raw = nskb->data + ETH_HLEN;
1360 dev_queue_xmit(nskb,nskb->dev,1);
1361 }
1362 }
1363 return(0);
1364 }
1365
1366 int find_port(struct device *dev)
1367 {
1368 int i;
1369
1370 for (i = One; i <= No_of_ports; i++)
1371 if ((port_info[i].dev == dev) &&
1372 (port_info[i].state != Disabled))
1373 return(i);
1374 return(0);
1375 }
1376
1377 int br_port_cost(struct device *dev)
1378 {
1379 if (strncmp(dev->name, "eth", 3) == 0)
1380 return(100);
1381 if (strncmp(dev->name, "wic", 3) == 0)
1382 return(1600);
1383 if (strncmp(dev->name, "plip",4) == 0)
1384 return (1600);
1385 return(100);
1386 }
1387
1388
1389
1390
1391
1392 void br_bpdu(struct sk_buff *skb)
1393 {
1394 Tcn_bpdu *bpdu;
1395 int port;
1396
1397 port = find_port(skb->dev);
1398 if (port == 0) {
1399 br_drop(skb);
1400 return;
1401 }
1402
1403 bpdu = (Tcn_bpdu *)skb->data + ETH_HLEN;
1404 switch (bpdu->type) {
1405 case BPDU_TYPE_CONFIG:
1406 received_config_bpdu(port, (Config_bpdu *)bpdu);
1407 break;
1408 case BPDU_TYPE_TOPO_CHANGE:
1409 received_tcn_bpdu(port, bpdu);
1410 break;
1411 default:
1412 printk("br_bpdu: received unknown bpdu, type = %i\n",
1413 bpdu->type);
1414
1415 }
1416 br_drop(skb);
1417 }
1418
1419 int br_ioctl(unsigned int cmd, void *arg)
1420 {
1421 int err;
1422 struct br_cf bcf;
1423 int i;
1424
1425 switch(cmd)
1426 {
1427 case SIOCGIFBR:
1428 err = verify_area(VERIFY_WRITE, arg,
1429 sizeof(struct br_stat));
1430 if(err)
1431 return err;
1432 memcpy(&br_stats.bridge_data, &bridge_info, sizeof(Bridge_data));
1433 memcpy(&br_stats.port_data, &port_info, sizeof(Port_data)*No_of_ports);
1434 memcpy_tofs(arg, &br_stats, sizeof(struct br_stat));
1435 return(0);
1436 case SIOCSIFBR:
1437 if (!suser())
1438 return -EPERM;
1439 err = verify_area(VERIFY_READ, arg,
1440 sizeof(struct br_cf));
1441 if(err)
1442 return err;
1443 memcpy_fromfs(&bcf, arg, sizeof(struct br_cf));
1444 switch (bcf.cmd) {
1445 case BRCMD_BRIDGE_ENABLE:
1446 if (br_stats.flags & BR_UP)
1447 return(-EALREADY);
1448 printk("br: enabling bridging function\n");
1449 br_stats.flags |= BR_UP;
1450 start_hello_timer();
1451 break;
1452 case BRCMD_BRIDGE_DISABLE:
1453 if (!(br_stats.flags & BR_UP))
1454 return(-EALREADY);
1455 printk("br: disabling bridging function\n");
1456 br_stats.flags &= ~BR_UP;
1457 stop_hello_timer();
1458 #if 0
1459 for (i = One; i <= No_of_ports; i++)
1460 if (port_info[i].state != Disabled)
1461 disable_port(i);
1462 #endif
1463 break;
1464 case BRCMD_PORT_ENABLE:
1465 if (port_info[bcf.arg1].dev == 0)
1466 return(-EINVAL);
1467 if (port_info[bcf.arg1].state != Disabled)
1468 return(-EALREADY);
1469 printk("br: enabling port %i\n",bcf.arg1);
1470 enable_port(bcf.arg1);
1471 break;
1472 case BRCMD_PORT_DISABLE:
1473 if (port_info[bcf.arg1].dev == 0)
1474 return(-EINVAL);
1475 if (port_info[bcf.arg1].state == Disabled)
1476 return(-EALREADY);
1477 printk("br: disabling port %i\n",bcf.arg1);
1478 disable_port(bcf.arg1);
1479 break;
1480 case BRCMD_SET_BRIDGE_PRIORITY:
1481 set_bridge_priority((bridge_id_t *)&bcf.arg1);
1482 break;
1483 case BRCMD_SET_PORT_PRIORITY:
1484 if (port_info[bcf.arg1].dev == 0)
1485 return(-EINVAL);
1486 set_port_priority(bcf.arg1, bcf.arg2);
1487 break;
1488 case BRCMD_SET_PATH_COST:
1489 if (port_info[bcf.arg1].dev == 0)
1490 return(-EINVAL);
1491 set_path_cost(bcf.arg1, bcf.arg2);
1492 break;
1493 case BRCMD_ENABLE_DEBUG:
1494 br_stats.flags |= BR_DEBUG;
1495 break;
1496 case BRCMD_DISABLE_DEBUG:
1497 br_stats.flags &= ~BR_DEBUG;
1498 break;
1499 default:
1500 return -EINVAL;
1501 }
1502 return(0);
1503 default:
1504 return -EINVAL;
1505 }
1506
1507 return 0;
1508 }
1509
1510 int br_cmp(unsigned int *a, unsigned int *b)
1511 {
1512 int i;
1513 for (i=0; i<2; i++)
1514 {
1515 if (a[i] == b[i])
1516 continue;
1517 if (a[i] < b[i])
1518 return(1);
1519 if (a[i] > b[i])
1520 return(-1);
1521 }
1522 return(0);
1523 }
1524