patch-1.3.91 linux/net/bridge/br.c

Next file: linux/net/ipv4/ip_options.c
Previous file: linux/net/ax25/ax25_subr.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.90/linux/net/bridge/br.c linux/net/bridge/br.c
@@ -16,8 +16,9 @@
  *	and use a netlink notifier so a daemon can maintain the bridge
  *	port group (could we also do multiple groups ????).
  *		A nice /proc file interface.
- *		Put the path costs in the port info and devices
+ *		Put the path costs in the port info and devices.
  *		Put the bridge port number in the device structure for speed.
+ *		Bridge SNMP stats.
  *	
  */
  
@@ -81,15 +82,14 @@
 /** Elements of Procedure (4.6) **/
 
 /*
- * this section of code was graciously borrowed from the IEEE 802.1d
+ * this section of code was gratiously borrowed from the IEEE 802.1d
  * specification section 4.9.1 starting on pg 69.  It has been
  * modified somewhat to fit within out framework and structure.  It
  * implements the spanning tree algorithm that is the heart of the
  * 802.1d bridging protocol.
  */
 
-void
-transmit_config(int port_no)			  /* (4.6.1)	 */
+void transmit_config(int port_no)			  /* (4.6.1)	 */
 {
 	if (hold_timer[port_no].active) {	  /* (4.6.1.3.1)	 */
 		port_info[port_no].config_pending = TRUE;	/* (4.6.1.3.1)	 */
@@ -132,15 +132,13 @@
 	}
 }
 
-int
-root_bridge(void)
+int root_bridge(void)
 {
 	return (br_cmp(bridge_info.designated_root.BRIDGE_ID,
 		 bridge_info.bridge_id.BRIDGE_ID)?FALSE:TRUE);
 }
 
-int
-supersedes_port_info(int port_no, Config_bpdu *config)	  /* (4.6.2.2)	 */
+int supersedes_port_info(int port_no, Config_bpdu *config)	  /* (4.6.2.2)	 */
 {
 	return (
 		(br_cmp(config->root_id.BRIDGE_ID,
@@ -177,8 +175,7 @@
 		);
 }
 
-void
-record_config_information(int port_no, Config_bpdu *config)	  /* (4.6.2)	 */
+void record_config_information(int port_no, Config_bpdu *config)	  /* (4.6.2)	 */
 {
 	port_info[port_no].designated_root = config->root_id;	/* (4.6.2.3.1)   */
 	port_info[port_no].designated_cost = config->root_path_cost;
@@ -187,8 +184,7 @@
 	start_message_age_timer(port_no, config->message_age);	/* (4.6.2.3.2)   */
 }
 
-void
-record_config_timeout_values(Config_bpdu *config)		  /* (4.6.3)	 */
+void record_config_timeout_values(Config_bpdu *config)		  /* (4.6.3)	 */
 {
 	bridge_info.max_age = config->max_age;	  /* (4.6.3.3)	 */
 	bridge_info.hello_time = config->hello_time;
@@ -197,8 +193,7 @@
 		bridge_info.top_change = 1;
 }
 
-void
-config_bpdu_generation(void)
+void config_bpdu_generation(void)
 {						  /* (4.6.4)	 */
 	int             port_no;
 	for (port_no = One; port_no <= No_of_ports; port_no++) {	/* (4.6.4.3) */
@@ -211,8 +206,7 @@
 	}
 }
 
-int
-designated_port(int port_no)
+int designated_port(int port_no)
 {
 	return ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
 		 bridge_info.bridge_id.BRIDGE_ID) == 0
@@ -224,14 +218,12 @@
 		);
 }
 
-void
-reply(int port_no)					  /* (4.6.5)	 */
+void reply(int port_no)					  /* (4.6.5)	 */
 {
 	transmit_config(port_no);		  /* (4.6.5.3)	 */
 }
 
-void
-transmit_tcn(void)
+void transmit_tcn(void)
 {						  /* (4.6.6)	 */
 	int             port_no;
 
@@ -240,8 +232,7 @@
 	send_tcn_bpdu(port_no, &tcn_bpdu[bridge_info.root_port]);	/* (4.6.6.3)     */
 }
 
