aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorMichał Mirosław <mirq-linux@rere.qmqm.pl>2009-06-05 01:35:28 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-12 00:03:21 -0400
commitda6782927de809d9d427bd4bd6a4024243e41f13 (patch)
tree79419b352017a0c125c2b17e6a170589b31d8cb3 /net/bridge
parent746e6ad23cd6fec2edce056e014a0eabeffa838c (diff)
bridge: Simplify interface for ATM LANE
This patch changes FDB entry check for ATM LANE bridge integration. There's no point in holding a FDB entry around SKB building. br_fdb_get()/br_fdb_put() pair are changed into single br_fdb_test_addr() hook that checks if the addr has FDB entry pointing to other port to the one the request arrived on. FDB entry refcounting is removed as it's not used anywhere else. Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> Acked-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br.c10
-rw-r--r--net/bridge/br_fdb.c43
-rw-r--r--net/bridge/br_private.h12
3 files changed, 31 insertions, 34 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 4d2c1f1cb524..9aac5213105a 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -65,8 +65,9 @@ static int __init br_init(void)
65 brioctl_set(br_ioctl_deviceless_stub); 65 brioctl_set(br_ioctl_deviceless_stub);
66 br_handle_frame_hook = br_handle_frame; 66 br_handle_frame_hook = br_handle_frame;
67 67
68 br_fdb_get_hook = br_fdb_get; 68#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
69 br_fdb_put_hook = br_fdb_put; 69 br_fdb_test_addr_hook = br_fdb_test_addr;
70#endif
70 71
71 return 0; 72 return 0;
72err_out4: 73err_out4:
@@ -95,8 +96,9 @@ static void __exit br_deinit(void)
95 synchronize_net(); 96 synchronize_net();
96 97
97 br_netfilter_fini(); 98 br_netfilter_fini();
98 br_fdb_get_hook = NULL; 99#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
99 br_fdb_put_hook = NULL; 100 br_fdb_test_addr_hook = NULL;
101#endif
100 102
101 br_handle_frame_hook = NULL; 103 br_handle_frame_hook = NULL;
102 br_fdb_fini(); 104 br_fdb_fini();
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index cb3e97b93aeb..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)
71 return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1); 71 return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1);
72} 72}
73 73
74static void fdb_rcu_free(struct rcu_head *head)
75{
76 struct net_bridge_fdb_entry *ent
77 = container_of(head, struct net_bridge_fdb_entry, rcu);
78 kmem_cache_free(br_fdb_cache, ent);
79}
80
74static inline void fdb_delete(struct net_bridge_fdb_entry *f) 81static inline void fdb_delete(struct net_bridge_fdb_entry *f)
75{ 82{
76 hlist_del_rcu(&f->hlist); 83 hlist_del_rcu(&f->hlist);
77 br_fdb_put(f); 84 call_rcu(&f->rcu, fdb_rcu_free);
78} 85}
79 86
80void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) 87void 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,
226 return NULL; 233 return NULL;
227} 234}
228 235
229/* Interface used by ATM hook that keeps a ref count */ 236#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
230struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, 237/* Interface used by ATM LANE hook to test
231 unsigned char *addr) 238 * if an addr is on some other bridge port */
239int br_fdb_test_addr(struct net_device *dev, unsigned char *addr)
232{ 240{
233 struct net_bridge_fdb_entry *fdb; 241 struct net_bridge_fdb_entry *fdb;
242 int ret;
243
244 if (!dev->br_port)
245 return 0;
234 246
235 rcu_read_lock(); 247 rcu_read_lock();
236 fdb = __br_fdb_get(br, addr); 248 fdb = __br_fdb_get(dev->br_port->br, addr);
237 if (fdb && !atomic_inc_not_zero(&fdb->use_count)) 249 ret = fdb && fdb->dst->dev != dev &&
238 fdb = NULL; 250 fdb->dst->state == BR_STATE_FORWARDING;
239 rcu_read_unlock(); 251 rcu_read_unlock();
240 return fdb;
241}
242
243static void fdb_rcu_free(struct rcu_head *head)
244{
245 struct net_bridge_fdb_entry *ent
246 = container_of(head, struct net_bridge_fdb_entry, rcu);
247 kmem_cache_free(br_fdb_cache, ent);
248}
249 252
250/* Set entry up for deletion with RCU */ 253 return ret;
251void br_fdb_put(struct net_bridge_fdb_entry *ent)
252{
253 if (atomic_dec_and_test(&ent->use_count))
254 call_rcu(&ent->rcu, fdb_rcu_free);
255} 254}
255#endif /* CONFIG_ATM_LANE */
256 256
257/* 257/*
258 * Fill buffer with forwarding table records in 258 * Fill buffer with forwarding table records in
@@ -326,7 +326,6 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
326 fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC); 326 fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
327 if (fdb) { 327 if (fdb) {
328 memcpy(fdb->addr.addr, addr, ETH_ALEN); 328 memcpy(fdb->addr.addr, addr, ETH_ALEN);
329 atomic_set(&fdb->use_count, 1);
330 hlist_add_head_rcu(&fdb->hlist, head); 329 hlist_add_head_rcu(&fdb->hlist, head);
331 330
332 fdb->dst = source; 331 fdb->dst = source;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index b6c3b71974dc..d5b5537272b4 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -51,7 +51,6 @@ struct net_bridge_fdb_entry
51 struct net_bridge_port *dst; 51 struct net_bridge_port *dst;
52 52
53 struct rcu_head rcu; 53 struct rcu_head rcu;
54 atomic_t use_count;
55 unsigned long ageing_timer; 54 unsigned long ageing_timer;
56 mac_addr addr; 55 mac_addr addr;
57 unsigned char is_local; 56 unsigned char is_local;
@@ -154,9 +153,7 @@ extern void br_fdb_delete_by_port(struct net_bridge *br,
154 const struct net_bridge_port *p, int do_all); 153 const struct net_bridge_port *p, int do_all);
155extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, 154extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
156 const unsigned char *addr); 155 const unsigned char *addr);
157extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, 156extern int br_fdb_test_addr(struct net_device *dev, unsigned char *addr);
158 unsigned char *addr);
159extern void br_fdb_put(struct net_bridge_fdb_entry *ent);
160extern int br_fdb_fillbuf(struct net_bridge *br, void *buf, 157extern int br_fdb_fillbuf(struct net_bridge *br, void *buf,
161 unsigned long count, unsigned long off); 158 unsigned long count, unsigned long off);
162extern int br_fdb_insert(struct net_bridge *br, 159extern int br_fdb_insert(struct net_bridge *br,
@@ -242,10 +239,9 @@ extern void br_stp_port_timer_init(struct net_bridge_port *p);
242extern unsigned long br_timer_value(const struct timer_list *timer); 239extern unsigned long br_timer_value(const struct timer_list *timer);
243 240
244/* br.c */ 241/* br.c */
245extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, 242#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
246 unsigned char *addr); 243extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr);
247extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); 244#endif
248
249 245
250/* br_netlink.c */ 246/* br_netlink.c */
251extern int br_netlink_init(void); 247extern int br_netlink_init(void);