aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_fdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_fdb.c')
-rw-r--r--net/bridge/br_fdb.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 8d566c13cc73..91b017016d5b 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -20,19 +20,28 @@
20#include <linux/netdevice.h> 20#include <linux/netdevice.h>
21#include <linux/etherdevice.h> 21#include <linux/etherdevice.h>
22#include <linux/jhash.h> 22#include <linux/jhash.h>
23#include <linux/random.h>
23#include <asm/atomic.h> 24#include <asm/atomic.h>
25#include <asm/unaligned.h>
24#include "br_private.h" 26#include "br_private.h"
25 27
26static struct kmem_cache *br_fdb_cache __read_mostly; 28static struct kmem_cache *br_fdb_cache __read_mostly;
27static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, 29static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
28 const unsigned char *addr); 30 const unsigned char *addr);
29 31
30void __init br_fdb_init(void) 32static u32 fdb_salt __read_mostly;
33
34int __init br_fdb_init(void)
31{ 35{
32 br_fdb_cache = kmem_cache_create("bridge_fdb_cache", 36 br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
33 sizeof(struct net_bridge_fdb_entry), 37 sizeof(struct net_bridge_fdb_entry),
34 0, 38 0,
35 SLAB_HWCACHE_ALIGN, NULL, NULL); 39 SLAB_HWCACHE_ALIGN, NULL, NULL);
40 if (!br_fdb_cache)
41 return -ENOMEM;
42
43 get_random_bytes(&fdb_salt, sizeof(fdb_salt));
44 return 0;
36} 45}
37 46
38void __exit br_fdb_fini(void) 47void __exit br_fdb_fini(void)
@@ -44,24 +53,26 @@ void __exit br_fdb_fini(void)
44/* if topology_changing then use forward_delay (default 15 sec) 53/* if topology_changing then use forward_delay (default 15 sec)
45 * otherwise keep longer (default 5 minutes) 54 * otherwise keep longer (default 5 minutes)
46 */ 55 */
47static __inline__ unsigned long hold_time(const struct net_bridge *br) 56static inline unsigned long hold_time(const struct net_bridge *br)
48{ 57{
49 return br->topology_change ? br->forward_delay : br->ageing_time; 58 return br->topology_change ? br->forward_delay : br->ageing_time;
50} 59}
51 60
52static __inline__ int has_expired(const struct net_bridge *br, 61static inline int has_expired(const struct net_bridge *br,
53 const struct net_bridge_fdb_entry *fdb) 62 const struct net_bridge_fdb_entry *fdb)
54{ 63{
55 return !fdb->is_static 64 return !fdb->is_static
56 && time_before_eq(fdb->ageing_timer + hold_time(br), jiffies); 65 && time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
57} 66}
58 67
59static __inline__ int br_mac_hash(const unsigned char *mac) 68static inline int br_mac_hash(const unsigned char *mac)
60{ 69{
61 return jhash(mac, ETH_ALEN, 0) & (BR_HASH_SIZE - 1); 70 /* use 1 byte of OUI cnd 3 bytes of NIC */
71 u32 key = get_unaligned((u32 *)(mac + 2));
72 return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1);
62} 73}
63 74
64static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f) 75static inline void fdb_delete(struct net_bridge_fdb_entry *f)
65{ 76{
66 hlist_del_rcu(&f->hlist); 77 hlist_del_rcu(&f->hlist);
67 br_fdb_put(f); 78 br_fdb_put(f);
@@ -128,7 +139,26 @@ void br_fdb_cleanup(unsigned long _data)
128 mod_timer(&br->gc_timer, jiffies + HZ/10); 139 mod_timer(&br->gc_timer, jiffies + HZ/10);
129} 140}
130 141
142/* Completely flush all dynamic entries in forwarding database.*/
143void br_fdb_flush(struct net_bridge *br)
144{
145 int i;
131 146
147 spin_lock_bh(&br->hash_lock);
148 for (i = 0; i < BR_HASH_SIZE; i++) {
149 struct net_bridge_fdb_entry *f;
150 struct hlist_node *h, *n;
151 hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) {
152 if (!f->is_static)
153 fdb_delete(f);
154 }
155 }
156 spin_unlock_bh(&br->hash_lock);
157}
158
159/* Flush all entries refering to a specific port.
160 * if do_all is set also flush static entries
161 */
132void br_fdb_delete_by_port(struct net_bridge *br, 162void br_fdb_delete_by_port(struct net_bridge *br,
133 const struct net_bridge_port *p, 163 const struct net_bridge_port *p,
134 int do_all) 164 int do_all)