-void
-configuration_update(void)	/* (4.6.7) */
+void configuration_update(void)	/* (4.6.7) */
 {
 	root_selection();			  /* (4.6.7.3.1)	 */
 	/* (4.6.8.2)	 */
@@ -249,8 +240,7 @@
 	/* (4.6.9.2)	 */
 }
 
-void
-root_selection(void)
+void root_selection(void)
 {						  /* (4.6.8) */
 	int             root_port;
 	int             port_no;
@@ -330,8 +320,7 @@
 	}
 }
 
-void
-designated_port_selection(void)
+void designated_port_selection(void)
 {						  /* (4.6.9)	 */
 	int             port_no;
 
@@ -368,8 +357,7 @@
 	}
 }
 
-void
-become_designated_port(int port_no)
+void become_designated_port(int port_no)
 {						  /* (4.6.10)	 */
 
 	/* (4.6.10.3.1) */
@@ -382,8 +370,7 @@
 	port_info[port_no].designated_port = port_info[port_no].port_id;
 }
 
-void
-port_state_selection(void)
+void port_state_selection(void)
 {						  /* (4.6.11) */
 	int             port_no;
 	for (port_no = One; port_no <= No_of_ports; port_no++) {
@@ -403,8 +390,7 @@
 
 }
 
-void
-make_forwarding(int port_no)
+void make_forwarding(int port_no)
 {						  /* (4.6.12) */
 	if (port_info[port_no].state == Blocking) {	/* (4.6.12.3) */
 		set_port_state(port_no, Listening);	/* (4.6.12.3.1) */
@@ -412,8 +398,7 @@
 	}
 }
 
-void 
-topology_change_detection(void)
+void topology_change_detection(void)
 {						  /* (4.6.14)       */
 	if (root_bridge()) {			  /* (4.6.14.3.1)   */
 		bridge_info.top_change = 1;
@@ -425,22 +410,19 @@
 	bridge_info.top_change = 1;
 }
 
-void
-topology_change_acknowledged(void)
+void topology_change_acknowledged(void)
 {						  /* (4.6.15) */
 	bridge_info.top_change_detected = 0;
 	stop_tcn_timer();			  /* (4.6.15.3.2) */
 }
 
-void
-acknowledge_topology_change(int port_no)
+void acknowledge_topology_change(int port_no)
 {						  /* (4.6.16) */
 	port_info[port_no].top_change_ack = 1;
 	transmit_config(port_no);		  /* (4.6.16.3.2) */
 }
 
-void
-make_blocking(int port_no)				  /* (4.6.13)	 */
+void make_blocking(int port_no)				  /* (4.6.13)	 */
 {
 
 	if ((port_info[port_no].state != Disabled)
@@ -460,14 +442,12 @@
 	}
 }
 
-void
-set_port_state(int port_no, int state)
+void set_port_state(int port_no, int state)
 {
 	port_info[port_no].state = state;
 }
 
-void
-received_config_bpdu(int port_no, Config_bpdu *config)		  /* (4.7.1)	 */
+void received_config_bpdu(int port_no, Config_bpdu *config)		  /* (4.7.1)	 */
 {
 	int         root;
 
@@ -504,8 +484,7 @@
 	}
 }
 
-void
-received_tcn_bpdu(int port_no, Tcn_bpdu *tcn)			  /* (4.7.2)	 */
+void received_tcn_bpdu(int port_no, Tcn_bpdu *tcn)			  /* (4.7.2)	 */
 {
 	if (port_info[port_no].state != Disabled) {
 		if (designated_port(port_no)) {
@@ -516,15 +495,13 @@
 	}
 }
 
-void
-hello_timer_expiry(void)
+void hello_timer_expiry(void)
 {						  /* (4.7.3)	 */
 	config_bpdu_generation();		  /* (4.6.4.2.2)	 */
 	start_hello_timer();
 }
 
-void
-message_age_timer_expiry(int port_no)		  /* (4.7.4)	 */
+void message_age_timer_expiry(int port_no)		  /* (4.7.4)	 */
 {
 	int         root;
 	root = root_bridge();
@@ -549,8 +526,7 @@
 	}
 }
 
-void
-forward_delay_timer_expiry(int port_no)		  /* (4.7.5)	 */
+void forward_delay_timer_expiry(int port_no)		  /* (4.7.5)	 */
 {
 	if (port_info[port_no].state == Listening) {	/* (4.7.5.1)	 */
 		set_port_state(port_no, Learning);	/* (4.7.5.1.1)	 */
@@ -564,8 +540,7 @@
 	}
 }
 
-int
-designated_for_some_port(void)
+int designated_for_some_port(void)
 {
 	int             port_no;
 
@@ -580,31 +555,27 @@
 	return (FALSE);
 }
 
-void
-tcn_timer_expiry(void)
+void tcn_timer_expiry(void)
 {						  /* (4.7.6)	 */
 	transmit_tcn();				  /* (4.7.6.1)	 */
 	start_tcn_timer();			  /* (4.7.6.2)	 */
 }
 
-void
-topology_change_timer_expiry(void)
+void topology_change_timer_expiry(void)
 {						  /* (4.7.7)	 */
 	bridge_info.top_change_detected = 0;
 	bridge_info.top_change = 0;
 	  /* (4.7.7.2)	 */
 }
 
-void
-hold_timer_expiry(int port_no)			  /* (4.7.8)	 */
+void hold_timer_expiry(int port_no)			  /* (4.7.8)	 */
 {
 	if (port_info[port_no].config_pending) {
 		transmit_config(port_no);	  /* (4.7.8.1)	 */
 	}					  /* (4.6.1.2.3)	 */
 }
 
-void
-br_init(void)
+void br_init(void)
 {						  /* (4.8.1)	 */
 	int             port_no;
 
@@ -633,17 +604,16 @@
 	config_bpdu_generation();		  /* (4.8.1.6)	 */
 	
 	/* initialize system timer */
-	tl.expires = HZ;	/* 1 second */
+	tl.expires = jiffies+HZ;	/* 1 second */
 	tl.function = br_tick;
 	add_timer(&tl);
 
 	register_netdevice_notifier(&br_dev_notifier);
-	br_stats.flags = BR_UP | BR_DEBUG;	/* enable bridge */
-	start_hello_timer();
+	br_stats.flags = 0; /*BR_UP | BR_DEBUG*/;	/* enable bridge */
+	/*start_hello_timer();*/
 }
 
-void
-br_init_port(int port_no)
+void br_init_port(int port_no)
 {
 	become_designated_port(port_no);	  /* (4.8.1.4.1) */
 	set_port_state(port_no, Blocking);	  /* (4.8.1.4.2)    */
@@ -654,15 +624,13 @@
 	stop_hold_timer(port_no);		  /* (4.8.1.4.7)	 */
 }
 
-void
-enable_port(int port_no)				  /* (4.8.2)	 */
+void enable_port(int port_no)				  /* (4.8.2)	 */
 {
 	br_init_port(port_no);
 	port_state_selection();			  /* (4.8.2.7)	 */
 }						  /* */
 
-void
-disable_port(int port_no)				  /* (4.8.3)	 */
+void disable_port(int port_no)				  /* (4.8.3)	 */
 {
 	int         root;
 
@@ -687,8 +655,7 @@
 }
 
 
-void
-set_bridge_priority(bridge_id_t *new_bridge_id)		  /* (4.8.4)	 */
+void set_bridge_priority(bridge_id_t *new_bridge_id)		  /* (4.8.4)	 */
 {
 
 	int         root;
@@ -714,8 +681,7 @@
 	}
 }
 
