bridge br_multicast: Fix handling of Max Response Code in IGMPv3 message.
[safe/jmp/linux-2.6] / net / bridge / br_fdb.c
index 4de74cd..3b8e038 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/rculist.h>
 #include <linux/spinlock.h>
 #include <linux/times.h>
 #include <linux/netdevice.h>
@@ -59,8 +60,8 @@ static inline unsigned long hold_time(const struct net_bridge *br)
 static inline int has_expired(const struct net_bridge *br,
                                  const struct net_bridge_fdb_entry *fdb)
 {
-       return !fdb->is_static
-               && time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
+       return !fdb->is_static &&
+               time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
 }
 
 static inline int br_mac_hash(const unsigned char *mac)
@@ -70,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)
@@ -225,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
@@ -325,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;
@@ -397,7 +397,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
                if (unlikely(fdb->is_local)) {
                        if (net_ratelimit())
                                printk(KERN_WARNING "%s: received packet with "
-                                      " own address as source address\n",
+                                      "own address as source address\n",
                                       source->dev->name);
                } else {
                        /* fastpath: update of existing entry */