summaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
commitdb7d4daea91e105e3859cf461d7e53b9b77454b2 (patch)
tree9bb65b95440af09e8aca63abe56970dd3360cc57 /net/bridge
parent9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff)
Merge with Linux 2.2.8.
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br.c55
-rw-r--r--net/bridge/br_tree.c24
2 files changed, 75 insertions, 4 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 204b00ca0..996aeb718 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -6,7 +6,7 @@
* More hacks to be able to switch protocols on and off by Christoph Lameter
* <clameter@debian.org>
* Software and more Documentation for the bridge is available from ftp.debian.org
- * in the bridge package or at ftp.fuller.edu/Linux/bridge
+ * in the bridgex package
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -63,7 +63,6 @@
#include <linux/net.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
-#include <linux/string.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/ip.h>
@@ -1239,6 +1238,13 @@ static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
struct sk_buff *skb;
/*
+ * Keep silent when disabled or when STP disabled
+ */
+
+ if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
+ return -1;
+
+ /*
* Create and send the message
*/
@@ -1270,6 +1276,14 @@ static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
{
struct sk_buff *skb;
+
+ /*
+ * Keep silent when disabled or when STP disabled
+ */
+
+ if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
+ return -1;
+
skb = alloc_bridge_skb(port_no, sizeof(Tcn_bpdu), "tcn");
if (skb == NULL)
@@ -1336,13 +1350,25 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
enable_port(i);
set_path_cost(i, br_port_cost(dev));
set_port_priority(i);
- make_forwarding(i);
+ if (br_stats.flags & BR_STP_DISABLED)
+ port_info[i].state = Forwarding;
+ else
+ make_forwarding(i);
}
return NOTIFY_DONE;
break;
}
}
break;
+ case NETDEV_UNREGISTER:
+ if (br_stats.flags & BR_DEBUG)
+ printk(KERN_DEBUG "br_device_event: NETDEV_UNREGISTER...\n");
+ i = find_port(dev);
+ if (i > 0) {
+ br_avl_delete_by_port(i);
+ port_info[i].dev = NULL;
+ }
+ break;
}
return NOTIFY_DONE;
}
@@ -1833,6 +1859,8 @@ static int find_port(struct device *dev)
static int br_port_cost(struct device *dev) /* 4.10.2 */
{
+ if (strncmp(dev->name, "lec", 3) == 0) /* ATM Lan Emulation (LANE) */
+ return(7); /* 155 Mbs */
if (strncmp(dev->name, "eth", 3) == 0) /* ethernet */
return(100);
if (strncmp(dev->name, "plip",4) == 0) /* plip */
@@ -1850,7 +1878,8 @@ static void br_bpdu(struct sk_buff *skb, int port) /* consumes skb */
Tcn_bpdu *bpdu = (Tcn_bpdu *) (bufp + BRIDGE_LLC1_HS);
Config_bpdu rcv_bpdu;
- if((*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
+ if(!(br_stats.flags & BR_STP_DISABLED) &&
+ (*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
(*bufp++ == BRIDGE_LLC1_CTRL) &&
(bpdu->protocol_id == BRIDGE_BPDU_8021_PROTOCOL_ID) &&
(bpdu->protocol_version_id == BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID))
@@ -1970,6 +1999,10 @@ int br_ioctl(unsigned int cmd, void *arg)
}
}
port_state_selection(); /* (4.8.1.5) */
+ if (br_stats.flags & BR_STP_DISABLED)
+ for(i=One;i<=No_of_ports; i++)
+ if((user_port_state[i] != Disabled) && port_info[i].dev)
+ port_info[i].state = Forwarding;
config_bpdu_generation(); /* (4.8.1.6) */
/* initialize system timer */
tl.expires = jiffies+HZ; /* 1 second */
@@ -1987,6 +2020,20 @@ int br_ioctl(unsigned int cmd, void *arg)
if (port_info[i].state != Disabled)
disable_port(i);
break;
+ case BRCMD_TOGGLE_STP:
+ printk(KERN_DEBUG "br: %s spanning tree protcol\n",
+ (br_stats.flags & BR_STP_DISABLED) ? "enabling" : "disabling");
+ if (br_stats.flags & BR_STP_DISABLED) { /* enable STP */
+ for(i=One;i<=No_of_ports; i++)
+ if((user_port_state[i] != Disabled) && port_info[i].dev)
+ enable_port(i);
+ } else { /* STP was enabled, now disable it */
+ for (i = One; i <= No_of_ports; i++)
+ if (port_info[i].state != Disabled && port_info[i].dev)
+ port_info[i].state = Forwarding;
+ }
+ br_stats.flags ^= BR_STP_DISABLED;
+ break;
case BRCMD_PORT_ENABLE:
if (port_info[bcf.arg1].dev == 0)
return(-EINVAL);
diff --git a/net/bridge/br_tree.c b/net/bridge/br_tree.c
index 0936a0f8b..c1ed82f10 100644
--- a/net/bridge/br_tree.c
+++ b/net/bridge/br_tree.c
@@ -474,3 +474,27 @@ void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,
return;
}
+
+/*
+ * Delete all nodes learnt by the port
+ */
+void br_avl_delete_by_port(int port)
+{
+ struct fdb *fdb, *next;
+
+ if (!fdb_inited)
+ fdb_init();
+
+ for(fdb = port_info[port].fdb; fdb != NULL; fdb = next) {
+ next = fdb->fdb_next;
+ br_avl_remove(fdb);
+ }
+ port_info[port].fdb = NULL;
+
+ /* remove the local mac too */
+ next = br_avl_find_addr(port_info[port].dev->dev_addr);
+ if (next != NULL)
+ br_avl_remove(next);
+
+ return;
+}