-void
-set_port_priority(int port_no, unsigned short new_port_id)		  /* (4.8.5)	 */
+void set_port_priority(int port_no, unsigned short new_port_id)		  /* (4.8.5)	 */
 {
 	if (designated_port(port_no)) {		  /* (4.8.5.2)	 */
 		port_info[port_no].designated_port = new_port_id;
@@ -735,16 +701,14 @@
 	}
 }
 
-void
-set_path_cost(int port_no, unsigned short path_cost)		  /* (4.8.6)	 */
+void set_path_cost(int port_no, unsigned short path_cost)		  /* (4.8.6)	 */
 {
 	port_info[port_no].path_cost = path_cost; /* (4.8.6.1)	 */
 	configuration_update();			  /* (4.8.6.2)	 */
 	port_state_selection();			  /* (4.8.6.3)	 */
 }
 
-static void
-br_tick(unsigned long arg)
+static void br_tick(unsigned long arg)
 {
 	int             port_no;
 
@@ -769,26 +733,23 @@
 		}
 	}
 	/* call me again sometime... */
-	tl.expires = HZ;	/* 1 second */
+	tl.expires = jiffies+HZ;	/* 1 second */
 	tl.function = br_tick;
 	add_timer(&tl);
 }
 
-void
-start_hello_timer(void)
+void start_hello_timer(void)
 {
 	hello_timer.value = 0;
 	hello_timer.active = TRUE;
 }
 
