diff options
| author | Stephen Hemminger <shemminger@osdl.org> | 2004-04-16 00:19:54 -0700 |
|---|---|---|
| committer | Stephen Hemminger <shemminger@osdl.org> | 2004-04-16 00:19:54 -0700 |
| commit | 5c648dca17cbe6be1b1a0f3fe5f0542cf79c65cd (patch) | |
| tree | b6b8f76241bfc38f7f694876aad860db81f1dcd3 /net | |
| parent | 045b897431e39d926ace8c46bac58acc4a3e2d34 (diff) | |
[BRIDGE]: Forwarding database changes.
Make forwarding database more robust.
+ Don't insert invalid ether address,
+ Report errors back so adding an interface to bridge can fail
+ get rid of unneeded explicit pads in data structure
+ replace bitfields with byte's for simple booleans.
Diffstat (limited to 'net')
| -rw-r--r-- | net/bridge/br_fdb.c | 16 | ||||
| -rw-r--r-- | net/bridge/br_if.c | 4 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 13 |
3 files changed, 22 insertions, 11 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index d82738264581..e4c548690be9 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -17,6 +17,7 @@ #include <linux/spinlock.h> #include <linux/if_bridge.h> #include <linux/times.h> +#include <linux/etherdevice.h> #include <asm/atomic.h> #include <asm/uaccess.h> #include "br_private.h" @@ -242,12 +243,16 @@ int br_fdb_get_entries(struct net_bridge *br, return num; } -void br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, - const unsigned char *addr, int is_local) +int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, + const unsigned char *addr, int is_local) { struct hlist_node *h; struct net_bridge_fdb_entry *fdb; int hash = br_mac_hash(addr); + int ret = 0; + + if (!is_valid_ether_addr(addr)) + return -EADDRNOTAVAIL; write_lock_bh(&br->hash_lock); hlist_for_each(h, &br->hash[hash]) { @@ -263,6 +268,7 @@ void br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, printk(KERN_WARNING "%s: received packet with " " own address as source address\n", source->dev->name); + ret = -EEXIST; goto out; } @@ -277,8 +283,10 @@ void br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, } fdb = kmalloc(sizeof(*fdb), GFP_ATOMIC); - if (fdb == NULL) + if (unlikely(fdb == NULL)) { + ret = -ENOMEM; goto out; + } memcpy(fdb->addr.addr, addr, ETH_ALEN); atomic_set(&fdb->use_count, 1); @@ -297,4 +305,6 @@ void br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, list_add_tail(&fdb->age_list, &br->age_list); out: write_unlock_bh(&br->hash_lock); + + return ret; } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 9c31907dbe2c..9d59dac9fb89 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -277,13 +277,15 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) else if (IS_ERR(p = new_nbp(br, dev, cost))) err = PTR_ERR(p); + else if ((err = br_fdb_insert(br, p, dev->dev_addr, 1))) + destroy_nbp(p); + else { dev_set_promiscuity(dev, 1); list_add_rcu(&p->list, &br->port_list); br_stp_recalculate_bridge_id(br); - br_fdb_insert(br, p, dev->dev_addr, 1); if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP)) br_stp_enable_port(p); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 5b1e0947e848..a7e7cf38106c 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -37,7 +37,6 @@ struct bridge_id struct mac_addr { unsigned char addr[6]; - unsigned char pad[2]; }; struct net_bridge_fdb_entry @@ -48,8 +47,8 @@ struct net_bridge_fdb_entry atomic_t use_count; unsigned long ageing_timer; mac_addr addr; - unsigned is_local:1; - unsigned is_static:1; + unsigned char is_local; + unsigned char is_static; }; struct net_bridge_port @@ -137,10 +136,10 @@ extern int br_fdb_get_entries(struct net_bridge *br, unsigned char *_buf, int maxnum, int offset); -extern void br_fdb_insert(struct net_bridge *br, - struct net_bridge_port *source, - const unsigned char *addr, - int is_local); +extern int br_fdb_insert(struct net_bridge *br, + struct net_bridge_port *source, + const unsigned char *addr, + int is_local); /* br_forward.c */ extern void br_deliver(const struct net_bridge_port *to, |
