]> git.pld-linux.org Git - packages/kernel.git/blob - bridge-1.0.2-against-2.2.20.diff
- obsolete
[packages/kernel.git] / bridge-1.0.2-against-2.2.20.diff
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
4 @@ -346,6 +346,13 @@
5  S: Orlando, Florida
6  S: USA
7  
8 +N: Lennert Buytenhek
9 +E: buytenh@gnu.org
10 +D: Rewrite of the ethernet bridging code
11 +S: Ravenhorst 58B
12 +S: 2317 AK Leiden
13 +S: The Netherlands
14 +
15  N: Michael Callahan
16  E: callahan@maths.ox.ac.uk
17  D: PPP for Linux
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. 
24  
25 -Bridging (EXPERIMENTAL)
26 +802.1d Ethernet Bridging
27  CONFIG_BRIDGE
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. 
36  
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.
42 +
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.
52 +
53 +  If unsure, say N.
54  
55  Frame Diverter (EXPERIMENTAL)
56  CONFIG_NET_DIVERT
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
60 @@ -0,0 +1,11 @@
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.
67 +
68 +
69 +
70 +Lennert Buytenhek
71 +<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
75 @@ -370,6 +370,13 @@
76  L:     linux-net@vger.kernel.org
77  S:     Maintained
78  
79 +ETHERNET BRIDGE
80 +P:     Lennert Buytenhek
81 +M:     buytenh@gnu.org
82 +L:     bridge@math.leidenuniv.nl
83 +W:     http://www.math.leidenuniv.nl/~buytenh/bridge
84 +S:     Maintained
85 +
86  ETHERTEAM 16I DRIVER
87  P:      Mika Kuoppala
88  M:      miku@iki.fi
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
92 @@ -0,0 +1,110 @@
93 +/*
94 + *     Linux ethernet bridge
95 + *
96 + *     Authors:
97 + *     Lennert Buytenhek               <buytenh@gnu.org>
98 + *
99 + *     $Id$
100 + *
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.
105 + */
106 +
107 +#ifndef _LINUX_IF_BRIDGE_H
108 +#define _LINUX_IF_BRIDGE_H
109 +
110 +#include <linux/types.h>
111 +
112 +#define BRCTL_VERSION 1
113 +
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
133 +
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
139 +
140 +struct __bridge_info
141 +{
142 +       __u64 designated_root;
143 +       __u64 bridge_id;
144 +       __u32 root_path_cost;
145 +       __u32 max_age;
146 +       __u32 hello_time;
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;
153 +       __u8 root_port;
154 +       __u8 stp_enabled;
155 +       __u32 ageing_time;
156 +       __u32 gc_interval;
157 +       __u32 hello_timer_value;
158 +       __u32 tcn_timer_value;
159 +       __u32 topology_change_timer_value;
160 +       __u32 gc_timer_value;
161 +};
162 +
163 +struct __port_info
164 +{
165 +       __u64 designated_root;
166 +       __u64 designated_bridge;
167 +       __u16 port_id;
168 +       __u16 designated_port;
169 +       __u32 path_cost;
170 +       __u32 designated_cost;
171 +       __u8 state;
172 +       __u8 top_change_ack;
173 +       __u8 config_pending;
174 +       __u8 unused0;
175 +       __u32 message_age_timer_value;
176 +       __u32 forward_delay_timer_value;
177 +       __u32 hold_timer_value;
178 +};
179 +
180 +struct __fdb_entry
181 +{
182 +       __u8 mac_addr[6];
183 +       __u8 port_no;
184 +       __u8 is_local;
185 +       __u32 ageing_timer_value;
186 +       __u32 unused;
187 +};
188 +
189 +#ifdef __KERNEL__
190 +
191 +#include <linux/netdevice.h>
192 +
193 +struct net_bridge;
194 +struct net_bridge_port;
195 +
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);
199 +
200 +#endif
201 +
202 +#endif
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
206 @@ -270,9 +270,6 @@
207         struct Qdisc            *qdisc_list;
208         unsigned long           tx_queue_len;   /* Max frames per queue allowed */
209  
210 -       /* Bridge stuff */
211 -       int                     bridge_port_id;         
212 -       
213         /* Pointers to interface service routines.      */
214         int                     (*open)(struct device *dev);
215         int                     (*stop)(struct device *dev);
216 @@ -310,6 +307,9 @@
217         int                     (*neigh_setup)(struct device *dev, struct neigh_parms *);
218         int                     (*accept_fastpath)(struct device *, struct dst_entry*);
219  
220 +       /* bridge stuff */
221 +       struct net_bridge_port  *br_port;
222 +
223  #ifdef CONFIG_NET_FASTROUTE
224         /* Really, this semaphore may be necessary and for not fastroute code;
225            f.e. SMP??
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
229 @@ -83,7 +83,6 @@
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
240 @@ -1,331 +0,0 @@
241 -/*
242 - * Constants and structure definitions for the bridging code
243 - */
244 -
245 -#if !defined(One)
246 -#define Zero    0
247 -#define One    1
248 -#endif  /* !defined(One) */
249 -
250 -#if !defined(TRUE)
251 -#define FALSE   0
252 -#define TRUE   1
253 -#endif /* !defined(TRUE) */
254 -
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)     */
261 -
262 -
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!
265 - */
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
270 -#endif
271 -#define No_of_ports CONFIG_BRIDGE_NUM_PORTS
272 -/* arbitrary choice, to allow the code below to compile */
273 -
274 -#define All_ports (No_of_ports + 1)
275 -
276 -/*
277 - * We time out our entries in the FDB after this many seconds.
278 - */
279 -#define FDB_TIMEOUT    20 /* JRP: 20s as NSC bridge code, was 300 for Linux */
280 -
281 -/*
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.
286 - */
287 -#define BRIDGE_MAX_AGE         20
288 -#define BRIDGE_HELLO_TIME      2
289 -#define BRIDGE_FORWARD_DELAY   15
290 -#define HOLD_TIME              1
291 -
292 -/* broacast/multicast storm limitation. This per source. */
293 -#define MAX_MCAST_PER_PERIOD    32
294 -#define MCAST_HOLD_TIME                (10*HZ/100)
295 -
296 -#define Default_path_cost 10
297 -
298 -/*
299 - * minimum increment possible to avoid underestimating age, allows for BPDU
300 - * transmission time
301 - */
302 -#define Message_age_increment 1
303 -
304 -#define No_port 0
305 -/*
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
309 - */
310 -
311 -/** Configuration BPDU Parameters (4.5.1) **/
312 -
313 -typedef struct {
314 -       union {
315 -               struct {
316 -                       unsigned short priority;
317 -                       unsigned char ula[6];
318 -               } p_u;
319 -               unsigned int id[2];
320 -       } bi;
321 -} bridge_id_t;
322 -
323 -#define BRIDGE_PRIORITY        bi.p_u.priority
324 -#define BRIDGE_ID_ULA  bi.p_u.ula
325 -#define BRIDGE_ID      bi.id
326 -
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
330 - */ 
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
341 -
342 -typedef struct {
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;
356 -} Config_bpdu;
357 -
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);
366 -#else
367 -#define config_bpdu_hton(config_bpdu)
368 -#endif
369 -#define config_bpdu_ntoh config_bpdu_hton
370 -
371 -
372 -/** Topology Change Notification BPDU Parameters (4.5.2) **/
373 -
374 -typedef struct {
375 -       unsigned short  protocol_id;    
376 -       unsigned char   protocol_version_id;
377 -       unsigned char   type;
378 -} Tcn_bpdu;
379 -
380 -#define BPDU_TYPE_CONFIG       0
381 -#define BPDU_TYPE_TOPO_CHANGE  128
382 -
383 -/** Bridge Parameters (4.5.3) **/
384 -typedef struct {
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;
400 -} Bridge_data;
401 -
402 -/** Port Parameters (4.5.5) **/
403 -typedef struct {
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)   */
413 -        bridge_id_t      ifmac; 
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 */
418 -} Port_data;
419 -
420 -
421 -
422 -/** types to support timers for this pseudo-implementation. **/
423 -typedef struct {
424 -       unsigned int     active;                          /* timer in use. */
425 -       unsigned int     value;                   /* current value of timer,
426 -                                                  * counting up. */
427 -} Timer;
428 -
429 -struct fdb {
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 */
438 -       
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;
445 -};
446 -
447 -/* data returned on BRCMD_DISPLAY_FDB */
448 -struct fdb_info {
449 -       unsigned char ula[6];
450 -       unsigned char port;
451 -        unsigned char flags;
452 -        unsigned int timer;
453 -};
454 -struct fdb_info_hdr {
455 -       int     copied;                 /* nb of entries copied to user */
456 -       int     not_copied;             /* when user buffer is too small */
457 -       int     cmd_time;
458 -};     
459 -
460 -#define IS_BRIDGED     0x2e
461 -
462 -
463 -#define BR_MAX_PROTOCOLS 32
464 -#define BR_MAX_PROT_STATS BR_MAX_PROTOCOLS
465 -
466 -/* policy values for policy field */
467 -#define BR_ACCEPT 1
468 -#define BR_REJECT 0
469 -
470 -/* JRP: extra statistics for debug */
471 -typedef struct {
472 -       /* br_receive_frame counters */
473 -       int port_disable_up_stack;
474 -       int rcv_bpdu;
475 -       int notForwarding;
476 -       int forwarding_up_stack;
477 -       int unknown_state;
478 -
479 -       /* br_tx_frame counters */
480 -       int port_disable;
481 -       int port_not_disable;
482 -
483 -       /* br_forward counters */
484 -       int local_multicast;
485 -       int forwarded_multicast;        /* up stack as well */
486 -       int flood_unicast;
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;
496 -} br_stats_counter;
497 -
498 -struct br_stat {
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];
509 -};
510 -
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 */
516 -
517 -struct br_cf {
518 -       unsigned int cmd;
519 -       unsigned int arg1;
520 -       unsigned int arg2;
521 -};
522 -
523 -/* defined cmds */
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 */
544 -
545 -/* prototypes of exported bridging functions... */
546 -
547 -#ifdef __KERNEL__
548 -void br_init(void);
549 -int br_receive_frame(struct sk_buff *skb);     /* 3.5 */
550 -int br_tx_frame(struct sk_buff *skb);
551 -int brg_init(void);
552 -int br_ioctl(unsigned int cmd, void *arg);
553 -void requeue_fdb(struct fdb *node, int new_port);
554 -
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);
562 -
563 -/* externs */
564 -
565 -extern struct br_stat br_stats;
566 -extern Port_data port_info[];
567 -
568 -#endif
569 -
570 -
571
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
575 @@ -31,6 +31,7 @@
576    source net/ipx/Config.in
577  fi
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
583 @@ -38,10 +39,6 @@
584  #  fi
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
590 -  fi
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
597 @@ -59,6 +59,10 @@
598  
599  ifeq ($(CONFIG_BRIDGE),y)
600  SUB_DIRS += bridge
601 +else
602 +  ifeq ($(CONFIG_BRIDGE),m)
603 +    MOD_SUB_DIRS += bridge
604 +  endif
605  endif
606  
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
611 @@ -7,6 +7,7 @@
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
622 @@ -1,5 +1,5 @@
623  #
624 -# Makefile for the Linux Bridge layer.
625 +# Makefile for the IEEE 802.1d ethernet bridging layer.
626  #
627  # Note! Dependencies are done automagically by 'make dep', which also
628  # removes any old dependencies. DON'T put your own dependencies here
629 @@ -7,15 +7,10 @@
630  #
631  # Note 2! The CFLAGS definition is now in the main makefile...
632  
633 -O_TARGET := bridge.o
634 -O_OBJS  := br.o br_tree.o
635 -M_OBJS   := $(O_TARGET)
636 -
637 -ifeq ($(CONFIG_SYSCTL),y)
638 -O_OBJS += sysctl_net_bridge.o
639 -endif
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)
645  
646  include $(TOPDIR)/Rules.make
647 -
648 -tar:
649 -               tar -cvf /dev/f1 .
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
653 @@ -1,2775 +1,63 @@
654  /*
655 - *     Linux NET3 Bridge Support
656 + *     Generic parts
657 + *     Linux ethernet bridge
658   *
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
665 + *     Authors:
666 + *     Lennert Buytenhek               <buytenh@gnu.org>
667 + *
668 + *     $Id$
669   *
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.
674 - *
675 - * Fixes:
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)
697 - *
698 - *     Alan Cox:       Merged Jean-Rene's stuff, reformatted stuff a bit
699 - *                     so blame me first if its broken ;)
700 - *
701 - *     Robert Pintarelli:      fixed bug in bpdu time values
702 - *
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.
712 - *     
713 - *     Todo:
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.
720 - *     
721   */
722
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>
729  
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>
751 -#include <net/br.h>
752 -#include <linux/proc_fs.h>
753 -#include <linux/delay.h>
754 -
755 -#ifndef min
756 -#define min(a, b) (((a) <= (b)) ? (a) : (b))
757 -#endif
758 -
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);
829 -
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)     */
833 -
834 -/* MAG: Maximum port registered - used to speed up flooding and to make
835 - * have a large ports array more efficient
836 - */
837 -static int max_port_used = 0; 
838 -
839 -/* JRP: fdb cache 1/port save kmalloc/kfree on every frame */
840 -struct fdb     *newfdb[All_ports];
841 -int allocated_fdb_cnt = 0;
842 -
843 -/* broacast/multicast storm limitation */
844 -int max_mcast_per_period = MAX_MCAST_PER_PERIOD;
845 -int mcast_hold_time     = MCAST_HOLD_TIME;
846 -
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];
852 -
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)   */
859 -
860 -/* entries timeout after this many seconds */
861 -unsigned int fdb_aging_time = FDB_TIMEOUT; 
862 -
863 -struct br_stat br_stats;
864 -#define br_stats_cnt br_stats.packet_cnts
865 -
866 -static struct timer_list tl; /* for 1 second timer... */
867 -
868 -/*
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).
872 - */
873 -static struct notifier_block br_dev_notifier={
874 -       br_device_event,
875 -       NULL,
876 -       0
877 -};
878 -
879 -
880 -/* 
881 - * the following data is for the bridge network device
882 - */
883 -struct brg_if {
884 -  struct device dev;
885 -  char name[IFNAMSIZ];
886 -};
887 -static struct brg_if brg_if;
888 -
889 -/* 
890 - * Here to save linkage? problems
891 - */
892 -
893 -static inline int find_port(struct device *dev)
894 -{
895 -       int i;
896 -
897 -       for (i = One; i <= No_of_ports; i++)
898 -               if (port_info[i].dev == dev)
899 -                       return(i);
900 -       return(0);
901 -}
902 -
903 -/*
904 - * Implementation of Protocol specific bridging
905 - *
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
908 - * is occupied.
909 - */
910 -
911 -#define BR_PROTOCOL_HASH(x) (x % BR_MAX_PROTOCOLS)
912 -
913 -/* Checks if that protocol type is to be bridged */
914 -
915 -static int inline br_protocol_ok(unsigned short protocol)
916 -{
917 -       unsigned x;
918 -       
919 -       /* See if protocol statistics are to be kept */
920 -       if (br_stats.flags & BR_PROT_STATS)
921 -       {
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)
924 -               {
925 -                       br_stats.prot_id[x]=protocol;br_stats.prot_counter[x]++;
926 -               }
927 -       }
928 -
929 -       for (x=BR_PROTOCOL_HASH(protocol); br_stats.protocols[x]!=0;) 
930 -       {
931 -               if (br_stats.protocols[x]==protocol)
932 -                       return !br_stats.policy;
933 -               x++;
934 -               if (x==BR_MAX_PROTOCOLS)
935 -                       x=0;
936 -       }
937 -       return br_stats.policy;
938 -}
939 -
940 -/* Add a protocol to be handled opposite to the standard policy of the bridge */
941 -
942 -static int br_add_exempt_protocol(unsigned short p)
943 -{
944 -       unsigned x;
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 */
949 -               x++;
950 -               if (x==BR_MAX_PROTOCOLS) x=0;
951 -       }
952 -       br_stats.protocols[x]=p;
953 -       br_stats.exempt_protocols++;
954 -       return 0;
955 -}
956 -
957 -/* Valid Policies are 0=No Protocols bridged 1=Bridge all protocols */
958 -static int br_set_policy(int policy)
959 -{
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;
965 -       return 0;
966 -}
967 -
968 -
969 -/** Elements of Procedure (4.6) **/
970 -
971 -/*
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.
977 - */
978 -
979 -static void transmit_config(int port_no)         /* (4.6.1)     */
980 -{
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;
992 -               /*
993 -                * (4.6.1.3.2(4))
994 -                */
995 -               if (root_bridge()) {
996 -                       config_bpdu.message_age = Zero; /* (4.6.1.3.2(5)) */
997 -               } else {
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)) */
1001 -               }
1002 -
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;
1010 -
1011 -               config_bpdu.top_change = 
1012 -                       bridge_info.top_change;         /* (4.6.1.3.2(9)) */
1013 -
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)) */
1017 -       }
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
1020 - */
1021 -       mark_bh(NET_BH);
1022 -}
1023 +#include "br_private.h"
1024  
1025 -static int root_bridge(void)
1026 +void br_dec_use_count()
1027  {
1028 -       return (br_cmp(bridge_info.designated_root.BRIDGE_ID,
1029 -                bridge_info.bridge_id.BRIDGE_ID)?FALSE:TRUE);
1030 +       MOD_DEC_USE_COUNT;
1031  }
1032  
1033 -static int supersedes_port_info(int port_no, Config_bpdu *config)        /* (4.6.2.2)   */
1034 +void br_inc_use_count()
1035  {
1036 -       return (
1037 -               (br_cmp(config->root_id.BRIDGE_ID,
1038 -                port_info[port_no].designated_root.BRIDGE_ID) < 0)     /* (4.6.2.2.1)   */ 
1039 -               ||
1040 -               ((br_cmp(config->root_id.BRIDGE_ID,
1041 -                 port_info[port_no].designated_root.BRIDGE_ID) == 0
1042 -                 )
1043 -                &&
1044 -                ((config->root_path_cost
1045 -                  < port_info[port_no].designated_cost /* (4.6.2.2.2)   */
1046 -                  )
1047 -                 ||
1048 -                 ((config->root_path_cost
1049 -                   == port_info[port_no].designated_cost
1050 -                   )
1051 -                  &&
1052 -                  ((br_cmp(config->bridge_id.BRIDGE_ID,
1053 -                    port_info[port_no].designated_bridge.BRIDGE_ID) < 0        /* (4.6.2.2.3)    */
1054 -                    )
1055 -                   ||
1056 -                   ((br_cmp(config->bridge_id.BRIDGE_ID,
1057 -                     port_info[port_no].designated_bridge.BRIDGE_ID) == 0
1058 -                     )                           /* (4.6.2.2.4)         */
1059 -                    &&
1060 -                    ((br_cmp(config->bridge_id.BRIDGE_ID,
1061 -                       bridge_info.bridge_id.BRIDGE_ID) != 0
1062 -                      )                          /* (4.6.2.2.4(1)) */
1063 -                     ||
1064 -                     (config->port_id <=
1065 -                      port_info[port_no].designated_port
1066 -                      )                          /* (4.6.2.2.4(2)) */
1067 -                     ))))))
1068 -               );
1069 +       MOD_INC_USE_COUNT;
1070  }
1071  
1072 -static void record_config_information(int port_no, Config_bpdu *config)          /* (4.6.2)     */
1073 +__initfunc(int br_init(void))
1074  {
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)   */
1080 -}
1081 -
1082 -static void record_config_timeout_values(Config_bpdu *config)            /* (4.6.3)     */
1083 -{
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;
1088 -}
1089 -
1090 -static void config_bpdu_generation(void)
1091 -{                                                /* (4.6.4)     */
1092 -       int             port_no;
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)   */
1095 -                               &&
1096 -                               (port_info[port_no].state != Disabled)
1097 -                       ) {
1098 -                       transmit_config(port_no); /* (4.6.4.3)   */
1099 -               }                                 /* (4.6.1.2)   */
1100 -       }
1101 -}
1102 -
1103 -static int designated_port(int port_no)
1104 -{
1105 -       return ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1106 -                bridge_info.bridge_id.BRIDGE_ID) == 0
1107 -                )
1108 -               &&
1109 -               (port_info[port_no].designated_port
1110 -                == port_info[port_no].port_id
1111 -                )
1112 -               );
1113 -}
1114 -
1115 -static void reply(int port_no)                                   /* (4.6.5)     */
1116 -{
1117 -       transmit_config(port_no);                 /* (4.6.5.3)   */
1118 -}
1119 -
1120 -static void transmit_tcn(void)
1121 -{                                                /* (4.6.6)     */
1122 -       int             port_no;
1123 -
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)     */
1127 -}
1128 -
1129 -static void configuration_update(void) /* (4.6.7) */
1130 -{
1131 -       root_selection();                         /* (4.6.7.3.1)         */
1132 -       /* (4.6.8.2)     */
1133 -       designated_port_selection();              /* (4.6.7.3.2)         */
1134 -       /* (4.6.9.2)     */
1135 -}
1136 -
1137 -static void root_selection(void)
1138 -{                                                /* (4.6.8) */
1139 -       int             root_port;
1140 -       int             port_no;
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))
1144 -                    &&
1145 -                    (port_info[port_no].state != Disabled)
1146 -                    &&
1147 -               (br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1148 -                       bridge_info.bridge_id.BRIDGE_ID) < 0)
1149 -                       )
1150 -                               &&
1151 -                               ((root_port == No_port)
1152 -                                ||
1153 -                                (br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1154 -                                 port_info[root_port].designated_root.BRIDGE_ID) < 0
1155 -                                 )
1156 -                                ||
1157 -                                ((br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1158 -                                  port_info[root_port].designated_root.BRIDGE_ID) == 0
1159 -                                  )
1160 -                                 &&
1161 -                                 (((port_info[port_no].designated_cost
1162 -                                    + port_info[port_no].path_cost
1163 -                                    )
1164 -                                   <
1165 -                                   (port_info[root_port].designated_cost
1166 -                                    + port_info[root_port].path_cost
1167 -                                    )            /* (4.6.8.3.1(2)) */
1168 -                                   )
1169 -                                  ||
1170 -                                  (((port_info[port_no].designated_cost
1171 -                                     + port_info[port_no].path_cost
1172 -                                     )
1173 -                                    ==
1174 -                                    (port_info[root_port].designated_cost
1175 -                                     + port_info[root_port].path_cost
1176 -                                     )
1177 -                                    )
1178 -                                   &&
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)) */
1182 -                                    ||
1183 -                                    ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1184 -                                  port_info[root_port].designated_bridge.BRIDGE_ID) == 0
1185 -                                      )
1186 -                                     &&
1187 -                                     ((port_info[port_no].designated_port
1188 -                                     < port_info[root_port].designated_port
1189 -                                       )         /* (4.6.8.3.1(4)) */
1190 -                                      ||
1191 -                                      ((port_info[port_no].designated_port
1192 -/* JRP: was missing an "=" ! */              == port_info[root_port].designated_port
1193 -                                        )
1194 -                                       &&
1195 -                                       (port_info[port_no].port_id
1196 -                                        < port_info[root_port].port_id
1197 -                                        )        /* (4.6.8.3.1(5)) */
1198 -                                       ))))))))) {
1199 -                       root_port = port_no;
1200 -               }
1201 -       }
1202 -       bridge_info.root_port = root_port;        /* (4.6.8.3.1)         */
1203 -
1204 -       if (root_port == No_port) {               /* (4.6.8.3.2)         */
1205 -#ifdef DEBUG_STP
1206 -               if (br_stats.flags & BR_DEBUG)
1207 -                       printk(KERN_DEBUG "root_selection: becomes root\n");
1208 -#endif
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)) */
1218 -       }
1219 -}
1220 -
1221 -static void designated_port_selection(void)
1222 -{                                                /* (4.6.9)     */
1223 -       int             port_no;
1224 -
1225 -       for (port_no = One; port_no <= No_of_ports; port_no++) {        /* (4.6.9.3)     */
1226 -               if(port_info[port_no].state == Disabled)
1227 -                       continue;
1228 -               if (designated_port(port_no)      /* (4.6.9.3.1)         */
1229 -                               ||
1230 -                               (
1231 -                                br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1232 -                                bridge_info.designated_root.BRIDGE_ID) != 0
1233 -                                )
1234 -                               ||
1235 -                               (bridge_info.root_path_cost
1236 -                                < port_info[port_no].designated_cost
1237 -                                )                /* (4.6.9.3.3)         */
1238 -                               ||
1239 -                               ((bridge_info.root_path_cost
1240 -                                 == port_info[port_no].designated_cost
1241 -                                 )
1242 -                                &&
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)         */
1246 -                                 ||
1247 -                                 ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
1248 -                                   port_info[port_no].designated_bridge.BRIDGE_ID) == 0
1249 -                                   )
1250 -                                  &&
1251 -                                  (port_info[port_no].port_id
1252 -                                   <= port_info[port_no].designated_port
1253 -                                   )             /* (4.6.9.3.5)         */
1254 -                                  )))) {
1255 -                       become_designated_port(port_no);        /* (4.6.10.3.2.2) */
1256 -               }
1257 -       }
1258 -}
1259 -
1260 -static void become_designated_port(int port_no)
1261 -{                                                /* (4.6.10)    */
1262 -
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;
1271 -}
1272 +       printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n");
1273  
1274 -static void port_state_selection(void)
1275 -{                                                /* (4.6.11) */
1276 -       int             port_no;
1277 -       char            *state_str;
1278 -       for (port_no = One; port_no <= No_of_ports; port_no++) {
1279 -
1280 -               if(port_info[port_no].state == Disabled)
1281 -                       continue;
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)) */
1296 -               }
1297 -#ifdef DEBUG_STP
1298 -               if (br_stats.flags & BR_DEBUG)
1299 -                       printk(KERN_DEBUG "port_state_selection: becomes %s port %d\n",
1300 -                               state_str, port_no);
1301 -#endif
1302 -               
1303 -       }
1304 -
1305 -}
1306 -
1307 -static void make_forwarding(int port_no)
1308 -{                                                /* (4.6.12) */
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) */
1312 -       }
1313 -}
1314 -
1315 -static void topology_change_detection(void)
1316 -{                                                /* (4.6.14)       */
1317 -#ifdef DEBUG_STP
1318 -       if ((br_stats.flags & BR_DEBUG)
1319 -           && (bridge_info.top_change_detected == 0))
1320 -               printk(KERN_DEBUG "topology_change_detected\n");
1321 -#endif
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)) */
1328 -       }
1329 -       bridge_info.top_change_detected = 1;    /* (4.6.14.3.3) */
1330 -}
1331 -
1332 -static void topology_change_acknowledged(void)
1333 -{                                                /* (4.6.15) */
1334 -#ifdef DEBUG_STP
1335 -       if (br_stats.flags & BR_DEBUG)
1336 -               printk(KERN_DEBUG "topology_change_acked\n");
1337 -#endif
1338 -       bridge_info.top_change_detected = 0;    /* (4.6.15.3.1) */
1339 -       stop_tcn_timer();                         /* (4.6.15.3.2) */
1340 -}
1341 -
1342 -static void acknowledge_topology_change(int port_no)
1343 -{                                                /* (4.6.16) */
1344 -       port_info[port_no].top_change_ack = 1;
1345 -       transmit_config(port_no);                 /* (4.6.16.3.2) */
1346 -}
1347 -
1348 -static void make_blocking(int port_no)                           /* (4.6.13)    */
1349 -{
1350 -
1351 -       if ((port_info[port_no].state != Disabled)
1352 -                       &&
1353 -                       (port_info[port_no].state != Blocking)
1354 -       /* (4.6.13.3)    */
1355 -               ) {
1356 -               if ((port_info[port_no].state == Forwarding)
1357 -                               ||
1358 -                               (port_info[port_no].state == Learning)
1359 -                       ) {
1360 -                       topology_change_detection();    /* (4.6.13.3.1) */
1361 -                       /* (4.6.14.2.3)  */
1362 -               }
1363 -               set_port_state(port_no, Blocking);/* (4.6.13.3.2) */
1364 -               stop_forward_delay_timer(port_no);/* (4.6.13.3.3) */
1365 -       }
1366 -}
1367 -
1368 -static void set_port_state(int port_no, int state)
1369 -{
1370 -       port_info[port_no].state = state;
1371 -}
1372 -
1373 -static void received_config_bpdu(int port_no, Config_bpdu *config)               /* (4.7.1)     */
1374 -{
1375 -       int root;
1376 -
1377 -       root = root_bridge();
1378 -       if (port_info[port_no].state != Disabled) {
1379 -
1380 -#ifdef DEBUG_STP
1381 -               if (br_stats.flags & BR_DEBUG)
1382 -                       printk(KERN_DEBUG "received_config_bpdu: port %d\n",
1383 -                               port_no);
1384 -#endif
1385 -               if (supersedes_port_info(port_no, config)) {    /* (4.7.1.1)     *//* (4.
1386 -                                                                * 6.2.2)        */
1387 -                       record_config_information(port_no, config);     /* (4.7.1.1.1)   */
1388 -                       /* (4.6.2.2)     */
1389 -                       configuration_update();   /* (4.7.1.1.2)         */
1390 -                       /* (4.6.7.2.1)   */
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();
1399 -                               }
1400 -                       }
1401 -                       if (port_no == bridge_info.root_port) {
1402 -                               record_config_timeout_values(config);   /* (4.7.1.1.6)   */
1403 -                               /* (4.6.3.2)     */
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)    */
1407 -                               }
1408 -                       }
1409 -               } else if (designated_port(port_no)) {  /* (4.7.1.2)     */
1410 -                       reply(port_no);           /* (4.7.1.2.1)         */
1411 -                       /* (4.6.5.2)     */
1412 -               }
1413 -       }
1414 -}
1415 -
1416 -static void received_tcn_bpdu(int port_no, Tcn_bpdu *tcn)                        /* (4.7.2)     */
1417 -{
1418 -       if (port_info[port_no].state != Disabled) {
1419 -#ifdef DEBUG_STP
1420 -               if (br_stats.flags & BR_DEBUG)
1421 -                       printk(KERN_DEBUG "received_tcn_bpdu: port %d\n",
1422 -                               port_no);
1423 -#endif
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)  */
1429 -       }
1430 -}
1431 -
1432 -static void hello_timer_expiry(void)
1433 -{                                                /* (4.7.3)     */
1434 -       config_bpdu_generation();                 /* (4.6.4.2.2)         */
1435 -       start_hello_timer();
1436 -}
1437 -
1438 -static void message_age_timer_expiry(int port_no) /* (4.7.4)    */
1439 -{
1440 -       int root;
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);
1445  
1446 -#ifdef DEBUG_STP
1447 -       if (br_stats.flags & BR_DEBUG)
1448 -               printk(KERN_DEBUG "message_age_timer_expiry: port %d\n",
1449 -                       port_no);
1450 -#endif
1451 -       become_designated_port(port_no);          /* (4.7.4.1)   */
1452 -       /* (4.6.10.2.1)  */
1453 -       configuration_update();                   /* (4.7.4.2)   */
1454 -       /* (4.6.7.2.2)   */
1455 -       port_state_selection();                   /* (4.7.4.3)   */
1456 -       /* (4.6.11.2.2)  */
1457 -       if ((root_bridge()) && (!root)) {         /* (4.7.4.4)   */
1458 -
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)         */
1466 -               /* (4.6.4.4.3)   */
1467 -               start_hello_timer();
1468 -       }
1469 -}
1470 -
1471 -static void forward_delay_timer_expiry(int port_no)    /* (4.7.5)       */
1472 -{
1473 -       if (port_info[port_no].state == Listening) 
1474 -       {                                               /* (4.7.5.1)     */
1475 -               set_port_state(port_no, Learning);      /* (4.7.5.1.1)   */
1476 -               start_forward_delay_timer(port_no);     /* (4.7.5.1.2)   */
1477 -       }
1478 -       else if (port_info[port_no].state == Learning) 
1479 -       {
1480 -                                                       /* (4.7.5.2) */
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) */
1485 -
1486 -               }
1487 -       }
1488 -}
1489 -
1490 -static int designated_for_some_port(void)
1491 -{
1492 -       int port_no;
1493 -
1494 -       for (port_no = One; port_no <= No_of_ports; port_no++) 
1495 -       {
1496 -               if(port_info[port_no].state == Disabled)
1497 -                       continue;
1498 -               if ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1499 -                               bridge_info.bridge_id.BRIDGE_ID) == 0)) 
1500 -               {
1501 -                       return (TRUE);
1502 -               }
1503 -       }
1504 -       return (FALSE);
1505 -}
1506 -
1507 -static void tcn_timer_expiry(void)
1508 -{                                                /* (4.7.6)     */
1509 -       transmit_tcn();                           /* (4.7.6.1)   */
1510 -       start_tcn_timer();                        /* (4.7.6.2)   */
1511 -}
1512 -
1513 -static void topology_change_timer_expiry(void)
1514 -{                                                /* (4.7.7)     */
1515 -       bridge_info.top_change_detected = 0;    /* (4.7.7.1) */
1516 -       bridge_info.top_change = 0;
1517 -         /* (4.7.7.2)   */
1518 -}
1519 -
1520 -static void hold_timer_expiry(int port_no)       /* (4.7.8)     */
1521 -{
1522 -       if (port_info[port_no].config_pending) 
1523 -       {
1524 -               transmit_config(port_no);         /* (4.7.8.1)   */
1525 -       }                                         /* (4.6.1.2.3)         */
1526 -}
1527 -
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)
1531 -{
1532 -       int size;
1533 -       int len=0;
1534 -       off_t pos=0;
1535 -       char* pbuffer;
1536 -
1537 -       if(0==offset)
1538 -       {
1539 -               /* first time write the header */
1540 -               size = sprintf(buffer,"%s","MAC address           Device     Flags     Age (sec.)\n");
1541 -               len=size;
1542 -       }
1543 -
1544 -       pbuffer=&buffer[len];
1545 -       sprintf_avl(&pbuffer,NULL,&pos,&len,offset,length);
1546 -
1547 -       *start = buffer+len-(pos-offset);       /* Start of wanted data */
1548 -       len = pos-offset;                       /* Start slop */
1549 -       if (len>length)
1550 -               len = length;                   /* Ending slop */
1551 -
1552 -       return len;
1553 -}
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,
1559 -       br_tree_get_info
1560 -};
1561 -#endif
1562 -__initfunc(void br_init(void))
1563 -{                                                /* (4.8.1)     */
1564 -       int port_no;
1565 -
1566 -       printk(KERN_INFO "NET4: Ethernet Bridge 007 for NET4.0\n");
1567 -
1568 -       /* Set up brg device information */
1569 -       bridge_info.instance = 0;
1570 -       brg_init();
1571 -
1572 -       max_port_used = 0;
1573 -       
1574 -       /*
1575 -        * Form initial topology change time.
1576 -        * The topology change timer is only used if this is the root bridge.
1577 -        */
1578 -       
1579 -       bridge_info.topology_change_time = BRIDGE_MAX_AGE + BRIDGE_FORWARD_DELAY;       /* (4.5.3.13) */
1580 -
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;
1584 -#ifdef DEBUG_STP
1585 -       printk(KERN_INFO "br_init: becomes root\n");
1586 -#endif
1587 -
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;
1592 -
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;
1596 -
1597 -       bridge_info.top_change_detected = 0;
1598 -       bridge_info.top_change = 0;
1599 -       stop_tcn_timer();
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);
1608 -       }
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;
1615 -       add_timer(&tl);
1616 -#endif 
1617 -
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);
1626 -#endif
1627 -}
1628 -
1629 -static inline unsigned short make_port_id(int port_no)
1630 -{
1631 -        return (port_priority[port_no] << 8) | port_no;
1632 -}
1633 -
1634 -static void br_init_port(int port_no)
1635 -{
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)         */
1644 -}
1645 -
1646 -static void enable_port(int port_no)                             /* (4.8.2)     */
1647 -{
1648 -       br_init_port(port_no);
1649 -       port_state_selection();                   /* (4.8.2.7)   */
1650 -}                                                /* */
1651 -
1652 -static void disable_port(int port_no)                            /* (4.8.3)     */
1653 -{
1654 -       int         root;
1655 -
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();
1673 -       }
1674 -}
1675 -
1676 -
1677 -static void set_bridge_priority(bridge_id_t *new_bridge_id)
1678 -                                                 /* (4.8.4)     */
1679 -{
1680 -
1681 -       int root;
1682 -       int port_no;
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)
1686 -                       continue;
1687 -               if (designated_port(port_no)) {
1688 -                       port_info[port_no].designated_bridge = *new_bridge_id;
1689 -               }
1690 -       }
1691 -
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();
1703 -       }
1704 -}
1705 -
1706 -static void set_port_priority(int port_no)
1707 -                                                 /* (4.8.5)     */
1708 -{int new_port_id = make_port_id(port_no);
1709 -
1710 -       if (designated_port(port_no)) {           /* (4.8.5.2)   */
1711 -               port_info[port_no].designated_port = new_port_id;
1712 -       }
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
1716 -            )
1717 -                       &&
1718 -                       (port_info[port_no].port_id
1719 -                        < port_info[port_no].designated_port
1720 -
1721 -                        )
1722 -               ) 
1723 -       {
1724 -               become_designated_port(port_no);  /* (4.8.5.4.1) */
1725 -               port_state_selection();           /* (4.8.5.4.2) */
1726 -       }
1727 -}
1728 -
1729 -static void set_path_cost(int port_no, unsigned short path_cost)
1730 -                                                  /* (4.8.6)    */
1731 -{
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)   */
1735 -}
1736 -
1737 -static void br_tick(unsigned long arg)
1738 -{
1739 -       int port_no;
1740 -
1741 -       if(!(br_stats.flags & BR_UP))
1742 -               return;                  /* JRP: we have been shot down */
1743 -
1744 -       if (hello_timer_expired())
1745 -               hello_timer_expiry();
1746 -
1747 -       if (tcn_timer_expired())
1748 -               tcn_timer_expiry();
1749 -
1750 -       if (topology_change_timer_expired())
1751 -               topology_change_timer_expiry();
1752 -
1753 -       for (port_no = One; port_no <= No_of_ports; port_no++) 
1754 -       {
1755 -               if(port_info[port_no].state == Disabled)
1756 -                       continue;
1757 -
1758 -               if (forward_delay_timer_expired(port_no)) 
1759 -                       forward_delay_timer_expiry(port_no);
1760 -
1761 -               if (message_age_timer_expired(port_no))
1762 -                       message_age_timer_expiry(port_no);
1763 -
1764 -               if (hold_timer_expired(port_no))
1765 -                       hold_timer_expiry(port_no);
1766 -       }
1767 -       /* call me again sometime... */
1768 -       tl.expires = jiffies+HZ;        /* 1 second */
1769 -       tl.function = br_tick;
1770 -       add_timer(&tl);
1771 -}
1772 -
1773 -static void start_hello_timer(void)
1774 -{
1775 -       hello_timer.value = 0;
1776 -       hello_timer.active = TRUE;
1777 -}
1778 -
1779 -static void stop_hello_timer(void)
1780 -{
1781 -       hello_timer.active = FALSE;
1782 -}
1783 -
1784 -static int hello_timer_expired(void)
1785 -{
1786 -       if (hello_timer.active && (++hello_timer.value >= bridge_info.hello_time)) 
1787 -       {
1788 -               hello_timer.active = FALSE;
1789 -               return (TRUE);
1790 -       }
1791 -       return (FALSE);
1792 -}
1793 -
1794 -static void start_tcn_timer(void)
1795 -{
1796 -       tcn_timer.value = 0;
1797 -       tcn_timer.active = TRUE;
1798 -}
1799 -
1800 -static void stop_tcn_timer(void)
1801 -{
1802 -       tcn_timer.active = FALSE;
1803 -}
1804 -
1805 -static int tcn_timer_expired(void)
1806 -{
1807 -       if (tcn_timer.active && (++tcn_timer.value >= bridge_info.bridge_hello_time)) 
1808 -       {
1809 -               tcn_timer.active = FALSE;
1810 -               return (TRUE);
1811 -       }
1812 -       return (FALSE);
1813 -
1814 -}
1815 -
1816 -static void start_topology_change_timer(void)
1817 -{
1818 -       topology_change_timer.value = 0;
1819 -       topology_change_timer.active = TRUE;
1820 -}
1821 -
1822 -static void stop_topology_change_timer(void)
1823 -{
1824 -       topology_change_timer.active = FALSE;
1825 -}
1826 -
1827 -static int topology_change_timer_expired(void)
1828 -{
1829 -       if (topology_change_timer.active
1830 -               && (++topology_change_timer.value >= bridge_info.topology_change_time )) 
1831 -       {
1832 -               topology_change_timer.active = FALSE;
1833 -               return (TRUE);
1834 -       }
1835 -       return (FALSE);
1836 -}
1837 -
1838 -static void start_message_age_timer(int port_no, unsigned short message_age)
1839 -{
1840 -       message_age_timer[port_no].value = message_age;
1841 -       message_age_timer[port_no].active = TRUE;
1842 -}
1843 -
1844 -static void stop_message_age_timer(int port_no)
1845 -{
1846 -       message_age_timer[port_no].active = FALSE;
1847 -}
1848 -
1849 -static int message_age_timer_expired(int port_no)
1850 -{
1851 -       if (message_age_timer[port_no].active && (++message_age_timer[port_no].value >= bridge_info.max_age)) 
1852 -       {
1853 -               message_age_timer[port_no].active = FALSE;
1854 -               return (TRUE);
1855 -       }
1856 -       return (FALSE);
1857 -}
1858 -
1859 -static void start_forward_delay_timer(int port_no)
1860 -{
1861 -       forward_delay_timer[port_no].value = 0;
1862 -       forward_delay_timer[port_no].active = TRUE;
1863 -}
1864 -
1865 -static void stop_forward_delay_timer(int port_no)
1866 -{
1867 -       forward_delay_timer[port_no].active = FALSE;
1868 -}
1869 -
1870 -static int forward_delay_timer_expired(int port_no)
1871 -{
1872 -       if (forward_delay_timer[port_no].active && (++forward_delay_timer[port_no].value >= bridge_info.forward_delay)) 
1873 -       {
1874 -               forward_delay_timer[port_no].active = FALSE;
1875 -               return (TRUE);
1876 -       }
1877 -       return (FALSE);
1878 -}
1879 -
1880 -static void start_hold_timer(int port_no)
1881 -{
1882 -       hold_timer[port_no].value = 0;
1883 -       hold_timer[port_no].active = TRUE;
1884 -}
1885 -
1886 -static void stop_hold_timer(int port_no)
1887 -{
1888 -       hold_timer[port_no].active = FALSE;
1889 -}
1890 -
1891 -static int hold_timer_expired(int port_no)
1892 -{
1893 -       if (hold_timer[port_no].active &&
1894 -                  (++hold_timer[port_no].value >= bridge_info.hold_time)) 
1895 -       {
1896 -               hold_timer[port_no].active = FALSE;
1897 -               return (TRUE);
1898 -       }
1899 -       return (FALSE);
1900 -
1901 -}
1902 -
1903 -static struct sk_buff *alloc_bridge_skb(int port_no, int pdu_size, char *pdu_name)
1904 -{
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; 
1911
1912 -       size = 60;      /* minimum Ethernet frame - CRC */
1913 -
1914 -       if (port_info[port_no].state == Disabled) 
1915 -       {
1916 -               printk(KERN_DEBUG "send_%s_bpdu: port %i not valid\n", pdu_name, port_no);
1917 -               return NULL;
1918 -       }
1919 -
1920 -       skb = alloc_skb(size, GFP_ATOMIC);
1921 -       if (skb == NULL) 
1922 -       {
1923 -               printk(KERN_DEBUG "send_%s_bpdu: no skb available\n", pdu_name);
1924 -               return NULL;
1925 -       }
1926 -       skb->dev = dev;
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);
1932
1933 -       if (br_stats.flags & BR_DEBUG)
1934 -               printk(KERN_DEBUG "send_%s_bpdu: port %i src %02x:%02x:%02x:%02x:%02x:%02x\n",
1935 -                       pdu_name,
1936 -                       port_no,
1937 -                       eth->h_source[0],
1938 -                       eth->h_source[1],
1939 -                       eth->h_source[2],
1940 -                       eth->h_source[3],
1941 -                       eth->h_source[4],
1942 -                       eth->h_source[5]);
1943 -#if 0
1944 - /* 8038 is used in older DEC spanning tree protocol which uses a
1945 -  * different pdu layout as well
1946 -  */
1947 -       eth->h_proto = htons(0x8038);
1948 -#endif
1949 -       eth->h_proto = htons(pdu_size + BRIDGE_LLC1_HS);
1950 -  
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;
1958 -  
1959 -       /* mark that we've been here... */
1960 -       skb->pkt_bridged = IS_BRIDGED;
1961 -       return skb;
1962 -}
1963
1964 -static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
1965 -{
1966 -       struct sk_buff *skb;
1967 -       
1968 -       /*
1969 -        *      Keep silent when disabled or when STP disabled
1970 -        */
1971 -        
1972 -       if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
1973 -               return -1;
1974 -
1975 -       /*
1976 -        *      Create and send the message
1977 -        */
1978 -        
1979 -       skb = alloc_bridge_skb(port_no, BRIDGE_BPDU_8021_CONFIG_SIZE,
1980 -                               "config");
1981 -       if (skb == NULL)
1982 -               return(-1);
1983 -
1984 -       /* copy fields before "flags" */
1985 -       memcpy(skb->nh.raw, config_bpdu, BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
1986 -
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;
1993 -
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);
1999 -
2000 -       dev_queue_xmit(skb);
2001 -       return(0);
2002 -}
2003 -  
2004 -static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
2005 -{
2006 -       struct sk_buff *skb;
2007 -       
2008 -       /*
2009 -        *      Keep silent when disabled or when STP disabled
2010 -        */
2011 -        
2012 -       if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
2013 -               return -1;
2014 -       
2015 -       
2016 -       skb = alloc_bridge_skb(port_no, sizeof(Tcn_bpdu), "tcn");
2017 -       if (skb == NULL)
2018 -               return(-1);
2019 -  
2020 -       memcpy(skb->nh.raw, bpdu, sizeof(Tcn_bpdu));
2021 -  
2022 -       dev_queue_xmit(skb);
2023 -       return(0);
2024 -}
2025 -
2026 -static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
2027 -{
2028 -       struct device *dev = ptr;
2029 -       int i;
2030 -
2031 -       /* check for loopback devices */
2032 -       if (dev->flags & IFF_LOOPBACK)
2033 -               return(NOTIFY_DONE);
2034 -
2035 -       if (dev == &brg_if.dev)
2036 -         return(NOTIFY_DONE);  /* Don't attach the brg device to a port! */
2037 -       
2038 -       switch (event) 
2039 -       {
2040 -               case NETDEV_DOWN:
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++) 
2045 -                       {
2046 -                               if (port_info[i].dev == dev) 
2047 -                               {
2048 -                                       disable_port(i);
2049 -                                       return NOTIFY_DONE;
2050 -                                       break;
2051 -                               }
2052 -                       }
2053 -                       break;
2054 -               case NETDEV_UP:
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++) 
2062 -                       {
2063 -                               if (port_info[i].dev == NULL || port_info[i].dev == dev) 
2064 -                               {
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)) 
2073 -                                       {
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);
2078 -                                       }
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)) 
2085 -                                       {
2086 -                                               /* don't start if user said so */
2087 -                                                       enable_port(i);
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;
2092 -                                               else
2093 -                                                       make_forwarding(i);
2094 -                                       }
2095 -                                       return NOTIFY_DONE;
2096 -                                       break;
2097 -                               }
2098 -                       }
2099 -                       break;
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++) 
2110 -                       {
2111 -                               if (port_info[i].dev == NULL || port_info[i].dev == dev) 
2112 -                               {
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;
2123 -                                       break;
2124 -                               }
2125 -                       }
2126 -                       break;
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);
2131 -                        if (i > 0) {
2132 -                               br_avl_delete_by_port(i);
2133 -                               memset(port_info[i].ifmac.BRIDGE_ID_ULA, 0, 6);
2134 -                               port_info[i].dev = NULL;
2135 -                       }
2136 -                       break;
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);
2141 -                        if (i <= 0)  
2142 -                         break;
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! */
2145 -                       if (dev->start) {
2146 -                         printk(KERN_CRIT "br_device_event: NETDEV_CHANGEADDR on busy device %s - FIX DRIVER!\n", 
2147 -                                dev->name);
2148 -                       /*  return NOTIFY_BAD;  It SHOULD be this, but I want to be friendly... */
2149 -                         return NOTIFY_DONE;
2150 -                       }
2151 -                       br_avl_delete_by_port(i);
2152 -                       memset(port_info[i].ifmac.BRIDGE_ID_ULA, 0, 6);
2153 -                       break;
2154 -       }
2155 -       return NOTIFY_DONE;
2156 -}
2157 -
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
2161 - */
2162 -void br_spacedevice_register(void) 
2163 -{
2164 -       struct device *dev;
2165 -       for( dev = dev_base; dev != NULL; dev = dev->next)
2166 -       {
2167 -               br_device_event(NULL, NETDEV_REGISTER, dev);
2168 -       }
2169 -}      
2170 -
2171 -
2172 -/* This is for SPEED in the kernel in net_bh.c */
2173 -
2174 -int br_call_bridge(struct sk_buff *skb, unsigned short type)
2175 -{
2176 -       int port;
2177 -       struct device *dev;
2178 -  
2179 -#if 0  /* Checked first in handle_bridge to save expense of function call */ 
2180 -       if(!(br_stats.flags & BR_UP))
2181 -               return 0;
2182 -#endif
2183 -  
2184 -       dev = skb->dev;
2185 -
2186 -       /* Check for brg0 device
2187 -        */
2188 -       if (dev == &brg_if.dev)
2189 -               return 0;
2190 -                
2191 -       port = dev->bridge_port_id;
2192 -
2193 -       if(!port)
2194 -               return 0;
2195 -
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",
2200 -                               dev->name,
2201 -                               dev->bridge_port_id);
2202 -               return 0;
2203 -       }
2204 -
2205 -       if(user_port_state[port] == Disabled)
2206 -               return 0;
2207 -  
2208 -       if (!br_protocol_ok(ntohs(type)))
2209 -               return 0;
2210 -
2211 -       return 1;
2212 -
2213 -}
2214 -
2215 -
2216 -/*
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
2220 - */
2221 -
2222 -int br_receive_frame(struct sk_buff *skb)      /* 3.5 */
2223 -{
2224 -       int port, ret;
2225 -       Port_data  *p;
2226 -       struct ethhdr *eth;
2227 -       struct device *dev;
2228 -       
2229 -       /* sanity */
2230 -       if (!skb) {
2231 -               printk(KERN_CRIT "br_receive_frame: no skb!\n");
2232 -               return(1);
2233 -       }
2234 -
2235 -       dev = skb->dev;
2236 -
2237 -       /* Check for brg0 device 
2238 -        */
2239 -       if (dev == &brg_if.dev)
2240 -               return 0;
2241 -
2242 -       skb->pkt_bridged = IS_BRIDGED;
2243 -
2244 -       /* check for loopback */
2245 -       if (dev->flags & IFF_LOOPBACK)
2246 -               return 0 ;
2247 -
2248 -#if 0
2249 -       port = find_port(dev);
2250 -#else
2251 -       port = dev->bridge_port_id;
2252 -#endif
2253 -       
2254 -       if(!port)
2255 -               return 0;
2256 -       
2257 -       /* Hand off to brg_rx BEFORE we screw up the skb */
2258 -       if(brg_rx(skb, port))
2259 -         return(1);
2260 -
2261 -       skb->nh.raw = skb->mac.raw;
2262 -       eth = skb->mac.ethernet;
2263 -       p = &port_info[port];
2264
2265 -       if(p->state == Disabled) 
2266 -       {
2267 -               /* We are here if BR_UP even if this port is Disabled.
2268 -                * Send everything up
2269 -                */
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) */
2274 -       }
2275
2276 -       /* Here only if not disable.
2277 -        * Remark: only frames going up will show up in NIT (tcpdump)
2278 -        */
2279 -
2280 -       /* JRP: even if port is Blocking we need to process the Spanning Tree
2281 -        * frames to keep the port in that state
2282 -        */
2283 -       if (memcmp(eth->h_dest, bridge_ula, ETH_ALEN) == 0) 
2284 -       {
2285 -               ++br_stats_cnt.rcv_bpdu;
2286 -               br_bpdu(skb, port); /* br_bpdu consumes skb */
2287 -               return(1);
2288 -       }
2289 -       switch (p->state) 
2290 -       {
2291 -               case Learning:
2292 -                       if((ret = br_learn(skb, port))) 
2293 -                       {       /* 3.8 */
2294 -                               if (ret > 0) ++br_stats_cnt.drop_multicast;
2295 -                               return br_drop(skb);
2296 -                       }
2297 -                       /* fall through */
2298 -               case Listening:
2299 -                       /* fall through */
2300 -               case Blocking:
2301 -                       ++br_stats_cnt.notForwarding;
2302 -                       return(br_drop(skb));   
2303 -               /*
2304 -               case Disabled: is now handled before this switch !
2305 -               Keep the break to allow GCC to use a jmp table.
2306 -                */
2307 -                       break;
2308 -               case Forwarding:
2309 -                       if((ret = br_learn(skb, port))) {       /* 3.8 */
2310 -                               if (ret > 0) ++br_stats_cnt.drop_multicast;
2311 -                               return br_drop(skb);
2312 -                       }
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
2318 -                          group address.
2319 -                          br_forward() will not consume the frame if this
2320 -                          is the case */
2321 -                       return(br_forward(skb, port));
2322 -               default:
2323 -                       printk(KERN_DEBUG "br_receive_frame: port [%i] unknown state [%i]\n",
2324 -                               port, p->state);
2325 -                       ++br_stats_cnt.unknown_state;
2326 -                       return(br_drop(skb));   /* discard frame */
2327 -       }
2328 -}
2329 -
2330 -/*
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.
2334 - */
2335 -
2336 -int br_tx_frame(struct sk_buff *skb)   /* 3.5 */
2337 -{
2338 -       int port;
2339 -       struct ethhdr *eth;
2340 -       
2341 -       /* sanity */
2342 -       if (!skb) 
2343 -       {
2344 -               printk(KERN_CRIT "br_tx_frame: no skb!\n");
2345 -               return(0);
2346 -       }
2347 -       
2348 -       if (!skb->dev)
2349 -       {
2350 -               printk(KERN_CRIT "br_tx_frame: no dev!\n");
2351 -               return(0);
2352 -       }
2353 -       
2354 -       /* check for loopback */
2355 -       if (skb->dev->flags & IFF_LOOPBACK)
2356 -               return(0);
2357 -
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;
2362 -               return(0);
2363 -       }
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", 
2371 -                       port,
2372 -                       eth->h_source[0],
2373 -                       eth->h_source[1],
2374 -                       eth->h_source[2],
2375 -                       eth->h_source[3],
2376 -                       eth->h_source[4],
2377 -                       eth->h_source[5],
2378 -                       eth->h_dest[0],
2379 -                       eth->h_dest[1],
2380 -                       eth->h_dest[2],
2381 -                       eth->h_dest[3],
2382 -                       eth->h_dest[4],
2383 -                       eth->h_dest[5]);
2384 -       return(br_forward(skb, port));
2385 -}
2386 -
2387 -static void br_add_local_mac(unsigned char *mac)
2388 -{
2389 -       struct fdb *f;
2390 -       f = (struct fdb *)kmalloc(sizeof(struct fdb), GFP_ATOMIC);
2391 -       if (!f) 
2392 -       {
2393 -               printk(KERN_CRIT "br_add_local_mac: unable to malloc fdb\n");
2394 -               return;
2395 -       }
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 */
2400 -       /*
2401 -        * add entity to AVL tree.  If entity already
2402 -        * exists in the tree, update the fields with
2403 -        * what we have here.
2404 -        */
2405 -       if (br_avl_insert(f) != NULL) 
2406 -       {
2407 -               /* Already in */
2408 -               kfree(f);
2409 -       }
2410 -}
2411 -
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
2416 - */
2417 -
2418 -static inline int mcast_quench(struct fdb *f)
2419 -{
2420 -       if(f->mcast_count++ == 0) /* first time */
2421 -               f->mcast_timer = jiffies;
2422 -       else {
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;
2426 -                       else    return 1;
2427 -               }
2428 -       }
2429 -       return 0;
2430 -}
2431 -
2432 -/*
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.
2436 - *
2437 - * NB Can be called when skb->nh.raw is NOT set up when
2438 - * receiving frames on brg0 via brg_rx
2439 - */
2440 -
2441 -static int br_learn(struct sk_buff *skb, int port)     /* 3.8 */
2442 -{
2443 -       struct fdb *f, *oldfdb;
2444 -       Port_data  *p = &port_info[port];
2445 -       struct ethhdr *eth = skb->mac.ethernet;
2446 -
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
2450 -        */
2451 -
2452 -       /* don't keep group addresses in the tree */
2453 -       if (eth->h_source[0] & 0x01)
2454 -               return 0;
2455 -
2456 -       if((f= newfdb[port]) == NULL) 
2457 -       {
2458 -               newfdb[port] = f = (struct fdb *)kmalloc(sizeof(struct fdb), GFP_ATOMIC);
2459 -               if (!f) 
2460 -               {
2461 -                       printk(KERN_WARNING "br_learn: unable to malloc fdb\n");
2462 -                       return(-1); /* this drops the frame */
2463 -               }
2464 -       }
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;
2469 -       /*
2470 -        * add entity to AVL tree.  If entity already
2471 -        * exists in the tree, update the fields with
2472 -        * what we have here.
2473 -        */
2474 -       if ((oldfdb = br_avl_insert(f))) 
2475 -       {
2476 -               /* update if !NULL */
2477 -               if((eth->h_dest[0] & 0x01) &&  /* multicast */ mcast_quench(oldfdb))
2478 -                       return 1;
2479 -               return 0;
2480 -       }
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;
2485 -       p->fdb = f;
2486 -       allocated_fdb_cnt++;
2487 -       return 0;
2488 -}
2489 -
2490 -/* JRP: always called under br_receive_frame(). No need for Q protection. */
2491 -
2492 -void requeue_fdb(struct fdb *node, int new_port)
2493 -{
2494 -       Port_data *p = &port_info[node->port];
2495 -
2496 -       /* dequeue */
2497 -       if(p->fdb == node)
2498 -               p->fdb = node->fdb_next;
2499 -       else 
2500 -       {
2501 -               struct fdb *prev;
2502 -
2503 -               for(prev = p->fdb; prev; prev = prev->fdb_next)
2504 -                       if (prev->fdb_next == node)
2505 -                               break;
2506 -
2507 -               if(prev != NULL)
2508 -                       prev->fdb_next = node->fdb_next;
2509 -               else 
2510 -               {
2511 -                       /*      Forget about this update. */
2512 -                       printk(KERN_ERR "br:requeue_fdb\n");
2513 -                       return;
2514 -               }
2515 -       }
2516 -       /* enqueue */
2517 -       node->port = new_port;
2518 -       node->fdb_next = port_info[new_port].fdb;
2519 -       port_info[new_port].fdb = node;
2520 -}
2521 -
2522 -/*
2523 - * this routine always consumes the frame
2524 - */
2525 -
2526 -static int br_drop(struct sk_buff *skb)
2527 -{
2528 -       kfree_skb(skb);
2529 -       return(1);
2530 -}
2531 -
2532 -/*
2533 - * this routine always consumes the frame
2534 - */
2535 -
2536 -static int br_dev_drop(struct sk_buff *skb)
2537 -{
2538 -       dev_kfree_skb(skb);
2539 -       return(1);
2540 -}
2541 -
2542 -/*
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().
2546 - *
2547 - * this routine returns 1 if it consumes the frame, 0
2548 - * if not...
2549 - */
2550 -
2551 -static int br_forward(struct sk_buff *skb, int port)   /* 3.7 */
2552 -{
2553 -       struct fdb *f;
2554 -       
2555 -       /*
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.
2561 -        */     
2562 -       if (skb->mac.ethernet->h_dest[0] & 0x01) 
2563 -       {
2564 -               /* group address */
2565 -               br_flood(skb, port);
2566 -               /*
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.
2570 -                */
2571 -               if (port == 0) 
2572 -               {
2573 -                       /* Locally generated */
2574 -                       ++br_stats_cnt.local_multicast;
2575 -                       return(br_dev_drop(skb));
2576 -               }
2577 -               ++br_stats_cnt.forwarded_multicast;
2578 -               return(0);
2579 -       }
2580 -       else 
2581 -       {
2582 -               /* unicast frame, locate port to forward to */
2583 -               f = br_avl_find_addr(skb->mac.ethernet->h_dest);
2584 -               /*
2585 -                *      Send flood and drop.
2586 -                */
2587 -               if (!f || !(f->flags & FDB_ENT_VALID)) 
2588 -               {
2589 -                       if(f && (f->port == 0)) 
2590 -                       {
2591 -                               skb->pkt_type = PACKET_HOST;
2592 -                               ++br_stats_cnt.forwarded_unicast_up_stack;
2593 -                               return(0);
2594 -                       }
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));
2599 -               }
2600 -               /*
2601 -                *      Sending
2602 -                */
2603 -               if (f->port!=port && port_info[f->port].state == Forwarding) 
2604 -               {
2605 -                       /* Has entry expired? */
2606 -                       if (f->timer + fdb_aging_time < CURRENT_TIME) 
2607 -                       {
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");
2612 -                               /*
2613 -                                *      Send flood and drop original
2614 -                                */
2615 -                               ++br_stats_cnt.aged_flood_unicast;
2616 -                               br_flood(skb, port);
2617 -                               return(br_dev_drop(skb));
2618 -                       }
2619 -                       ++br_stats_cnt.forwarded_unicast;
2620 -                       /* mark that's we've been here... */
2621 -                       skb->pkt_bridged = IS_BRIDGED;
2622 -                       
2623 -                       /* reset the skb->ip pointer */ 
2624 -                       skb->nh.raw = skb->data + ETH_HLEN;
2625 -
2626 -                       /*
2627 -                        *      Send the buffer out.
2628 -                        */
2629 -                        
2630 -                       skb->dev=port_info[f->port].dev;
2631 -                        
2632 -                       /*
2633 -                        *      We send this still locked
2634 -                        */
2635 -                       skb->priority = 1;
2636 -                       dev_queue_xmit(skb);
2637 -                       return(1);      /* skb has been consumed */
2638 -               }
2639 -               else 
2640 -               {
2641 -                       /* JRP: Needs to aged entry as well, if topology changes
2642 -                        * the entry would not age. Got this while swapping
2643 -                        * two cables !
2644 -                        *
2645 -                        *      Has entry expired?
2646 -                        */
2647 -                        
2648 -                       if (f->timer + fdb_aging_time < CURRENT_TIME) 
2649 -                       {
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;
2655 -                       }
2656 -                       else ++br_stats_cnt.drop_same_port;
2657 -                       /*
2658 -                        *      Arrived on the right port, we discard
2659 -                        */
2660 -                       return(br_dev_drop(skb));
2661 -               }
2662 -       }
2663 -}
2664 -
2665 -/*
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.
2669 - */
2670 -       
2671 -static int br_flood(struct sk_buff *skb, int port)
2672 -{
2673 -       int i;
2674 -       struct sk_buff *nskb;
2675 -
2676 -       for (i = One; i <= No_of_ports; i++) 
2677 -       {
2678 -               if (i == port)  /* don't send back where we got it */
2679 -                       continue;
2680 -               if (i > max_port_used)
2681 -                       /* Don't go scanning empty port entries */
2682 -                       break;
2683 -               if (port_info[i].state == Forwarding) 
2684 -               {
2685 -                       nskb = skb_clone(skb, GFP_ATOMIC);
2686 -                       if(nskb==NULL)
2687 -                               continue;
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 */
2694 -                       
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);
2699 -               }
2700 -       }
2701 -       return(0);
2702 -}
2703 -
2704 -/*
2705 - *     FIXME: This needs to come from the device structs, eg for
2706 - *     10,100,1Gbit ethernet.
2707 - */
2708
2709 -static int br_port_cost(struct device *dev)    /* 4.10.2 */
2710 -{
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 */
2714 -               return(100);
2715 -       if (strncmp(dev->name, "plip",4) == 0) /* plip */
2716 -               return (1600);
2717 -       return(100);    /* default */
2718 -}
2719 -
2720 -/*
2721 - * this routine always consumes the skb 
2722 - */
2723 -
2724 -static void br_bpdu(struct sk_buff *skb, int port) /* consumes skb */
2725 -{
2726 -       char *bufp = skb->data + ETH_HLEN;
2727 -       Tcn_bpdu *bpdu = (Tcn_bpdu *) (bufp + BRIDGE_LLC1_HS);
2728 -       Config_bpdu rcv_bpdu;
2729 -
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)) 
2735 -       {
2736 -  
2737 -               switch (bpdu->type) 
2738 -               {
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;
2748 -                               bufp++;
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);
2754 -                               break;
2755 -                       
2756 -                       case BPDU_TYPE_TOPO_CHANGE:
2757 -                               received_tcn_bpdu(port, bpdu);
2758 -                               break;
2759 -                       default:
2760 -                               printk(KERN_DEBUG "br_bpdu: received unknown bpdu, type = %i\n", bpdu->type);
2761 -                       /* break; */
2762 -               }
2763 -       }
2764 -       br_drop(skb);
2765 -}
2766 -
2767 -struct fdb_info *get_fdb_info(int user_buf_size, int *copied,int *notcopied)
2768 -{
2769 -       int fdb_size, i, built = 0;
2770 -       struct fdb_info *fdbi, *fdbis;
2771 -
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;
2776 -       if(*copied == 0)
2777 -               return NULL;
2778 -       fdb_size = *copied * sizeof(struct fdb_info);
2779 -       fdbis = kmalloc(fdb_size, GFP_KERNEL);
2780 -       if(fdbis == NULL)
2781 -               return NULL;
2782 -       fdbi = fdbis;
2783 -
2784 -       for(i=One; i<=No_of_ports;i++)
2785 -       {
2786 -               struct fdb *fdb;
2787 -
2788 -               cli();
2789 -               fdb = port_info[i].fdb;
2790 -               while(fdb) 
2791 -               {
2792 -                       memcpy(fdbi->ula, fdb->ula, ETH_ALEN);
2793 -                       fdbi->port = fdb->port;
2794 -                       fdbi->flags = fdb->flags;
2795 -                       fdbi->timer = fdb->timer;
2796 -                       fdbi++;
2797 -                       if(++built == *copied) 
2798 -                       {
2799 -                               sti();
2800 -                               return fdbis;
2801 -                       }
2802 -                       fdb = fdb->fdb_next;
2803 -               }
2804 -               sti();
2805 -       }
2806 -       printk(KERN_DEBUG "get_fdb_info: built=%d\n", built);
2807 -       return fdbis;
2808 -}
2809 -
2810 -
2811 -/* Fill in interface names in port_info structure
2812 - */
2813 -static void br_get_ifdata(void) {
2814 -       int i;
2815 -
2816 -       for(i=One;i<=No_of_ports; i++) {
2817 -
2818 -               port_info[i].admin_state = user_port_state[i]; 
2819 -               
2820 -               /* memset IS needed.  Kernel strncpy does NOT NULL terminate 
2821 -                * strings when limit reached 
2822 -                */
2823 -               memset(port_info[i].ifname, 0, IFNAMSIZ); 
2824 -               if( port_info[i].dev == 0 )
2825 -                       continue;
2826 -               strncpy(port_info[i].ifname, port_info[i].dev->name, IFNAMSIZ-1);
2827 -               /* Being paranoid */
2828 -               port_info[i].ifname[IFNAMSIZ-1] = '\0';
2829 -       }
2830 -}
2831 -
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) 
2835 -{
2836 -  int i;
2837 -  
2838 -  for(i=1; i <= No_of_ports; i++) {
2839 -    if (port_info[i].dev == 0)
2840 -      continue;
2841 -    if (port_info[i].dev->ifindex == ifindex)
2842 -      return(i);
2843 -  }
2844 -  
2845 -  return -EUNATCH;  /* Tell me if this is incorrect error code for this case */
2846 -} 
2847 -
2848 -
2849 -int br_ioctl(unsigned int cmd, void *arg)
2850 -{
2851 -       int err, i, ifflags;
2852 -       struct br_cf bcf;
2853 -       bridge_id_t new_id;
2854 -       struct device *dev;
2855 -       
2856 -       switch(cmd)
2857 -       {
2858 -               case SIOCGIFBR: /* get bridging control blocks */
2859 -                       memcpy(&br_stats.bridge_data, &bridge_info, sizeof(Bridge_data));
2860 -
2861 -                       /* Fill in interface names in port_info*/
2862 -                       br_get_ifdata();
2863 -                       
2864 -                       br_stats.num_ports = No_of_ports;
2865 -                       memcpy(&br_stats.port_data, &port_info, sizeof(Port_data)*All_ports);
2866 -
2867 -                       err = copy_to_user(arg, &br_stats, sizeof(struct br_stat));
2868 -                       if (err)
2869 -                       {
2870 -                               err = -EFAULT;
2871 -                       }
2872 -                       return err;
2873 -               case SIOCSIFBR:
2874 -                       err = copy_from_user(&bcf, arg, sizeof(struct br_cf));
2875 -                       if (err)
2876 -                               return -EFAULT; 
2877 -                       if (bcf.cmd != BRCMD_DISPLAY_FDB && !suser())
2878 -                               return -EPERM;
2879 -                       switch (bcf.cmd) 
2880 -                       {
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++)
2887 -                                       {
2888 -                                               /* don't start if user said so */
2889 -                                               if((user_port_state[i] != Disabled)
2890 -                                                       && port_info[i].dev) 
2891 -                                               {
2892 -                                                       enable_port(i);
2893 -                                               }
2894 -                                       }
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;
2904 -                                       add_timer(&tl);
2905 -                                       start_hello_timer();
2906 -                                       break;
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)
2915 -                                                       disable_port(i);
2916 -                                       break;
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)
2923 -                                                               enable_port(i);
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;
2928 -                                       }
2929 -                                       br_stats.flags ^= BR_STP_DISABLED;
2930 -                                       break;
2931 -                               case BRCMD_IF_ENABLE:
2932 -                                       bcf.arg1 = br_find_port(bcf.arg1);
2933 -                                       if ((signed)bcf.arg1 < 0)
2934 -                                               return(bcf.arg1);
2935 -                               case BRCMD_PORT_ENABLE:
2936 -                                       if (port_info[bcf.arg1].dev == 0)
2937 -                                               return(-EINVAL);
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);
2948 -                                       break;
2949 -                               case BRCMD_IF_DISABLE:
2950 -                                       bcf.arg1 = br_find_port(bcf.arg1);
2951 -                                       if ((signed)bcf.arg1 < 0)
2952 -                                               return(bcf.arg1);
2953 -                               case BRCMD_PORT_DISABLE:
2954 -                                       if (port_info[bcf.arg1].dev == 0)
2955 -                                               return(-EINVAL);
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);
2966 -                                       break;
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);
2971 -                                       break;
2972 -                               case BRCMD_SET_IF_PRIORITY:
2973 -                                       bcf.arg1 = br_find_port(bcf.arg1);
2974 -                                       if ((signed)bcf.arg1 < 0)
2975 -                                               return(bcf.arg1);
2976 -                               case BRCMD_SET_PORT_PRIORITY:
2977 -                                       if((port_info[bcf.arg1].dev == 0)
2978 -                                           || (bcf.arg2 & ~0xff))
2979 -                                               return(-EINVAL);
2980 -                                       port_priority[bcf.arg1] = bcf.arg2;
2981 -                                       set_port_priority(bcf.arg1);
2982 -                                       break;
2983 -                               case BRCMD_SET_IF_PATH_COST:
2984 -                                       bcf.arg1 = br_find_port(bcf.arg1);
2985 -                                       if ((signed)bcf.arg1 < 0)
2986 -                                               return(bcf.arg1);
2987 -                               case BRCMD_SET_PATH_COST:
2988 -                                       if (port_info[bcf.arg1].dev == 0)
2989 -                                               return(-EINVAL);
2990 -                                       set_path_cost(bcf.arg1, bcf.arg2);
2991 -                                       break;
2992 -                               case BRCMD_ENABLE_DEBUG:
2993 -                                       br_stats.flags |= BR_DEBUG;
2994 -                                       break;
2995 -                               case BRCMD_DISABLE_DEBUG:
2996 -                                       br_stats.flags &= ~BR_DEBUG;
2997 -                                       break;
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;
3004 -                                       break;
3005 -                               case BRCMD_DISABLE_PROT_STATS:
3006 -                                       br_stats.flags &= ~BR_PROT_STATS;
3007 -                                       break;
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));
3011 -                                       break;
3012 -                               case BRCMD_DISPLAY_FDB:
3013 -                               {
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;
3018 -
3019 -                                       if(bcf.arg2<sizeof(struct fdb_info_hdr))
3020 -                                               return -EINVAL;
3021 -                                       put_user(j, &user_buf->cmd_time);
3022 -                                       if(allocated_fdb_cnt == 0) 
3023 -                                       {
3024 -                                               put_user(0, &user_buf->copied);
3025 -                                               put_user(0, &user_buf->not_copied);
3026 -                                               return 0;
3027 -                                       }
3028 -                                       fdbis = get_fdb_info(bcf.arg2, &copied, &notcopied);
3029 -                                       put_user(copied, &user_buf->copied);
3030 -                                       put_user(notcopied, &user_buf->not_copied);
3031 -                                       if(!fdbis)
3032 -                                               return -ENOMEM;
3033 -                                       u_fdbs = (struct fdb_info *) (user_buf+1);
3034 -                                       err = copy_to_user(u_fdbs, fdbis, copied*sizeof(struct fdb_info));
3035 -                                       kfree(fdbis);
3036 -                                       if (err)
3037 -                                       {
3038 -                                               err = -EFAULT;
3039 -                                       }
3040 -                                       return err;
3041 -                               }
3042 -                               default:
3043 -                                       return -EINVAL;
3044 -                       }
3045 -                       return(0);
3046 -               default:
3047 -                       return -EINVAL;
3048 -       }
3049 -       /*NOTREACHED*/
3050         return 0;
3051  }
3052  
3053 -static int br_cmp(unsigned int *a, unsigned int *b)
3054 -{
3055 -       int i;  
3056 -       for (i=0; i<2; i++) 
3057 -       {
3058 -               /* JRP: compares prty then MAC address in memory byte order
3059 -                * OK optimizer does htonl() only once per long !
3060 -                */
3061 -               if (htonl(a[i]) < htonl(b[i]))
3062 -                       return(-1);
3063 -               if (htonl(a[i]) > htonl(b[i]))
3064 -                       return(1);
3065 -       }
3066 -       return(0);
3067 -}
3068 -
3069 -
3070 -
3071 -
3072 -/* --------------------------------------------------------------------------------
3073 - *
3074 - *
3075 - *  Bridge network device here for future modularization - device structures
3076 - *  must be 'static' inside bridge instance
3077 - *  Modelled after sch_teql.c
3078 - * 
3079 - */
3080 -
3081 -
3082 -
3083 -/*
3084 - *     Index to functions.
3085 - */
3086 -
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);
3093 -
3094 -/*
3095 - *     Board-specific info in dev->priv.
3096 - */
3097 -
3098 -struct net_local
3099 -{
3100 -       __u32           groups;
3101 -       struct net_device_stats stats;
3102 -};
3103 -
3104 -
3105 -
3106 -
3107 -/*
3108 - *     To call this a probe is a bit misleading, however for real
3109 - *     hardware it would have to check what was present.
3110 - */
3111
3112 -__initfunc(int brg_probe(struct device *dev))
3113 -{
3114 -       unsigned int bogomips;
3115 -       struct timeval utime;
3116 -
3117 -       printk(KERN_INFO "%s: network interface for Ethernet Bridge 007/NET4.0\n", dev->name);
3118 -
3119 -       /*
3120 -        *      Initialize the device structure.
3121 -        */
3122 -  
3123 -       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
3124 -       if (dev->priv == NULL)
3125 -               return -ENOMEM;
3126 -       memset(dev->priv, 0, sizeof(struct net_local));
3127 -
3128 -       /* Set up MAC address based on BogoMIPs figure for first CPU and time
3129 -        */ 
3130 -       bogomips = (loops_per_jiffy+2500)/500000/HZ ;
3131 -       get_fast_time(&utime);
3132 -
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);
3141 -  
3142 -       printk(KERN_INFO "%s: generated MAC address %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", 
3143 -               dev->name,
3144 -               dev->dev_addr[0],
3145 -               dev->dev_addr[1],
3146 -               dev->dev_addr[2],
3147 -               dev->dev_addr[3],
3148 -               dev->dev_addr[4],
3149 -               dev->dev_addr[5]);
3150 -
3151 -  
3152 -       printk(KERN_INFO "%s: attached to bridge instance %lu\n", dev->name, dev->base_addr);
3153 -
3154 -       /*
3155 -        *      The brg specific entries in the device structure.
3156 -        */
3157 -
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;
3163 -
3164 -       /*
3165 -        *      Setup the generic properties
3166 -        */
3167 -
3168 -       ether_setup(dev);
3169 -       dev->tx_queue_len = 0;
3170 -       return 0;
3171 -}
3172 -
3173 -/*
3174 - *     Open/initialize the board.
3175 - */
3176 -
3177 -static int brg_open(struct device *dev)
3178 -{
3179 -        if (br_stats.flags & BR_DEBUG)
3180 -               printk(KERN_DEBUG "%s: Doing brg_open()...", dev->name);
3181 -
3182 -       if (memcmp(dev->dev_addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
3183 -         return -EFAULT;
3184 -
3185 -       dev->start = 1;
3186 -       dev->tbusy = 0;
3187 -       return 0;
3188 -}
3189 -
3190 -static unsigned brg_mc_hash(__u8 *dest)
3191 -{
3192 -       unsigned idx = 0;
3193 -       idx ^= dest[0];
3194 -       idx ^= dest[1];
3195 -       idx ^= dest[2];
3196 -       idx ^= dest[3];
3197 -       idx ^= dest[4];
3198 -       idx ^= dest[5];
3199 -       return 1U << (idx&0x1F);
3200 -}
3201 -
3202 -static void brg_set_multicast_list(struct device *dev)
3203 -{
3204 -       unsigned groups = ~0;
3205 -       struct net_local *lp = (struct net_local *)dev->priv;
3206 -
3207 -       if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
3208 -               struct dev_mc_list *dmi;
3209 -
3210 -               groups = brg_mc_hash(dev->broadcast);
3211 -
3212 -               for (dmi=dev->mc_list; dmi; dmi=dmi->next) {
3213 -                       if (dmi->dmi_addrlen != 6)
3214 -                               continue;
3215 -                       groups |= brg_mc_hash(dmi->dmi_addr);
3216 -               }
3217 -       }
3218 -       lp->groups = groups;
3219 -}
3220 -
3221 -/*
3222 - *     We transmit by throwing the packet at the bridge.
3223 - */
3224
3225 -static int brg_start_xmit(struct sk_buff *skb, struct device *dev)
3226 -{
3227 -       struct net_local *lp = (struct net_local *)dev->priv;
3228 -       struct ethhdr *eth = (struct ethhdr*)skb->data;
3229 -       int port;
3230 -
3231 -       /* Deal with the bridge being disabled */
3232 -       if(!(br_stats.flags & BR_UP)) {
3233 -               /* Either this */
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);
3238 -               return 0;
3239 -       }
3240 -
3241 -       lp->stats.tx_bytes+=skb->len;
3242 -       lp->stats.tx_packets++;
3243 -
3244 -#if 0
3245 -       ++br_stats_cnt.port_not_disable;
3246 -#endif
3247 -       skb->mac.raw = skb->nh.raw = skb->data;
3248 -       eth = skb->mac.ethernet;
3249 -       port = 0;       /* an impossible port (locally generated) */    
3250 -
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", 
3254 -                      dev->name,
3255 -                      eth->h_source[0],
3256 -                      eth->h_source[1],
3257 -                      eth->h_source[2],
3258 -                      eth->h_source[3],
3259 -                      eth->h_source[4],
3260 -                      eth->h_source[5],
3261 -                      eth->h_dest[0],
3262 -                      eth->h_dest[1],
3263 -                      eth->h_dest[2],
3264 -                      eth->h_dest[3],
3265 -                      eth->h_dest[4],
3266 -                      eth->h_dest[5]);
3267 -       
3268 -       /* Forward the packet ! */
3269 -       if(br_forward(skb, port))
3270 -         return(0);
3271 -    
3272 -       /* Throw packet initially */
3273 -       dev_kfree_skb(skb);
3274 -       return 0;
3275 -}
3276 -
3277 -
3278 -/*
3279 - *     The typical workload of the driver:
3280 - *     Handle the ether interface interrupts.
3281 - *
3282 - *     (In this case handle the packets posted from the bridge)
3283 - */
3284 -
3285 -static int brg_rx(struct sk_buff *skb, int port)
3286 -{
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;
3291 -       int clone = 0;
3292 -
3293 -       if (br_stats.flags & BR_DEBUG)
3294 -               printk(KERN_DEBUG "%s: brg_rx()\n", dev->name);
3295 -
3296 -       /* Get out of here if the bridge interface is not up
3297 -        */
3298 -       if(!(dev->flags & IFF_UP))
3299 -         return(0);
3300 -       
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.
3303 -        */
3304 -       if(port_info[port].state != Forwarding)
3305 -         return(0);
3306 -
3307 -       /* Is this for us? - broadcast/mulitcast/promiscuous packets need cloning,
3308 -         * with uni-cast we eat the packet
3309 -        */
3310 -       clone = 0;
3311 -       if (dev->flags & IFF_PROMISC) {
3312 -         clone = 1;
3313 -       }
3314 -       else if (eth->h_dest[0]&1) {
3315 -         if (!(dev->flags&(IFF_ALLMULTI))
3316 -             && !(brg_mc_hash(eth->h_dest)&lp->groups))
3317 -           return(0);
3318 -         clone = 1;
3319 -       }
3320 -       else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN) != 0) {
3321 -         return(0);
3322 -       }
3323 -
3324 -       /* Clone things here - we want to be transparent before we check packet data 
3325 -        * integrity
3326 -        */
3327 -       if(clone) {
3328 -         struct sk_buff *skb2 = skb;
3329 -         skb = skb_clone(skb2, GFP_ATOMIC);
3330 -         if (skb == NULL) {
3331 -           return(0);
3332 -         }
3333 -         
3334 -       }
3335 -       else {
3336 -               /* Learn source addresses for unicast non-promiscuous 
3337 -                * frames for brg0
3338 -                */
3339 -               if(br_learn(skb, port)) {
3340 -                       return br_drop(skb);
3341 -               }
3342 -       }
3343 -
3344 -       /* Check packet length 
3345 -        */
3346 -       if (len < 16) {
3347 -               printk(KERN_DEBUG "%s : rx len = %d\n", dev->name, len);
3348 -               kfree_skb(skb);
3349 -               return(!clone);
3350 -       }
3351 -
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", 
3355 -                dev->name,
3356 -                eth->h_source[0],
3357 -                eth->h_source[1],
3358 -                eth->h_source[2],
3359 -                eth->h_source[3],
3360 -                eth->h_source[4],
3361 -                eth->h_source[5],
3362 -                eth->h_dest[0],
3363 -                eth->h_dest[1],
3364 -                eth->h_dest[2],
3365 -                eth->h_dest[3],
3366 -                eth->h_dest[4],
3367 -                eth->h_dest[5]);
3368 -
3369 -       /* Do it */
3370 -       skb->pkt_type = PACKET_HOST;
3371 -       skb->dev = dev;
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;
3376 -       netif_rx(skb);
3377 -       return(!clone);
3378 -}
3379 -
3380 -static int brg_close(struct device *dev)
3381 -{
3382 -       if (br_stats.flags & BR_DEBUG)
3383 -               printk(KERN_DEBUG "%s: Shutting down.\n", dev->name);
3384 -
3385 -       dev->tbusy = 1;
3386 -       dev->start = 0;
3387 -
3388 -       return 0;
3389 -}
3390 -
3391 -static struct net_device_stats *brg_get_stats(struct device *dev)
3392 -{
3393 -       struct net_local *lp = (struct net_local *)dev->priv;
3394 -       return &lp->stats;
3395 -}
3396 -
3397 -/* 
3398 - *      
3399 - */
3400 +#ifdef MODULE
3401 +EXPORT_NO_SYMBOLS;
3402  
3403 -__initfunc(int brg_init(void))
3404 +int init_module(void)
3405  {
3406 -        int err;
3407 -
3408 -       memset(&brg_if, 0, sizeof(brg_if));
3409 -
3410 -        rtnl_lock();
3411 -
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);
3417 -              return -EBUSY;
3418 -       }
3419 -        brg_if.dev.init = brg_probe;
3420 -
3421 -        err = register_netdevice(&brg_if.dev);
3422 -        rtnl_unlock();
3423 -        return err;
3424 +       return br_init();
3425  }
3426  
3427 -
3428 -#if 0                          /* Its here if we ever need it... */
3429 -#ifdef MODULE
3430 -
3431  void cleanup_module(void)
3432  {
3433 -
3434 -  /* 
3435 -   * Unregister the device
3436 -   */
3437 -  rtnl_lock();
3438 -  unregister_netdevice(&the_master.dev);
3439 -  rtnl_unlock();
3440 -
3441 -  /*
3442 -   *   Free up the private structure.
3443 -   */
3444 -  
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;
3450 +       synchronize_bh();
3451  }
3452  
3453 -#endif /* MODULE */
3454 -
3455  #endif
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
3459 @@ -0,0 +1,126 @@
3460 +/*
3461 + *     Device handling code
3462 + *     Linux ethernet bridge
3463 + *
3464 + *     Authors:
3465 + *     Lennert Buytenhek               <buytenh@gnu.org>
3466 + *
3467 + *     $Id$
3468 + *
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.
3473 + */
3474 +
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"
3481 +
3482 +static int br_dev_do_ioctl(struct device *dev, struct ifreq *rq, int cmd)
3483 +{
3484 +       unsigned long args[4];
3485 +       unsigned long *data;
3486 +
3487 +       if (cmd != SIOCDEVPRIVATE)
3488 +               return -EOPNOTSUPP;
3489 +
3490 +       data = (unsigned long *)rq->ifr_data;
3491 +       if (copy_from_user(args, data, 4*sizeof(unsigned long)))
3492 +               return -EFAULT;
3493 +
3494 +       return br_ioctl(dev->priv, args[0], args[1], args[2], args[3]);
3495 +}
3496 +
3497 +static struct net_device_stats *br_dev_get_stats(struct device *dev)
3498 +{
3499 +       struct net_bridge *br;
3500 +
3501 +       br = dev->priv;
3502 +
3503 +       return &br->statistics;
3504 +}
3505 +
3506 +int br_dev_xmit(struct sk_buff *skb, struct device *dev)
3507 +{
3508 +       struct net_bridge *br;
3509 +       unsigned char *dest;
3510 +       struct net_bridge_fdb_entry *dst;
3511 +
3512 +       br = dev->priv;
3513 +       br->statistics.tx_packets++;
3514 +       br->statistics.tx_bytes += skb->len;
3515 +
3516 +       dest = skb->data;
3517 +
3518 +       if (dest[0] & 1) {
3519 +               br_flood(br, skb, 0);
3520 +               return 0;
3521 +       }
3522 +
3523 +       if ((dst = br_fdb_get(br, dest)) != NULL) {
3524 +               br_forward(dst->dst, skb);
3525 +               br_fdb_put(dst);
3526 +               return 0;
3527 +       }
3528 +
3529 +       br_flood(br, skb, 0);
3530 +       return 0;
3531 +}
3532 +
3533 +static int br_dev_open(struct device *dev)
3534 +{
3535 +       struct net_bridge *br;
3536 +
3537 +       dev->start = 1;
3538 +       dev->tbusy = 0;
3539 +
3540 +       br = dev->priv;
3541 +       read_lock(&br->lock);
3542 +       br_stp_enable_bridge(br);
3543 +       read_unlock(&br->lock);
3544 +
3545 +       return 0;
3546 +}
3547 +
3548 +static void br_dev_set_multicast_list(struct device *dev)
3549 +{
3550 +}
3551 +
3552 +static int br_dev_stop(struct device *dev)
3553 +{
3554 +       struct net_bridge *br;
3555 +
3556 +       br = dev->priv;
3557 +       read_lock(&br->lock);
3558 +       br_stp_disable_bridge(br);
3559 +       read_unlock(&br->lock);
3560 +
3561 +       dev->start = 0;
3562 +       dev->tbusy = 1;
3563 +
3564 +       return 0;
3565 +}
3566 +
3567 +static int br_dev_accept_fastpath(struct device *dev, struct dst_entry *dst)
3568 +{
3569 +       return -1;
3570 +}
3571 +
3572 +void br_dev_setup(struct device *dev)
3573 +{
3574 +       memset(dev->dev_addr, 0, ETH_ALEN);
3575 +
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;
3585 +}
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
3589 @@ -0,0 +1,320 @@
3590 +/*
3591 + *     Forwarding database
3592 + *     Linux ethernet bridge
3593 + *
3594 + *     Authors:
3595 + *     Lennert Buytenhek               <buytenh@gnu.org>
3596 + *
3597 + *     $Id$
3598 + *
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.
3603 + */
3604 +
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"
3612 +
3613 +static __inline__ unsigned long __timeout(struct net_bridge *br)
3614 +{
3615 +       unsigned long timeout;
3616 +
3617 +       timeout = jiffies - br->ageing_time;
3618 +       if (br->topology_change)
3619 +               timeout = jiffies - br->forward_delay;
3620 +
3621 +       return timeout;
3622 +}
3623 +
3624 +static __inline__ int has_expired(struct net_bridge *br,
3625 +                                 struct net_bridge_fdb_entry *fdb)
3626 +{
3627 +       if (!fdb->is_static &&
3628 +           time_before_eq(fdb->ageing_timer, __timeout(br)))
3629 +               return 1;
3630 +
3631 +       return 0;
3632 +}
3633 +
3634 +static __inline__ void copy_fdb(struct __fdb_entry *ent, struct net_bridge_fdb_entry *f)
3635 +{
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;
3643 +}
3644 +
3645 +static __inline__ int br_mac_hash(unsigned char *mac)
3646 +{
3647 +       unsigned long x;
3648 +
3649 +       x = mac[0];
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];
3655 +
3656 +       x ^= x >> 8;
3657 +
3658 +       return x & (BR_HASH_SIZE - 1);
3659 +}
3660 +
3661 +static __inline__ void __hash_link(struct net_bridge *br,
3662 +                                  struct net_bridge_fdb_entry *ent,
3663 +                                  int hash)
3664 +{
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];
3670 +}
3671 +
3672 +static __inline__ void __hash_unlink(struct net_bridge_fdb_entry *ent)
3673 +{
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;
3679 +}
3680 +
3681 +
3682 +
3683 +void br_fdb_changeaddr(struct net_bridge_port *p, unsigned char *newaddr)
3684 +{
3685 +       struct net_bridge *br;
3686 +       int i;
3687 +
3688 +       br = p->br;
3689 +       write_lock_bh(&br->hash_lock);
3690 +       for (i=0;i<BR_HASH_SIZE;i++) {
3691 +               struct net_bridge_fdb_entry *f;
3692 +
3693 +               f = br->hash[i];
3694 +               while (f != NULL) {
3695 +                       if (f->dst == p && f->is_local) {
3696 +                               __hash_unlink(f);
3697 +                               memcpy(f->addr.addr, newaddr, ETH_ALEN);
3698 +                               __hash_link(br, f, br_mac_hash(newaddr));
3699 +                               write_unlock_bh(&br->hash_lock);
3700 +                               return;
3701 +                       }
3702 +                       f = f->next_hash;
3703 +               }
3704 +       }
3705 +       write_unlock_bh(&br->hash_lock);
3706 +}
3707 +
3708 +void br_fdb_cleanup(struct net_bridge *br)
3709 +{
3710 +       int i;
3711 +       unsigned long timeout;
3712 +
3713 +       timeout = __timeout(br);
3714 +
3715 +       write_lock_bh(&br->hash_lock);
3716 +       for (i=0;i<BR_HASH_SIZE;i++) {
3717 +               struct net_bridge_fdb_entry *f;
3718 +
3719 +               f = br->hash[i];
3720 +               while (f != NULL) {
3721 +                       struct net_bridge_fdb_entry *g;
3722 +
3723 +                       g = f->next_hash;
3724 +                       if (!f->is_static &&
3725 +                           time_before_eq(f->ageing_timer, timeout)) {
3726 +                               __hash_unlink(f);
3727 +                               br_fdb_put(f);
3728 +                       }
3729 +                       f = g;
3730 +               }
3731 +       }
3732 +       write_unlock_bh(&br->hash_lock);
3733 +}
3734 +
3735 +void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
3736 +{
3737 +       int i;
3738 +
3739 +       write_lock_bh(&br->hash_lock);
3740 +       for (i=0;i<BR_HASH_SIZE;i++) {
3741 +               struct net_bridge_fdb_entry *f;
3742 +
3743 +               f = br->hash[i];
3744 +               while (f != NULL) {
3745 +                       struct net_bridge_fdb_entry *g;
3746 +
3747 +                       g = f->next_hash;
3748 +                       if (f->dst == p) {
3749 +                               __hash_unlink(f);
3750 +                               br_fdb_put(f);
3751 +                       }
3752 +                       f = g;
3753 +               }
3754 +       }
3755 +       write_unlock_bh(&br->hash_lock);
3756 +}
3757 +
3758 +struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, unsigned char *addr)
3759 +{
3760 +       struct net_bridge_fdb_entry *fdb;
3761 +
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);
3769 +                               return fdb;
3770 +                       }
3771 +
3772 +                       read_unlock_bh(&br->hash_lock);
3773 +                       return NULL;
3774 +               }
3775 +
3776 +               fdb = fdb->next_hash;
3777 +       }
3778 +
3779 +       read_unlock_bh(&br->hash_lock);
3780 +       return NULL;
3781 +}
3782 +
3783 +void br_fdb_put(struct net_bridge_fdb_entry *ent)
3784 +{
3785 +       if (atomic_dec_and_test(&ent->use_count))
3786 +               kfree(ent);
3787 +}
3788 +
3789 +int br_fdb_get_entries(struct net_bridge *br,
3790 +                      unsigned char *_buf,
3791 +                      int maxnum,
3792 +                      int offset)
3793 +{
3794 +       int i;
3795 +       int num;
3796 +       struct __fdb_entry *walk;
3797 +
3798 +       num = 0;
3799 +       walk = (struct __fdb_entry *)_buf;
3800 +
3801 +       read_lock_bh(&br->hash_lock);
3802 +       for (i=0;i<BR_HASH_SIZE;i++) {
3803 +               struct net_bridge_fdb_entry *f;
3804 +
3805 +               f = br->hash[i];
3806 +               while (f != NULL && num < maxnum) {
3807 +                       struct __fdb_entry ent;
3808 +                       int err;
3809 +                       struct net_bridge_fdb_entry *g;
3810 +
3811 +                       if (has_expired(br, f)) {
3812 +                               f = f->next_hash;
3813 +                               continue;
3814 +                       }
3815 +
3816 +                       if (offset) {
3817 +                               offset--;
3818 +                               f = f->next_hash;
3819 +                               continue;
3820 +                       }
3821 +
3822 +                       copy_fdb(&ent, f);
3823 +
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);
3828 +
3829 +                       g = f->next_hash;
3830 +                       br_fdb_put(f);
3831 +
3832 +                       if (err)
3833 +                               goto out_fault;
3834 +
3835 +                       if (f->next_hash == NULL &&
3836 +                           f->pprev_hash == NULL)
3837 +                               goto out_disappeared;
3838 +
3839 +                       num++;
3840 +                       walk++;
3841 +
3842 +                       f = g;
3843 +               }
3844 +       }
3845 +
3846 + out:
3847 +       read_unlock_bh(&br->hash_lock);
3848 +       return num;
3849 +
3850 + out_disappeared:
3851 +       num = -EAGAIN;
3852 +       goto out;
3853 +
3854 + out_fault:
3855 +       num = -EFAULT;
3856 +       goto out;
3857 +}
3858 +
3859 +static __inline__ void __fdb_possibly_replace(struct net_bridge_fdb_entry *fdb,
3860 +                                             struct net_bridge_port *source,
3861 +                                             int is_local)
3862 +{
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;
3868 +       }
3869 +}
3870 +
3871 +void br_fdb_insert(struct net_bridge *br,
3872 +                  struct net_bridge_port *source,
3873 +                  unsigned char *addr,
3874 +                  int is_local)
3875 +{
3876 +       struct net_bridge_fdb_entry *fdb;
3877 +       int hash;
3878 +
3879 +       hash = br_mac_hash(addr);
3880 +
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);
3887 +                       return;
3888 +               }
3889 +
3890 +               fdb = fdb->next_hash;
3891 +       }
3892 +
3893 +       fdb = kmalloc(sizeof(*fdb), GFP_ATOMIC);
3894 +       if (fdb == NULL) {
3895 +               write_unlock_bh(&br->hash_lock);
3896 +               return;
3897 +       }
3898 +
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;
3905 +
3906 +       __hash_link(br, fdb, hash);
3907 +
3908 +       write_unlock_bh(&br->hash_lock);
3909 +}
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
3913 @@ -0,0 +1,98 @@
3914 +/*
3915 + *     Forwarding decision
3916 + *     Linux ethernet bridge
3917 + *
3918 + *     Authors:
3919 + *     Lennert Buytenhek               <buytenh@gnu.org>
3920 + *
3921 + *     $Id$
3922 + *
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.
3927 + */
3928 +
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"
3937 +
3938 +static inline int should_forward(struct net_bridge_port *p, struct sk_buff *skb)
3939 +{
3940 +       if (skb->dev != p->dev && p->state == BR_STATE_FORWARDING)
3941 +               return 1;
3942 +
3943 +       return 0;
3944 +}
3945 +
3946 +static void __br_forward(struct net_bridge_port *to, struct sk_buff *skb)
3947 +{
3948 +       skb->dev = to->dev;
3949 +       dev_queue_xmit(skb);
3950 +}
3951 +
3952 +void br_forward(struct net_bridge_port *to, struct sk_buff *skb)
3953 +{
3954 +       if (should_forward(to, skb)) {
3955 +               __br_forward(to, skb);
3956 +               return;
3957 +       }
3958 +
3959 +       kfree_skb(skb);
3960 +}
3961 +
3962 +void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone)
3963 +{
3964 +       struct net_bridge_port *p;
3965 +       struct net_bridge_port *prev;
3966 +
3967 +       if (clone) {
3968 +               struct sk_buff *skb2;
3969 +
3970 +               if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
3971 +                       br->statistics.tx_dropped++;
3972 +                       return;
3973 +               }
3974 +
3975 +               skb = skb2;
3976 +       }
3977 +
3978 +       prev = NULL;
3979 +
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;
3986 +
3987 +                               if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
3988 +                                       br->statistics.tx_dropped++;
3989 +                                       kfree_skb(skb);
3990 +                                       read_unlock(&br->lock);
3991 +                                       return;
3992 +                               }
3993 +
3994 +                               __br_forward(prev, skb2);
3995 +                       }
3996 +
3997 +                       prev = p;
3998 +               }
3999 +
4000 +               p = p->next;
4001 +       }
4002 +
4003 +       if (prev != NULL) {
4004 +               __br_forward(prev, skb);
4005 +               read_unlock(&br->lock);
4006 +               return;
4007 +       }
4008 +
4009 +       read_unlock(&br->lock);
4010 +       kfree_skb(skb);
4011 +}
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
4015 @@ -0,0 +1,297 @@
4016 +/*
4017 + *     Userspace interface
4018 + *     Linux ethernet bridge
4019 + *
4020 + *     Authors:
4021 + *     Lennert Buytenhek               <buytenh@gnu.org>
4022 + *
4023 + *     $Id$
4024 + *
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.
4029 + */
4030 +
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"
4038 +
4039 +static struct net_bridge *bridge_list;
4040 +
4041 +static int br_initial_port_cost(struct device *dev)
4042 +{
4043 +       if (!strncmp(dev->name, "lec", 3))
4044 +               return 7;
4045 +
4046 +       if (!strncmp(dev->name, "eth", 3))
4047 +               return 100;                     /* FIXME handle 100Mbps */
4048 +
4049 +       if (!strncmp(dev->name, "plip", 4))
4050 +               return 2500;
4051 +
4052 +       return 100;
4053 +}
4054 +
4055 +/* called under bridge lock */
4056 +static int __br_del_if(struct net_bridge *br, struct device *dev)
4057 +{
4058 +       struct net_bridge_port *p;
4059 +       struct net_bridge_port **pptr;
4060 +
4061 +       if ((p = dev->br_port) == NULL)
4062 +               return -EINVAL;
4063 +
4064 +       br_stp_disable_port(p);
4065 +
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;
4070 +       }
4071 +
4072 +       dev->br_port = NULL;
4073 +
4074 +       pptr = &br->port_list;
4075 +       while (*pptr != NULL) {
4076 +               if (*pptr == p) {
4077 +                       *pptr = p->next;
4078 +                       break;
4079 +               }
4080 +
4081 +               pptr = &((*pptr)->next);
4082 +       }
4083 +
4084 +       br_fdb_delete_by_port(br, p);
4085 +       kfree(p);
4086 +
4087 +       return 0;
4088 +}
4089 +
4090 +static struct net_bridge **__find_br(char *name)
4091 +{
4092 +       struct net_bridge **b;
4093 +       struct net_bridge *br;
4094 +
4095 +       b = &bridge_list;
4096 +       while ((br = *b) != NULL) {
4097 +               if (!strncmp(br->name, name, IFNAMSIZ))
4098 +                       return b;
4099 +
4100 +               b = &(br->next);
4101 +       }
4102 +
4103 +       return NULL;
4104 +}
4105 +
4106 +static void del_ifs(struct net_bridge *br)
4107 +{
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);
4112 +}
4113 +
4114 +static struct net_bridge *new_nb(char *name)
4115 +{
4116 +       struct net_bridge *br;
4117 +       struct device *dev;
4118 +
4119 +       if ((br = kmalloc(sizeof(*br), GFP_KERNEL)) == NULL)
4120 +               return NULL;
4121 +
4122 +       memset(br, 0, sizeof(*br));
4123 +       dev = &br->dev;
4124 +
4125 +       strncpy(br->name, name, IFNAMSIZ);
4126 +       dev->priv = br;
4127 +       dev->name = br->name;
4128 +       ether_setup(dev);
4129 +       br_dev_setup(dev);
4130 +
4131 +       br->lock = RW_LOCK_UNLOCKED;
4132 +       br->hash_lock = RW_LOCK_UNLOCKED;
4133 +
4134 +       br->bridge_id.prio[0] = 0x80;
4135 +       br->bridge_id.prio[1] = 0x00;
4136 +       memset(br->bridge_id.addr, 0, ETH_ALEN);
4137 +
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);
4150 +
4151 +       br->ageing_time = 300 * HZ;
4152 +       br->gc_interval = 4 * HZ;
4153 +
4154 +       return br;
4155 +}
4156 +
4157 +/* called under bridge lock */
4158 +static struct net_bridge_port *new_nbp(struct net_bridge *br, struct device *dev)
4159 +{
4160 +       int i;
4161 +       struct net_bridge_port *p;
4162 +
4163 +       p = kmalloc(sizeof(*p), GFP_KERNEL);
4164 +       if (p == NULL)
4165 +               return p;
4166 +
4167 +       memset(p, 0, sizeof(*p));
4168 +       p->br = br;
4169 +       p->dev = dev;
4170 +       p->path_cost = br_initial_port_cost(dev);
4171 +       p->priority = 0x80;
4172 +
4173 +       dev->br_port = p;
4174 +
4175 +       for (i=1;i<255;i++)
4176 +               if (br_get_port(br, i) == NULL)
4177 +                       break;
4178 +
4179 +       if (i == 255) {
4180 +               kfree(p);
4181 +               return NULL;
4182 +       }
4183 +
4184 +       p->port_no = i;
4185 +       br_init_port(p);
4186 +       p->state = BR_STATE_DISABLED;
4187 +
4188 +       p->next = br->port_list;
4189 +       br->port_list = p;
4190 +
4191 +       return p;
4192 +}
4193 +
4194 +int br_add_bridge(char *name)
4195 +{
4196 +       struct net_bridge *br;
4197 +
4198 +       if ((br = new_nb(name)) == NULL)
4199 +               return -ENOMEM;
4200 +
4201 +       if (dev_get(name) != NULL) {
4202 +               kfree(br);
4203 +               return -EEXIST;
4204 +       }
4205 +
4206 +       br->next = bridge_list;
4207 +       bridge_list = br;
4208 +
4209 +       br_inc_use_count();
4210 +       register_netdevice(&br->dev);
4211 +
4212 +       return 0;
4213 +}
4214 +
4215 +int br_del_bridge(char *name)
4216 +{
4217 +       struct net_bridge **b;
4218 +       struct net_bridge *br;
4219 +
4220 +       if ((b = __find_br(name)) == NULL)
4221 +               return -ENXIO;
4222 +
4223 +       br = *b;
4224 +
4225 +       if (br->dev.flags & IFF_UP)
4226 +               return -EBUSY;
4227 +
4228 +       del_ifs(br);
4229 +
4230 +       *b = br->next;
4231 +
4232 +       unregister_netdevice(&br->dev);
4233 +       kfree(br);
4234 +       br_dec_use_count();
4235 +
4236 +       return 0;
4237 +}
4238 +
4239 +int br_add_if(struct net_bridge *br, struct device *dev)
4240 +{
4241 +       struct net_bridge_port *p;
4242 +
4243 +       if (dev->br_port != NULL)
4244 +               return -EBUSY;
4245 +
4246 +       if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
4247 +               return -EINVAL;
4248 +
4249 +       if (dev->hard_start_xmit == br_dev_xmit)
4250 +               return -ELOOP;
4251 +
4252 +       write_lock_bh(&br->lock);
4253 +       if ((p = new_nbp(br, dev)) == NULL) {
4254 +               write_unlock_bh(&br->lock);
4255 +               return -EXFULL;
4256 +       }
4257 +
4258 +       if (dev->ip_ptr != NULL) {
4259 +               struct in_device *idev = dev->ip_ptr;
4260 +               idev->cnf.hidden = 1;
4261 +       }
4262 +       dev_set_promiscuity(dev, 1);
4263 +
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);
4269 +
4270 +       return 0;
4271 +}
4272 +
4273 +int br_del_if(struct net_bridge *br, struct device *dev)
4274 +{
4275 +       int retval;
4276 +
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);
4281 +
4282 +       return retval;
4283 +}
4284 +
4285 +int br_get_bridge_ifindices(int *indices, int num)
4286 +{
4287 +       struct net_bridge *br;
4288 +       int i;
4289 +
4290 +       br = bridge_list;
4291 +       for (i=0;i<num;i++) {
4292 +               if (br == NULL)
4293 +                       break;
4294 +
4295 +               indices[i] = br->dev.ifindex;
4296 +               br = br->next;
4297 +       }
4298 +
4299 +       return i;
4300 +}
4301 +
4302 +/* called under ioctl_lock */
4303 +void br_get_port_ifindices(struct net_bridge *br, int *ifindices)
4304 +{
4305 +       struct net_bridge_port *p;
4306 +
4307 +       p = br->port_list;
4308 +       while (p != NULL) {
4309 +               ifindices[p->port_no] = p->dev->ifindex;
4310 +               p = p->next;
4311 +       }
4312 +}
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
4316 @@ -0,0 +1,134 @@
4317 +/*
4318 + *     Handle incoming frames
4319 + *     Linux ethernet bridge
4320 + *
4321 + *     Authors:
4322 + *     Lennert Buytenhek               <buytenh@gnu.org>
4323 + *
4324 + *     $Id$
4325 + *
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.
4330 + *
4331 + *      Changes: 2000/02/03 [AF] Arne Fitzenreiter <arne.fitzenreiter@gmx.de>
4332 + *                               Bugfix - Multicast & Promiscious Mode
4333 + *
4334 + */
4335 +
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"
4342 +
4343 +unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
4344 +
4345 +static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
4346 +{
4347 +       br->statistics.rx_packets++;
4348 +       br->statistics.rx_bytes += skb->len;
4349 +
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);
4354 +       netif_rx(skb);
4355 +}
4356 +
4357 +void br_handle_frame(struct sk_buff *skb)
4358 +{
4359 +       struct net_bridge *br;
4360 +       unsigned char *dest;
4361 +       struct net_bridge_fdb_entry *dst;
4362 +       struct net_bridge_port *p;
4363 +       int passedup;
4364 +
4365 +       dest = skb->mac.ethernet->h_dest;
4366 +
4367 +       p = skb->dev->br_port;
4368 +       br = p->br;
4369 +       passedup = 0;
4370 +
4371 +       if (!(br->dev.flags & IFF_UP) ||
4372 +           p->state == BR_STATE_DISABLED)
4373 +               goto freeandout;
4374 +
4375 +       skb_push(skb, skb->data - skb->mac.raw);
4376 +       
4377 +       if (br->dev.flags & IFF_PROMISC && p->state == BR_STATE_FORWARDING) {
4378 +               struct sk_buff *skb2;
4379 +
4380 +               skb2 = skb_clone(skb, GFP_ATOMIC);
4381 +               if (skb2) {
4382 +                       passedup = 1;
4383 +                       br_pass_frame_up(br, skb2);
4384 +               }
4385 +       }
4386 +
4387 +       if (skb->mac.ethernet->h_source[0] & 1)
4388 +               goto freeandout;
4389 +
4390 +       if (!passedup &&
4391 +           (dest[0] & 1) &&
4392 +           (br->dev.flags & IFF_ALLMULTI || br->dev.mc_list != NULL) &&
4393 +           (p->state == BR_STATE_FORWARDING)) {
4394 +               struct sk_buff *skb2;
4395 +
4396 +               skb2 = skb_clone(skb, GFP_ATOMIC);
4397 +               if (skb2) {
4398 +                       passedup = 1;
4399 +                       br_pass_frame_up(br, skb2);
4400 +               }
4401 +       }
4402 +
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);
4406 +
4407 +       if (br->stp_enabled &&
4408 +           !memcmp(dest, bridge_ula, 5) &&
4409 +           !(dest[5] & 0xF0))
4410 +               goto handle_special_frame;
4411 +
4412 +       if (p->state != BR_STATE_FORWARDING)
4413 +               goto freeandout;
4414 +
4415 +       if (dest[0] & 1) {
4416 +               br_flood(br, skb, !passedup);
4417 +               if (!passedup)
4418 +                       br_pass_frame_up(br, skb);
4419 +               return;
4420 +       }
4421 +
4422 +       dst = br_fdb_get(br, dest);
4423 +
4424 +       if (dst != NULL && dst->is_local) {
4425 +               if (!passedup)
4426 +                       br_pass_frame_up(br, skb);
4427 +               else
4428 +                       kfree_skb(skb);
4429 +               br_fdb_put(dst);
4430 +               return;
4431 +       }
4432 +
4433 +       if (dst != NULL) {
4434 +               br_forward(dst->dst, skb);
4435 +               br_fdb_put(dst);
4436 +               return;
4437 +       }
4438 +
4439 +       br_flood(br, skb, 0);
4440 +       return;
4441 +
4442 + handle_special_frame:
4443 +       if (!dest[5]) {
4444 +               br_stp_handle_bpdu(skb);
4445 +               return;
4446 +       }
4447 +
4448 + freeandout:
4449 +       kfree_skb(skb);
4450 +}
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
4454 @@ -0,0 +1,264 @@
4455 +/*
4456 + *     Ioctl handler
4457 + *     Linux ethernet bridge
4458 + *
4459 + *     Authors:
4460 + *     Lennert Buytenhek               <buytenh@gnu.org>
4461 + *
4462 + *     $Id$
4463 + *
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.
4468 + */
4469 +
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"
4476 +
4477 +static int br_ioctl_device(struct net_bridge *br,
4478 +                          unsigned int cmd,
4479 +                          unsigned long arg0,
4480 +                          unsigned long arg1,
4481 +                          unsigned long arg2)
4482 +{
4483 +       if (br == NULL)
4484 +               return -EINVAL;
4485 +
4486 +       switch (cmd)
4487 +       {
4488 +       case BRCTL_ADD_IF:
4489 +       case BRCTL_DEL_IF:
4490 +       {
4491 +               struct device *dev;
4492 +
4493 +               dev = dev_get_by_index(arg0);
4494 +               if (dev == NULL)
4495 +                       return -EINVAL;
4496 +
4497 +               if (cmd == BRCTL_ADD_IF)
4498 +                       return br_add_if(br, dev);
4499 +
4500 +               return br_del_if(br, dev);
4501 +       }
4502 +
4503 +       case BRCTL_GET_BRIDGE_INFO:
4504 +       {
4505 +               struct __bridge_info b;
4506 +
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);
4527 +
4528 +               if (copy_to_user((void *)arg0, &b, sizeof(b)))
4529 +                       return -EFAULT;
4530 +
4531 +               return 0;
4532 +       }
4533 +
4534 +       case BRCTL_GET_PORT_LIST:
4535 +       {
4536 +               int i;
4537 +               int indices[256];
4538 +
4539 +               for (i=0;i<256;i++)
4540 +                       indices[i] = 0;
4541 +
4542 +               br_get_port_ifindices(br, indices);
4543 +               if (copy_to_user((void *)arg0, indices, 256*sizeof(int)))
4544 +                       return -EFAULT;
4545 +
4546 +               return 0;
4547 +       }
4548 +
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;
4553 +               return 0;
4554 +
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;
4559 +               return 0;
4560 +
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;
4565 +               return 0;
4566 +
4567 +       case BRCTL_SET_AGEING_TIME:
4568 +               br->ageing_time = arg0;
4569 +               return 0;
4570 +
4571 +       case BRCTL_SET_GC_INTERVAL:
4572 +               br->gc_interval = arg0;
4573 +               return 0;
4574 +
4575 +       case BRCTL_GET_PORT_INFO:
4576 +       {
4577 +               struct __port_info p;
4578 +               struct net_bridge_port *pt;
4579 +
4580 +               if ((pt = br_get_port(br, arg1)) == NULL)
4581 +                       return -EINVAL;
4582 +
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);
4596 +
4597 +               if (copy_to_user((void *)arg0, &p, sizeof(p)))
4598 +                       return -EFAULT;
4599 +
4600 +               return 0;
4601 +       }
4602 +
4603 +       case BRCTL_SET_BRIDGE_STP_STATE:
4604 +               br->stp_enabled = arg0?1:0;
4605 +               return 0;
4606 +
4607 +       case BRCTL_SET_BRIDGE_PRIORITY:
4608 +               br_stp_set_bridge_priority(br, arg0);
4609 +               return 0;
4610 +
4611 +       case BRCTL_SET_PORT_PRIORITY:
4612 +       {
4613 +               struct net_bridge_port *p;
4614 +
4615 +               if ((p = br_get_port(br, arg0)) == NULL)
4616 +                       return -EINVAL;
4617 +               br_stp_set_port_priority(p, arg1);
4618 +               return 0;
4619 +       }
4620 +
4621 +       case BRCTL_SET_PATH_COST:
4622 +       {
4623 +               struct net_bridge_port *p;
4624 +
4625 +               if ((p = br_get_port(br, arg0)) == NULL)
4626 +                       return -EINVAL;
4627 +               br_stp_set_path_cost(p, arg1);
4628 +               return 0;
4629 +       }
4630 +
4631 +       case BRCTL_GET_FDB_ENTRIES:
4632 +               return br_fdb_get_entries(br, (void *)arg0, arg1, arg2);
4633 +       }
4634 +
4635 +       return -EOPNOTSUPP;
4636 +}
4637 +
4638 +static int br_ioctl_deviceless(unsigned int cmd,
4639 +                              unsigned long arg0,
4640 +                              unsigned long arg1)
4641 +{
4642 +       switch (cmd)
4643 +       {
4644 +       case BRCTL_GET_VERSION:
4645 +               return BRCTL_VERSION;
4646 +
4647 +       case BRCTL_GET_BRIDGES:
4648 +       {
4649 +               int i;
4650 +               int indices[64];
4651 +
4652 +               for (i=0;i<64;i++)
4653 +                       indices[i] = 0;
4654 +
4655 +               if (arg1 > 64)
4656 +                       arg1 = 64;
4657 +               arg1 = br_get_bridge_ifindices(indices, arg1);
4658 +               if (copy_to_user((void *)arg0, indices, arg1*sizeof(int)))
4659 +                       return -EFAULT;
4660 +
4661 +               return arg1;
4662 +       }
4663 +
4664 +       case BRCTL_ADD_BRIDGE:
4665 +       case BRCTL_DEL_BRIDGE:
4666 +       {
4667 +               char buf[IFNAMSIZ];
4668 +
4669 +               if (copy_from_user(buf, (void *)arg0, IFNAMSIZ))
4670 +                       return -EFAULT;
4671 +
4672 +               buf[IFNAMSIZ-1] = 0;
4673 +
4674 +               if (cmd == BRCTL_ADD_BRIDGE)
4675 +                       return br_add_bridge(buf);
4676 +
4677 +               return br_del_bridge(buf);
4678 +       }
4679 +       }
4680 +
4681 +       return -EOPNOTSUPP;
4682 +}
4683 +
4684 +static struct semaphore ioctl_mutex = MUTEX;
4685 +
4686 +int br_ioctl_deviceless_stub(unsigned long arg)
4687 +{
4688 +       int err;
4689 +       unsigned long i[3];
4690 +
4691 +       if (!capable(CAP_NET_ADMIN))
4692 +               return -EPERM;
4693 +
4694 +       if (copy_from_user(i, (void *)arg, 3*sizeof(unsigned long)))
4695 +               return -EFAULT;
4696 +
4697 +       down(&ioctl_mutex);
4698 +       err = br_ioctl_deviceless(i[0], i[1], i[2]);
4699 +       up(&ioctl_mutex);
4700 +
4701 +       return err;
4702 +}
4703 +
4704 +int br_ioctl(struct net_bridge *br, unsigned int cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2)
4705 +{
4706 +       int err;
4707 +
4708 +       if (!capable(CAP_NET_ADMIN))
4709 +               return -EPERM;
4710 +
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);
4715 +       up(&ioctl_mutex);
4716 +
4717 +       return err;
4718 +}
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
4722 @@ -0,0 +1,76 @@
4723 +/*
4724 + *     Device event handling
4725 + *     Linux ethernet bridge
4726 + *
4727 + *     Authors:
4728 + *     Lennert Buytenhek               <buytenh@gnu.org>
4729 + *
4730 + *     $Id$
4731 + *
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.
4736 + */
4737 +
4738 +#include <linux/config.h>
4739 +#include <linux/kernel.h>
4740 +#include <linux/if_bridge.h>
4741 +#include "br_private.h"
4742 +
4743 +static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr);
4744 +
4745 +struct notifier_block br_device_notifier =
4746 +{
4747 +       br_device_event,
4748 +       NULL,
4749 +       0
4750 +};
4751 +
4752 +static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
4753 +{
4754 +       struct device *dev;
4755 +       struct net_bridge_port *p;
4756 +
4757 +       dev = ptr;
4758 +       p = dev->br_port;
4759 +
4760 +       if (p == NULL)
4761 +               return NOTIFY_DONE;
4762 +
4763 +       switch (event)
4764 +       {
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);
4770 +               break;
4771 +
4772 +       case NETDEV_GOING_DOWN:
4773 +               /* extend the protocol to send some kind of notification? */
4774 +               break;
4775 +
4776 +       case NETDEV_DOWN:
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);
4781 +               }
4782 +               break;
4783 +
4784 +       case NETDEV_UP:
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);
4789 +               }
4790 +               break;
4791 +
4792 +       case NETDEV_UNREGISTER:
4793 +               br_del_if(dev->br_port->br, dev);
4794 +               break;
4795 +       }
4796 +
4797 +       return NOTIFY_DONE;
4798 +}
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
4802 @@ -0,0 +1,216 @@
4803 +/*
4804 + *     Linux ethernet bridge
4805 + *
4806 + *     Authors:
4807 + *     Lennert Buytenhek               <buytenh@gnu.org>
4808 + *
4809 + *     $Id$
4810 + *
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.
4815 + */
4816 +
4817 +#ifndef _BR_PRIVATE_H
4818 +#define _BR_PRIVATE_H
4819 +
4820 +#include <linux/netdevice.h>
4821 +#include <linux/miscdevice.h>
4822 +#include <linux/if_bridge.h>
4823 +
4824 +#define BR_HASH_BITS 8
4825 +#define BR_HASH_SIZE (1 << BR_HASH_BITS)
4826 +
4827 +#define BR_HOLD_TIME (1*HZ)
4828 +
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(); }
4834 +#endif
4835 +
4836 +typedef struct bridge_id bridge_id;
4837 +typedef struct mac_addr mac_addr;
4838 +typedef __u16 port_id;
4839 +
4840 +#if 1
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)))
4847 +#endif
4848 +
4849 +
4850 +
4851 +struct bridge_id
4852 +{
4853 +       unsigned char   prio[2];
4854 +       unsigned char   addr[6];
4855 +};
4856 +
4857 +struct mac_addr
4858 +{
4859 +       unsigned char   addr[6];
4860 +       unsigned char   pad[2];
4861 +};
4862 +
4863 +struct net_bridge_fdb_entry
4864 +{
4865 +       struct net_bridge_fdb_entry     *next_hash;
4866 +       struct net_bridge_fdb_entry     **pprev_hash;
4867 +       atomic_t                        use_count;
4868 +       mac_addr                        addr;
4869 +       struct net_bridge_port          *dst;
4870 +       unsigned long                   ageing_timer;
4871 +       unsigned                        is_local:1;
4872 +       unsigned                        is_static:1;
4873 +};
4874 +
4875 +struct net_bridge_port
4876 +{
4877 +       struct net_bridge_port          *next;
4878 +       struct net_bridge               *br;
4879 +       struct device                   *dev;
4880 +       int                             port_no;
4881 +
4882 +       /* STP */
4883 +       port_id                         port_id;
4884 +       int                             state;
4885 +       int                             path_cost;
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;
4892 +       int                             priority;
4893 +
4894 +       struct br_timer                 forward_delay_timer;
4895 +       struct br_timer                 hold_timer;
4896 +       struct br_timer                 message_age_timer;
4897 +};
4898 +
4899 +struct net_bridge
4900 +{
4901 +       struct net_bridge               *next;
4902 +       rwlock_t                        lock;
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;
4910 +
4911 +       /* STP */
4912 +       bridge_id                       designated_root;
4913 +       int                             root_path_cost;
4914 +       int                             root_port;
4915 +       int                             max_age;
4916 +       int                             hello_time;
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;
4925 +
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;
4930 +
4931 +       int                             ageing_time;
4932 +       int                             gc_interval;
4933 +};
4934 +
4935 +struct notifier_block br_device_notifier;
4936 +unsigned char bridge_ula[6];
4937 +
4938 +/* br.c */
4939 +void br_dec_use_count(void);
4940 +void br_inc_use_count(void);
4941 +
4942 +/* br_device.c */
4943 +void br_dev_setup(struct device *dev);
4944 +int br_dev_xmit(struct sk_buff *skb, struct device *dev);
4945 +
4946 +/* br_fdb.c */
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,
4957 +                       int maxnum,
4958 +                       int offset);
4959 +void br_fdb_insert(struct net_bridge *br,
4960 +                  struct net_bridge_port *source,
4961 +                  unsigned char *addr,
4962 +                  int is_local);
4963 +
4964 +/* br_forward.c */
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,
4969 +             int clone);
4970 +
4971 +/* br_if.c */
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,
4979 +                           int num);
4980 +void br_get_port_ifindices(struct net_bridge *br,
4981 +                          int *ifindices);
4982 +
4983 +/* br_input.c */
4984 +void br_handle_frame(struct sk_buff *skb);
4985 +
4986 +/* br_ioctl.c */
4987 +int br_ioctl(struct net_bridge *br,
4988 +            unsigned int cmd,
4989 +            unsigned long arg0,
4990 +            unsigned long arg1,
4991 +            unsigned long arg2);
4992 +int br_ioctl_deviceless_stub(unsigned long arg);
4993 +
4994 +/* br_stp.c */
4995 +int br_is_root_bridge(struct net_bridge *br);
4996 +struct net_bridge_port *br_get_port(struct net_bridge *br,
4997 +                                   int port_no);
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);
5001 +
5002 +/* br_stp_if.c */
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,
5009 +                               int newprio);
5010 +void br_stp_set_port_priority(struct net_bridge_port *p,
5011 +                             int newprio);
5012 +void br_stp_set_path_cost(struct net_bridge_port *p,
5013 +                         int path_cost);
5014 +
5015 +/* br_stp_bpdu.c */
5016 +void br_stp_handle_bpdu(struct sk_buff *skb);
5017 +
5018 +#endif
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
5022 @@ -0,0 +1,53 @@
5023 +/*
5024 + *     Linux ethernet bridge
5025 + *
5026 + *     Authors:
5027 + *     Lennert Buytenhek               <buytenh@gnu.org>
5028 + *
5029 + *     $Id$
5030 + *
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.
5035 + */
5036 +
5037 +#ifndef _BR_PRIVATE_STP_H
5038 +#define _BR_PRIVATE_STP_H
5039 +
5040 +#define BPDU_TYPE_CONFIG 0
5041 +#define BPDU_TYPE_TCN 0x80
5042 +
5043 +struct br_config_bpdu
5044 +{
5045 +       unsigned        topology_change:1;
5046 +       unsigned        topology_change_ack:1;
5047 +       bridge_id       root;
5048 +       int             root_path_cost;
5049 +       bridge_id       bridge_id;
5050 +       port_id         port_id;
5051 +       int             message_age;
5052 +       int             max_age;
5053 +       int             hello_time;
5054 +       int             forward_delay;
5055 +};
5056 +
5057 +/* br_stp.c */
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);
5070 +
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 *);
5074 +
5075 +#endif
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
5079 @@ -0,0 +1,467 @@
5080 +/*
5081 + *     Spanning tree protocol; generic parts
5082 + *     Linux ethernet bridge
5083 + *
5084 + *     Authors:
5085 + *     Lennert Buytenhek               <buytenh@gnu.org>
5086 + *
5087 + *     $Id$
5088 + *
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.
5093 + */
5094 +
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"
5102 +
5103 +
5104 +
5105 +/* called under ioctl_lock or bridge lock */
5106 +int br_is_root_bridge(struct net_bridge *br)
5107 +{
5108 +       return !memcmp(&br->bridge_id, &br->designated_root, 8);
5109 +}
5110 +
5111 +/* called under bridge lock */
5112 +int br_is_designated_port(struct net_bridge_port *p)
5113 +{
5114 +       return !memcmp(&p->designated_bridge, &p->br->bridge_id, 8) &&
5115 +               (p->designated_port == p->port_id);
5116 +}
5117 +
5118 +/* called under ioctl_lock or bridge lock */
5119 +struct net_bridge_port *br_get_port(struct net_bridge *br, int port_no)
5120 +{
5121 +       struct net_bridge_port *p;
5122 +
5123 +       p = br->port_list;
5124 +       while (p != NULL) {
5125 +               if (p->port_no == port_no)
5126 +                       return p;
5127 +
5128 +               p = p->next;
5129 +       }
5130 +
5131 +       return NULL;
5132 +}
5133 +
5134 +/* called under bridge lock */
5135 +static int br_should_become_root_port(struct net_bridge_port *p, int root_port)
5136 +{
5137 +       struct net_bridge *br;
5138 +       struct net_bridge_port *rp;
5139 +       int t;
5140 +
5141 +       br = p->br;
5142 +       if (p->state == BR_STATE_DISABLED ||
5143 +           br_is_designated_port(p))
5144 +               return 0;
5145 +
5146 +       if (memcmp(&br->bridge_id, &p->designated_root, 8) <= 0)
5147 +               return 0;
5148 +
5149 +       if (!root_port)
5150 +               return 1;
5151 +
5152 +       rp = br_get_port(br, root_port);
5153 +
5154 +       t = memcmp(&p->designated_root, &rp->designated_root, 8);
5155 +       if (t < 0)
5156 +               return 1;
5157 +       else if (t > 0)
5158 +               return 0;
5159 +
5160 +       if (p->designated_cost + p->path_cost <
5161 +           rp->designated_cost + rp->path_cost)
5162 +               return 1;
5163 +       else if (p->designated_cost + p->path_cost >
5164 +                rp->designated_cost + rp->path_cost)
5165 +               return 0;
5166 +
5167 +       t = memcmp(&p->designated_bridge, &rp->designated_bridge, 8);
5168 +       if (t < 0)
5169 +               return 1;
5170 +       else if (t > 0)
5171 +               return 0;
5172 +
5173 +       if (p->designated_port < rp->designated_port)
5174 +               return 1;
5175 +       else if (p->designated_port > rp->designated_port)
5176 +               return 0;
5177 +
5178 +       if (p->port_id < rp->port_id)
5179 +               return 1;
5180 +
5181 +       return 0;
5182 +}
5183 +
5184 +/* called under bridge lock */
5185 +static void br_root_selection(struct net_bridge *br)
5186 +{
5187 +       struct net_bridge_port *p;
5188 +       int root_port;
5189 +
5190 +       root_port = 0;
5191 +
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;
5196 +
5197 +               p = p->next;
5198 +       }
5199 +
5200 +       br->root_port = root_port;
5201 +
5202 +       if (!root_port) {
5203 +               br->designated_root = br->bridge_id;
5204 +               br->root_path_cost = 0;
5205 +       } else {
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;
5209 +       }
5210 +}
5211 +
5212 +/* called under bridge lock */
5213 +void br_become_root_bridge(struct net_bridge *br)
5214 +{
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);
5222 +}
5223 +
5224 +/* called under bridge lock */
5225 +void br_transmit_config(struct net_bridge_port *p)
5226 +{
5227 +       struct br_config_bpdu bpdu;
5228 +       struct net_bridge *br;
5229 +
5230 +       if (br_timer_is_running(&p->hold_timer)) {
5231 +               p->config_pending = 1;
5232 +               return;
5233 +       }
5234 +
5235 +       br = p->br;
5236 +
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;
5247 +
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;
5251 +       }
5252 +       bpdu.max_age = br->max_age;
5253 +       bpdu.hello_time = br->hello_time;
5254 +       bpdu.forward_delay = br->forward_delay;
5255 +
5256 +       br_send_config_bpdu(p, &bpdu);
5257 +
5258 +       p->topology_change_ack = 0;
5259 +       p->config_pending = 0;
5260 +       br_timer_set(&p->hold_timer, jiffies);
5261 +}
5262 +
5263 +/* called under bridge lock */
5264 +static void br_record_config_information(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5265 +{
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;
5270 +
5271 +       br_timer_set(&p->message_age_timer, jiffies - bpdu->message_age);
5272 +}
5273 +
5274 +/* called under bridge lock */
5275 +static void br_record_config_timeout_values(struct net_bridge *br, struct br_config_bpdu *bpdu)
5276 +{
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;
5281 +}
5282 +
5283 +/* called under bridge lock */
5284 +void br_transmit_tcn(struct net_bridge *br)
5285 +{
5286 +       br_send_tcn_bpdu(br_get_port(br, br->root_port));
5287 +}
5288 +
5289 +/* called under bridge lock */
5290 +static int br_should_become_designated_port(struct net_bridge_port *p)
5291 +{
5292 +       struct net_bridge *br;
5293 +       int t;
5294 +
5295 +       br = p->br;
5296 +       if (br_is_designated_port(p))
5297 +               return 1;
5298 +
5299 +       if (memcmp(&p->designated_root, &br->designated_root, 8))
5300 +               return 1;
5301 +
5302 +       if (br->root_path_cost < p->designated_cost)
5303 +               return 1;
5304 +       else if (br->root_path_cost > p->designated_cost)
5305 +               return 0;
5306 +
5307 +       t = memcmp(&br->bridge_id, &p->designated_bridge, 8);
5308 +       if (t < 0)
5309 +               return 1;
5310 +       else if (t > 0)
5311 +               return 0;
5312 +
5313 +       if (p->port_id < p->designated_port)
5314 +               return 1;
5315 +
5316 +       return 0;
5317 +}
5318 +
5319 +/* called under bridge lock */
5320 +static void br_designated_port_selection(struct net_bridge *br)
5321 +{
5322 +       struct net_bridge_port *p;
5323 +
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);
5329 +
5330 +               p = p->next;
5331 +       }
5332 +}
5333 +
5334 +/* called under bridge lock */
5335 +static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5336 +{
5337 +       int t;
5338 +
5339 +       t = memcmp(&bpdu->root, &p->designated_root, 8);
5340 +       if (t < 0)
5341 +               return 1;
5342 +       else if (t > 0)
5343 +               return 0;
5344 +
5345 +       if (bpdu->root_path_cost < p->designated_cost)
5346 +               return 1;
5347 +       else if (bpdu->root_path_cost > p->designated_cost)
5348 +               return 0;
5349 +
5350 +       t = memcmp(&bpdu->bridge_id, &p->designated_bridge, 8);
5351 +       if (t < 0)
5352 +               return 1;
5353 +       else if (t > 0)
5354 +               return 0;
5355 +
5356 +       if (memcmp(&bpdu->bridge_id, &p->br->bridge_id, 8))
5357 +               return 1;
5358 +
5359 +       if (bpdu->port_id <= p->designated_port)
5360 +               return 1;
5361 +
5362 +       return 0;
5363 +}
5364 +
5365 +/* called under bridge lock */
5366 +static void br_topology_change_acknowledged(struct net_bridge *br)
5367 +{
5368 +       br->topology_change_detected = 0;
5369 +       br_timer_clear(&br->tcn_timer);
5370 +}
5371 +
5372 +/* called under bridge lock */
5373 +void br_topology_change_detection(struct net_bridge *br)
5374 +{
5375 +       printk(KERN_INFO "%s: topology change detected", br->name);
5376 +
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);
5385 +       }
5386 +
5387 +       printk("\n");
5388 +       br->topology_change_detected = 1;
5389 +}
5390 +
5391 +/* called under bridge lock */
5392 +void br_config_bpdu_generation(struct net_bridge *br)
5393 +{
5394 +       struct net_bridge_port *p;
5395 +
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);
5401 +
5402 +               p = p->next;
5403 +       }
5404 +}
5405 +
5406 +/* called under bridge lock */
5407 +static void br_reply(struct net_bridge_port *p)
5408 +{
5409 +       br_transmit_config(p);
5410 +}
5411 +
5412 +/* called under bridge lock */
5413 +void br_configuration_update(struct net_bridge *br)
5414 +{
5415 +       br_root_selection(br);
5416 +       br_designated_port_selection(br);
5417 +}
5418 +
5419 +/* called under bridge lock */
5420 +void br_become_designated_port(struct net_bridge_port *p)
5421 +{
5422 +       struct net_bridge *br;
5423 +
5424 +       br = p->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;
5429 +}
5430 +
5431 +/* called under bridge lock */
5432 +static void br_make_blocking(struct net_bridge_port *p)
5433 +{
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);
5439 +
5440 +               printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
5441 +                      p->br->name, p->port_no, p->dev->name, "blocking");
5442 +
5443 +               p->state = BR_STATE_BLOCKING;
5444 +               br_timer_clear(&p->forward_delay_timer);
5445 +       }
5446 +}
5447 +
5448 +/* called under bridge lock */
5449 +static void br_make_forwarding(struct net_bridge_port *p)
5450 +{
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");
5454 +
5455 +               p->state = BR_STATE_LISTENING;
5456 +               br_timer_set(&p->forward_delay_timer, jiffies);
5457 +       }
5458 +}
5459 +
5460 +/* called under bridge lock */
5461 +void br_port_state_selection(struct net_bridge *br)
5462 +{
5463 +       struct net_bridge_port *p;
5464 +
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);
5475 +                       } else {
5476 +                               p->config_pending = 0;
5477 +                               p->topology_change_ack = 0;
5478 +                               br_make_blocking(p);
5479 +                       }
5480 +               }
5481 +
5482 +               p = p->next;
5483 +       }
5484 +}
5485 +
5486 +/* called under bridge lock */
5487 +static void br_topology_change_acknowledge(struct net_bridge_port *p)
5488 +{
5489 +       p->topology_change_ack = 1;
5490 +       br_transmit_config(p);
5491 +}
5492 +
5493 +/* lock-safe */
5494 +void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5495 +{
5496 +       struct net_bridge *br;
5497 +       int was_root;
5498 +
5499 +       if (p->state == BR_STATE_DISABLED)
5500 +               return;
5501 +
5502 +       br = p->br;
5503 +       read_lock(&br->lock);
5504 +
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);
5510 +
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);
5517 +                       }
5518 +               }
5519 +
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);
5525 +               }
5526 +       } else if (br_is_designated_port(p)) {          
5527 +               br_reply(p);            
5528 +       }
5529 +
5530 +       read_unlock(&br->lock);
5531 +}
5532 +
5533 +/* lock-safe */
5534 +void br_received_tcn_bpdu(struct net_bridge_port *p)
5535 +{
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);
5541 +
5542 +               br_topology_change_detection(p->br);
5543 +               br_topology_change_acknowledge(p);
5544 +       }
5545 +       read_unlock(&p->br->lock);
5546 +}
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
5550 @@ -0,0 +1,191 @@
5551 +/*
5552 + *     Spanning tree protocol; BPDU handling
5553 + *     Linux ethernet bridge
5554 + *
5555 + *     Authors:
5556 + *     Lennert Buytenhek               <buytenh@gnu.org>
5557 + *
5558 + *     $Id$
5559 + *
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.
5564 + */
5565 +
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"
5572 +
5573 +#define JIFFIES_TO_TICKS(j) (((j) << 8) / HZ)
5574 +#define TICKS_TO_JIFFIES(j) (((j) * HZ) >> 8)
5575 +
5576 +static void br_send_bpdu(struct net_bridge_port *p, unsigned char *data, int length)
5577 +{
5578 +       struct device *dev;
5579 +       struct sk_buff *skb;
5580 +       int size;
5581 +
5582 +       if (!p->br->stp_enabled)
5583 +               return;
5584 +
5585 +       size = length + 2*ETH_ALEN + 2;
5586 +       if (size < 60)
5587 +               size = 60;
5588 +
5589 +       dev = p->dev;
5590 +
5591 +       if ((skb = dev_alloc_skb(size)) == NULL) {
5592 +               printk(KERN_INFO "br: memory squeeze!\n");
5593 +               return;
5594 +       }
5595 +
5596 +       skb->dev = dev;
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);
5606 +
5607 +       dev_queue_xmit(skb);
5608 +}
5609 +
5610 +static __inline__ void br_set_ticks(unsigned char *dest, int jiff)
5611 +{
5612 +       __u16 ticks;
5613 +
5614 +       ticks = JIFFIES_TO_TICKS(jiff);
5615 +       dest[0] = (ticks >> 8) & 0xFF;
5616 +       dest[1] = ticks & 0xFF;
5617 +}
5618 +
5619 +static __inline__ int br_get_ticks(unsigned char *dest)
5620 +{
5621 +       return TICKS_TO_JIFFIES((dest[0] << 8) | dest[1]);
5622 +}
5623 +
5624 +void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5625 +{
5626 +       unsigned char buf[38];
5627 +
5628 +       buf[0] = 0x42;
5629 +       buf[1] = 0x42;
5630 +       buf[2] = 0x03;
5631 +       buf[3] = 0;
5632 +       buf[4] = 0;
5633 +       buf[5] = 0;
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;
5659 +
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);
5664 +
5665 +       br_send_bpdu(p, buf, 38);
5666 +}
5667 +
5668 +void br_send_tcn_bpdu(struct net_bridge_port *p)
5669 +{
5670 +       unsigned char buf[7];
5671 +
5672 +       buf[0] = 0x42;
5673 +       buf[1] = 0x42;
5674 +       buf[2] = 0x03;
5675 +       buf[3] = 0;
5676 +       buf[4] = 0;
5677 +       buf[5] = 0;
5678 +       buf[6] = BPDU_TYPE_TCN;
5679 +       br_send_bpdu(p, buf, 7);
5680 +}
5681 +
5682 +static unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
5683 +
5684 +void br_stp_handle_bpdu(struct sk_buff *skb)
5685 +{
5686 +       unsigned char *buf;
5687 +       struct net_bridge_port *p;
5688 +
5689 +       buf = skb->mac.raw + 14;
5690 +       p = skb->dev->br_port;
5691 +       if (!p->br->stp_enabled || memcmp(buf, header, 6)) {
5692 +               kfree_skb(skb);
5693 +               return;
5694 +       }
5695 +
5696 +       if (buf[6] == BPDU_TYPE_CONFIG) {
5697 +               struct br_config_bpdu bpdu;
5698 +
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 =
5710 +                       (buf[16] << 24) |
5711 +                       (buf[17] << 16) |
5712 +                       (buf[18] << 8) |
5713 +                       buf[19];
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];
5723 +
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);
5728 +
5729 +               kfree_skb(skb);
5730 +               br_received_config_bpdu(p, &bpdu);
5731 +               return;
5732 +       }
5733 +
5734 +       if (buf[6] == BPDU_TYPE_TCN) {
5735 +               br_received_tcn_bpdu(p);
5736 +               kfree_skb(skb);
5737 +               return;
5738 +       }
5739 +
5740 +       kfree_skb(skb);
5741 +}
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
5745 @@ -0,0 +1,232 @@
5746 +/*
5747 + *     Spanning tree protocol; interface code
5748 + *     Linux ethernet bridge
5749 + *
5750 + *     Authors:
5751 + *     Lennert Buytenhek               <buytenh@gnu.org>
5752 + *
5753 + *     $Id$
5754 + *
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.
5759 + */
5760 +
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"
5770 +
5771 +__u16 br_make_port_id(struct net_bridge_port *p)
5772 +{
5773 +       return (p->priority << 8) | p->port_no;
5774 +}
5775 +
5776 +/* called under bridge lock */
5777 +void br_init_port(struct net_bridge_port *p)
5778 +{
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);
5787 +}
5788 +
5789 +/* called under bridge lock */
5790 +void br_stp_enable_bridge(struct net_bridge *br)
5791 +{
5792 +       struct net_bridge_port *p;
5793 +       struct timer_list *timer = &br->tick;
5794 +
5795 +       init_timer(timer);
5796 +       timer->data = (unsigned long) br;
5797 +       timer->function = br_tick;
5798 +       timer->expires = jiffies + 1;
5799 +       add_timer(timer);
5800 +
5801 +       br_timer_set(&br->hello_timer, jiffies);
5802 +       br_config_bpdu_generation(br);
5803 +
5804 +       p = br->port_list;
5805 +       while (p != NULL) {
5806 +               if (p->dev->flags & IFF_UP)
5807 +                       br_stp_enable_port(p);
5808 +
5809 +               p = p->next;
5810 +       }
5811 +
5812 +       br_timer_set(&br->gc_timer, jiffies);
5813 +}
5814 +
5815 +/* called under bridge lock */
5816 +void br_stp_disable_bridge(struct net_bridge *br)
5817 +{
5818 +       struct net_bridge_port *p;
5819 +
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);
5827 +
5828 +       p = br->port_list;
5829 +       while (p != NULL) {
5830 +               if (p->state != BR_STATE_DISABLED)
5831 +                       br_stp_disable_port(p);
5832 +
5833 +               p = p->next;
5834 +       }
5835 +
5836 +       del_timer(&br->tick);
5837 +       synchronize_bh();
5838 +}
5839 +
5840 +/* called under bridge lock */
5841 +void br_stp_enable_port(struct net_bridge_port *p)
5842 +{
5843 +       br_init_port(p);
5844 +       br_port_state_selection(p->br);
5845 +}
5846 +
5847 +/* called under bridge lock */
5848 +void br_stp_disable_port(struct net_bridge_port *p)
5849 +{
5850 +       struct net_bridge *br;
5851 +       int wasroot;
5852 +
5853 +       br = p->br;
5854 +       printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
5855 +              br->name, p->port_no, p->dev->name, "disabled");
5856 +
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);
5867 +
5868 +       if (br_is_root_bridge(br) && !wasroot)
5869 +               br_become_root_bridge(br);
5870 +}
5871 +
5872 +/* called under bridge lock */
5873 +static void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr)
5874 +{
5875 +       unsigned char oldaddr[6];
5876 +       struct net_bridge_port *p;
5877 +       int wasroot;
5878 +
5879 +       wasroot = br_is_root_bridge(br);
5880 +
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);
5884 +
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);
5889 +
5890 +               if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN))
5891 +                       memcpy(p->designated_root.addr, addr, ETH_ALEN);
5892 +
5893 +               p = p->next;
5894 +       }
5895 +
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);
5900 +}
5901 +
5902 +static unsigned char br_mac_zero[6] = {0,0,0,0,0,0};
5903 +
5904 +/* called under bridge lock */
5905 +void br_stp_recalculate_bridge_id(struct net_bridge *br)
5906 +{
5907 +       unsigned char *addr;
5908 +       struct net_bridge_port *p;
5909 +
5910 +       addr = br_mac_zero;
5911 +
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;
5917 +
5918 +               p = p->next;
5919 +       }
5920 +
5921 +       if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))
5922 +               br_stp_change_bridge_id(br, addr);
5923 +}
5924 +
5925 +/* called under bridge lock */
5926 +void br_stp_set_bridge_priority(struct net_bridge *br, int newprio)
5927 +{
5928 +       struct net_bridge_port *p;
5929 +       int wasroot;
5930 +
5931 +       wasroot = br_is_root_bridge(br);
5932 +
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;
5939 +               }
5940 +
5941 +               p = p->next;
5942 +       }
5943 +
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);
5950 +}
5951 +
5952 +/* called under bridge lock */
5953 +void br_stp_set_port_priority(struct net_bridge_port *p, int newprio)
5954 +{
5955 +       __u16 new_port_id;
5956 +
5957 +       p->priority = newprio & 0xFF;
5958 +       new_port_id = br_make_port_id(p);
5959 +
5960 +       if (br_is_designated_port(p))
5961 +               p->designated_port = new_port_id;
5962 +
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);
5968 +       }
5969 +}
5970 +
5971 +/* called under bridge lock */
5972 +void br_stp_set_path_cost(struct net_bridge_port *p, int path_cost)
5973 +{
5974 +       p->path_cost = path_cost;
5975 +       br_configuration_update(p->br);
5976 +       br_port_state_selection(p->br);
5977 +}
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
5981 @@ -0,0 +1,185 @@
5982 +/*
5983 + *     Spanning tree protocol; timer-related code
5984 + *     Linux ethernet bridge
5985 + *
5986 + *     Authors:
5987 + *     Lennert Buytenhek               <buytenh@gnu.org>
5988 + *
5989 + *     $Id$
5990 + *
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.
5995 + */
5996 +
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"
6004 +
6005 +static void dump_bridge_id(bridge_id *id)
6006 +{
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]);
6010 +}
6011 +
6012 +/* called under bridge lock */
6013 +static int br_is_designated_for_some_port(struct net_bridge *br)
6014 +{
6015 +       struct net_bridge_port *p;
6016 +
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))
6021 +                       return 1;
6022 +
6023 +               p = p->next;
6024 +       }
6025 +
6026 +       return 0;
6027 +}
6028 +
6029 +/* called under bridge lock */
6030 +static void br_hello_timer_expired(struct net_bridge *br)
6031 +{
6032 +       br_config_bpdu_generation(br);
6033 +       br_timer_set(&br->hello_timer, jiffies);
6034 +}
6035 +
6036 +/* called under bridge lock */
6037 +static void br_message_age_timer_expired(struct net_bridge_port *p)
6038 +{
6039 +       struct net_bridge *br;
6040 +       int was_root;
6041 +
6042 +       br = p->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);
6047 +
6048 +       /*
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.
6052 +        */
6053 +       was_root = br_is_root_bridge(br);
6054 +
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);
6060 +}
6061 +
6062 +/* called under bridge lock */
6063 +static void br_forward_delay_timer_expired(struct net_bridge_port *p)
6064 +{
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");
6068 +
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");
6074 +
6075 +               p->state = BR_STATE_FORWARDING;
6076 +               if (br_is_designated_for_some_port(p->br))
6077 +                       br_topology_change_detection(p->br);
6078 +       }
6079 +}
6080 +
6081 +/* called under bridge lock */
6082 +static void br_tcn_timer_expired(struct net_bridge *br)
6083 +{
6084 +       printk(KERN_INFO "%s: retransmitting tcn bpdu\n", br->name);
6085 +       br_transmit_tcn(br);
6086 +       br_timer_set(&br->tcn_timer, jiffies);
6087 +}
6088 +
6089 +/* called under bridge lock */
6090 +static void br_topology_change_timer_expired(struct net_bridge *br)
6091 +{
6092 +       br->topology_change_detected = 0;
6093 +       br->topology_change = 0;
6094 +}
6095 +
6096 +/* called under bridge lock */
6097 +static void br_hold_timer_expired(struct net_bridge_port *p)
6098 +{
6099 +       if (p->config_pending)
6100 +               br_transmit_config(p);
6101 +}
6102 +
6103 +/* called under bridge lock */
6104 +static void br_check_port_timers(struct net_bridge_port *p)
6105 +{
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);
6109 +       }
6110 +
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);
6114 +       }
6115 +
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);
6119 +       }
6120 +}
6121 +
6122 +/* called under bridge lock */
6123 +static void br_check_timers(struct net_bridge *br)
6124 +{
6125 +       struct net_bridge_port *p;
6126 +
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);
6130 +       }
6131 +
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);
6135 +       }
6136 +
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);
6140 +       }
6141 +
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);
6145 +       }
6146 +
6147 +       p = br->port_list;
6148 +       while (p != NULL) {
6149 +               if (p->state != BR_STATE_DISABLED)
6150 +                       br_check_port_timers(p);
6151 +
6152 +               p = p->next;
6153 +       }
6154 +}
6155 +
6156 +void br_tick(unsigned long __data)
6157 +{
6158 +       struct net_bridge *br = (struct net_bridge *)__data;
6159 +
6160 +       read_lock(&br->lock);
6161 +       br_check_timers(br);
6162 +       read_unlock(&br->lock);
6163 +
6164 +       br->tick.expires = jiffies + 1;
6165 +       add_timer(&br->tick);
6166 +}
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
6170 @@ -1,501 +0,0 @@
6171 -/*
6172 - *     This code is derived from the avl functions in mmap.c
6173 - */
6174 -
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>
6181 -
6182 -#include <net/br.h>
6183 -#define _DEBUG_AVL
6184 -
6185 -/*
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
6195 - */
6196 -
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;
6201 -
6202 -#ifdef DEBUG_AVL
6203 -static void printk_avl (struct fdb * tree);
6204 -#endif
6205 -
6206 -static int addr_cmp(unsigned char *a1, unsigned char *a2);
6207 -
6208 -/*
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.
6216 - */
6217
6218 -#ifndef avl_br_empty
6219 -#define avl_br_empty   (struct fdb *) NULL
6220 -#endif
6221 -
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)
6225 -/*
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.
6231 - */
6232 -
6233 -static int fdb_init(void)
6234 -{
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;
6238 -       fdb_inited = 1;
6239 -       return(0);
6240 -}
6241 -
6242 -struct fdb *br_avl_find_addr(unsigned char addr[6])
6243 -{
6244 -       struct fdb * result = NULL;
6245 -       struct fdb * tree;
6246 -
6247 -       if (!fdb_inited)
6248 -               fdb_init();
6249 -#if (DEBUG_AVL)
6250 -       printk("searching for ula %02x:%02x:%02x:%02x:%02x:%02x\n",
6251 -               addr[0],
6252 -               addr[1],
6253 -               addr[2],
6254 -               addr[3],
6255 -               addr[4],
6256 -               addr[5]);
6257 -#endif /* DEBUG_AVL */
6258 -       for (tree = fhp ; ; ) {
6259 -               if (tree == avl_br_empty) {
6260 -#if (DEBUG_AVL)
6261 -                       printk("search failed, returning node 0x%x\n", (unsigned int)result);
6262 -#endif /* DEBUG_AVL */
6263 -                       return result;
6264 -               }
6265 -
6266 -#if (DEBUG_AVL)
6267 -               printk("node 0x%x: checking ula %02x:%02x:%02x:%02x:%02x:%02x\n",
6268 -                       (unsigned int)tree,
6269 -                       tree->ula[0],
6270 -                       tree->ula[1],
6271 -                       tree->ula[2],
6272 -                       tree->ula[3],
6273 -                       tree->ula[4],
6274 -                       tree->ula[5]);
6275 -#endif /* DEBUG_AVL */
6276 -               if (addr_cmp(addr, tree->ula) == 0) {
6277 -#if (DEBUG_AVL)
6278 -                       printk("found node 0x%x\n", (unsigned int)tree);
6279 -#endif /* DEBUG_AVL */
6280 -                       return tree;
6281 -               }
6282 -               if (addr_cmp(addr, tree->ula) < 0) {
6283 -                       tree = tree->fdb_avl_left;
6284 -               } else {
6285 -                       tree = tree->fdb_avl_right;
6286 -               }
6287 -       }
6288 -}
6289 -
6290 -
6291 -/*
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}.
6296 - */
6297 -static void br_avl_rebalance (struct fdb *** nodeplaces_ptr, int count)
6298 -{
6299 -       if (!fdb_inited)
6300 -               fdb_init();
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) {
6309 -                       /*                                                      */
6310 -                       /*                            *                         */
6311 -                       /*                          /   \                       */
6312 -                       /*                       n+2      n                     */
6313 -                       /*                                                      */
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) {
6318 -                               /*                                                        */
6319 -                               /*                *                    n+2|n+3            */
6320 -                               /*              /   \                  /    \             */
6321 -                               /*           n+2      n      -->      /   n+1|n+2         */
6322 -                               /*           / \                      |    /    \         */
6323 -                               /*         n+1 n|n+1                 n+1  n|n+1  n        */
6324 -                               /*                                                        */
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;
6329 -                       } else {
6330 -                               /*                                                        */
6331 -                               /*                *                     n+2               */
6332 -                               /*              /   \                 /     \             */
6333 -                               /*           n+2      n      -->    n+1     n+1           */
6334 -                               /*           / \                    / \     / \           */
6335 -                               /*          n  n+1                 n   L   R   n          */
6336 -                               /*             / \                                        */
6337 -                               /*            L   R                                       */
6338 -                               /*                                                        */
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;
6346 -                       }
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;
6357 -                       } else {
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;
6365 -                       }
6366 -               } else {
6367 -                       int height = (heightleft<heightright ? heightright : heightleft) + 1;
6368 -                       if (height == node->fdb_avl_height)
6369 -                               break;
6370 -                       node->fdb_avl_height = height;
6371 -               }
6372 -       }
6373 -#ifdef DEBUG_AVL
6374 -       printk_avl(&fdb_head);
6375 -#endif /* DEBUG_AVL */
6376 -}
6377 -
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
6383 - */
6384 -struct fdb *br_avl_insert (struct fdb * new_node)
6385 -{
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] */
6390 -       if (!fdb_inited)
6391 -               fdb_init();
6392 -       for (;;) {
6393 -               struct fdb *node;
6394 -               
6395 -               node = *nodeplace;
6396 -               if (node == avl_br_empty)
6397 -                       break;
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) &&
6405 -                               node->port) {
6406 -                       /* update fdb but never for local interfaces */
6407 -#if (DEBUG_AVL)
6408 -                       printk("node 0x%x:port changed old=%d new=%d\n",
6409 -                               (unsigned int)node, node->port,new_node->port);
6410 -#endif
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.
6416 -                        */
6417 -                       requeue_fdb(node, new_node->port);
6418 -                       node->flags = new_node->flags;
6419 -                       node->timer = new_node->timer;  
6420 -#if (DEBUG_AVL)
6421 -                       printk_avl(&fdb_head);
6422 -#endif /* DEBUG_AVL */
6423 -                  }
6424 -                  return node;         /* pass old fdb to caller */
6425 -
6426 -               case 1: /* new_node->ula > node->ula */
6427 -                  nodeplace = &node->fdb_avl_right;
6428 -                  break;
6429 -               default: /* -1 => new_node->ula < node->ula */
6430 -                  nodeplace = &node->fdb_avl_left;
6431 -               }
6432 -       }
6433 -#if (DEBUG_AVL)
6434 -       printk("node 0x%x: adding ula %02x:%02x:%02x:%02x:%02x:%02x\n",
6435 -               (unsigned int)new_node,
6436 -               new_node->ula[0],
6437 -               new_node->ula[1],
6438 -               new_node->ula[2],
6439 -               new_node->ula[3],
6440 -               new_node->ula[4],
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);
6448 -#ifdef DEBUG_AVL
6449 -       printk_avl(&fdb_head);
6450 -#endif /* DEBUG_AVL */
6451 -       return NULL;            /* this is a new node */
6452 -}
6453 -
6454 -
6455 -/* Removes a node out of a tree. */
6456 -static int br_avl_remove (struct fdb * node_to_delete)
6457 -{
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;
6463 -       if (!fdb_inited)
6464 -               fdb_init();
6465 -       for (;;) {
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");
6470 -                       return(-1);
6471 -               }
6472 -               *stack_ptr++ = nodeplace; stack_count++;
6473 -               if (addr_cmp(node_to_delete->ula, node->ula) == 0)
6474 -                               break;
6475 -               if (addr_cmp(node_to_delete->ula, node->ula) < 0)
6476 -                       nodeplace = &node->fdb_avl_left;
6477 -               else
6478 -                       nodeplace = &node->fdb_avl_right;
6479 -       }
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--;
6485 -       } else {
6486 -               struct fdb *** stack_ptr_to_delete = stack_ptr;
6487 -               struct fdb ** nodeplace = &node_to_delete->fdb_avl_left;
6488 -               struct fdb * node;
6489 -               for (;;) {
6490 -                       node = *nodeplace;
6491 -                       if (node->fdb_avl_right == avl_br_empty)
6492 -                               break;
6493 -                       *stack_ptr++ = nodeplace; stack_count++;
6494 -                       nodeplace = &node->fdb_avl_right;
6495 -               }
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 */
6503 -       }
6504 -       br_avl_rebalance(stack_ptr,stack_count);
6505 -       return(0);
6506 -}
6507 -
6508 -#ifdef DEBUG_AVL
6509 -
6510 -/* print a tree */
6511 -static void printk_avl (struct fdb * tree)
6512 -{
6513 -       if (tree != avl_br_empty) {
6514 -               printk("(");
6515 -               printk("%02x:%02x:%02x:%02x:%02x:%02x(%d)",
6516 -                       tree->ula[0],
6517 -                       tree->ula[1],
6518 -                       tree->ula[2],
6519 -                       tree->ula[3],
6520 -                       tree->ula[4],
6521 -                       tree->ula[5],
6522 -                       tree->port);
6523 -               if (tree->fdb_avl_left != avl_br_empty) {
6524 -                       printk_avl(tree->fdb_avl_left);
6525 -                       printk("<");
6526 -               }
6527 -               if (tree->fdb_avl_right != avl_br_empty) {
6528 -                       printk(">");
6529 -                       printk_avl(tree->fdb_avl_right);
6530 -               }
6531 -               printk(")\n");
6532 -       }
6533 -}
6534 -
6535 -static char *avl_check_point = "somewhere";
6536 -
6537 -/* check a tree's consistency and balancing */
6538 -static void avl_checkheights (struct fdb * tree)
6539 -{
6540 -       int h, hl, hr;
6541 -
6542 -       if (tree == avl_br_empty)
6543 -               return;
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))
6550 -               return;
6551 -       if ((h == hr+1) && (hl <= hr) && (hr <= hl+1))
6552 -               return;
6553 -       printk("%s: avl_checkheights: heights inconsistent\n",avl_check_point);
6554 -}
6555 -
6556 -/* check that all values stored in a tree are < key */
6557 -static void avl_checkleft (struct fdb * tree, fdb_avl_key_t key)
6558 -{
6559 -       if (tree == avl_br_empty)
6560 -               return;
6561 -       avl_checkleft(tree->fdb_avl_left,key);
6562 -       avl_checkleft(tree->fdb_avl_right,key);
6563 -       if (tree->fdb_avl_key < key)
6564 -               return;
6565 -       printk("%s: avl_checkleft: left key %lu >= top key %lu\n",avl_check_point,tree->fdb_avl_key,key);
6566 -}
6567 -
6568 -/* check that all values stored in a tree are > key */
6569 -static void avl_checkright (struct fdb * tree, fdb_avl_key_t key)
6570 -{
6571 -       if (tree == avl_br_empty)
6572 -               return;
6573 -       avl_checkright(tree->fdb_avl_left,key);
6574 -       avl_checkright(tree->fdb_avl_right,key);
6575 -       if (tree->fdb_avl_key > key)
6576 -               return;
6577 -       printk("%s: avl_checkright: right key %lu <= top key %lu\n",avl_check_point,tree->fdb_avl_key,key);
6578 -}
6579 -
6580 -/* check that all values are properly increasing */
6581 -static void avl_checkorder (struct fdb * tree)
6582 -{
6583 -       if (tree == avl_br_empty)
6584 -               return;
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);
6589 -}
6590 -
6591 -#endif /* DEBUG_AVL */
6592 -
6593 -static int addr_cmp(unsigned char a1[], unsigned char a2[])
6594 -{
6595 -       int i;
6596 -
6597 -       for (i=0; i<6; i++) {
6598 -               if (a1[i] > a2[i]) return(1);
6599 -               if (a1[i] < a2[i]) return(-1);
6600 -       }
6601 -       return(0);
6602 -}
6603 -
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)
6607 -{
6608 -       int size;
6609 -
6610 -       if( 0 == *pos){
6611 -               if(avl_br_empty == tree)
6612 -               /* begin from the root */
6613 -                       tree = fhp;
6614 -               *pos = *len;
6615 -       }
6616 -
6617 -       if (*pos >= offset+length)
6618 -               return;
6619 -
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);
6628 -
6629 -                       (*pos)+=size;
6630 -                       (*len)+=size;
6631 -                       (*pbuffer)+=size;
6632 -               }
6633 -               if (*pos <= offset)
6634 -                       *len=0;
6635 -
6636 -               if (tree->fdb_avl_left != avl_br_empty) {
6637 -                       sprintf_avl (pbuffer,tree->fdb_avl_left,pos,len,offset,length);
6638 -               }
6639 -               if (tree->fdb_avl_right != avl_br_empty) {
6640 -                       sprintf_avl (pbuffer,tree->fdb_avl_right,pos,len,offset,length);
6641 -               }
6642 -
6643 -       }
6644 -
6645 -       return;
6646 -}
6647 -
6648 -/*
6649 - * Delete all nodes learnt by the port
6650 - */
6651 -void br_avl_delete_by_port(int port)
6652 -{
6653 -        struct fdb *fdb, *next;
6654 -
6655 -       if (!fdb_inited)
6656 -               fdb_init();
6657 -
6658 -        for(fdb = port_info[port].fdb; fdb != NULL; fdb = next) {
6659 -                next = fdb->fdb_next;
6660 -                br_avl_remove(fdb);
6661 -        }
6662 -        port_info[port].fdb = NULL;
6663 -
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);
6667 -        if (next != NULL)
6668 -                br_avl_remove(next);
6669 -
6670 -        return;
6671 -}
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
6675 @@ -1,13 +0,0 @@
6676 -/* -*- linux-c -*-
6677 - * sysctl_net_bridge.c: sysctl interface to net bridge subsystem.
6678 - *
6679 - * Begun June 1, 1996, Mike Shaver.
6680 - * Added /proc/sys/net/bridge directory entry (empty =) ). [MS]
6681 - */
6682 -
6683 -#include <linux/mm.h>
6684 -#include <linux/sysctl.h>
6685 -
6686 -ctl_table bridge_table[] = {
6687 -       {0}
6688 -};
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
6692 @@ -84,7 +84,7 @@
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 @@
6702         kfree_skb(skb);
6703  }
6704  
6705 -#ifdef CONFIG_BRIDGE
6706 -static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
6707 -{
6708 -       /* 
6709 -        * The br_stats.flags is checked here to save the expense of a 
6710 -        * function call.
6711 -        */
6712 -       if ((br_stats.flags & BR_UP) && br_call_bridge(skb, type))
6713 -       {
6714 -               /*
6715 -                *      We pass the bridge a complete frame. This means
6716 -                *      recovering the MAC header first.
6717 -                */
6718 -               
6719 -               int offset;
6720 -
6721 -               skb=skb_clone(skb, GFP_ATOMIC);
6722 -               if(skb==NULL)           
6723 -                       return;
6724 -                       
6725 -               offset=skb->data-skb->mac.raw;
6726 -               skb_push(skb,offset);   /* Put header back on for bridge */
6727 -
6728 -               if(br_receive_frame(skb))
6729 -                       return;
6730 -               kfree_skb(skb);
6731 -       }
6732 -       return;
6733 -}
6734 +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
6735 +void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL;
6736  #endif
6737  
6738  
6739 @@ -955,11 +928,6 @@
6740                         continue;
6741                 }
6742  
6743 -               /*
6744 -                *      Fetch the packet protocol ID. 
6745 -                */
6746 -
6747 -               type = skb->protocol;
6748  
6749  #ifdef CONFIG_NET_DIVERT
6750                 /*
6751 @@ -970,15 +938,6 @@
6752  #endif /* CONFIG_NET_DIVERT */
6753                 
6754  
6755 -#ifdef CONFIG_BRIDGE
6756 -               /*
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
6760 -                */
6761 -               handle_bridge(skb, type); 
6762 -#endif
6763 -
6764                 /*
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 @@
6768                  */
6769  
6770                 pt_prev = NULL;
6771 -               for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next)
6772 +               for (ptype = ptype_all; ptype != NULL; ptype = ptype->next)
6773                 {
6774                         if (!ptype->dev || ptype->dev == skb->dev) {
6775 -                               if(pt_prev)
6776 +                               if (pt_prev)
6777                                 {
6778 -                                       struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
6779 -                                       if(skb2)
6780 -                                               pt_prev->func(skb2,skb->dev, pt_prev);
6781 +                                       struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
6782 +                                       if (skb2)
6783 +                                               pt_prev->func(skb2, skb->dev, pt_prev);
6784                                 }
6785 -                               pt_prev=ptype;
6786 +                               pt_prev = ptype;
6787                         }
6788                 }
6789  
6790 +               /*
6791 +                *      Is there a last item to send to ?
6792 +                */
6793 +
6794 +               if (pt_prev)
6795 +               {
6796 +                       struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
6797 +                       if (skb2)
6798 +                               pt_prev->func(skb2, skb->dev, pt_prev);
6799 +                       pt_prev = NULL;
6800 +               }
6801 +
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);
6805 +                       continue;
6806 +               }
6807 +#endif
6808 +
6809 +               /*
6810 +                *      Fetch the packet protocol ID. 
6811 +                */
6812 +
6813 +               type = skb->protocol;
6814 +
6815                 for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) 
6816                 {
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
6821                                  */
6822 -                               if(pt_prev)
6823 +
6824 +                               if (pt_prev)
6825                                 {
6826                                         struct sk_buff *skb2;
6827  
6828 @@ -1032,13 +1017,14 @@
6829  
6830                 if(pt_prev)
6831                         pt_prev->func(skb, skb->dev, pt_prev);
6832 +
6833                 /*
6834                  *      Has an unknown packet has been received ?
6835                  */
6836          
6837 -               else {
6838 +               else
6839                         kfree_skb(skb);
6840 -               }
6841 +
6842         }       /* End of queue loop */
6843         
6844         /*
6845 @@ -1963,12 +1949,11 @@
6846         skb_queue_head_init(&backlog);
6847         
6848         /*
6849 -        *      The bridge has to be up before the devices
6850 +        * Initialize the ethernet bridge.
6851          */
6852 -
6853 -#ifdef CONFIG_BRIDGE    
6854 +#ifdef CONFIG_BRIDGE
6855         br_init();
6856 -#endif 
6857 +#endif
6858  
6859         /*
6860          * Frame Diverter init
6861 @@ -2083,13 +2068,6 @@
6862  
6863         dev_mcast_init();
6864  
6865 -#ifdef CONFIG_BRIDGE
6866 -       /*
6867 -        * Register any statically linked ethernet devices with the bridge
6868 -        */
6869 -       br_spacedevice_register();
6870 -#endif
6871 -
6872  #ifdef CONFIG_N2
6873         n2_init();
6874  #endif
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
6878 @@ -184,7 +184,6 @@
6879  
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;
6884         skb->list = NULL;
6885         skb->sk = 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>
6892  #endif
6893 -#ifdef CONFIG_BRIDGE
6894 -#include <net/br.h>
6895 -#endif
6896
6897 +#include <linux/if_bridge.h>
6898 +
6899  #ifdef CONFIG_NET_DIVERT
6900  #include <linux/divert.h>
6901  #endif /* CONFIG_NET_DIVERT */
6902 @@ -139,6 +137,7 @@
6903  int (*dlci_ioctl_hook)(unsigned int, void *) = NULL;
6904  #endif
6905  
6906 +int (*br_ioctl_hook)(unsigned long) = NULL;
6907  int (*rarp_ioctl_hook)(unsigned int,void*) = NULL;
6908  
6909  /*
6910 @@ -913,11 +912,15 @@
6911                         return(devinet_ioctl(cmd,(void *) arg));
6912                 case SIOCGIFBR:
6913                 case SIOCSIFBR:
6914 -#ifdef CONFIG_BRIDGE           
6915 -                       return(br_ioctl(cmd,(void *) arg));
6916 -#else
6917 +#ifdef CONFIG_KMOD
6918 +                       if (br_ioctl_hook == NULL)
6919 +                               request_module("bridge");
6920 +#endif
6921 +
6922 +                       if (br_ioctl_hook != NULL)
6923 +                               return br_ioctl_hook(arg);
6924 +
6925                         return -ENOPKG;
6926 -#endif                                         
6927                         
6928                 case SIOCGIFDIVERT:
6929                 case SIOCSIFDIVERT:
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
6933 @@ -28,10 +28,7 @@
6934  #endif
6935  #include <net/pkt_sched.h>
6936  #include <net/scm.h>
6937 -
6938 -#ifdef CONFIG_BRIDGE
6939 -#include <net/br.h>
6940 -#endif
6941 +#include <linux/if_bridge.h>
6942  
6943  #ifdef CONFIG_NET_DIVERT
6944  #include <linux/divert.h>
6945 @@ -225,9 +222,10 @@
6946  
6947  EXPORT_SYMBOL(scm_detach_fds);
6948  
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);
6953  #endif
6954 +EXPORT_SYMBOL(br_ioctl_hook);
6955  
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
6961 @@ -63,14 +63,12 @@
6962  #include <asm/uaccess.h>
6963  #include <linux/module.h>
6964  #include <linux/init.h>
6965 +#include <linux/if_bridge.h>
6966  
6967  #ifdef CONFIG_INET
6968  #include <net/inet_common.h>
6969  #endif
6970  
6971 -#ifdef CONFIG_BRIDGE
6972 -#include <net/br.h>
6973 -#endif
6974  
6975  #ifdef CONFIG_NET_DIVERT
6976  #include <linux/divert.h>
6977 @@ -1131,11 +1129,15 @@
6978  
6979                 case SIOCGIFBR:
6980                 case SIOCSIFBR:
6981 -#ifdef CONFIG_BRIDGE           
6982 -                       return(br_ioctl(cmd,(void *) arg));
6983 -#else
6984 +#ifdef CONFIG_KMOD
6985 +                       if (br_ioctl_hook == NULL)
6986 +                               request_module("bridge");
6987 +#endif
6988 +
6989 +                       if (br_ioctl_hook != NULL)
6990 +                               return br_ioctl_hook(arg);
6991 +
6992                         return -ENOPKG;
6993 -#endif                                         
6994                         
6995                 case SIOCGIFDIVERT:
6996                 case SIOCSIFDIVERT:
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
7000 @@ -34,10 +34,6 @@
7001  extern ctl_table ether_table[], e802_table[];
7002  #endif
7003  
7004 -#ifdef CONFIG_BRIDGE
7005 -extern ctl_table bridge_table[];
7006 -#endif
7007 -
7008  #ifdef CONFIG_IPV6
7009  extern ctl_table ipv6_table[];
7010  #endif
7011 @@ -61,9 +57,6 @@
7012  #ifdef CONFIG_IPX
7013          {NET_IPX,    "ipx",       NULL, 0, 0555, ipx_table},
7014  #endif
7015 -#ifdef CONFIG_BRIDGE
7016 -        {NET_BRIDGE, "bridge",    NULL, 0, 0555, bridge_table},
7017 -#endif
7018  #ifdef CONFIG_IPV6
7019         {NET_IPV6, "ipv6", NULL, 0, 0555, ipv6_table},
7020  #endif
This page took 0.733048 seconds and 3 git commands to generate.