aboutsummaryrefslogtreecommitdiff
path: root/net/bridge/br_fdb.c
diff options
context:
space:
mode:
authorstephen hemminger <shemminger@vyatta.com>2011-04-04 14:03:29 +0000
committerDavid S. Miller <davem@davemloft.net>2011-04-04 17:22:26 -0700
commit664de48bb6c4e167fcdf92a4bddf880030fbfbb3 (patch)
tree3da0ad964f1ad79f567ed04a5e5b32c201687787 /net/bridge/br_fdb.c
parent7cd8861ab0d907430bbea0af93bc41aee0437efc (diff)
bridge: split rcu and no-rcu cases of fdb lookup
In some cases, look up of forward database entry is done with RCU; and for others no RCU is needed because of locking. Split the two cases into two differnt loops (and take off inline). Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_fdb.c')
-rw-r--r--net/bridge/br_fdb.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index b39135285f8..a839a5d9d2c 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -305,8 +305,21 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf,
return num;
}
-static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
- const unsigned char *addr)
+static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
+ const unsigned char *addr)
+{
+ struct hlist_node *h;
+ struct net_bridge_fdb_entry *fdb;
+
+ hlist_for_each_entry(fdb, h, head, hlist) {
+ if (!compare_ether_addr(fdb->addr.addr, addr))
+ return fdb;
+ }
+ return NULL;
+}
+
+static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head,
+ const unsigned char *addr)
{
struct hlist_node *h;
struct net_bridge_fdb_entry *fdb;
@@ -393,7 +406,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
source->state == BR_STATE_FORWARDING))
return;
- fdb = fdb_find(head, addr);
+ fdb = fdb_find_rcu(head, addr);
if (likely(fdb)) {
/* attempt to update an entry for a local interface */
if (unlikely(fdb->is_local)) {