|
@@ -71,10 +71,17 @@ static inline int br_mac_hash(const unsigned char *mac)
|
|
|
return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1);
|
|
|
}
|
|
|
|
|
|
+static void fdb_rcu_free(struct rcu_head *head)
|
|
|
+{
|
|
|
+ struct net_bridge_fdb_entry *ent
|
|
|
+ = container_of(head, struct net_bridge_fdb_entry, rcu);
|
|
|
+ kmem_cache_free(br_fdb_cache, ent);
|
|
|
+}
|
|
|
+
|
|
|
static inline void fdb_delete(struct net_bridge_fdb_entry *f)
|
|
|
{
|
|
|
hlist_del_rcu(&f->hlist);
|
|
|
- br_fdb_put(f);
|
|
|
+ call_rcu(&f->rcu, fdb_rcu_free);
|
|
|
}
|
|
|
|
|
|
void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
|
|
@@ -226,33 +233,26 @@ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/* Interface used by ATM hook that keeps a ref count */
|
|
|
-struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
|
|
|
- unsigned char *addr)
|
|
|
+#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
|
|
|
+/* Interface used by ATM LANE hook to test
|
|
|
+ * if an addr is on some other bridge port */
|
|
|
+int br_fdb_test_addr(struct net_device *dev, unsigned char *addr)
|
|
|
{
|
|
|
struct net_bridge_fdb_entry *fdb;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!dev->br_port)
|
|
|
+ return 0;
|
|
|
|
|
|
rcu_read_lock();
|
|
|
- fdb = __br_fdb_get(br, addr);
|
|
|
- if (fdb && !atomic_inc_not_zero(&fdb->use_count))
|
|
|
- fdb = NULL;
|
|
|
+ fdb = __br_fdb_get(dev->br_port->br, addr);
|
|
|
+ ret = fdb && fdb->dst->dev != dev &&
|
|
|
+ fdb->dst->state == BR_STATE_FORWARDING;
|
|
|
rcu_read_unlock();
|
|
|
- return fdb;
|
|
|
-}
|
|
|
-
|
|
|
-static void fdb_rcu_free(struct rcu_head *head)
|
|
|
-{
|
|
|
- struct net_bridge_fdb_entry *ent
|
|
|
- = container_of(head, struct net_bridge_fdb_entry, rcu);
|
|
|
- kmem_cache_free(br_fdb_cache, ent);
|
|
|
-}
|
|
|
|
|
|
-/* Set entry up for deletion with RCU */
|
|
|
-void br_fdb_put(struct net_bridge_fdb_entry *ent)
|
|
|
-{
|
|
|
- if (atomic_dec_and_test(&ent->use_count))
|
|
|
- call_rcu(&ent->rcu, fdb_rcu_free);
|
|
|
+ return ret;
|
|
|
}
|
|
|
+#endif /* CONFIG_ATM_LANE */
|
|
|
|
|
|
/*
|
|
|
* Fill buffer with forwarding table records in
|
|
@@ -326,7 +326,6 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
|
|
|
fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
|
|
|
if (fdb) {
|
|
|
memcpy(fdb->addr.addr, addr, ETH_ALEN);
|
|
|
- atomic_set(&fdb->use_count, 1);
|
|
|
hlist_add_head_rcu(&fdb->hlist, head);
|
|
|
|
|
|
fdb->dst = source;
|