1 diff -urN linux-2.2.20/CREDITS linux-2.2.20br/CREDITS
2 --- linux-2.2.20/CREDITS Fri Nov 2 17:39:05 2001
3 +++ linux-2.2.20br/CREDITS Mon Dec 10 16:24:28 2001
10 +D: Rewrite of the ethernet bridging code
16 E: callahan@maths.ox.ac.uk
18 diff -urN linux-2.2.20/Documentation/Configure.help linux-2.2.20br/Documentation/Configure.help
19 --- linux-2.2.20/Documentation/Configure.help Fri Nov 2 17:39:05 2001
20 +++ linux-2.2.20br/Documentation/Configure.help Mon Dec 10 16:24:28 2001
21 @@ -4099,24 +4099,26 @@
22 This is a Logical Link Layer protocol used for X.25 connections over
23 Ethernet, using ordinary Ethernet cards.
25 -Bridging (EXPERIMENTAL)
26 +802.1d Ethernet Bridging
28 If you say Y here, then your Linux box will be able to act as an
29 Ethernet bridge, which means that the different Ethernet segments it
30 is connected to will appear as one Ethernet to the participants.
31 Several such bridges can work together to create even larger
32 - networks of Ethernets using the IEEE802.1 spanning tree algorithm.
33 + networks of Ethernets using the IEEE 802.1d spanning tree protocol.
34 As this is a standard, Linux bridges will interwork properly with
35 other third party bridge products.
37 - In order to use this, you'll need the bridge configuration tools
38 - available from http://lrp.plain.co.nz/tarballs/bridgex-0.30.tar.gz
39 + In order to use the ethernet bridge, you'll need the bridge configuration
40 + tools available from http://www.math.leidenuniv.nl/~buytenh/bridge. Please
41 + read the documentation for more information.
43 Note that if your box acts as a bridge, it probably contains several
44 - Ethernet devices, but the kernel is not able to recognize more than
45 - one ISA ethernet card at boot time without help; for details read
46 - the Ethernet-HOWTO, available via FTP (user: anonymous)
47 - in ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. The Bridging code is
48 - still in test. If unsure, say N.
49 + Ethernet devices, but the kernel is not able to recognize more than one
50 + at boot time without help; for details read the Ethernet-HOWTO, available
51 + via FTP (user: anonymous) in ftp://metalab.unc.edu/pub/Linux/docs/HOWTO.
55 Frame Diverter (EXPERIMENTAL)
57 diff -urN linux-2.2.20/Documentation/networking/bridge.txt linux-2.2.20br/Documentation/networking/bridge.txt
58 --- linux-2.2.20/Documentation/networking/bridge.txt Thu Jan 1 01:00:00 1970
59 +++ linux-2.2.20br/Documentation/networking/bridge.txt Mon Dec 10 16:24:28 2001
61 +In order to use the ethernet bridging functionality you'll need the
62 +userspace tools available at http://www.math.leidenuniv.nl/~buytenh/bridge.
63 +The tarball available there contains extensive documentation, but if you
64 +still have questions, don't hesitate to post to the mailing list (more info
65 +at http://www.math.leidenuniv.nl/mailman/listinfo/bridge). You can also mail
66 +me at buytenh@gnu.org.
72 diff -urN linux-2.2.20/MAINTAINERS linux-2.2.20br/MAINTAINERS
73 --- linux-2.2.20/MAINTAINERS Fri Nov 2 17:39:05 2001
74 +++ linux-2.2.20br/MAINTAINERS Mon Dec 10 16:24:28 2001
76 L: linux-net@vger.kernel.org
82 +L: bridge@math.leidenuniv.nl
83 +W: http://www.math.leidenuniv.nl/~buytenh/bridge
89 diff -urN linux-2.2.20/include/linux/if_bridge.h linux-2.2.20br/include/linux/if_bridge.h
90 --- linux-2.2.20/include/linux/if_bridge.h Thu Jan 1 01:00:00 1970
91 +++ linux-2.2.20br/include/linux/if_bridge.h Mon Dec 10 16:24:28 2001
94 + * Linux ethernet bridge
97 + * Lennert Buytenhek <buytenh@gnu.org>
101 + * This program is free software; you can redistribute it and/or
102 + * modify it under the terms of the GNU General Public License
103 + * as published by the Free Software Foundation; either version
104 + * 2 of the License, or (at your option) any later version.
107 +#ifndef _LINUX_IF_BRIDGE_H
108 +#define _LINUX_IF_BRIDGE_H
110 +#include <linux/types.h>
112 +#define BRCTL_VERSION 1
114 +#define BRCTL_GET_VERSION 0
115 +#define BRCTL_GET_BRIDGES 1
116 +#define BRCTL_ADD_BRIDGE 2
117 +#define BRCTL_DEL_BRIDGE 3
118 +#define BRCTL_ADD_IF 4
119 +#define BRCTL_DEL_IF 5
120 +#define BRCTL_GET_BRIDGE_INFO 6
121 +#define BRCTL_GET_PORT_LIST 7
122 +#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8
123 +#define BRCTL_SET_BRIDGE_HELLO_TIME 9
124 +#define BRCTL_SET_BRIDGE_MAX_AGE 10
125 +#define BRCTL_SET_AGEING_TIME 11
126 +#define BRCTL_SET_GC_INTERVAL 12
127 +#define BRCTL_GET_PORT_INFO 13
128 +#define BRCTL_SET_BRIDGE_STP_STATE 14
129 +#define BRCTL_SET_BRIDGE_PRIORITY 15
130 +#define BRCTL_SET_PORT_PRIORITY 16
131 +#define BRCTL_SET_PATH_COST 17
132 +#define BRCTL_GET_FDB_ENTRIES 18
134 +#define BR_STATE_DISABLED 0
135 +#define BR_STATE_LISTENING 1
136 +#define BR_STATE_LEARNING 2
137 +#define BR_STATE_FORWARDING 3
138 +#define BR_STATE_BLOCKING 4
140 +struct __bridge_info
142 + __u64 designated_root;
144 + __u32 root_path_cost;
147 + __u32 forward_delay;
148 + __u32 bridge_max_age;
149 + __u32 bridge_hello_time;
150 + __u32 bridge_forward_delay;
151 + __u8 topology_change;
152 + __u8 topology_change_detected;
157 + __u32 hello_timer_value;
158 + __u32 tcn_timer_value;
159 + __u32 topology_change_timer_value;
160 + __u32 gc_timer_value;
165 + __u64 designated_root;
166 + __u64 designated_bridge;
168 + __u16 designated_port;
170 + __u32 designated_cost;
172 + __u8 top_change_ack;
173 + __u8 config_pending;
175 + __u32 message_age_timer_value;
176 + __u32 forward_delay_timer_value;
177 + __u32 hold_timer_value;
185 + __u32 ageing_timer_value;
191 +#include <linux/netdevice.h>
194 +struct net_bridge_port;
196 +extern int br_init(void);
197 +extern int (*br_ioctl_hook)(unsigned long arg);
198 +extern void (*br_handle_frame_hook)(struct sk_buff *skb);
203 diff -urN linux-2.2.20/include/linux/netdevice.h linux-2.2.20br/include/linux/netdevice.h
204 --- linux-2.2.20/include/linux/netdevice.h Fri Nov 2 17:39:09 2001
205 +++ linux-2.2.20br/include/linux/netdevice.h Mon Dec 10 16:24:28 2001
207 struct Qdisc *qdisc_list;
208 unsigned long tx_queue_len; /* Max frames per queue allowed */
211 - int bridge_port_id;
213 /* Pointers to interface service routines. */
214 int (*open)(struct device *dev);
215 int (*stop)(struct device *dev);
217 int (*neigh_setup)(struct device *dev, struct neigh_parms *);
218 int (*accept_fastpath)(struct device *, struct dst_entry*);
221 + struct net_bridge_port *br_port;
223 #ifdef CONFIG_NET_FASTROUTE
224 /* Really, this semaphore may be necessary and for not fastroute code;
226 diff -urN linux-2.2.20/include/linux/skbuff.h linux-2.2.20br/include/linux/skbuff.h
227 --- linux-2.2.20/include/linux/skbuff.h Sun Mar 25 18:31:03 2001
228 +++ linux-2.2.20br/include/linux/skbuff.h Mon Dec 10 16:24:28 2001
230 unsigned char is_clone, /* We are a clone */
231 cloned, /* head may be cloned (check refcnt to be sure). */
232 pkt_type, /* Packet class */
233 - pkt_bridged, /* Tracker for bridging */
234 ip_summed; /* Driver fed us an IP checksum */
235 __u32 priority; /* Packet queueing priority */
236 atomic_t users; /* User count - see datagram.c,tcp.c */
237 diff -urN linux-2.2.20/include/net/br.h linux-2.2.20br/include/net/br.h
238 --- linux-2.2.20/include/net/br.h Sun Mar 25 18:31:08 2001
239 +++ linux-2.2.20br/include/net/br.h Thu Jan 1 01:00:00 1970
242 - * Constants and structure definitions for the bridging code
248 -#endif /* !defined(One) */
253 -#endif /* !defined(TRUE) */
255 -/** port states. **/
256 -#define Disabled 0 /* (4.4 5) */
257 -#define Listening 1 /* (4.4.2) */
258 -#define Learning 2 /* (4.4.3) */
259 -#define Forwarding 3 /* (4 4 4) */
260 -#define Blocking 4 /* (4.4.1) */
263 -/* MAG Yich! Easiest way of giving a configurable number of ports
264 - * If you want more than 32, change BR_MAX_PORTS and recompile brcfg!
266 -#define BR_MAX_PORTS (32)
267 -#if CONFIG_BRIDGE_NUM_PORTS > BR_MAX_PORTS
268 -#undef CONFIG_BRIDGE_NUM_PORTS
269 -#define CONFIG_BRIDGE_NUM_PORTS BR_MAX_PORTS
271 -#define No_of_ports CONFIG_BRIDGE_NUM_PORTS
272 -/* arbitrary choice, to allow the code below to compile */
274 -#define All_ports (No_of_ports + 1)
277 - * We time out our entries in the FDB after this many seconds.
279 -#define FDB_TIMEOUT 20 /* JRP: 20s as NSC bridge code, was 300 for Linux */
282 - * the following defines are the initial values used when the
283 - * bridge is booted. These may be overridden when this bridge is
284 - * not the root bridge. These are the recommended default values
285 - * from the 802.1d specification.
287 -#define BRIDGE_MAX_AGE 20
288 -#define BRIDGE_HELLO_TIME 2
289 -#define BRIDGE_FORWARD_DELAY 15
292 -/* broacast/multicast storm limitation. This per source. */
293 -#define MAX_MCAST_PER_PERIOD 32
294 -#define MCAST_HOLD_TIME (10*HZ/100)
296 -#define Default_path_cost 10
299 - * minimum increment possible to avoid underestimating age, allows for BPDU
300 - * transmission time
302 -#define Message_age_increment 1
306 - * reserved value for Bridge's root port parameter indicating no root port,
307 - * used when Bridge is the root - also used to indicate the source when
308 - * a frame is being generated by a higher layer protocol on this host
311 -/** Configuration BPDU Parameters (4.5.1) **/
316 - unsigned short priority;
317 - unsigned char ula[6];
319 - unsigned int id[2];
323 -#define BRIDGE_PRIORITY bi.p_u.priority
324 -#define BRIDGE_ID_ULA bi.p_u.ula
325 -#define BRIDGE_ID bi.id
327 -/* JRP: on the network the flags field is between "type" and "root_id"
328 - * this is unfortunated! To make the code portable to a RISC machine
329 - * the pdus are now massaged a little bit for processing
331 -#define TOPOLOGY_CHANGE 0x01
332 -#define TOPOLOGY_CHANGE_ACK 0x80
333 -#define BRIDGE_BPDU_8021_CONFIG_SIZE 35 /* real size */
334 -#define BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET 4
335 -#define BRIDGE_BPDU_8021_PROTOCOL_ID 0
336 -#define BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID 0
337 -#define BRIDGE_LLC1_HS 3
338 -#define BRIDGE_LLC1_DSAP 0x42
339 -#define BRIDGE_LLC1_SSAP 0x42
340 -#define BRIDGE_LLC1_CTRL 0x03
343 - unsigned short protocol_id;
344 - unsigned char protocol_version_id;
345 - unsigned char type;
346 - bridge_id_t root_id; /* (4.5.1.1) */
347 - unsigned int root_path_cost; /* (4.5.1.2) */
348 - bridge_id_t bridge_id; /* (4.5.1.3) */
349 - unsigned short port_id; /* (4.5.1.4) */
350 - unsigned short message_age; /* (4.5.1.5) */
351 - unsigned short max_age; /* (4.5.1.6) */
352 - unsigned short hello_time; /* (4.5.1.7) */
353 - unsigned short forward_delay; /* (4.5.1.8) */
354 - unsigned char top_change_ack;
355 - unsigned char top_change;
358 -#ifdef __LITTLE_ENDIAN
359 -#define config_bpdu_hton(config_bpdu) \
360 - (config_bpdu)->root_path_cost = htonl((config_bpdu)->root_path_cost); \
361 - (config_bpdu)->port_id = htons((config_bpdu)->port_id); \
362 - (config_bpdu)->message_age = htons((config_bpdu)->message_age); \
363 - (config_bpdu)->max_age = htons((config_bpdu)->max_age); \
364 - (config_bpdu)->hello_time = htons((config_bpdu)->hello_time); \
365 - (config_bpdu)->forward_delay = htons((config_bpdu)->forward_delay);
367 -#define config_bpdu_hton(config_bpdu)
369 -#define config_bpdu_ntoh config_bpdu_hton
372 -/** Topology Change Notification BPDU Parameters (4.5.2) **/
375 - unsigned short protocol_id;
376 - unsigned char protocol_version_id;
377 - unsigned char type;
380 -#define BPDU_TYPE_CONFIG 0
381 -#define BPDU_TYPE_TOPO_CHANGE 128
383 -/** Bridge Parameters (4.5.3) **/
385 - bridge_id_t designated_root; /* (4.5.3.1) */
386 - unsigned int root_path_cost; /* (4.5.3.2) */
387 - unsigned int root_port; /* (4.5.3.3) */
388 - unsigned short max_age; /* (4.5.3.4) */
389 - unsigned short hello_time; /* (4.5.3.5) */
390 - unsigned short forward_delay; /* (4.5.3.6) */
391 - bridge_id_t bridge_id; /* (4.5.3.7) */
392 - unsigned short bridge_max_age; /* (4.5.3.8) */
393 - unsigned short bridge_hello_time; /* (4.5.3.9) */
394 - unsigned short bridge_forward_delay; /* (4.5.3.10) */
395 - unsigned int top_change_detected; /* (4.5.3.11) */
396 - unsigned int top_change; /* (4.5.3.12) */
397 - unsigned short topology_change_time; /* (4.5.3.13) */
398 - unsigned short hold_time; /* (4.5.3.14) */
399 - unsigned int instance;
402 -/** Port Parameters (4.5.5) **/
404 - unsigned short port_id; /* (4.5.5.1) */
405 - unsigned int state; /* (4.5.5.2) */
406 - unsigned int path_cost; /* (4.5.5.3) */
407 - bridge_id_t designated_root; /* (4.5.5.4) */
408 - unsigned int designated_cost; /* (4.5.5.5) */
409 - bridge_id_t designated_bridge; /* (4.5.5.6) */
410 - unsigned short designated_port; /* (4.5.5.7) */
411 - unsigned int top_change_ack; /* (4.5.5.8) */
412 - unsigned int config_pending; /* (4.5.5.9) */
414 - unsigned int admin_state;
415 - char ifname[IFNAMSIZ]; /* Make life easier for brcfg */
416 - struct device *dev;
417 - struct fdb *fdb; /* head of per port fdb chain */
422 -/** types to support timers for this pseudo-implementation. **/
424 - unsigned int active; /* timer in use. */
425 - unsigned int value; /* current value of timer,
430 - unsigned char ula[6];
431 - unsigned char pad[2];
432 - unsigned short port;
433 - unsigned int timer;
434 - unsigned short flags;
435 -#define FDB_ENT_VALID 0x01
436 - unsigned short mcast_count;
437 - unsigned int mcast_timer; /* oldest xxxxxcast */
439 -/* AVL tree of all addresses, sorted by address */
440 - short fdb_avl_height;
441 - struct fdb *fdb_avl_left;
442 - struct fdb *fdb_avl_right;
443 -/* linked list of addresses for each port */
444 - struct fdb *fdb_next;
447 -/* data returned on BRCMD_DISPLAY_FDB */
449 - unsigned char ula[6];
450 - unsigned char port;
451 - unsigned char flags;
452 - unsigned int timer;
454 -struct fdb_info_hdr {
455 - int copied; /* nb of entries copied to user */
456 - int not_copied; /* when user buffer is too small */
460 -#define IS_BRIDGED 0x2e
463 -#define BR_MAX_PROTOCOLS 32
464 -#define BR_MAX_PROT_STATS BR_MAX_PROTOCOLS
466 -/* policy values for policy field */
470 -/* JRP: extra statistics for debug */
472 - /* br_receive_frame counters */
473 - int port_disable_up_stack;
476 - int forwarding_up_stack;
479 - /* br_tx_frame counters */
481 - int port_not_disable;
483 - /* br_forward counters */
484 - int local_multicast;
485 - int forwarded_multicast; /* up stack as well */
487 - int aged_flood_unicast;
488 - int forwarded_unicast;
489 - int forwarded_unicast_up_stack;
490 - int forwarded_ip_up_stack;
491 - int forwarded_ip_up_stack_lie; /* received on alternate device */
492 - int arp_for_local_mac;
493 - int drop_same_port;
494 - int drop_same_port_aged;
495 - int drop_multicast;
499 - unsigned int flags;
500 - Bridge_data bridge_data;
501 - unsigned int policy;
502 - unsigned int exempt_protocols;
503 - unsigned short protocols[BR_MAX_PROTOCOLS];
504 - unsigned short prot_id[BR_MAX_PROT_STATS]; /* Protocol encountered */
505 - unsigned int prot_counter[BR_MAX_PROT_STATS]; /* How many packets ? */
506 - br_stats_counter packet_cnts;
507 - unsigned int num_ports;
508 - Port_data port_data[BR_MAX_PORTS + 1];
511 -/* defined flags for br_stat.flags */
512 -#define BR_UP 0x0001 /* bridging enabled */
513 -#define BR_DEBUG 0x0002 /* debugging enabled */
514 -#define BR_PROT_STATS 0x0004 /* protocol statistics enabled */
515 -#define BR_STP_DISABLED 0x0008 /* Spanning tree protocol disabled */
524 -#define BRCMD_BRIDGE_ENABLE 1
525 -#define BRCMD_BRIDGE_DISABLE 2
526 -#define BRCMD_PORT_ENABLE 3 /* arg1 = port */
527 -#define BRCMD_PORT_DISABLE 4 /* arg1 = port */
528 -#define BRCMD_SET_BRIDGE_PRIORITY 5 /* arg1 = priority */
529 -#define BRCMD_SET_PORT_PRIORITY 6 /* arg1 = port, arg2 = priority */
530 -#define BRCMD_SET_PATH_COST 7 /* arg1 = port, arg2 = cost */
531 -#define BRCMD_DISPLAY_FDB 8
532 -#define BRCMD_ENABLE_DEBUG 9
533 -#define BRCMD_DISABLE_DEBUG 10
534 -#define BRCMD_SET_POLICY 11 /* arg1 = default policy (1==bridge all) */
535 -#define BRCMD_EXEMPT_PROTOCOL 12 /* arg1 = protocol (see net/if_ether.h) */
536 -#define BRCMD_ENABLE_PROT_STATS 13
537 -#define BRCMD_DISABLE_PROT_STATS 14
538 -#define BRCMD_ZERO_PROT_STATS 15
539 -#define BRCMD_TOGGLE_STP 16
540 -#define BRCMD_IF_ENABLE 17 /* arg1 = if_index */
541 -#define BRCMD_IF_DISABLE 18 /* arg1 = if_index */
542 -#define BRCMD_SET_IF_PRIORITY 19 /* arg1 = if_index, arg2 = priority */
543 -#define BRCMD_SET_IF_PATH_COST 20 /* arg1 = if_index, arg2 = cost */
545 -/* prototypes of exported bridging functions... */
549 -int br_receive_frame(struct sk_buff *skb); /* 3.5 */
550 -int br_tx_frame(struct sk_buff *skb);
552 -int br_ioctl(unsigned int cmd, void *arg);
553 -void requeue_fdb(struct fdb *node, int new_port);
555 -struct fdb *br_avl_find_addr(unsigned char addr[6]);
556 -struct fdb *br_avl_insert (struct fdb * new_node);
557 -void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,int* len, off_t offset, int length);
558 -int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
559 -void br_avl_delete_by_port(int port);
560 -int br_call_bridge(struct sk_buff *skb, unsigned short type);
561 -void br_spacedevice_register(void);
565 -extern struct br_stat br_stats;
566 -extern Port_data port_info[];
572 diff -urN linux-2.2.20/net/Config.in linux-2.2.20br/net/Config.in
573 --- linux-2.2.20/net/Config.in Sun Mar 25 18:37:41 2001
574 +++ linux-2.2.20br/net/Config.in Mon Dec 10 16:25:05 2001
576 source net/ipx/Config.in
578 tristate 'Appletalk DDP' CONFIG_ATALK
579 +dep_tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE $CONFIG_INET
580 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
581 # tristate 'DECnet Support (NOT YET FUNCTIONAL)' CONFIG_DECNET
582 # if [ "$CONFIG_DECNET" != "n" ]; then
585 tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25
586 tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB
587 - bool 'Bridging (EXPERIMENTAL)' CONFIG_BRIDGE
588 - if [ "$CONFIG_BRIDGE" != "n" ]; then
589 - int ' Maximum number of bridged interfaces' CONFIG_BRIDGE_NUM_PORTS 8
591 bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT
592 bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC
593 # if [ "$CONFIG_LLC" = "y" ]; then
594 diff -urN linux-2.2.20/net/Makefile linux-2.2.20br/net/Makefile
595 --- linux-2.2.20/net/Makefile Sun Mar 25 18:31:11 2001
596 +++ linux-2.2.20br/net/Makefile Mon Dec 10 16:24:28 2001
599 ifeq ($(CONFIG_BRIDGE),y)
602 + ifeq ($(CONFIG_BRIDGE),m)
603 + MOD_SUB_DIRS += bridge
607 ifeq ($(CONFIG_IPX),y)
608 diff -urN linux-2.2.20/net/README linux-2.2.20br/net/README
609 --- linux-2.2.20/net/README Sun Mar 25 18:31:11 2001
610 +++ linux-2.2.20br/net/README Mon Dec 10 16:24:28 2001
612 [token ring ] p.norton@computer.org
613 appletalk Jay.Schulist@spacs.k12.wi.us
614 ax25 g4klx@g4klx.demon.co.uk
615 +bridge buytenh@gnu.org
616 core alan@lxorguk.ukuu.org.uk
617 decnet SteveW@ACM.org
618 ethernet alan@lxorguk.ukuu.org.uk
619 diff -urN linux-2.2.20/net/bridge/Makefile linux-2.2.20br/net/bridge/Makefile
620 --- linux-2.2.20/net/bridge/Makefile Sun Mar 25 18:31:13 2001
621 +++ linux-2.2.20br/net/bridge/Makefile Mon Dec 10 16:24:28 2001
624 -# Makefile for the Linux Bridge layer.
625 +# Makefile for the IEEE 802.1d ethernet bridging layer.
627 # Note! Dependencies are done automagically by 'make dep', which also
628 # removes any old dependencies. DON'T put your own dependencies here
631 # Note 2! The CFLAGS definition is now in the main makefile...
633 -O_TARGET := bridge.o
634 -O_OBJS := br.o br_tree.o
635 -M_OBJS := $(O_TARGET)
637 -ifeq ($(CONFIG_SYSCTL),y)
638 -O_OBJS += sysctl_net_bridge.o
640 +O_TARGET := bridge.o
641 +O_OBJS := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
642 + br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \
643 + br_stp_if.o br_stp_timer.o
644 +M_OBJS := $(O_TARGET)
646 include $(TOPDIR)/Rules.make
650 diff -urN linux-2.2.20/net/bridge/br.c linux-2.2.20br/net/bridge/br.c
651 --- linux-2.2.20/net/bridge/br.c Sun Mar 25 18:31:13 2001
652 +++ linux-2.2.20br/net/bridge/br.c Mon Dec 10 16:25:36 2001
655 - * Linux NET3 Bridge Support
657 + * Linux ethernet bridge
659 - * Originally by John Hayes (Network Plumbing).
660 - * Minor hacks to get it to run with 1.3.x by Alan Cox <Alan.Cox@linux.org>
661 - * More hacks to be able to switch protocols on and off by Christoph Lameter
662 - * <clameter@debian.org>
663 - * Software and more Documentation for the bridge is available from ftp.debian.org
664 - * in the bridgex package
666 + * Lennert Buytenhek <buytenh@gnu.org>
670 * This program is free software; you can redistribute it and/or
671 * modify it under the terms of the GNU General Public License
672 * as published by the Free Software Foundation; either version
673 * 2 of the License, or (at your option) any later version.
676 - * Yury Shevchuk : Bridge with non bridging ports
677 - * Jean-Rene Peulve: jr.peulve@aix.pacwan.net Jan/Feb 98
678 - * support Linux 2.0
679 - * Handle Receive config bpdu
680 - * kick mark_bh to send Spanning Tree pdus
681 - * bridgeId comparison using htonl()
682 - * make STP interoperable with other vendors
683 - * wrong test in root_selection()
684 - * add more STP debug info
685 - * some performance improvments
686 - * do not clear bridgeId.mac while setting priority
687 - * do not reset port priority when starting bridge
688 - * make port priority from user value and port number
689 - * maintains user port state out of device state
690 - * broacast/multicast storm limitation
691 - * forwarding statistics
692 - * stop br_tick when bridge is turn off
693 - * add local MACs in avl_tree to forward up stack
694 - * fake receive on right port for IP/ARP
695 - * ages tree even if packet does not cross bridge
696 - * add BRCMD_DISPLAY_FDB (ioctl for now)
698 - * Alan Cox: Merged Jean-Rene's stuff, reformatted stuff a bit
699 - * so blame me first if its broken ;)
701 - * Robert Pintarelli: fixed bug in bpdu time values
703 - * Matthew Grant: start ports disabled.
704 - * auto-promiscuous mode on port enable/disable
705 - * fleshed out interface event handling, interfaces
706 - * now register with bridge on module load as well as ifup
707 - * port control ioctls with ifindex support
708 - * brg0 logical ethernet interface
709 - * reworked brcfg to take interface arguments
710 - * added support for changing the hardware address
711 - * generally made bridge a lot more usable.
714 - * Use a netlink notifier so a daemon can maintain the bridge
715 - * port group (could we also do multiple groups ????).
716 - * A nice /proc file interface.
717 - * Put the path costs in the port info and devices.
718 - * Put the bridge port number in the device structure for speed.
719 - * Bridge SNMP stats.
723 -#include <linux/config.h>
724 -#include <linux/module.h>
725 -#include <linux/errno.h>
726 -#include <linux/types.h>
727 -#include <linux/socket.h>
728 -#include <linux/in.h>
730 +#include <linux/module.h>
731 #include <linux/kernel.h>
732 -#include <linux/sched.h>
733 -#include <linux/timer.h>
734 -#include <linux/malloc.h>
735 -#include <linux/string.h>
736 -#include <linux/net.h>
737 -#include <linux/inet.h>
738 +#include <linux/miscdevice.h>
739 #include <linux/netdevice.h>
740 -#include <linux/inetdevice.h>
741 #include <linux/etherdevice.h>
742 -#include <linux/skbuff.h>
743 -#include <linux/if_arp.h>
744 -#include <linux/ip.h>
745 -#include <linux/version.h>
746 #include <linux/init.h>
747 +#include <linux/if_bridge.h>
748 #include <asm/uaccess.h>
749 -#include <asm/system.h>
750 -#include <linux/rtnetlink.h>
752 -#include <linux/proc_fs.h>
753 -#include <linux/delay.h>
756 -#define min(a, b) (((a) <= (b)) ? (a) : (b))
759 -static void transmit_config(int port_no);
760 -static int root_bridge(void);
761 -static int supersedes_port_info(int port_no, Config_bpdu *config);
762 -static void record_config_information(int port_no, Config_bpdu *config);
763 -static void record_config_timeout_values(Config_bpdu *config);
764 -static void config_bpdu_generation(void);
765 -static int designated_port(int port_no);
766 -static void reply(int port_no);
767 -static void transmit_tcn(void);
768 -static void configuration_update(void);
769 -static void root_selection(void);
770 -static void designated_port_selection(void);
771 -static void become_designated_port(int port_no);
772 -static void port_state_selection(void);
773 -static void make_forwarding(int port_no);
774 -static void topology_change_detection(void);
775 -static void topology_change_acknowledged(void);
776 -static void acknowledge_topology_change(int port_no);
777 -static void make_blocking(int port_no);
778 -static void set_port_state(int port_no, int state);
779 -static void received_config_bpdu(int port_no, Config_bpdu *config);
780 -static void received_tcn_bpdu(int port_no, Tcn_bpdu *tcn);
781 -static void hello_timer_expiry(void);
782 -static void message_age_timer_expiry(int port_no);
783 -static void forward_delay_timer_expiry(int port_no);
784 -static int designated_for_some_port(void);
785 -static void tcn_timer_expiry(void);
786 -static void topology_change_timer_expiry(void);
787 -static void hold_timer_expiry(int port_no);
788 -static void br_init_port(int port_no);
789 -static void enable_port(int port_no);
790 -static void disable_port(int port_no);
791 -static void set_bridge_priority(bridge_id_t *new_bridge_id);
792 -static void set_port_priority(int port_no);
793 -static void set_path_cost(int port_no, unsigned short path_cost);
794 -static void start_hello_timer(void);
795 -static void stop_hello_timer(void);
796 -static int hello_timer_expired(void);
797 -static void start_tcn_timer(void);
798 -static void stop_tcn_timer(void);
799 -static int tcn_timer_expired(void);
800 -static void start_topology_change_timer(void);
801 -static void stop_topology_change_timer(void);
802 -static int topology_change_timer_expired(void);
803 -static void start_message_age_timer(int port_no, unsigned short message_age);
804 -static void stop_message_age_timer(int port_no);
805 -static int message_age_timer_expired(int port_no);
806 -static void start_forward_delay_timer(int port_no);
807 -static void stop_forward_delay_timer(int port_no);
808 -static int forward_delay_timer_expired(int port_no);
809 -static void start_hold_timer(int port_no);
810 -static void stop_hold_timer(int port_no);
811 -static int hold_timer_expired(int port_no);
812 -static int br_device_event(struct notifier_block *dnot, unsigned long event, void *ptr);
813 -static void br_tick(unsigned long arg);
814 -static int br_forward(struct sk_buff *skb, int port); /* 3.7 */
815 -static int br_port_cost(struct device *dev); /* 4.10.2 */
816 -static void br_bpdu(struct sk_buff *skb, int port); /* consumes skb */
817 -static int br_cmp(unsigned int *a, unsigned int *b);
818 -static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu);
819 -static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu);
820 -static int find_port(struct device *dev);
821 -static void br_add_local_mac(unsigned char *mac);
822 -static int br_flood(struct sk_buff *skb, int port);
823 -static int br_drop(struct sk_buff *skb);
824 -static int br_learn(struct sk_buff *skb, int port); /* 3.8 */
825 -static int br_protocol_ok(unsigned short protocol);
826 -static int br_find_port(int ifindex);
827 -static void br_get_ifnames(void);
828 -static int brg_rx(struct sk_buff *skb, int port);
830 -static unsigned char bridge_ula[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
831 -static Bridge_data bridge_info; /* (4.5.3) */
832 -Port_data port_info[All_ports]; /* (4.5.5) */
834 -/* MAG: Maximum port registered - used to speed up flooding and to make
835 - * have a large ports array more efficient
837 -static int max_port_used = 0;
839 -/* JRP: fdb cache 1/port save kmalloc/kfree on every frame */
840 -struct fdb *newfdb[All_ports];
841 -int allocated_fdb_cnt = 0;
843 -/* broacast/multicast storm limitation */
844 -int max_mcast_per_period = MAX_MCAST_PER_PERIOD;
845 -int mcast_hold_time = MCAST_HOLD_TIME;
847 -/* JRP: next two bpdu are copied to skbuff so we need only 1 of each */
848 -static Config_bpdu config_bpdu;
849 -static Tcn_bpdu tcn_bpdu;
850 -static unsigned char port_priority[All_ports];
851 -static unsigned char user_port_state[All_ports];
853 -static Timer hello_timer; /* (4.5.4.1) */
854 -static Timer tcn_timer; /* (4.5.4.2) */
855 -static Timer topology_change_timer; /* (4.5.4.3) */
856 -static Timer message_age_timer[All_ports]; /* (4.5.6.1) */
857 -static Timer forward_delay_timer[All_ports]; /* (4.5.6.2) */
858 -static Timer hold_timer[All_ports]; /* (4.5.6.3) */
860 -/* entries timeout after this many seconds */
861 -unsigned int fdb_aging_time = FDB_TIMEOUT;
863 -struct br_stat br_stats;
864 -#define br_stats_cnt br_stats.packet_cnts
866 -static struct timer_list tl; /* for 1 second timer... */
869 - * the following structure is required so that we receive
870 - * event notifications when network devices are enabled and
871 - * disabled (ifconfig up and down).
873 -static struct notifier_block br_dev_notifier={
881 - * the following data is for the bridge network device
885 - char name[IFNAMSIZ];
887 -static struct brg_if brg_if;
890 - * Here to save linkage? problems
893 -static inline int find_port(struct device *dev)
897 - for (i = One; i <= No_of_ports; i++)
898 - if (port_info[i].dev == dev)
904 - * Implementation of Protocol specific bridging
906 - * The protocols to be bridged or not to be bridged are stored in a hashed array. This is the old type
907 - * of unlinked hash array where one simply takes the next cell if the one the hash function points to
911 -#define BR_PROTOCOL_HASH(x) (x % BR_MAX_PROTOCOLS)
913 -/* Checks if that protocol type is to be bridged */
915 -static int inline br_protocol_ok(unsigned short protocol)
919 - /* See if protocol statistics are to be kept */
920 - if (br_stats.flags & BR_PROT_STATS)
922 - for(x=0;x<BR_MAX_PROT_STATS && br_stats.prot_id[x]!=protocol && br_stats.prot_id[x];x++);
923 - if (x<BR_MAX_PROT_STATS)
925 - br_stats.prot_id[x]=protocol;br_stats.prot_counter[x]++;
929 - for (x=BR_PROTOCOL_HASH(protocol); br_stats.protocols[x]!=0;)
931 - if (br_stats.protocols[x]==protocol)
932 - return !br_stats.policy;
934 - if (x==BR_MAX_PROTOCOLS)
937 - return br_stats.policy;
940 -/* Add a protocol to be handled opposite to the standard policy of the bridge */
942 -static int br_add_exempt_protocol(unsigned short p)
945 - if (p == 0) return -EINVAL;
946 - if (br_stats.exempt_protocols > BR_MAX_PROTOCOLS-2) return -EXFULL;
947 - for (x=BR_PROTOCOL_HASH(p);br_stats.protocols[x]!=0;) {
948 - if (br_stats.protocols[x]==p) return 0; /* Attempt to add the protocol a second time */
950 - if (x==BR_MAX_PROTOCOLS) x=0;
952 - br_stats.protocols[x]=p;
953 - br_stats.exempt_protocols++;
957 -/* Valid Policies are 0=No Protocols bridged 1=Bridge all protocols */
958 -static int br_set_policy(int policy)
960 - if (policy>1) return -EINVAL;
961 - br_stats.policy=policy;
962 - /* Policy change means initializing the exempt table */
963 - memset(br_stats.protocols,0,sizeof(br_stats.protocols));
964 - br_stats.exempt_protocols = 0;
969 -/** Elements of Procedure (4.6) **/
972 - * this section of code was graciously borrowed from the IEEE 802.1d
973 - * specification section 4.9.1 starting on pg 69. It has been
974 - * modified somewhat to fit within our framework and structure. It
975 - * implements the spanning tree algorithm that is the heart of the
976 - * 802.1d bridging protocol.
979 -static void transmit_config(int port_no) /* (4.6.1) */
981 - if (hold_timer[port_no].active) { /* (4.6.1.3.1) */
982 - port_info[port_no].config_pending = TRUE; /* (4.6.1.3.1) */
983 - } else { /* (4.6.1.3.2) */
984 - config_bpdu.type = BPDU_TYPE_CONFIG;
985 - config_bpdu.root_id = bridge_info.designated_root;
986 - /* (4.6.1.3.2(1)) */
987 - config_bpdu.root_path_cost = bridge_info.root_path_cost;
988 - /* (4.6.1.3.2(2)) */
989 - config_bpdu.bridge_id = bridge_info.bridge_id;
990 - /* (4.6.1.3.2(3)) */
991 - config_bpdu.port_id = port_info[port_no].port_id;
995 - if (root_bridge()) {
996 - config_bpdu.message_age = Zero; /* (4.6.1.3.2(5)) */
998 - config_bpdu.message_age
999 - = (message_age_timer[bridge_info.root_port].value
1000 - + Message_age_increment) << 8; /* (4.6.1.3.2(6)) */
1003 - config_bpdu.max_age = bridge_info.max_age << 8;/* (4.6.1.3.2(7)) */
1004 - config_bpdu.hello_time = bridge_info.hello_time << 8;
1005 - config_bpdu.forward_delay = bridge_info.forward_delay << 8;
1006 - config_bpdu.top_change_ack =
1007 - port_info[port_no].top_change_ack;
1008 - /* (4.6.1.3.2(8)) */
1009 - port_info[port_no].top_change_ack = 0;
1011 - config_bpdu.top_change =
1012 - bridge_info.top_change; /* (4.6.1.3.2(9)) */
1014 - send_config_bpdu(port_no, &config_bpdu);
1015 - port_info[port_no].config_pending = FALSE; /* (4.6.1.3.2(10)) */
1016 - start_hold_timer(port_no); /* (4.6.1.3.2(11)) */
1018 -/* JRP: we want the frame to be xmitted even if no other traffic.
1019 - * net_bh() will do a dev_transmit() that kicks all devices
1023 +#include "br_private.h"
1025 -static int root_bridge(void)
1026 +void br_dec_use_count()
1028 - return (br_cmp(bridge_info.designated_root.BRIDGE_ID,
1029 - bridge_info.bridge_id.BRIDGE_ID)?FALSE:TRUE);
1030 + MOD_DEC_USE_COUNT;
1033 -static int supersedes_port_info(int port_no, Config_bpdu *config) /* (4.6.2.2) */
1034 +void br_inc_use_count()
1037 - (br_cmp(config->root_id.BRIDGE_ID,
1038 - port_info[port_no].designated_root.BRIDGE_ID) < 0) /* (4.6.2.2.1) */
1040 - ((br_cmp(config->root_id.BRIDGE_ID,
1041 - port_info[port_no].designated_root.BRIDGE_ID) == 0
1044 - ((config->root_path_cost
1045 - < port_info[port_no].designated_cost /* (4.6.2.2.2) */
1048 - ((config->root_path_cost
1049 - == port_info[port_no].designated_cost
1052 - ((br_cmp(config->bridge_id.BRIDGE_ID,
1053 - port_info[port_no].designated_bridge.BRIDGE_ID) < 0 /* (4.6.2.2.3) */
1056 - ((br_cmp(config->bridge_id.BRIDGE_ID,
1057 - port_info[port_no].designated_bridge.BRIDGE_ID) == 0
1058 - ) /* (4.6.2.2.4) */
1060 - ((br_cmp(config->bridge_id.BRIDGE_ID,
1061 - bridge_info.bridge_id.BRIDGE_ID) != 0
1062 - ) /* (4.6.2.2.4(1)) */
1064 - (config->port_id <=
1065 - port_info[port_no].designated_port
1066 - ) /* (4.6.2.2.4(2)) */
1069 + MOD_INC_USE_COUNT;
1072 -static void record_config_information(int port_no, Config_bpdu *config) /* (4.6.2) */
1073 +__initfunc(int br_init(void))
1075 - port_info[port_no].designated_root = config->root_id; /* (4.6.2.3.1) */
1076 - port_info[port_no].designated_cost = config->root_path_cost;
1077 - port_info[port_no].designated_bridge = config->bridge_id;
1078 - port_info[port_no].designated_port = config->port_id;
1079 - start_message_age_timer(port_no, config->message_age); /* (4.6.2.3.2) */
1082 -static void record_config_timeout_values(Config_bpdu *config) /* (4.6.3) */
1084 - bridge_info.max_age = config->max_age >> 8; /* (4.6.3.3) */
1085 - bridge_info.hello_time = config->hello_time >> 8;
1086 - bridge_info.forward_delay = config->forward_delay >> 8;
1087 - bridge_info.top_change = config->top_change >> 8;
1090 -static void config_bpdu_generation(void)
1093 - for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.6.4.3) */
1094 - if (designated_port(port_no) /* (4.6.4.3) */
1096 - (port_info[port_no].state != Disabled)
1098 - transmit_config(port_no); /* (4.6.4.3) */
1103 -static int designated_port(int port_no)
1105 - return ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1106 - bridge_info.bridge_id.BRIDGE_ID) == 0
1109 - (port_info[port_no].designated_port
1110 - == port_info[port_no].port_id
1115 -static void reply(int port_no) /* (4.6.5) */
1117 - transmit_config(port_no); /* (4.6.5.3) */
1120 -static void transmit_tcn(void)
1124 - port_no = bridge_info.root_port;
1125 - tcn_bpdu.type = BPDU_TYPE_TOPO_CHANGE;
1126 - send_tcn_bpdu(port_no, &tcn_bpdu); /* (4.6.6.3) */
1129 -static void configuration_update(void) /* (4.6.7) */
1131 - root_selection(); /* (4.6.7.3.1) */
1133 - designated_port_selection(); /* (4.6.7.3.2) */
1137 -static void root_selection(void)
1141 - root_port = No_port;
1142 - for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.6.8.3.1) */
1143 - if (((!designated_port(port_no))
1145 - (port_info[port_no].state != Disabled)
1147 - (br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1148 - bridge_info.bridge_id.BRIDGE_ID) < 0)
1151 - ((root_port == No_port)
1153 - (br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1154 - port_info[root_port].designated_root.BRIDGE_ID) < 0
1157 - ((br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1158 - port_info[root_port].designated_root.BRIDGE_ID) == 0
1161 - (((port_info[port_no].designated_cost
1162 - + port_info[port_no].path_cost
1165 - (port_info[root_port].designated_cost
1166 - + port_info[root_port].path_cost
1167 - ) /* (4.6.8.3.1(2)) */
1170 - (((port_info[port_no].designated_cost
1171 - + port_info[port_no].path_cost
1174 - (port_info[root_port].designated_cost
1175 - + port_info[root_port].path_cost
1179 - ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1180 - port_info[root_port].designated_bridge.BRIDGE_ID) < 0
1181 - ) /* (4.6.8.3.1(3)) */
1183 - ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1184 - port_info[root_port].designated_bridge.BRIDGE_ID) == 0
1187 - ((port_info[port_no].designated_port
1188 - < port_info[root_port].designated_port
1189 - ) /* (4.6.8.3.1(4)) */
1191 - ((port_info[port_no].designated_port
1192 -/* JRP: was missing an "=" ! */ == port_info[root_port].designated_port
1195 - (port_info[port_no].port_id
1196 - < port_info[root_port].port_id
1197 - ) /* (4.6.8.3.1(5)) */
1199 - root_port = port_no;
1202 - bridge_info.root_port = root_port; /* (4.6.8.3.1) */
1204 - if (root_port == No_port) { /* (4.6.8.3.2) */
1206 - if (br_stats.flags & BR_DEBUG)
1207 - printk(KERN_DEBUG "root_selection: becomes root\n");
1209 - bridge_info.designated_root = bridge_info.bridge_id;
1210 - /* (4.6.8.3.2(1)) */
1211 - bridge_info.root_path_cost = Zero;/* (4.6.8.3.2(2)) */
1212 - } else { /* (4.6.8.3.3) */
1213 - bridge_info.designated_root = port_info[root_port].designated_root;
1214 - /* (4.6.8.3.3(1)) */
1215 - bridge_info.root_path_cost = (port_info[root_port].designated_cost
1216 - + port_info[root_port].path_cost
1217 - ); /* (4.6.8.3.3(2)) */
1221 -static void designated_port_selection(void)
1225 - for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.6.9.3) */
1226 - if(port_info[port_no].state == Disabled)
1228 - if (designated_port(port_no) /* (4.6.9.3.1) */
1231 - br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1232 - bridge_info.designated_root.BRIDGE_ID) != 0
1235 - (bridge_info.root_path_cost
1236 - < port_info[port_no].designated_cost
1237 - ) /* (4.6.9.3.3) */
1239 - ((bridge_info.root_path_cost
1240 - == port_info[port_no].designated_cost
1243 - ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
1244 - port_info[port_no].designated_bridge.BRIDGE_ID) < 0
1245 - ) /* (4.6.9.3.4) */
1247 - ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
1248 - port_info[port_no].designated_bridge.BRIDGE_ID) == 0
1251 - (port_info[port_no].port_id
1252 - <= port_info[port_no].designated_port
1253 - ) /* (4.6.9.3.5) */
1255 - become_designated_port(port_no); /* (4.6.10.3.2.2) */
1260 -static void become_designated_port(int port_no)
1263 - /* (4.6.10.3.1) */
1264 - port_info[port_no].designated_root = bridge_info.designated_root;
1265 - /* (4.6.10.3.2) */
1266 - port_info[port_no].designated_cost = bridge_info.root_path_cost;
1267 - /* (4.6.10.3.3) */
1268 - port_info[port_no].designated_bridge = bridge_info.bridge_id;
1269 - /* (4.6.10.3.4) */
1270 - port_info[port_no].designated_port = port_info[port_no].port_id;
1272 + printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n");
1274 -static void port_state_selection(void)
1278 - for (port_no = One; port_no <= No_of_ports; port_no++) {
1280 - if(port_info[port_no].state == Disabled)
1282 - if (port_no == bridge_info.root_port) { /* (4.6.11.3.1) */
1283 - state_str = "root";
1284 - port_info[port_no].config_pending = FALSE; /* (4.6.11.3.1(1)) */
1285 - port_info[port_no].top_change_ack = 0;
1286 - make_forwarding(port_no); /* (4.6.11.3.1(2)) */
1287 - } else if (designated_port(port_no)) { /* (4.6.11.3.2) */
1288 - state_str = "designated";
1289 - stop_message_age_timer(port_no); /* (4.6.11.3.2(1)) */
1290 - make_forwarding(port_no); /* (4.6.11.3.2(2)) */
1291 - } else { /* (4.6.11.3.3) */
1292 - state_str = "blocking";
1293 - port_info[port_no].config_pending = FALSE; /* (4.6.11.3.3(1)) */
1294 - port_info[port_no].top_change_ack = 0;
1295 - make_blocking(port_no); /* (4.6.11.3.3(2)) */
1298 - if (br_stats.flags & BR_DEBUG)
1299 - printk(KERN_DEBUG "port_state_selection: becomes %s port %d\n",
1300 - state_str, port_no);
1307 -static void make_forwarding(int port_no)
1309 - if (port_info[port_no].state == Blocking) { /* (4.6.12.3) */
1310 - set_port_state(port_no, Listening); /* (4.6.12.3.1) */
1311 - start_forward_delay_timer(port_no); /* (4.6.12.3.2) */
1315 -static void topology_change_detection(void)
1318 - if ((br_stats.flags & BR_DEBUG)
1319 - && (bridge_info.top_change_detected == 0))
1320 - printk(KERN_DEBUG "topology_change_detected\n");
1322 - if (root_bridge()) { /* (4.6.14.3.1) */
1323 - bridge_info.top_change = 1;
1324 - start_topology_change_timer(); /* (4.6.14.3.1(2)) */
1325 - } else if (!(bridge_info.top_change_detected)) {
1326 - transmit_tcn(); /* (4.6.14.3.2(1)) */
1327 - start_tcn_timer(); /* (4.6.14.3.2(2)) */
1329 - bridge_info.top_change_detected = 1; /* (4.6.14.3.3) */
1332 -static void topology_change_acknowledged(void)
1335 - if (br_stats.flags & BR_DEBUG)
1336 - printk(KERN_DEBUG "topology_change_acked\n");
1338 - bridge_info.top_change_detected = 0; /* (4.6.15.3.1) */
1339 - stop_tcn_timer(); /* (4.6.15.3.2) */
1342 -static void acknowledge_topology_change(int port_no)
1344 - port_info[port_no].top_change_ack = 1;
1345 - transmit_config(port_no); /* (4.6.16.3.2) */
1348 -static void make_blocking(int port_no) /* (4.6.13) */
1351 - if ((port_info[port_no].state != Disabled)
1353 - (port_info[port_no].state != Blocking)
1356 - if ((port_info[port_no].state == Forwarding)
1358 - (port_info[port_no].state == Learning)
1360 - topology_change_detection(); /* (4.6.13.3.1) */
1361 - /* (4.6.14.2.3) */
1363 - set_port_state(port_no, Blocking);/* (4.6.13.3.2) */
1364 - stop_forward_delay_timer(port_no);/* (4.6.13.3.3) */
1368 -static void set_port_state(int port_no, int state)
1370 - port_info[port_no].state = state;
1373 -static void received_config_bpdu(int port_no, Config_bpdu *config) /* (4.7.1) */
1377 - root = root_bridge();
1378 - if (port_info[port_no].state != Disabled) {
1381 - if (br_stats.flags & BR_DEBUG)
1382 - printk(KERN_DEBUG "received_config_bpdu: port %d\n",
1385 - if (supersedes_port_info(port_no, config)) { /* (4.7.1.1) *//* (4.
1387 - record_config_information(port_no, config); /* (4.7.1.1.1) */
1389 - configuration_update(); /* (4.7.1.1.2) */
1391 - port_state_selection(); /* (4.7.1.1.3) */
1392 - /* (4.6.11.2.1) */
1393 - if ((!root_bridge()) && root) { /* (4.7.1.1.4) */
1394 - stop_hello_timer();
1395 - if (bridge_info.top_change_detected) { /* (4.7.1.1.5 */
1396 - stop_topology_change_timer();
1397 - transmit_tcn(); /* (4.6.6.1) */
1398 - start_tcn_timer();
1401 - if (port_no == bridge_info.root_port) {
1402 - record_config_timeout_values(config); /* (4.7.1.1.6) */
1404 - config_bpdu_generation(); /* (4.6.4.2.1) */
1405 - if (config->top_change_ack) { /* (4.7.1.1.7) */
1406 - topology_change_acknowledged(); /* (4.6.15.2) */
1409 - } else if (designated_port(port_no)) { /* (4.7.1.2) */
1410 - reply(port_no); /* (4.7.1.2.1) */
1416 -static void received_tcn_bpdu(int port_no, Tcn_bpdu *tcn) /* (4.7.2) */
1418 - if (port_info[port_no].state != Disabled) {
1420 - if (br_stats.flags & BR_DEBUG)
1421 - printk(KERN_DEBUG "received_tcn_bpdu: port %d\n",
1424 - if (designated_port(port_no)) {
1425 - topology_change_detection(); /* (4.7.2.1) */
1426 - /* (4.6.14.2.1) */
1427 - acknowledge_topology_change(port_no); /* (4.7.2.2) */
1428 - } /* (4.6.16.2) */
1432 -static void hello_timer_expiry(void)
1434 - config_bpdu_generation(); /* (4.6.4.2.2) */
1435 - start_hello_timer();
1438 -static void message_age_timer_expiry(int port_no) /* (4.7.4) */
1441 - root = root_bridge();
1442 + br_handle_frame_hook = br_handle_frame;
1443 + br_ioctl_hook = br_ioctl_deviceless_stub;
1444 + register_netdevice_notifier(&br_device_notifier);
1447 - if (br_stats.flags & BR_DEBUG)
1448 - printk(KERN_DEBUG "message_age_timer_expiry: port %d\n",
1451 - become_designated_port(port_no); /* (4.7.4.1) */
1452 - /* (4.6.10.2.1) */
1453 - configuration_update(); /* (4.7.4.2) */
1455 - port_state_selection(); /* (4.7.4.3) */
1456 - /* (4.6.11.2.2) */
1457 - if ((root_bridge()) && (!root)) { /* (4.7.4.4) */
1459 - bridge_info.max_age = bridge_info.bridge_max_age; /* (4.7.4.4.1) */
1460 - bridge_info.hello_time = bridge_info.bridge_hello_time;
1461 - bridge_info.forward_delay = bridge_info.bridge_forward_delay;
1462 - topology_change_detection(); /* (4.7.4.4.2) */
1463 - /* (4.6.14.2.4) */
1464 - stop_tcn_timer(); /* (4.7.4.4.3) */
1465 - config_bpdu_generation(); /* (4.7.4.4.4) */
1467 - start_hello_timer();
1471 -static void forward_delay_timer_expiry(int port_no) /* (4.7.5) */
1473 - if (port_info[port_no].state == Listening)
1475 - set_port_state(port_no, Learning); /* (4.7.5.1.1) */
1476 - start_forward_delay_timer(port_no); /* (4.7.5.1.2) */
1478 - else if (port_info[port_no].state == Learning)
1481 - set_port_state(port_no, Forwarding); /* (4.7.5.2.1) */
1482 - if (designated_for_some_port())
1483 - { /* (4.7.5.2.2) */
1484 - topology_change_detection(); /* (4.6.14.2.2) */
1490 -static int designated_for_some_port(void)
1494 - for (port_no = One; port_no <= No_of_ports; port_no++)
1496 - if(port_info[port_no].state == Disabled)
1498 - if ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1499 - bridge_info.bridge_id.BRIDGE_ID) == 0))
1507 -static void tcn_timer_expiry(void)
1509 - transmit_tcn(); /* (4.7.6.1) */
1510 - start_tcn_timer(); /* (4.7.6.2) */
1513 -static void topology_change_timer_expiry(void)
1515 - bridge_info.top_change_detected = 0; /* (4.7.7.1) */
1516 - bridge_info.top_change = 0;
1520 -static void hold_timer_expiry(int port_no) /* (4.7.8) */
1522 - if (port_info[port_no].config_pending)
1524 - transmit_config(port_no); /* (4.7.8.1) */
1525 - } /* (4.6.1.2.3) */
1528 -/* Vova Oksman: Write the buffer (contents of the Bridge table) */
1529 -/* to a PROCfs file */
1530 -int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
1539 - /* first time write the header */
1540 - size = sprintf(buffer,"%s","MAC address Device Flags Age (sec.)\n");
1544 - pbuffer=&buffer[len];
1545 - sprintf_avl(&pbuffer,NULL,&pos,&len,offset,length);
1547 - *start = buffer+len-(pos-offset); /* Start of wanted data */
1548 - len = pos-offset; /* Start slop */
1550 - len = length; /* Ending slop */
1554 -#ifdef CONFIG_PROC_FS
1555 -struct proc_dir_entry proc_net_bridge= {
1556 - PROC_NET_BRIDGE, 6, "bridge",
1557 - S_IFREG | S_IRUGO, 1, 0, 0,
1558 - 0, &proc_net_inode_operations,
1562 -__initfunc(void br_init(void))
1566 - printk(KERN_INFO "NET4: Ethernet Bridge 007 for NET4.0\n");
1568 - /* Set up brg device information */
1569 - bridge_info.instance = 0;
1572 - max_port_used = 0;
1575 - * Form initial topology change time.
1576 - * The topology change timer is only used if this is the root bridge.
1579 - bridge_info.topology_change_time = BRIDGE_MAX_AGE + BRIDGE_FORWARD_DELAY; /* (4.5.3.13) */
1581 - bridge_info.designated_root = bridge_info.bridge_id; /* (4.8.1.1) */
1582 - bridge_info.root_path_cost = Zero;
1583 - bridge_info.root_port = No_port;
1585 - printk(KERN_INFO "br_init: becomes root\n");
1588 - bridge_info.bridge_max_age = BRIDGE_MAX_AGE;
1589 - bridge_info.bridge_hello_time = BRIDGE_HELLO_TIME;
1590 - bridge_info.bridge_forward_delay = BRIDGE_FORWARD_DELAY;
1591 - bridge_info.hold_time = HOLD_TIME;
1593 - bridge_info.max_age = bridge_info.bridge_max_age; /* (4.8.1.2) */
1594 - bridge_info.hello_time = bridge_info.bridge_hello_time;
1595 - bridge_info.forward_delay = bridge_info.bridge_forward_delay;
1597 - bridge_info.top_change_detected = 0;
1598 - bridge_info.top_change = 0;
1600 - stop_topology_change_timer();
1601 - memset(newfdb, 0, sizeof(newfdb));
1602 - for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.8.1.4) */
1603 - /* initial state = Disable */
1604 - user_port_state[port_no] = Disabled;
1605 - port_priority[port_no] = 128;
1606 - br_init_port(port_no);
1607 - disable_port(port_no);
1609 -#if 0 /* JRP: We are not UP ! Wait for the start command */
1610 - port_state_selection(); /* (4.8.1.5) */
1611 - config_bpdu_generation(); /* (4.8.1.6) */
1612 - /* initialize system timer */
1613 - tl.expires = jiffies+HZ; /* 1 second */
1614 - tl.function = br_tick;
1618 - register_netdevice_notifier(&br_dev_notifier);
1619 - br_stats.flags = 0; /*BR_UP | BR_DEBUG*/; /* enable bridge */
1620 - br_stats.policy = BR_ACCEPT; /* Enable bridge to accpet all protocols */
1621 - br_stats.exempt_protocols = 0;
1622 - /*start_hello_timer();*/
1623 - /* Vova Oksman: register the function for the PROCfs "bridge" file */
1624 -#ifdef CONFIG_PROC_FS
1625 - proc_net_register(&proc_net_bridge);
1629 -static inline unsigned short make_port_id(int port_no)
1631 - return (port_priority[port_no] << 8) | port_no;
1634 -static void br_init_port(int port_no)
1636 - port_info[port_no].port_id = make_port_id(port_no);
1637 - become_designated_port(port_no); /* (4.8.1.4.1) */
1638 - set_port_state(port_no, Blocking); /* (4.8.1.4.2) */
1639 - port_info[port_no].top_change_ack = 0;
1640 - port_info[port_no].config_pending = FALSE;/* (4.8.1.4.4) */
1641 - stop_message_age_timer(port_no); /* (4.8.1.4.5) */
1642 - stop_forward_delay_timer(port_no); /* (4.8.1.4.6) */
1643 - stop_hold_timer(port_no); /* (4.8.1.4.7) */
1646 -static void enable_port(int port_no) /* (4.8.2) */
1648 - br_init_port(port_no);
1649 - port_state_selection(); /* (4.8.2.7) */
1652 -static void disable_port(int port_no) /* (4.8.3) */
1656 - root = root_bridge();
1657 - become_designated_port(port_no); /* (4.8.3.1) */
1658 - set_port_state(port_no, Disabled); /* (4.8.3.2) */
1659 - port_info[port_no].top_change_ack = 0;
1660 - port_info[port_no].config_pending = FALSE;/* (4.8.3.4) */
1661 - stop_message_age_timer(port_no); /* (4.8.3.5) */
1662 - stop_forward_delay_timer(port_no); /* (4.8.3.6) */
1663 - configuration_update();
1664 - port_state_selection(); /* (4.8.3.7) */
1665 - if ((root_bridge()) && (!root)) { /* (4.8.3.8) */
1666 - bridge_info.max_age = bridge_info.bridge_max_age; /* (4.8.3.8.1) */
1667 - bridge_info.hello_time = bridge_info.bridge_hello_time;
1668 - bridge_info.forward_delay = bridge_info.bridge_forward_delay;
1669 - topology_change_detection(); /* (4.8.3.8.2) */
1670 - stop_tcn_timer(); /* (4.8.3.8.3) */
1671 - config_bpdu_generation(); /* (4.8.3.8.4) */
1672 - start_hello_timer();
1677 -static void set_bridge_priority(bridge_id_t *new_bridge_id)
1683 - root = root_bridge();
1684 - for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.8.4.2) */
1685 - if(port_info[port_no].state == Disabled)
1687 - if (designated_port(port_no)) {
1688 - port_info[port_no].designated_bridge = *new_bridge_id;
1692 - bridge_info.bridge_id = *new_bridge_id; /* (4.8.4.3) */
1693 - configuration_update(); /* (4.8.4.4) */
1694 - port_state_selection(); /* (4.8.4.5) */
1695 - if ((root_bridge()) && (!root)) { /* (4.8.4.6) */
1696 - bridge_info.max_age = bridge_info.bridge_max_age; /* (4.8.4.6.1) */
1697 - bridge_info.hello_time = bridge_info.bridge_hello_time;
1698 - bridge_info.forward_delay = bridge_info.bridge_forward_delay;
1699 - topology_change_detection(); /* (4.8.4.6.2) */
1700 - stop_tcn_timer(); /* (4.8.4.6.3) */
1701 - config_bpdu_generation(), /* (4.8.4.6.4) */
1702 - start_hello_timer();
1706 -static void set_port_priority(int port_no)
1708 -{int new_port_id = make_port_id(port_no);
1710 - if (designated_port(port_no)) { /* (4.8.5.2) */
1711 - port_info[port_no].designated_port = new_port_id;
1713 - port_info[port_no].port_id = new_port_id; /* (4.8.5.3) */
1714 - if ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
1715 - port_info[port_no].designated_bridge.BRIDGE_ID) == 0
1718 - (port_info[port_no].port_id
1719 - < port_info[port_no].designated_port
1724 - become_designated_port(port_no); /* (4.8.5.4.1) */
1725 - port_state_selection(); /* (4.8.5.4.2) */
1729 -static void set_path_cost(int port_no, unsigned short path_cost)
1732 - port_info[port_no].path_cost = path_cost; /* (4.8.6.1) */
1733 - configuration_update(); /* (4.8.6.2) */
1734 - port_state_selection(); /* (4.8.6.3) */
1737 -static void br_tick(unsigned long arg)
1741 - if(!(br_stats.flags & BR_UP))
1742 - return; /* JRP: we have been shot down */
1744 - if (hello_timer_expired())
1745 - hello_timer_expiry();
1747 - if (tcn_timer_expired())
1748 - tcn_timer_expiry();
1750 - if (topology_change_timer_expired())
1751 - topology_change_timer_expiry();
1753 - for (port_no = One; port_no <= No_of_ports; port_no++)
1755 - if(port_info[port_no].state == Disabled)
1758 - if (forward_delay_timer_expired(port_no))
1759 - forward_delay_timer_expiry(port_no);
1761 - if (message_age_timer_expired(port_no))
1762 - message_age_timer_expiry(port_no);
1764 - if (hold_timer_expired(port_no))
1765 - hold_timer_expiry(port_no);
1767 - /* call me again sometime... */
1768 - tl.expires = jiffies+HZ; /* 1 second */
1769 - tl.function = br_tick;
1773 -static void start_hello_timer(void)
1775 - hello_timer.value = 0;
1776 - hello_timer.active = TRUE;
1779 -static void stop_hello_timer(void)
1781 - hello_timer.active = FALSE;
1784 -static int hello_timer_expired(void)
1786 - if (hello_timer.active && (++hello_timer.value >= bridge_info.hello_time))
1788 - hello_timer.active = FALSE;
1794 -static void start_tcn_timer(void)
1796 - tcn_timer.value = 0;
1797 - tcn_timer.active = TRUE;
1800 -static void stop_tcn_timer(void)
1802 - tcn_timer.active = FALSE;
1805 -static int tcn_timer_expired(void)
1807 - if (tcn_timer.active && (++tcn_timer.value >= bridge_info.bridge_hello_time))
1809 - tcn_timer.active = FALSE;
1816 -static void start_topology_change_timer(void)
1818 - topology_change_timer.value = 0;
1819 - topology_change_timer.active = TRUE;
1822 -static void stop_topology_change_timer(void)
1824 - topology_change_timer.active = FALSE;
1827 -static int topology_change_timer_expired(void)
1829 - if (topology_change_timer.active
1830 - && (++topology_change_timer.value >= bridge_info.topology_change_time ))
1832 - topology_change_timer.active = FALSE;
1838 -static void start_message_age_timer(int port_no, unsigned short message_age)
1840 - message_age_timer[port_no].value = message_age;
1841 - message_age_timer[port_no].active = TRUE;
1844 -static void stop_message_age_timer(int port_no)
1846 - message_age_timer[port_no].active = FALSE;
1849 -static int message_age_timer_expired(int port_no)
1851 - if (message_age_timer[port_no].active && (++message_age_timer[port_no].value >= bridge_info.max_age))
1853 - message_age_timer[port_no].active = FALSE;
1859 -static void start_forward_delay_timer(int port_no)
1861 - forward_delay_timer[port_no].value = 0;
1862 - forward_delay_timer[port_no].active = TRUE;
1865 -static void stop_forward_delay_timer(int port_no)
1867 - forward_delay_timer[port_no].active = FALSE;
1870 -static int forward_delay_timer_expired(int port_no)
1872 - if (forward_delay_timer[port_no].active && (++forward_delay_timer[port_no].value >= bridge_info.forward_delay))
1874 - forward_delay_timer[port_no].active = FALSE;
1880 -static void start_hold_timer(int port_no)
1882 - hold_timer[port_no].value = 0;
1883 - hold_timer[port_no].active = TRUE;
1886 -static void stop_hold_timer(int port_no)
1888 - hold_timer[port_no].active = FALSE;
1891 -static int hold_timer_expired(int port_no)
1893 - if (hold_timer[port_no].active &&
1894 - (++hold_timer[port_no].value >= bridge_info.hold_time))
1896 - hold_timer[port_no].active = FALSE;
1903 -static struct sk_buff *alloc_bridge_skb(int port_no, int pdu_size, char *pdu_name)
1905 - struct sk_buff *skb;
1906 - struct device *dev = port_info[port_no].dev;
1907 - struct ethhdr *eth;
1908 - int size = dev->hard_header_len + BRIDGE_LLC1_HS + pdu_size;
1909 - unsigned char *llc_buffer;
1910 - int pad_size = 60 - size;
1912 - size = 60; /* minimum Ethernet frame - CRC */
1914 - if (port_info[port_no].state == Disabled)
1916 - printk(KERN_DEBUG "send_%s_bpdu: port %i not valid\n", pdu_name, port_no);
1920 - skb = alloc_skb(size, GFP_ATOMIC);
1923 - printk(KERN_DEBUG "send_%s_bpdu: no skb available\n", pdu_name);
1927 - skb->mac.raw = skb->nh.raw = skb_put(skb,size);
1928 - memset(skb->nh.raw + 60 - pad_size, 0xa5, pad_size);
1929 - eth = skb->mac.ethernet;
1930 - memcpy(eth->h_dest, bridge_ula, ETH_ALEN);
1931 - memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
1933 - if (br_stats.flags & BR_DEBUG)
1934 - printk(KERN_DEBUG "send_%s_bpdu: port %i src %02x:%02x:%02x:%02x:%02x:%02x\n",
1942 - eth->h_source[5]);
1944 - /* 8038 is used in older DEC spanning tree protocol which uses a
1945 - * different pdu layout as well
1947 - eth->h_proto = htons(0x8038);
1949 - eth->h_proto = htons(pdu_size + BRIDGE_LLC1_HS);
1951 - skb->nh.raw += skb->dev->hard_header_len;
1952 - llc_buffer = skb->nh.raw;
1953 - *llc_buffer++ = BRIDGE_LLC1_DSAP;
1954 - *llc_buffer++ = BRIDGE_LLC1_SSAP;
1955 - *llc_buffer++ = BRIDGE_LLC1_CTRL;
1956 - /* set nh.raw to where the bpdu starts */
1957 - skb->nh.raw += BRIDGE_LLC1_HS;
1959 - /* mark that we've been here... */
1960 - skb->pkt_bridged = IS_BRIDGED;
1964 -static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
1966 - struct sk_buff *skb;
1969 - * Keep silent when disabled or when STP disabled
1972 - if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
1976 - * Create and send the message
1979 - skb = alloc_bridge_skb(port_no, BRIDGE_BPDU_8021_CONFIG_SIZE,
1984 - /* copy fields before "flags" */
1985 - memcpy(skb->nh.raw, config_bpdu, BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
1987 - /* build the "flags" field */
1988 - *(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) = 0;
1989 - if (config_bpdu->top_change_ack)
1990 - *(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x80;
1991 - if (config_bpdu->top_change)
1992 - *(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x01;
1994 - config_bpdu_hton(config_bpdu);
1995 - /* copy the rest */
1996 - memcpy(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET+1,
1997 - (char*)&(config_bpdu->root_id),
1998 - BRIDGE_BPDU_8021_CONFIG_SIZE-1-BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
2000 - dev_queue_xmit(skb);
2004 -static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
2006 - struct sk_buff *skb;
2009 - * Keep silent when disabled or when STP disabled
2012 - if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
2016 - skb = alloc_bridge_skb(port_no, sizeof(Tcn_bpdu), "tcn");
2020 - memcpy(skb->nh.raw, bpdu, sizeof(Tcn_bpdu));
2022 - dev_queue_xmit(skb);
2026 -static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
2028 - struct device *dev = ptr;
2031 - /* check for loopback devices */
2032 - if (dev->flags & IFF_LOOPBACK)
2033 - return(NOTIFY_DONE);
2035 - if (dev == &brg_if.dev)
2036 - return(NOTIFY_DONE); /* Don't attach the brg device to a port! */
2041 - if (br_stats.flags & BR_DEBUG)
2042 - printk(KERN_DEBUG "br_device_event: NETDEV_DOWN...\n");
2043 - /* find our device and mark it down */
2044 - for (i = One; i <= No_of_ports; i++)
2046 - if (port_info[i].dev == dev)
2049 - return NOTIFY_DONE;
2055 - if (br_stats.flags & BR_DEBUG)
2056 - printk(KERN_DEBUG "br_device_event: NETDEV_UP...\n");
2057 - /* Only handle ethernet ports */
2058 - if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_LOOPBACK)
2059 - return NOTIFY_DONE;
2060 - /* look up an unused device and enable it */
2061 - for (i = One; i <= No_of_ports; i++)
2063 - if (port_info[i].dev == NULL || port_info[i].dev == dev)
2065 - port_info[i].dev = dev;
2066 - port_info[i].port_id = i;
2067 - dev->bridge_port_id = i;
2068 - if( i > max_port_used )
2069 - max_port_used = i;
2070 - /* set bridge addr from 1st device addr */
2071 - if (((htonl(bridge_info.bridge_id.BRIDGE_ID[0])&0xffff) == 0) &&
2072 - (bridge_info.bridge_id.BRIDGE_ID[1] == 0))
2074 - memcpy(bridge_info.bridge_id.BRIDGE_ID_ULA, dev->dev_addr, 6);
2075 - if(bridge_info.bridge_id.BRIDGE_PRIORITY == 0)
2076 - bridge_info.bridge_id.BRIDGE_PRIORITY = htons(32768);
2077 - set_bridge_priority(&bridge_info.bridge_id);
2079 - /* Add local MAC address */
2080 - br_add_local_mac(dev->dev_addr);
2081 - /* Save MAC address for latter change address events */
2082 - memcpy(port_info[i].ifmac.BRIDGE_ID_ULA, dev->dev_addr, 6);
2083 - if((br_stats.flags & BR_UP) &&
2084 - (user_port_state[i] != Disabled))
2086 - /* don't start if user said so */
2088 - set_path_cost(i, br_port_cost(dev));
2089 - set_port_priority(i);
2090 - if (br_stats.flags & BR_STP_DISABLED)
2091 - port_info[i].state = Forwarding;
2093 - make_forwarding(i);
2095 - return NOTIFY_DONE;
2100 - case NETDEV_REGISTER:
2101 - if (br_stats.flags & BR_DEBUG)
2102 - printk(KERN_DEBUG "br_device_event: NETDEV_REGISTER...\n");
2103 - /* printk(KERN_ERR "br_device_event: NETDEV_REGISTER...\n"); */
2104 - /* printk(KERN_ERR "br_device_event: dev->type: 0x%X\n", dev->type); */
2105 - /* Only handle ethernet ports */
2106 - if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_LOOPBACK)
2107 - return NOTIFY_DONE;
2108 - /* printk(KERN_ERR "br_device_event: Looking for port...\n"); */
2109 - for (i = One; i <= No_of_ports; i++)
2111 - if (port_info[i].dev == NULL || port_info[i].dev == dev)
2113 - /* printk(KERN_ERR "br_device_event: Found port %d\n", i); */
2114 - port_info[i].dev = dev;
2115 - port_info[i].port_id = i;
2116 - dev->bridge_port_id = i;
2117 - if( i > max_port_used )
2118 - max_port_used = i;
2119 - /* handle local MAC address minuplations */
2120 - br_add_local_mac(dev->dev_addr);
2121 - memcpy(port_info[i].ifmac.BRIDGE_ID_ULA, dev->dev_addr, 6);
2122 - return NOTIFY_DONE;
2127 - case NETDEV_UNREGISTER:
2128 - if (br_stats.flags & BR_DEBUG)
2129 - printk(KERN_DEBUG "br_device_event: NETDEV_UNREGISTER...\n");
2130 - i = find_port(dev);
2132 - br_avl_delete_by_port(i);
2133 - memset(port_info[i].ifmac.BRIDGE_ID_ULA, 0, 6);
2134 - port_info[i].dev = NULL;
2137 - case NETDEV_CHANGEADDR:
2138 - if (br_stats.flags & BR_DEBUG)
2139 - printk(KERN_DEBUG "br_device_event: NETDEV_CHANGEADDR...\n");
2140 - i = find_port(dev);
2143 - if (memcmp(port_info[i].ifmac.BRIDGE_ID_ULA, dev->dev_addr, 6) != 0)
2144 - break; /* Don't worry about a change of hardware broadcast address! */
2146 - printk(KERN_CRIT "br_device_event: NETDEV_CHANGEADDR on busy device %s - FIX DRIVER!\n",
2148 - /* return NOTIFY_BAD; It SHOULD be this, but I want to be friendly... */
2149 - return NOTIFY_DONE;
2151 - br_avl_delete_by_port(i);
2152 - memset(port_info[i].ifmac.BRIDGE_ID_ULA, 0, 6);
2155 - return NOTIFY_DONE;
2158 -/* Routine to loop over device list and register
2159 - * interfaces to bridge. Called from last part of net_dev_init just before
2160 - * bootp/rarp interface setup
2162 -void br_spacedevice_register(void)
2164 - struct device *dev;
2165 - for( dev = dev_base; dev != NULL; dev = dev->next)
2167 - br_device_event(NULL, NETDEV_REGISTER, dev);
2172 -/* This is for SPEED in the kernel in net_bh.c */
2174 -int br_call_bridge(struct sk_buff *skb, unsigned short type)
2177 - struct device *dev;
2179 -#if 0 /* Checked first in handle_bridge to save expense of function call */
2180 - if(!(br_stats.flags & BR_UP))
2186 - /* Check for brg0 device
2188 - if (dev == &brg_if.dev)
2191 - port = dev->bridge_port_id;
2196 - /* Sanity - make sure we are not leaping off into fairy space! */
2197 - if ( port < 0 || port > max_port_used || port_info[port].dev != dev) {
2198 - if (net_ratelimit())
2199 - printk(KERN_CRIT "br_call_bridge: device %s has invalid port ID %d!\n",
2201 - dev->bridge_port_id);
2205 - if(user_port_state[port] == Disabled)
2208 - if (!br_protocol_ok(ntohs(type)))
2217 - * following routine is called when a frame is received
2218 - * from an interface, it returns 1 when it consumes the
2219 - * frame, 0 when it does not
2222 -int br_receive_frame(struct sk_buff *skb) /* 3.5 */
2226 - struct ethhdr *eth;
2227 - struct device *dev;
2231 - printk(KERN_CRIT "br_receive_frame: no skb!\n");
2237 - /* Check for brg0 device
2239 - if (dev == &brg_if.dev)
2242 - skb->pkt_bridged = IS_BRIDGED;
2244 - /* check for loopback */
2245 - if (dev->flags & IFF_LOOPBACK)
2249 - port = find_port(dev);
2251 - port = dev->bridge_port_id;
2257 - /* Hand off to brg_rx BEFORE we screw up the skb */
2258 - if(brg_rx(skb, port))
2261 - skb->nh.raw = skb->mac.raw;
2262 - eth = skb->mac.ethernet;
2263 - p = &port_info[port];
2265 - if(p->state == Disabled)
2267 - /* We are here if BR_UP even if this port is Disabled.
2268 - * Send everything up
2270 - skb->pkt_type = PACKET_HOST;
2271 - ++br_stats_cnt.port_disable_up_stack;
2272 - return(0); /* pass frame up our stack (this will */
2273 - /* happen in net_bh() in dev.c) */
2276 - /* Here only if not disable.
2277 - * Remark: only frames going up will show up in NIT (tcpdump)
2280 - /* JRP: even if port is Blocking we need to process the Spanning Tree
2281 - * frames to keep the port in that state
2283 - if (memcmp(eth->h_dest, bridge_ula, ETH_ALEN) == 0)
2285 - ++br_stats_cnt.rcv_bpdu;
2286 - br_bpdu(skb, port); /* br_bpdu consumes skb */
2292 - if((ret = br_learn(skb, port)))
2294 - if (ret > 0) ++br_stats_cnt.drop_multicast;
2295 - return br_drop(skb);
2297 - /* fall through */
2299 - /* fall through */
2301 - ++br_stats_cnt.notForwarding;
2302 - return(br_drop(skb));
2304 - case Disabled: is now handled before this switch !
2305 - Keep the break to allow GCC to use a jmp table.
2309 - if((ret = br_learn(skb, port))) { /* 3.8 */
2310 - if (ret > 0) ++br_stats_cnt.drop_multicast;
2311 - return br_drop(skb);
2313 - /* Now this frame came from one of bridged
2314 - ports this means we should attempt to forward it.
2315 - JRP: local addresses are now in the AVL tree,
2316 - br_forward will pass frames up if it matches
2317 - one of our local MACs or if it is a multicast
2319 - br_forward() will not consume the frame if this
2321 - return(br_forward(skb, port));
2323 - printk(KERN_DEBUG "br_receive_frame: port [%i] unknown state [%i]\n",
2325 - ++br_stats_cnt.unknown_state;
2326 - return(br_drop(skb)); /* discard frame */
2331 - * the following routine is called to transmit frames from the host
2332 - * stack. it returns 1 when it consumes the frame and
2333 - * 0 when it does not.
2336 -int br_tx_frame(struct sk_buff *skb) /* 3.5 */
2339 - struct ethhdr *eth;
2344 - printk(KERN_CRIT "br_tx_frame: no skb!\n");
2350 - printk(KERN_CRIT "br_tx_frame: no dev!\n");
2354 - /* check for loopback */
2355 - if (skb->dev->flags & IFF_LOOPBACK)
2358 - /* if bridging is not enabled on the port we are going to send
2359 - to, we have nothing to do with this frame, hands off */
2360 - if (((port=find_port(skb->dev))==0)||(port_info[port].state==Disabled)) {
2361 - ++br_stats_cnt.port_disable;
2364 - ++br_stats_cnt.port_not_disable;
2365 - skb->mac.raw = skb->nh.raw = skb->data;
2366 - eth = skb->mac.ethernet;
2367 - port = 0; /* an impossible port (locally generated) */
2368 - if (br_stats.flags & BR_DEBUG)
2369 - printk(KERN_DEBUG "br_tx_fr : port %i src %02x:%02x:%02x:%02x:%02x:%02x"
2370 - " dest %02x:%02x:%02x:%02x:%02x:%02x\n",
2384 - return(br_forward(skb, port));
2387 -static void br_add_local_mac(unsigned char *mac)
2390 - f = (struct fdb *)kmalloc(sizeof(struct fdb), GFP_ATOMIC);
2393 - printk(KERN_CRIT "br_add_local_mac: unable to malloc fdb\n");
2396 - f->port = 0; /* dest port == 0 =>local */
2397 - memcpy(f->ula, mac, 6);
2398 - f->timer = 0; /* will not aged anyway */
2399 - f->flags = 0; /* not valid => br_forward special route */
2401 - * add entity to AVL tree. If entity already
2402 - * exists in the tree, update the fields with
2403 - * what we have here.
2405 - if (br_avl_insert(f) != NULL)
2412 -/* Avoid broadcast loop by limiting the number of broacast frames per
2413 - * period. The idea is to limit this per source
2414 - * returns: 0 if limit is not reached
2415 - * 1 if frame should be dropped
2418 -static inline int mcast_quench(struct fdb *f)
2420 - if(f->mcast_count++ == 0) /* first time */
2421 - f->mcast_timer = jiffies;
2423 - if(f->mcast_count > max_mcast_per_period) {
2424 - if(time_after(jiffies, f->mcast_timer + mcast_hold_time))
2425 - f->mcast_count = 0;
2433 - * this routine returns 0 when it learns (or updates) from the
2434 - * frame, and 1 if we must dropped the frame due to multicast
2435 - * limitations, or -1 because of not enough memory.
2437 - * NB Can be called when skb->nh.raw is NOT set up when
2438 - * receiving frames on brg0 via brg_rx
2441 -static int br_learn(struct sk_buff *skb, int port) /* 3.8 */
2443 - struct fdb *f, *oldfdb;
2444 - Port_data *p = &port_info[port];
2445 - struct ethhdr *eth = skb->mac.ethernet;
2447 - /* JRP: no reason to check port state again. We are called by
2448 - * br_receive_frame() only when in Learning or Forwarding
2449 - * Remark: code not realigned yet to keep diffs smaller
2452 - /* don't keep group addresses in the tree */
2453 - if (eth->h_source[0] & 0x01)
2456 - if((f= newfdb[port]) == NULL)
2458 - newfdb[port] = f = (struct fdb *)kmalloc(sizeof(struct fdb), GFP_ATOMIC);
2461 - printk(KERN_WARNING "br_learn: unable to malloc fdb\n");
2462 - return(-1); /* this drops the frame */
2465 - f->port = port; /* source port */
2466 - memcpy(f->ula, eth->h_source, 6);
2467 - f->timer = CURRENT_TIME;
2468 - f->flags = FDB_ENT_VALID;
2470 - * add entity to AVL tree. If entity already
2471 - * exists in the tree, update the fields with
2472 - * what we have here.
2474 - if ((oldfdb = br_avl_insert(f)))
2476 - /* update if !NULL */
2477 - if((eth->h_dest[0] & 0x01) && /* multicast */ mcast_quench(oldfdb))
2481 - newfdb[port] = NULL; /* force kmalloc next time */
2482 - f->mcast_count = 0;
2483 - /* add to head of port chain */
2484 - f->fdb_next = p->fdb;
2486 - allocated_fdb_cnt++;
2490 -/* JRP: always called under br_receive_frame(). No need for Q protection. */
2492 -void requeue_fdb(struct fdb *node, int new_port)
2494 - Port_data *p = &port_info[node->port];
2497 - if(p->fdb == node)
2498 - p->fdb = node->fdb_next;
2503 - for(prev = p->fdb; prev; prev = prev->fdb_next)
2504 - if (prev->fdb_next == node)
2508 - prev->fdb_next = node->fdb_next;
2511 - /* Forget about this update. */
2512 - printk(KERN_ERR "br:requeue_fdb\n");
2517 - node->port = new_port;
2518 - node->fdb_next = port_info[new_port].fdb;
2519 - port_info[new_port].fdb = node;
2523 - * this routine always consumes the frame
2526 -static int br_drop(struct sk_buff *skb)
2533 - * this routine always consumes the frame
2536 -static int br_dev_drop(struct sk_buff *skb)
2538 - dev_kfree_skb(skb);
2543 - * Forward the frame SKB to proper port[s]. PORT is the port that the
2544 - * frame has come from; we will not send the frame back there. PORT == 0
2545 - * means we have been called from br_tx_fr(), not from br_receive_frame().
2547 - * this routine returns 1 if it consumes the frame, 0
2551 -static int br_forward(struct sk_buff *skb, int port) /* 3.7 */
2556 - * flood all ports with frames destined for a group
2557 - * address. If frame came from above, drop it,
2558 - * otherwise it will be handled in br_receive_frame()
2559 - * Multicast frames will also need to be seen
2560 - * by our upper layers.
2562 - if (skb->mac.ethernet->h_dest[0] & 0x01)
2564 - /* group address */
2565 - br_flood(skb, port);
2567 - * External groups are fed out via the normal source
2568 - * This probably should be dropped since the flood will
2569 - * have sent it anyway.
2573 - /* Locally generated */
2574 - ++br_stats_cnt.local_multicast;
2575 - return(br_dev_drop(skb));
2577 - ++br_stats_cnt.forwarded_multicast;
2582 - /* unicast frame, locate port to forward to */
2583 - f = br_avl_find_addr(skb->mac.ethernet->h_dest);
2585 - * Send flood and drop.
2587 - if (!f || !(f->flags & FDB_ENT_VALID))
2589 - if(f && (f->port == 0))
2591 - skb->pkt_type = PACKET_HOST;
2592 - ++br_stats_cnt.forwarded_unicast_up_stack;
2595 - /* not found or too old; flood all ports */
2596 - ++br_stats_cnt.flood_unicast;
2597 - br_flood(skb, port);
2598 - return(br_dev_drop(skb));
2603 - if (f->port!=port && port_info[f->port].state == Forwarding)
2605 - /* Has entry expired? */
2606 - if (f->timer + fdb_aging_time < CURRENT_TIME)
2608 - /* timer expired, invalidate entry */
2609 - f->flags &= ~FDB_ENT_VALID;
2610 - if (br_stats.flags & BR_DEBUG)
2611 - printk(KERN_DEBUG "fdb entry expired...\n");
2613 - * Send flood and drop original
2615 - ++br_stats_cnt.aged_flood_unicast;
2616 - br_flood(skb, port);
2617 - return(br_dev_drop(skb));
2619 - ++br_stats_cnt.forwarded_unicast;
2620 - /* mark that's we've been here... */
2621 - skb->pkt_bridged = IS_BRIDGED;
2623 - /* reset the skb->ip pointer */
2624 - skb->nh.raw = skb->data + ETH_HLEN;
2627 - * Send the buffer out.
2630 - skb->dev=port_info[f->port].dev;
2633 - * We send this still locked
2635 - skb->priority = 1;
2636 - dev_queue_xmit(skb);
2637 - return(1); /* skb has been consumed */
2641 - /* JRP: Needs to aged entry as well, if topology changes
2642 - * the entry would not age. Got this while swapping
2645 - * Has entry expired?
2648 - if (f->timer + fdb_aging_time < CURRENT_TIME)
2650 - /* timer expired, invalidate entry */
2651 - f->flags &= ~FDB_ENT_VALID;
2652 - if (br_stats.flags & BR_DEBUG)
2653 - printk(KERN_DEBUG "fdb entry expired...\n");
2654 - ++br_stats_cnt.drop_same_port_aged;
2656 - else ++br_stats_cnt.drop_same_port;
2658 - * Arrived on the right port, we discard
2660 - return(br_dev_drop(skb));
2666 - * this routine sends a copy of the frame to all forwarding ports
2667 - * with the exception of the port given. This routine never
2668 - * consumes the original frame.
2671 -static int br_flood(struct sk_buff *skb, int port)
2674 - struct sk_buff *nskb;
2676 - for (i = One; i <= No_of_ports; i++)
2678 - if (i == port) /* don't send back where we got it */
2680 - if (i > max_port_used)
2681 - /* Don't go scanning empty port entries */
2683 - if (port_info[i].state == Forwarding)
2685 - nskb = skb_clone(skb, GFP_ATOMIC);
2688 - /* mark that's we've been here... */
2689 - nskb->pkt_bridged = IS_BRIDGED;
2690 - /* Send to each port in turn */
2691 - nskb->dev= port_info[i].dev;
2692 - /* To get here we must have done ARP already,
2693 - or have a received valid MAC header */
2695 -/* printk(KERN_DEBUG "Flood to port %d\n",i);*/
2696 - nskb->nh.raw = nskb->data + ETH_HLEN;
2697 - nskb->priority = 1;
2698 - dev_queue_xmit(nskb);
2705 - * FIXME: This needs to come from the device structs, eg for
2706 - * 10,100,1Gbit ethernet.
2709 -static int br_port_cost(struct device *dev) /* 4.10.2 */
2711 - if (strncmp(dev->name, "lec", 3) == 0) /* ATM Lan Emulation (LANE) */
2712 - return(7); /* 155 Mbs */
2713 - if (strncmp(dev->name, "eth", 3) == 0) /* ethernet */
2715 - if (strncmp(dev->name, "plip",4) == 0) /* plip */
2717 - return(100); /* default */
2721 - * this routine always consumes the skb
2724 -static void br_bpdu(struct sk_buff *skb, int port) /* consumes skb */
2726 - char *bufp = skb->data + ETH_HLEN;
2727 - Tcn_bpdu *bpdu = (Tcn_bpdu *) (bufp + BRIDGE_LLC1_HS);
2728 - Config_bpdu rcv_bpdu;
2730 - if(!(br_stats.flags & BR_STP_DISABLED) &&
2731 - (*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
2732 - (*bufp++ == BRIDGE_LLC1_CTRL) &&
2733 - (bpdu->protocol_id == BRIDGE_BPDU_8021_PROTOCOL_ID) &&
2734 - (bpdu->protocol_version_id == BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID))
2737 - switch (bpdu->type)
2739 - case BPDU_TYPE_CONFIG:
2740 - /* realign for portability to RISC */
2741 - memcpy((char*)&rcv_bpdu, bufp,
2742 - BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
2743 - bufp+= BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET;
2744 - rcv_bpdu.top_change_ack =
2745 - (*bufp & TOPOLOGY_CHANGE_ACK) != 0;
2746 - rcv_bpdu.top_change =
2747 - (*bufp & TOPOLOGY_CHANGE) != 0;
2749 - memcpy((char*)&rcv_bpdu.root_id, bufp,
2750 - BRIDGE_BPDU_8021_CONFIG_SIZE-1
2751 - -BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
2752 - config_bpdu_ntoh(&rcv_bpdu);
2753 - received_config_bpdu(port, &rcv_bpdu);
2756 - case BPDU_TYPE_TOPO_CHANGE:
2757 - received_tcn_bpdu(port, bpdu);
2760 - printk(KERN_DEBUG "br_bpdu: received unknown bpdu, type = %i\n", bpdu->type);
2767 -struct fdb_info *get_fdb_info(int user_buf_size, int *copied,int *notcopied)
2769 - int fdb_size, i, built = 0;
2770 - struct fdb_info *fdbi, *fdbis;
2772 - *copied = user_buf_size - sizeof(struct fdb_info_hdr);
2773 - *copied /= sizeof(struct fdb_info);
2774 - *copied = min(*copied, allocated_fdb_cnt);
2775 - *notcopied = allocated_fdb_cnt - *copied;
2778 - fdb_size = *copied * sizeof(struct fdb_info);
2779 - fdbis = kmalloc(fdb_size, GFP_KERNEL);
2784 - for(i=One; i<=No_of_ports;i++)
2789 - fdb = port_info[i].fdb;
2792 - memcpy(fdbi->ula, fdb->ula, ETH_ALEN);
2793 - fdbi->port = fdb->port;
2794 - fdbi->flags = fdb->flags;
2795 - fdbi->timer = fdb->timer;
2797 - if(++built == *copied)
2802 - fdb = fdb->fdb_next;
2806 - printk(KERN_DEBUG "get_fdb_info: built=%d\n", built);
2811 -/* Fill in interface names in port_info structure
2813 -static void br_get_ifdata(void) {
2816 - for(i=One;i<=No_of_ports; i++) {
2818 - port_info[i].admin_state = user_port_state[i];
2820 - /* memset IS needed. Kernel strncpy does NOT NULL terminate
2821 - * strings when limit reached
2823 - memset(port_info[i].ifname, 0, IFNAMSIZ);
2824 - if( port_info[i].dev == 0 )
2826 - strncpy(port_info[i].ifname, port_info[i].dev->name, IFNAMSIZ-1);
2827 - /* Being paranoid */
2828 - port_info[i].ifname[IFNAMSIZ-1] = '\0';
2832 -/* Given an interface index, loop over port array to see if configured. If
2833 - so, return port number, otherwise error */
2834 -static int br_find_port(int ifindex)
2838 - for(i=1; i <= No_of_ports; i++) {
2839 - if (port_info[i].dev == 0)
2841 - if (port_info[i].dev->ifindex == ifindex)
2845 - return -EUNATCH; /* Tell me if this is incorrect error code for this case */
2849 -int br_ioctl(unsigned int cmd, void *arg)
2851 - int err, i, ifflags;
2853 - bridge_id_t new_id;
2854 - struct device *dev;
2858 - case SIOCGIFBR: /* get bridging control blocks */
2859 - memcpy(&br_stats.bridge_data, &bridge_info, sizeof(Bridge_data));
2861 - /* Fill in interface names in port_info*/
2864 - br_stats.num_ports = No_of_ports;
2865 - memcpy(&br_stats.port_data, &port_info, sizeof(Port_data)*All_ports);
2867 - err = copy_to_user(arg, &br_stats, sizeof(struct br_stat));
2874 - err = copy_from_user(&bcf, arg, sizeof(struct br_cf));
2877 - if (bcf.cmd != BRCMD_DISPLAY_FDB && !suser())
2881 - case BRCMD_BRIDGE_ENABLE:
2882 - if (br_stats.flags & BR_UP)
2883 - return(-EALREADY);
2884 - printk(KERN_DEBUG "br: enabling bridging function\n");
2885 - br_stats.flags |= BR_UP; /* enable bridge */
2886 - for(i=One;i<=No_of_ports; i++)
2888 - /* don't start if user said so */
2889 - if((user_port_state[i] != Disabled)
2890 - && port_info[i].dev)
2895 - port_state_selection(); /* (4.8.1.5) */
2896 - if (br_stats.flags & BR_STP_DISABLED)
2897 - for(i=One;i<=No_of_ports; i++)
2898 - if((user_port_state[i] != Disabled) && port_info[i].dev)
2899 - port_info[i].state = Forwarding;
2900 - config_bpdu_generation(); /* (4.8.1.6) */
2901 - /* initialize system timer */
2902 - tl.expires = jiffies+HZ; /* 1 second */
2903 - tl.function = br_tick;
2905 - start_hello_timer();
2907 - case BRCMD_BRIDGE_DISABLE:
2908 - if (!(br_stats.flags & BR_UP))
2909 - return(-EALREADY);
2910 - printk(KERN_DEBUG "br: disabling bridging function\n");
2911 - br_stats.flags &= ~BR_UP; /* disable bridge */
2912 - stop_hello_timer();
2913 - for (i = One; i <= No_of_ports; i++)
2914 - if (port_info[i].state != Disabled)
2917 - case BRCMD_TOGGLE_STP:
2918 - printk(KERN_DEBUG "br: %s spanning tree protcol\n",
2919 - (br_stats.flags & BR_STP_DISABLED) ? "enabling" : "disabling");
2920 - if (br_stats.flags & BR_STP_DISABLED) { /* enable STP */
2921 - for(i=One;i<=No_of_ports; i++)
2922 - if((user_port_state[i] != Disabled) && port_info[i].dev)
2924 - } else { /* STP was enabled, now disable it */
2925 - for (i = One; i <= No_of_ports; i++)
2926 - if (port_info[i].state != Disabled && port_info[i].dev)
2927 - port_info[i].state = Forwarding;
2929 - br_stats.flags ^= BR_STP_DISABLED;
2931 - case BRCMD_IF_ENABLE:
2932 - bcf.arg1 = br_find_port(bcf.arg1);
2933 - if ((signed)bcf.arg1 < 0)
2935 - case BRCMD_PORT_ENABLE:
2936 - if (port_info[bcf.arg1].dev == 0)
2938 - if (user_port_state[bcf.arg1] != Disabled)
2939 - return(-EALREADY);
2940 - printk(KERN_DEBUG "br: enabling port %i\n",bcf.arg1);
2941 - dev = port_info[bcf.arg1].dev;
2942 - ifflags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
2943 - |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
2944 - dev_change_flags(dev, ifflags|IFF_PROMISC);
2945 - user_port_state[bcf.arg1] = ~Disabled;
2946 - if(br_stats.flags & BR_UP)
2947 - enable_port(bcf.arg1);
2949 - case BRCMD_IF_DISABLE:
2950 - bcf.arg1 = br_find_port(bcf.arg1);
2951 - if ((signed)bcf.arg1 < 0)
2953 - case BRCMD_PORT_DISABLE:
2954 - if (port_info[bcf.arg1].dev == 0)
2956 - if (user_port_state[bcf.arg1] == Disabled)
2957 - return(-EALREADY);
2958 - printk(KERN_DEBUG "br: disabling port %i\n",bcf.arg1);
2959 - user_port_state[bcf.arg1] = Disabled;
2960 - if(br_stats.flags & BR_UP)
2961 - disable_port(bcf.arg1);
2962 - dev = port_info[bcf.arg1].dev;
2963 - ifflags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
2964 - |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
2965 - dev_change_flags(port_info[bcf.arg1].dev, ifflags & ~IFF_PROMISC);
2967 - case BRCMD_SET_BRIDGE_PRIORITY:
2968 - new_id = bridge_info.bridge_id;
2969 - new_id.BRIDGE_PRIORITY = htons(bcf.arg1);
2970 - set_bridge_priority(&new_id);
2972 - case BRCMD_SET_IF_PRIORITY:
2973 - bcf.arg1 = br_find_port(bcf.arg1);
2974 - if ((signed)bcf.arg1 < 0)
2976 - case BRCMD_SET_PORT_PRIORITY:
2977 - if((port_info[bcf.arg1].dev == 0)
2978 - || (bcf.arg2 & ~0xff))
2980 - port_priority[bcf.arg1] = bcf.arg2;
2981 - set_port_priority(bcf.arg1);
2983 - case BRCMD_SET_IF_PATH_COST:
2984 - bcf.arg1 = br_find_port(bcf.arg1);
2985 - if ((signed)bcf.arg1 < 0)
2987 - case BRCMD_SET_PATH_COST:
2988 - if (port_info[bcf.arg1].dev == 0)
2990 - set_path_cost(bcf.arg1, bcf.arg2);
2992 - case BRCMD_ENABLE_DEBUG:
2993 - br_stats.flags |= BR_DEBUG;
2995 - case BRCMD_DISABLE_DEBUG:
2996 - br_stats.flags &= ~BR_DEBUG;
2998 - case BRCMD_SET_POLICY:
2999 - return br_set_policy(bcf.arg1);
3000 - case BRCMD_EXEMPT_PROTOCOL:
3001 - return br_add_exempt_protocol(bcf.arg1);
3002 - case BRCMD_ENABLE_PROT_STATS:
3003 - br_stats.flags |= BR_PROT_STATS;
3005 - case BRCMD_DISABLE_PROT_STATS:
3006 - br_stats.flags &= ~BR_PROT_STATS;
3008 - case BRCMD_ZERO_PROT_STATS:
3009 - memset(&br_stats.prot_id,0,sizeof(br_stats.prot_id));
3010 - memset(&br_stats.prot_counter,0,sizeof(br_stats.prot_counter));
3012 - case BRCMD_DISPLAY_FDB:
3014 - struct fdb_info_hdr *user_buf = (void*) bcf.arg1;
3015 - struct fdb_info *u_fdbs, *fdbis;
3016 - int copied, notcopied;
3017 - u32 j = CURRENT_TIME;
3019 - if(bcf.arg2<sizeof(struct fdb_info_hdr))
3021 - put_user(j, &user_buf->cmd_time);
3022 - if(allocated_fdb_cnt == 0)
3024 - put_user(0, &user_buf->copied);
3025 - put_user(0, &user_buf->not_copied);
3028 - fdbis = get_fdb_info(bcf.arg2, &copied, ¬copied);
3029 - put_user(copied, &user_buf->copied);
3030 - put_user(notcopied, &user_buf->not_copied);
3033 - u_fdbs = (struct fdb_info *) (user_buf+1);
3034 - err = copy_to_user(u_fdbs, fdbis, copied*sizeof(struct fdb_info));
3053 -static int br_cmp(unsigned int *a, unsigned int *b)
3056 - for (i=0; i<2; i++)
3058 - /* JRP: compares prty then MAC address in memory byte order
3059 - * OK optimizer does htonl() only once per long !
3061 - if (htonl(a[i]) < htonl(b[i]))
3063 - if (htonl(a[i]) > htonl(b[i]))
3072 -/* --------------------------------------------------------------------------------
3075 - * Bridge network device here for future modularization - device structures
3076 - * must be 'static' inside bridge instance
3077 - * Modelled after sch_teql.c
3084 - * Index to functions.
3087 -int brg_probe(struct device *dev);
3088 -static int brg_open(struct device *dev);
3089 -static int brg_start_xmit(struct sk_buff *skb, struct device *dev);
3090 -static int brg_close(struct device *dev);
3091 -static struct net_device_stats *brg_get_stats(struct device *dev);
3092 -static void brg_set_multicast_list(struct device *dev);
3095 - * Board-specific info in dev->priv.
3101 - struct net_device_stats stats;
3108 - * To call this a probe is a bit misleading, however for real
3109 - * hardware it would have to check what was present.
3112 -__initfunc(int brg_probe(struct device *dev))
3114 - unsigned int bogomips;
3115 - struct timeval utime;
3117 - printk(KERN_INFO "%s: network interface for Ethernet Bridge 007/NET4.0\n", dev->name);
3120 - * Initialize the device structure.
3123 - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
3124 - if (dev->priv == NULL)
3126 - memset(dev->priv, 0, sizeof(struct net_local));
3128 - /* Set up MAC address based on BogoMIPs figure for first CPU and time
3130 - bogomips = (loops_per_jiffy+2500)/500000/HZ ;
3131 - get_fast_time(&utime);
3133 - /* Ummmm.... YES! */
3134 - dev->dev_addr[0] = '\xFE';
3135 - dev->dev_addr[1] = '\xFD';
3136 - dev->dev_addr[2] = (bridge_info.instance & 0x0F) << 4;
3137 - dev->dev_addr[2] |= ((utime.tv_sec & 0x000F0000) >> 16);
3138 - dev->dev_addr[3] = bogomips & 0xFF;
3139 - dev->dev_addr[4] = (utime.tv_sec & 0x0000FF00) >> 8;
3140 - dev->dev_addr[5] = (utime.tv_sec & 0x000000FF);
3142 - printk(KERN_INFO "%s: generated MAC address %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
3149 - dev->dev_addr[5]);
3152 - printk(KERN_INFO "%s: attached to bridge instance %lu\n", dev->name, dev->base_addr);
3155 - * The brg specific entries in the device structure.
3158 - dev->open = brg_open;
3159 - dev->hard_start_xmit = brg_start_xmit;
3160 - dev->stop = brg_close;
3161 - dev->get_stats = brg_get_stats;
3162 - dev->set_multicast_list = brg_set_multicast_list;
3165 - * Setup the generic properties
3169 - dev->tx_queue_len = 0;
3174 - * Open/initialize the board.
3177 -static int brg_open(struct device *dev)
3179 - if (br_stats.flags & BR_DEBUG)
3180 - printk(KERN_DEBUG "%s: Doing brg_open()...", dev->name);
3182 - if (memcmp(dev->dev_addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
3190 -static unsigned brg_mc_hash(__u8 *dest)
3199 - return 1U << (idx&0x1F);
3202 -static void brg_set_multicast_list(struct device *dev)
3204 - unsigned groups = ~0;
3205 - struct net_local *lp = (struct net_local *)dev->priv;
3207 - if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
3208 - struct dev_mc_list *dmi;
3210 - groups = brg_mc_hash(dev->broadcast);
3212 - for (dmi=dev->mc_list; dmi; dmi=dmi->next) {
3213 - if (dmi->dmi_addrlen != 6)
3215 - groups |= brg_mc_hash(dmi->dmi_addr);
3218 - lp->groups = groups;
3222 - * We transmit by throwing the packet at the bridge.
3225 -static int brg_start_xmit(struct sk_buff *skb, struct device *dev)
3227 - struct net_local *lp = (struct net_local *)dev->priv;
3228 - struct ethhdr *eth = (struct ethhdr*)skb->data;
3231 - /* Deal with the bridge being disabled */
3232 - if(!(br_stats.flags & BR_UP)) {
3234 - /* lp->stats.tx_errors++; */ /* this condition is NOT an error */
3235 - /* or this (implied by RFC 2233) */
3236 - lp->stats.tx_dropped++;
3237 - dev_kfree_skb(skb);
3241 - lp->stats.tx_bytes+=skb->len;
3242 - lp->stats.tx_packets++;
3245 - ++br_stats_cnt.port_not_disable;
3247 - skb->mac.raw = skb->nh.raw = skb->data;
3248 - eth = skb->mac.ethernet;
3249 - port = 0; /* an impossible port (locally generated) */
3251 - if (br_stats.flags & BR_DEBUG)
3252 - printk(KERN_DEBUG "%s: brg_start_xmit - src %02x:%02x:%02x:%02x:%02x:%02x"
3253 - " dest %02x:%02x:%02x:%02x:%02x:%02x\n",
3268 - /* Forward the packet ! */
3269 - if(br_forward(skb, port))
3272 - /* Throw packet initially */
3273 - dev_kfree_skb(skb);
3279 - * The typical workload of the driver:
3280 - * Handle the ether interface interrupts.
3282 - * (In this case handle the packets posted from the bridge)
3285 -static int brg_rx(struct sk_buff *skb, int port)
3287 - struct device *dev = &brg_if.dev;
3288 - struct net_local *lp = (struct net_local *)dev->priv;
3289 - struct ethhdr *eth = (struct ethhdr*)(skb->data);
3290 - int len = skb->len;
3293 - if (br_stats.flags & BR_DEBUG)
3294 - printk(KERN_DEBUG "%s: brg_rx()\n", dev->name);
3296 - /* Get out of here if the bridge interface is not up
3298 - if(!(dev->flags & IFF_UP))
3301 - /* Check that the port that this thing came off is in the forwarding state
3302 - * We sould only listen to the same address scope we will transmit to.
3304 - if(port_info[port].state != Forwarding)
3307 - /* Is this for us? - broadcast/mulitcast/promiscuous packets need cloning,
3308 - * with uni-cast we eat the packet
3311 - if (dev->flags & IFF_PROMISC) {
3314 - else if (eth->h_dest[0]&1) {
3315 - if (!(dev->flags&(IFF_ALLMULTI))
3316 - && !(brg_mc_hash(eth->h_dest)&lp->groups))
3320 - else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN) != 0) {
3324 - /* Clone things here - we want to be transparent before we check packet data
3328 - struct sk_buff *skb2 = skb;
3329 - skb = skb_clone(skb2, GFP_ATOMIC);
3330 - if (skb == NULL) {
3336 - /* Learn source addresses for unicast non-promiscuous
3339 - if(br_learn(skb, port)) {
3340 - return br_drop(skb);
3344 - /* Check packet length
3347 - printk(KERN_DEBUG "%s : rx len = %d\n", dev->name, len);
3352 - if (br_stats.flags & BR_DEBUG)
3353 - printk(KERN_DEBUG "%s: brg_rx - src %02x:%02x:%02x:%02x:%02x:%02x"
3354 - " dest %02x:%02x:%02x:%02x:%02x:%02x\n",
3370 - skb->pkt_type = PACKET_HOST;
3372 - skb->protocol=eth_type_trans(skb,dev);
3373 - memset(skb->cb, 0, sizeof(skb->cb));
3374 - lp->stats.rx_packets++;
3375 - lp->stats.rx_bytes+=len;
3380 -static int brg_close(struct device *dev)
3382 - if (br_stats.flags & BR_DEBUG)
3383 - printk(KERN_DEBUG "%s: Shutting down.\n", dev->name);
3391 -static struct net_device_stats *brg_get_stats(struct device *dev)
3393 - struct net_local *lp = (struct net_local *)dev->priv;
3394 - return &lp->stats;
3403 -__initfunc(int brg_init(void))
3404 +int init_module(void)
3408 - memset(&brg_if, 0, sizeof(brg_if));
3412 - brg_if.dev.base_addr = bridge_info.instance;
3413 - sprintf (brg_if.name, "brg%d", bridge_info.instance);
3414 - brg_if.dev.name = (void*)&brg_if.name;
3415 - if(dev_get(brg_if.name)) {
3416 - printk(KERN_INFO "%s already loaded.\n", brg_if.name);
3419 - brg_if.dev.init = brg_probe;
3421 - err = register_netdevice(&brg_if.dev);
3428 -#if 0 /* Its here if we ever need it... */
3431 void cleanup_module(void)
3435 - * Unregister the device
3438 - unregister_netdevice(&the_master.dev);
3442 - * Free up the private structure.
3445 - kfree(brg_if.dev.priv);
3446 - brg_if.dev.priv = NULL; /* gets re-allocated by brg_probe */
3447 + unregister_netdevice_notifier(&br_device_notifier);
3448 + br_ioctl_hook = NULL;
3449 + br_handle_frame_hook = NULL;
3453 -#endif /* MODULE */
3456 diff -urN linux-2.2.20/net/bridge/br_device.c linux-2.2.20br/net/bridge/br_device.c
3457 --- linux-2.2.20/net/bridge/br_device.c Thu Jan 1 01:00:00 1970
3458 +++ linux-2.2.20br/net/bridge/br_device.c Mon Dec 10 16:25:58 2001
3461 + * Device handling code
3462 + * Linux ethernet bridge
3465 + * Lennert Buytenhek <buytenh@gnu.org>
3469 + * This program is free software; you can redistribute it and/or
3470 + * modify it under the terms of the GNU General Public License
3471 + * as published by the Free Software Foundation; either version
3472 + * 2 of the License, or (at your option) any later version.
3475 +#include <linux/config.h>
3476 +#include <linux/kernel.h>
3477 +#include <linux/netdevice.h>
3478 +#include <linux/if_bridge.h>
3479 +#include <asm/uaccess.h>
3480 +#include "br_private.h"
3482 +static int br_dev_do_ioctl(struct device *dev, struct ifreq *rq, int cmd)
3484 + unsigned long args[4];
3485 + unsigned long *data;
3487 + if (cmd != SIOCDEVPRIVATE)
3488 + return -EOPNOTSUPP;
3490 + data = (unsigned long *)rq->ifr_data;
3491 + if (copy_from_user(args, data, 4*sizeof(unsigned long)))
3494 + return br_ioctl(dev->priv, args[0], args[1], args[2], args[3]);
3497 +static struct net_device_stats *br_dev_get_stats(struct device *dev)
3499 + struct net_bridge *br;
3503 + return &br->statistics;
3506 +int br_dev_xmit(struct sk_buff *skb, struct device *dev)
3508 + struct net_bridge *br;
3509 + unsigned char *dest;
3510 + struct net_bridge_fdb_entry *dst;
3513 + br->statistics.tx_packets++;
3514 + br->statistics.tx_bytes += skb->len;
3518 + if (dest[0] & 1) {
3519 + br_flood(br, skb, 0);
3523 + if ((dst = br_fdb_get(br, dest)) != NULL) {
3524 + br_forward(dst->dst, skb);
3529 + br_flood(br, skb, 0);
3533 +static int br_dev_open(struct device *dev)
3535 + struct net_bridge *br;
3541 + read_lock(&br->lock);
3542 + br_stp_enable_bridge(br);
3543 + read_unlock(&br->lock);
3548 +static void br_dev_set_multicast_list(struct device *dev)
3552 +static int br_dev_stop(struct device *dev)
3554 + struct net_bridge *br;
3557 + read_lock(&br->lock);
3558 + br_stp_disable_bridge(br);
3559 + read_unlock(&br->lock);
3567 +static int br_dev_accept_fastpath(struct device *dev, struct dst_entry *dst)
3572 +void br_dev_setup(struct device *dev)
3574 + memset(dev->dev_addr, 0, ETH_ALEN);
3576 + dev->do_ioctl = br_dev_do_ioctl;
3577 + dev->get_stats = br_dev_get_stats;
3578 + dev->hard_start_xmit = br_dev_xmit;
3579 + dev->open = br_dev_open;
3580 + dev->set_multicast_list = br_dev_set_multicast_list;
3581 + dev->stop = br_dev_stop;
3582 + dev->accept_fastpath = br_dev_accept_fastpath;
3583 + dev->tx_queue_len = 0;
3584 + dev->set_mac_address = NULL;
3586 diff -urN linux-2.2.20/net/bridge/br_fdb.c linux-2.2.20br/net/bridge/br_fdb.c
3587 --- linux-2.2.20/net/bridge/br_fdb.c Thu Jan 1 01:00:00 1970
3588 +++ linux-2.2.20br/net/bridge/br_fdb.c Mon Dec 10 16:24:28 2001
3591 + * Forwarding database
3592 + * Linux ethernet bridge
3595 + * Lennert Buytenhek <buytenh@gnu.org>
3599 + * This program is free software; you can redistribute it and/or
3600 + * modify it under the terms of the GNU General Public License
3601 + * as published by the Free Software Foundation; either version
3602 + * 2 of the License, or (at your option) any later version.
3605 +#include <linux/config.h>
3606 +#include <linux/kernel.h>
3607 +#include <linux/if_bridge.h>
3608 +#include <asm/atomic.h>
3609 +#include <asm/spinlock.h>
3610 +#include <asm/uaccess.h>
3611 +#include "br_private.h"
3613 +static __inline__ unsigned long __timeout(struct net_bridge *br)
3615 + unsigned long timeout;
3617 + timeout = jiffies - br->ageing_time;
3618 + if (br->topology_change)
3619 + timeout = jiffies - br->forward_delay;
3624 +static __inline__ int has_expired(struct net_bridge *br,
3625 + struct net_bridge_fdb_entry *fdb)
3627 + if (!fdb->is_static &&
3628 + time_before_eq(fdb->ageing_timer, __timeout(br)))
3634 +static __inline__ void copy_fdb(struct __fdb_entry *ent, struct net_bridge_fdb_entry *f)
3636 + memset(ent, 0, sizeof(struct __fdb_entry));
3637 + memcpy(ent->mac_addr, f->addr.addr, ETH_ALEN);
3638 + ent->port_no = f->dst?f->dst->port_no:0;
3639 + ent->is_local = f->is_local;
3640 + ent->ageing_timer_value = 0;
3641 + if (!f->is_static)
3642 + ent->ageing_timer_value = jiffies - f->ageing_timer;
3645 +static __inline__ int br_mac_hash(unsigned char *mac)
3650 + x = (x << 2) ^ mac[1];
3651 + x = (x << 2) ^ mac[2];
3652 + x = (x << 2) ^ mac[3];
3653 + x = (x << 2) ^ mac[4];
3654 + x = (x << 2) ^ mac[5];
3658 + return x & (BR_HASH_SIZE - 1);
3661 +static __inline__ void __hash_link(struct net_bridge *br,
3662 + struct net_bridge_fdb_entry *ent,
3665 + ent->next_hash = br->hash[hash];
3666 + if (ent->next_hash != NULL)
3667 + ent->next_hash->pprev_hash = &ent->next_hash;
3668 + br->hash[hash] = ent;
3669 + ent->pprev_hash = &br->hash[hash];
3672 +static __inline__ void __hash_unlink(struct net_bridge_fdb_entry *ent)
3674 + *(ent->pprev_hash) = ent->next_hash;
3675 + if (ent->next_hash != NULL)
3676 + ent->next_hash->pprev_hash = ent->pprev_hash;
3677 + ent->next_hash = NULL;
3678 + ent->pprev_hash = NULL;
3683 +void br_fdb_changeaddr(struct net_bridge_port *p, unsigned char *newaddr)
3685 + struct net_bridge *br;
3689 + write_lock_bh(&br->hash_lock);
3690 + for (i=0;i<BR_HASH_SIZE;i++) {
3691 + struct net_bridge_fdb_entry *f;
3694 + while (f != NULL) {
3695 + if (f->dst == p && f->is_local) {
3697 + memcpy(f->addr.addr, newaddr, ETH_ALEN);
3698 + __hash_link(br, f, br_mac_hash(newaddr));
3699 + write_unlock_bh(&br->hash_lock);
3705 + write_unlock_bh(&br->hash_lock);
3708 +void br_fdb_cleanup(struct net_bridge *br)
3711 + unsigned long timeout;
3713 + timeout = __timeout(br);
3715 + write_lock_bh(&br->hash_lock);
3716 + for (i=0;i<BR_HASH_SIZE;i++) {
3717 + struct net_bridge_fdb_entry *f;
3720 + while (f != NULL) {
3721 + struct net_bridge_fdb_entry *g;
3724 + if (!f->is_static &&
3725 + time_before_eq(f->ageing_timer, timeout)) {
3732 + write_unlock_bh(&br->hash_lock);
3735 +void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
3739 + write_lock_bh(&br->hash_lock);
3740 + for (i=0;i<BR_HASH_SIZE;i++) {
3741 + struct net_bridge_fdb_entry *f;
3744 + while (f != NULL) {
3745 + struct net_bridge_fdb_entry *g;
3748 + if (f->dst == p) {
3755 + write_unlock_bh(&br->hash_lock);
3758 +struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, unsigned char *addr)
3760 + struct net_bridge_fdb_entry *fdb;
3762 + read_lock_bh(&br->hash_lock);
3763 + fdb = br->hash[br_mac_hash(addr)];
3764 + while (fdb != NULL) {
3765 + if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
3766 + if (!has_expired(br, fdb)) {
3767 + atomic_inc(&fdb->use_count);
3768 + read_unlock_bh(&br->hash_lock);
3772 + read_unlock_bh(&br->hash_lock);
3776 + fdb = fdb->next_hash;
3779 + read_unlock_bh(&br->hash_lock);
3783 +void br_fdb_put(struct net_bridge_fdb_entry *ent)
3785 + if (atomic_dec_and_test(&ent->use_count))
3789 +int br_fdb_get_entries(struct net_bridge *br,
3790 + unsigned char *_buf,
3796 + struct __fdb_entry *walk;
3799 + walk = (struct __fdb_entry *)_buf;
3801 + read_lock_bh(&br->hash_lock);
3802 + for (i=0;i<BR_HASH_SIZE;i++) {
3803 + struct net_bridge_fdb_entry *f;
3806 + while (f != NULL && num < maxnum) {
3807 + struct __fdb_entry ent;
3809 + struct net_bridge_fdb_entry *g;
3811 + if (has_expired(br, f)) {
3822 + copy_fdb(&ent, f);
3824 + atomic_inc(&f->use_count);
3825 + read_unlock_bh(&br->hash_lock);
3826 + err = copy_to_user(walk, &ent, sizeof(struct __fdb_entry));
3827 + read_lock_bh(&br->hash_lock);
3835 + if (f->next_hash == NULL &&
3836 + f->pprev_hash == NULL)
3837 + goto out_disappeared;
3847 + read_unlock_bh(&br->hash_lock);
3859 +static __inline__ void __fdb_possibly_replace(struct net_bridge_fdb_entry *fdb,
3860 + struct net_bridge_port *source,
3863 + if (!fdb->is_static || is_local) {
3864 + fdb->dst = source;
3865 + fdb->is_local = is_local;
3866 + fdb->is_static = is_local;
3867 + fdb->ageing_timer = jiffies;
3871 +void br_fdb_insert(struct net_bridge *br,
3872 + struct net_bridge_port *source,
3873 + unsigned char *addr,
3876 + struct net_bridge_fdb_entry *fdb;
3879 + hash = br_mac_hash(addr);
3881 + write_lock_bh(&br->hash_lock);
3882 + fdb = br->hash[hash];
3883 + while (fdb != NULL) {
3884 + if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
3885 + __fdb_possibly_replace(fdb, source, is_local);
3886 + write_unlock_bh(&br->hash_lock);
3890 + fdb = fdb->next_hash;
3893 + fdb = kmalloc(sizeof(*fdb), GFP_ATOMIC);
3894 + if (fdb == NULL) {
3895 + write_unlock_bh(&br->hash_lock);
3899 + memcpy(fdb->addr.addr, addr, ETH_ALEN);
3900 + atomic_set(&fdb->use_count, 1);
3901 + fdb->dst = source;
3902 + fdb->is_local = is_local;
3903 + fdb->is_static = is_local;
3904 + fdb->ageing_timer = jiffies;
3906 + __hash_link(br, fdb, hash);
3908 + write_unlock_bh(&br->hash_lock);
3910 diff -urN linux-2.2.20/net/bridge/br_forward.c linux-2.2.20br/net/bridge/br_forward.c
3911 --- linux-2.2.20/net/bridge/br_forward.c Thu Jan 1 01:00:00 1970
3912 +++ linux-2.2.20br/net/bridge/br_forward.c Mon Dec 10 16:24:28 2001
3915 + * Forwarding decision
3916 + * Linux ethernet bridge
3919 + * Lennert Buytenhek <buytenh@gnu.org>
3923 + * This program is free software; you can redistribute it and/or
3924 + * modify it under the terms of the GNU General Public License
3925 + * as published by the Free Software Foundation; either version
3926 + * 2 of the License, or (at your option) any later version.
3929 +#include <linux/config.h>
3930 +#include <linux/kernel.h>
3931 +#include <linux/netdevice.h>
3932 +#include <linux/inetdevice.h>
3933 +#include <linux/skbuff.h>
3934 +#include <linux/firewall.h>
3935 +#include <linux/if_bridge.h>
3936 +#include "br_private.h"
3938 +static inline int should_forward(struct net_bridge_port *p, struct sk_buff *skb)
3940 + if (skb->dev != p->dev && p->state == BR_STATE_FORWARDING)
3946 +static void __br_forward(struct net_bridge_port *to, struct sk_buff *skb)
3948 + skb->dev = to->dev;
3949 + dev_queue_xmit(skb);
3952 +void br_forward(struct net_bridge_port *to, struct sk_buff *skb)
3954 + if (should_forward(to, skb)) {
3955 + __br_forward(to, skb);
3962 +void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone)
3964 + struct net_bridge_port *p;
3965 + struct net_bridge_port *prev;
3968 + struct sk_buff *skb2;
3970 + if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
3971 + br->statistics.tx_dropped++;
3980 + read_lock(&br->lock);
3981 + p = br->port_list;
3982 + while (p != NULL) {
3983 + if (should_forward(p, skb)) {
3984 + if (prev != NULL) {
3985 + struct sk_buff *skb2;
3987 + if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
3988 + br->statistics.tx_dropped++;
3990 + read_unlock(&br->lock);
3994 + __br_forward(prev, skb2);
4003 + if (prev != NULL) {
4004 + __br_forward(prev, skb);
4005 + read_unlock(&br->lock);
4009 + read_unlock(&br->lock);
4012 diff -urN linux-2.2.20/net/bridge/br_if.c linux-2.2.20br/net/bridge/br_if.c
4013 --- linux-2.2.20/net/bridge/br_if.c Thu Jan 1 01:00:00 1970
4014 +++ linux-2.2.20br/net/bridge/br_if.c Mon Dec 10 16:26:38 2001
4017 + * Userspace interface
4018 + * Linux ethernet bridge
4021 + * Lennert Buytenhek <buytenh@gnu.org>
4025 + * This program is free software; you can redistribute it and/or
4026 + * modify it under the terms of the GNU General Public License
4027 + * as published by the Free Software Foundation; either version
4028 + * 2 of the License, or (at your option) any later version.
4031 +#include <linux/config.h>
4032 +#include <linux/kernel.h>
4033 +#include <linux/if_arp.h>
4034 +#include <linux/if_bridge.h>
4035 +#include <linux/inetdevice.h>
4036 +#include <asm/uaccess.h>
4037 +#include "br_private.h"
4039 +static struct net_bridge *bridge_list;
4041 +static int br_initial_port_cost(struct device *dev)
4043 + if (!strncmp(dev->name, "lec", 3))
4046 + if (!strncmp(dev->name, "eth", 3))
4047 + return 100; /* FIXME handle 100Mbps */
4049 + if (!strncmp(dev->name, "plip", 4))
4055 +/* called under bridge lock */
4056 +static int __br_del_if(struct net_bridge *br, struct device *dev)
4058 + struct net_bridge_port *p;
4059 + struct net_bridge_port **pptr;
4061 + if ((p = dev->br_port) == NULL)
4064 + br_stp_disable_port(p);
4066 + dev_set_promiscuity(dev, -1);
4067 + if (dev->ip_ptr != NULL) {
4068 + struct in_device *idev = dev->ip_ptr;
4069 + idev->cnf.hidden = 0;
4072 + dev->br_port = NULL;
4074 + pptr = &br->port_list;
4075 + while (*pptr != NULL) {
4081 + pptr = &((*pptr)->next);
4084 + br_fdb_delete_by_port(br, p);
4090 +static struct net_bridge **__find_br(char *name)
4092 + struct net_bridge **b;
4093 + struct net_bridge *br;
4096 + while ((br = *b) != NULL) {
4097 + if (!strncmp(br->name, name, IFNAMSIZ))
4106 +static void del_ifs(struct net_bridge *br)
4108 + write_lock_bh(&br->lock);
4109 + while (br->port_list != NULL)
4110 + __br_del_if(br, br->port_list->dev);
4111 + write_unlock_bh(&br->lock);
4114 +static struct net_bridge *new_nb(char *name)
4116 + struct net_bridge *br;
4117 + struct device *dev;
4119 + if ((br = kmalloc(sizeof(*br), GFP_KERNEL)) == NULL)
4122 + memset(br, 0, sizeof(*br));
4125 + strncpy(br->name, name, IFNAMSIZ);
4127 + dev->name = br->name;
4129 + br_dev_setup(dev);
4131 + br->lock = RW_LOCK_UNLOCKED;
4132 + br->hash_lock = RW_LOCK_UNLOCKED;
4134 + br->bridge_id.prio[0] = 0x80;
4135 + br->bridge_id.prio[1] = 0x00;
4136 + memset(br->bridge_id.addr, 0, ETH_ALEN);
4138 + br->stp_enabled = 1;
4139 + br->designated_root = br->bridge_id;
4140 + br->root_path_cost = 0;
4141 + br->root_port = 0;
4142 + br->bridge_max_age = br->max_age = 20 * HZ;
4143 + br->bridge_hello_time = br->hello_time = 2 * HZ;
4144 + br->bridge_forward_delay = br->forward_delay = 15 * HZ;
4145 + br->topology_change = 0;
4146 + br->topology_change_detected = 0;
4147 + br_timer_clear(&br->hello_timer);
4148 + br_timer_clear(&br->tcn_timer);
4149 + br_timer_clear(&br->topology_change_timer);
4151 + br->ageing_time = 300 * HZ;
4152 + br->gc_interval = 4 * HZ;
4157 +/* called under bridge lock */
4158 +static struct net_bridge_port *new_nbp(struct net_bridge *br, struct device *dev)
4161 + struct net_bridge_port *p;
4163 + p = kmalloc(sizeof(*p), GFP_KERNEL);
4167 + memset(p, 0, sizeof(*p));
4170 + p->path_cost = br_initial_port_cost(dev);
4171 + p->priority = 0x80;
4175 + for (i=1;i<255;i++)
4176 + if (br_get_port(br, i) == NULL)
4186 + p->state = BR_STATE_DISABLED;
4188 + p->next = br->port_list;
4189 + br->port_list = p;
4194 +int br_add_bridge(char *name)
4196 + struct net_bridge *br;
4198 + if ((br = new_nb(name)) == NULL)
4201 + if (dev_get(name) != NULL) {
4206 + br->next = bridge_list;
4209 + br_inc_use_count();
4210 + register_netdevice(&br->dev);
4215 +int br_del_bridge(char *name)
4217 + struct net_bridge **b;
4218 + struct net_bridge *br;
4220 + if ((b = __find_br(name)) == NULL)
4225 + if (br->dev.flags & IFF_UP)
4232 + unregister_netdevice(&br->dev);
4234 + br_dec_use_count();
4239 +int br_add_if(struct net_bridge *br, struct device *dev)
4241 + struct net_bridge_port *p;
4243 + if (dev->br_port != NULL)
4246 + if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
4249 + if (dev->hard_start_xmit == br_dev_xmit)
4252 + write_lock_bh(&br->lock);
4253 + if ((p = new_nbp(br, dev)) == NULL) {
4254 + write_unlock_bh(&br->lock);
4258 + if (dev->ip_ptr != NULL) {
4259 + struct in_device *idev = dev->ip_ptr;
4260 + idev->cnf.hidden = 1;
4262 + dev_set_promiscuity(dev, 1);
4264 + br_stp_recalculate_bridge_id(br);
4265 + br_fdb_insert(br, p, dev->dev_addr, 1);
4266 + if ((br->dev.flags & IFF_UP) && (dev->flags & IFF_UP))
4267 + br_stp_enable_port(p);
4268 + write_unlock_bh(&br->lock);
4273 +int br_del_if(struct net_bridge *br, struct device *dev)
4277 + write_lock_bh(&br->lock);
4278 + retval = __br_del_if(br, dev);
4279 + br_stp_recalculate_bridge_id(br);
4280 + write_unlock_bh(&br->lock);
4285 +int br_get_bridge_ifindices(int *indices, int num)
4287 + struct net_bridge *br;
4291 + for (i=0;i<num;i++) {
4295 + indices[i] = br->dev.ifindex;
4302 +/* called under ioctl_lock */
4303 +void br_get_port_ifindices(struct net_bridge *br, int *ifindices)
4305 + struct net_bridge_port *p;
4307 + p = br->port_list;
4308 + while (p != NULL) {
4309 + ifindices[p->port_no] = p->dev->ifindex;
4313 diff -urN linux-2.2.20/net/bridge/br_input.c linux-2.2.20br/net/bridge/br_input.c
4314 --- linux-2.2.20/net/bridge/br_input.c Thu Jan 1 01:00:00 1970
4315 +++ linux-2.2.20br/net/bridge/br_input.c Mon Dec 10 16:31:55 2001
4318 + * Handle incoming frames
4319 + * Linux ethernet bridge
4322 + * Lennert Buytenhek <buytenh@gnu.org>
4326 + * This program is free software; you can redistribute it and/or
4327 + * modify it under the terms of the GNU General Public License
4328 + * as published by the Free Software Foundation; either version
4329 + * 2 of the License, or (at your option) any later version.
4331 + * Changes: 2000/02/03 [AF] Arne Fitzenreiter <arne.fitzenreiter@gmx.de>
4332 + * Bugfix - Multicast & Promiscious Mode
4336 +#include <linux/config.h>
4337 +#include <linux/kernel.h>
4338 +#include <linux/netdevice.h>
4339 +#include <linux/etherdevice.h>
4340 +#include <linux/if_bridge.h>
4341 +#include "br_private.h"
4343 +unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
4345 +static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
4347 + br->statistics.rx_packets++;
4348 + br->statistics.rx_bytes += skb->len;
4350 + skb->dev = &br->dev;
4351 + skb->pkt_type = PACKET_HOST;
4352 + skb_pull(skb, skb->mac.raw - skb->data);
4353 + skb->protocol = eth_type_trans(skb, &br->dev);
4357 +void br_handle_frame(struct sk_buff *skb)
4359 + struct net_bridge *br;
4360 + unsigned char *dest;
4361 + struct net_bridge_fdb_entry *dst;
4362 + struct net_bridge_port *p;
4365 + dest = skb->mac.ethernet->h_dest;
4367 + p = skb->dev->br_port;
4371 + if (!(br->dev.flags & IFF_UP) ||
4372 + p->state == BR_STATE_DISABLED)
4375 + skb_push(skb, skb->data - skb->mac.raw);
4377 + if (br->dev.flags & IFF_PROMISC && p->state == BR_STATE_FORWARDING) {
4378 + struct sk_buff *skb2;
4380 + skb2 = skb_clone(skb, GFP_ATOMIC);
4383 + br_pass_frame_up(br, skb2);
4387 + if (skb->mac.ethernet->h_source[0] & 1)
4392 + (br->dev.flags & IFF_ALLMULTI || br->dev.mc_list != NULL) &&
4393 + (p->state == BR_STATE_FORWARDING)) {
4394 + struct sk_buff *skb2;
4396 + skb2 = skb_clone(skb, GFP_ATOMIC);
4399 + br_pass_frame_up(br, skb2);
4403 + if (p->state == BR_STATE_LEARNING ||
4404 + p->state == BR_STATE_FORWARDING)
4405 + br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0);
4407 + if (br->stp_enabled &&
4408 + !memcmp(dest, bridge_ula, 5) &&
4409 + !(dest[5] & 0xF0))
4410 + goto handle_special_frame;
4412 + if (p->state != BR_STATE_FORWARDING)
4415 + if (dest[0] & 1) {
4416 + br_flood(br, skb, !passedup);
4418 + br_pass_frame_up(br, skb);
4422 + dst = br_fdb_get(br, dest);
4424 + if (dst != NULL && dst->is_local) {
4426 + br_pass_frame_up(br, skb);
4433 + if (dst != NULL) {
4434 + br_forward(dst->dst, skb);
4439 + br_flood(br, skb, 0);
4442 + handle_special_frame:
4444 + br_stp_handle_bpdu(skb);
4451 diff -urN linux-2.2.20/net/bridge/br_ioctl.c linux-2.2.20br/net/bridge/br_ioctl.c
4452 --- linux-2.2.20/net/bridge/br_ioctl.c Thu Jan 1 01:00:00 1970
4453 +++ linux-2.2.20br/net/bridge/br_ioctl.c Mon Dec 10 16:24:28 2001
4457 + * Linux ethernet bridge
4460 + * Lennert Buytenhek <buytenh@gnu.org>
4464 + * This program is free software; you can redistribute it and/or
4465 + * modify it under the terms of the GNU General Public License
4466 + * as published by the Free Software Foundation; either version
4467 + * 2 of the License, or (at your option) any later version.
4470 +#include <linux/config.h>
4471 +#include <linux/kernel.h>
4472 +#include <linux/if_bridge.h>
4473 +#include <linux/inetdevice.h>
4474 +#include <asm/uaccess.h>
4475 +#include "br_private.h"
4477 +static int br_ioctl_device(struct net_bridge *br,
4479 + unsigned long arg0,
4480 + unsigned long arg1,
4481 + unsigned long arg2)
4488 + case BRCTL_ADD_IF:
4489 + case BRCTL_DEL_IF:
4491 + struct device *dev;
4493 + dev = dev_get_by_index(arg0);
4497 + if (cmd == BRCTL_ADD_IF)
4498 + return br_add_if(br, dev);
4500 + return br_del_if(br, dev);
4503 + case BRCTL_GET_BRIDGE_INFO:
4505 + struct __bridge_info b;
4507 + memset(&b, 0, sizeof(struct __bridge_info));
4508 + memcpy(&b.designated_root, &br->designated_root, 8);
4509 + memcpy(&b.bridge_id, &br->bridge_id, 8);
4510 + b.root_path_cost = br->root_path_cost;
4511 + b.max_age = br->max_age;
4512 + b.hello_time = br->hello_time;
4513 + b.forward_delay = br->forward_delay;
4514 + b.bridge_max_age = br->bridge_max_age;
4515 + b.bridge_hello_time = br->bridge_hello_time;
4516 + b.bridge_forward_delay = br->bridge_forward_delay;
4517 + b.topology_change = br->topology_change;
4518 + b.topology_change_detected = br->topology_change_detected;
4519 + b.root_port = br->root_port;
4520 + b.stp_enabled = br->stp_enabled;
4521 + b.ageing_time = br->ageing_time;
4522 + b.gc_interval = br->gc_interval;
4523 + b.hello_timer_value = br_timer_get_residue(&br->hello_timer);
4524 + b.tcn_timer_value = br_timer_get_residue(&br->tcn_timer);
4525 + b.topology_change_timer_value = br_timer_get_residue(&br->topology_change_timer);
4526 + b.gc_timer_value = br_timer_get_residue(&br->gc_timer);
4528 + if (copy_to_user((void *)arg0, &b, sizeof(b)))
4534 + case BRCTL_GET_PORT_LIST:
4539 + for (i=0;i<256;i++)
4542 + br_get_port_ifindices(br, indices);
4543 + if (copy_to_user((void *)arg0, indices, 256*sizeof(int)))
4549 + case BRCTL_SET_BRIDGE_FORWARD_DELAY:
4550 + br->bridge_forward_delay = arg0;
4551 + if (br_is_root_bridge(br))
4552 + br->forward_delay = arg0;
4555 + case BRCTL_SET_BRIDGE_HELLO_TIME:
4556 + br->bridge_hello_time = arg0;
4557 + if (br_is_root_bridge(br))
4558 + br->hello_time = arg0;
4561 + case BRCTL_SET_BRIDGE_MAX_AGE:
4562 + br->bridge_max_age = arg0;
4563 + if (br_is_root_bridge(br))
4564 + br->max_age = arg0;
4567 + case BRCTL_SET_AGEING_TIME:
4568 + br->ageing_time = arg0;
4571 + case BRCTL_SET_GC_INTERVAL:
4572 + br->gc_interval = arg0;
4575 + case BRCTL_GET_PORT_INFO:
4577 + struct __port_info p;
4578 + struct net_bridge_port *pt;
4580 + if ((pt = br_get_port(br, arg1)) == NULL)
4583 + memset(&p, 0, sizeof(struct __port_info));
4584 + memcpy(&p.designated_root, &pt->designated_root, 8);
4585 + memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
4586 + p.port_id = pt->port_id;
4587 + p.designated_port = pt->designated_port;
4588 + p.path_cost = pt->path_cost;
4589 + p.designated_cost = pt->designated_cost;
4590 + p.state = pt->state;
4591 + p.top_change_ack = pt->topology_change_ack;
4592 + p.config_pending = pt->config_pending;
4593 + p.message_age_timer_value = br_timer_get_residue(&pt->message_age_timer);
4594 + p.forward_delay_timer_value = br_timer_get_residue(&pt->forward_delay_timer);
4595 + p.hold_timer_value = br_timer_get_residue(&pt->hold_timer);
4597 + if (copy_to_user((void *)arg0, &p, sizeof(p)))
4603 + case BRCTL_SET_BRIDGE_STP_STATE:
4604 + br->stp_enabled = arg0?1:0;
4607 + case BRCTL_SET_BRIDGE_PRIORITY:
4608 + br_stp_set_bridge_priority(br, arg0);
4611 + case BRCTL_SET_PORT_PRIORITY:
4613 + struct net_bridge_port *p;
4615 + if ((p = br_get_port(br, arg0)) == NULL)
4617 + br_stp_set_port_priority(p, arg1);
4621 + case BRCTL_SET_PATH_COST:
4623 + struct net_bridge_port *p;
4625 + if ((p = br_get_port(br, arg0)) == NULL)
4627 + br_stp_set_path_cost(p, arg1);
4631 + case BRCTL_GET_FDB_ENTRIES:
4632 + return br_fdb_get_entries(br, (void *)arg0, arg1, arg2);
4635 + return -EOPNOTSUPP;
4638 +static int br_ioctl_deviceless(unsigned int cmd,
4639 + unsigned long arg0,
4640 + unsigned long arg1)
4644 + case BRCTL_GET_VERSION:
4645 + return BRCTL_VERSION;
4647 + case BRCTL_GET_BRIDGES:
4652 + for (i=0;i<64;i++)
4657 + arg1 = br_get_bridge_ifindices(indices, arg1);
4658 + if (copy_to_user((void *)arg0, indices, arg1*sizeof(int)))
4664 + case BRCTL_ADD_BRIDGE:
4665 + case BRCTL_DEL_BRIDGE:
4667 + char buf[IFNAMSIZ];
4669 + if (copy_from_user(buf, (void *)arg0, IFNAMSIZ))
4672 + buf[IFNAMSIZ-1] = 0;
4674 + if (cmd == BRCTL_ADD_BRIDGE)
4675 + return br_add_bridge(buf);
4677 + return br_del_bridge(buf);
4681 + return -EOPNOTSUPP;
4684 +static struct semaphore ioctl_mutex = MUTEX;
4686 +int br_ioctl_deviceless_stub(unsigned long arg)
4689 + unsigned long i[3];
4691 + if (!capable(CAP_NET_ADMIN))
4694 + if (copy_from_user(i, (void *)arg, 3*sizeof(unsigned long)))
4697 + down(&ioctl_mutex);
4698 + err = br_ioctl_deviceless(i[0], i[1], i[2]);
4704 +int br_ioctl(struct net_bridge *br, unsigned int cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2)
4708 + if (!capable(CAP_NET_ADMIN))
4711 + down(&ioctl_mutex);
4712 + err = br_ioctl_deviceless(cmd, arg0, arg1);
4713 + if (err == -EOPNOTSUPP)
4714 + err = br_ioctl_device(br, cmd, arg0, arg1, arg2);
4719 diff -urN linux-2.2.20/net/bridge/br_notify.c linux-2.2.20br/net/bridge/br_notify.c
4720 --- linux-2.2.20/net/bridge/br_notify.c Thu Jan 1 01:00:00 1970
4721 +++ linux-2.2.20br/net/bridge/br_notify.c Mon Dec 10 16:24:28 2001
4724 + * Device event handling
4725 + * Linux ethernet bridge
4728 + * Lennert Buytenhek <buytenh@gnu.org>
4732 + * This program is free software; you can redistribute it and/or
4733 + * modify it under the terms of the GNU General Public License
4734 + * as published by the Free Software Foundation; either version
4735 + * 2 of the License, or (at your option) any later version.
4738 +#include <linux/config.h>
4739 +#include <linux/kernel.h>
4740 +#include <linux/if_bridge.h>
4741 +#include "br_private.h"
4743 +static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr);
4745 +struct notifier_block br_device_notifier =
4752 +static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
4754 + struct device *dev;
4755 + struct net_bridge_port *p;
4761 + return NOTIFY_DONE;
4765 + case NETDEV_CHANGEADDR:
4766 + read_lock(&p->br->lock);
4767 + br_fdb_changeaddr(p, dev->dev_addr);
4768 + br_stp_recalculate_bridge_id(p->br);
4769 + read_unlock(&p->br->lock);
4772 + case NETDEV_GOING_DOWN:
4773 + /* extend the protocol to send some kind of notification? */
4777 + if (p->br->dev.flags & IFF_UP) {
4778 + read_lock(&p->br->lock);
4779 + br_stp_disable_port(dev->br_port);
4780 + read_unlock(&p->br->lock);
4785 + if (p->br->dev.flags & IFF_UP) {
4786 + read_lock(&p->br->lock);
4787 + br_stp_enable_port(dev->br_port);
4788 + read_unlock(&p->br->lock);
4792 + case NETDEV_UNREGISTER:
4793 + br_del_if(dev->br_port->br, dev);
4797 + return NOTIFY_DONE;
4799 diff -urN linux-2.2.20/net/bridge/br_private.h linux-2.2.20br/net/bridge/br_private.h
4800 --- linux-2.2.20/net/bridge/br_private.h Thu Jan 1 01:00:00 1970
4801 +++ linux-2.2.20br/net/bridge/br_private.h Mon Dec 10 16:26:19 2001
4804 + * Linux ethernet bridge
4807 + * Lennert Buytenhek <buytenh@gnu.org>
4811 + * This program is free software; you can redistribute it and/or
4812 + * modify it under the terms of the GNU General Public License
4813 + * as published by the Free Software Foundation; either version
4814 + * 2 of the License, or (at your option) any later version.
4817 +#ifndef _BR_PRIVATE_H
4818 +#define _BR_PRIVATE_H
4820 +#include <linux/netdevice.h>
4821 +#include <linux/miscdevice.h>
4822 +#include <linux/if_bridge.h>
4824 +#define BR_HASH_BITS 8
4825 +#define BR_HASH_SIZE (1 << BR_HASH_BITS)
4827 +#define BR_HOLD_TIME (1*HZ)
4829 +#ifndef read_lock_bh
4830 +#define read_lock_bh(x) { start_bh_atomic(); read_lock(x); }
4831 +#define read_unlock_bh(x) { read_unlock(x); end_bh_atomic(); }
4832 +#define write_lock_bh(x) { start_bh_atomic(); write_lock(x); }
4833 +#define write_unlock_bh(x) { write_unlock(x); end_bh_atomic(); }
4836 +typedef struct bridge_id bridge_id;
4837 +typedef struct mac_addr mac_addr;
4838 +typedef __u16 port_id;
4841 +struct br_timer { int running; unsigned long expires; };
4842 +#define br_timer_clear(t) { (t)->running = 0; }
4843 +#define br_timer_get_residue(t) (((t)->running)?(jiffies - (t)->expires):0)
4844 +#define br_timer_set(t,x) { (t)->expires = (x); (t)->running = 1; }
4845 +#define br_timer_is_running(t) ((t)->running)
4846 +#define br_timer_has_expired(t,to) ((t)->running && time_after_eq(jiffies, (t)->expires + (to)))
4853 + unsigned char prio[2];
4854 + unsigned char addr[6];
4859 + unsigned char addr[6];
4860 + unsigned char pad[2];
4863 +struct net_bridge_fdb_entry
4865 + struct net_bridge_fdb_entry *next_hash;
4866 + struct net_bridge_fdb_entry **pprev_hash;
4867 + atomic_t use_count;
4869 + struct net_bridge_port *dst;
4870 + unsigned long ageing_timer;
4871 + unsigned is_local:1;
4872 + unsigned is_static:1;
4875 +struct net_bridge_port
4877 + struct net_bridge_port *next;
4878 + struct net_bridge *br;
4879 + struct device *dev;
4886 + bridge_id designated_root;
4887 + int designated_cost;
4888 + bridge_id designated_bridge;
4889 + port_id designated_port;
4890 + unsigned topology_change_ack:1;
4891 + unsigned config_pending:1;
4894 + struct br_timer forward_delay_timer;
4895 + struct br_timer hold_timer;
4896 + struct br_timer message_age_timer;
4901 + struct net_bridge *next;
4903 + struct net_bridge_port *port_list;
4904 + char name[IFNAMSIZ];
4905 + struct device dev;
4906 + struct net_device_stats statistics;
4907 + rwlock_t hash_lock;
4908 + struct net_bridge_fdb_entry *hash[BR_HASH_SIZE];
4909 + struct timer_list tick;
4912 + bridge_id designated_root;
4913 + int root_path_cost;
4917 + int forward_delay;
4918 + bridge_id bridge_id;
4919 + int bridge_max_age;
4920 + int bridge_hello_time;
4921 + int bridge_forward_delay;
4922 + unsigned stp_enabled:1;
4923 + unsigned topology_change:1;
4924 + unsigned topology_change_detected:1;
4926 + struct br_timer hello_timer;
4927 + struct br_timer tcn_timer;
4928 + struct br_timer topology_change_timer;
4929 + struct br_timer gc_timer;
4935 +struct notifier_block br_device_notifier;
4936 +unsigned char bridge_ula[6];
4939 +void br_dec_use_count(void);
4940 +void br_inc_use_count(void);
4943 +void br_dev_setup(struct device *dev);
4944 +int br_dev_xmit(struct sk_buff *skb, struct device *dev);
4947 +void br_fdb_changeaddr(struct net_bridge_port *p,
4948 + unsigned char *newaddr);
4949 +void br_fdb_cleanup(struct net_bridge *br);
4950 +void br_fdb_delete_by_port(struct net_bridge *br,
4951 + struct net_bridge_port *p);
4952 +struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
4953 + unsigned char *addr);
4954 +void br_fdb_put(struct net_bridge_fdb_entry *ent);
4955 +int br_fdb_get_entries(struct net_bridge *br,
4956 + unsigned char *_buf,
4959 +void br_fdb_insert(struct net_bridge *br,
4960 + struct net_bridge_port *source,
4961 + unsigned char *addr,
4965 +void br_forward(struct net_bridge_port *to,
4966 + struct sk_buff *skb);
4967 +void br_flood(struct net_bridge *br,
4968 + struct sk_buff *skb,
4972 +int br_add_bridge(char *name);
4973 +int br_del_bridge(char *name);
4974 +int br_add_if(struct net_bridge *br,
4975 + struct device *dev);
4976 +int br_del_if(struct net_bridge *br,
4977 + struct device *dev);
4978 +int br_get_bridge_ifindices(int *indices,
4980 +void br_get_port_ifindices(struct net_bridge *br,
4984 +void br_handle_frame(struct sk_buff *skb);
4987 +int br_ioctl(struct net_bridge *br,
4989 + unsigned long arg0,
4990 + unsigned long arg1,
4991 + unsigned long arg2);
4992 +int br_ioctl_deviceless_stub(unsigned long arg);
4995 +int br_is_root_bridge(struct net_bridge *br);
4996 +struct net_bridge_port *br_get_port(struct net_bridge *br,
4998 +void br_init_port(struct net_bridge_port *p);
4999 +port_id br_make_port_id(struct net_bridge_port *p);
5000 +void br_become_designated_port(struct net_bridge_port *p);
5003 +void br_stp_enable_bridge(struct net_bridge *br);
5004 +void br_stp_disable_bridge(struct net_bridge *br);
5005 +void br_stp_enable_port(struct net_bridge_port *p);
5006 +void br_stp_disable_port(struct net_bridge_port *p);
5007 +void br_stp_recalculate_bridge_id(struct net_bridge *br);
5008 +void br_stp_set_bridge_priority(struct net_bridge *br,
5010 +void br_stp_set_port_priority(struct net_bridge_port *p,
5012 +void br_stp_set_path_cost(struct net_bridge_port *p,
5015 +/* br_stp_bpdu.c */
5016 +void br_stp_handle_bpdu(struct sk_buff *skb);
5019 diff -urN linux-2.2.20/net/bridge/br_private_stp.h linux-2.2.20br/net/bridge/br_private_stp.h
5020 --- linux-2.2.20/net/bridge/br_private_stp.h Thu Jan 1 01:00:00 1970
5021 +++ linux-2.2.20br/net/bridge/br_private_stp.h Mon Dec 10 16:24:28 2001
5024 + * Linux ethernet bridge
5027 + * Lennert Buytenhek <buytenh@gnu.org>
5031 + * This program is free software; you can redistribute it and/or
5032 + * modify it under the terms of the GNU General Public License
5033 + * as published by the Free Software Foundation; either version
5034 + * 2 of the License, or (at your option) any later version.
5037 +#ifndef _BR_PRIVATE_STP_H
5038 +#define _BR_PRIVATE_STP_H
5040 +#define BPDU_TYPE_CONFIG 0
5041 +#define BPDU_TYPE_TCN 0x80
5043 +struct br_config_bpdu
5045 + unsigned topology_change:1;
5046 + unsigned topology_change_ack:1;
5048 + int root_path_cost;
5049 + bridge_id bridge_id;
5054 + int forward_delay;
5058 +void br_become_root_bridge(struct net_bridge *br);
5059 +void br_config_bpdu_generation(struct net_bridge *);
5060 +void br_configuration_update(struct net_bridge *);
5061 +int br_is_designated_port(struct net_bridge_port *p);
5062 +int br_is_root_bridge(struct net_bridge *br);
5063 +void br_port_state_selection(struct net_bridge *);
5064 +void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu);
5065 +void br_received_tcn_bpdu(struct net_bridge_port *p);
5066 +void br_tick(unsigned long __data);
5067 +void br_transmit_config(struct net_bridge_port *p);
5068 +void br_transmit_tcn(struct net_bridge *br);
5069 +void br_topology_change_detection(struct net_bridge *br);
5071 +/* br_stp_bpdu.c */
5072 +void br_send_config_bpdu(struct net_bridge_port *, struct br_config_bpdu *);
5073 +void br_send_tcn_bpdu(struct net_bridge_port *);
5076 diff -urN linux-2.2.20/net/bridge/br_stp.c linux-2.2.20br/net/bridge/br_stp.c
5077 --- linux-2.2.20/net/bridge/br_stp.c Thu Jan 1 01:00:00 1970
5078 +++ linux-2.2.20br/net/bridge/br_stp.c Mon Dec 10 16:24:28 2001
5081 + * Spanning tree protocol; generic parts
5082 + * Linux ethernet bridge
5085 + * Lennert Buytenhek <buytenh@gnu.org>
5089 + * This program is free software; you can redistribute it and/or
5090 + * modify it under the terms of the GNU General Public License
5091 + * as published by the Free Software Foundation; either version
5092 + * 2 of the License, or (at your option) any later version.
5095 +#include <linux/config.h>
5096 +#include <linux/kernel.h>
5097 +#include <linux/if_bridge.h>
5098 +#include <linux/smp_lock.h>
5099 +#include <asm/uaccess.h>
5100 +#include "br_private.h"
5101 +#include "br_private_stp.h"
5105 +/* called under ioctl_lock or bridge lock */
5106 +int br_is_root_bridge(struct net_bridge *br)
5108 + return !memcmp(&br->bridge_id, &br->designated_root, 8);
5111 +/* called under bridge lock */
5112 +int br_is_designated_port(struct net_bridge_port *p)
5114 + return !memcmp(&p->designated_bridge, &p->br->bridge_id, 8) &&
5115 + (p->designated_port == p->port_id);
5118 +/* called under ioctl_lock or bridge lock */
5119 +struct net_bridge_port *br_get_port(struct net_bridge *br, int port_no)
5121 + struct net_bridge_port *p;
5123 + p = br->port_list;
5124 + while (p != NULL) {
5125 + if (p->port_no == port_no)
5134 +/* called under bridge lock */
5135 +static int br_should_become_root_port(struct net_bridge_port *p, int root_port)
5137 + struct net_bridge *br;
5138 + struct net_bridge_port *rp;
5142 + if (p->state == BR_STATE_DISABLED ||
5143 + br_is_designated_port(p))
5146 + if (memcmp(&br->bridge_id, &p->designated_root, 8) <= 0)
5152 + rp = br_get_port(br, root_port);
5154 + t = memcmp(&p->designated_root, &rp->designated_root, 8);
5160 + if (p->designated_cost + p->path_cost <
5161 + rp->designated_cost + rp->path_cost)
5163 + else if (p->designated_cost + p->path_cost >
5164 + rp->designated_cost + rp->path_cost)
5167 + t = memcmp(&p->designated_bridge, &rp->designated_bridge, 8);
5173 + if (p->designated_port < rp->designated_port)
5175 + else if (p->designated_port > rp->designated_port)
5178 + if (p->port_id < rp->port_id)
5184 +/* called under bridge lock */
5185 +static void br_root_selection(struct net_bridge *br)
5187 + struct net_bridge_port *p;
5192 + p = br->port_list;
5193 + while (p != NULL) {
5194 + if (br_should_become_root_port(p, root_port))
5195 + root_port = p->port_no;
5200 + br->root_port = root_port;
5203 + br->designated_root = br->bridge_id;
5204 + br->root_path_cost = 0;
5206 + p = br_get_port(br, root_port);
5207 + br->designated_root = p->designated_root;
5208 + br->root_path_cost = p->designated_cost + p->path_cost;
5212 +/* called under bridge lock */
5213 +void br_become_root_bridge(struct net_bridge *br)
5215 + br->max_age = br->bridge_max_age;
5216 + br->hello_time = br->bridge_hello_time;
5217 + br->forward_delay = br->bridge_forward_delay;
5218 + br_topology_change_detection(br);
5219 + br_timer_clear(&br->tcn_timer);
5220 + br_config_bpdu_generation(br);
5221 + br_timer_set(&br->hello_timer, jiffies);
5224 +/* called under bridge lock */
5225 +void br_transmit_config(struct net_bridge_port *p)
5227 + struct br_config_bpdu bpdu;
5228 + struct net_bridge *br;
5230 + if (br_timer_is_running(&p->hold_timer)) {
5231 + p->config_pending = 1;
5237 + bpdu.topology_change = br->topology_change;
5238 + bpdu.topology_change_ack = p->topology_change_ack;
5239 + bpdu.root = br->designated_root;
5240 + bpdu.root_path_cost = br->root_path_cost;
5241 + bpdu.bridge_id = br->bridge_id;
5242 + bpdu.port_id = p->port_id;
5243 + bpdu.message_age = 0;
5244 + if (!br_is_root_bridge(br)) {
5245 + struct net_bridge_port *root;
5246 + unsigned long age;
5248 + root = br_get_port(br, br->root_port);
5249 + age = br_timer_get_residue(&root->message_age_timer) + 1;
5250 + bpdu.message_age = age;
5252 + bpdu.max_age = br->max_age;
5253 + bpdu.hello_time = br->hello_time;
5254 + bpdu.forward_delay = br->forward_delay;
5256 + br_send_config_bpdu(p, &bpdu);
5258 + p->topology_change_ack = 0;
5259 + p->config_pending = 0;
5260 + br_timer_set(&p->hold_timer, jiffies);
5263 +/* called under bridge lock */
5264 +static void br_record_config_information(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5266 + p->designated_root = bpdu->root;
5267 + p->designated_cost = bpdu->root_path_cost;
5268 + p->designated_bridge = bpdu->bridge_id;
5269 + p->designated_port = bpdu->port_id;
5271 + br_timer_set(&p->message_age_timer, jiffies - bpdu->message_age);
5274 +/* called under bridge lock */
5275 +static void br_record_config_timeout_values(struct net_bridge *br, struct br_config_bpdu *bpdu)
5277 + br->max_age = bpdu->max_age;
5278 + br->hello_time = bpdu->hello_time;
5279 + br->forward_delay = bpdu->forward_delay;
5280 + br->topology_change = bpdu->topology_change;
5283 +/* called under bridge lock */
5284 +void br_transmit_tcn(struct net_bridge *br)
5286 + br_send_tcn_bpdu(br_get_port(br, br->root_port));
5289 +/* called under bridge lock */
5290 +static int br_should_become_designated_port(struct net_bridge_port *p)
5292 + struct net_bridge *br;
5296 + if (br_is_designated_port(p))
5299 + if (memcmp(&p->designated_root, &br->designated_root, 8))
5302 + if (br->root_path_cost < p->designated_cost)
5304 + else if (br->root_path_cost > p->designated_cost)
5307 + t = memcmp(&br->bridge_id, &p->designated_bridge, 8);
5313 + if (p->port_id < p->designated_port)
5319 +/* called under bridge lock */
5320 +static void br_designated_port_selection(struct net_bridge *br)
5322 + struct net_bridge_port *p;
5324 + p = br->port_list;
5325 + while (p != NULL) {
5326 + if (p->state != BR_STATE_DISABLED &&
5327 + br_should_become_designated_port(p))
5328 + br_become_designated_port(p);
5334 +/* called under bridge lock */
5335 +static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5339 + t = memcmp(&bpdu->root, &p->designated_root, 8);
5345 + if (bpdu->root_path_cost < p->designated_cost)
5347 + else if (bpdu->root_path_cost > p->designated_cost)
5350 + t = memcmp(&bpdu->bridge_id, &p->designated_bridge, 8);
5356 + if (memcmp(&bpdu->bridge_id, &p->br->bridge_id, 8))
5359 + if (bpdu->port_id <= p->designated_port)
5365 +/* called under bridge lock */
5366 +static void br_topology_change_acknowledged(struct net_bridge *br)
5368 + br->topology_change_detected = 0;
5369 + br_timer_clear(&br->tcn_timer);
5372 +/* called under bridge lock */
5373 +void br_topology_change_detection(struct net_bridge *br)
5375 + printk(KERN_INFO "%s: topology change detected", br->name);
5377 + if (br_is_root_bridge(br)) {
5378 + printk(", propagating");
5379 + br->topology_change = 1;
5380 + br_timer_set(&br->topology_change_timer, jiffies);
5381 + } else if (!br->topology_change_detected) {
5382 + printk(", sending tcn bpdu");
5383 + br_transmit_tcn(br);
5384 + br_timer_set(&br->tcn_timer, jiffies);
5388 + br->topology_change_detected = 1;
5391 +/* called under bridge lock */
5392 +void br_config_bpdu_generation(struct net_bridge *br)
5394 + struct net_bridge_port *p;
5396 + p = br->port_list;
5397 + while (p != NULL) {
5398 + if (p->state != BR_STATE_DISABLED &&
5399 + br_is_designated_port(p))
5400 + br_transmit_config(p);
5406 +/* called under bridge lock */
5407 +static void br_reply(struct net_bridge_port *p)
5409 + br_transmit_config(p);
5412 +/* called under bridge lock */
5413 +void br_configuration_update(struct net_bridge *br)
5415 + br_root_selection(br);
5416 + br_designated_port_selection(br);
5419 +/* called under bridge lock */
5420 +void br_become_designated_port(struct net_bridge_port *p)
5422 + struct net_bridge *br;
5425 + p->designated_root = br->designated_root;
5426 + p->designated_cost = br->root_path_cost;
5427 + p->designated_bridge = br->bridge_id;
5428 + p->designated_port = p->port_id;
5431 +/* called under bridge lock */
5432 +static void br_make_blocking(struct net_bridge_port *p)
5434 + if (p->state != BR_STATE_DISABLED &&
5435 + p->state != BR_STATE_BLOCKING) {
5436 + if (p->state == BR_STATE_FORWARDING ||
5437 + p->state == BR_STATE_LEARNING)
5438 + br_topology_change_detection(p->br);
5440 + printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
5441 + p->br->name, p->port_no, p->dev->name, "blocking");
5443 + p->state = BR_STATE_BLOCKING;
5444 + br_timer_clear(&p->forward_delay_timer);
5448 +/* called under bridge lock */
5449 +static void br_make_forwarding(struct net_bridge_port *p)
5451 + if (p->state == BR_STATE_BLOCKING) {
5452 + printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
5453 + p->br->name, p->port_no, p->dev->name, "listening");
5455 + p->state = BR_STATE_LISTENING;
5456 + br_timer_set(&p->forward_delay_timer, jiffies);
5460 +/* called under bridge lock */
5461 +void br_port_state_selection(struct net_bridge *br)
5463 + struct net_bridge_port *p;
5465 + p = br->port_list;
5466 + while (p != NULL) {
5467 + if (p->state != BR_STATE_DISABLED) {
5468 + if (p->port_no == br->root_port) {
5469 + p->config_pending = 0;
5470 + p->topology_change_ack = 0;
5471 + br_make_forwarding(p);
5472 + } else if (br_is_designated_port(p)) {
5473 + br_timer_clear(&p->message_age_timer);
5474 + br_make_forwarding(p);
5476 + p->config_pending = 0;
5477 + p->topology_change_ack = 0;
5478 + br_make_blocking(p);
5486 +/* called under bridge lock */
5487 +static void br_topology_change_acknowledge(struct net_bridge_port *p)
5489 + p->topology_change_ack = 1;
5490 + br_transmit_config(p);
5494 +void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5496 + struct net_bridge *br;
5499 + if (p->state == BR_STATE_DISABLED)
5503 + read_lock(&br->lock);
5505 + was_root = br_is_root_bridge(br);
5506 + if (br_supersedes_port_info(p, bpdu)) {
5507 + br_record_config_information(p, bpdu);
5508 + br_configuration_update(br);
5509 + br_port_state_selection(br);
5511 + if (!br_is_root_bridge(br) && was_root) {
5512 + br_timer_clear(&br->hello_timer);
5513 + if (br->topology_change_detected) {
5514 + br_timer_clear(&br->topology_change_timer);
5515 + br_transmit_tcn(br);
5516 + br_timer_set(&br->tcn_timer, jiffies);
5520 + if (p->port_no == br->root_port) {
5521 + br_record_config_timeout_values(br, bpdu);
5522 + br_config_bpdu_generation(br);
5523 + if (bpdu->topology_change_ack)
5524 + br_topology_change_acknowledged(br);
5526 + } else if (br_is_designated_port(p)) {
5530 + read_unlock(&br->lock);
5534 +void br_received_tcn_bpdu(struct net_bridge_port *p)
5536 + read_lock(&p->br->lock);
5537 + if (p->state != BR_STATE_DISABLED &&
5538 + br_is_designated_port(p)) {
5539 + printk(KERN_INFO "%s: received tcn bpdu on port %i(%s)\n",
5540 + p->br->name, p->port_no, p->dev->name);
5542 + br_topology_change_detection(p->br);
5543 + br_topology_change_acknowledge(p);
5545 + read_unlock(&p->br->lock);
5547 diff -urN linux-2.2.20/net/bridge/br_stp_bpdu.c linux-2.2.20br/net/bridge/br_stp_bpdu.c
5548 --- linux-2.2.20/net/bridge/br_stp_bpdu.c Thu Jan 1 01:00:00 1970
5549 +++ linux-2.2.20br/net/bridge/br_stp_bpdu.c Mon Dec 10 16:24:28 2001
5552 + * Spanning tree protocol; BPDU handling
5553 + * Linux ethernet bridge
5556 + * Lennert Buytenhek <buytenh@gnu.org>
5560 + * This program is free software; you can redistribute it and/or
5561 + * modify it under the terms of the GNU General Public License
5562 + * as published by the Free Software Foundation; either version
5563 + * 2 of the License, or (at your option) any later version.
5566 +#include <linux/config.h>
5567 +#include <linux/kernel.h>
5568 +#include <linux/if_ether.h>
5569 +#include <linux/if_bridge.h>
5570 +#include "br_private.h"
5571 +#include "br_private_stp.h"
5573 +#define JIFFIES_TO_TICKS(j) (((j) << 8) / HZ)
5574 +#define TICKS_TO_JIFFIES(j) (((j) * HZ) >> 8)
5576 +static void br_send_bpdu(struct net_bridge_port *p, unsigned char *data, int length)
5578 + struct device *dev;
5579 + struct sk_buff *skb;
5582 + if (!p->br->stp_enabled)
5585 + size = length + 2*ETH_ALEN + 2;
5591 + if ((skb = dev_alloc_skb(size)) == NULL) {
5592 + printk(KERN_INFO "br: memory squeeze!\n");
5597 + skb->protocol = htons(ETH_P_802_2);
5598 + skb->mac.raw = skb_put(skb, size);
5599 + memcpy(skb->mac.raw, bridge_ula, ETH_ALEN);
5600 + memcpy(skb->mac.raw+ETH_ALEN, dev->dev_addr, ETH_ALEN);
5601 + skb->mac.raw[2*ETH_ALEN] = 0;
5602 + skb->mac.raw[2*ETH_ALEN+1] = length;
5603 + skb->nh.raw = skb->mac.raw + 2*ETH_ALEN + 2;
5604 + memcpy(skb->nh.raw, data, length);
5605 + memset(skb->nh.raw + length, 0xa5, size - length - 2*ETH_ALEN - 2);
5607 + dev_queue_xmit(skb);
5610 +static __inline__ void br_set_ticks(unsigned char *dest, int jiff)
5614 + ticks = JIFFIES_TO_TICKS(jiff);
5615 + dest[0] = (ticks >> 8) & 0xFF;
5616 + dest[1] = ticks & 0xFF;
5619 +static __inline__ int br_get_ticks(unsigned char *dest)
5621 + return TICKS_TO_JIFFIES((dest[0] << 8) | dest[1]);
5624 +void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5626 + unsigned char buf[38];
5634 + buf[6] = BPDU_TYPE_CONFIG;
5635 + buf[7] = (bpdu->topology_change ? 0x01 : 0) |
5636 + (bpdu->topology_change_ack ? 0x80 : 0);
5637 + buf[8] = bpdu->root.prio[0];
5638 + buf[9] = bpdu->root.prio[1];
5639 + buf[10] = bpdu->root.addr[0];
5640 + buf[11] = bpdu->root.addr[1];
5641 + buf[12] = bpdu->root.addr[2];
5642 + buf[13] = bpdu->root.addr[3];
5643 + buf[14] = bpdu->root.addr[4];
5644 + buf[15] = bpdu->root.addr[5];
5645 + buf[16] = (bpdu->root_path_cost >> 24) & 0xFF;
5646 + buf[17] = (bpdu->root_path_cost >> 16) & 0xFF;
5647 + buf[18] = (bpdu->root_path_cost >> 8) & 0xFF;
5648 + buf[19] = bpdu->root_path_cost & 0xFF;
5649 + buf[20] = bpdu->bridge_id.prio[0];
5650 + buf[21] = bpdu->bridge_id.prio[1];
5651 + buf[22] = bpdu->bridge_id.addr[0];
5652 + buf[23] = bpdu->bridge_id.addr[1];
5653 + buf[24] = bpdu->bridge_id.addr[2];
5654 + buf[25] = bpdu->bridge_id.addr[3];
5655 + buf[26] = bpdu->bridge_id.addr[4];
5656 + buf[27] = bpdu->bridge_id.addr[5];
5657 + buf[28] = (bpdu->port_id >> 8) & 0xFF;
5658 + buf[29] = bpdu->port_id & 0xFF;
5660 + br_set_ticks(buf+30, bpdu->message_age);
5661 + br_set_ticks(buf+32, bpdu->max_age);
5662 + br_set_ticks(buf+34, bpdu->hello_time);
5663 + br_set_ticks(buf+36, bpdu->forward_delay);
5665 + br_send_bpdu(p, buf, 38);
5668 +void br_send_tcn_bpdu(struct net_bridge_port *p)
5670 + unsigned char buf[7];
5678 + buf[6] = BPDU_TYPE_TCN;
5679 + br_send_bpdu(p, buf, 7);
5682 +static unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
5684 +void br_stp_handle_bpdu(struct sk_buff *skb)
5686 + unsigned char *buf;
5687 + struct net_bridge_port *p;
5689 + buf = skb->mac.raw + 14;
5690 + p = skb->dev->br_port;
5691 + if (!p->br->stp_enabled || memcmp(buf, header, 6)) {
5696 + if (buf[6] == BPDU_TYPE_CONFIG) {
5697 + struct br_config_bpdu bpdu;
5699 + bpdu.topology_change = (buf[7] & 0x01) ? 1 : 0;
5700 + bpdu.topology_change_ack = (buf[7] & 0x80) ? 1 : 0;
5701 + bpdu.root.prio[0] = buf[8];
5702 + bpdu.root.prio[1] = buf[9];
5703 + bpdu.root.addr[0] = buf[10];
5704 + bpdu.root.addr[1] = buf[11];
5705 + bpdu.root.addr[2] = buf[12];
5706 + bpdu.root.addr[3] = buf[13];
5707 + bpdu.root.addr[4] = buf[14];
5708 + bpdu.root.addr[5] = buf[15];
5709 + bpdu.root_path_cost =
5714 + bpdu.bridge_id.prio[0] = buf[20];
5715 + bpdu.bridge_id.prio[1] = buf[21];
5716 + bpdu.bridge_id.addr[0] = buf[22];
5717 + bpdu.bridge_id.addr[1] = buf[23];
5718 + bpdu.bridge_id.addr[2] = buf[24];
5719 + bpdu.bridge_id.addr[3] = buf[25];
5720 + bpdu.bridge_id.addr[4] = buf[26];
5721 + bpdu.bridge_id.addr[5] = buf[27];
5722 + bpdu.port_id = (buf[28] << 8) | buf[29];
5724 + bpdu.message_age = br_get_ticks(buf+30);
5725 + bpdu.max_age = br_get_ticks(buf+32);
5726 + bpdu.hello_time = br_get_ticks(buf+34);
5727 + bpdu.forward_delay = br_get_ticks(buf+36);
5730 + br_received_config_bpdu(p, &bpdu);
5734 + if (buf[6] == BPDU_TYPE_TCN) {
5735 + br_received_tcn_bpdu(p);
5742 diff -urN linux-2.2.20/net/bridge/br_stp_if.c linux-2.2.20br/net/bridge/br_stp_if.c
5743 --- linux-2.2.20/net/bridge/br_stp_if.c Thu Jan 1 01:00:00 1970
5744 +++ linux-2.2.20br/net/bridge/br_stp_if.c Mon Dec 10 16:24:28 2001
5747 + * Spanning tree protocol; interface code
5748 + * Linux ethernet bridge
5751 + * Lennert Buytenhek <buytenh@gnu.org>
5755 + * This program is free software; you can redistribute it and/or
5756 + * modify it under the terms of the GNU General Public License
5757 + * as published by the Free Software Foundation; either version
5758 + * 2 of the License, or (at your option) any later version.
5761 +#include <linux/config.h>
5762 +#include <linux/kernel.h>
5763 +#include <linux/types.h>
5764 +#include <linux/notifier.h>
5765 +#include <linux/if_bridge.h>
5766 +#include <linux/smp_lock.h>
5767 +#include <asm/uaccess.h>
5768 +#include "br_private.h"
5769 +#include "br_private_stp.h"
5771 +__u16 br_make_port_id(struct net_bridge_port *p)
5773 + return (p->priority << 8) | p->port_no;
5776 +/* called under bridge lock */
5777 +void br_init_port(struct net_bridge_port *p)
5779 + p->port_id = br_make_port_id(p);
5780 + br_become_designated_port(p);
5781 + p->state = BR_STATE_BLOCKING;
5782 + p->topology_change_ack = 0;
5783 + p->config_pending = 0;
5784 + br_timer_clear(&p->message_age_timer);
5785 + br_timer_clear(&p->forward_delay_timer);
5786 + br_timer_clear(&p->hold_timer);
5789 +/* called under bridge lock */
5790 +void br_stp_enable_bridge(struct net_bridge *br)
5792 + struct net_bridge_port *p;
5793 + struct timer_list *timer = &br->tick;
5795 + init_timer(timer);
5796 + timer->data = (unsigned long) br;
5797 + timer->function = br_tick;
5798 + timer->expires = jiffies + 1;
5801 + br_timer_set(&br->hello_timer, jiffies);
5802 + br_config_bpdu_generation(br);
5804 + p = br->port_list;
5805 + while (p != NULL) {
5806 + if (p->dev->flags & IFF_UP)
5807 + br_stp_enable_port(p);
5812 + br_timer_set(&br->gc_timer, jiffies);
5815 +/* called under bridge lock */
5816 +void br_stp_disable_bridge(struct net_bridge *br)
5818 + struct net_bridge_port *p;
5820 + br->topology_change = 0;
5821 + br->topology_change_detected = 0;
5822 + br_timer_clear(&br->hello_timer);
5823 + br_timer_clear(&br->topology_change_timer);
5824 + br_timer_clear(&br->tcn_timer);
5825 + br_timer_clear(&br->gc_timer);
5826 + br_fdb_cleanup(br);
5828 + p = br->port_list;
5829 + while (p != NULL) {
5830 + if (p->state != BR_STATE_DISABLED)
5831 + br_stp_disable_port(p);
5836 + del_timer(&br->tick);
5840 +/* called under bridge lock */
5841 +void br_stp_enable_port(struct net_bridge_port *p)
5844 + br_port_state_selection(p->br);
5847 +/* called under bridge lock */
5848 +void br_stp_disable_port(struct net_bridge_port *p)
5850 + struct net_bridge *br;
5854 + printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
5855 + br->name, p->port_no, p->dev->name, "disabled");
5857 + wasroot = br_is_root_bridge(br);
5858 + br_become_designated_port(p);
5859 + p->state = BR_STATE_DISABLED;
5860 + p->topology_change_ack = 0;
5861 + p->config_pending = 0;
5862 + br_timer_clear(&p->message_age_timer);
5863 + br_timer_clear(&p->forward_delay_timer);
5864 + br_timer_clear(&p->hold_timer);
5865 + br_configuration_update(br);
5866 + br_port_state_selection(br);
5868 + if (br_is_root_bridge(br) && !wasroot)
5869 + br_become_root_bridge(br);
5872 +/* called under bridge lock */
5873 +static void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr)
5875 + unsigned char oldaddr[6];
5876 + struct net_bridge_port *p;
5879 + wasroot = br_is_root_bridge(br);
5881 + memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
5882 + memcpy(br->bridge_id.addr, addr, ETH_ALEN);
5883 + memcpy(br->dev.dev_addr, addr, ETH_ALEN);
5885 + p = br->port_list;
5886 + while (p != NULL) {
5887 + if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN))
5888 + memcpy(p->designated_bridge.addr, addr, ETH_ALEN);
5890 + if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN))
5891 + memcpy(p->designated_root.addr, addr, ETH_ALEN);
5896 + br_configuration_update(br);
5897 + br_port_state_selection(br);
5898 + if (br_is_root_bridge(br) && !wasroot)
5899 + br_become_root_bridge(br);
5902 +static unsigned char br_mac_zero[6] = {0,0,0,0,0,0};
5904 +/* called under bridge lock */
5905 +void br_stp_recalculate_bridge_id(struct net_bridge *br)
5907 + unsigned char *addr;
5908 + struct net_bridge_port *p;
5910 + addr = br_mac_zero;
5912 + p = br->port_list;
5913 + while (p != NULL) {
5914 + if (addr == br_mac_zero ||
5915 + memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
5916 + addr = p->dev->dev_addr;
5921 + if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))
5922 + br_stp_change_bridge_id(br, addr);
5925 +/* called under bridge lock */
5926 +void br_stp_set_bridge_priority(struct net_bridge *br, int newprio)
5928 + struct net_bridge_port *p;
5931 + wasroot = br_is_root_bridge(br);
5933 + p = br->port_list;
5934 + while (p != NULL) {
5935 + if (p->state != BR_STATE_DISABLED &&
5936 + br_is_designated_port(p)) {
5937 + p->designated_bridge.prio[0] = (newprio >> 8) & 0xFF;
5938 + p->designated_bridge.prio[1] = newprio & 0xFF;
5944 + br->bridge_id.prio[0] = (newprio >> 8) & 0xFF;
5945 + br->bridge_id.prio[1] = newprio & 0xFF;
5946 + br_configuration_update(br);
5947 + br_port_state_selection(br);
5948 + if (br_is_root_bridge(br) && !wasroot)
5949 + br_become_root_bridge(br);
5952 +/* called under bridge lock */
5953 +void br_stp_set_port_priority(struct net_bridge_port *p, int newprio)
5955 + __u16 new_port_id;
5957 + p->priority = newprio & 0xFF;
5958 + new_port_id = br_make_port_id(p);
5960 + if (br_is_designated_port(p))
5961 + p->designated_port = new_port_id;
5963 + p->port_id = new_port_id;
5964 + if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) &&
5965 + p->port_id < p->designated_port) {
5966 + br_become_designated_port(p);
5967 + br_port_state_selection(p->br);
5971 +/* called under bridge lock */
5972 +void br_stp_set_path_cost(struct net_bridge_port *p, int path_cost)
5974 + p->path_cost = path_cost;
5975 + br_configuration_update(p->br);
5976 + br_port_state_selection(p->br);
5978 diff -urN linux-2.2.20/net/bridge/br_stp_timer.c linux-2.2.20br/net/bridge/br_stp_timer.c
5979 --- linux-2.2.20/net/bridge/br_stp_timer.c Thu Jan 1 01:00:00 1970
5980 +++ linux-2.2.20br/net/bridge/br_stp_timer.c Mon Dec 10 16:24:28 2001
5983 + * Spanning tree protocol; timer-related code
5984 + * Linux ethernet bridge
5987 + * Lennert Buytenhek <buytenh@gnu.org>
5991 + * This program is free software; you can redistribute it and/or
5992 + * modify it under the terms of the GNU General Public License
5993 + * as published by the Free Software Foundation; either version
5994 + * 2 of the License, or (at your option) any later version.
5997 +#include <linux/config.h>
5998 +#include <linux/kernel.h>
5999 +#include <linux/if_bridge.h>
6000 +#include <linux/smp_lock.h>
6001 +#include <asm/uaccess.h>
6002 +#include "br_private.h"
6003 +#include "br_private_stp.h"
6005 +static void dump_bridge_id(bridge_id *id)
6007 + printk("%.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", id->prio[0],
6008 + id->prio[1], id->addr[0], id->addr[1], id->addr[2], id->addr[3],
6009 + id->addr[4], id->addr[5]);
6012 +/* called under bridge lock */
6013 +static int br_is_designated_for_some_port(struct net_bridge *br)
6015 + struct net_bridge_port *p;
6017 + p = br->port_list;
6018 + while (p != NULL) {
6019 + if (p->state != BR_STATE_DISABLED &&
6020 + !memcmp(&p->designated_bridge, &br->bridge_id, 8))
6029 +/* called under bridge lock */
6030 +static void br_hello_timer_expired(struct net_bridge *br)
6032 + br_config_bpdu_generation(br);
6033 + br_timer_set(&br->hello_timer, jiffies);
6036 +/* called under bridge lock */
6037 +static void br_message_age_timer_expired(struct net_bridge_port *p)
6039 + struct net_bridge *br;
6043 + printk(KERN_INFO "%s: ", br->name);
6044 + printk("neighbour ");
6045 + dump_bridge_id(&p->designated_bridge);
6046 + printk(" lost on port %i(%s)\n", p->port_no, p->dev->name);
6049 + * According to the spec, the message age timer cannot be
6050 + * running when we are the root bridge. So.. this was_root
6051 + * check is redundant. I'm leaving it in for now, though.
6053 + was_root = br_is_root_bridge(br);
6055 + br_become_designated_port(p);
6056 + br_configuration_update(br);
6057 + br_port_state_selection(br);
6058 + if (br_is_root_bridge(br) && !was_root)
6059 + br_become_root_bridge(br);
6062 +/* called under bridge lock */
6063 +static void br_forward_delay_timer_expired(struct net_bridge_port *p)
6065 + if (p->state == BR_STATE_LISTENING) {
6066 + printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
6067 + p->br->name, p->port_no, p->dev->name, "learning");
6069 + p->state = BR_STATE_LEARNING;
6070 + br_timer_set(&p->forward_delay_timer, jiffies);
6071 + } else if (p->state == BR_STATE_LEARNING) {
6072 + printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
6073 + p->br->name, p->port_no, p->dev->name, "forwarding");
6075 + p->state = BR_STATE_FORWARDING;
6076 + if (br_is_designated_for_some_port(p->br))
6077 + br_topology_change_detection(p->br);
6081 +/* called under bridge lock */
6082 +static void br_tcn_timer_expired(struct net_bridge *br)
6084 + printk(KERN_INFO "%s: retransmitting tcn bpdu\n", br->name);
6085 + br_transmit_tcn(br);
6086 + br_timer_set(&br->tcn_timer, jiffies);
6089 +/* called under bridge lock */
6090 +static void br_topology_change_timer_expired(struct net_bridge *br)
6092 + br->topology_change_detected = 0;
6093 + br->topology_change = 0;
6096 +/* called under bridge lock */
6097 +static void br_hold_timer_expired(struct net_bridge_port *p)
6099 + if (p->config_pending)
6100 + br_transmit_config(p);
6103 +/* called under bridge lock */
6104 +static void br_check_port_timers(struct net_bridge_port *p)
6106 + if (br_timer_has_expired(&p->message_age_timer, p->br->max_age)) {
6107 + br_timer_clear(&p->message_age_timer);
6108 + br_message_age_timer_expired(p);
6111 + if (br_timer_has_expired(&p->forward_delay_timer, p->br->forward_delay)) {
6112 + br_timer_clear(&p->forward_delay_timer);
6113 + br_forward_delay_timer_expired(p);
6116 + if (br_timer_has_expired(&p->hold_timer, BR_HOLD_TIME)) {
6117 + br_timer_clear(&p->hold_timer);
6118 + br_hold_timer_expired(p);
6122 +/* called under bridge lock */
6123 +static void br_check_timers(struct net_bridge *br)
6125 + struct net_bridge_port *p;
6127 + if (br_timer_has_expired(&br->gc_timer, br->gc_interval)) {
6128 + br_timer_set(&br->gc_timer, jiffies);
6129 + br_fdb_cleanup(br);
6132 + if (br_timer_has_expired(&br->hello_timer, br->hello_time)) {
6133 + br_timer_clear(&br->hello_timer);
6134 + br_hello_timer_expired(br);
6137 + if (br_timer_has_expired(&br->tcn_timer, br->bridge_hello_time)) {
6138 + br_timer_clear(&br->tcn_timer);
6139 + br_tcn_timer_expired(br);
6142 + if (br_timer_has_expired(&br->topology_change_timer, br->bridge_forward_delay + br->bridge_max_age)) {
6143 + br_timer_clear(&br->topology_change_timer);
6144 + br_topology_change_timer_expired(br);
6147 + p = br->port_list;
6148 + while (p != NULL) {
6149 + if (p->state != BR_STATE_DISABLED)
6150 + br_check_port_timers(p);
6156 +void br_tick(unsigned long __data)
6158 + struct net_bridge *br = (struct net_bridge *)__data;
6160 + read_lock(&br->lock);
6161 + br_check_timers(br);
6162 + read_unlock(&br->lock);
6164 + br->tick.expires = jiffies + 1;
6165 + add_timer(&br->tick);
6167 diff -urN linux-2.2.20/net/bridge/br_tree.c linux-2.2.20br/net/bridge/br_tree.c
6168 --- linux-2.2.20/net/bridge/br_tree.c Sun Mar 25 18:31:13 2001
6169 +++ linux-2.2.20br/net/bridge/br_tree.c Thu Jan 1 01:00:00 1970
6172 - * This code is derived from the avl functions in mmap.c
6175 -#include <linux/kernel.h>
6176 -#include <linux/errno.h>
6177 -#include <linux/string.h>
6178 -#include <linux/malloc.h>
6179 -#include <linux/skbuff.h>
6180 -#include <linux/netdevice.h>
6182 -#include <net/br.h>
6186 - * Use an AVL (Adelson-Velskii and Landis) tree to speed up this search
6187 - * from O(n) to O(log n), where n is the number of ULAs.
6188 - * Written by Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de>.
6189 - * Taken from mmap.c, extensively modified by John Hayes
6190 - * <hayes@netplumbing.com>
6191 - * 98-02 Modified by Jean-Rene Peulve jr.peulve@aix.pacwan.net
6192 - * update port number when topology change
6193 - * return oldfdb when updating, for broadcast storm checking
6194 - * call addr_cmp once per node
6197 -static struct fdb fdb_head;
6198 -static struct fdb *fhp = &fdb_head;
6199 -static struct fdb **fhpp = &fhp;
6200 -static int fdb_inited = 0;
6203 -static void printk_avl (struct fdb * tree);
6206 -static int addr_cmp(unsigned char *a1, unsigned char *a2);
6209 - * fdb_head is the AVL tree corresponding to fdb
6210 - * or, more exactly, its root.
6211 - * A fdb has the following fields:
6212 - * fdb_avl_left left son of a tree node
6213 - * fdb_avl_right right son of a tree node
6214 - * fdb_avl_height 1+max(heightof(left),heightof(right))
6215 - * The empty tree is represented as NULL.
6218 -#ifndef avl_br_empty
6219 -#define avl_br_empty (struct fdb *) NULL
6222 -/* Since the trees are balanced, their height will never be large. */
6223 -#define avl_maxheight 127
6224 -#define heightof(tree) ((tree) == avl_br_empty ? 0 : (tree)->fdb_avl_height)
6226 - * Consistency and balancing rules:
6227 - * 1. tree->fdb_avl_height == 1+max(heightof(tree->fdb_avl_left),heightof(tree->fdb_avl_right))
6228 - * 2. abs( heightof(tree->fdb_avl_left) - heightof(tree->fdb_avl_right) ) <= 1
6229 - * 3. foreach node in tree->fdb_avl_left: node->fdb_avl_key <= tree->fdb_avl_key,
6230 - * foreach node in tree->fdb_avl_right: node->fdb_avl_key >= tree->fdb_avl_key.
6233 -static int fdb_init(void)
6235 - fdb_head.fdb_avl_height = 0;
6236 - fdb_head.fdb_avl_left = (struct fdb *)0;
6237 - fdb_head.fdb_avl_right = (struct fdb *)0;
6242 -struct fdb *br_avl_find_addr(unsigned char addr[6])
6244 - struct fdb * result = NULL;
6245 - struct fdb * tree;
6250 - printk("searching for ula %02x:%02x:%02x:%02x:%02x:%02x\n",
6257 -#endif /* DEBUG_AVL */
6258 - for (tree = fhp ; ; ) {
6259 - if (tree == avl_br_empty) {
6261 - printk("search failed, returning node 0x%x\n", (unsigned int)result);
6262 -#endif /* DEBUG_AVL */
6267 - printk("node 0x%x: checking ula %02x:%02x:%02x:%02x:%02x:%02x\n",
6268 - (unsigned int)tree,
6275 -#endif /* DEBUG_AVL */
6276 - if (addr_cmp(addr, tree->ula) == 0) {
6278 - printk("found node 0x%x\n", (unsigned int)tree);
6279 -#endif /* DEBUG_AVL */
6282 - if (addr_cmp(addr, tree->ula) < 0) {
6283 - tree = tree->fdb_avl_left;
6285 - tree = tree->fdb_avl_right;
6292 - * Rebalance a tree.
6293 - * After inserting or deleting a node of a tree we have a sequence of subtrees
6294 - * nodes[0]..nodes[k-1] such that
6295 - * nodes[0] is the root and nodes[i+1] = nodes[i]->{fdb_avl_left|fdb_avl_right}.
6297 -static void br_avl_rebalance (struct fdb *** nodeplaces_ptr, int count)
6301 - for ( ; count > 0 ; count--) {
6302 - struct fdb ** nodeplace = *--nodeplaces_ptr;
6303 - struct fdb * node = *nodeplace;
6304 - struct fdb * nodeleft = node->fdb_avl_left;
6305 - struct fdb * noderight = node->fdb_avl_right;
6306 - int heightleft = heightof(nodeleft);
6307 - int heightright = heightof(noderight);
6308 - if (heightright + 1 < heightleft) {
6314 - struct fdb * nodeleftleft = nodeleft->fdb_avl_left;
6315 - struct fdb * nodeleftright = nodeleft->fdb_avl_right;
6316 - int heightleftright = heightof(nodeleftright);
6317 - if (heightof(nodeleftleft) >= heightleftright) {
6321 - /* n+2 n --> / n+1|n+2 */
6323 - /* n+1 n|n+1 n+1 n|n+1 n */
6325 - node->fdb_avl_left = nodeleftright;
6326 - nodeleft->fdb_avl_right = node;
6327 - nodeleft->fdb_avl_height = 1 + (node->fdb_avl_height = 1 + heightleftright);
6328 - *nodeplace = nodeleft;
6333 - /* n+2 n --> n+1 n+1 */
6335 - /* n n+1 n L R n */
6339 - nodeleft->fdb_avl_right = nodeleftright->fdb_avl_left;
6340 - node->fdb_avl_left = nodeleftright->fdb_avl_right;
6341 - nodeleftright->fdb_avl_left = nodeleft;
6342 - nodeleftright->fdb_avl_right = node;
6343 - nodeleft->fdb_avl_height = node->fdb_avl_height = heightleftright;
6344 - nodeleftright->fdb_avl_height = heightleft;
6345 - *nodeplace = nodeleftright;
6347 - } else if (heightleft + 1 < heightright) {
6348 - /* similar to the above, just interchange 'left' <--> 'right' */
6349 - struct fdb * noderightright = noderight->fdb_avl_right;
6350 - struct fdb * noderightleft = noderight->fdb_avl_left;
6351 - int heightrightleft = heightof(noderightleft);
6352 - if (heightof(noderightright) >= heightrightleft) {
6353 - node->fdb_avl_right = noderightleft;
6354 - noderight->fdb_avl_left = node;
6355 - noderight->fdb_avl_height = 1 + (node->fdb_avl_height = 1 + heightrightleft);
6356 - *nodeplace = noderight;
6358 - noderight->fdb_avl_left = noderightleft->fdb_avl_right;
6359 - node->fdb_avl_right = noderightleft->fdb_avl_left;
6360 - noderightleft->fdb_avl_right = noderight;
6361 - noderightleft->fdb_avl_left = node;
6362 - noderight->fdb_avl_height = node->fdb_avl_height = heightrightleft;
6363 - noderightleft->fdb_avl_height = heightright;
6364 - *nodeplace = noderightleft;
6367 - int height = (heightleft<heightright ? heightright : heightleft) + 1;
6368 - if (height == node->fdb_avl_height)
6370 - node->fdb_avl_height = height;
6374 - printk_avl(&fdb_head);
6375 -#endif /* DEBUG_AVL */
6378 -/* Insert a node into a tree.
6379 - * Performance improvement:
6380 - * call addr_cmp() only once per node and use result in a switch.
6381 - * Return old node address if we knew that MAC address already
6382 - * Return NULL if we insert the new node
6384 -struct fdb *br_avl_insert (struct fdb * new_node)
6386 - struct fdb ** nodeplace = fhpp;
6387 - struct fdb ** stack[avl_maxheight];
6388 - int stack_count = 0;
6389 - struct fdb *** stack_ptr = &stack[0]; /* = &stack[stackcount] */
6395 - node = *nodeplace;
6396 - if (node == avl_br_empty)
6398 - *stack_ptr++ = nodeplace; stack_count++;
6399 - switch(addr_cmp(new_node->ula, node->ula)) {
6400 - case 0: /* update */
6401 - if (node->port == new_node->port) {
6402 - node->flags = new_node->flags;
6403 - node->timer = new_node->timer;
6404 - } else if (!(node->flags & FDB_ENT_VALID) &&
6406 - /* update fdb but never for local interfaces */
6408 - printk("node 0x%x:port changed old=%d new=%d\n",
6409 - (unsigned int)node, node->port,new_node->port);
6411 - /* JRP: update port as well if the topology change !
6412 - * Don't do this while entry is still valid otherwise
6413 - * a broadcast that we flooded and is reentered by another
6414 - * port would mess up the good port number.
6415 - * The fdb list per port needs to be updated as well.
6417 - requeue_fdb(node, new_node->port);
6418 - node->flags = new_node->flags;
6419 - node->timer = new_node->timer;
6421 - printk_avl(&fdb_head);
6422 -#endif /* DEBUG_AVL */
6424 - return node; /* pass old fdb to caller */
6426 - case 1: /* new_node->ula > node->ula */
6427 - nodeplace = &node->fdb_avl_right;
6429 - default: /* -1 => new_node->ula < node->ula */
6430 - nodeplace = &node->fdb_avl_left;
6434 - printk("node 0x%x: adding ula %02x:%02x:%02x:%02x:%02x:%02x\n",
6435 - (unsigned int)new_node,
6441 - new_node->ula[5]);
6442 -#endif /* (DEBUG_AVL) */
6443 - new_node->fdb_avl_left = avl_br_empty;
6444 - new_node->fdb_avl_right = avl_br_empty;
6445 - new_node->fdb_avl_height = 1;
6446 - *nodeplace = new_node;
6447 - br_avl_rebalance(stack_ptr,stack_count);
6449 - printk_avl(&fdb_head);
6450 -#endif /* DEBUG_AVL */
6451 - return NULL; /* this is a new node */
6455 -/* Removes a node out of a tree. */
6456 -static int br_avl_remove (struct fdb * node_to_delete)
6458 - struct fdb ** nodeplace = fhpp;
6459 - struct fdb ** stack[avl_maxheight];
6460 - int stack_count = 0;
6461 - struct fdb *** stack_ptr = &stack[0]; /* = &stack[stackcount] */
6462 - struct fdb ** nodeplace_to_delete;
6466 - struct fdb * node = *nodeplace;
6467 - if (node == avl_br_empty) {
6468 - /* what? node_to_delete not found in tree? */
6469 - printk(KERN_ERR "br: avl_remove: node to delete not found in tree\n");
6472 - *stack_ptr++ = nodeplace; stack_count++;
6473 - if (addr_cmp(node_to_delete->ula, node->ula) == 0)
6475 - if (addr_cmp(node_to_delete->ula, node->ula) < 0)
6476 - nodeplace = &node->fdb_avl_left;
6478 - nodeplace = &node->fdb_avl_right;
6480 - nodeplace_to_delete = nodeplace;
6481 - /* Have to remove node_to_delete = *nodeplace_to_delete. */
6482 - if (node_to_delete->fdb_avl_left == avl_br_empty) {
6483 - *nodeplace_to_delete = node_to_delete->fdb_avl_right;
6484 - stack_ptr--; stack_count--;
6486 - struct fdb *** stack_ptr_to_delete = stack_ptr;
6487 - struct fdb ** nodeplace = &node_to_delete->fdb_avl_left;
6488 - struct fdb * node;
6490 - node = *nodeplace;
6491 - if (node->fdb_avl_right == avl_br_empty)
6493 - *stack_ptr++ = nodeplace; stack_count++;
6494 - nodeplace = &node->fdb_avl_right;
6496 - *nodeplace = node->fdb_avl_left;
6497 - /* node replaces node_to_delete */
6498 - node->fdb_avl_left = node_to_delete->fdb_avl_left;
6499 - node->fdb_avl_right = node_to_delete->fdb_avl_right;
6500 - node->fdb_avl_height = node_to_delete->fdb_avl_height;
6501 - *nodeplace_to_delete = node; /* replace node_to_delete */
6502 - *stack_ptr_to_delete = &node->fdb_avl_left; /* replace &node_to_delete->fdb_avl_left */
6504 - br_avl_rebalance(stack_ptr,stack_count);
6511 -static void printk_avl (struct fdb * tree)
6513 - if (tree != avl_br_empty) {
6515 - printk("%02x:%02x:%02x:%02x:%02x:%02x(%d)",
6523 - if (tree->fdb_avl_left != avl_br_empty) {
6524 - printk_avl(tree->fdb_avl_left);
6527 - if (tree->fdb_avl_right != avl_br_empty) {
6529 - printk_avl(tree->fdb_avl_right);
6535 -static char *avl_check_point = "somewhere";
6537 -/* check a tree's consistency and balancing */
6538 -static void avl_checkheights (struct fdb * tree)
6542 - if (tree == avl_br_empty)
6544 - avl_checkheights(tree->fdb_avl_left);
6545 - avl_checkheights(tree->fdb_avl_right);
6546 - h = tree->fdb_avl_height;
6547 - hl = heightof(tree->fdb_avl_left);
6548 - hr = heightof(tree->fdb_avl_right);
6549 - if ((h == hl+1) && (hr <= hl) && (hl <= hr+1))
6551 - if ((h == hr+1) && (hl <= hr) && (hr <= hl+1))
6553 - printk("%s: avl_checkheights: heights inconsistent\n",avl_check_point);
6556 -/* check that all values stored in a tree are < key */
6557 -static void avl_checkleft (struct fdb * tree, fdb_avl_key_t key)
6559 - if (tree == avl_br_empty)
6561 - avl_checkleft(tree->fdb_avl_left,key);
6562 - avl_checkleft(tree->fdb_avl_right,key);
6563 - if (tree->fdb_avl_key < key)
6565 - printk("%s: avl_checkleft: left key %lu >= top key %lu\n",avl_check_point,tree->fdb_avl_key,key);
6568 -/* check that all values stored in a tree are > key */
6569 -static void avl_checkright (struct fdb * tree, fdb_avl_key_t key)
6571 - if (tree == avl_br_empty)
6573 - avl_checkright(tree->fdb_avl_left,key);
6574 - avl_checkright(tree->fdb_avl_right,key);
6575 - if (tree->fdb_avl_key > key)
6577 - printk("%s: avl_checkright: right key %lu <= top key %lu\n",avl_check_point,tree->fdb_avl_key,key);
6580 -/* check that all values are properly increasing */
6581 -static void avl_checkorder (struct fdb * tree)
6583 - if (tree == avl_br_empty)
6585 - avl_checkorder(tree->fdb_avl_left);
6586 - avl_checkorder(tree->fdb_avl_right);
6587 - avl_checkleft(tree->fdb_avl_left,tree->fdb_avl_key);
6588 - avl_checkright(tree->fdb_avl_right,tree->fdb_avl_key);
6591 -#endif /* DEBUG_AVL */
6593 -static int addr_cmp(unsigned char a1[], unsigned char a2[])
6597 - for (i=0; i<6; i++) {
6598 - if (a1[i] > a2[i]) return(1);
6599 - if (a1[i] < a2[i]) return(-1);
6604 -/* Vova Oksman: function for copy tree to the buffer */
6605 -void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,
6606 - int* len, off_t offset, int length)
6611 - if(avl_br_empty == tree)
6612 - /* begin from the root */
6617 - if (*pos >= offset+length)
6620 - if (tree != avl_br_empty) {
6621 - /* don't write the local device */
6622 - if(tree->port != 0){
6623 - size = sprintf(*pbuffer,
6624 - "%02x:%02x:%02x:%02x:%02x:%02x %s %d %ld\n",
6625 - tree->ula[0],tree->ula[1],tree->ula[2],
6626 - tree->ula[3],tree->ula[4],tree->ula[5],
6627 - port_info[tree->port].dev->name, tree->flags,CURRENT_TIME-tree->timer);
6633 - if (*pos <= offset)
6636 - if (tree->fdb_avl_left != avl_br_empty) {
6637 - sprintf_avl (pbuffer,tree->fdb_avl_left,pos,len,offset,length);
6639 - if (tree->fdb_avl_right != avl_br_empty) {
6640 - sprintf_avl (pbuffer,tree->fdb_avl_right,pos,len,offset,length);
6649 - * Delete all nodes learnt by the port
6651 -void br_avl_delete_by_port(int port)
6653 - struct fdb *fdb, *next;
6658 - for(fdb = port_info[port].fdb; fdb != NULL; fdb = next) {
6659 - next = fdb->fdb_next;
6660 - br_avl_remove(fdb);
6662 - port_info[port].fdb = NULL;
6664 - /* remove the local mac too */
6665 -/* next = br_avl_find_addr(port_info[port].dev->dev_addr); */
6666 - next = br_avl_find_addr(port_info[port].ifmac.BRIDGE_ID_ULA);
6668 - br_avl_remove(next);
6672 diff -urN linux-2.2.20/net/bridge/sysctl_net_bridge.c linux-2.2.20br/net/bridge/sysctl_net_bridge.c
6673 --- linux-2.2.20/net/bridge/sysctl_net_bridge.c Sun Mar 25 18:31:13 2001
6674 +++ linux-2.2.20br/net/bridge/sysctl_net_bridge.c Thu Jan 1 01:00:00 1970
6677 - * sysctl_net_bridge.c: sysctl interface to net bridge subsystem.
6679 - * Begun June 1, 1996, Mike Shaver.
6680 - * Added /proc/sys/net/bridge directory entry (empty =) ). [MS]
6683 -#include <linux/mm.h>
6684 -#include <linux/sysctl.h>
6686 -ctl_table bridge_table[] = {
6689 diff -urN linux-2.2.20/net/core/dev.c linux-2.2.20br/net/core/dev.c
6690 --- linux-2.2.20/net/core/dev.c Fri Nov 2 17:39:16 2001
6691 +++ linux-2.2.20br/net/core/dev.c Mon Dec 10 16:24:28 2001
6693 #include <linux/rtnetlink.h>
6694 #include <linux/proc_fs.h>
6695 #include <linux/stat.h>
6696 -#include <net/br.h>
6697 +#include <linux/if_bridge.h>
6698 #include <linux/divert.h>
6699 #include <net/dst.h>
6700 #include <net/pkt_sched.h>
6701 @@ -810,35 +810,8 @@
6705 -#ifdef CONFIG_BRIDGE
6706 -static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
6709 - * The br_stats.flags is checked here to save the expense of a
6712 - if ((br_stats.flags & BR_UP) && br_call_bridge(skb, type))
6715 - * We pass the bridge a complete frame. This means
6716 - * recovering the MAC header first.
6721 - skb=skb_clone(skb, GFP_ATOMIC);
6725 - offset=skb->data-skb->mac.raw;
6726 - skb_push(skb,offset); /* Put header back on for bridge */
6728 - if(br_receive_frame(skb))
6734 +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
6735 +void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL;
6739 @@ -955,11 +928,6 @@
6744 - * Fetch the packet protocol ID.
6747 - type = skb->protocol;
6749 #ifdef CONFIG_NET_DIVERT
6751 @@ -970,15 +938,6 @@
6752 #endif /* CONFIG_NET_DIVERT */
6755 -#ifdef CONFIG_BRIDGE
6757 - * If we are bridging then pass the frame up to the
6758 - * bridging code (if this protocol is to be bridged).
6759 - * If it is bridged then move on
6761 - handle_bridge(skb, type);
6765 * We got a packet ID. Now loop over the "known protocols"
6766 * list. There are two lists. The ptype_all list of taps (normally empty)
6767 @@ -986,19 +945,44 @@
6771 - for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next)
6772 + for (ptype = ptype_all; ptype != NULL; ptype = ptype->next)
6774 if (!ptype->dev || ptype->dev == skb->dev) {
6778 - struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
6780 - pt_prev->func(skb2,skb->dev, pt_prev);
6781 + struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
6783 + pt_prev->func(skb2, skb->dev, pt_prev);
6791 + * Is there a last item to send to ?
6796 + struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
6798 + pt_prev->func(skb2, skb->dev, pt_prev);
6802 +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
6803 + if (skb->dev->br_port != NULL && br_handle_frame_hook != NULL) {
6804 + br_handle_frame_hook(skb);
6810 + * Fetch the packet protocol ID.
6813 + type = skb->protocol;
6815 for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next)
6817 if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))
6818 @@ -1007,7 +991,8 @@
6819 * We already have a match queued. Deliver
6820 * to it and then remember the new match
6826 struct sk_buff *skb2;
6828 @@ -1032,13 +1017,14 @@
6831 pt_prev->func(skb, skb->dev, pt_prev);
6834 * Has an unknown packet has been received ?
6842 } /* End of queue loop */
6845 @@ -1963,12 +1949,11 @@
6846 skb_queue_head_init(&backlog);
6849 - * The bridge has to be up before the devices
6850 + * Initialize the ethernet bridge.
6853 -#ifdef CONFIG_BRIDGE
6854 +#ifdef CONFIG_BRIDGE
6860 * Frame Diverter init
6861 @@ -2083,13 +2068,6 @@
6865 -#ifdef CONFIG_BRIDGE
6867 - * Register any statically linked ethernet devices with the bridge
6869 - br_spacedevice_register();
6875 diff -urN linux-2.2.20/net/core/skbuff.c linux-2.2.20br/net/core/skbuff.c
6876 --- linux-2.2.20/net/core/skbuff.c Sun Mar 25 18:31:12 2001
6877 +++ linux-2.2.20br/net/core/skbuff.c Mon Dec 10 16:24:28 2001
6880 skb->destructor = NULL;
6881 skb->pkt_type = PACKET_HOST; /* Default type */
6882 - skb->pkt_bridged = 0; /* Not bridged */
6883 skb->prev = skb->next = NULL;
6886 diff -urN linux-2.2.20/net/ipv4/af_inet.c linux-2.2.20br/net/ipv4/af_inet.c
6887 --- linux-2.2.20/net/ipv4/af_inet.c Fri Nov 2 17:39:16 2001
6888 +++ linux-2.2.20br/net/ipv4/af_inet.c Mon Dec 10 16:24:28 2001
6889 @@ -106,10 +106,8 @@
6890 #ifdef CONFIG_IP_MASQUERADE
6891 #include <net/ip_masq.h>
6893 -#ifdef CONFIG_BRIDGE
6894 -#include <net/br.h>
6897 +#include <linux/if_bridge.h>
6899 #ifdef CONFIG_NET_DIVERT
6900 #include <linux/divert.h>
6901 #endif /* CONFIG_NET_DIVERT */
6903 int (*dlci_ioctl_hook)(unsigned int, void *) = NULL;
6906 +int (*br_ioctl_hook)(unsigned long) = NULL;
6907 int (*rarp_ioctl_hook)(unsigned int,void*) = NULL;
6910 @@ -913,11 +912,15 @@
6911 return(devinet_ioctl(cmd,(void *) arg));
6914 -#ifdef CONFIG_BRIDGE
6915 - return(br_ioctl(cmd,(void *) arg));
6918 + if (br_ioctl_hook == NULL)
6919 + request_module("bridge");
6922 + if (br_ioctl_hook != NULL)
6923 + return br_ioctl_hook(arg);
6930 diff -urN linux-2.2.20/net/netsyms.c linux-2.2.20br/net/netsyms.c
6931 --- linux-2.2.20/net/netsyms.c Sun Mar 25 18:37:41 2001
6932 +++ linux-2.2.20br/net/netsyms.c Mon Dec 10 16:24:28 2001
6935 #include <net/pkt_sched.h>
6936 #include <net/scm.h>
6938 -#ifdef CONFIG_BRIDGE
6939 -#include <net/br.h>
6941 +#include <linux/if_bridge.h>
6943 #ifdef CONFIG_NET_DIVERT
6944 #include <linux/divert.h>
6945 @@ -225,9 +222,10 @@
6947 EXPORT_SYMBOL(scm_detach_fds);
6949 -#ifdef CONFIG_BRIDGE
6950 -EXPORT_SYMBOL(br_ioctl);
6951 +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
6952 +EXPORT_SYMBOL(br_handle_frame_hook);
6954 +EXPORT_SYMBOL(br_ioctl_hook);
6956 #ifdef CONFIG_NET_DIVERT
6957 EXPORT_SYMBOL(alloc_divert_blk);
6958 diff -urN linux-2.2.20/net/packet/af_packet.c linux-2.2.20br/net/packet/af_packet.c
6959 --- linux-2.2.20/net/packet/af_packet.c Sun Mar 25 18:31:14 2001
6960 +++ linux-2.2.20br/net/packet/af_packet.c Mon Dec 10 16:24:28 2001
6962 #include <asm/uaccess.h>
6963 #include <linux/module.h>
6964 #include <linux/init.h>
6965 +#include <linux/if_bridge.h>
6968 #include <net/inet_common.h>
6971 -#ifdef CONFIG_BRIDGE
6972 -#include <net/br.h>
6975 #ifdef CONFIG_NET_DIVERT
6976 #include <linux/divert.h>
6977 @@ -1131,11 +1129,15 @@
6981 -#ifdef CONFIG_BRIDGE
6982 - return(br_ioctl(cmd,(void *) arg));
6985 + if (br_ioctl_hook == NULL)
6986 + request_module("bridge");
6989 + if (br_ioctl_hook != NULL)
6990 + return br_ioctl_hook(arg);
6997 diff -urN linux-2.2.20/net/sysctl_net.c linux-2.2.20br/net/sysctl_net.c
6998 --- linux-2.2.20/net/sysctl_net.c Sun Mar 25 18:31:13 2001
6999 +++ linux-2.2.20br/net/sysctl_net.c Mon Dec 10 16:24:28 2001
7001 extern ctl_table ether_table[], e802_table[];
7004 -#ifdef CONFIG_BRIDGE
7005 -extern ctl_table bridge_table[];
7009 extern ctl_table ipv6_table[];
7013 {NET_IPX, "ipx", NULL, 0, 0555, ipx_table},
7015 -#ifdef CONFIG_BRIDGE
7016 - {NET_BRIDGE, "bridge", NULL, 0, 0555, bridge_table},
7019 {NET_IPV6, "ipv6", NULL, 0, 0555, ipv6_table},