-void
-stop_hello_timer(void)
+void stop_hello_timer(void)
 {
 	hello_timer.active = FALSE;
 }
 
-int
-hello_timer_expired(void)
+int hello_timer_expired(void)
 {
 	if (hello_timer.active && (++hello_timer.value >= bridge_info.hello_time)) {
 		hello_timer.active = FALSE;
@@ -797,21 +758,18 @@
 	return (FALSE);
 }
 
-void
-start_tcn_timer(void)
+void start_tcn_timer(void)
 {
 	tcn_timer.value = 0;
 	tcn_timer.active = TRUE;
 }
 
-void
-stop_tcn_timer(void)
+void stop_tcn_timer(void)
 {
 	tcn_timer.active = FALSE;
 }
 
-int
-tcn_timer_expired(void)
+int tcn_timer_expired(void)
 {
 	if (tcn_timer.active && (++tcn_timer.value >=
 				 bridge_info.bridge_hello_time)) {
@@ -822,21 +780,18 @@
 
 }
 
-void
-start_topology_change_timer(void)
+void start_topology_change_timer(void)
 {
 	topology_change_timer.value = 0;
 	topology_change_timer.active = TRUE;
 }
 
-void
-stop_topology_change_timer(void)
+void stop_topology_change_timer(void)
 {
 	topology_change_timer.active = FALSE;
 }
 
-int
-topology_change_timer_expired(void)
+int topology_change_timer_expired(void)
 {
 	if (topology_change_timer.active
 			&& (++topology_change_timer.value
@@ -848,21 +803,18 @@
 	return (FALSE);
 }
 
-void
-start_message_age_timer(int port_no, unsigned short message_age)
+void start_message_age_timer(int port_no, unsigned short message_age)
 {
 	message_age_timer[port_no].value = message_age;
 	message_age_timer[port_no].active = TRUE;
 }
 
-void
-stop_message_age_timer(int port_no)
+void stop_message_age_timer(int port_no)
 {
 	message_age_timer[port_no].active = FALSE;
 }
 
-int
-message_age_timer_expired(int port_no)
+int message_age_timer_expired(int port_no)
 {
 	if (message_age_timer[port_no].active &&
 	      (++message_age_timer[port_no].value >= bridge_info.max_age)) {
@@ -872,21 +824,18 @@
 	return (FALSE);
 }
 
-void
-start_forward_delay_timer(int port_no)
+void start_forward_delay_timer(int port_no)
 {
 	forward_delay_timer[port_no].value = 0;
 	forward_delay_timer[port_no].active = TRUE;
 }
 
-void
-stop_forward_delay_timer(int port_no)
+void stop_forward_delay_timer(int port_no)
 {
 	forward_delay_timer[port_no].active = FALSE;
 }
 
-int
-forward_delay_timer_expired(int port_no)
+int forward_delay_timer_expired(int port_no)
 {
 		if (forward_delay_timer[port_no].active &&
 				(++forward_delay_timer[port_no].value >= bridge_info.forward_delay)) {
@@ -896,22 +845,19 @@
 		return (FALSE);
 }
 
-void
-start_hold_timer(int port_no)
+void start_hold_timer(int port_no)
 {
 	hold_timer[port_no].value = 0;
 	hold_timer[port_no].active = TRUE;
 }
 
-void
-stop_hold_timer(int port_no)
+void stop_hold_timer(int port_no)
 {
 	hold_timer[port_no].active = FALSE;
 }
 
 
-int
-hold_timer_expired(int port_no)
+int hold_timer_expired(int port_no)
 {
 	if (hold_timer[port_no].active &&
 		   (++hold_timer[port_no].value >= bridge_info.hold_time)) {
@@ -922,8 +868,7 @@
 
 }
 
-int
-send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
+int send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
 {
 struct sk_buff *skb;
 struct device *dev = port_info[port_no].dev;
@@ -982,8 +927,7 @@
 	return(0);
 }
 
-int
-send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
+int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
 {
 struct sk_buff *skb;
 struct device *dev = port_info[port_no].dev;
@@ -1039,8 +983,7 @@
 	return(0);
 }
 
-static int 
-br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
+static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
 {
 	struct device *dev = ptr;
 	int i;
@@ -1103,8 +1046,7 @@
  * frame, 0 when it does not
  */
 
-int
-br_receive_frame(struct sk_buff *skb)	/* 3.5 */
+int br_receive_frame(struct sk_buff *skb)	/* 3.5 */
 {
 	int port;
 	
@@ -1115,12 +1057,15 @@
 		printk("no skb!\n");
 		return(1);
 	}
+
+	skb->pkt_bridged = IS_BRIDGED;
+
 	/* check for loopback */
 	if (skb->dev->flags & IFF_LOOPBACK)
 		return(0);
 
 	port = find_port(skb->dev);
-	skb->h.raw = skb->data;
+	skb->h.raw = skb->mac.raw;
 	if (br_stats.flags & BR_DEBUG)
 		printk("port %i src %02x:%02x:%02x:%02x:%02x:%02x\
 			dest %02x:%02x:%02x:%02x:%02x:%02x\n", 
@@ -1139,11 +1084,13 @@
 			skb->h.eth->h_dest[5]);
 
 	if (!port) {
-		printk("\nbr_receive_frame: no port!\n");
+		if(br_stats.flags&BR_DEBUG)
+			printk("\nbr_receive_frame: no port!\n");
 		return(0);
 	}
 
-	switch (port_info[port].state) {
+	switch (port_info[port].state) 
+	{
 		case Learning:
 			(void) br_learn(skb, port);	/* 3.8 */
 			/* fall through */
@@ -1167,19 +1114,22 @@
 			(void) br_learn(skb, port);	/* 3.8 */
 			/* process BPDUs */
 			if (memcmp(skb->h.eth->h_dest, bridge_ula, 
-					ETH_ALEN) == 0) {
-				printk("frame bpdu processor for me!!!\n");
+					ETH_ALEN) == 0) 
+			{
+				/*printk("frame bpdu processor for me!!!\n");*/
 				br_bpdu(skb);
 				return(1); /* br_bpdu consumes skb */
 			}
 			/* is frame for me? */	
 			if (memcmp(skb->h.eth->h_dest, 
 					port_info[port].dev->dev_addr, 
-					ETH_ALEN) == 0) {
+					ETH_ALEN) == 0) 
+			{
 				return(0);	/* pass frame up our stack (this will */
 						/* happen in net_bh() in dev.c) */
 			}
 			/* ok, forward this frame... */
+			skb_device_lock(skb);
 			return(br_forward(skb, port));
 		default:
 			printk("br_receive_frame: port [%i] unknown state [%i]\n",
@@ -1194,13 +1144,13 @@
  * 0 when it does not.
  */
 
-int
-br_tx_frame(struct sk_buff *skb)	/* 3.5 */
+int br_tx_frame(struct sk_buff *skb)	/* 3.5 */
 {
 	int port;
 	
 	/* sanity */
-	if (!skb) {
+	if (!skb) 
+	{
 		printk("br_tx_frame: no skb!\n");
 		return(0);
 	}
@@ -1235,8 +1185,7 @@
  * state or lack of resources...
  */
 
-int
-br_learn(struct sk_buff *skb, int port)	/* 3.8 */
+int br_learn(struct sk_buff *skb, int port)	/* 3.8 */
 {
 	struct fdb *f;
 
@@ -1285,23 +1234,31 @@
  * this routine always consumes the frame
  */
 
-int
-br_drop(struct sk_buff *skb)
+int br_drop(struct sk_buff *skb)
 {
 	kfree_skb(skb, 0);
 	return(1);
 }
 
 /*
+ * this routine always consumes the frame
+ */
+
+int br_dev_drop(struct sk_buff *skb)
+{
+	dev_kfree_skb(skb, 0);
+	return(1);
+}
+
+/*
  * this routine returns 1 if it consumes the frame, 0
  * if not...
  */
 
-int
-br_forward(struct sk_buff *skb, int port)	/* 3.7 */
+int br_forward(struct sk_buff *skb, int port)	/* 3.7 */
 {
-struct fdb *f;
-unsigned long flags;
+	struct fdb *f;
+	unsigned long flags;
 	
 	/*
    	 * flood all ports with frames destined for a group
@@ -1310,19 +1267,32 @@
 	 * Multicast frames will also need to be seen
 	 * by our upper layers.
 	 */	
-	if (skb->h.eth->h_dest[0] & 0x01) {	/* group address */
+	if (skb->h.eth->h_dest[0] & 0x01) 
+	{
+		/* group address */
 		br_flood(skb, port);
+		/*
+		 *	External groups are fed out via the normal source
+		 *	This probably should be dropped since the flood will
+		 *	have sent it anyway.
+		 */
 		if (port == 0) 			/* locally generated */
-			return(br_drop(skb));
+			return(br_dev_drop(skb));
 		return(0);
 	} else {
 		/* locate port to forward to */
 		f = br_avl_find_addr(skb->h.eth->h_dest);
+		/*
+		 *	Send flood and drop.
+		 */
 		if (!f | !(f->flags & FDB_ENT_VALID)) {
 		 	/* not found; flood all ports */
 			br_flood(skb, port);
-			return(br_drop(skb));
+			return(br_dev_drop(skb));
 		}
+		/*
+		 *	Sending
+		 */
 		if (port_info[f->port].state == Forwarding) {
 			/* has entry expired? */
 			if (f->timer + fdb_aging_time < CURRENT_TIME) {
@@ -1330,33 +1300,34 @@
 				f->flags &= ~FDB_ENT_VALID;
 				if (br_stats.flags & BR_DEBUG)
 					printk("fdb entry expired...\n");
+				/*
+				 *	Send flood and drop original
+				 */
 				br_flood(skb, port);
-				return(br_drop(skb));
+				return(br_dev_drop(skb));
 			}
 			/* mark that's we've been here... */
 			skb->pkt_bridged = IS_BRIDGED;
 			
-			/*
-			 * if the frame is originating in this host,
-			 * we may need to resolve the outgoing address
-			if (port != 0)
-				skb->arp = 1;
-			 */
-		
 			/* reset the skb->ip pointer */	
 			skb->h.raw = skb->data + ETH_HLEN;
 
-			/* we must unlock the skb before requeueing it... */
-			if (skb_device_locked(skb))
-				skb_device_unlock(skb);
-
-			save_flags(flags);	/* enter critical section */
-			cli();
-			skb_queue_head(port_info[f->port].dev->buffs, skb);
-			restore_flags(flags);	/* exit critical section */
+			/*
+			 *	Send the buffer out.
+			 */
+			 
+			skb->dev=port_info[f->port].dev;
+			 
+			/*
+			 *	We send this still locked
+			 */
+			dev_queue_xmit(skb, skb->dev,1);
 			return(1);	/* skb has been consumed */
 		} else {
-			return(br_drop(skb));
+			/*
+			 *	Arrived on the right port, we discard
+			 */
+			return(br_dev_drop(skb));
 		}
 	}
 }
@@ -1367,40 +1338,34 @@
  * consumes the original frame.
  */
 	
-int
-br_flood(struct sk_buff *skb, int port)
+int br_flood(struct sk_buff *skb, int port)
 {
-int i;
-struct sk_buff *nskb;
-unsigned long flags;
+	int i;
+	struct sk_buff *nskb;
+	unsigned long flags;
 
-	for (i = One; i <= No_of_ports; i++) {
+	for (i = One; i <= No_of_ports; i++) 
+	{
 		if (i == port)
 			continue;
-		if (port_info[i].state == Forwarding) {
+		if (port_info[i].state == Forwarding) 
+		{
 			nskb = skb_clone(skb, GFP_ATOMIC);
 			/* mark that's we've been here... */
 			nskb->pkt_bridged = IS_BRIDGED;
-			/*
-			 * if the frame is originating in this host,
-			 * we may need to resolve the outgoing address
-			if (port != 0)
-				nskb->arp = 1;
-			 */
+			nskb->arp = skb->arp;
+			
+/*			printk("Flood to port %d\n",i);*/
 			nskb->h.raw = nskb->data + ETH_HLEN;
-			save_flags(flags);
-			cli();
-			skb_queue_tail(port_info[i].dev->buffs, nskb);
-			restore_flags(flags);
+			dev_queue_xmit(nskb,nskb->dev,1);
 		}
 	}
 	return(0);
 }
 
-int
-find_port(struct device *dev)
+int find_port(struct device *dev)
 {
-int i;
+	int i;
 
 	for (i = One; i <= No_of_ports; i++)
 		if ((port_info[i].dev == dev) && 
@@ -1409,8 +1374,7 @@
 	return(0);
 }
 
-int
-br_port_cost(struct device *dev)	/* 4.10.2 */
+int br_port_cost(struct device *dev)	/* 4.10.2 */
 {
 	if (strncmp(dev->name, "eth", 3) == 0)	/* ethernet */
 		return(100);
@@ -1425,11 +1389,10 @@
  * this routine always consumes the skb 
  */
 
-void
-br_bpdu(struct sk_buff *skb) /* consumes skb */
+void br_bpdu(struct sk_buff *skb) /* consumes skb */
 {
-Tcn_bpdu *bpdu;
-int port;
+	Tcn_bpdu *bpdu;
+	int port;
 
 	port = find_port(skb->dev);
 	if (port == 0) {	/* unknown port */
@@ -1453,8 +1416,7 @@
 	br_drop(skb);
 }
 
-int
-br_ioctl(unsigned int cmd, void *arg)
+int br_ioctl(unsigned int cmd, void *arg)
 {
 	int err;
 	struct br_cf bcf;
@@ -1484,7 +1446,6 @@
 					if (br_stats.flags & BR_UP)
 						return(-EALREADY);	
 					printk("br: enabling bridging function\n");
-					register_netdevice_notifier(&br_dev_notifier);
 					br_stats.flags |= BR_UP;	/* enable bridge */
 					start_hello_timer();
 					break;
@@ -1492,12 +1453,13 @@
 					if (!(br_stats.flags & BR_UP))
 						return(-EALREADY);	
 					printk("br: disabling bridging function\n");
-					unregister_netdevice_notifier(&br_dev_notifier);
 					br_stats.flags &= ~BR_UP;	/* disable bridge */
 					stop_hello_timer();
+#if 0					
 					for (i = One; i <= No_of_ports; i++)
 						if (port_info[i].state != Disabled)
 							disable_port(i);
+#endif							
 					break;
 				case BRCMD_PORT_ENABLE:
 					if (port_info[bcf.arg1].dev == 0)
@@ -1548,7 +1510,8 @@
 int br_cmp(unsigned int *a, unsigned int *b)
 {
 	int i;	
-	for (i=0; i<2; i++) {
+	for (i=0; i<2; i++) 
+	{
 		if (a[i] == b[i])
 			continue;
 		if (a[i] < b[i])

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this