]> git.pld-linux.org Git - packages/kernel.git/blame - bridge-1.0.1-against-2.2.20.diff
- removed all Group fields translations (oure rpm now can handle translating
[packages/kernel.git] / bridge-1.0.1-against-2.2.20.diff
CommitLineData
95859684
KT
1diff -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 Sat Nov 10 21:44:20 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
18diff -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 Sat Nov 10 21:44:20 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
57diff -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 Sat Nov 10 21:44:20 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>
72diff -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 Sat Nov 10 21:44:20 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
95859684
KT
89diff -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 Sat Nov 10 21:44:20 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
203diff -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 Sat Nov 10 21:44:20 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??
226diff -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 Sat Nov 10 21:44:20 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 */
237diff -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-
572diff -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 Sat Nov 10 21:44:20 2001
575@@ -31,6 +31,7 @@
576 source net/ipx/Config.in
577 fi
578 tristate 'Appletalk DDP' CONFIG_ATALK
579+tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE
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
594diff -urN linux-2.2.20/net/README linux-2.2.20br/net/README
595--- linux-2.2.20/net/README Sun Mar 25 18:31:11 2001
596+++ linux-2.2.20br/net/README Sat Nov 10 21:44:20 2001
597@@ -7,6 +7,7 @@
598 [token ring ] p.norton@computer.org
599 appletalk Jay.Schulist@spacs.k12.wi.us
600 ax25 g4klx@g4klx.demon.co.uk
601+bridge buytenh@gnu.org
602 core alan@lxorguk.ukuu.org.uk
603 decnet SteveW@ACM.org
604 ethernet alan@lxorguk.ukuu.org.uk
605diff -urN linux-2.2.20/net/bridge/Makefile linux-2.2.20br/net/bridge/Makefile
606--- linux-2.2.20/net/bridge/Makefile Sun Mar 25 18:31:13 2001
607+++ linux-2.2.20br/net/bridge/Makefile Sat Nov 10 21:44:20 2001
608@@ -1,5 +1,5 @@
609 #
610-# Makefile for the Linux Bridge layer.
611+# Makefile for the IEEE 802.1d ethernet bridging layer.
612 #
613 # Note! Dependencies are done automagically by 'make dep', which also
614 # removes any old dependencies. DON'T put your own dependencies here
615@@ -7,15 +7,10 @@
616 #
617 # Note 2! The CFLAGS definition is now in the main makefile...
618
619-O_TARGET := bridge.o
620-O_OBJS := br.o br_tree.o
621-M_OBJS := $(O_TARGET)
622-
623-ifeq ($(CONFIG_SYSCTL),y)
624-O_OBJS += sysctl_net_bridge.o
625-endif
626+O_TARGET := bridge.o
627+O_OBJS := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
628+ br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \
629+ br_stp_if.o br_stp_timer.o
630+M_OBJS := $(O_TARGET)
631
632 include $(TOPDIR)/Rules.make
633-
634-tar:
635- tar -cvf /dev/f1 .
636diff -urN linux-2.2.20/net/bridge/br.c linux-2.2.20br/net/bridge/br.c
637--- linux-2.2.20/net/bridge/br.c Sun Mar 25 18:31:13 2001
638+++ linux-2.2.20br/net/bridge/br.c Sat Nov 10 21:44:20 2001
639@@ -1,2775 +1,67 @@
640 /*
641- * Linux NET3 Bridge Support
642+ * Generic parts
643+ * Linux ethernet bridge
644 *
645- * Originally by John Hayes (Network Plumbing).
646- * Minor hacks to get it to run with 1.3.x by Alan Cox <Alan.Cox@linux.org>
647- * More hacks to be able to switch protocols on and off by Christoph Lameter
648- * <clameter@debian.org>
649- * Software and more Documentation for the bridge is available from ftp.debian.org
650- * in the bridgex package
651+ * Authors:
652+ * Lennert Buytenhek <buytenh@gnu.org>
653+ *
654+ * $Id$
655 *
656 * This program is free software; you can redistribute it and/or
657 * modify it under the terms of the GNU General Public License
658 * as published by the Free Software Foundation; either version
659 * 2 of the License, or (at your option) any later version.
660- *
661- * Fixes:
662- * Yury Shevchuk : Bridge with non bridging ports
663- * Jean-Rene Peulve: jr.peulve@aix.pacwan.net Jan/Feb 98
664- * support Linux 2.0
665- * Handle Receive config bpdu
666- * kick mark_bh to send Spanning Tree pdus
667- * bridgeId comparison using htonl()
668- * make STP interoperable with other vendors
669- * wrong test in root_selection()
670- * add more STP debug info
671- * some performance improvments
672- * do not clear bridgeId.mac while setting priority
673- * do not reset port priority when starting bridge
674- * make port priority from user value and port number
675- * maintains user port state out of device state
676- * broacast/multicast storm limitation
677- * forwarding statistics
678- * stop br_tick when bridge is turn off
679- * add local MACs in avl_tree to forward up stack
680- * fake receive on right port for IP/ARP
681- * ages tree even if packet does not cross bridge
682- * add BRCMD_DISPLAY_FDB (ioctl for now)
683- *
684- * Alan Cox: Merged Jean-Rene's stuff, reformatted stuff a bit
685- * so blame me first if its broken ;)
686- *
687- * Robert Pintarelli: fixed bug in bpdu time values
688- *
689- * Matthew Grant: start ports disabled.
690- * auto-promiscuous mode on port enable/disable
691- * fleshed out interface event handling, interfaces
692- * now register with bridge on module load as well as ifup
693- * port control ioctls with ifindex support
694- * brg0 logical ethernet interface
695- * reworked brcfg to take interface arguments
696- * added support for changing the hardware address
697- * generally made bridge a lot more usable.
698- *
699- * Todo:
700- * Use a netlink notifier so a daemon can maintain the bridge
701- * port group (could we also do multiple groups ????).
702- * A nice /proc file interface.
703- * Put the path costs in the port info and devices.
704- * Put the bridge port number in the device structure for speed.
705- * Bridge SNMP stats.
706- *
707 */
708-
709-#include <linux/config.h>
710-#include <linux/module.h>
711-#include <linux/errno.h>
712-#include <linux/types.h>
713-#include <linux/socket.h>
714-#include <linux/in.h>
715
716+#include <linux/module.h>
717 #include <linux/kernel.h>
718-#include <linux/sched.h>
719-#include <linux/timer.h>
720-#include <linux/malloc.h>
721-#include <linux/string.h>
722-#include <linux/net.h>
723-#include <linux/inet.h>
724+#include <linux/miscdevice.h>
725 #include <linux/netdevice.h>
726-#include <linux/inetdevice.h>
727 #include <linux/etherdevice.h>
728-#include <linux/skbuff.h>
729-#include <linux/if_arp.h>
730-#include <linux/ip.h>
731-#include <linux/version.h>
732 #include <linux/init.h>
733+#include <linux/if_bridge.h>
734 #include <asm/uaccess.h>
735-#include <asm/system.h>
736-#include <linux/rtnetlink.h>
737-#include <net/br.h>
738-#include <linux/proc_fs.h>
739-#include <linux/delay.h>
740-
741-#ifndef min
742-#define min(a, b) (((a) <= (b)) ? (a) : (b))
743-#endif
744-
745-static void transmit_config(int port_no);
746-static int root_bridge(void);
747-static int supersedes_port_info(int port_no, Config_bpdu *config);
748-static void record_config_information(int port_no, Config_bpdu *config);
749-static void record_config_timeout_values(Config_bpdu *config);
750-static void config_bpdu_generation(void);
751-static int designated_port(int port_no);
752-static void reply(int port_no);
753-static void transmit_tcn(void);
754-static void configuration_update(void);
755-static void root_selection(void);
756-static void designated_port_selection(void);
757-static void become_designated_port(int port_no);
758-static void port_state_selection(void);
759-static void make_forwarding(int port_no);
760-static void topology_change_detection(void);
761-static void topology_change_acknowledged(void);
762-static void acknowledge_topology_change(int port_no);
763-static void make_blocking(int port_no);
764-static void set_port_state(int port_no, int state);
765-static void received_config_bpdu(int port_no, Config_bpdu *config);
766-static void received_tcn_bpdu(int port_no, Tcn_bpdu *tcn);
767-static void hello_timer_expiry(void);
768-static void message_age_timer_expiry(int port_no);
769-static void forward_delay_timer_expiry(int port_no);
770-static int designated_for_some_port(void);
771-static void tcn_timer_expiry(void);
772-static void topology_change_timer_expiry(void);
773-static void hold_timer_expiry(int port_no);
774-static void br_init_port(int port_no);
775-static void enable_port(int port_no);
776-static void disable_port(int port_no);
777-static void set_bridge_priority(bridge_id_t *new_bridge_id);
778-static void set_port_priority(int port_no);
779-static void set_path_cost(int port_no, unsigned short path_cost);
780-static void start_hello_timer(void);
781-static void stop_hello_timer(void);
782-static int hello_timer_expired(void);
783-static void start_tcn_timer(void);
784-static void stop_tcn_timer(void);
785-static int tcn_timer_expired(void);
786-static void start_topology_change_timer(void);
787-static void stop_topology_change_timer(void);
788-static int topology_change_timer_expired(void);
789-static void start_message_age_timer(int port_no, unsigned short message_age);
790-static void stop_message_age_timer(int port_no);
791-static int message_age_timer_expired(int port_no);
792-static void start_forward_delay_timer(int port_no);
793-static void stop_forward_delay_timer(int port_no);
794-static int forward_delay_timer_expired(int port_no);
795-static void start_hold_timer(int port_no);
796-static void stop_hold_timer(int port_no);
797-static int hold_timer_expired(int port_no);
798-static int br_device_event(struct notifier_block *dnot, unsigned long event, void *ptr);
799-static void br_tick(unsigned long arg);
800-static int br_forward(struct sk_buff *skb, int port); /* 3.7 */
801-static int br_port_cost(struct device *dev); /* 4.10.2 */
802-static void br_bpdu(struct sk_buff *skb, int port); /* consumes skb */
803-static int br_cmp(unsigned int *a, unsigned int *b);
804-static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu);
805-static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu);
806-static int find_port(struct device *dev);
807-static void br_add_local_mac(unsigned char *mac);
808-static int br_flood(struct sk_buff *skb, int port);
809-static int br_drop(struct sk_buff *skb);
810-static int br_learn(struct sk_buff *skb, int port); /* 3.8 */
811-static int br_protocol_ok(unsigned short protocol);
812-static int br_find_port(int ifindex);
813-static void br_get_ifnames(void);
814-static int brg_rx(struct sk_buff *skb, int port);
815-
816-static unsigned char bridge_ula[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
817-static Bridge_data bridge_info; /* (4.5.3) */
818-Port_data port_info[All_ports]; /* (4.5.5) */
819-
820-/* MAG: Maximum port registered - used to speed up flooding and to make
821- * have a large ports array more efficient
822- */
823-static int max_port_used = 0;
824-
825-/* JRP: fdb cache 1/port save kmalloc/kfree on every frame */
826-struct fdb *newfdb[All_ports];
827-int allocated_fdb_cnt = 0;
828-
829-/* broacast/multicast storm limitation */
830-int max_mcast_per_period = MAX_MCAST_PER_PERIOD;
831-int mcast_hold_time = MCAST_HOLD_TIME;
832-
833-/* JRP: next two bpdu are copied to skbuff so we need only 1 of each */
834-static Config_bpdu config_bpdu;
835-static Tcn_bpdu tcn_bpdu;
836-static unsigned char port_priority[All_ports];
837-static unsigned char user_port_state[All_ports];
838-
839-static Timer hello_timer; /* (4.5.4.1) */
840-static Timer tcn_timer; /* (4.5.4.2) */
841-static Timer topology_change_timer; /* (4.5.4.3) */
842-static Timer message_age_timer[All_ports]; /* (4.5.6.1) */
843-static Timer forward_delay_timer[All_ports]; /* (4.5.6.2) */
844-static Timer hold_timer[All_ports]; /* (4.5.6.3) */
845-
846-/* entries timeout after this many seconds */
847-unsigned int fdb_aging_time = FDB_TIMEOUT;
848-
849-struct br_stat br_stats;
850-#define br_stats_cnt br_stats.packet_cnts
851-
852-static struct timer_list tl; /* for 1 second timer... */
853-
854-/*
855- * the following structure is required so that we receive
856- * event notifications when network devices are enabled and
857- * disabled (ifconfig up and down).
858- */
859-static struct notifier_block br_dev_notifier={
860- br_device_event,
861- NULL,
862- 0
863-};
864-
865-
866-/*
867- * the following data is for the bridge network device
868- */
869-struct brg_if {
870- struct device dev;
871- char name[IFNAMSIZ];
872-};
873-static struct brg_if brg_if;
874-
875-/*
876- * Here to save linkage? problems
877- */
878-
879-static inline int find_port(struct device *dev)
880-{
881- int i;
882-
883- for (i = One; i <= No_of_ports; i++)
884- if (port_info[i].dev == dev)
885- return(i);
886- return(0);
887-}
888-
889-/*
890- * Implementation of Protocol specific bridging
891- *
892- * The protocols to be bridged or not to be bridged are stored in a hashed array. This is the old type
893- * of unlinked hash array where one simply takes the next cell if the one the hash function points to
894- * is occupied.
895- */
896-
897-#define BR_PROTOCOL_HASH(x) (x % BR_MAX_PROTOCOLS)
898-
899-/* Checks if that protocol type is to be bridged */
900-
901-static int inline br_protocol_ok(unsigned short protocol)
902-{
903- unsigned x;
904-
905- /* See if protocol statistics are to be kept */
906- if (br_stats.flags & BR_PROT_STATS)
907- {
908- for(x=0;x<BR_MAX_PROT_STATS && br_stats.prot_id[x]!=protocol && br_stats.prot_id[x];x++);
909- if (x<BR_MAX_PROT_STATS)
910- {
911- br_stats.prot_id[x]=protocol;br_stats.prot_counter[x]++;
912- }
913- }
914-
915- for (x=BR_PROTOCOL_HASH(protocol); br_stats.protocols[x]!=0;)
916- {
917- if (br_stats.protocols[x]==protocol)
918- return !br_stats.policy;
919- x++;
920- if (x==BR_MAX_PROTOCOLS)
921- x=0;
922- }
923- return br_stats.policy;
924-}
925-
926-/* Add a protocol to be handled opposite to the standard policy of the bridge */
927-
928-static int br_add_exempt_protocol(unsigned short p)
929-{
930- unsigned x;
931- if (p == 0) return -EINVAL;
932- if (br_stats.exempt_protocols > BR_MAX_PROTOCOLS-2) return -EXFULL;
933- for (x=BR_PROTOCOL_HASH(p);br_stats.protocols[x]!=0;) {
934- if (br_stats.protocols[x]==p) return 0; /* Attempt to add the protocol a second time */
935- x++;
936- if (x==BR_MAX_PROTOCOLS) x=0;
937- }
938- br_stats.protocols[x]=p;
939- br_stats.exempt_protocols++;
940- return 0;
941-}
942-
943-/* Valid Policies are 0=No Protocols bridged 1=Bridge all protocols */
944-static int br_set_policy(int policy)
945-{
946- if (policy>1) return -EINVAL;
947- br_stats.policy=policy;
948- /* Policy change means initializing the exempt table */
949- memset(br_stats.protocols,0,sizeof(br_stats.protocols));
950- br_stats.exempt_protocols = 0;
951- return 0;
952-}
953-
954-
955-/** Elements of Procedure (4.6) **/
956-
957-/*
958- * this section of code was graciously borrowed from the IEEE 802.1d
959- * specification section 4.9.1 starting on pg 69. It has been
960- * modified somewhat to fit within our framework and structure. It
961- * implements the spanning tree algorithm that is the heart of the
962- * 802.1d bridging protocol.
963- */
964-
965-static void transmit_config(int port_no) /* (4.6.1) */
966-{
967- if (hold_timer[port_no].active) { /* (4.6.1.3.1) */
968- port_info[port_no].config_pending = TRUE; /* (4.6.1.3.1) */
969- } else { /* (4.6.1.3.2) */
970- config_bpdu.type = BPDU_TYPE_CONFIG;
971- config_bpdu.root_id = bridge_info.designated_root;
972- /* (4.6.1.3.2(1)) */
973- config_bpdu.root_path_cost = bridge_info.root_path_cost;
974- /* (4.6.1.3.2(2)) */
975- config_bpdu.bridge_id = bridge_info.bridge_id;
976- /* (4.6.1.3.2(3)) */
977- config_bpdu.port_id = port_info[port_no].port_id;
978- /*
979- * (4.6.1.3.2(4))
980- */
981- if (root_bridge()) {
982- config_bpdu.message_age = Zero; /* (4.6.1.3.2(5)) */
983- } else {
984- config_bpdu.message_age
985- = (message_age_timer[bridge_info.root_port].value
986- + Message_age_increment) << 8; /* (4.6.1.3.2(6)) */
987- }
988-
989- config_bpdu.max_age = bridge_info.max_age << 8;/* (4.6.1.3.2(7)) */
990- config_bpdu.hello_time = bridge_info.hello_time << 8;
991- config_bpdu.forward_delay = bridge_info.forward_delay << 8;
992- config_bpdu.top_change_ack =
993- port_info[port_no].top_change_ack;
994- /* (4.6.1.3.2(8)) */
995- port_info[port_no].top_change_ack = 0;
996-
997- config_bpdu.top_change =
998- bridge_info.top_change; /* (4.6.1.3.2(9)) */
999-
1000- send_config_bpdu(port_no, &config_bpdu);
1001- port_info[port_no].config_pending = FALSE; /* (4.6.1.3.2(10)) */
1002- start_hold_timer(port_no); /* (4.6.1.3.2(11)) */
1003- }
1004-/* JRP: we want the frame to be xmitted even if no other traffic.
1005- * net_bh() will do a dev_transmit() that kicks all devices
1006- */
1007- mark_bh(NET_BH);
1008-}
1009+#include "br_private.h"
1010
1011-static int root_bridge(void)
1012+void br_dec_use_count()
1013 {
1014- return (br_cmp(bridge_info.designated_root.BRIDGE_ID,
1015- bridge_info.bridge_id.BRIDGE_ID)?FALSE:TRUE);
1016+ MOD_DEC_USE_COUNT;
1017 }
1018
1019-static int supersedes_port_info(int port_no, Config_bpdu *config) /* (4.6.2.2) */
1020+void br_inc_use_count()
1021 {
1022- return (
1023- (br_cmp(config->root_id.BRIDGE_ID,
1024- port_info[port_no].designated_root.BRIDGE_ID) < 0) /* (4.6.2.2.1) */
1025- ||
1026- ((br_cmp(config->root_id.BRIDGE_ID,
1027- port_info[port_no].designated_root.BRIDGE_ID) == 0
1028- )
1029- &&
1030- ((config->root_path_cost
1031- < port_info[port_no].designated_cost /* (4.6.2.2.2) */
1032- )
1033- ||
1034- ((config->root_path_cost
1035- == port_info[port_no].designated_cost
1036- )
1037- &&
1038- ((br_cmp(config->bridge_id.BRIDGE_ID,
1039- port_info[port_no].designated_bridge.BRIDGE_ID) < 0 /* (4.6.2.2.3) */
1040- )
1041- ||
1042- ((br_cmp(config->bridge_id.BRIDGE_ID,
1043- port_info[port_no].designated_bridge.BRIDGE_ID) == 0
1044- ) /* (4.6.2.2.4) */
1045- &&
1046- ((br_cmp(config->bridge_id.BRIDGE_ID,
1047- bridge_info.bridge_id.BRIDGE_ID) != 0
1048- ) /* (4.6.2.2.4(1)) */
1049- ||
1050- (config->port_id <=
1051- port_info[port_no].designated_port
1052- ) /* (4.6.2.2.4(2)) */
1053- ))))))
1054- );
1055+ MOD_INC_USE_COUNT;
1056 }
1057
1058-static void record_config_information(int port_no, Config_bpdu *config) /* (4.6.2) */
1059+__initfunc(int br_init(void))
1060 {
1061- port_info[port_no].designated_root = config->root_id; /* (4.6.2.3.1) */
1062- port_info[port_no].designated_cost = config->root_path_cost;
1063- port_info[port_no].designated_bridge = config->bridge_id;
1064- port_info[port_no].designated_port = config->port_id;
1065- start_message_age_timer(port_no, config->message_age); /* (4.6.2.3.2) */
1066-}
1067-
1068-static void record_config_timeout_values(Config_bpdu *config) /* (4.6.3) */
1069-{
1070- bridge_info.max_age = config->max_age >> 8; /* (4.6.3.3) */
1071- bridge_info.hello_time = config->hello_time >> 8;
1072- bridge_info.forward_delay = config->forward_delay >> 8;
1073- bridge_info.top_change = config->top_change >> 8;
1074-}
1075-
1076-static void config_bpdu_generation(void)
1077-{ /* (4.6.4) */
1078- int port_no;
1079- for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.6.4.3) */
1080- if (designated_port(port_no) /* (4.6.4.3) */
1081- &&
1082- (port_info[port_no].state != Disabled)
1083- ) {
1084- transmit_config(port_no); /* (4.6.4.3) */
1085- } /* (4.6.1.2) */
1086- }
1087-}
1088-
1089-static int designated_port(int port_no)
1090-{
1091- return ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1092- bridge_info.bridge_id.BRIDGE_ID) == 0
1093- )
1094- &&
1095- (port_info[port_no].designated_port
1096- == port_info[port_no].port_id
1097- )
1098- );
1099-}
1100-
1101-static void reply(int port_no) /* (4.6.5) */
1102-{
1103- transmit_config(port_no); /* (4.6.5.3) */
1104-}
1105-
1106-static void transmit_tcn(void)
1107-{ /* (4.6.6) */
1108- int port_no;
1109-
1110- port_no = bridge_info.root_port;
1111- tcn_bpdu.type = BPDU_TYPE_TOPO_CHANGE;
1112- send_tcn_bpdu(port_no, &tcn_bpdu); /* (4.6.6.3) */
1113-}
1114-
1115-static void configuration_update(void) /* (4.6.7) */
1116-{
1117- root_selection(); /* (4.6.7.3.1) */
1118- /* (4.6.8.2) */
1119- designated_port_selection(); /* (4.6.7.3.2) */
1120- /* (4.6.9.2) */
1121-}
1122-
1123-static void root_selection(void)
1124-{ /* (4.6.8) */
1125- int root_port;
1126- int port_no;
1127- root_port = No_port;
1128- for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.6.8.3.1) */
1129- if (((!designated_port(port_no))
1130- &&
1131- (port_info[port_no].state != Disabled)
1132- &&
1133- (br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1134- bridge_info.bridge_id.BRIDGE_ID) < 0)
1135- )
1136- &&
1137- ((root_port == No_port)
1138- ||
1139- (br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1140- port_info[root_port].designated_root.BRIDGE_ID) < 0
1141- )
1142- ||
1143- ((br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1144- port_info[root_port].designated_root.BRIDGE_ID) == 0
1145- )
1146- &&
1147- (((port_info[port_no].designated_cost
1148- + port_info[port_no].path_cost
1149- )
1150- <
1151- (port_info[root_port].designated_cost
1152- + port_info[root_port].path_cost
1153- ) /* (4.6.8.3.1(2)) */
1154- )
1155- ||
1156- (((port_info[port_no].designated_cost
1157- + port_info[port_no].path_cost
1158- )
1159- ==
1160- (port_info[root_port].designated_cost
1161- + port_info[root_port].path_cost
1162- )
1163- )
1164- &&
1165- ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1166- port_info[root_port].designated_bridge.BRIDGE_ID) < 0
1167- ) /* (4.6.8.3.1(3)) */
1168- ||
1169- ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1170- port_info[root_port].designated_bridge.BRIDGE_ID) == 0
1171- )
1172- &&
1173- ((port_info[port_no].designated_port
1174- < port_info[root_port].designated_port
1175- ) /* (4.6.8.3.1(4)) */
1176- ||
1177- ((port_info[port_no].designated_port
1178-/* JRP: was missing an "=" ! */ == port_info[root_port].designated_port
1179- )
1180- &&
1181- (port_info[port_no].port_id
1182- < port_info[root_port].port_id
1183- ) /* (4.6.8.3.1(5)) */
1184- ))))))))) {
1185- root_port = port_no;
1186- }
1187- }
1188- bridge_info.root_port = root_port; /* (4.6.8.3.1) */
1189-
1190- if (root_port == No_port) { /* (4.6.8.3.2) */
1191-#ifdef DEBUG_STP
1192- if (br_stats.flags & BR_DEBUG)
1193- printk(KERN_DEBUG "root_selection: becomes root\n");
1194-#endif
1195- bridge_info.designated_root = bridge_info.bridge_id;
1196- /* (4.6.8.3.2(1)) */
1197- bridge_info.root_path_cost = Zero;/* (4.6.8.3.2(2)) */
1198- } else { /* (4.6.8.3.3) */
1199- bridge_info.designated_root = port_info[root_port].designated_root;
1200- /* (4.6.8.3.3(1)) */
1201- bridge_info.root_path_cost = (port_info[root_port].designated_cost
1202- + port_info[root_port].path_cost
1203- ); /* (4.6.8.3.3(2)) */
1204- }
1205-}
1206-
1207-static void designated_port_selection(void)
1208-{ /* (4.6.9) */
1209- int port_no;
1210-
1211- for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.6.9.3) */
1212- if(port_info[port_no].state == Disabled)
1213- continue;
1214- if (designated_port(port_no) /* (4.6.9.3.1) */
1215- ||
1216- (
1217- br_cmp(port_info[port_no].designated_root.BRIDGE_ID,
1218- bridge_info.designated_root.BRIDGE_ID) != 0
1219- )
1220- ||
1221- (bridge_info.root_path_cost
1222- < port_info[port_no].designated_cost
1223- ) /* (4.6.9.3.3) */
1224- ||
1225- ((bridge_info.root_path_cost
1226- == port_info[port_no].designated_cost
1227- )
1228- &&
1229- ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
1230- port_info[port_no].designated_bridge.BRIDGE_ID) < 0
1231- ) /* (4.6.9.3.4) */
1232- ||
1233- ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
1234- port_info[port_no].designated_bridge.BRIDGE_ID) == 0
1235- )
1236- &&
1237- (port_info[port_no].port_id
1238- <= port_info[port_no].designated_port
1239- ) /* (4.6.9.3.5) */
1240- )))) {
1241- become_designated_port(port_no); /* (4.6.10.3.2.2) */
1242- }
1243- }
1244-}
1245-
1246-static void become_designated_port(int port_no)
1247-{ /* (4.6.10) */
1248-
1249- /* (4.6.10.3.1) */
1250- port_info[port_no].designated_root = bridge_info.designated_root;
1251- /* (4.6.10.3.2) */
1252- port_info[port_no].designated_cost = bridge_info.root_path_cost;
1253- /* (4.6.10.3.3) */
1254- port_info[port_no].designated_bridge = bridge_info.bridge_id;
1255- /* (4.6.10.3.4) */
1256- port_info[port_no].designated_port = port_info[port_no].port_id;
1257-}
1258+ printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n");
1259
1260-static void port_state_selection(void)
1261-{ /* (4.6.11) */
1262- int port_no;
1263- char *state_str;
1264- for (port_no = One; port_no <= No_of_ports; port_no++) {
1265-
1266- if(port_info[port_no].state == Disabled)
1267- continue;
1268- if (port_no == bridge_info.root_port) { /* (4.6.11.3.1) */
1269- state_str = "root";
1270- port_info[port_no].config_pending = FALSE; /* (4.6.11.3.1(1)) */
1271- port_info[port_no].top_change_ack = 0;
1272- make_forwarding(port_no); /* (4.6.11.3.1(2)) */
1273- } else if (designated_port(port_no)) { /* (4.6.11.3.2) */
1274- state_str = "designated";
1275- stop_message_age_timer(port_no); /* (4.6.11.3.2(1)) */
1276- make_forwarding(port_no); /* (4.6.11.3.2(2)) */
1277- } else { /* (4.6.11.3.3) */
1278- state_str = "blocking";
1279- port_info[port_no].config_pending = FALSE; /* (4.6.11.3.3(1)) */
1280- port_info[port_no].top_change_ack = 0;
1281- make_blocking(port_no); /* (4.6.11.3.3(2)) */
1282- }
1283-#ifdef DEBUG_STP
1284- if (br_stats.flags & BR_DEBUG)
1285- printk(KERN_DEBUG "port_state_selection: becomes %s port %d\n",
1286- state_str, port_no);
1287+ br_handle_frame_hook = br_handle_frame;
1288+#ifdef CONFIG_INET
1289+ br_ioctl_hook = br_ioctl_deviceless_stub;
1290 #endif
1291-
1292- }
1293-
1294-}
1295-
1296-static void make_forwarding(int port_no)
1297-{ /* (4.6.12) */
1298- if (port_info[port_no].state == Blocking) { /* (4.6.12.3) */
1299- set_port_state(port_no, Listening); /* (4.6.12.3.1) */
1300- start_forward_delay_timer(port_no); /* (4.6.12.3.2) */
1301- }
1302-}
1303-
1304-static void topology_change_detection(void)
1305-{ /* (4.6.14) */
1306-#ifdef DEBUG_STP
1307- if ((br_stats.flags & BR_DEBUG)
1308- && (bridge_info.top_change_detected == 0))
1309- printk(KERN_DEBUG "topology_change_detected\n");
1310-#endif
1311- if (root_bridge()) { /* (4.6.14.3.1) */
1312- bridge_info.top_change = 1;
1313- start_topology_change_timer(); /* (4.6.14.3.1(2)) */
1314- } else if (!(bridge_info.top_change_detected)) {
1315- transmit_tcn(); /* (4.6.14.3.2(1)) */
1316- start_tcn_timer(); /* (4.6.14.3.2(2)) */
1317- }
1318- bridge_info.top_change_detected = 1; /* (4.6.14.3.3) */
1319-}
1320-
1321-static void topology_change_acknowledged(void)
1322-{ /* (4.6.15) */
1323-#ifdef DEBUG_STP
1324- if (br_stats.flags & BR_DEBUG)
1325- printk(KERN_DEBUG "topology_change_acked\n");
1326-#endif
1327- bridge_info.top_change_detected = 0; /* (4.6.15.3.1) */
1328- stop_tcn_timer(); /* (4.6.15.3.2) */
1329-}
1330-
1331-static void acknowledge_topology_change(int port_no)
1332-{ /* (4.6.16) */
1333- port_info[port_no].top_change_ack = 1;
1334- transmit_config(port_no); /* (4.6.16.3.2) */
1335-}
1336-
1337-static void make_blocking(int port_no) /* (4.6.13) */
1338-{
1339-
1340- if ((port_info[port_no].state != Disabled)
1341- &&
1342- (port_info[port_no].state != Blocking)
1343- /* (4.6.13.3) */
1344- ) {
1345- if ((port_info[port_no].state == Forwarding)
1346- ||
1347- (port_info[port_no].state == Learning)
1348- ) {
1349- topology_change_detection(); /* (4.6.13.3.1) */
1350- /* (4.6.14.2.3) */
1351- }
1352- set_port_state(port_no, Blocking);/* (4.6.13.3.2) */
1353- stop_forward_delay_timer(port_no);/* (4.6.13.3.3) */
1354- }
1355-}
1356-
1357-static void set_port_state(int port_no, int state)
1358-{
1359- port_info[port_no].state = state;
1360-}
1361-
1362-static void received_config_bpdu(int port_no, Config_bpdu *config) /* (4.7.1) */
1363-{
1364- int root;
1365-
1366- root = root_bridge();
1367- if (port_info[port_no].state != Disabled) {
1368-
1369-#ifdef DEBUG_STP
1370- if (br_stats.flags & BR_DEBUG)
1371- printk(KERN_DEBUG "received_config_bpdu: port %d\n",
1372- port_no);
1373-#endif
1374- if (supersedes_port_info(port_no, config)) { /* (4.7.1.1) *//* (4.
1375- * 6.2.2) */
1376- record_config_information(port_no, config); /* (4.7.1.1.1) */
1377- /* (4.6.2.2) */
1378- configuration_update(); /* (4.7.1.1.2) */
1379- /* (4.6.7.2.1) */
1380- port_state_selection(); /* (4.7.1.1.3) */
1381- /* (4.6.11.2.1) */
1382- if ((!root_bridge()) && root) { /* (4.7.1.1.4) */
1383- stop_hello_timer();
1384- if (bridge_info.top_change_detected) { /* (4.7.1.1.5 */
1385- stop_topology_change_timer();
1386- transmit_tcn(); /* (4.6.6.1) */
1387- start_tcn_timer();
1388- }
1389- }
1390- if (port_no == bridge_info.root_port) {
1391- record_config_timeout_values(config); /* (4.7.1.1.6) */
1392- /* (4.6.3.2) */
1393- config_bpdu_generation(); /* (4.6.4.2.1) */
1394- if (config->top_change_ack) { /* (4.7.1.1.7) */
1395- topology_change_acknowledged(); /* (4.6.15.2) */
1396- }
1397- }
1398- } else if (designated_port(port_no)) { /* (4.7.1.2) */
1399- reply(port_no); /* (4.7.1.2.1) */
1400- /* (4.6.5.2) */
1401- }
1402- }
1403-}
1404-
1405-static void received_tcn_bpdu(int port_no, Tcn_bpdu *tcn) /* (4.7.2) */
1406-{
1407- if (port_info[port_no].state != Disabled) {
1408-#ifdef DEBUG_STP
1409- if (br_stats.flags & BR_DEBUG)
1410- printk(KERN_DEBUG "received_tcn_bpdu: port %d\n",
1411- port_no);
1412-#endif
1413- if (designated_port(port_no)) {
1414- topology_change_detection(); /* (4.7.2.1) */
1415- /* (4.6.14.2.1) */
1416- acknowledge_topology_change(port_no); /* (4.7.2.2) */
1417- } /* (4.6.16.2) */
1418- }
1419-}
1420-
1421-static void hello_timer_expiry(void)
1422-{ /* (4.7.3) */
1423- config_bpdu_generation(); /* (4.6.4.2.2) */
1424- start_hello_timer();
1425-}
1426-
1427-static void message_age_timer_expiry(int port_no) /* (4.7.4) */
1428-{
1429- int root;
1430- root = root_bridge();
1431-
1432-#ifdef DEBUG_STP
1433- if (br_stats.flags & BR_DEBUG)
1434- printk(KERN_DEBUG "message_age_timer_expiry: port %d\n",
1435- port_no);
1436-#endif
1437- become_designated_port(port_no); /* (4.7.4.1) */
1438- /* (4.6.10.2.1) */
1439- configuration_update(); /* (4.7.4.2) */
1440- /* (4.6.7.2.2) */
1441- port_state_selection(); /* (4.7.4.3) */
1442- /* (4.6.11.2.2) */
1443- if ((root_bridge()) && (!root)) { /* (4.7.4.4) */
1444-
1445- bridge_info.max_age = bridge_info.bridge_max_age; /* (4.7.4.4.1) */
1446- bridge_info.hello_time = bridge_info.bridge_hello_time;
1447- bridge_info.forward_delay = bridge_info.bridge_forward_delay;
1448- topology_change_detection(); /* (4.7.4.4.2) */
1449- /* (4.6.14.2.4) */
1450- stop_tcn_timer(); /* (4.7.4.4.3) */
1451- config_bpdu_generation(); /* (4.7.4.4.4) */
1452- /* (4.6.4.4.3) */
1453- start_hello_timer();
1454- }
1455-}
1456-
1457-static void forward_delay_timer_expiry(int port_no) /* (4.7.5) */
1458-{
1459- if (port_info[port_no].state == Listening)
1460- { /* (4.7.5.1) */
1461- set_port_state(port_no, Learning); /* (4.7.5.1.1) */
1462- start_forward_delay_timer(port_no); /* (4.7.5.1.2) */
1463- }
1464- else if (port_info[port_no].state == Learning)
1465- {
1466- /* (4.7.5.2) */
1467- set_port_state(port_no, Forwarding); /* (4.7.5.2.1) */
1468- if (designated_for_some_port())
1469- { /* (4.7.5.2.2) */
1470- topology_change_detection(); /* (4.6.14.2.2) */
1471-
1472- }
1473- }
1474-}
1475-
1476-static int designated_for_some_port(void)
1477-{
1478- int port_no;
1479-
1480- for (port_no = One; port_no <= No_of_ports; port_no++)
1481- {
1482- if(port_info[port_no].state == Disabled)
1483- continue;
1484- if ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
1485- bridge_info.bridge_id.BRIDGE_ID) == 0))
1486- {
1487- return (TRUE);
1488- }
1489- }
1490- return (FALSE);
1491-}
1492-
1493-static void tcn_timer_expiry(void)
1494-{ /* (4.7.6) */
1495- transmit_tcn(); /* (4.7.6.1) */
1496- start_tcn_timer(); /* (4.7.6.2) */
1497-}
1498-
1499-static void topology_change_timer_expiry(void)
1500-{ /* (4.7.7) */
1501- bridge_info.top_change_detected = 0; /* (4.7.7.1) */
1502- bridge_info.top_change = 0;
1503- /* (4.7.7.2) */
1504-}
1505-
1506-static void hold_timer_expiry(int port_no) /* (4.7.8) */
1507-{
1508- if (port_info[port_no].config_pending)
1509- {
1510- transmit_config(port_no); /* (4.7.8.1) */
1511- } /* (4.6.1.2.3) */
1512-}
1513-
1514-/* Vova Oksman: Write the buffer (contents of the Bridge table) */
1515-/* to a PROCfs file */
1516-int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
1517-{
1518- int size;
1519- int len=0;
1520- off_t pos=0;
1521- char* pbuffer;
1522-
1523- if(0==offset)
1524- {
1525- /* first time write the header */
1526- size = sprintf(buffer,"%s","MAC address Device Flags Age (sec.)\n");
1527- len=size;
1528- }
1529-
1530- pbuffer=&buffer[len];
1531- sprintf_avl(&pbuffer,NULL,&pos,&len,offset,length);
1532-
1533- *start = buffer+len-(pos-offset); /* Start of wanted data */
1534- len = pos-offset; /* Start slop */
1535- if (len>length)
1536- len = length; /* Ending slop */
1537-
1538- return len;
1539-}
1540-#ifdef CONFIG_PROC_FS
1541-struct proc_dir_entry proc_net_bridge= {
1542- PROC_NET_BRIDGE, 6, "bridge",
1543- S_IFREG | S_IRUGO, 1, 0, 0,
1544- 0, &proc_net_inode_operations,
1545- br_tree_get_info
1546-};
1547-#endif
1548-__initfunc(void br_init(void))
1549-{ /* (4.8.1) */
1550- int port_no;
1551-
1552- printk(KERN_INFO "NET4: Ethernet Bridge 007 for NET4.0\n");
1553-
1554- /* Set up brg device information */
1555- bridge_info.instance = 0;
1556- brg_init();
1557-
1558- max_port_used = 0;
1559-
1560- /*
1561- * Form initial topology change time.
1562- * The topology change timer is only used if this is the root bridge.
1563- */
1564-
1565- bridge_info.topology_change_time = BRIDGE_MAX_AGE + BRIDGE_FORWARD_DELAY; /* (4.5.3.13) */
1566-
1567- bridge_info.designated_root = bridge_info.bridge_id; /* (4.8.1.1) */
1568- bridge_info.root_path_cost = Zero;
1569- bridge_info.root_port = No_port;
1570-#ifdef DEBUG_STP
1571- printk(KERN_INFO "br_init: becomes root\n");
1572-#endif
1573-
1574- bridge_info.bridge_max_age = BRIDGE_MAX_AGE;
1575- bridge_info.bridge_hello_time = BRIDGE_HELLO_TIME;
1576- bridge_info.bridge_forward_delay = BRIDGE_FORWARD_DELAY;
1577- bridge_info.hold_time = HOLD_TIME;
1578-
1579- bridge_info.max_age = bridge_info.bridge_max_age; /* (4.8.1.2) */
1580- bridge_info.hello_time = bridge_info.bridge_hello_time;
1581- bridge_info.forward_delay = bridge_info.bridge_forward_delay;
1582-
1583- bridge_info.top_change_detected = 0;
1584- bridge_info.top_change = 0;
1585- stop_tcn_timer();
1586- stop_topology_change_timer();
1587- memset(newfdb, 0, sizeof(newfdb));
1588- for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.8.1.4) */
1589- /* initial state = Disable */
1590- user_port_state[port_no] = Disabled;
1591- port_priority[port_no] = 128;
1592- br_init_port(port_no);
1593- disable_port(port_no);
1594- }
1595-#if 0 /* JRP: We are not UP ! Wait for the start command */
1596- port_state_selection(); /* (4.8.1.5) */
1597- config_bpdu_generation(); /* (4.8.1.6) */
1598- /* initialize system timer */
1599- tl.expires = jiffies+HZ; /* 1 second */
1600- tl.function = br_tick;
1601- add_timer(&tl);
1602-#endif
1603-
1604- register_netdevice_notifier(&br_dev_notifier);
1605- br_stats.flags = 0; /*BR_UP | BR_DEBUG*/; /* enable bridge */
1606- br_stats.policy = BR_ACCEPT; /* Enable bridge to accpet all protocols */
1607- br_stats.exempt_protocols = 0;
1608- /*start_hello_timer();*/
1609- /* Vova Oksman: register the function for the PROCfs "bridge" file */
1610-#ifdef CONFIG_PROC_FS
1611- proc_net_register(&proc_net_bridge);
1612-#endif
1613-}
1614-
1615-static inline unsigned short make_port_id(int port_no)
1616-{
1617- return (port_priority[port_no] << 8) | port_no;
1618-}
1619-
1620-static void br_init_port(int port_no)
1621-{
1622- port_info[port_no].port_id = make_port_id(port_no);
1623- become_designated_port(port_no); /* (4.8.1.4.1) */
1624- set_port_state(port_no, Blocking); /* (4.8.1.4.2) */
1625- port_info[port_no].top_change_ack = 0;
1626- port_info[port_no].config_pending = FALSE;/* (4.8.1.4.4) */
1627- stop_message_age_timer(port_no); /* (4.8.1.4.5) */
1628- stop_forward_delay_timer(port_no); /* (4.8.1.4.6) */
1629- stop_hold_timer(port_no); /* (4.8.1.4.7) */
1630-}
1631-
1632-static void enable_port(int port_no) /* (4.8.2) */
1633-{
1634- br_init_port(port_no);
1635- port_state_selection(); /* (4.8.2.7) */
1636-} /* */
1637-
1638-static void disable_port(int port_no) /* (4.8.3) */
1639-{
1640- int root;
1641-
1642- root = root_bridge();
1643- become_designated_port(port_no); /* (4.8.3.1) */
1644- set_port_state(port_no, Disabled); /* (4.8.3.2) */
1645- port_info[port_no].top_change_ack = 0;
1646- port_info[port_no].config_pending = FALSE;/* (4.8.3.4) */
1647- stop_message_age_timer(port_no); /* (4.8.3.5) */
1648- stop_forward_delay_timer(port_no); /* (4.8.3.6) */
1649- configuration_update();
1650- port_state_selection(); /* (4.8.3.7) */
1651- if ((root_bridge()) && (!root)) { /* (4.8.3.8) */
1652- bridge_info.max_age = bridge_info.bridge_max_age; /* (4.8.3.8.1) */
1653- bridge_info.hello_time = bridge_info.bridge_hello_time;
1654- bridge_info.forward_delay = bridge_info.bridge_forward_delay;
1655- topology_change_detection(); /* (4.8.3.8.2) */
1656- stop_tcn_timer(); /* (4.8.3.8.3) */
1657- config_bpdu_generation(); /* (4.8.3.8.4) */
1658- start_hello_timer();
1659- }
1660-}
1661-
1662-
1663-static void set_bridge_priority(bridge_id_t *new_bridge_id)
1664- /* (4.8.4) */
1665-{
1666-
1667- int root;
1668- int port_no;
1669- root = root_bridge();
1670- for (port_no = One; port_no <= No_of_ports; port_no++) { /* (4.8.4.2) */
1671- if(port_info[port_no].state == Disabled)
1672- continue;
1673- if (designated_port(port_no)) {
1674- port_info[port_no].designated_bridge = *new_bridge_id;
1675- }
1676- }
1677-
1678- bridge_info.bridge_id = *new_bridge_id; /* (4.8.4.3) */
1679- configuration_update(); /* (4.8.4.4) */
1680- port_state_selection(); /* (4.8.4.5) */
1681- if ((root_bridge()) && (!root)) { /* (4.8.4.6) */
1682- bridge_info.max_age = bridge_info.bridge_max_age; /* (4.8.4.6.1) */
1683- bridge_info.hello_time = bridge_info.bridge_hello_time;
1684- bridge_info.forward_delay = bridge_info.bridge_forward_delay;
1685- topology_change_detection(); /* (4.8.4.6.2) */
1686- stop_tcn_timer(); /* (4.8.4.6.3) */
1687- config_bpdu_generation(), /* (4.8.4.6.4) */
1688- start_hello_timer();
1689- }
1690-}
1691-
1692-static void set_port_priority(int port_no)
1693- /* (4.8.5) */
1694-{int new_port_id = make_port_id(port_no);
1695-
1696- if (designated_port(port_no)) { /* (4.8.5.2) */
1697- port_info[port_no].designated_port = new_port_id;
1698- }
1699- port_info[port_no].port_id = new_port_id; /* (4.8.5.3) */
1700- if ((br_cmp(bridge_info.bridge_id.BRIDGE_ID,
1701- port_info[port_no].designated_bridge.BRIDGE_ID) == 0
1702- )
1703- &&
1704- (port_info[port_no].port_id
1705- < port_info[port_no].designated_port
1706-
1707- )
1708- )
1709- {
1710- become_designated_port(port_no); /* (4.8.5.4.1) */
1711- port_state_selection(); /* (4.8.5.4.2) */
1712- }
1713-}
1714-
1715-static void set_path_cost(int port_no, unsigned short path_cost)
1716- /* (4.8.6) */
1717-{
1718- port_info[port_no].path_cost = path_cost; /* (4.8.6.1) */
1719- configuration_update(); /* (4.8.6.2) */
1720- port_state_selection(); /* (4.8.6.3) */
1721-}
1722-
1723-static void br_tick(unsigned long arg)
1724-{
1725- int port_no;
1726-
1727- if(!(br_stats.flags & BR_UP))
1728- return; /* JRP: we have been shot down */
1729-
1730- if (hello_timer_expired())
1731- hello_timer_expiry();
1732-
1733- if (tcn_timer_expired())
1734- tcn_timer_expiry();
1735-
1736- if (topology_change_timer_expired())
1737- topology_change_timer_expiry();
1738-
1739- for (port_no = One; port_no <= No_of_ports; port_no++)
1740- {
1741- if(port_info[port_no].state == Disabled)
1742- continue;
1743-
1744- if (forward_delay_timer_expired(port_no))
1745- forward_delay_timer_expiry(port_no);
1746-
1747- if (message_age_timer_expired(port_no))
1748- message_age_timer_expiry(port_no);
1749-
1750- if (hold_timer_expired(port_no))
1751- hold_timer_expiry(port_no);
1752- }
1753- /* call me again sometime... */
1754- tl.expires = jiffies+HZ; /* 1 second */
1755- tl.function = br_tick;
1756- add_timer(&tl);
1757-}
1758-
1759-static void start_hello_timer(void)
1760-{
1761- hello_timer.value = 0;
1762- hello_timer.active = TRUE;
1763-}
1764-
1765-static void stop_hello_timer(void)
1766-{
1767- hello_timer.active = FALSE;
1768-}
1769-
1770-static int hello_timer_expired(void)
1771-{
1772- if (hello_timer.active && (++hello_timer.value >= bridge_info.hello_time))
1773- {
1774- hello_timer.active = FALSE;
1775- return (TRUE);
1776- }
1777- return (FALSE);
1778-}
1779-
1780-static void start_tcn_timer(void)
1781-{
1782- tcn_timer.value = 0;
1783- tcn_timer.active = TRUE;
1784-}
1785-
1786-static void stop_tcn_timer(void)
1787-{
1788- tcn_timer.active = FALSE;
1789-}
1790-
1791-static int tcn_timer_expired(void)
1792-{
1793- if (tcn_timer.active && (++tcn_timer.value >= bridge_info.bridge_hello_time))
1794- {
1795- tcn_timer.active = FALSE;
1796- return (TRUE);
1797- }
1798- return (FALSE);
1799-
1800-}
1801-
1802-static void start_topology_change_timer(void)
1803-{
1804- topology_change_timer.value = 0;
1805- topology_change_timer.active = TRUE;
1806-}
1807-
1808-static void stop_topology_change_timer(void)
1809-{
1810- topology_change_timer.active = FALSE;
1811-}
1812-
1813-static int topology_change_timer_expired(void)
1814-{
1815- if (topology_change_timer.active
1816- && (++topology_change_timer.value >= bridge_info.topology_change_time ))
1817- {
1818- topology_change_timer.active = FALSE;
1819- return (TRUE);
1820- }
1821- return (FALSE);
1822-}
1823-
1824-static void start_message_age_timer(int port_no, unsigned short message_age)
1825-{
1826- message_age_timer[port_no].value = message_age;
1827- message_age_timer[port_no].active = TRUE;
1828-}
1829-
1830-static void stop_message_age_timer(int port_no)
1831-{
1832- message_age_timer[port_no].active = FALSE;
1833-}
1834-
1835-static int message_age_timer_expired(int port_no)
1836-{
1837- if (message_age_timer[port_no].active && (++message_age_timer[port_no].value >= bridge_info.max_age))
1838- {
1839- message_age_timer[port_no].active = FALSE;
1840- return (TRUE);
1841- }
1842- return (FALSE);
1843-}
1844-
1845-static void start_forward_delay_timer(int port_no)
1846-{
1847- forward_delay_timer[port_no].value = 0;
1848- forward_delay_timer[port_no].active = TRUE;
1849-}
1850-
1851-static void stop_forward_delay_timer(int port_no)
1852-{
1853- forward_delay_timer[port_no].active = FALSE;
1854-}
1855-
1856-static int forward_delay_timer_expired(int port_no)
1857-{
1858- if (forward_delay_timer[port_no].active && (++forward_delay_timer[port_no].value >= bridge_info.forward_delay))
1859- {
1860- forward_delay_timer[port_no].active = FALSE;
1861- return (TRUE);
1862- }
1863- return (FALSE);
1864-}
1865-
1866-static void start_hold_timer(int port_no)
1867-{
1868- hold_timer[port_no].value = 0;
1869- hold_timer[port_no].active = TRUE;
1870-}
1871-
1872-static void stop_hold_timer(int port_no)
1873-{
1874- hold_timer[port_no].active = FALSE;
1875-}
1876+ register_netdevice_notifier(&br_device_notifier);
1877
1878-static int hold_timer_expired(int port_no)
1879-{
1880- if (hold_timer[port_no].active &&
1881- (++hold_timer[port_no].value >= bridge_info.hold_time))
1882- {
1883- hold_timer[port_no].active = FALSE;
1884- return (TRUE);
1885- }
1886- return (FALSE);
1887-
1888-}
1889-
1890-static struct sk_buff *alloc_bridge_skb(int port_no, int pdu_size, char *pdu_name)
1891-{
1892- struct sk_buff *skb;
1893- struct device *dev = port_info[port_no].dev;
1894- struct ethhdr *eth;
1895- int size = dev->hard_header_len + BRIDGE_LLC1_HS + pdu_size;
1896- unsigned char *llc_buffer;
1897- int pad_size = 60 - size;
1898-
1899- size = 60; /* minimum Ethernet frame - CRC */
1900-
1901- if (port_info[port_no].state == Disabled)
1902- {
1903- printk(KERN_DEBUG "send_%s_bpdu: port %i not valid\n", pdu_name, port_no);
1904- return NULL;
1905- }
1906-
1907- skb = alloc_skb(size, GFP_ATOMIC);
1908- if (skb == NULL)
1909- {
1910- printk(KERN_DEBUG "send_%s_bpdu: no skb available\n", pdu_name);
1911- return NULL;
1912- }
1913- skb->dev = dev;
1914- skb->mac.raw = skb->nh.raw = skb_put(skb,size);
1915- memset(skb->nh.raw + 60 - pad_size, 0xa5, pad_size);
1916- eth = skb->mac.ethernet;
1917- memcpy(eth->h_dest, bridge_ula, ETH_ALEN);
1918- memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
1919-
1920- if (br_stats.flags & BR_DEBUG)
1921- printk(KERN_DEBUG "send_%s_bpdu: port %i src %02x:%02x:%02x:%02x:%02x:%02x\n",
1922- pdu_name,
1923- port_no,
1924- eth->h_source[0],
1925- eth->h_source[1],
1926- eth->h_source[2],
1927- eth->h_source[3],
1928- eth->h_source[4],
1929- eth->h_source[5]);
1930-#if 0
1931- /* 8038 is used in older DEC spanning tree protocol which uses a
1932- * different pdu layout as well
1933- */
1934- eth->h_proto = htons(0x8038);
1935-#endif
1936- eth->h_proto = htons(pdu_size + BRIDGE_LLC1_HS);
1937-
1938- skb->nh.raw += skb->dev->hard_header_len;
1939- llc_buffer = skb->nh.raw;
1940- *llc_buffer++ = BRIDGE_LLC1_DSAP;
1941- *llc_buffer++ = BRIDGE_LLC1_SSAP;
1942- *llc_buffer++ = BRIDGE_LLC1_CTRL;
1943- /* set nh.raw to where the bpdu starts */
1944- skb->nh.raw += BRIDGE_LLC1_HS;
1945-
1946- /* mark that we've been here... */
1947- skb->pkt_bridged = IS_BRIDGED;
1948- return skb;
1949-}
1950-
1951-static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
1952-{
1953- struct sk_buff *skb;
1954-
1955- /*
1956- * Keep silent when disabled or when STP disabled
1957- */
1958-
1959- if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
1960- return -1;
1961-
1962- /*
1963- * Create and send the message
1964- */
1965-
1966- skb = alloc_bridge_skb(port_no, BRIDGE_BPDU_8021_CONFIG_SIZE,
1967- "config");
1968- if (skb == NULL)
1969- return(-1);
1970-
1971- /* copy fields before "flags" */
1972- memcpy(skb->nh.raw, config_bpdu, BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
1973-
1974- /* build the "flags" field */
1975- *(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) = 0;
1976- if (config_bpdu->top_change_ack)
1977- *(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x80;
1978- if (config_bpdu->top_change)
1979- *(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x01;
1980-
1981- config_bpdu_hton(config_bpdu);
1982- /* copy the rest */
1983- memcpy(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET+1,
1984- (char*)&(config_bpdu->root_id),
1985- BRIDGE_BPDU_8021_CONFIG_SIZE-1-BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
1986-
1987- dev_queue_xmit(skb);
1988- return(0);
1989-}
1990-
1991-static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
1992-{
1993- struct sk_buff *skb;
1994-
1995- /*
1996- * Keep silent when disabled or when STP disabled
1997- */
1998-
1999- if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
2000- return -1;
2001-
2002-
2003- skb = alloc_bridge_skb(port_no, sizeof(Tcn_bpdu), "tcn");
2004- if (skb == NULL)
2005- return(-1);
2006-
2007- memcpy(skb->nh.raw, bpdu, sizeof(Tcn_bpdu));
2008-
2009- dev_queue_xmit(skb);
2010- return(0);
2011-}
2012-
2013-static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
2014-{
2015- struct device *dev = ptr;
2016- int i;
2017-
2018- /* check for loopback devices */
2019- if (dev->flags & IFF_LOOPBACK)
2020- return(NOTIFY_DONE);
2021-
2022- if (dev == &brg_if.dev)
2023- return(NOTIFY_DONE); /* Don't attach the brg device to a port! */
2024-
2025- switch (event)
2026- {
2027- case NETDEV_DOWN:
2028- if (br_stats.flags & BR_DEBUG)
2029- printk(KERN_DEBUG "br_device_event: NETDEV_DOWN...\n");
2030- /* find our device and mark it down */
2031- for (i = One; i <= No_of_ports; i++)
2032- {
2033- if (port_info[i].dev == dev)
2034- {
2035- disable_port(i);
2036- return NOTIFY_DONE;
2037- break;
2038- }
2039- }
2040- break;
2041- case NETDEV_UP:
2042- if (br_stats.flags & BR_DEBUG)
2043- printk(KERN_DEBUG "br_device_event: NETDEV_UP...\n");
2044- /* Only handle ethernet ports */
2045- if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_LOOPBACK)
2046- return NOTIFY_DONE;
2047- /* look up an unused device and enable it */
2048- for (i = One; i <= No_of_ports; i++)
2049- {
2050- if (port_info[i].dev == NULL || port_info[i].dev == dev)
2051- {
2052- port_info[i].dev = dev;
2053- port_info[i].port_id = i;
2054- dev->bridge_port_id = i;
2055- if( i > max_port_used )
2056- max_port_used = i;
2057- /* set bridge addr from 1st device addr */
2058- if (((htonl(bridge_info.bridge_id.BRIDGE_ID[0])&0xffff) == 0) &&
2059- (bridge_info.bridge_id.BRIDGE_ID[1] == 0))
2060- {
2061- memcpy(bridge_info.bridge_id.BRIDGE_ID_ULA, dev->dev_addr, 6);
2062- if(bridge_info.bridge_id.BRIDGE_PRIORITY == 0)
2063- bridge_info.bridge_id.BRIDGE_PRIORITY = htons(32768);
2064- set_bridge_priority(&bridge_info.bridge_id);
2065- }
2066- /* Add local MAC address */
2067- br_add_local_mac(dev->dev_addr);
2068- /* Save MAC address for latter change address events */
2069- memcpy(port_info[i].ifmac.BRIDGE_ID_ULA, dev->dev_addr, 6);
2070- if((br_stats.flags & BR_UP) &&
2071- (user_port_state[i] != Disabled))
2072- {
2073- /* don't start if user said so */
2074- enable_port(i);
2075- set_path_cost(i, br_port_cost(dev));
2076- set_port_priority(i);
2077- if (br_stats.flags & BR_STP_DISABLED)
2078- port_info[i].state = Forwarding;
2079- else
2080- make_forwarding(i);
2081- }
2082- return NOTIFY_DONE;
2083- break;
2084- }
2085- }
2086- break;
2087- case NETDEV_REGISTER:
2088- if (br_stats.flags & BR_DEBUG)
2089- printk(KERN_DEBUG "br_device_event: NETDEV_REGISTER...\n");
2090- /* printk(KERN_ERR "br_device_event: NETDEV_REGISTER...\n"); */
2091- /* printk(KERN_ERR "br_device_event: dev->type: 0x%X\n", dev->type); */
2092- /* Only handle ethernet ports */
2093- if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_LOOPBACK)
2094- return NOTIFY_DONE;
2095- /* printk(KERN_ERR "br_device_event: Looking for port...\n"); */
2096- for (i = One; i <= No_of_ports; i++)
2097- {
2098- if (port_info[i].dev == NULL || port_info[i].dev == dev)
2099- {
2100- /* printk(KERN_ERR "br_device_event: Found port %d\n", i); */
2101- port_info[i].dev = dev;
2102- port_info[i].port_id = i;
2103- dev->bridge_port_id = i;
2104- if( i > max_port_used )
2105- max_port_used = i;
2106- /* handle local MAC address minuplations */
2107- br_add_local_mac(dev->dev_addr);
2108- memcpy(port_info[i].ifmac.BRIDGE_ID_ULA, dev->dev_addr, 6);
2109- return NOTIFY_DONE;
2110- break;
2111- }
2112- }
2113- break;
2114- case NETDEV_UNREGISTER:
2115- if (br_stats.flags & BR_DEBUG)
2116- printk(KERN_DEBUG "br_device_event: NETDEV_UNREGISTER...\n");
2117- i = find_port(dev);
2118- if (i > 0) {
2119- br_avl_delete_by_port(i);
2120- memset(port_info[i].ifmac.BRIDGE_ID_ULA, 0, 6);
2121- port_info[i].dev = NULL;
2122- }
2123- break;
2124- case NETDEV_CHANGEADDR:
2125- if (br_stats.flags & BR_DEBUG)
2126- printk(KERN_DEBUG "br_device_event: NETDEV_CHANGEADDR...\n");
2127- i = find_port(dev);
2128- if (i <= 0)
2129- break;
2130- if (memcmp(port_info[i].ifmac.BRIDGE_ID_ULA, dev->dev_addr, 6) != 0)
2131- break; /* Don't worry about a change of hardware broadcast address! */
2132- if (dev->start) {
2133- printk(KERN_CRIT "br_device_event: NETDEV_CHANGEADDR on busy device %s - FIX DRIVER!\n",
2134- dev->name);
2135- /* return NOTIFY_BAD; It SHOULD be this, but I want to be friendly... */
2136- return NOTIFY_DONE;
2137- }
2138- br_avl_delete_by_port(i);
2139- memset(port_info[i].ifmac.BRIDGE_ID_ULA, 0, 6);
2140- break;
2141- }
2142- return NOTIFY_DONE;
2143-}
2144-
2145-/* Routine to loop over device list and register
2146- * interfaces to bridge. Called from last part of net_dev_init just before
2147- * bootp/rarp interface setup
2148- */
2149-void br_spacedevice_register(void)
2150-{
2151- struct device *dev;
2152- for( dev = dev_base; dev != NULL; dev = dev->next)
2153- {
2154- br_device_event(NULL, NETDEV_REGISTER, dev);
2155- }
2156-}
2157-
2158-
2159-/* This is for SPEED in the kernel in net_bh.c */
2160-
2161-int br_call_bridge(struct sk_buff *skb, unsigned short type)
2162-{
2163- int port;
2164- struct device *dev;
2165-
2166-#if 0 /* Checked first in handle_bridge to save expense of function call */
2167- if(!(br_stats.flags & BR_UP))
2168- return 0;
2169-#endif
2170-
2171- dev = skb->dev;
2172-
2173- /* Check for brg0 device
2174- */
2175- if (dev == &brg_if.dev)
2176- return 0;
2177-
2178- port = dev->bridge_port_id;
2179-
2180- if(!port)
2181- return 0;
2182-
2183- /* Sanity - make sure we are not leaping off into fairy space! */
2184- if ( port < 0 || port > max_port_used || port_info[port].dev != dev) {
2185- if (net_ratelimit())
2186- printk(KERN_CRIT "br_call_bridge: device %s has invalid port ID %d!\n",
2187- dev->name,
2188- dev->bridge_port_id);
2189- return 0;
2190- }
2191-
2192- if(user_port_state[port] == Disabled)
2193- return 0;
2194-
2195- if (!br_protocol_ok(ntohs(type)))
2196- return 0;
2197-
2198- return 1;
2199-
2200-}
2201-
2202-
2203-/*
2204- * following routine is called when a frame is received
2205- * from an interface, it returns 1 when it consumes the
2206- * frame, 0 when it does not
2207- */
2208-
2209-int br_receive_frame(struct sk_buff *skb) /* 3.5 */
2210-{
2211- int port, ret;
2212- Port_data *p;
2213- struct ethhdr *eth;
2214- struct device *dev;
2215-
2216- /* sanity */
2217- if (!skb) {
2218- printk(KERN_CRIT "br_receive_frame: no skb!\n");
2219- return(1);
2220- }
2221-
2222- dev = skb->dev;
2223-
2224- /* Check for brg0 device
2225- */
2226- if (dev == &brg_if.dev)
2227- return 0;
2228-
2229- skb->pkt_bridged = IS_BRIDGED;
2230-
2231- /* check for loopback */
2232- if (dev->flags & IFF_LOOPBACK)
2233- return 0 ;
2234-
2235-#if 0
2236- port = find_port(dev);
2237-#else
2238- port = dev->bridge_port_id;
2239-#endif
2240-
2241- if(!port)
2242- return 0;
2243-
2244- /* Hand off to brg_rx BEFORE we screw up the skb */
2245- if(brg_rx(skb, port))
2246- return(1);
2247-
2248- skb->nh.raw = skb->mac.raw;
2249- eth = skb->mac.ethernet;
2250- p = &port_info[port];
2251-
2252- if(p->state == Disabled)
2253- {
2254- /* We are here if BR_UP even if this port is Disabled.
2255- * Send everything up
2256- */
2257- skb->pkt_type = PACKET_HOST;
2258- ++br_stats_cnt.port_disable_up_stack;
2259- return(0); /* pass frame up our stack (this will */
2260- /* happen in net_bh() in dev.c) */
2261- }
2262-
2263- /* Here only if not disable.
2264- * Remark: only frames going up will show up in NIT (tcpdump)
2265- */
2266-
2267- /* JRP: even if port is Blocking we need to process the Spanning Tree
2268- * frames to keep the port in that state
2269- */
2270- if (memcmp(eth->h_dest, bridge_ula, ETH_ALEN) == 0)
2271- {
2272- ++br_stats_cnt.rcv_bpdu;
2273- br_bpdu(skb, port); /* br_bpdu consumes skb */
2274- return(1);
2275- }
2276- switch (p->state)
2277- {
2278- case Learning:
2279- if((ret = br_learn(skb, port)))
2280- { /* 3.8 */
2281- if (ret > 0) ++br_stats_cnt.drop_multicast;
2282- return br_drop(skb);
2283- }
2284- /* fall through */
2285- case Listening:
2286- /* fall through */
2287- case Blocking:
2288- ++br_stats_cnt.notForwarding;
2289- return(br_drop(skb));
2290- /*
2291- case Disabled: is now handled before this switch !
2292- Keep the break to allow GCC to use a jmp table.
2293- */
2294- break;
2295- case Forwarding:
2296- if((ret = br_learn(skb, port))) { /* 3.8 */
2297- if (ret > 0) ++br_stats_cnt.drop_multicast;
2298- return br_drop(skb);
2299- }
2300- /* Now this frame came from one of bridged
2301- ports this means we should attempt to forward it.
2302- JRP: local addresses are now in the AVL tree,
2303- br_forward will pass frames up if it matches
2304- one of our local MACs or if it is a multicast
2305- group address.
2306- br_forward() will not consume the frame if this
2307- is the case */
2308- return(br_forward(skb, port));
2309- default:
2310- printk(KERN_DEBUG "br_receive_frame: port [%i] unknown state [%i]\n",
2311- port, p->state);
2312- ++br_stats_cnt.unknown_state;
2313- return(br_drop(skb)); /* discard frame */
2314- }
2315-}
2316-
2317-/*
2318- * the following routine is called to transmit frames from the host
2319- * stack. it returns 1 when it consumes the frame and
2320- * 0 when it does not.
2321- */
2322-
2323-int br_tx_frame(struct sk_buff *skb) /* 3.5 */
2324-{
2325- int port;
2326- struct ethhdr *eth;
2327-
2328- /* sanity */
2329- if (!skb)
2330- {
2331- printk(KERN_CRIT "br_tx_frame: no skb!\n");
2332- return(0);
2333- }
2334-
2335- if (!skb->dev)
2336- {
2337- printk(KERN_CRIT "br_tx_frame: no dev!\n");
2338- return(0);
2339- }
2340-
2341- /* check for loopback */
2342- if (skb->dev->flags & IFF_LOOPBACK)
2343- return(0);
2344-
2345- /* if bridging is not enabled on the port we are going to send
2346- to, we have nothing to do with this frame, hands off */
2347- if (((port=find_port(skb->dev))==0)||(port_info[port].state==Disabled)) {
2348- ++br_stats_cnt.port_disable;
2349- return(0);
2350- }
2351- ++br_stats_cnt.port_not_disable;
2352- skb->mac.raw = skb->nh.raw = skb->data;
2353- eth = skb->mac.ethernet;
2354- port = 0; /* an impossible port (locally generated) */
2355- if (br_stats.flags & BR_DEBUG)
2356- printk(KERN_DEBUG "br_tx_fr : port %i src %02x:%02x:%02x:%02x:%02x:%02x"
2357- " dest %02x:%02x:%02x:%02x:%02x:%02x\n",
2358- port,
2359- eth->h_source[0],
2360- eth->h_source[1],
2361- eth->h_source[2],
2362- eth->h_source[3],
2363- eth->h_source[4],
2364- eth->h_source[5],
2365- eth->h_dest[0],
2366- eth->h_dest[1],
2367- eth->h_dest[2],
2368- eth->h_dest[3],
2369- eth->h_dest[4],
2370- eth->h_dest[5]);
2371- return(br_forward(skb, port));
2372-}
2373-
2374-static void br_add_local_mac(unsigned char *mac)
2375-{
2376- struct fdb *f;
2377- f = (struct fdb *)kmalloc(sizeof(struct fdb), GFP_ATOMIC);
2378- if (!f)
2379- {
2380- printk(KERN_CRIT "br_add_local_mac: unable to malloc fdb\n");
2381- return;
2382- }
2383- f->port = 0; /* dest port == 0 =>local */
2384- memcpy(f->ula, mac, 6);
2385- f->timer = 0; /* will not aged anyway */
2386- f->flags = 0; /* not valid => br_forward special route */
2387- /*
2388- * add entity to AVL tree. If entity already
2389- * exists in the tree, update the fields with
2390- * what we have here.
2391- */
2392- if (br_avl_insert(f) != NULL)
2393- {
2394- /* Already in */
2395- kfree(f);
2396- }
2397-}
2398-
2399-/* Avoid broadcast loop by limiting the number of broacast frames per
2400- * period. The idea is to limit this per source
2401- * returns: 0 if limit is not reached
2402- * 1 if frame should be dropped
2403- */
2404-
2405-static inline int mcast_quench(struct fdb *f)
2406-{
2407- if(f->mcast_count++ == 0) /* first time */
2408- f->mcast_timer = jiffies;
2409- else {
2410- if(f->mcast_count > max_mcast_per_period) {
2411- if(time_after(jiffies, f->mcast_timer + mcast_hold_time))
2412- f->mcast_count = 0;
2413- else return 1;
2414- }
2415- }
2416- return 0;
2417-}
2418-
2419-/*
2420- * this routine returns 0 when it learns (or updates) from the
2421- * frame, and 1 if we must dropped the frame due to multicast
2422- * limitations, or -1 because of not enough memory.
2423- *
2424- * NB Can be called when skb->nh.raw is NOT set up when
2425- * receiving frames on brg0 via brg_rx
2426- */
2427-
2428-static int br_learn(struct sk_buff *skb, int port) /* 3.8 */
2429-{
2430- struct fdb *f, *oldfdb;
2431- Port_data *p = &port_info[port];
2432- struct ethhdr *eth = skb->mac.ethernet;
2433-
2434- /* JRP: no reason to check port state again. We are called by
2435- * br_receive_frame() only when in Learning or Forwarding
2436- * Remark: code not realigned yet to keep diffs smaller
2437- */
2438-
2439- /* don't keep group addresses in the tree */
2440- if (eth->h_source[0] & 0x01)
2441- return 0;
2442-
2443- if((f= newfdb[port]) == NULL)
2444- {
2445- newfdb[port] = f = (struct fdb *)kmalloc(sizeof(struct fdb), GFP_ATOMIC);
2446- if (!f)
2447- {
2448- printk(KERN_WARNING "br_learn: unable to malloc fdb\n");
2449- return(-1); /* this drops the frame */
2450- }
2451- }
2452- f->port = port; /* source port */
2453- memcpy(f->ula, eth->h_source, 6);
2454- f->timer = CURRENT_TIME;
2455- f->flags = FDB_ENT_VALID;
2456- /*
2457- * add entity to AVL tree. If entity already
2458- * exists in the tree, update the fields with
2459- * what we have here.
2460- */
2461- if ((oldfdb = br_avl_insert(f)))
2462- {
2463- /* update if !NULL */
2464- if((eth->h_dest[0] & 0x01) && /* multicast */ mcast_quench(oldfdb))
2465- return 1;
2466- return 0;
2467- }
2468- newfdb[port] = NULL; /* force kmalloc next time */
2469- f->mcast_count = 0;
2470- /* add to head of port chain */
2471- f->fdb_next = p->fdb;
2472- p->fdb = f;
2473- allocated_fdb_cnt++;
2474- return 0;
2475-}
2476-
2477-/* JRP: always called under br_receive_frame(). No need for Q protection. */
2478-
2479-void requeue_fdb(struct fdb *node, int new_port)
2480-{
2481- Port_data *p = &port_info[node->port];
2482-
2483- /* dequeue */
2484- if(p->fdb == node)
2485- p->fdb = node->fdb_next;
2486- else
2487- {
2488- struct fdb *prev;
2489-
2490- for(prev = p->fdb; prev; prev = prev->fdb_next)
2491- if (prev->fdb_next == node)
2492- break;
2493-
2494- if(prev != NULL)
2495- prev->fdb_next = node->fdb_next;
2496- else
2497- {
2498- /* Forget about this update. */
2499- printk(KERN_ERR "br:requeue_fdb\n");
2500- return;
2501- }
2502- }
2503- /* enqueue */
2504- node->port = new_port;
2505- node->fdb_next = port_info[new_port].fdb;
2506- port_info[new_port].fdb = node;
2507-}
2508-
2509-/*
2510- * this routine always consumes the frame
2511- */
2512-
2513-static int br_drop(struct sk_buff *skb)
2514-{
2515- kfree_skb(skb);
2516- return(1);
2517-}
2518-
2519-/*
2520- * this routine always consumes the frame
2521- */
2522-
2523-static int br_dev_drop(struct sk_buff *skb)
2524-{
2525- dev_kfree_skb(skb);
2526- return(1);
2527-}
2528-
2529-/*
2530- * Forward the frame SKB to proper port[s]. PORT is the port that the
2531- * frame has come from; we will not send the frame back there. PORT == 0
2532- * means we have been called from br_tx_fr(), not from br_receive_frame().
2533- *
2534- * this routine returns 1 if it consumes the frame, 0
2535- * if not...
2536- */
2537-
2538-static int br_forward(struct sk_buff *skb, int port) /* 3.7 */
2539-{
2540- struct fdb *f;
2541-
2542- /*
2543- * flood all ports with frames destined for a group
2544- * address. If frame came from above, drop it,
2545- * otherwise it will be handled in br_receive_frame()
2546- * Multicast frames will also need to be seen
2547- * by our upper layers.
2548- */
2549- if (skb->mac.ethernet->h_dest[0] & 0x01)
2550- {
2551- /* group address */
2552- br_flood(skb, port);
2553- /*
2554- * External groups are fed out via the normal source
2555- * This probably should be dropped since the flood will
2556- * have sent it anyway.
2557- */
2558- if (port == 0)
2559- {
2560- /* Locally generated */
2561- ++br_stats_cnt.local_multicast;
2562- return(br_dev_drop(skb));
2563- }
2564- ++br_stats_cnt.forwarded_multicast;
2565- return(0);
2566- }
2567- else
2568- {
2569- /* unicast frame, locate port to forward to */
2570- f = br_avl_find_addr(skb->mac.ethernet->h_dest);
2571- /*
2572- * Send flood and drop.
2573- */
2574- if (!f || !(f->flags & FDB_ENT_VALID))
2575- {
2576- if(f && (f->port == 0))
2577- {
2578- skb->pkt_type = PACKET_HOST;
2579- ++br_stats_cnt.forwarded_unicast_up_stack;
2580- return(0);
2581- }
2582- /* not found or too old; flood all ports */
2583- ++br_stats_cnt.flood_unicast;
2584- br_flood(skb, port);
2585- return(br_dev_drop(skb));
2586- }
2587- /*
2588- * Sending
2589- */
2590- if (f->port!=port && port_info[f->port].state == Forwarding)
2591- {
2592- /* Has entry expired? */
2593- if (f->timer + fdb_aging_time < CURRENT_TIME)
2594- {
2595- /* timer expired, invalidate entry */
2596- f->flags &= ~FDB_ENT_VALID;
2597- if (br_stats.flags & BR_DEBUG)
2598- printk(KERN_DEBUG "fdb entry expired...\n");
2599- /*
2600- * Send flood and drop original
2601- */
2602- ++br_stats_cnt.aged_flood_unicast;
2603- br_flood(skb, port);
2604- return(br_dev_drop(skb));
2605- }
2606- ++br_stats_cnt.forwarded_unicast;
2607- /* mark that's we've been here... */
2608- skb->pkt_bridged = IS_BRIDGED;
2609-
2610- /* reset the skb->ip pointer */
2611- skb->nh.raw = skb->data + ETH_HLEN;
2612-
2613- /*
2614- * Send the buffer out.
2615- */
2616-
2617- skb->dev=port_info[f->port].dev;
2618-
2619- /*
2620- * We send this still locked
2621- */
2622- skb->priority = 1;
2623- dev_queue_xmit(skb);
2624- return(1); /* skb has been consumed */
2625- }
2626- else
2627- {
2628- /* JRP: Needs to aged entry as well, if topology changes
2629- * the entry would not age. Got this while swapping
2630- * two cables !
2631- *
2632- * Has entry expired?
2633- */
2634-
2635- if (f->timer + fdb_aging_time < CURRENT_TIME)
2636- {
2637- /* timer expired, invalidate entry */
2638- f->flags &= ~FDB_ENT_VALID;
2639- if (br_stats.flags & BR_DEBUG)
2640- printk(KERN_DEBUG "fdb entry expired...\n");
2641- ++br_stats_cnt.drop_same_port_aged;
2642- }
2643- else ++br_stats_cnt.drop_same_port;
2644- /*
2645- * Arrived on the right port, we discard
2646- */
2647- return(br_dev_drop(skb));
2648- }
2649- }
2650-}
2651-
2652-/*
2653- * this routine sends a copy of the frame to all forwarding ports
2654- * with the exception of the port given. This routine never
2655- * consumes the original frame.
2656- */
2657-
2658-static int br_flood(struct sk_buff *skb, int port)
2659-{
2660- int i;
2661- struct sk_buff *nskb;
2662-
2663- for (i = One; i <= No_of_ports; i++)
2664- {
2665- if (i == port) /* don't send back where we got it */
2666- continue;
2667- if (i > max_port_used)
2668- /* Don't go scanning empty port entries */
2669- break;
2670- if (port_info[i].state == Forwarding)
2671- {
2672- nskb = skb_clone(skb, GFP_ATOMIC);
2673- if(nskb==NULL)
2674- continue;
2675- /* mark that's we've been here... */
2676- nskb->pkt_bridged = IS_BRIDGED;
2677- /* Send to each port in turn */
2678- nskb->dev= port_info[i].dev;
2679- /* To get here we must have done ARP already,
2680- or have a received valid MAC header */
2681-
2682-/* printk(KERN_DEBUG "Flood to port %d\n",i);*/
2683- nskb->nh.raw = nskb->data + ETH_HLEN;
2684- nskb->priority = 1;
2685- dev_queue_xmit(nskb);
2686- }
2687- }
2688- return(0);
2689-}
2690-
2691-/*
2692- * FIXME: This needs to come from the device structs, eg for
2693- * 10,100,1Gbit ethernet.
2694- */
2695-
2696-static int br_port_cost(struct device *dev) /* 4.10.2 */
2697-{
2698- if (strncmp(dev->name, "lec", 3) == 0) /* ATM Lan Emulation (LANE) */
2699- return(7); /* 155 Mbs */
2700- if (strncmp(dev->name, "eth", 3) == 0) /* ethernet */
2701- return(100);
2702- if (strncmp(dev->name, "plip",4) == 0) /* plip */
2703- return (1600);
2704- return(100); /* default */
2705-}
2706-
2707-/*
2708- * this routine always consumes the skb
2709- */
2710-
2711-static void br_bpdu(struct sk_buff *skb, int port) /* consumes skb */
2712-{
2713- char *bufp = skb->data + ETH_HLEN;
2714- Tcn_bpdu *bpdu = (Tcn_bpdu *) (bufp + BRIDGE_LLC1_HS);
2715- Config_bpdu rcv_bpdu;
2716-
2717- if(!(br_stats.flags & BR_STP_DISABLED) &&
2718- (*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
2719- (*bufp++ == BRIDGE_LLC1_CTRL) &&
2720- (bpdu->protocol_id == BRIDGE_BPDU_8021_PROTOCOL_ID) &&
2721- (bpdu->protocol_version_id == BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID))
2722- {
2723-
2724- switch (bpdu->type)
2725- {
2726- case BPDU_TYPE_CONFIG:
2727- /* realign for portability to RISC */
2728- memcpy((char*)&rcv_bpdu, bufp,
2729- BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
2730- bufp+= BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET;
2731- rcv_bpdu.top_change_ack =
2732- (*bufp & TOPOLOGY_CHANGE_ACK) != 0;
2733- rcv_bpdu.top_change =
2734- (*bufp & TOPOLOGY_CHANGE) != 0;
2735- bufp++;
2736- memcpy((char*)&rcv_bpdu.root_id, bufp,
2737- BRIDGE_BPDU_8021_CONFIG_SIZE-1
2738- -BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
2739- config_bpdu_ntoh(&rcv_bpdu);
2740- received_config_bpdu(port, &rcv_bpdu);
2741- break;
2742-
2743- case BPDU_TYPE_TOPO_CHANGE:
2744- received_tcn_bpdu(port, bpdu);
2745- break;
2746- default:
2747- printk(KERN_DEBUG "br_bpdu: received unknown bpdu, type = %i\n", bpdu->type);
2748- /* break; */
2749- }
2750- }
2751- br_drop(skb);
2752-}
2753-
2754-struct fdb_info *get_fdb_info(int user_buf_size, int *copied,int *notcopied)
2755-{
2756- int fdb_size, i, built = 0;
2757- struct fdb_info *fdbi, *fdbis;
2758-
2759- *copied = user_buf_size - sizeof(struct fdb_info_hdr);
2760- *copied /= sizeof(struct fdb_info);
2761- *copied = min(*copied, allocated_fdb_cnt);
2762- *notcopied = allocated_fdb_cnt - *copied;
2763- if(*copied == 0)
2764- return NULL;
2765- fdb_size = *copied * sizeof(struct fdb_info);
2766- fdbis = kmalloc(fdb_size, GFP_KERNEL);
2767- if(fdbis == NULL)
2768- return NULL;
2769- fdbi = fdbis;
2770-
2771- for(i=One; i<=No_of_ports;i++)
2772- {
2773- struct fdb *fdb;
2774-
2775- cli();
2776- fdb = port_info[i].fdb;
2777- while(fdb)
2778- {
2779- memcpy(fdbi->ula, fdb->ula, ETH_ALEN);
2780- fdbi->port = fdb->port;
2781- fdbi->flags = fdb->flags;
2782- fdbi->timer = fdb->timer;
2783- fdbi++;
2784- if(++built == *copied)
2785- {
2786- sti();
2787- return fdbis;
2788- }
2789- fdb = fdb->fdb_next;
2790- }
2791- sti();
2792- }
2793- printk(KERN_DEBUG "get_fdb_info: built=%d\n", built);
2794- return fdbis;
2795-}
2796-
2797-
2798-/* Fill in interface names in port_info structure
2799- */
2800-static void br_get_ifdata(void) {
2801- int i;
2802-
2803- for(i=One;i<=No_of_ports; i++) {
2804-
2805- port_info[i].admin_state = user_port_state[i];
2806-
2807- /* memset IS needed. Kernel strncpy does NOT NULL terminate
2808- * strings when limit reached
2809- */
2810- memset(port_info[i].ifname, 0, IFNAMSIZ);
2811- if( port_info[i].dev == 0 )
2812- continue;
2813- strncpy(port_info[i].ifname, port_info[i].dev->name, IFNAMSIZ-1);
2814- /* Being paranoid */
2815- port_info[i].ifname[IFNAMSIZ-1] = '\0';
2816- }
2817-}
2818-
2819-/* Given an interface index, loop over port array to see if configured. If
2820- so, return port number, otherwise error */
2821-static int br_find_port(int ifindex)
2822-{
2823- int i;
2824-
2825- for(i=1; i <= No_of_ports; i++) {
2826- if (port_info[i].dev == 0)
2827- continue;
2828- if (port_info[i].dev->ifindex == ifindex)
2829- return(i);
2830- }
2831-
2832- return -EUNATCH; /* Tell me if this is incorrect error code for this case */
2833-}
2834-
2835-
2836-int br_ioctl(unsigned int cmd, void *arg)
2837-{
2838- int err, i, ifflags;
2839- struct br_cf bcf;
2840- bridge_id_t new_id;
2841- struct device *dev;
2842-
2843- switch(cmd)
2844- {
2845- case SIOCGIFBR: /* get bridging control blocks */
2846- memcpy(&br_stats.bridge_data, &bridge_info, sizeof(Bridge_data));
2847-
2848- /* Fill in interface names in port_info*/
2849- br_get_ifdata();
2850-
2851- br_stats.num_ports = No_of_ports;
2852- memcpy(&br_stats.port_data, &port_info, sizeof(Port_data)*All_ports);
2853-
2854- err = copy_to_user(arg, &br_stats, sizeof(struct br_stat));
2855- if (err)
2856- {
2857- err = -EFAULT;
2858- }
2859- return err;
2860- case SIOCSIFBR:
2861- err = copy_from_user(&bcf, arg, sizeof(struct br_cf));
2862- if (err)
2863- return -EFAULT;
2864- if (bcf.cmd != BRCMD_DISPLAY_FDB && !suser())
2865- return -EPERM;
2866- switch (bcf.cmd)
2867- {
2868- case BRCMD_BRIDGE_ENABLE:
2869- if (br_stats.flags & BR_UP)
2870- return(-EALREADY);
2871- printk(KERN_DEBUG "br: enabling bridging function\n");
2872- br_stats.flags |= BR_UP; /* enable bridge */
2873- for(i=One;i<=No_of_ports; i++)
2874- {
2875- /* don't start if user said so */
2876- if((user_port_state[i] != Disabled)
2877- && port_info[i].dev)
2878- {
2879- enable_port(i);
2880- }
2881- }
2882- port_state_selection(); /* (4.8.1.5) */
2883- if (br_stats.flags & BR_STP_DISABLED)
2884- for(i=One;i<=No_of_ports; i++)
2885- if((user_port_state[i] != Disabled) && port_info[i].dev)
2886- port_info[i].state = Forwarding;
2887- config_bpdu_generation(); /* (4.8.1.6) */
2888- /* initialize system timer */
2889- tl.expires = jiffies+HZ; /* 1 second */
2890- tl.function = br_tick;
2891- add_timer(&tl);
2892- start_hello_timer();
2893- break;
2894- case BRCMD_BRIDGE_DISABLE:
2895- if (!(br_stats.flags & BR_UP))
2896- return(-EALREADY);
2897- printk(KERN_DEBUG "br: disabling bridging function\n");
2898- br_stats.flags &= ~BR_UP; /* disable bridge */
2899- stop_hello_timer();
2900- for (i = One; i <= No_of_ports; i++)
2901- if (port_info[i].state != Disabled)
2902- disable_port(i);
2903- break;
2904- case BRCMD_TOGGLE_STP:
2905- printk(KERN_DEBUG "br: %s spanning tree protcol\n",
2906- (br_stats.flags & BR_STP_DISABLED) ? "enabling" : "disabling");
2907- if (br_stats.flags & BR_STP_DISABLED) { /* enable STP */
2908- for(i=One;i<=No_of_ports; i++)
2909- if((user_port_state[i] != Disabled) && port_info[i].dev)
2910- enable_port(i);
2911- } else { /* STP was enabled, now disable it */
2912- for (i = One; i <= No_of_ports; i++)
2913- if (port_info[i].state != Disabled && port_info[i].dev)
2914- port_info[i].state = Forwarding;
2915- }
2916- br_stats.flags ^= BR_STP_DISABLED;
2917- break;
2918- case BRCMD_IF_ENABLE:
2919- bcf.arg1 = br_find_port(bcf.arg1);
2920- if ((signed)bcf.arg1 < 0)
2921- return(bcf.arg1);
2922- case BRCMD_PORT_ENABLE:
2923- if (port_info[bcf.arg1].dev == 0)
2924- return(-EINVAL);
2925- if (user_port_state[bcf.arg1] != Disabled)
2926- return(-EALREADY);
2927- printk(KERN_DEBUG "br: enabling port %i\n",bcf.arg1);
2928- dev = port_info[bcf.arg1].dev;
2929- ifflags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
2930- |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
2931- dev_change_flags(dev, ifflags|IFF_PROMISC);
2932- user_port_state[bcf.arg1] = ~Disabled;
2933- if(br_stats.flags & BR_UP)
2934- enable_port(bcf.arg1);
2935- break;
2936- case BRCMD_IF_DISABLE:
2937- bcf.arg1 = br_find_port(bcf.arg1);
2938- if ((signed)bcf.arg1 < 0)
2939- return(bcf.arg1);
2940- case BRCMD_PORT_DISABLE:
2941- if (port_info[bcf.arg1].dev == 0)
2942- return(-EINVAL);
2943- if (user_port_state[bcf.arg1] == Disabled)
2944- return(-EALREADY);
2945- printk(KERN_DEBUG "br: disabling port %i\n",bcf.arg1);
2946- user_port_state[bcf.arg1] = Disabled;
2947- if(br_stats.flags & BR_UP)
2948- disable_port(bcf.arg1);
2949- dev = port_info[bcf.arg1].dev;
2950- ifflags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
2951- |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
2952- dev_change_flags(port_info[bcf.arg1].dev, ifflags & ~IFF_PROMISC);
2953- break;
2954- case BRCMD_SET_BRIDGE_PRIORITY:
2955- new_id = bridge_info.bridge_id;
2956- new_id.BRIDGE_PRIORITY = htons(bcf.arg1);
2957- set_bridge_priority(&new_id);
2958- break;
2959- case BRCMD_SET_IF_PRIORITY:
2960- bcf.arg1 = br_find_port(bcf.arg1);
2961- if ((signed)bcf.arg1 < 0)
2962- return(bcf.arg1);
2963- case BRCMD_SET_PORT_PRIORITY:
2964- if((port_info[bcf.arg1].dev == 0)
2965- || (bcf.arg2 & ~0xff))
2966- return(-EINVAL);
2967- port_priority[bcf.arg1] = bcf.arg2;
2968- set_port_priority(bcf.arg1);
2969- break;
2970- case BRCMD_SET_IF_PATH_COST:
2971- bcf.arg1 = br_find_port(bcf.arg1);
2972- if ((signed)bcf.arg1 < 0)
2973- return(bcf.arg1);
2974- case BRCMD_SET_PATH_COST:
2975- if (port_info[bcf.arg1].dev == 0)
2976- return(-EINVAL);
2977- set_path_cost(bcf.arg1, bcf.arg2);
2978- break;
2979- case BRCMD_ENABLE_DEBUG:
2980- br_stats.flags |= BR_DEBUG;
2981- break;
2982- case BRCMD_DISABLE_DEBUG:
2983- br_stats.flags &= ~BR_DEBUG;
2984- break;
2985- case BRCMD_SET_POLICY:
2986- return br_set_policy(bcf.arg1);
2987- case BRCMD_EXEMPT_PROTOCOL:
2988- return br_add_exempt_protocol(bcf.arg1);
2989- case BRCMD_ENABLE_PROT_STATS:
2990- br_stats.flags |= BR_PROT_STATS;
2991- break;
2992- case BRCMD_DISABLE_PROT_STATS:
2993- br_stats.flags &= ~BR_PROT_STATS;
2994- break;
2995- case BRCMD_ZERO_PROT_STATS:
2996- memset(&br_stats.prot_id,0,sizeof(br_stats.prot_id));
2997- memset(&br_stats.prot_counter,0,sizeof(br_stats.prot_counter));
2998- break;
2999- case BRCMD_DISPLAY_FDB:
3000- {
3001- struct fdb_info_hdr *user_buf = (void*) bcf.arg1;
3002- struct fdb_info *u_fdbs, *fdbis;
3003- int copied, notcopied;
3004- u32 j = CURRENT_TIME;
3005-
3006- if(bcf.arg2<sizeof(struct fdb_info_hdr))
3007- return -EINVAL;
3008- put_user(j, &user_buf->cmd_time);
3009- if(allocated_fdb_cnt == 0)
3010- {
3011- put_user(0, &user_buf->copied);
3012- put_user(0, &user_buf->not_copied);
3013- return 0;
3014- }
3015- fdbis = get_fdb_info(bcf.arg2, &copied, &notcopied);
3016- put_user(copied, &user_buf->copied);
3017- put_user(notcopied, &user_buf->not_copied);
3018- if(!fdbis)
3019- return -ENOMEM;
3020- u_fdbs = (struct fdb_info *) (user_buf+1);
3021- err = copy_to_user(u_fdbs, fdbis, copied*sizeof(struct fdb_info));
3022- kfree(fdbis);
3023- if (err)
3024- {
3025- err = -EFAULT;
3026- }
3027- return err;
3028- }
3029- default:
3030- return -EINVAL;
3031- }
3032- return(0);
3033- default:
3034- return -EINVAL;
3035- }
3036- /*NOTREACHED*/
3037 return 0;
3038 }
3039
3040-static int br_cmp(unsigned int *a, unsigned int *b)
3041-{
3042- int i;
3043- for (i=0; i<2; i++)
3044- {
3045- /* JRP: compares prty then MAC address in memory byte order
3046- * OK optimizer does htonl() only once per long !
3047- */
3048- if (htonl(a[i]) < htonl(b[i]))
3049- return(-1);
3050- if (htonl(a[i]) > htonl(b[i]))
3051- return(1);
3052- }
3053- return(0);
3054-}
3055-
3056-
3057-
3058-
3059-/* --------------------------------------------------------------------------------
3060- *
3061- *
3062- * Bridge network device here for future modularization - device structures
3063- * must be 'static' inside bridge instance
3064- * Modelled after sch_teql.c
3065- *
3066- */
3067-
3068-
3069-
3070-/*
3071- * Index to functions.
3072- */
3073-
3074-int brg_probe(struct device *dev);
3075-static int brg_open(struct device *dev);
3076-static int brg_start_xmit(struct sk_buff *skb, struct device *dev);
3077-static int brg_close(struct device *dev);
3078-static struct net_device_stats *brg_get_stats(struct device *dev);
3079-static void brg_set_multicast_list(struct device *dev);
3080-
3081-/*
3082- * Board-specific info in dev->priv.
3083- */
3084-
3085-struct net_local
3086-{
3087- __u32 groups;
3088- struct net_device_stats stats;
3089-};
3090-
3091-
3092-
3093-
3094-/*
3095- * To call this a probe is a bit misleading, however for real
3096- * hardware it would have to check what was present.
3097- */
3098-
3099-__initfunc(int brg_probe(struct device *dev))
3100-{
3101- unsigned int bogomips;
3102- struct timeval utime;
3103-
3104- printk(KERN_INFO "%s: network interface for Ethernet Bridge 007/NET4.0\n", dev->name);
3105-
3106- /*
3107- * Initialize the device structure.
3108- */
3109-
3110- dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
3111- if (dev->priv == NULL)
3112- return -ENOMEM;
3113- memset(dev->priv, 0, sizeof(struct net_local));
3114-
3115- /* Set up MAC address based on BogoMIPs figure for first CPU and time
3116- */
3117- bogomips = (loops_per_jiffy+2500)/500000/HZ ;
3118- get_fast_time(&utime);
3119-
3120- /* Ummmm.... YES! */
3121- dev->dev_addr[0] = '\xFE';
3122- dev->dev_addr[1] = '\xFD';
3123- dev->dev_addr[2] = (bridge_info.instance & 0x0F) << 4;
3124- dev->dev_addr[2] |= ((utime.tv_sec & 0x000F0000) >> 16);
3125- dev->dev_addr[3] = bogomips & 0xFF;
3126- dev->dev_addr[4] = (utime.tv_sec & 0x0000FF00) >> 8;
3127- dev->dev_addr[5] = (utime.tv_sec & 0x000000FF);
3128-
3129- printk(KERN_INFO "%s: generated MAC address %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
3130- dev->name,
3131- dev->dev_addr[0],
3132- dev->dev_addr[1],
3133- dev->dev_addr[2],
3134- dev->dev_addr[3],
3135- dev->dev_addr[4],
3136- dev->dev_addr[5]);
3137-
3138-
3139- printk(KERN_INFO "%s: attached to bridge instance %lu\n", dev->name, dev->base_addr);
3140-
3141- /*
3142- * The brg specific entries in the device structure.
3143- */
3144-
3145- dev->open = brg_open;
3146- dev->hard_start_xmit = brg_start_xmit;
3147- dev->stop = brg_close;
3148- dev->get_stats = brg_get_stats;
3149- dev->set_multicast_list = brg_set_multicast_list;
3150-
3151- /*
3152- * Setup the generic properties
3153- */
3154-
3155- ether_setup(dev);
3156- dev->tx_queue_len = 0;
3157- return 0;
3158-}
3159-
3160-/*
3161- * Open/initialize the board.
3162- */
3163-
3164-static int brg_open(struct device *dev)
3165-{
3166- if (br_stats.flags & BR_DEBUG)
3167- printk(KERN_DEBUG "%s: Doing brg_open()...", dev->name);
3168-
3169- if (memcmp(dev->dev_addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
3170- return -EFAULT;
3171-
3172- dev->start = 1;
3173- dev->tbusy = 0;
3174- return 0;
3175-}
3176-
3177-static unsigned brg_mc_hash(__u8 *dest)
3178-{
3179- unsigned idx = 0;
3180- idx ^= dest[0];
3181- idx ^= dest[1];
3182- idx ^= dest[2];
3183- idx ^= dest[3];
3184- idx ^= dest[4];
3185- idx ^= dest[5];
3186- return 1U << (idx&0x1F);
3187-}
3188-
3189-static void brg_set_multicast_list(struct device *dev)
3190-{
3191- unsigned groups = ~0;
3192- struct net_local *lp = (struct net_local *)dev->priv;
3193-
3194- if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
3195- struct dev_mc_list *dmi;
3196-
3197- groups = brg_mc_hash(dev->broadcast);
3198-
3199- for (dmi=dev->mc_list; dmi; dmi=dmi->next) {
3200- if (dmi->dmi_addrlen != 6)
3201- continue;
3202- groups |= brg_mc_hash(dmi->dmi_addr);
3203- }
3204- }
3205- lp->groups = groups;
3206-}
3207-
3208-/*
3209- * We transmit by throwing the packet at the bridge.
3210- */
3211-
3212-static int brg_start_xmit(struct sk_buff *skb, struct device *dev)
3213-{
3214- struct net_local *lp = (struct net_local *)dev->priv;
3215- struct ethhdr *eth = (struct ethhdr*)skb->data;
3216- int port;
3217-
3218- /* Deal with the bridge being disabled */
3219- if(!(br_stats.flags & BR_UP)) {
3220- /* Either this */
3221- /* lp->stats.tx_errors++; */ /* this condition is NOT an error */
3222- /* or this (implied by RFC 2233) */
3223- lp->stats.tx_dropped++;
3224- dev_kfree_skb(skb);
3225- return 0;
3226- }
3227-
3228- lp->stats.tx_bytes+=skb->len;
3229- lp->stats.tx_packets++;
3230-
3231-#if 0
3232- ++br_stats_cnt.port_not_disable;
3233-#endif
3234- skb->mac.raw = skb->nh.raw = skb->data;
3235- eth = skb->mac.ethernet;
3236- port = 0; /* an impossible port (locally generated) */
3237-
3238- if (br_stats.flags & BR_DEBUG)
3239- printk(KERN_DEBUG "%s: brg_start_xmit - src %02x:%02x:%02x:%02x:%02x:%02x"
3240- " dest %02x:%02x:%02x:%02x:%02x:%02x\n",
3241- dev->name,
3242- eth->h_source[0],
3243- eth->h_source[1],
3244- eth->h_source[2],
3245- eth->h_source[3],
3246- eth->h_source[4],
3247- eth->h_source[5],
3248- eth->h_dest[0],
3249- eth->h_dest[1],
3250- eth->h_dest[2],
3251- eth->h_dest[3],
3252- eth->h_dest[4],
3253- eth->h_dest[5]);
3254-
3255- /* Forward the packet ! */
3256- if(br_forward(skb, port))
3257- return(0);
3258-
3259- /* Throw packet initially */
3260- dev_kfree_skb(skb);
3261- return 0;
3262-}
3263-
3264-
3265-/*
3266- * The typical workload of the driver:
3267- * Handle the ether interface interrupts.
3268- *
3269- * (In this case handle the packets posted from the bridge)
3270- */
3271-
3272-static int brg_rx(struct sk_buff *skb, int port)
3273-{
3274- struct device *dev = &brg_if.dev;
3275- struct net_local *lp = (struct net_local *)dev->priv;
3276- struct ethhdr *eth = (struct ethhdr*)(skb->data);
3277- int len = skb->len;
3278- int clone = 0;
3279-
3280- if (br_stats.flags & BR_DEBUG)
3281- printk(KERN_DEBUG "%s: brg_rx()\n", dev->name);
3282-
3283- /* Get out of here if the bridge interface is not up
3284- */
3285- if(!(dev->flags & IFF_UP))
3286- return(0);
3287-
3288- /* Check that the port that this thing came off is in the forwarding state
3289- * We sould only listen to the same address scope we will transmit to.
3290- */
3291- if(port_info[port].state != Forwarding)
3292- return(0);
3293-
3294- /* Is this for us? - broadcast/mulitcast/promiscuous packets need cloning,
3295- * with uni-cast we eat the packet
3296- */
3297- clone = 0;
3298- if (dev->flags & IFF_PROMISC) {
3299- clone = 1;
3300- }
3301- else if (eth->h_dest[0]&1) {
3302- if (!(dev->flags&(IFF_ALLMULTI))
3303- && !(brg_mc_hash(eth->h_dest)&lp->groups))
3304- return(0);
3305- clone = 1;
3306- }
3307- else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN) != 0) {
3308- return(0);
3309- }
3310-
3311- /* Clone things here - we want to be transparent before we check packet data
3312- * integrity
3313- */
3314- if(clone) {
3315- struct sk_buff *skb2 = skb;
3316- skb = skb_clone(skb2, GFP_ATOMIC);
3317- if (skb == NULL) {
3318- return(0);
3319- }
3320-
3321- }
3322- else {
3323- /* Learn source addresses for unicast non-promiscuous
3324- * frames for brg0
3325- */
3326- if(br_learn(skb, port)) {
3327- return br_drop(skb);
3328- }
3329- }
3330-
3331- /* Check packet length
3332- */
3333- if (len < 16) {
3334- printk(KERN_DEBUG "%s : rx len = %d\n", dev->name, len);
3335- kfree_skb(skb);
3336- return(!clone);
3337- }
3338-
3339- if (br_stats.flags & BR_DEBUG)
3340- printk(KERN_DEBUG "%s: brg_rx - src %02x:%02x:%02x:%02x:%02x:%02x"
3341- " dest %02x:%02x:%02x:%02x:%02x:%02x\n",
3342- dev->name,
3343- eth->h_source[0],
3344- eth->h_source[1],
3345- eth->h_source[2],
3346- eth->h_source[3],
3347- eth->h_source[4],
3348- eth->h_source[5],
3349- eth->h_dest[0],
3350- eth->h_dest[1],
3351- eth->h_dest[2],
3352- eth->h_dest[3],
3353- eth->h_dest[4],
3354- eth->h_dest[5]);
3355-
3356- /* Do it */
3357- skb->pkt_type = PACKET_HOST;
3358- skb->dev = dev;
3359- skb->protocol=eth_type_trans(skb,dev);
3360- memset(skb->cb, 0, sizeof(skb->cb));
3361- lp->stats.rx_packets++;
3362- lp->stats.rx_bytes+=len;
3363- netif_rx(skb);
3364- return(!clone);
3365-}
3366-
3367-static int brg_close(struct device *dev)
3368-{
3369- if (br_stats.flags & BR_DEBUG)
3370- printk(KERN_DEBUG "%s: Shutting down.\n", dev->name);
3371-
3372- dev->tbusy = 1;
3373- dev->start = 0;
3374-
3375- return 0;
3376-}
3377-
3378-static struct net_device_stats *brg_get_stats(struct device *dev)
3379-{
3380- struct net_local *lp = (struct net_local *)dev->priv;
3381- return &lp->stats;
3382-}
3383-
3384-/*
3385- *
3386- */
3387+#ifdef MODULE
3388+EXPORT_NO_SYMBOLS;
3389
3390-__initfunc(int brg_init(void))
3391+int init_module(void)
3392 {
3393- int err;
3394-
3395- memset(&brg_if, 0, sizeof(brg_if));
3396-
3397- rtnl_lock();
3398-
3399- brg_if.dev.base_addr = bridge_info.instance;
3400- sprintf (brg_if.name, "brg%d", bridge_info.instance);
3401- brg_if.dev.name = (void*)&brg_if.name;
3402- if(dev_get(brg_if.name)) {
3403- printk(KERN_INFO "%s already loaded.\n", brg_if.name);
3404- return -EBUSY;
3405- }
3406- brg_if.dev.init = brg_probe;
3407-
3408- err = register_netdevice(&brg_if.dev);
3409- rtnl_unlock();
3410- return err;
3411+ return br_init();
3412 }
3413
3414-
3415-#if 0 /* Its here if we ever need it... */
3416-#ifdef MODULE
3417-
3418 void cleanup_module(void)
3419 {
3420-
3421- /*
3422- * Unregister the device
3423- */
3424- rtnl_lock();
3425- unregister_netdevice(&the_master.dev);
3426- rtnl_unlock();
3427-
3428- /*
3429- * Free up the private structure.
3430- */
3431-
3432- kfree(brg_if.dev.priv);
3433- brg_if.dev.priv = NULL; /* gets re-allocated by brg_probe */
3434+ unregister_netdevice_notifier(&br_device_notifier);
3435+#ifdef CONFIG_INET
3436+ br_ioctl_hook = NULL;
3437+#endif
3438+ br_handle_frame_hook = NULL;
3439+ synchronize_bh();
3440 }
3441
3442-#endif /* MODULE */
3443-
3444 #endif
3445diff -urN linux-2.2.20/net/bridge/br_device.c linux-2.2.20br/net/bridge/br_device.c
3446--- linux-2.2.20/net/bridge/br_device.c Thu Jan 1 01:00:00 1970
3447+++ linux-2.2.20br/net/bridge/br_device.c Sat Nov 10 21:44:20 2001
3448@@ -0,0 +1,126 @@
3449+/*
3450+ * Device handling code
3451+ * Linux ethernet bridge
3452+ *
3453+ * Authors:
3454+ * Lennert Buytenhek <buytenh@gnu.org>
3455+ *
3456+ * $Id$
3457+ *
3458+ * This program is free software; you can redistribute it and/or
3459+ * modify it under the terms of the GNU General Public License
3460+ * as published by the Free Software Foundation; either version
3461+ * 2 of the License, or (at your option) any later version.
3462+ */
3463+
3464+#include <linux/config.h>
3465+#include <linux/kernel.h>
3466+#include <linux/netdevice.h>
3467+#include <linux/if_bridge.h>
3468+#include <asm/uaccess.h>
3469+#include "br_private.h"
3470+
3471+static int br_dev_do_ioctl(struct device *dev, struct ifreq *rq, int cmd)
3472+{
3473+ unsigned long args[4];
3474+ unsigned long *data;
3475+
3476+ if (cmd != SIOCDEVPRIVATE)
3477+ return -EOPNOTSUPP;
3478+
3479+ data = (unsigned long *)rq->ifr_data;
3480+ if (copy_from_user(args, data, 4*sizeof(unsigned long)))
3481+ return -EFAULT;
3482+
3483+ return br_ioctl(dev->priv, args[0], args[1], args[2], args[3]);
3484+}
3485+
3486+static struct net_device_stats *br_dev_get_stats(struct device *dev)
3487+{
3488+ struct net_bridge *br;
3489+
3490+ br = dev->priv;
3491+
3492+ return &br->statistics;
3493+}
3494+
3495+static int br_dev_xmit(struct sk_buff *skb, struct device *dev)
3496+{
3497+ struct net_bridge *br;
3498+ unsigned char *dest;
3499+ struct net_bridge_fdb_entry *dst;
3500+
3501+ br = dev->priv;
3502+ br->statistics.tx_packets++;
3503+ br->statistics.tx_bytes += skb->len;
3504+
3505+ dest = skb->data;
3506+
3507+ if (dest[0] & 1) {
3508+ br_flood(br, skb, 0);
3509+ return 0;
3510+ }
3511+
3512+ if ((dst = br_fdb_get(br, dest)) != NULL) {
3513+ br_forward(dst->dst, skb);
3514+ br_fdb_put(dst);
3515+ return 0;
3516+ }
3517+
3518+ br_flood(br, skb, 0);
3519+ return 0;
3520+}
3521+
3522+static int br_dev_open(struct device *dev)
3523+{
3524+ struct net_bridge *br;
3525+
3526+ dev->start = 1;
3527+ dev->tbusy = 0;
3528+
3529+ br = dev->priv;
3530+ read_lock(&br->lock);
3531+ br_stp_enable_bridge(br);
3532+ read_unlock(&br->lock);
3533+
3534+ return 0;
3535+}
3536+
3537+static void br_dev_set_multicast_list(struct device *dev)
3538+{
3539+}
3540+
3541+static int br_dev_stop(struct device *dev)
3542+{
3543+ struct net_bridge *br;
3544+
3545+ br = dev->priv;
3546+ read_lock(&br->lock);
3547+ br_stp_disable_bridge(br);
3548+ read_unlock(&br->lock);
3549+
3550+ dev->start = 0;
3551+ dev->tbusy = 1;
3552+
3553+ return 0;
3554+}
3555+
3556+static int br_dev_accept_fastpath(struct device *dev, struct dst_entry *dst)
3557+{
3558+ return -1;
3559+}
3560+
3561+void br_dev_setup(struct device *dev)
3562+{
3563+ memset(dev->dev_addr, 0, ETH_ALEN);
3564+
3565+ dev->do_ioctl = br_dev_do_ioctl;
3566+ dev->get_stats = br_dev_get_stats;
3567+ dev->hard_start_xmit = br_dev_xmit;
3568+ dev->open = br_dev_open;
3569+ dev->set_multicast_list = br_dev_set_multicast_list;
3570+ dev->stop = br_dev_stop;
3571+ dev->accept_fastpath = br_dev_accept_fastpath;
3572+ dev->tx_queue_len = 0;
3573+ dev->set_mac_address = NULL;
3574+}
3575diff -urN linux-2.2.20/net/bridge/br_fdb.c linux-2.2.20br/net/bridge/br_fdb.c
3576--- linux-2.2.20/net/bridge/br_fdb.c Thu Jan 1 01:00:00 1970
3577+++ linux-2.2.20br/net/bridge/br_fdb.c Sat Nov 10 21:44:20 2001
3578@@ -0,0 +1,320 @@
3579+/*
3580+ * Forwarding database
3581+ * Linux ethernet bridge
3582+ *
3583+ * Authors:
3584+ * Lennert Buytenhek <buytenh@gnu.org>
3585+ *
3586+ * $Id$
3587+ *
3588+ * This program is free software; you can redistribute it and/or
3589+ * modify it under the terms of the GNU General Public License
3590+ * as published by the Free Software Foundation; either version
3591+ * 2 of the License, or (at your option) any later version.
3592+ */
3593+
3594+#include <linux/config.h>
3595+#include <linux/kernel.h>
3596+#include <linux/if_bridge.h>
3597+#include <asm/atomic.h>
3598+#include <asm/spinlock.h>
3599+#include <asm/uaccess.h>
3600+#include "br_private.h"
3601+
3602+static __inline__ unsigned long __timeout(struct net_bridge *br)
3603+{
3604+ unsigned long timeout;
3605+
3606+ timeout = jiffies - br->ageing_time;
3607+ if (br->topology_change)
3608+ timeout = jiffies - br->forward_delay;
3609+
3610+ return timeout;
3611+}
3612+
3613+static __inline__ int has_expired(struct net_bridge *br,
3614+ struct net_bridge_fdb_entry *fdb)
3615+{
3616+ if (!fdb->is_static &&
3617+ time_before_eq(fdb->ageing_timer, __timeout(br)))
3618+ return 1;
3619+
3620+ return 0;
3621+}
3622+
3623+static __inline__ void copy_fdb(struct __fdb_entry *ent, struct net_bridge_fdb_entry *f)
3624+{
3625+ memset(ent, 0, sizeof(struct __fdb_entry));
3626+ memcpy(ent->mac_addr, f->addr.addr, ETH_ALEN);
3627+ ent->port_no = f->dst?f->dst->port_no:0;
3628+ ent->is_local = f->is_local;
3629+ ent->ageing_timer_value = 0;
3630+ if (!f->is_static)
3631+ ent->ageing_timer_value = jiffies - f->ageing_timer;
3632+}
3633+
3634+static __inline__ int br_mac_hash(unsigned char *mac)
3635+{
3636+ unsigned long x;
3637+
3638+ x = mac[0];
3639+ x = (x << 2) ^ mac[1];
3640+ x = (x << 2) ^ mac[2];
3641+ x = (x << 2) ^ mac[3];
3642+ x = (x << 2) ^ mac[4];
3643+ x = (x << 2) ^ mac[5];
3644+
3645+ x ^= x >> 8;
3646+
3647+ return x & (BR_HASH_SIZE - 1);
3648+}
3649+
3650+static __inline__ void __hash_link(struct net_bridge *br,
3651+ struct net_bridge_fdb_entry *ent,
3652+ int hash)
3653+{
3654+ ent->next_hash = br->hash[hash];
3655+ if (ent->next_hash != NULL)
3656+ ent->next_hash->pprev_hash = &ent->next_hash;
3657+ br->hash[hash] = ent;
3658+ ent->pprev_hash = &br->hash[hash];
3659+}
3660+
3661+static __inline__ void __hash_unlink(struct net_bridge_fdb_entry *ent)
3662+{
3663+ *(ent->pprev_hash) = ent->next_hash;
3664+ if (ent->next_hash != NULL)
3665+ ent->next_hash->pprev_hash = ent->pprev_hash;
3666+ ent->next_hash = NULL;
3667+ ent->pprev_hash = NULL;
3668+}
3669+
3670+
3671+
3672+void br_fdb_changeaddr(struct net_bridge_port *p, unsigned char *newaddr)
3673+{
3674+ struct net_bridge *br;
3675+ int i;
3676+
3677+ br = p->br;
3678+ write_lock_bh(&br->hash_lock);
3679+ for (i=0;i<BR_HASH_SIZE;i++) {
3680+ struct net_bridge_fdb_entry *f;
3681+
3682+ f = br->hash[i];
3683+ while (f != NULL) {
3684+ if (f->dst == p && f->is_local) {
3685+ __hash_unlink(f);
3686+ memcpy(f->addr.addr, newaddr, ETH_ALEN);
3687+ __hash_link(br, f, br_mac_hash(newaddr));
3688+ write_unlock_bh(&br->hash_lock);
3689+ return;
3690+ }
3691+ f = f->next_hash;
3692+ }
3693+ }
3694+ write_unlock_bh(&br->hash_lock);
3695+}
3696+
3697+void br_fdb_cleanup(struct net_bridge *br)
3698+{
3699+ int i;
3700+ unsigned long timeout;
3701+
3702+ timeout = __timeout(br);
3703+
3704+ write_lock_bh(&br->hash_lock);
3705+ for (i=0;i<BR_HASH_SIZE;i++) {
3706+ struct net_bridge_fdb_entry *f;
3707+
3708+ f = br->hash[i];
3709+ while (f != NULL) {
3710+ struct net_bridge_fdb_entry *g;
3711+
3712+ g = f->next_hash;
3713+ if (!f->is_static &&
3714+ time_before_eq(f->ageing_timer, timeout)) {
3715+ __hash_unlink(f);
3716+ br_fdb_put(f);
3717+ }
3718+ f = g;
3719+ }
3720+ }
3721+ write_unlock_bh(&br->hash_lock);
3722+}
3723+
3724+void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
3725+{
3726+ int i;
3727+
3728+ write_lock_bh(&br->hash_lock);
3729+ for (i=0;i<BR_HASH_SIZE;i++) {
3730+ struct net_bridge_fdb_entry *f;
3731+
3732+ f = br->hash[i];
3733+ while (f != NULL) {
3734+ struct net_bridge_fdb_entry *g;
3735+
3736+ g = f->next_hash;
3737+ if (f->dst == p) {
3738+ __hash_unlink(f);
3739+ br_fdb_put(f);
3740+ }
3741+ f = g;
3742+ }
3743+ }
3744+ write_unlock_bh(&br->hash_lock);
3745+}
3746+
3747+struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, unsigned char *addr)
3748+{
3749+ struct net_bridge_fdb_entry *fdb;
3750+
3751+ read_lock_bh(&br->hash_lock);
3752+ fdb = br->hash[br_mac_hash(addr)];
3753+ while (fdb != NULL) {
3754+ if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
3755+ if (!has_expired(br, fdb)) {
3756+ atomic_inc(&fdb->use_count);
3757+ read_unlock_bh(&br->hash_lock);
3758+ return fdb;
3759+ }
3760+
3761+ read_unlock_bh(&br->hash_lock);
3762+ return NULL;
3763+ }
3764+
3765+ fdb = fdb->next_hash;
3766+ }
3767+
3768+ read_unlock_bh(&br->hash_lock);
3769+ return NULL;
3770+}
3771+
3772+void br_fdb_put(struct net_bridge_fdb_entry *ent)
3773+{
3774+ if (atomic_dec_and_test(&ent->use_count))
3775+ kfree(ent);
3776+}
3777+
3778+int br_fdb_get_entries(struct net_bridge *br,
3779+ unsigned char *_buf,
3780+ int maxnum,
3781+ int offset)
3782+{
3783+ int i;
3784+ int num;
3785+ struct __fdb_entry *walk;
3786+
3787+ num = 0;
3788+ walk = (struct __fdb_entry *)_buf;
3789+
3790+ read_lock_bh(&br->hash_lock);
3791+ for (i=0;i<BR_HASH_SIZE;i++) {
3792+ struct net_bridge_fdb_entry *f;
3793+
3794+ f = br->hash[i];
3795+ while (f != NULL && num < maxnum) {
3796+ struct __fdb_entry ent;
3797+ int err;
3798+ struct net_bridge_fdb_entry *g;
3799+
3800+ if (has_expired(br, f)) {
3801+ f = f->next_hash;
3802+ continue;
3803+ }
3804+
3805+ if (offset) {
3806+ offset--;
3807+ f = f->next_hash;
3808+ continue;
3809+ }
3810+
3811+ copy_fdb(&ent, f);
3812+
3813+ atomic_inc(&f->use_count);
3814+ read_unlock_bh(&br->hash_lock);
3815+ err = copy_to_user(walk, &ent, sizeof(struct __fdb_entry));
3816+ read_lock_bh(&br->hash_lock);
3817+
3818+ g = f->next_hash;
3819+ br_fdb_put(f);
3820+
3821+ if (err)
3822+ goto out_fault;
3823+
3824+ if (f->next_hash == NULL &&
3825+ f->pprev_hash == NULL)
3826+ goto out_disappeared;
3827+
3828+ num++;
3829+ walk++;
3830+
3831+ f = g;
3832+ }
3833+ }
3834+
3835+ out:
3836+ read_unlock_bh(&br->hash_lock);
3837+ return num;
3838+
3839+ out_disappeared:
3840+ num = -EAGAIN;
3841+ goto out;
3842+
3843+ out_fault:
3844+ num = -EFAULT;
3845+ goto out;
3846+}
3847+
3848+static __inline__ void __fdb_possibly_replace(struct net_bridge_fdb_entry *fdb,
3849+ struct net_bridge_port *source,
3850+ int is_local)
3851+{
3852+ if (!fdb->is_static || is_local) {
3853+ fdb->dst = source;
3854+ fdb->is_local = is_local;
3855+ fdb->is_static = is_local;
3856+ fdb->ageing_timer = jiffies;
3857+ }
3858+}
3859+
3860+void br_fdb_insert(struct net_bridge *br,
3861+ struct net_bridge_port *source,
3862+ unsigned char *addr,
3863+ int is_local)
3864+{
3865+ struct net_bridge_fdb_entry *fdb;
3866+ int hash;
3867+
3868+ hash = br_mac_hash(addr);
3869+
3870+ write_lock_bh(&br->hash_lock);
3871+ fdb = br->hash[hash];
3872+ while (fdb != NULL) {
3873+ if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
3874+ __fdb_possibly_replace(fdb, source, is_local);
3875+ write_unlock_bh(&br->hash_lock);
3876+ return;
3877+ }
3878+
3879+ fdb = fdb->next_hash;
3880+ }
3881+
3882+ fdb = kmalloc(sizeof(*fdb), GFP_ATOMIC);
3883+ if (fdb == NULL) {
3884+ write_unlock_bh(&br->hash_lock);
3885+ return;
3886+ }
3887+
3888+ memcpy(fdb->addr.addr, addr, ETH_ALEN);
3889+ atomic_set(&fdb->use_count, 1);
3890+ fdb->dst = source;
3891+ fdb->is_local = is_local;
3892+ fdb->is_static = is_local;
3893+ fdb->ageing_timer = jiffies;
3894+
3895+ __hash_link(br, fdb, hash);
3896+
3897+ write_unlock_bh(&br->hash_lock);
3898+}
3899diff -urN linux-2.2.20/net/bridge/br_forward.c linux-2.2.20br/net/bridge/br_forward.c
3900--- linux-2.2.20/net/bridge/br_forward.c Thu Jan 1 01:00:00 1970
3901+++ linux-2.2.20br/net/bridge/br_forward.c Sat Nov 10 21:44:20 2001
3902@@ -0,0 +1,98 @@
3903+/*
3904+ * Forwarding decision
3905+ * Linux ethernet bridge
3906+ *
3907+ * Authors:
3908+ * Lennert Buytenhek <buytenh@gnu.org>
3909+ *
3910+ * $Id$
3911+ *
3912+ * This program is free software; you can redistribute it and/or
3913+ * modify it under the terms of the GNU General Public License
3914+ * as published by the Free Software Foundation; either version
3915+ * 2 of the License, or (at your option) any later version.
3916+ */
3917+
3918+#include <linux/config.h>
3919+#include <linux/kernel.h>
3920+#include <linux/netdevice.h>
3921+#include <linux/inetdevice.h>
3922+#include <linux/skbuff.h>
3923+#include <linux/firewall.h>
3924+#include <linux/if_bridge.h>
3925+#include "br_private.h"
3926+
3927+static inline int should_forward(struct net_bridge_port *p, struct sk_buff *skb)
3928+{
3929+ if (skb->dev != p->dev && p->state == BR_STATE_FORWARDING)
3930+ return 1;
3931+
3932+ return 0;
3933+}
3934+
3935+static void __br_forward(struct net_bridge_port *to, struct sk_buff *skb)
3936+{
3937+ skb->dev = to->dev;
3938+ dev_queue_xmit(skb);
3939+}
3940+
3941+void br_forward(struct net_bridge_port *to, struct sk_buff *skb)
3942+{
3943+ if (should_forward(to, skb)) {
3944+ __br_forward(to, skb);
3945+ return;
3946+ }
3947+
3948+ kfree_skb(skb);
3949+}
3950+
3951+void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone)
3952+{
3953+ struct net_bridge_port *p;
3954+ struct net_bridge_port *prev;
3955+
3956+ if (clone) {
3957+ struct sk_buff *skb2;
3958+
3959+ if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
3960+ br->statistics.tx_dropped++;
3961+ return;
3962+ }
3963+
3964+ skb = skb2;
3965+ }
3966+
3967+ prev = NULL;
3968+
3969+ read_lock(&br->lock);
3970+ p = br->port_list;
3971+ while (p != NULL) {
3972+ if (should_forward(p, skb)) {
3973+ if (prev != NULL) {
3974+ struct sk_buff *skb2;
3975+
3976+ if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
3977+ br->statistics.tx_dropped++;
3978+ kfree_skb(skb);
3979+ read_unlock(&br->lock);
3980+ return;
3981+ }
3982+
3983+ __br_forward(prev, skb2);
3984+ }
3985+
3986+ prev = p;
3987+ }
3988+
3989+ p = p->next;
3990+ }
3991+
3992+ if (prev != NULL) {
3993+ __br_forward(prev, skb);
3994+ read_unlock(&br->lock);
3995+ return;
3996+ }
3997+
3998+ read_unlock(&br->lock);
3999+ kfree_skb(skb);
4000+}
4001diff -urN linux-2.2.20/net/bridge/br_if.c linux-2.2.20br/net/bridge/br_if.c
4002--- linux-2.2.20/net/bridge/br_if.c Thu Jan 1 01:00:00 1970
4003+++ linux-2.2.20br/net/bridge/br_if.c Sat Nov 10 21:44:20 2001
4004@@ -0,0 +1,296 @@
4005+/*
4006+ * Userspace interface
4007+ * Linux ethernet bridge
4008+ *
4009+ * Authors:
4010+ * Lennert Buytenhek <buytenh@gnu.org>
4011+ *
4012+ * $Id$
4013+ *
4014+ * This program is free software; you can redistribute it and/or
4015+ * modify it under the terms of the GNU General Public License
4016+ * as published by the Free Software Foundation; either version
4017+ * 2 of the License, or (at your option) any later version.
4018+ */
4019+
4020+#include <linux/config.h>
4021+#include <linux/kernel.h>
4022+#include <linux/if_arp.h>
4023+#include <linux/if_bridge.h>
4024+#include <linux/inetdevice.h>
4025+#include <asm/uaccess.h>
4026+#include "br_private.h"
4027+
4028+static struct net_bridge *bridge_list;
4029+
4030+static int br_initial_port_cost(struct device *dev)
4031+{
4032+ if (!strncmp(dev->name, "lec", 3))
4033+ return 7;
4034+
4035+ if (!strncmp(dev->name, "eth", 3))
4036+ return 100; /* FIXME handle 100Mbps */
4037+
4038+ if (!strncmp(dev->name, "plip", 4))
4039+ return 2500;
4040+
4041+ return 100;
4042+}
4043+
4044+/* called under bridge lock */
4045+static int __br_del_if(struct net_bridge *br, struct device *dev)
4046+{
4047+ struct net_bridge_port *p;
4048+ struct net_bridge_port **pptr;
4049+
4050+ if ((p = dev->br_port) == NULL)
4051+ return -EINVAL;
4052+
4053+ br_stp_disable_port(p);
4054+
4055+ dev_set_promiscuity(dev, -1);
4056+ if (dev->ip_ptr != NULL) {
4057+ struct in_device *idev = dev->ip_ptr;
4058+ idev->cnf.hidden = 0;
4059+ }
4060+
4061+ dev->br_port = NULL;
4062+
4063+ pptr = &br->port_list;
4064+ while (*pptr != NULL) {
4065+ if (*pptr == p) {
4066+ *pptr = p->next;
4067+ break;
4068+ }
4069+
4070+ pptr = &((*pptr)->next);
4071+ }
4072+
4073+ br_fdb_delete_by_port(br, p);
4074+ kfree(p);
4075+
4076+ return 0;
4077+}
4078+
4079+static struct net_bridge **__find_br(char *name)
4080+{
4081+ struct net_bridge **b;
4082+ struct net_bridge *br;
4083+
4084+ b = &bridge_list;
4085+ while ((br = *b) != NULL) {
4086+ if (!strncmp(br->name, name, IFNAMSIZ))
4087+ return b;
4088+
4089+ b = &(br->next);
4090+ }
4091+
4092+ return NULL;
4093+}
4094+
4095+static void del_ifs(struct net_bridge *br)
4096+{
4097+ write_lock_bh(&br->lock);
4098+ while (br->port_list != NULL)
4099+ __br_del_if(br, br->port_list->dev);
4100+ write_unlock_bh(&br->lock);
4101+}
4102+
4103+static struct net_bridge *new_nb(char *name)
4104+{
4105+ struct net_bridge *br;
4106+ struct device *dev;
4107+
4108+ if ((br = kmalloc(sizeof(*br), GFP_KERNEL)) == NULL)
4109+ return NULL;
4110+
4111+ memset(br, 0, sizeof(*br));
4112+ dev = &br->dev;
4113+
4114+ strncpy(br->name, name, IFNAMSIZ);
4115+ dev->priv = br;
4116+ dev->name = br->name;
4117+ ether_setup(dev);
4118+ br_dev_setup(dev);
4119+
4120+ br->lock = RW_LOCK_UNLOCKED;
4121+ br->hash_lock = RW_LOCK_UNLOCKED;
4122+
4123+ br->bridge_id.prio[0] = 0x80;
4124+ br->bridge_id.prio[1] = 0x00;
4125+ memset(br->bridge_id.addr, 0, ETH_ALEN);
4126+
4127+ br->stp_enabled = 1;
4128+ br->designated_root = br->bridge_id;
4129+ br->root_path_cost = 0;
4130+ br->root_port = 0;
4131+ br->bridge_max_age = br->max_age = 20 * HZ;
4132+ br->bridge_hello_time = br->hello_time = 2 * HZ;
4133+ br->bridge_forward_delay = br->forward_delay = 15 * HZ;
4134+ br->topology_change = 0;
4135+ br->topology_change_detected = 0;
4136+ br_timer_clear(&br->hello_timer);
4137+ br_timer_clear(&br->tcn_timer);
4138+ br_timer_clear(&br->topology_change_timer);
4139+
4140+ br->ageing_time = 300 * HZ;
4141+ br->gc_interval = 4 * HZ;
4142+
4143+ return br;
4144+}
4145+
4146+/* called under bridge lock */
4147+static struct net_bridge_port *new_nbp(struct net_bridge *br, struct device *dev)
4148+{
4149+ int i;
4150+ struct net_bridge_port *p;
4151+
4152+ p = kmalloc(sizeof(*p), GFP_KERNEL);
4153+ if (p == NULL)
4154+ return p;
4155+
4156+ memset(p, 0, sizeof(*p));
4157+ p->br = br;
4158+ p->dev = dev;
4159+ p->path_cost = br_initial_port_cost(dev);
4160+ p->priority = 0x80;
4161+
4162+ dev->br_port = p;
4163+
4164+ for (i=1;i<255;i++)
4165+ if (br_get_port(br, i) == NULL)
4166+ break;
4167+
4168+ if (i == 255) {
4169+ kfree(p);
4170+ return NULL;
4171+ }
4172+
4173+ p->port_no = i;
4174+ br_init_port(p);
4175+ p->state = BR_STATE_DISABLED;
4176+
4177+ p->next = br->port_list;
4178+ br->port_list = p;
4179+
4180+ return p;
4181+}
4182+
4183+int br_add_bridge(char *name)
4184+{
4185+ struct net_bridge *br;
4186+
4187+ if ((br = new_nb(name)) == NULL)
4188+ return -ENOMEM;
4189+
4190+ if (dev_get(name) != NULL) {
4191+ kfree(br);
4192+ return -EEXIST;
4193+ }
4194+
4195+ br->next = bridge_list;
4196+ bridge_list = br;
4197+
4198+ br_inc_use_count();
4199+ register_netdevice(&br->dev);
4200+
4201+ return 0;
4202+}
4203+
4204+int br_del_bridge(char *name)
4205+{
4206+ struct net_bridge **b;
4207+ struct net_bridge *br;
4208+
4209+ if ((b = __find_br(name)) == NULL)
4210+ return -ENXIO;
4211+
4212+ br = *b;
4213+
4214+ if (br->dev.flags & IFF_UP)
4215+ return -EBUSY;
4216+
4217+ del_ifs(br);
4218+
4219+ *b = br->next;
4220+
4221+ unregister_netdevice(&br->dev);
4222+ kfree(br);
4223+ br_dec_use_count();
4224+
4225+ return 0;
4226+}
4227+
4228+int br_add_if(struct net_bridge *br, struct device *dev)
4229+{
4230+ struct net_bridge_port *p;
4231+
4232+ if (dev->br_port != NULL)
4233+ return -EBUSY;
4234+
4235+ if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
4236+ return -EINVAL;
4237+
4238+ write_lock_bh(&br->lock);
4239+ if ((p = new_nbp(br, dev)) == NULL) {
4240+ write_unlock_bh(&br->lock);
4241+ return -EXFULL;
4242+ }
4243+
4244+ if (dev->ip_ptr != NULL) {
4245+ struct in_device *idev = dev->ip_ptr;
4246+ idev->cnf.hidden = 1;
4247+ }
4248+ dev_set_promiscuity(dev, 1);
4249+
4250+ br_stp_recalculate_bridge_id(br);
4251+ br_fdb_insert(br, p, dev->dev_addr, 1);
4252+ if ((br->dev.flags & IFF_UP) && (dev->flags & IFF_UP))
4253+ br_stp_enable_port(p);
4254+ write_unlock_bh(&br->lock);
4255+
4256+ return 0;
4257+}
4258+
4259+int br_del_if(struct net_bridge *br, struct device *dev)
4260+{
4261+ int retval;
4262+
4263+ write_lock_bh(&br->lock);
4264+ retval = __br_del_if(br, dev);
4265+ br_stp_recalculate_bridge_id(br);
4266+ write_unlock_bh(&br->lock);
4267+
4268+ return retval;
4269+}
4270+
4271+int br_get_bridge_ifindices(int *indices, int num)
4272+{
4273+ struct net_bridge *br;
4274+ int i;
4275+
4276+ i = 0;
4277+
4278+ br = bridge_list;
4279+ for (i=0;i<num;i++) {
4280+ if (br == NULL)
4281+ break;
4282+
4283+ indices[i] = br->dev.ifindex;
4284+ br = br->next;
4285+ }
4286+
4287+ return i;
4288+}
4289+
4290+/* called under ioctl_lock */
4291+void br_get_port_ifindices(struct net_bridge *br, int *ifindices)
4292+{
4293+ struct net_bridge_port *p;
4294+
4295+ p = br->port_list;
4296+ while (p != NULL) {
4297+ ifindices[p->port_no] = p->dev->ifindex;
4298+ p = p->next;
4299+ }
4300+}
4301diff -urN linux-2.2.20/net/bridge/br_input.c linux-2.2.20br/net/bridge/br_input.c
4302--- linux-2.2.20/net/bridge/br_input.c Thu Jan 1 01:00:00 1970
4303+++ linux-2.2.20br/net/bridge/br_input.c Sat Nov 10 21:44:20 2001
4304@@ -0,0 +1,135 @@
4305+/*
4306+ * Handle incoming frames
4307+ * Linux ethernet bridge
4308+ *
4309+ * Authors:
4310+ * Lennert Buytenhek <buytenh@gnu.org>
4311+ *
4312+ * $Id$
4313+ *
4314+ * This program is free software; you can redistribute it and/or
4315+ * modify it under the terms of the GNU General Public License
4316+ * as published by the Free Software Foundation; either version
4317+ * 2 of the License, or (at your option) any later version.
4318+ *
4319+ * Changes: 2000/02/03 [AF] Arne Fitzenreiter <arne.fitzenreiter@gmx.de>
4320+ * Bugfix - Multicast & Promiscious Mode
4321+ *
4322+ */
4323+
4324+#include <linux/config.h>
4325+#include <linux/kernel.h>
4326+#include <linux/netdevice.h>
4327+#include <linux/etherdevice.h>
4328+#include <linux/if_bridge.h>
4329+#include "br_private.h"
4330+
4331+unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
4332+
4333+static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
4334+{
4335+ br->statistics.rx_packets++;
4336+ br->statistics.rx_bytes += skb->len;
4337+
4338+ skb->dev = &br->dev;
4339+ skb->pkt_type = PACKET_HOST;
4340+ skb_pull(skb, skb->mac.raw - skb->data);
4341+ skb->protocol = eth_type_trans(skb, &br->dev);
4342+ netif_rx(skb);
4343+}
4344+
4345+void br_handle_frame(struct sk_buff *skb)
4346+{
4347+ struct net_bridge *br;
4348+ unsigned char *dest;
4349+ struct net_bridge_fdb_entry *dst;
4350+ struct net_bridge_port *p;
4351+ int passedup;
4352+
4353+ dest = skb->mac.ethernet->h_dest;
4354+
4355+ p = skb->dev->br_port;
4356+ br = p->br;
4357+ passedup = 0;
4358+
4359+ if (!(br->dev.flags & IFF_UP) ||
4360+ p->state == BR_STATE_DISABLED)
4361+ goto freeandout;
4362+
4363+ skb_push(skb, skb->data - skb->mac.raw);
4364+
4365+ if (br->dev.flags & IFF_PROMISC) {
4366+ struct sk_buff *skb2;
4367+
4368+ skb2 = skb_clone(skb, GFP_ATOMIC);
4369+ if (skb2) {
4370+ passedup = 1;
4371+ br_pass_frame_up(br, skb2);
4372+ }
4373+ }
4374+
4375+ if (skb->mac.ethernet->h_source[0] & 1)
4376+ goto freeandout;
4377+
4378+ if (!passedup &&
4379+ (dest[0] & 1) &&
4380+ (br->dev.flags & IFF_ALLMULTI || br->dev.mc_list != NULL)) {
4381+ struct sk_buff *skb2;
4382+
4383+ skb2 = skb_clone(skb, GFP_ATOMIC);
4384+ if (skb2) {
4385+ passedup = 1;
4386+ br_pass_frame_up(br, skb2);
4387+ }
4388+ }
4389+
4390+ if (br->stp_enabled &&
4391+ !memcmp(dest, bridge_ula, 5) &&
4392+ !(dest[5] & 0xF0))
4393+ goto handle_special_frame;
4394+
4395+ if (p->state == BR_STATE_LEARNING ||
4396+ p->state == BR_STATE_FORWARDING)
4397+ br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0);
4398+
4399+ if (p->state != BR_STATE_FORWARDING)
4400+ goto freeandout;
4401+
4402+ if (dest[0] & 1) {
4403+ br_flood(br, skb, 1);
4404+ if (!passedup)
4405+ br_pass_frame_up(br, skb);
4406+ else
4407+ kfree_skb(skb);
4408+ return;
4409+ }
4410+
4411+ dst = br_fdb_get(br, dest);
4412+
4413+ if (dst != NULL && dst->is_local) {
4414+ if (!passedup)
4415+ br_pass_frame_up(br, skb);
4416+ else
4417+ kfree_skb(skb);
4418+ br_fdb_put(dst);
4419+ return;
4420+ }
4421+
4422+ if (dst != NULL) {
4423+ br_forward(dst->dst, skb);
4424+ br_fdb_put(dst);
4425+ return;
4426+ }
4427+
4428+ br_flood(br, skb, 0);
4429+ return;
4430+
4431+ handle_special_frame:
4432+ if (!dest[5]) {
4433+ br_stp_handle_bpdu(skb);
4434+ return;
4435+ }
4436+
4437+ freeandout:
4438+ kfree_skb(skb);
4439+}
4440diff -urN linux-2.2.20/net/bridge/br_ioctl.c linux-2.2.20br/net/bridge/br_ioctl.c
4441--- linux-2.2.20/net/bridge/br_ioctl.c Thu Jan 1 01:00:00 1970
4442+++ linux-2.2.20br/net/bridge/br_ioctl.c Sat Nov 10 21:44:20 2001
4443@@ -0,0 +1,264 @@
4444+/*
4445+ * Ioctl handler
4446+ * Linux ethernet bridge
4447+ *
4448+ * Authors:
4449+ * Lennert Buytenhek <buytenh@gnu.org>
4450+ *
4451+ * $Id$
4452+ *
4453+ * This program is free software; you can redistribute it and/or
4454+ * modify it under the terms of the GNU General Public License
4455+ * as published by the Free Software Foundation; either version
4456+ * 2 of the License, or (at your option) any later version.
4457+ */
4458+
4459+#include <linux/config.h>
4460+#include <linux/kernel.h>
4461+#include <linux/if_bridge.h>
4462+#include <linux/inetdevice.h>
4463+#include <asm/uaccess.h>
4464+#include "br_private.h"
4465+
4466+static int br_ioctl_device(struct net_bridge *br,
4467+ unsigned int cmd,
4468+ unsigned long arg0,
4469+ unsigned long arg1,
4470+ unsigned long arg2)
4471+{
4472+ if (br == NULL)
4473+ return -EINVAL;
4474+
4475+ switch (cmd)
4476+ {
4477+ case BRCTL_ADD_IF:
4478+ case BRCTL_DEL_IF:
4479+ {
4480+ struct device *dev;
4481+
4482+ dev = dev_get_by_index(arg0);
4483+ if (dev == NULL)
4484+ return -EINVAL;
4485+
4486+ if (cmd == BRCTL_ADD_IF)
4487+ return br_add_if(br, dev);
4488+
4489+ return br_del_if(br, dev);
4490+ }
4491+
4492+ case BRCTL_GET_BRIDGE_INFO:
4493+ {
4494+ struct __bridge_info b;
4495+
4496+ memset(&b, 0, sizeof(struct __bridge_info));
4497+ memcpy(&b.designated_root, &br->designated_root, 8);
4498+ memcpy(&b.bridge_id, &br->bridge_id, 8);
4499+ b.root_path_cost = br->root_path_cost;
4500+ b.max_age = br->max_age;
4501+ b.hello_time = br->hello_time;
4502+ b.forward_delay = br->forward_delay;
4503+ b.bridge_max_age = br->bridge_max_age;
4504+ b.bridge_hello_time = br->bridge_hello_time;
4505+ b.bridge_forward_delay = br->bridge_forward_delay;
4506+ b.topology_change = br->topology_change;
4507+ b.topology_change_detected = br->topology_change_detected;
4508+ b.root_port = br->root_port;
4509+ b.stp_enabled = br->stp_enabled;
4510+ b.ageing_time = br->ageing_time;
4511+ b.gc_interval = br->gc_interval;
4512+ b.hello_timer_value = br_timer_get_residue(&br->hello_timer);
4513+ b.tcn_timer_value = br_timer_get_residue(&br->tcn_timer);
4514+ b.topology_change_timer_value = br_timer_get_residue(&br->topology_change_timer);
4515+ b.gc_timer_value = br_timer_get_residue(&br->gc_timer);
4516+
4517+ if (copy_to_user((void *)arg0, &b, sizeof(b)))
4518+ return -EFAULT;
4519+
4520+ return 0;
4521+ }
4522+
4523+ case BRCTL_GET_PORT_LIST:
4524+ {
4525+ int i;
4526+ int indices[256];
4527+
4528+ for (i=0;i<256;i++)
4529+ indices[i] = 0;
4530+
4531+ br_get_port_ifindices(br, indices);
4532+ if (copy_to_user((void *)arg0, indices, 256*sizeof(int)))
4533+ return -EFAULT;
4534+
4535+ return 0;
4536+ }
4537+
4538+ case BRCTL_SET_BRIDGE_FORWARD_DELAY:
4539+ br->bridge_forward_delay = arg0;
4540+ if (br_is_root_bridge(br))
4541+ br->forward_delay = arg0;
4542+ return 0;
4543+
4544+ case BRCTL_SET_BRIDGE_HELLO_TIME:
4545+ br->bridge_hello_time = arg0;
4546+ if (br_is_root_bridge(br))
4547+ br->hello_time = arg0;
4548+ return 0;
4549+
4550+ case BRCTL_SET_BRIDGE_MAX_AGE:
4551+ br->bridge_max_age = arg0;
4552+ if (br_is_root_bridge(br))
4553+ br->max_age = arg0;
4554+ return 0;
4555+
4556+ case BRCTL_SET_AGEING_TIME:
4557+ br->ageing_time = arg0;
4558+ return 0;
4559+
4560+ case BRCTL_SET_GC_INTERVAL:
4561+ br->gc_interval = arg0;
4562+ return 0;
4563+
4564+ case BRCTL_GET_PORT_INFO:
4565+ {
4566+ struct __port_info p;
4567+ struct net_bridge_port *pt;
4568+
4569+ if ((pt = br_get_port(br, arg1)) == NULL)
4570+ return -EINVAL;
4571+
4572+ memset(&p, 0, sizeof(struct __port_info));
4573+ memcpy(&p.designated_root, &pt->designated_root, 8);
4574+ memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
4575+ p.port_id = pt->port_id;
4576+ p.designated_port = pt->designated_port;
4577+ p.path_cost = pt->path_cost;
4578+ p.designated_cost = pt->designated_cost;
4579+ p.state = pt->state;
4580+ p.top_change_ack = pt->topology_change_ack;
4581+ p.config_pending = pt->config_pending;
4582+ p.message_age_timer_value = br_timer_get_residue(&pt->message_age_timer);
4583+ p.forward_delay_timer_value = br_timer_get_residue(&pt->forward_delay_timer);
4584+ p.hold_timer_value = br_timer_get_residue(&pt->hold_timer);
4585+
4586+ if (copy_to_user((void *)arg0, &p, sizeof(p)))
4587+ return -EFAULT;
4588+
4589+ return 0;
4590+ }
4591+
4592+ case BRCTL_SET_BRIDGE_STP_STATE:
4593+ br->stp_enabled = arg0?1:0;
4594+ return 0;
4595+
4596+ case BRCTL_SET_BRIDGE_PRIORITY:
4597+ br_stp_set_bridge_priority(br, arg0);
4598+ return 0;
4599+
4600+ case BRCTL_SET_PORT_PRIORITY:
4601+ {
4602+ struct net_bridge_port *p;
4603+
4604+ if ((p = br_get_port(br, arg0)) == NULL)
4605+ return -EINVAL;
4606+ br_stp_set_port_priority(p, arg1);
4607+ return 0;
4608+ }
4609+
4610+ case BRCTL_SET_PATH_COST:
4611+ {
4612+ struct net_bridge_port *p;
4613+
4614+ if ((p = br_get_port(br, arg0)) == NULL)
4615+ return -EINVAL;
4616+ br_stp_set_path_cost(p, arg1);
4617+ return 0;
4618+ }
4619+
4620+ case BRCTL_GET_FDB_ENTRIES:
4621+ return br_fdb_get_entries(br, (void *)arg0, arg1, arg2);
4622+ }
4623+
4624+ return -EOPNOTSUPP;
4625+}
4626+
4627+static int br_ioctl_deviceless(unsigned int cmd,
4628+ unsigned long arg0,
4629+ unsigned long arg1)
4630+{
4631+ switch (cmd)
4632+ {
4633+ case BRCTL_GET_VERSION:
4634+ return BRCTL_VERSION;
4635+
4636+ case BRCTL_GET_BRIDGES:
4637+ {
4638+ int i;
4639+ int indices[64];
4640+
4641+ for (i=0;i<64;i++)
4642+ indices[i] = 0;
4643+
4644+ if (arg1 > 64)
4645+ arg1 = 64;
4646+ arg1 = br_get_bridge_ifindices(indices, arg1);
4647+ if (copy_to_user((void *)arg0, indices, arg1*sizeof(int)))
4648+ return -EFAULT;
4649+
4650+ return arg1;
4651+ }
4652+
4653+ case BRCTL_ADD_BRIDGE:
4654+ case BRCTL_DEL_BRIDGE:
4655+ {
4656+ char buf[IFNAMSIZ];
4657+
4658+ if (copy_from_user(buf, (void *)arg0, IFNAMSIZ))
4659+ return -EFAULT;
4660+
4661+ buf[IFNAMSIZ-1] = 0;
4662+
4663+ if (cmd == BRCTL_ADD_BRIDGE)
4664+ return br_add_bridge(buf);
4665+
4666+ return br_del_bridge(buf);
4667+ }
4668+ }
4669+
4670+ return -EOPNOTSUPP;
4671+}
4672+
4673+static struct semaphore ioctl_mutex = MUTEX;
4674+
4675+int br_ioctl_deviceless_stub(unsigned long arg)
4676+{
4677+ int err;
4678+ unsigned long i[3];
4679+
4680+ if (!capable(CAP_NET_ADMIN))
4681+ return -EPERM;
4682+
4683+ if (copy_from_user(i, (void *)arg, 3*sizeof(unsigned long)))
4684+ return -EFAULT;
4685+
4686+ down(&ioctl_mutex);
4687+ err = br_ioctl_deviceless(i[0], i[1], i[2]);
4688+ up(&ioctl_mutex);
4689+
4690+ return err;
4691+}
4692+
4693+int br_ioctl(struct net_bridge *br, unsigned int cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2)
4694+{
4695+ int err;
4696+
4697+ if (!capable(CAP_NET_ADMIN))
4698+ return -EPERM;
4699+
4700+ down(&ioctl_mutex);
4701+ err = br_ioctl_deviceless(cmd, arg0, arg1);
4702+ if (err == -EOPNOTSUPP)
4703+ err = br_ioctl_device(br, cmd, arg0, arg1, arg2);
4704+ up(&ioctl_mutex);
4705+
4706+ return err;
4707+}
4708diff -urN linux-2.2.20/net/bridge/br_notify.c linux-2.2.20br/net/bridge/br_notify.c
4709--- linux-2.2.20/net/bridge/br_notify.c Thu Jan 1 01:00:00 1970
4710+++ linux-2.2.20br/net/bridge/br_notify.c Sat Nov 10 21:44:20 2001
4711@@ -0,0 +1,76 @@
4712+/*
4713+ * Device event handling
4714+ * Linux ethernet bridge
4715+ *
4716+ * Authors:
4717+ * Lennert Buytenhek <buytenh@gnu.org>
4718+ *
4719+ * $Id$
4720+ *
4721+ * This program is free software; you can redistribute it and/or
4722+ * modify it under the terms of the GNU General Public License
4723+ * as published by the Free Software Foundation; either version
4724+ * 2 of the License, or (at your option) any later version.
4725+ */
4726+
4727+#include <linux/config.h>
4728+#include <linux/kernel.h>
4729+#include <linux/if_bridge.h>
4730+#include "br_private.h"
4731+
4732+static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr);
4733+
4734+struct notifier_block br_device_notifier =
4735+{
4736+ br_device_event,
4737+ NULL,
4738+ 0
4739+};
4740+
4741+static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
4742+{
4743+ struct device *dev;
4744+ struct net_bridge_port *p;
4745+
4746+ dev = ptr;
4747+ p = dev->br_port;
4748+
4749+ if (p == NULL)
4750+ return NOTIFY_DONE;
4751+
4752+ switch (event)
4753+ {
4754+ case NETDEV_CHANGEADDR:
4755+ read_lock(&p->br->lock);
4756+ br_fdb_changeaddr(p, dev->dev_addr);
4757+ br_stp_recalculate_bridge_id(p->br);
4758+ read_unlock(&p->br->lock);
4759+ break;
4760+
4761+ case NETDEV_GOING_DOWN:
4762+ /* extend the protocol to send some kind of notification? */
4763+ break;
4764+
4765+ case NETDEV_DOWN:
4766+ if (p->br->dev.flags & IFF_UP) {
4767+ read_lock(&p->br->lock);
4768+ br_stp_disable_port(dev->br_port);
4769+ read_unlock(&p->br->lock);
4770+ }
4771+ break;
4772+
4773+ case NETDEV_UP:
4774+ if (p->br->dev.flags & IFF_UP) {
4775+ read_lock(&p->br->lock);
4776+ br_stp_enable_port(dev->br_port);
4777+ read_unlock(&p->br->lock);
4778+ }
4779+ break;
4780+
4781+ case NETDEV_UNREGISTER:
4782+ br_del_if(dev->br_port->br, dev);
4783+ break;
4784+ }
4785+
4786+ return NOTIFY_DONE;
4787+}
4788diff -urN linux-2.2.20/net/bridge/br_private.h linux-2.2.20br/net/bridge/br_private.h
4789--- linux-2.2.20/net/bridge/br_private.h Thu Jan 1 01:00:00 1970
4790+++ linux-2.2.20br/net/bridge/br_private.h Sat Nov 10 21:44:20 2001
4791@@ -0,0 +1,215 @@
4792+/*
4793+ * Linux ethernet bridge
4794+ *
4795+ * Authors:
4796+ * Lennert Buytenhek <buytenh@gnu.org>
4797+ *
4798+ * $Id$
4799+ *
4800+ * This program is free software; you can redistribute it and/or
4801+ * modify it under the terms of the GNU General Public License
4802+ * as published by the Free Software Foundation; either version
4803+ * 2 of the License, or (at your option) any later version.
4804+ */
4805+
4806+#ifndef _BR_PRIVATE_H
4807+#define _BR_PRIVATE_H
4808+
4809+#include <linux/netdevice.h>
4810+#include <linux/miscdevice.h>
4811+#include <linux/if_bridge.h>
4812+
4813+#define BR_HASH_BITS 8
4814+#define BR_HASH_SIZE (1 << BR_HASH_BITS)
4815+
4816+#define BR_HOLD_TIME (1*HZ)
4817+
4818+#ifndef read_lock_bh
4819+#define read_lock_bh(x) { start_bh_atomic(); read_lock(x); }
4820+#define read_unlock_bh(x) { read_unlock(x); end_bh_atomic(); }
4821+#define write_lock_bh(x) { start_bh_atomic(); write_lock(x); }
4822+#define write_unlock_bh(x) { write_unlock(x); end_bh_atomic(); }
4823+#endif
4824+
4825+typedef struct bridge_id bridge_id;
4826+typedef struct mac_addr mac_addr;
4827+typedef __u16 port_id;
4828+
4829+#if 1
4830+struct br_timer { int running; unsigned long expires; };
4831+#define br_timer_clear(t) { (t)->running = 0; }
4832+#define br_timer_get_residue(t) (((t)->running)?(jiffies - (t)->expires):0)
4833+#define br_timer_set(t,x) { (t)->expires = (x); (t)->running = 1; }
4834+#define br_timer_is_running(t) ((t)->running)
4835+#define br_timer_has_expired(t,to) ((t)->running && time_after_eq(jiffies, (t)->expires + (to)))
4836+#endif
4837+
4838+
4839+
4840+struct bridge_id
4841+{
4842+ unsigned char prio[2];
4843+ unsigned char addr[6];
4844+};
4845+
4846+struct mac_addr
4847+{
4848+ unsigned char addr[6];
4849+ unsigned char pad[2];
4850+};
4851+
4852+struct net_bridge_fdb_entry
4853+{
4854+ struct net_bridge_fdb_entry *next_hash;
4855+ struct net_bridge_fdb_entry **pprev_hash;
4856+ atomic_t use_count;
4857+ mac_addr addr;
4858+ struct net_bridge_port *dst;
4859+ unsigned long ageing_timer;
4860+ unsigned is_local:1;
4861+ unsigned is_static:1;
4862+};
4863+
4864+struct net_bridge_port
4865+{
4866+ struct net_bridge_port *next;
4867+ struct net_bridge *br;
4868+ struct device *dev;
4869+ int port_no;
4870+
4871+ /* STP */
4872+ port_id port_id;
4873+ int state;
4874+ int path_cost;
4875+ bridge_id designated_root;
4876+ int designated_cost;
4877+ bridge_id designated_bridge;
4878+ port_id designated_port;
4879+ unsigned topology_change_ack:1;
4880+ unsigned config_pending:1;
4881+ int priority;
4882+
4883+ struct br_timer forward_delay_timer;
4884+ struct br_timer hold_timer;
4885+ struct br_timer message_age_timer;
4886+};
4887+
4888+struct net_bridge
4889+{
4890+ struct net_bridge *next;
4891+ rwlock_t lock;
4892+ struct net_bridge_port *port_list;
4893+ char name[IFNAMSIZ];
4894+ struct device dev;
4895+ struct net_device_stats statistics;
4896+ rwlock_t hash_lock;
4897+ struct net_bridge_fdb_entry *hash[BR_HASH_SIZE];
4898+ struct timer_list tick;
4899+
4900+ /* STP */
4901+ bridge_id designated_root;
4902+ int root_path_cost;
4903+ int root_port;
4904+ int max_age;
4905+ int hello_time;
4906+ int forward_delay;
4907+ bridge_id bridge_id;
4908+ int bridge_max_age;
4909+ int bridge_hello_time;
4910+ int bridge_forward_delay;
4911+ unsigned stp_enabled:1;
4912+ unsigned topology_change:1;
4913+ unsigned topology_change_detected:1;
4914+
4915+ struct br_timer hello_timer;
4916+ struct br_timer tcn_timer;
4917+ struct br_timer topology_change_timer;
4918+ struct br_timer gc_timer;
4919+
4920+ int ageing_time;
4921+ int gc_interval;
4922+};
4923+
4924+struct notifier_block br_device_notifier;
4925+unsigned char bridge_ula[6];
4926+
4927+/* br.c */
4928+void br_dec_use_count(void);
4929+void br_inc_use_count(void);
4930+
4931+/* br_device.c */
4932+void br_dev_setup(struct device *dev);
4933+
4934+/* br_fdb.c */
4935+void br_fdb_changeaddr(struct net_bridge_port *p,
4936+ unsigned char *newaddr);
4937+void br_fdb_cleanup(struct net_bridge *br);
4938+void br_fdb_delete_by_port(struct net_bridge *br,
4939+ struct net_bridge_port *p);
4940+struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
4941+ unsigned char *addr);
4942+void br_fdb_put(struct net_bridge_fdb_entry *ent);
4943+int br_fdb_get_entries(struct net_bridge *br,
4944+ unsigned char *_buf,
4945+ int maxnum,
4946+ int offset);
4947+void br_fdb_insert(struct net_bridge *br,
4948+ struct net_bridge_port *source,
4949+ unsigned char *addr,
4950+ int is_local);
4951+
4952+/* br_forward.c */
4953+void br_forward(struct net_bridge_port *to,
4954+ struct sk_buff *skb);
4955+void br_flood(struct net_bridge *br,
4956+ struct sk_buff *skb,
4957+ int clone);
4958+
4959+/* br_if.c */
4960+int br_add_bridge(char *name);
4961+int br_del_bridge(char *name);
4962+int br_add_if(struct net_bridge *br,
4963+ struct device *dev);
4964+int br_del_if(struct net_bridge *br,
4965+ struct device *dev);
4966+int br_get_bridge_ifindices(int *indices,
4967+ int num);
4968+void br_get_port_ifindices(struct net_bridge *br,
4969+ int *ifindices);
4970+
4971+/* br_input.c */
4972+void br_handle_frame(struct sk_buff *skb);
4973+
4974+/* br_ioctl.c */
4975+int br_ioctl(struct net_bridge *br,
4976+ unsigned int cmd,
4977+ unsigned long arg0,
4978+ unsigned long arg1,
4979+ unsigned long arg2);
4980+int br_ioctl_deviceless_stub(unsigned long arg);
4981+
4982+/* br_stp.c */
4983+int br_is_root_bridge(struct net_bridge *br);
4984+struct net_bridge_port *br_get_port(struct net_bridge *br,
4985+ int port_no);
4986+void br_init_port(struct net_bridge_port *p);
4987+port_id br_make_port_id(struct net_bridge_port *p);
4988+void br_become_designated_port(struct net_bridge_port *p);
4989+
4990+/* br_stp_if.c */
4991+void br_stp_enable_bridge(struct net_bridge *br);
4992+void br_stp_disable_bridge(struct net_bridge *br);
4993+void br_stp_enable_port(struct net_bridge_port *p);
4994+void br_stp_disable_port(struct net_bridge_port *p);
4995+void br_stp_recalculate_bridge_id(struct net_bridge *br);
4996+void br_stp_set_bridge_priority(struct net_bridge *br,
4997+ int newprio);
4998+void br_stp_set_port_priority(struct net_bridge_port *p,
4999+ int newprio);
5000+void br_stp_set_path_cost(struct net_bridge_port *p,
5001+ int path_cost);
5002+
5003+/* br_stp_bpdu.c */
5004+void br_stp_handle_bpdu(struct sk_buff *skb);
5005+
5006+#endif
5007diff -urN linux-2.2.20/net/bridge/br_private_stp.h linux-2.2.20br/net/bridge/br_private_stp.h
5008--- linux-2.2.20/net/bridge/br_private_stp.h Thu Jan 1 01:00:00 1970
5009+++ linux-2.2.20br/net/bridge/br_private_stp.h Sat Nov 10 21:44:20 2001
5010@@ -0,0 +1,53 @@
5011+/*
5012+ * Linux ethernet bridge
5013+ *
5014+ * Authors:
5015+ * Lennert Buytenhek <buytenh@gnu.org>
5016+ *
5017+ * $Id$
5018+ *
5019+ * This program is free software; you can redistribute it and/or
5020+ * modify it under the terms of the GNU General Public License
5021+ * as published by the Free Software Foundation; either version
5022+ * 2 of the License, or (at your option) any later version.
5023+ */
5024+
5025+#ifndef _BR_PRIVATE_STP_H
5026+#define _BR_PRIVATE_STP_H
5027+
5028+#define BPDU_TYPE_CONFIG 0
5029+#define BPDU_TYPE_TCN 0x80
5030+
5031+struct br_config_bpdu
5032+{
5033+ unsigned topology_change:1;
5034+ unsigned topology_change_ack:1;
5035+ bridge_id root;
5036+ int root_path_cost;
5037+ bridge_id bridge_id;
5038+ port_id port_id;
5039+ int message_age;
5040+ int max_age;
5041+ int hello_time;
5042+ int forward_delay;
5043+};
5044+
5045+/* br_stp.c */
5046+void br_become_root_bridge(struct net_bridge *br);
5047+void br_config_bpdu_generation(struct net_bridge *);
5048+void br_configuration_update(struct net_bridge *);
5049+int br_is_designated_port(struct net_bridge_port *p);
5050+int br_is_root_bridge(struct net_bridge *br);
5051+void br_port_state_selection(struct net_bridge *);
5052+void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu);
5053+void br_received_tcn_bpdu(struct net_bridge_port *p);
5054+void br_tick(unsigned long __data);
5055+void br_transmit_config(struct net_bridge_port *p);
5056+void br_transmit_tcn(struct net_bridge *br);
5057+void br_topology_change_detection(struct net_bridge *br);
5058+
5059+/* br_stp_bpdu.c */
5060+void br_send_config_bpdu(struct net_bridge_port *, struct br_config_bpdu *);
5061+void br_send_tcn_bpdu(struct net_bridge_port *);
5062+
5063+#endif
5064diff -urN linux-2.2.20/net/bridge/br_stp.c linux-2.2.20br/net/bridge/br_stp.c
5065--- linux-2.2.20/net/bridge/br_stp.c Thu Jan 1 01:00:00 1970
5066+++ linux-2.2.20br/net/bridge/br_stp.c Sat Nov 10 21:44:20 2001
5067@@ -0,0 +1,467 @@
5068+/*
5069+ * Spanning tree protocol; generic parts
5070+ * Linux ethernet bridge
5071+ *
5072+ * Authors:
5073+ * Lennert Buytenhek <buytenh@gnu.org>
5074+ *
5075+ * $Id$
5076+ *
5077+ * This program is free software; you can redistribute it and/or
5078+ * modify it under the terms of the GNU General Public License
5079+ * as published by the Free Software Foundation; either version
5080+ * 2 of the License, or (at your option) any later version.
5081+ */
5082+
5083+#include <linux/config.h>
5084+#include <linux/kernel.h>
5085+#include <linux/if_bridge.h>
5086+#include <linux/smp_lock.h>
5087+#include <asm/uaccess.h>
5088+#include "br_private.h"
5089+#include "br_private_stp.h"
5090+
5091+
5092+
5093+/* called under ioctl_lock or bridge lock */
5094+int br_is_root_bridge(struct net_bridge *br)
5095+{
5096+ return !memcmp(&br->bridge_id, &br->designated_root, 8);
5097+}
5098+
5099+/* called under bridge lock */
5100+int br_is_designated_port(struct net_bridge_port *p)
5101+{
5102+ return !memcmp(&p->designated_bridge, &p->br->bridge_id, 8) &&
5103+ (p->designated_port == p->port_id);
5104+}
5105+
5106+/* called under ioctl_lock or bridge lock */
5107+struct net_bridge_port *br_get_port(struct net_bridge *br, int port_no)
5108+{
5109+ struct net_bridge_port *p;
5110+
5111+ p = br->port_list;
5112+ while (p != NULL) {
5113+ if (p->port_no == port_no)
5114+ return p;
5115+
5116+ p = p->next;
5117+ }
5118+
5119+ return NULL;
5120+}
5121+
5122+/* called under bridge lock */
5123+static int br_should_become_root_port(struct net_bridge_port *p, int root_port)
5124+{
5125+ struct net_bridge *br;
5126+ struct net_bridge_port *rp;
5127+ int t;
5128+
5129+ br = p->br;
5130+ if (p->state == BR_STATE_DISABLED ||
5131+ br_is_designated_port(p))
5132+ return 0;
5133+
5134+ if (memcmp(&br->bridge_id, &p->designated_root, 8) <= 0)
5135+ return 0;
5136+
5137+ if (!root_port)
5138+ return 1;
5139+
5140+ rp = br_get_port(br, root_port);
5141+
5142+ t = memcmp(&p->designated_root, &rp->designated_root, 8);
5143+ if (t < 0)
5144+ return 1;
5145+ else if (t > 0)
5146+ return 0;
5147+
5148+ if (p->designated_cost + p->path_cost <
5149+ rp->designated_cost + rp->path_cost)
5150+ return 1;
5151+ else if (p->designated_cost + p->path_cost >
5152+ rp->designated_cost + rp->path_cost)
5153+ return 0;
5154+
5155+ t = memcmp(&p->designated_bridge, &rp->designated_bridge, 8);
5156+ if (t < 0)
5157+ return 1;
5158+ else if (t > 0)
5159+ return 0;
5160+
5161+ if (p->designated_port < rp->designated_port)
5162+ return 1;
5163+ else if (p->designated_port > rp->designated_port)
5164+ return 0;
5165+
5166+ if (p->port_id < rp->port_id)
5167+ return 1;
5168+
5169+ return 0;
5170+}
5171+
5172+/* called under bridge lock */
5173+static void br_root_selection(struct net_bridge *br)
5174+{
5175+ struct net_bridge_port *p;
5176+ int root_port;
5177+
5178+ root_port = 0;
5179+
5180+ p = br->port_list;
5181+ while (p != NULL) {
5182+ if (br_should_become_root_port(p, root_port))
5183+ root_port = p->port_no;
5184+
5185+ p = p->next;
5186+ }
5187+
5188+ br->root_port = root_port;
5189+
5190+ if (!root_port) {
5191+ br->designated_root = br->bridge_id;
5192+ br->root_path_cost = 0;
5193+ } else {
5194+ p = br_get_port(br, root_port);
5195+ br->designated_root = p->designated_root;
5196+ br->root_path_cost = p->designated_cost + p->path_cost;
5197+ }
5198+}
5199+
5200+/* called under bridge lock */
5201+void br_become_root_bridge(struct net_bridge *br)
5202+{
5203+ br->max_age = br->bridge_max_age;
5204+ br->hello_time = br->bridge_hello_time;
5205+ br->forward_delay = br->bridge_forward_delay;
5206+ br_topology_change_detection(br);
5207+ br_timer_clear(&br->tcn_timer);
5208+ br_config_bpdu_generation(br);
5209+ br_timer_set(&br->hello_timer, jiffies);
5210+}
5211+
5212+/* called under bridge lock */
5213+void br_transmit_config(struct net_bridge_port *p)
5214+{
5215+ struct br_config_bpdu bpdu;
5216+ struct net_bridge *br;
5217+
5218+ if (br_timer_is_running(&p->hold_timer)) {
5219+ p->config_pending = 1;
5220+ return;
5221+ }
5222+
5223+ br = p->br;
5224+
5225+ bpdu.topology_change = br->topology_change;
5226+ bpdu.topology_change_ack = p->topology_change_ack;
5227+ bpdu.root = br->designated_root;
5228+ bpdu.root_path_cost = br->root_path_cost;
5229+ bpdu.bridge_id = br->bridge_id;
5230+ bpdu.port_id = p->port_id;
5231+ bpdu.message_age = 0;
5232+ if (!br_is_root_bridge(br)) {
5233+ struct net_bridge_port *root;
5234+ unsigned long age;
5235+
5236+ root = br_get_port(br, br->root_port);
5237+ age = br_timer_get_residue(&root->message_age_timer) + 1;
5238+ bpdu.message_age = age;
5239+ }
5240+ bpdu.max_age = br->max_age;
5241+ bpdu.hello_time = br->hello_time;
5242+ bpdu.forward_delay = br->forward_delay;
5243+
5244+ br_send_config_bpdu(p, &bpdu);
5245+
5246+ p->topology_change_ack = 0;
5247+ p->config_pending = 0;
5248+ br_timer_set(&p->hold_timer, jiffies);
5249+}
5250+
5251+/* called under bridge lock */
5252+static void br_record_config_information(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5253+{
5254+ p->designated_root = bpdu->root;
5255+ p->designated_cost = bpdu->root_path_cost;
5256+ p->designated_bridge = bpdu->bridge_id;
5257+ p->designated_port = bpdu->port_id;
5258+
5259+ br_timer_set(&p->message_age_timer, jiffies - bpdu->message_age);
5260+}
5261+
5262+/* called under bridge lock */
5263+static void br_record_config_timeout_values(struct net_bridge *br, struct br_config_bpdu *bpdu)
5264+{
5265+ br->max_age = bpdu->max_age;
5266+ br->hello_time = bpdu->hello_time;
5267+ br->forward_delay = bpdu->forward_delay;
5268+ br->topology_change = bpdu->topology_change;
5269+}
5270+
5271+/* called under bridge lock */
5272+void br_transmit_tcn(struct net_bridge *br)
5273+{
5274+ br_send_tcn_bpdu(br_get_port(br, br->root_port));
5275+}
5276+
5277+/* called under bridge lock */
5278+static int br_should_become_designated_port(struct net_bridge_port *p)
5279+{
5280+ struct net_bridge *br;
5281+ int t;
5282+
5283+ br = p->br;
5284+ if (br_is_designated_port(p))
5285+ return 1;
5286+
5287+ if (memcmp(&p->designated_root, &br->designated_root, 8))
5288+ return 1;
5289+
5290+ if (br->root_path_cost < p->designated_cost)
5291+ return 1;
5292+ else if (br->root_path_cost > p->designated_cost)
5293+ return 0;
5294+
5295+ t = memcmp(&br->bridge_id, &p->designated_bridge, 8);
5296+ if (t < 0)
5297+ return 1;
5298+ else if (t > 0)
5299+ return 0;
5300+
5301+ if (p->port_id < p->designated_port)
5302+ return 1;
5303+
5304+ return 0;
5305+}
5306+
5307+/* called under bridge lock */
5308+static void br_designated_port_selection(struct net_bridge *br)
5309+{
5310+ struct net_bridge_port *p;
5311+
5312+ p = br->port_list;
5313+ while (p != NULL) {
5314+ if (p->state != BR_STATE_DISABLED &&
5315+ br_should_become_designated_port(p))
5316+ br_become_designated_port(p);
5317+
5318+ p = p->next;
5319+ }
5320+}
5321+
5322+/* called under bridge lock */
5323+static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5324+{
5325+ int t;
5326+
5327+ t = memcmp(&bpdu->root, &p->designated_root, 8);
5328+ if (t < 0)
5329+ return 1;
5330+ else if (t > 0)
5331+ return 0;
5332+
5333+ if (bpdu->root_path_cost < p->designated_cost)
5334+ return 1;
5335+ else if (bpdu->root_path_cost > p->designated_cost)
5336+ return 0;
5337+
5338+ t = memcmp(&bpdu->bridge_id, &p->designated_bridge, 8);
5339+ if (t < 0)
5340+ return 1;
5341+ else if (t > 0)
5342+ return 0;
5343+
5344+ if (memcmp(&bpdu->bridge_id, &p->br->bridge_id, 8))
5345+ return 1;
5346+
5347+ if (bpdu->port_id <= p->designated_port)
5348+ return 1;
5349+
5350+ return 0;
5351+}
5352+
5353+/* called under bridge lock */
5354+static void br_topology_change_acknowledged(struct net_bridge *br)
5355+{
5356+ br->topology_change_detected = 0;
5357+ br_timer_clear(&br->tcn_timer);
5358+}
5359+
5360+/* called under bridge lock */
5361+void br_topology_change_detection(struct net_bridge *br)
5362+{
5363+ printk(KERN_INFO "%s: topology change detected", br->name);
5364+
5365+ if (br_is_root_bridge(br)) {
5366+ printk(", propagating");
5367+ br->topology_change = 1;
5368+ br_timer_set(&br->topology_change_timer, jiffies);
5369+ } else if (!br->topology_change_detected) {
5370+ printk(", sending tcn bpdu");
5371+ br_transmit_tcn(br);
5372+ br_timer_set(&br->tcn_timer, jiffies);
5373+ }
5374+
5375+ printk("\n");
5376+ br->topology_change_detected = 1;
5377+}
5378+
5379+/* called under bridge lock */
5380+void br_config_bpdu_generation(struct net_bridge *br)
5381+{
5382+ struct net_bridge_port *p;
5383+
5384+ p = br->port_list;
5385+ while (p != NULL) {
5386+ if (p->state != BR_STATE_DISABLED &&
5387+ br_is_designated_port(p))
5388+ br_transmit_config(p);
5389+
5390+ p = p->next;
5391+ }
5392+}
5393+
5394+/* called under bridge lock */
5395+static void br_reply(struct net_bridge_port *p)
5396+{
5397+ br_transmit_config(p);
5398+}
5399+
5400+/* called under bridge lock */
5401+void br_configuration_update(struct net_bridge *br)
5402+{
5403+ br_root_selection(br);
5404+ br_designated_port_selection(br);
5405+}
5406+
5407+/* called under bridge lock */
5408+void br_become_designated_port(struct net_bridge_port *p)
5409+{
5410+ struct net_bridge *br;
5411+
5412+ br = p->br;
5413+ p->designated_root = br->designated_root;
5414+ p->designated_cost = br->root_path_cost;
5415+ p->designated_bridge = br->bridge_id;
5416+ p->designated_port = p->port_id;
5417+}
5418+
5419+/* called under bridge lock */
5420+static void br_make_blocking(struct net_bridge_port *p)
5421+{
5422+ if (p->state != BR_STATE_DISABLED &&
5423+ p->state != BR_STATE_BLOCKING) {
5424+ if (p->state == BR_STATE_FORWARDING ||
5425+ p->state == BR_STATE_LEARNING)
5426+ br_topology_change_detection(p->br);
5427+
5428+ printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
5429+ p->br->name, p->port_no, p->dev->name, "blocking");
5430+
5431+ p->state = BR_STATE_BLOCKING;
5432+ br_timer_clear(&p->forward_delay_timer);
5433+ }
5434+}
5435+
5436+/* called under bridge lock */
5437+static void br_make_forwarding(struct net_bridge_port *p)
5438+{
5439+ if (p->state == BR_STATE_BLOCKING) {
5440+ printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
5441+ p->br->name, p->port_no, p->dev->name, "listening");
5442+
5443+ p->state = BR_STATE_LISTENING;
5444+ br_timer_set(&p->forward_delay_timer, jiffies);
5445+ }
5446+}
5447+
5448+/* called under bridge lock */
5449+void br_port_state_selection(struct net_bridge *br)
5450+{
5451+ struct net_bridge_port *p;
5452+
5453+ p = br->port_list;
5454+ while (p != NULL) {
5455+ if (p->state != BR_STATE_DISABLED) {
5456+ if (p->port_no == br->root_port) {
5457+ p->config_pending = 0;
5458+ p->topology_change_ack = 0;
5459+ br_make_forwarding(p);
5460+ } else if (br_is_designated_port(p)) {
5461+ br_timer_clear(&p->message_age_timer);
5462+ br_make_forwarding(p);
5463+ } else {
5464+ p->config_pending = 0;
5465+ p->topology_change_ack = 0;
5466+ br_make_blocking(p);
5467+ }
5468+ }
5469+
5470+ p = p->next;
5471+ }
5472+}
5473+
5474+/* called under bridge lock */
5475+static void br_topology_change_acknowledge(struct net_bridge_port *p)
5476+{
5477+ p->topology_change_ack = 1;
5478+ br_transmit_config(p);
5479+}
5480+
5481+/* lock-safe */
5482+void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5483+{
5484+ struct net_bridge *br;
5485+ int was_root;
5486+
5487+ if (p->state == BR_STATE_DISABLED)
5488+ return;
5489+
5490+ br = p->br;
5491+ read_lock(&br->lock);
5492+
5493+ was_root = br_is_root_bridge(br);
5494+ if (br_supersedes_port_info(p, bpdu)) {
5495+ br_record_config_information(p, bpdu);
5496+ br_configuration_update(br);
5497+ br_port_state_selection(br);
5498+
5499+ if (!br_is_root_bridge(br) && was_root) {
5500+ br_timer_clear(&br->hello_timer);
5501+ if (br->topology_change_detected) {
5502+ br_timer_clear(&br->topology_change_timer);
5503+ br_transmit_tcn(br);
5504+ br_timer_set(&br->tcn_timer, jiffies);
5505+ }
5506+ }
5507+
5508+ if (p->port_no == br->root_port) {
5509+ br_record_config_timeout_values(br, bpdu);
5510+ br_config_bpdu_generation(br);
5511+ if (bpdu->topology_change_ack)
5512+ br_topology_change_acknowledged(br);
5513+ }
5514+ } else if (br_is_designated_port(p)) {
5515+ br_reply(p);
5516+ }
5517+
5518+ read_unlock(&br->lock);
5519+}
5520+
5521+/* lock-safe */
5522+void br_received_tcn_bpdu(struct net_bridge_port *p)
5523+{
5524+ read_lock(&p->br->lock);
5525+ if (p->state != BR_STATE_DISABLED &&
5526+ br_is_designated_port(p)) {
5527+ printk(KERN_INFO "%s: received tcn bpdu on port %i(%s)\n",
5528+ p->br->name, p->port_no, p->dev->name);
5529+
5530+ br_topology_change_detection(p->br);
5531+ br_topology_change_acknowledge(p);
5532+ }
5533+ read_unlock(&p->br->lock);
5534+}
5535diff -urN linux-2.2.20/net/bridge/br_stp_bpdu.c linux-2.2.20br/net/bridge/br_stp_bpdu.c
5536--- linux-2.2.20/net/bridge/br_stp_bpdu.c Thu Jan 1 01:00:00 1970
5537+++ linux-2.2.20br/net/bridge/br_stp_bpdu.c Sat Nov 10 21:45:16 2001
5538@@ -0,0 +1,191 @@
5539+/*
5540+ * Spanning tree protocol; BPDU handling
5541+ * Linux ethernet bridge
5542+ *
5543+ * Authors:
5544+ * Lennert Buytenhek <buytenh@gnu.org>
5545+ *
5546+ * $Id$
5547+ *
5548+ * This program is free software; you can redistribute it and/or
5549+ * modify it under the terms of the GNU General Public License
5550+ * as published by the Free Software Foundation; either version
5551+ * 2 of the License, or (at your option) any later version.
5552+ */
5553+
5554+#include <linux/config.h>
5555+#include <linux/kernel.h>
5556+#include <linux/if_ether.h>
5557+#include <linux/if_bridge.h>
5558+#include "br_private.h"
5559+#include "br_private_stp.h"
5560+
5561+#define JIFFIES_TO_TICKS(j) (((j) << 8) / HZ)
5562+#define TICKS_TO_JIFFIES(j) (((j) * HZ) >> 8)
5563+
5564+static void br_send_bpdu(struct net_bridge_port *p, unsigned char *data, int length)
5565+{
5566+ struct device *dev;
5567+ struct sk_buff *skb;
5568+ int size;
5569+
5570+ if (!p->br->stp_enabled)
5571+ return;
5572+
5573+ size = length + 2*ETH_ALEN + 2;
5574+ if (size < 60)
5575+ size = 60;
5576+
5577+ dev = p->dev;
5578+
5579+ if ((skb = dev_alloc_skb(size)) == NULL) {
5580+ printk(KERN_INFO "br: memory squeeze!\n");
5581+ return;
5582+ }
5583+
5584+ skb->dev = dev;
5585+ skb->protocol = htons(ETH_P_802_2);
5586+ skb->mac.raw = skb_put(skb, size);
5587+ memcpy(skb->mac.raw, bridge_ula, ETH_ALEN);
5588+ memcpy(skb->mac.raw+ETH_ALEN, dev->dev_addr, ETH_ALEN);
5589+ skb->mac.raw[2*ETH_ALEN] = 0;
5590+ skb->mac.raw[2*ETH_ALEN+1] = length;
5591+ skb->nh.raw = skb->mac.raw + 2*ETH_ALEN + 2;
5592+ memcpy(skb->nh.raw, data, length);
5593+ memset(skb->nh.raw + length, 0xa5, size - length - 2*ETH_ALEN - 2);
5594+
5595+ dev_queue_xmit(skb);
5596+}
5597+
5598+static __inline__ void br_set_ticks(unsigned char *dest, int jiff)
5599+{
5600+ __u16 ticks;
5601+
5602+ ticks = JIFFIES_TO_TICKS(jiff);
5603+ dest[0] = (ticks >> 8) & 0xFF;
5604+ dest[1] = ticks & 0xFF;
5605+}
5606+
5607+static __inline__ int br_get_ticks(unsigned char *dest)
5608+{
5609+ return TICKS_TO_JIFFIES((dest[0] << 8) | dest[1]);
5610+}
5611+
5612+void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
5613+{
5614+ unsigned char buf[38];
5615+
5616+ buf[0] = 0x42;
5617+ buf[1] = 0x42;
5618+ buf[2] = 0x03;
5619+ buf[3] = 0;
5620+ buf[4] = 0;
5621+ buf[5] = 0;
5622+ buf[6] = BPDU_TYPE_CONFIG;
5623+ buf[7] = (bpdu->topology_change ? 0x01 : 0) |
5624+ (bpdu->topology_change_ack ? 0x80 : 0);
5625+ buf[8] = bpdu->root.prio[0];
5626+ buf[9] = bpdu->root.prio[1];
5627+ buf[10] = bpdu->root.addr[0];
5628+ buf[11] = bpdu->root.addr[1];
5629+ buf[12] = bpdu->root.addr[2];
5630+ buf[13] = bpdu->root.addr[3];
5631+ buf[14] = bpdu->root.addr[4];
5632+ buf[15] = bpdu->root.addr[5];
5633+ buf[16] = (bpdu->root_path_cost >> 24) & 0xFF;
5634+ buf[17] = (bpdu->root_path_cost >> 16) & 0xFF;
5635+ buf[18] = (bpdu->root_path_cost >> 8) & 0xFF;
5636+ buf[19] = bpdu->root_path_cost & 0xFF;
5637+ buf[20] = bpdu->bridge_id.prio[0];
5638+ buf[21] = bpdu->bridge_id.prio[1];
5639+ buf[22] = bpdu->bridge_id.addr[0];
5640+ buf[23] = bpdu->bridge_id.addr[1];
5641+ buf[24] = bpdu->bridge_id.addr[2];
5642+ buf[25] = bpdu->bridge_id.addr[3];
5643+ buf[26] = bpdu->bridge_id.addr[4];
5644+ buf[27] = bpdu->bridge_id.addr[5];
5645+ buf[28] = (bpdu->port_id >> 8) & 0xFF;
5646+ buf[29] = bpdu->port_id & 0xFF;
5647+
5648+ br_set_ticks(buf+30, bpdu->message_age);
5649+ br_set_ticks(buf+32, bpdu->max_age);
5650+ br_set_ticks(buf+34, bpdu->hello_time);
5651+ br_set_ticks(buf+36, bpdu->forward_delay);
5652+
5653+ br_send_bpdu(p, buf, 38);
5654+}
5655+
5656+void br_send_tcn_bpdu(struct net_bridge_port *p)
5657+{
5658+ unsigned char buf[7];
5659+
5660+ buf[0] = 0x42;
5661+ buf[1] = 0x42;
5662+ buf[2] = 0x03;
5663+ buf[3] = 0;
5664+ buf[4] = 0;
5665+ buf[5] = 0;
5666+ buf[6] = BPDU_TYPE_TCN;
5667+ br_send_bpdu(p, buf, 7);
5668+}
5669+
5670+static unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
5671+
5672+void br_stp_handle_bpdu(struct sk_buff *skb)
5673+{
5674+ unsigned char *buf;
5675+ struct net_bridge_port *p;
5676+
5677+ buf = skb->mac.raw + 14;
5678+ p = skb->dev->br_port;
5679+ if (!p->br->stp_enabled || memcmp(buf, header, 6)) {
5680+ kfree_skb(skb);
5681+ return;
5682+ }
5683+
5684+ if (buf[6] == BPDU_TYPE_CONFIG) {
5685+ struct br_config_bpdu bpdu;
5686+
5687+ bpdu.topology_change = (buf[7] & 0x01) ? 1 : 0;
5688+ bpdu.topology_change_ack = (buf[7] & 0x80) ? 1 : 0;
5689+ bpdu.root.prio[0] = buf[8];
5690+ bpdu.root.prio[1] = buf[9];
5691+ bpdu.root.addr[0] = buf[10];
5692+ bpdu.root.addr[1] = buf[11];
5693+ bpdu.root.addr[2] = buf[12];
5694+ bpdu.root.addr[3] = buf[13];
5695+ bpdu.root.addr[4] = buf[14];
5696+ bpdu.root.addr[5] = buf[15];
5697+ bpdu.root_path_cost =
5698+ (buf[16] << 24) |
5699+ (buf[17] << 16) |
5700+ (buf[18] << 8) |
5701+ buf[19];
5702+ bpdu.bridge_id.prio[0] = buf[20];
5703+ bpdu.bridge_id.prio[1] = buf[21];
5704+ bpdu.bridge_id.addr[0] = buf[22];
5705+ bpdu.bridge_id.addr[1] = buf[23];
5706+ bpdu.bridge_id.addr[2] = buf[24];
5707+ bpdu.bridge_id.addr[3] = buf[25];
5708+ bpdu.bridge_id.addr[4] = buf[26];
5709+ bpdu.bridge_id.addr[5] = buf[27];
5710+ bpdu.port_id = (buf[28] << 8) | buf[29];
5711+
5712+ bpdu.message_age = br_get_ticks(buf+30);
5713+ bpdu.max_age = br_get_ticks(buf+32);
5714+ bpdu.hello_time = br_get_ticks(buf+34);
5715+ bpdu.forward_delay = br_get_ticks(buf+36);
5716+
5717+ kfree_skb(skb);
5718+ br_received_config_bpdu(p, &bpdu);
5719+ return;
5720+ }
5721+
5722+ if (buf[6] == BPDU_TYPE_TCN) {
5723+ br_received_tcn_bpdu(p);
5724+ kfree_skb(skb);
5725+ return;
5726+ }
5727+
5728+ kfree_skb(skb);
5729+}
5730diff -urN linux-2.2.20/net/bridge/br_stp_if.c linux-2.2.20br/net/bridge/br_stp_if.c
5731--- linux-2.2.20/net/bridge/br_stp_if.c Thu Jan 1 01:00:00 1970
5732+++ linux-2.2.20br/net/bridge/br_stp_if.c Sat Nov 10 21:44:20 2001
5733@@ -0,0 +1,232 @@
5734+/*
5735+ * Spanning tree protocol; interface code
5736+ * Linux ethernet bridge
5737+ *
5738+ * Authors:
5739+ * Lennert Buytenhek <buytenh@gnu.org>
5740+ *
5741+ * $Id$
5742+ *
5743+ * This program is free software; you can redistribute it and/or
5744+ * modify it under the terms of the GNU General Public License
5745+ * as published by the Free Software Foundation; either version
5746+ * 2 of the License, or (at your option) any later version.
5747+ */
5748+
5749+#include <linux/config.h>
5750+#include <linux/kernel.h>
5751+#include <linux/types.h>
5752+#include <linux/notifier.h>
5753+#include <linux/if_bridge.h>
5754+#include <linux/smp_lock.h>
5755+#include <asm/uaccess.h>
5756+#include "br_private.h"
5757+#include "br_private_stp.h"
5758+
5759+__u16 br_make_port_id(struct net_bridge_port *p)
5760+{
5761+ return (p->priority << 8) | p->port_no;
5762+}
5763+
5764+/* called under bridge lock */
5765+void br_init_port(struct net_bridge_port *p)
5766+{
5767+ p->port_id = br_make_port_id(p);
5768+ br_become_designated_port(p);
5769+ p->state = BR_STATE_BLOCKING;
5770+ p->topology_change_ack = 0;
5771+ p->config_pending = 0;
5772+ br_timer_clear(&p->message_age_timer);
5773+ br_timer_clear(&p->forward_delay_timer);
5774+ br_timer_clear(&p->hold_timer);
5775+}
5776+
5777+/* called under bridge lock */
5778+void br_stp_enable_bridge(struct net_bridge *br)
5779+{
5780+ struct net_bridge_port *p;
5781+ struct timer_list *timer = &br->tick;
5782+
5783+ init_timer(timer);
5784+ timer->data = (unsigned long) br;
5785+ timer->function = br_tick;
5786+ timer->expires = jiffies + 1;
5787+ add_timer(timer);
5788+
5789+ br_timer_set(&br->hello_timer, jiffies);
5790+ br_config_bpdu_generation(br);
5791+
5792+ p = br->port_list;
5793+ while (p != NULL) {
5794+ if (p->dev->flags & IFF_UP)
5795+ br_stp_enable_port(p);
5796+
5797+ p = p->next;
5798+ }
5799+
5800+ br_timer_set(&br->gc_timer, jiffies);
5801+}
5802+
5803+/* called under bridge lock */
5804+void br_stp_disable_bridge(struct net_bridge *br)
5805+{
5806+ struct net_bridge_port *p;
5807+
5808+ br->topology_change = 0;
5809+ br->topology_change_detected = 0;
5810+ br_timer_clear(&br->hello_timer);
5811+ br_timer_clear(&br->topology_change_timer);
5812+ br_timer_clear(&br->tcn_timer);
5813+ br_timer_clear(&br->gc_timer);
5814+ br_fdb_cleanup(br);
5815+
5816+ p = br->port_list;
5817+ while (p != NULL) {
5818+ if (p->state != BR_STATE_DISABLED)
5819+ br_stp_disable_port(p);
5820+
5821+ p = p->next;
5822+ }
5823+
5824+ del_timer(&br->tick);
5825+ synchronize_bh();
5826+}
5827+
5828+/* called under bridge lock */
5829+void br_stp_enable_port(struct net_bridge_port *p)
5830+{
5831+ br_init_port(p);
5832+ br_port_state_selection(p->br);
5833+}
5834+
5835+/* called under bridge lock */
5836+void br_stp_disable_port(struct net_bridge_port *p)
5837+{
5838+ struct net_bridge *br;
5839+ int wasroot;
5840+
5841+ br = p->br;
5842+ printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
5843+ br->name, p->port_no, p->dev->name, "disabled");
5844+
5845+ wasroot = br_is_root_bridge(br);
5846+ br_become_designated_port(p);
5847+ p->state = BR_STATE_DISABLED;
5848+ p->topology_change_ack = 0;
5849+ p->config_pending = 0;
5850+ br_timer_clear(&p->message_age_timer);
5851+ br_timer_clear(&p->forward_delay_timer);
5852+ br_timer_clear(&p->hold_timer);
5853+ br_configuration_update(br);
5854+ br_port_state_selection(br);
5855+
5856+ if (br_is_root_bridge(br) && !wasroot)
5857+ br_become_root_bridge(br);
5858+}
5859+
5860+/* called under bridge lock */
5861+static void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr)
5862+{
5863+ unsigned char oldaddr[6];
5864+ struct net_bridge_port *p;
5865+ int wasroot;
5866+
5867+ wasroot = br_is_root_bridge(br);
5868+
5869+ memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
5870+ memcpy(br->bridge_id.addr, addr, ETH_ALEN);
5871+ memcpy(br->dev.dev_addr, addr, ETH_ALEN);
5872+
5873+ p = br->port_list;
5874+ while (p != NULL) {
5875+ if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN))
5876+ memcpy(p->designated_bridge.addr, addr, ETH_ALEN);
5877+
5878+ if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN))
5879+ memcpy(p->designated_root.addr, addr, ETH_ALEN);
5880+
5881+ p = p->next;
5882+ }
5883+
5884+ br_configuration_update(br);
5885+ br_port_state_selection(br);
5886+ if (br_is_root_bridge(br) && !wasroot)
5887+ br_become_root_bridge(br);
5888+}
5889+
5890+static unsigned char br_mac_zero[6] = {0,0,0,0,0,0};
5891+
5892+/* called under bridge lock */
5893+void br_stp_recalculate_bridge_id(struct net_bridge *br)
5894+{
5895+ unsigned char *addr;
5896+ struct net_bridge_port *p;
5897+
5898+ addr = br_mac_zero;
5899+
5900+ p = br->port_list;
5901+ while (p != NULL) {
5902+ if (addr == br_mac_zero ||
5903+ memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
5904+ addr = p->dev->dev_addr;
5905+
5906+ p = p->next;
5907+ }
5908+
5909+ if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))
5910+ br_stp_change_bridge_id(br, addr);
5911+}
5912+
5913+/* called under bridge lock */
5914+void br_stp_set_bridge_priority(struct net_bridge *br, int newprio)
5915+{
5916+ struct net_bridge_port *p;
5917+ int wasroot;
5918+
5919+ wasroot = br_is_root_bridge(br);
5920+
5921+ p = br->port_list;
5922+ while (p != NULL) {
5923+ if (p->state != BR_STATE_DISABLED &&
5924+ br_is_designated_port(p)) {
5925+ p->designated_bridge.prio[0] = (newprio >> 8) & 0xFF;
5926+ p->designated_bridge.prio[1] = newprio & 0xFF;
5927+ }
5928+
5929+ p = p->next;
5930+ }
5931+
5932+ br->bridge_id.prio[0] = (newprio >> 8) & 0xFF;
5933+ br->bridge_id.prio[1] = newprio & 0xFF;
5934+ br_configuration_update(br);
5935+ br_port_state_selection(br);
5936+ if (br_is_root_bridge(br) && !wasroot)
5937+ br_become_root_bridge(br);
5938+}
5939+
5940+/* called under bridge lock */
5941+void br_stp_set_port_priority(struct net_bridge_port *p, int newprio)
5942+{
5943+ __u16 new_port_id;
5944+
5945+ p->priority = newprio & 0xFF;
5946+ new_port_id = br_make_port_id(p);
5947+
5948+ if (br_is_designated_port(p))
5949+ p->designated_port = new_port_id;
5950+
5951+ p->port_id = new_port_id;
5952+ if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) &&
5953+ p->port_id < p->designated_port) {
5954+ br_become_designated_port(p);
5955+ br_port_state_selection(p->br);
5956+ }
5957+}
5958+
5959+/* called under bridge lock */
5960+void br_stp_set_path_cost(struct net_bridge_port *p, int path_cost)
5961+{
5962+ p->path_cost = path_cost;
5963+ br_configuration_update(p->br);
5964+ br_port_state_selection(p->br);
5965+}
5966diff -urN linux-2.2.20/net/bridge/br_stp_timer.c linux-2.2.20br/net/bridge/br_stp_timer.c
5967--- linux-2.2.20/net/bridge/br_stp_timer.c Thu Jan 1 01:00:00 1970
5968+++ linux-2.2.20br/net/bridge/br_stp_timer.c Sat Nov 10 21:44:20 2001
5969@@ -0,0 +1,185 @@
5970+/*
5971+ * Spanning tree protocol; timer-related code
5972+ * Linux ethernet bridge
5973+ *
5974+ * Authors:
5975+ * Lennert Buytenhek <buytenh@gnu.org>
5976+ *
5977+ * $Id$
5978+ *
5979+ * This program is free software; you can redistribute it and/or
5980+ * modify it under the terms of the GNU General Public License
5981+ * as published by the Free Software Foundation; either version
5982+ * 2 of the License, or (at your option) any later version.
5983+ */
5984+
5985+#include <linux/config.h>
5986+#include <linux/kernel.h>
5987+#include <linux/if_bridge.h>
5988+#include <linux/smp_lock.h>
5989+#include <asm/uaccess.h>
5990+#include "br_private.h"
5991+#include "br_private_stp.h"
5992+
5993+static void dump_bridge_id(bridge_id *id)
5994+{
5995+ printk("%.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", id->prio[0],
5996+ id->prio[1], id->addr[0], id->addr[1], id->addr[2], id->addr[3],
5997+ id->addr[4], id->addr[5]);
5998+}
5999+
6000+/* called under bridge lock */
6001+static int br_is_designated_for_some_port(struct net_bridge *br)
6002+{
6003+ struct net_bridge_port *p;
6004+
6005+ p = br->port_list;
6006+ while (p != NULL) {
6007+ if (p->state != BR_STATE_DISABLED &&
6008+ !memcmp(&p->designated_bridge, &br->bridge_id, 8))
6009+ return 1;
6010+
6011+ p = p->next;
6012+ }
6013+
6014+ return 0;
6015+}
6016+
6017+/* called under bridge lock */
6018+static void br_hello_timer_expired(struct net_bridge *br)
6019+{
6020+ br_config_bpdu_generation(br);
6021+ br_timer_set(&br->hello_timer, jiffies);
6022+}
6023+
6024+/* called under bridge lock */
6025+static void br_message_age_timer_expired(struct net_bridge_port *p)
6026+{
6027+ struct net_bridge *br;
6028+ int was_root;
6029+
6030+ br = p->br;
6031+ printk(KERN_INFO "%s: ", br->name);
6032+ printk("neighbour ");
6033+ dump_bridge_id(&p->designated_bridge);
6034+ printk(" lost on port %i(%s)\n", p->port_no, p->dev->name);
6035+
6036+ /*
6037+ * According to the spec, the message age timer cannot be
6038+ * running when we are the root bridge. So.. this was_root
6039+ * check is redundant. I'm leaving it in for now, though.
6040+ */
6041+ was_root = br_is_root_bridge(br);
6042+
6043+ br_become_designated_port(p);
6044+ br_configuration_update(br);
6045+ br_port_state_selection(br);
6046+ if (br_is_root_bridge(br) && !was_root)
6047+ br_become_root_bridge(br);
6048+}
6049+
6050+/* called under bridge lock */
6051+static void br_forward_delay_timer_expired(struct net_bridge_port *p)
6052+{
6053+ if (p->state == BR_STATE_LISTENING) {
6054+ printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
6055+ p->br->name, p->port_no, p->dev->name, "learning");
6056+
6057+ p->state = BR_STATE_LEARNING;
6058+ br_timer_set(&p->forward_delay_timer, jiffies);
6059+ } else if (p->state == BR_STATE_LEARNING) {
6060+ printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
6061+ p->br->name, p->port_no, p->dev->name, "forwarding");
6062+
6063+ p->state = BR_STATE_FORWARDING;
6064+ if (br_is_designated_for_some_port(p->br))
6065+ br_topology_change_detection(p->br);
6066+ }
6067+}
6068+
6069+/* called under bridge lock */
6070+static void br_tcn_timer_expired(struct net_bridge *br)
6071+{
6072+ printk(KERN_INFO "%s: retransmitting tcn bpdu\n", br->name);
6073+ br_transmit_tcn(br);
6074+ br_timer_set(&br->tcn_timer, jiffies);
6075+}
6076+
6077+/* called under bridge lock */
6078+static void br_topology_change_timer_expired(struct net_bridge *br)
6079+{
6080+ br->topology_change_detected = 0;
6081+ br->topology_change = 0;
6082+}
6083+
6084+/* called under bridge lock */
6085+static void br_hold_timer_expired(struct net_bridge_port *p)
6086+{
6087+ if (p->config_pending)
6088+ br_transmit_config(p);
6089+}
6090+
6091+/* called under bridge lock */
6092+static void br_check_port_timers(struct net_bridge_port *p)
6093+{
6094+ if (br_timer_has_expired(&p->message_age_timer, p->br->max_age)) {
6095+ br_timer_clear(&p->message_age_timer);
6096+ br_message_age_timer_expired(p);
6097+ }
6098+
6099+ if (br_timer_has_expired(&p->forward_delay_timer, p->br->forward_delay)) {
6100+ br_timer_clear(&p->forward_delay_timer);
6101+ br_forward_delay_timer_expired(p);
6102+ }
6103+
6104+ if (br_timer_has_expired(&p->hold_timer, BR_HOLD_TIME)) {
6105+ br_timer_clear(&p->hold_timer);
6106+ br_hold_timer_expired(p);
6107+ }
6108+}
6109+
6110+/* called under bridge lock */
6111+static void br_check_timers(struct net_bridge *br)
6112+{
6113+ struct net_bridge_port *p;
6114+
6115+ if (br_timer_has_expired(&br->gc_timer, br->gc_interval)) {
6116+ br_timer_set(&br->gc_timer, jiffies);
6117+ br_fdb_cleanup(br);
6118+ }
6119+
6120+ if (br_timer_has_expired(&br->hello_timer, br->hello_time)) {
6121+ br_timer_clear(&br->hello_timer);
6122+ br_hello_timer_expired(br);
6123+ }
6124+
6125+ if (br_timer_has_expired(&br->tcn_timer, br->bridge_hello_time)) {
6126+ br_timer_clear(&br->tcn_timer);
6127+ br_tcn_timer_expired(br);
6128+ }
6129+
6130+ if (br_timer_has_expired(&br->topology_change_timer, br->bridge_forward_delay + br->bridge_max_age)) {
6131+ br_timer_clear(&br->topology_change_timer);
6132+ br_topology_change_timer_expired(br);
6133+ }
6134+
6135+ p = br->port_list;
6136+ while (p != NULL) {
6137+ if (p->state != BR_STATE_DISABLED)
6138+ br_check_port_timers(p);
6139+
6140+ p = p->next;
6141+ }
6142+}
6143+
6144+void br_tick(unsigned long __data)
6145+{
6146+ struct net_bridge *br = (struct net_bridge *)__data;
6147+
6148+ read_lock(&br->lock);
6149+ br_check_timers(br);
6150+ read_unlock(&br->lock);
6151+
6152+ br->tick.expires = jiffies + 1;
6153+ add_timer(&br->tick);
6154+}
6155diff -urN linux-2.2.20/net/bridge/br_tree.c linux-2.2.20br/net/bridge/br_tree.c
6156--- linux-2.2.20/net/bridge/br_tree.c Sun Mar 25 18:31:13 2001
6157+++ linux-2.2.20br/net/bridge/br_tree.c Thu Jan 1 01:00:00 1970
6158@@ -1,501 +0,0 @@
6159-/*
6160- * This code is derived from the avl functions in mmap.c
6161- */
6162-
6163-#include <linux/kernel.h>
6164-#include <linux/errno.h>
6165-#include <linux/string.h>
6166-#include <linux/malloc.h>
6167-#include <linux/skbuff.h>
6168-#include <linux/netdevice.h>
6169-
6170-#include <net/br.h>
6171-#define _DEBUG_AVL
6172-
6173-/*
6174- * Use an AVL (Adelson-Velskii and Landis) tree to speed up this search
6175- * from O(n) to O(log n), where n is the number of ULAs.
6176- * Written by Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de>.
6177- * Taken from mmap.c, extensively modified by John Hayes
6178- * <hayes@netplumbing.com>
6179- * 98-02 Modified by Jean-Rene Peulve jr.peulve@aix.pacwan.net
6180- * update port number when topology change
6181- * return oldfdb when updating, for broadcast storm checking
6182- * call addr_cmp once per node
6183- */
6184-
6185-static struct fdb fdb_head;
6186-static struct fdb *fhp = &fdb_head;
6187-static struct fdb **fhpp = &fhp;
6188-static int fdb_inited = 0;
6189-
6190-#ifdef DEBUG_AVL
6191-static void printk_avl (struct fdb * tree);
6192-#endif
6193-
6194-static int addr_cmp(unsigned char *a1, unsigned char *a2);
6195-
6196-/*
6197- * fdb_head is the AVL tree corresponding to fdb
6198- * or, more exactly, its root.
6199- * A fdb has the following fields:
6200- * fdb_avl_left left son of a tree node
6201- * fdb_avl_right right son of a tree node
6202- * fdb_avl_height 1+max(heightof(left),heightof(right))
6203- * The empty tree is represented as NULL.
6204- */
6205-
6206-#ifndef avl_br_empty
6207-#define avl_br_empty (struct fdb *) NULL
6208-#endif
6209-
6210-/* Since the trees are balanced, their height will never be large. */
6211-#define avl_maxheight 127
6212-#define heightof(tree) ((tree) == avl_br_empty ? 0 : (tree)->fdb_avl_height)
6213-/*
6214- * Consistency and balancing rules:
6215- * 1. tree->fdb_avl_height == 1+max(heightof(tree->fdb_avl_left),heightof(tree->fdb_avl_right))
6216- * 2. abs( heightof(tree->fdb_avl_left) - heightof(tree->fdb_avl_right) ) <= 1
6217- * 3. foreach node in tree->fdb_avl_left: node->fdb_avl_key <= tree->fdb_avl_key,
6218- * foreach node in tree->fdb_avl_right: node->fdb_avl_key >= tree->fdb_avl_key.
6219- */
6220-
6221-static int fdb_init(void)
6222-{
6223- fdb_head.fdb_avl_height = 0;
6224- fdb_head.fdb_avl_left = (struct fdb *)0;
6225- fdb_head.fdb_avl_right = (struct fdb *)0;
6226- fdb_inited = 1;
6227- return(0);
6228-}
6229-
6230-struct fdb *br_avl_find_addr(unsigned char addr[6])
6231-{
6232- struct fdb * result = NULL;
6233- struct fdb * tree;
6234-
6235- if (!fdb_inited)
6236- fdb_init();
6237-#if (DEBUG_AVL)
6238- printk("searching for ula %02x:%02x:%02x:%02x:%02x:%02x\n",
6239- addr[0],
6240- addr[1],
6241- addr[2],
6242- addr[3],
6243- addr[4],
6244- addr[5]);
6245-#endif /* DEBUG_AVL */
6246- for (tree = fhp ; ; ) {
6247- if (tree == avl_br_empty) {
6248-#if (DEBUG_AVL)
6249- printk("search failed, returning node 0x%x\n", (unsigned int)result);
6250-#endif /* DEBUG_AVL */
6251- return result;
6252- }
6253-
6254-#if (DEBUG_AVL)
6255- printk("node 0x%x: checking ula %02x:%02x:%02x:%02x:%02x:%02x\n",
6256- (unsigned int)tree,
6257- tree->ula[0],
6258- tree->ula[1],
6259- tree->ula[2],
6260- tree->ula[3],
6261- tree->ula[4],
6262- tree->ula[5]);
6263-#endif /* DEBUG_AVL */
6264- if (addr_cmp(addr, tree->ula) == 0) {
6265-#if (DEBUG_AVL)
6266- printk("found node 0x%x\n", (unsigned int)tree);
6267-#endif /* DEBUG_AVL */
6268- return tree;
6269- }
6270- if (addr_cmp(addr, tree->ula) < 0) {
6271- tree = tree->fdb_avl_left;
6272- } else {
6273- tree = tree->fdb_avl_right;
6274- }
6275- }
6276-}
6277-
6278-
6279-/*
6280- * Rebalance a tree.
6281- * After inserting or deleting a node of a tree we have a sequence of subtrees
6282- * nodes[0]..nodes[k-1] such that
6283- * nodes[0] is the root and nodes[i+1] = nodes[i]->{fdb_avl_left|fdb_avl_right}.
6284- */
6285-static void br_avl_rebalance (struct fdb *** nodeplaces_ptr, int count)
6286-{
6287- if (!fdb_inited)
6288- fdb_init();
6289- for ( ; count > 0 ; count--) {
6290- struct fdb ** nodeplace = *--nodeplaces_ptr;
6291- struct fdb * node = *nodeplace;
6292- struct fdb * nodeleft = node->fdb_avl_left;
6293- struct fdb * noderight = node->fdb_avl_right;
6294- int heightleft = heightof(nodeleft);
6295- int heightright = heightof(noderight);
6296- if (heightright + 1 < heightleft) {
6297- /* */
6298- /* * */
6299- /* / \ */
6300- /* n+2 n */
6301- /* */
6302- struct fdb * nodeleftleft = nodeleft->fdb_avl_left;
6303- struct fdb * nodeleftright = nodeleft->fdb_avl_right;
6304- int heightleftright = heightof(nodeleftright);
6305- if (heightof(nodeleftleft) >= heightleftright) {
6306- /* */
6307- /* * n+2|n+3 */
6308- /* / \ / \ */
6309- /* n+2 n --> / n+1|n+2 */
6310- /* / \ | / \ */
6311- /* n+1 n|n+1 n+1 n|n+1 n */
6312- /* */
6313- node->fdb_avl_left = nodeleftright;
6314- nodeleft->fdb_avl_right = node;
6315- nodeleft->fdb_avl_height = 1 + (node->fdb_avl_height = 1 + heightleftright);
6316- *nodeplace = nodeleft;
6317- } else {
6318- /* */
6319- /* * n+2 */
6320- /* / \ / \ */
6321- /* n+2 n --> n+1 n+1 */
6322- /* / \ / \ / \ */
6323- /* n n+1 n L R n */
6324- /* / \ */
6325- /* L R */
6326- /* */
6327- nodeleft->fdb_avl_right = nodeleftright->fdb_avl_left;
6328- node->fdb_avl_left = nodeleftright->fdb_avl_right;
6329- nodeleftright->fdb_avl_left = nodeleft;
6330- nodeleftright->fdb_avl_right = node;
6331- nodeleft->fdb_avl_height = node->fdb_avl_height = heightleftright;
6332- nodeleftright->fdb_avl_height = heightleft;
6333- *nodeplace = nodeleftright;
6334- }
6335- } else if (heightleft + 1 < heightright) {
6336- /* similar to the above, just interchange 'left' <--> 'right' */
6337- struct fdb * noderightright = noderight->fdb_avl_right;
6338- struct fdb * noderightleft = noderight->fdb_avl_left;
6339- int heightrightleft = heightof(noderightleft);
6340- if (heightof(noderightright) >= heightrightleft) {
6341- node->fdb_avl_right = noderightleft;
6342- noderight->fdb_avl_left = node;
6343- noderight->fdb_avl_height = 1 + (node->fdb_avl_height = 1 + heightrightleft);
6344- *nodeplace = noderight;
6345- } else {
6346- noderight->fdb_avl_left = noderightleft->fdb_avl_right;
6347- node->fdb_avl_right = noderightleft->fdb_avl_left;
6348- noderightleft->fdb_avl_right = noderight;
6349- noderightleft->fdb_avl_left = node;
6350- noderight->fdb_avl_height = node->fdb_avl_height = heightrightleft;
6351- noderightleft->fdb_avl_height = heightright;
6352- *nodeplace = noderightleft;
6353- }
6354- } else {
6355- int height = (heightleft<heightright ? heightright : heightleft) + 1;
6356- if (height == node->fdb_avl_height)
6357- break;
6358- node->fdb_avl_height = height;
6359- }
6360- }
6361-#ifdef DEBUG_AVL
6362- printk_avl(&fdb_head);
6363-#endif /* DEBUG_AVL */
6364-}
6365-
6366-/* Insert a node into a tree.
6367- * Performance improvement:
6368- * call addr_cmp() only once per node and use result in a switch.
6369- * Return old node address if we knew that MAC address already
6370- * Return NULL if we insert the new node
6371- */
6372-struct fdb *br_avl_insert (struct fdb * new_node)
6373-{
6374- struct fdb ** nodeplace = fhpp;
6375- struct fdb ** stack[avl_maxheight];
6376- int stack_count = 0;
6377- struct fdb *** stack_ptr = &stack[0]; /* = &stack[stackcount] */
6378- if (!fdb_inited)
6379- fdb_init();
6380- for (;;) {
6381- struct fdb *node;
6382-
6383- node = *nodeplace;
6384- if (node == avl_br_empty)
6385- break;
6386- *stack_ptr++ = nodeplace; stack_count++;
6387- switch(addr_cmp(new_node->ula, node->ula)) {
6388- case 0: /* update */
6389- if (node->port == new_node->port) {
6390- node->flags = new_node->flags;
6391- node->timer = new_node->timer;
6392- } else if (!(node->flags & FDB_ENT_VALID) &&
6393- node->port) {
6394- /* update fdb but never for local interfaces */
6395-#if (DEBUG_AVL)
6396- printk("node 0x%x:port changed old=%d new=%d\n",
6397- (unsigned int)node, node->port,new_node->port);
6398-#endif
6399- /* JRP: update port as well if the topology change !
6400- * Don't do this while entry is still valid otherwise
6401- * a broadcast that we flooded and is reentered by another
6402- * port would mess up the good port number.
6403- * The fdb list per port needs to be updated as well.
6404- */
6405- requeue_fdb(node, new_node->port);
6406- node->flags = new_node->flags;
6407- node->timer = new_node->timer;
6408-#if (DEBUG_AVL)
6409- printk_avl(&fdb_head);
6410-#endif /* DEBUG_AVL */
6411- }
6412- return node; /* pass old fdb to caller */
6413-
6414- case 1: /* new_node->ula > node->ula */
6415- nodeplace = &node->fdb_avl_right;
6416- break;
6417- default: /* -1 => new_node->ula < node->ula */
6418- nodeplace = &node->fdb_avl_left;
6419- }
6420- }
6421-#if (DEBUG_AVL)
6422- printk("node 0x%x: adding ula %02x:%02x:%02x:%02x:%02x:%02x\n",
6423- (unsigned int)new_node,
6424- new_node->ula[0],
6425- new_node->ula[1],
6426- new_node->ula[2],
6427- new_node->ula[3],
6428- new_node->ula[4],
6429- new_node->ula[5]);
6430-#endif /* (DEBUG_AVL) */
6431- new_node->fdb_avl_left = avl_br_empty;
6432- new_node->fdb_avl_right = avl_br_empty;
6433- new_node->fdb_avl_height = 1;
6434- *nodeplace = new_node;
6435- br_avl_rebalance(stack_ptr,stack_count);
6436-#ifdef DEBUG_AVL
6437- printk_avl(&fdb_head);
6438-#endif /* DEBUG_AVL */
6439- return NULL; /* this is a new node */
6440-}
6441-
6442-
6443-/* Removes a node out of a tree. */
6444-static int br_avl_remove (struct fdb * node_to_delete)
6445-{
6446- struct fdb ** nodeplace = fhpp;
6447- struct fdb ** stack[avl_maxheight];
6448- int stack_count = 0;
6449- struct fdb *** stack_ptr = &stack[0]; /* = &stack[stackcount] */
6450- struct fdb ** nodeplace_to_delete;
6451- if (!fdb_inited)
6452- fdb_init();
6453- for (;;) {
6454- struct fdb * node = *nodeplace;
6455- if (node == avl_br_empty) {
6456- /* what? node_to_delete not found in tree? */
6457- printk(KERN_ERR "br: avl_remove: node to delete not found in tree\n");
6458- return(-1);
6459- }
6460- *stack_ptr++ = nodeplace; stack_count++;
6461- if (addr_cmp(node_to_delete->ula, node->ula) == 0)
6462- break;
6463- if (addr_cmp(node_to_delete->ula, node->ula) < 0)
6464- nodeplace = &node->fdb_avl_left;
6465- else
6466- nodeplace = &node->fdb_avl_right;
6467- }
6468- nodeplace_to_delete = nodeplace;
6469- /* Have to remove node_to_delete = *nodeplace_to_delete. */
6470- if (node_to_delete->fdb_avl_left == avl_br_empty) {
6471- *nodeplace_to_delete = node_to_delete->fdb_avl_right;
6472- stack_ptr--; stack_count--;
6473- } else {
6474- struct fdb *** stack_ptr_to_delete = stack_ptr;
6475- struct fdb ** nodeplace = &node_to_delete->fdb_avl_left;
6476- struct fdb * node;
6477- for (;;) {
6478- node = *nodeplace;
6479- if (node->fdb_avl_right == avl_br_empty)
6480- break;
6481- *stack_ptr++ = nodeplace; stack_count++;
6482- nodeplace = &node->fdb_avl_right;
6483- }
6484- *nodeplace = node->fdb_avl_left;
6485- /* node replaces node_to_delete */
6486- node->fdb_avl_left = node_to_delete->fdb_avl_left;
6487- node->fdb_avl_right = node_to_delete->fdb_avl_right;
6488- node->fdb_avl_height = node_to_delete->fdb_avl_height;
6489- *nodeplace_to_delete = node; /* replace node_to_delete */
6490- *stack_ptr_to_delete = &node->fdb_avl_left; /* replace &node_to_delete->fdb_avl_left */
6491- }
6492- br_avl_rebalance(stack_ptr,stack_count);
6493- return(0);
6494-}
6495-
6496-#ifdef DEBUG_AVL
6497-
6498-/* print a tree */
6499-static void printk_avl (struct fdb * tree)
6500-{
6501- if (tree != avl_br_empty) {
6502- printk("(");
6503- printk("%02x:%02x:%02x:%02x:%02x:%02x(%d)",
6504- tree->ula[0],
6505- tree->ula[1],
6506- tree->ula[2],
6507- tree->ula[3],
6508- tree->ula[4],
6509- tree->ula[5],
6510- tree->port);
6511- if (tree->fdb_avl_left != avl_br_empty) {
6512- printk_avl(tree->fdb_avl_left);
6513- printk("<");
6514- }
6515- if (tree->fdb_avl_right != avl_br_empty) {
6516- printk(">");
6517- printk_avl(tree->fdb_avl_right);
6518- }
6519- printk(")\n");
6520- }
6521-}
6522-
6523-static char *avl_check_point = "somewhere";
6524-
6525-/* check a tree's consistency and balancing */
6526-static void avl_checkheights (struct fdb * tree)
6527-{
6528- int h, hl, hr;
6529-
6530- if (tree == avl_br_empty)
6531- return;
6532- avl_checkheights(tree->fdb_avl_left);
6533- avl_checkheights(tree->fdb_avl_right);
6534- h = tree->fdb_avl_height;
6535- hl = heightof(tree->fdb_avl_left);
6536- hr = heightof(tree->fdb_avl_right);
6537- if ((h == hl+1) && (hr <= hl) && (hl <= hr+1))
6538- return;
6539- if ((h == hr+1) && (hl <= hr) && (hr <= hl+1))
6540- return;
6541- printk("%s: avl_checkheights: heights inconsistent\n",avl_check_point);
6542-}
6543-
6544-/* check that all values stored in a tree are < key */
6545-static void avl_checkleft (struct fdb * tree, fdb_avl_key_t key)
6546-{
6547- if (tree == avl_br_empty)
6548- return;
6549- avl_checkleft(tree->fdb_avl_left,key);
6550- avl_checkleft(tree->fdb_avl_right,key);
6551- if (tree->fdb_avl_key < key)
6552- return;
6553- printk("%s: avl_checkleft: left key %lu >= top key %lu\n",avl_check_point,tree->fdb_avl_key,key);
6554-}
6555-
6556-/* check that all values stored in a tree are > key */
6557-static void avl_checkright (struct fdb * tree, fdb_avl_key_t key)
6558-{
6559- if (tree == avl_br_empty)
6560- return;
6561- avl_checkright(tree->fdb_avl_left,key);
6562- avl_checkright(tree->fdb_avl_right,key);
6563- if (tree->fdb_avl_key > key)
6564- return;
6565- printk("%s: avl_checkright: right key %lu <= top key %lu\n",avl_check_point,tree->fdb_avl_key,key);
6566-}
6567-
6568-/* check that all values are properly increasing */
6569-static void avl_checkorder (struct fdb * tree)
6570-{
6571- if (tree == avl_br_empty)
6572- return;
6573- avl_checkorder(tree->fdb_avl_left);
6574- avl_checkorder(tree->fdb_avl_right);
6575- avl_checkleft(tree->fdb_avl_left,tree->fdb_avl_key);
6576- avl_checkright(tree->fdb_avl_right,tree->fdb_avl_key);
6577-}
6578-
6579-#endif /* DEBUG_AVL */
6580-
6581-static int addr_cmp(unsigned char a1[], unsigned char a2[])
6582-{
6583- int i;
6584-
6585- for (i=0; i<6; i++) {
6586- if (a1[i] > a2[i]) return(1);
6587- if (a1[i] < a2[i]) return(-1);
6588- }
6589- return(0);
6590-}
6591-
6592-/* Vova Oksman: function for copy tree to the buffer */
6593-void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,
6594- int* len, off_t offset, int length)
6595-{
6596- int size;
6597-
6598- if( 0 == *pos){
6599- if(avl_br_empty == tree)
6600- /* begin from the root */
6601- tree = fhp;
6602- *pos = *len;
6603- }
6604-
6605- if (*pos >= offset+length)
6606- return;
6607-
6608- if (tree != avl_br_empty) {
6609- /* don't write the local device */
6610- if(tree->port != 0){
6611- size = sprintf(*pbuffer,
6612- "%02x:%02x:%02x:%02x:%02x:%02x %s %d %ld\n",
6613- tree->ula[0],tree->ula[1],tree->ula[2],
6614- tree->ula[3],tree->ula[4],tree->ula[5],
6615- port_info[tree->port].dev->name, tree->flags,CURRENT_TIME-tree->timer);
6616-
6617- (*pos)+=size;
6618- (*len)+=size;
6619- (*pbuffer)+=size;
6620- }
6621- if (*pos <= offset)
6622- *len=0;
6623-
6624- if (tree->fdb_avl_left != avl_br_empty) {
6625- sprintf_avl (pbuffer,tree->fdb_avl_left,pos,len,offset,length);
6626- }
6627- if (tree->fdb_avl_right != avl_br_empty) {
6628- sprintf_avl (pbuffer,tree->fdb_avl_right,pos,len,offset,length);
6629- }
6630-
6631- }
6632-
6633- return;
6634-}
6635-
6636-/*
6637- * Delete all nodes learnt by the port
6638- */
6639-void br_avl_delete_by_port(int port)
6640-{
6641- struct fdb *fdb, *next;
6642-
6643- if (!fdb_inited)
6644- fdb_init();
6645-
6646- for(fdb = port_info[port].fdb; fdb != NULL; fdb = next) {
6647- next = fdb->fdb_next;
6648- br_avl_remove(fdb);
6649- }
6650- port_info[port].fdb = NULL;
6651-
6652- /* remove the local mac too */
6653-/* next = br_avl_find_addr(port_info[port].dev->dev_addr); */
6654- next = br_avl_find_addr(port_info[port].ifmac.BRIDGE_ID_ULA);
6655- if (next != NULL)
6656- br_avl_remove(next);
6657-
6658- return;
6659-}
6660diff -urN linux-2.2.20/net/bridge/sysctl_net_bridge.c linux-2.2.20br/net/bridge/sysctl_net_bridge.c
6661--- linux-2.2.20/net/bridge/sysctl_net_bridge.c Sun Mar 25 18:31:13 2001
6662+++ linux-2.2.20br/net/bridge/sysctl_net_bridge.c Thu Jan 1 01:00:00 1970
6663@@ -1,13 +0,0 @@
6664-/* -*- linux-c -*-
6665- * sysctl_net_bridge.c: sysctl interface to net bridge subsystem.
6666- *
6667- * Begun June 1, 1996, Mike Shaver.
6668- * Added /proc/sys/net/bridge directory entry (empty =) ). [MS]
6669- */
6670-
6671-#include <linux/mm.h>
6672-#include <linux/sysctl.h>
6673-
6674-ctl_table bridge_table[] = {
6675- {0}
6676-};
6677diff -urN linux-2.2.20/net/core/skbuff.c linux-2.2.20br/net/core/skbuff.c
6678--- linux-2.2.20/net/core/skbuff.c Sun Mar 25 18:31:12 2001
6679+++ linux-2.2.20br/net/core/skbuff.c Sat Nov 10 21:44:20 2001
6680@@ -184,7 +184,6 @@
6681
6682 skb->destructor = NULL;
6683 skb->pkt_type = PACKET_HOST; /* Default type */
6684- skb->pkt_bridged = 0; /* Not bridged */
6685 skb->prev = skb->next = NULL;
6686 skb->list = NULL;
6687 skb->sk = NULL;
6688diff -urN linux-2.2.20/net/ipv4/af_inet.c linux-2.2.20br/net/ipv4/af_inet.c
6689--- linux-2.2.20/net/ipv4/af_inet.c Fri Nov 2 17:39:16 2001
6690+++ linux-2.2.20br/net/ipv4/af_inet.c Sat Nov 10 21:44:20 2001
6691@@ -106,10 +106,8 @@
6692 #ifdef CONFIG_IP_MASQUERADE
6693 #include <net/ip_masq.h>
6694 #endif
6695-#ifdef CONFIG_BRIDGE
6696-#include <net/br.h>
6697-#endif
6698-
6699+#include <linux/if_bridge.h>
6700+
6701 #ifdef CONFIG_NET_DIVERT
6702 #include <linux/divert.h>
6703 #endif /* CONFIG_NET_DIVERT */
6704@@ -139,6 +137,7 @@
6705 int (*dlci_ioctl_hook)(unsigned int, void *) = NULL;
6706 #endif
6707
6708+int (*br_ioctl_hook)(unsigned long) = NULL;
6709 int (*rarp_ioctl_hook)(unsigned int,void*) = NULL;
6710
6711 /*
6712@@ -913,11 +912,15 @@
6713 return(devinet_ioctl(cmd,(void *) arg));
6714 case SIOCGIFBR:
6715 case SIOCSIFBR:
6716-#ifdef CONFIG_BRIDGE
6717- return(br_ioctl(cmd,(void *) arg));
6718-#else
6719+#ifdef CONFIG_KMOD
6720+ if (br_ioctl_hook == NULL)
6721+ request_module("bridge");
6722+#endif
6723+
6724+ if (br_ioctl_hook != NULL)
6725+ return br_ioctl_hook(arg);
6726+
6727 return -ENOPKG;
6728-#endif
6729
6730 case SIOCGIFDIVERT:
6731 case SIOCSIFDIVERT:
6732diff -urN linux-2.2.20/net/netsyms.c linux-2.2.20br/net/netsyms.c
6733--- linux-2.2.20/net/netsyms.c Sun Mar 25 18:37:41 2001
6734+++ linux-2.2.20br/net/netsyms.c Sat Nov 10 21:44:20 2001
6735@@ -28,10 +28,7 @@
6736 #endif
6737 #include <net/pkt_sched.h>
6738 #include <net/scm.h>
6739-
6740-#ifdef CONFIG_BRIDGE
6741-#include <net/br.h>
6742-#endif
6743+#include <linux/if_bridge.h>
6744
6745 #ifdef CONFIG_NET_DIVERT
6746 #include <linux/divert.h>
6747@@ -225,9 +222,10 @@
6748
6749 EXPORT_SYMBOL(scm_detach_fds);
6750
6751-#ifdef CONFIG_BRIDGE
6752-EXPORT_SYMBOL(br_ioctl);
6753+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
6754+EXPORT_SYMBOL(br_handle_frame_hook);
6755 #endif
6756+EXPORT_SYMBOL(br_ioctl_hook);
6757
6758 #ifdef CONFIG_NET_DIVERT
6759 EXPORT_SYMBOL(alloc_divert_blk);
6760diff -urN linux-2.2.20/net/packet/af_packet.c linux-2.2.20br/net/packet/af_packet.c
6761--- linux-2.2.20/net/packet/af_packet.c Sun Mar 25 18:31:14 2001
6762+++ linux-2.2.20br/net/packet/af_packet.c Sat Nov 10 21:44:21 2001
6763@@ -63,14 +63,12 @@
6764 #include <asm/uaccess.h>
6765 #include <linux/module.h>
6766 #include <linux/init.h>
6767+#include <linux/if_bridge.h>
6768
6769 #ifdef CONFIG_INET
6770 #include <net/inet_common.h>
6771 #endif
6772
6773-#ifdef CONFIG_BRIDGE
6774-#include <net/br.h>
6775-#endif
6776
6777 #ifdef CONFIG_NET_DIVERT
6778 #include <linux/divert.h>
6779@@ -1131,11 +1129,15 @@
6780
6781 case SIOCGIFBR:
6782 case SIOCSIFBR:
6783-#ifdef CONFIG_BRIDGE
6784- return(br_ioctl(cmd,(void *) arg));
6785-#else
6786+#ifdef CONFIG_KMOD
6787+ if (br_ioctl_hook == NULL)
6788+ request_module("bridge");
6789+#endif
6790+
6791+ if (br_ioctl_hook != NULL)
6792+ return br_ioctl_hook(arg);
6793+
6794 return -ENOPKG;
6795-#endif
6796
6797 case SIOCGIFDIVERT:
6798 case SIOCSIFDIVERT:
6799diff -urN linux-2.2.20/net/sysctl_net.c linux-2.2.20br/net/sysctl_net.c
6800--- linux-2.2.20/net/sysctl_net.c Sun Mar 25 18:31:13 2001
6801+++ linux-2.2.20br/net/sysctl_net.c Sat Nov 10 21:44:21 2001
6802@@ -34,10 +34,6 @@
6803 extern ctl_table ether_table[], e802_table[];
6804 #endif
6805
6806-#ifdef CONFIG_BRIDGE
6807-extern ctl_table bridge_table[];
6808-#endif
6809-
6810 #ifdef CONFIG_IPV6
6811 extern ctl_table ipv6_table[];
6812 #endif
6813@@ -61,9 +57,6 @@
6814 #ifdef CONFIG_IPX
6815 {NET_IPX, "ipx", NULL, 0, 0555, ipx_table},
6816 #endif
6817-#ifdef CONFIG_BRIDGE
6818- {NET_BRIDGE, "bridge", NULL, 0, 0555, bridge_table},
6819-#endif
6820 #ifdef CONFIG_IPV6
6821 {NET_IPV6, "ipv6", NULL, 0, 0555, ipv6_table},
6822 #endif
This page took 1.130485 seconds and 4 git commands to generate.