summary refs log tree commit diff
path: root/net/bridge/br_fdb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-15 09:40:05 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-15 09:40:05 -0700
commit2ed0e21b30b53d3a94e204196e523e6c8f732b56 (patch)
treede2635426477d86338a9469ce09ba0626052288f /net/bridge/br_fdb.c
parent0fa213310cd8fa7a51071cdcf130e26fa56e9549 (diff)
parent9cbc1cb8cd46ce1f7645b9de249b2ce8460129bb (diff)
downloadlinux-2ed0e21b30b53d3a94e204196e523e6c8f732b56.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1244 commits)
  pkt_sched: Rename PSCHED_US2NS and PSCHED_NS2US
  ipv4: Fix fib_trie rebalancing
  Bluetooth: Fix issue with uninitialized nsh.type in DTL-1 driver
  Bluetooth: Fix Kconfig issue with RFKILL integration
  PIM-SM: namespace changes
  ipv4: update ARPD help text
  net: use a deferred timer in rt_check_expire
  ieee802154: fix kconfig bool/tristate muckup
  bonding: initialization rework
  bonding: use is_zero_ether_addr
  bonding: network device names are case sensative
  bonding: elminate bad refcount code
  bonding: fix style issues
  bonding: fix destructor
  bonding: remove bonding read/write semaphore
  bonding: initialize before registration
  bonding: bond_create always called with default parameters
  x_tables: Convert printk to pr_err
  netfilter: conntrack: optional reliable conntrack event delivery
  list_nulls: add hlist_nulls_add_head and hlist_nulls_del
  ...
Diffstat (limited to 'net/bridge/br_fdb.c')
-rw-r--r--net/bridge/br_fdb.c45
1 files changed, 22 insertions, 23 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index a48f5efdb6bf..57bf05c353bc 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -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;
@@ -398,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 */