diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
commit | db7d4daea91e105e3859cf461d7e53b9b77454b2 (patch) | |
tree | 9bb65b95440af09e8aca63abe56970dd3360cc57 /net/bridge | |
parent | 9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff) |
Merge with Linux 2.2.8.
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br.c | 55 | ||||
-rw-r--r-- | net/bridge/br_tree.c | 24 |
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; +} |