aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--net/atm/lec.c17
-rw-r--r--net/bridge/br.c10
-rw-r--r--net/bridge/br_fdb.c43
-rw-r--r--net/bridge/br_private.h12
-rw-r--r--net/core/dev.c20
5 files changed, 44 insertions, 58 deletions
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 199b6bb79f42..75b9d59553fc 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -34,7 +34,6 @@
34 34
35/* Proxy LEC knows about bridging */ 35/* Proxy LEC knows about bridging */
36#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) 36#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
37#include <linux/if_bridge.h>
38#include "../bridge/br_private.h" 37#include "../bridge/br_private.h"
39 38
40static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; 39static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
@@ -518,18 +517,14 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
518 case l_should_bridge: 517 case l_should_bridge:
519#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) 518#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
520 { 519 {
521 struct net_bridge_fdb_entry *f;
522
523 pr_debug("%s: bridge zeppelin asks about %pM\n", 520 pr_debug("%s: bridge zeppelin asks about %pM\n",
524 dev->name, mesg->content.proxy.mac_addr); 521 dev->name, mesg->content.proxy.mac_addr);
525 522
526 if (br_fdb_get_hook == NULL || dev->br_port == NULL) 523 if (br_fdb_test_addr_hook == NULL)
527 break; 524 break;
528 525
529 f = br_fdb_get_hook(dev->br_port->br, 526 if (br_fdb_test_addr_hook(dev,
530 mesg->content.proxy.mac_addr); 527 mesg->content.proxy.mac_addr)) {
531 if (f != NULL && f->dst->dev != dev
532 && f->dst->state == BR_STATE_FORWARDING) {
533 /* hit from bridge table, send LE_ARP_RESPONSE */ 528 /* hit from bridge table, send LE_ARP_RESPONSE */
534 struct sk_buff *skb2; 529 struct sk_buff *skb2;
535 struct sock *sk; 530 struct sock *sk;
@@ -540,10 +535,8 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
540 skb2 = 535 skb2 =
541 alloc_skb(sizeof(struct atmlec_msg), 536 alloc_skb(sizeof(struct atmlec_msg),
542 GFP_ATOMIC); 537 GFP_ATOMIC);
543 if (skb2 == NULL) { 538 if (skb2 == NULL)
544 br_fdb_put_hook(f);
545 break; 539 break;
546 }
547 skb2->len = sizeof(struct atmlec_msg); 540 skb2->len = sizeof(struct atmlec_msg);
548 skb_copy_to_linear_data(skb2, mesg, 541 skb_copy_to_linear_data(skb2, mesg,
549 sizeof(*mesg)); 542 sizeof(*mesg));
@@ -552,8 +545,6 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
552 skb_queue_tail(&sk->sk_receive_queue, skb2); 545 skb_queue_tail(&sk->sk_receive_queue, skb2);
553 sk->sk_data_ready(sk, skb2->len); 546 sk->sk_data_ready(sk, skb2->len);
554 } 547 }
555 if (f != NULL)
556 br_fdb_put_hook(f);
557 } 548 }
558#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ 549#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
559 break; 550 break;
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);
diff --git a/net/core/dev.c b/net/core/dev.c
index a09bf658970f..ea00e36f48e1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2071,11 +2071,13 @@ static inline int deliver_skb(struct sk_buff *skb,
2071} 2071}
2072 2072
2073#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE) 2073#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
2074/* These hooks defined here for ATM */ 2074
2075struct net_bridge; 2075#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
2076struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, 2076/* This hook is defined here for ATM LANE */
2077 unsigned char *addr); 2077int (*br_fdb_test_addr_hook)(struct net_device *dev,
2078void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly; 2078 unsigned char *addr) __read_mostly;
2079EXPORT_SYMBOL(br_fdb_test_addr_hook);
2080#endif
2079 2081
2080/* 2082/*
2081 * If bridge module is loaded call bridging hook. 2083 * If bridge module is loaded call bridging hook.
@@ -2083,6 +2085,8 @@ void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly;
2083 */ 2085 */
2084struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, 2086struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
2085 struct sk_buff *skb) __read_mostly; 2087 struct sk_buff *skb) __read_mostly;
2088EXPORT_SYMBOL(br_handle_frame_hook);
2089
2086static inline struct sk_buff *handle_bridge(struct sk_buff *skb, 2090static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
2087 struct packet_type **pt_prev, int *ret, 2091 struct packet_type **pt_prev, int *ret,
2088 struct net_device *orig_dev) 2092 struct net_device *orig_dev)
@@ -5665,12 +5669,6 @@ EXPORT_SYMBOL(net_enable_timestamp);
5665EXPORT_SYMBOL(net_disable_timestamp); 5669EXPORT_SYMBOL(net_disable_timestamp);
5666EXPORT_SYMBOL(dev_get_flags); 5670EXPORT_SYMBOL(dev_get_flags);
5667 5671
5668#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
5669EXPORT_SYMBOL(br_handle_frame_hook);
5670EXPORT_SYMBOL(br_fdb_get_hook);
5671EXPORT_SYMBOL(br_fdb_put_hook);
5672#endif
5673
5674EXPORT_SYMBOL(dev_load); 5672EXPORT_SYMBOL(dev_load);
5675 5673
5676EXPORT_PER_CPU_SYMBOL(softnet_data); 5674EXPORT_PER_CPU_SYMBOL(softnet_data);