summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2004-04-16 00:19:54 -0700
committerStephen Hemminger <shemminger@osdl.org>2004-04-16 00:19:54 -0700
commit5c648dca17cbe6be1b1a0f3fe5f0542cf79c65cd (patch)
treeb6b8f76241bfc38f7f694876aad860db81f1dcd3 /net
parent045b897431e39d926ace8c46bac58acc4a3e2d34 (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.c16
-rw-r--r--net/bridge/br_if.c4
-rw-r--r--net/bridge/br_private.h13
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,