diff options
author | Michał Mirosław <mirq-linux@rere.qmqm.pl> | 2009-06-05 01:35:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-12 00:03:21 -0400 |
commit | da6782927de809d9d427bd4bd6a4024243e41f13 (patch) | |
tree | 79419b352017a0c125c2b17e6a170589b31d8cb3 /net | |
parent | 746e6ad23cd6fec2edce056e014a0eabeffa838c (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')
-rw-r--r-- | net/atm/lec.c | 17 | ||||
-rw-r--r-- | net/bridge/br.c | 10 | ||||
-rw-r--r-- | net/bridge/br_fdb.c | 43 | ||||
-rw-r--r-- | net/bridge/br_private.h | 12 | ||||
-rw-r--r-- | net/core/dev.c | 20 |
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 | ||
40 | static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; | 39 | static 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; |
72 | err_out4: | 73 | err_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 | ||
74 | static 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 | |||
74 | static inline void fdb_delete(struct net_bridge_fdb_entry *f) | 81 | static 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 | ||
80 | void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) | 87 | 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, | |||
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) |
230 | struct 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 */ |
239 | int 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 | |||
243 | static 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; |
251 | void 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); |
155 | extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, | 154 | extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, |
156 | const unsigned char *addr); | 155 | const unsigned char *addr); |
157 | extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, | 156 | extern int br_fdb_test_addr(struct net_device *dev, unsigned char *addr); |
158 | unsigned char *addr); | ||
159 | extern void br_fdb_put(struct net_bridge_fdb_entry *ent); | ||
160 | extern int br_fdb_fillbuf(struct net_bridge *br, void *buf, | 157 | extern int br_fdb_fillbuf(struct net_bridge *br, void *buf, |
161 | unsigned long count, unsigned long off); | 158 | unsigned long count, unsigned long off); |
162 | extern int br_fdb_insert(struct net_bridge *br, | 159 | extern int br_fdb_insert(struct net_bridge *br, |
@@ -242,10 +239,9 @@ extern void br_stp_port_timer_init(struct net_bridge_port *p); | |||
242 | extern unsigned long br_timer_value(const struct timer_list *timer); | 239 | extern unsigned long br_timer_value(const struct timer_list *timer); |
243 | 240 | ||
244 | /* br.c */ | 241 | /* br.c */ |
245 | extern 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); | 243 | extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr); |
247 | extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); | 244 | #endif |
248 | |||
249 | 245 | ||
250 | /* br_netlink.c */ | 246 | /* br_netlink.c */ |
251 | extern int br_netlink_init(void); | 247 | extern 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 | |
2075 | struct net_bridge; | 2075 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
2076 | struct 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); | 2077 | int (*br_fdb_test_addr_hook)(struct net_device *dev, |
2078 | void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly; | 2078 | unsigned char *addr) __read_mostly; |
2079 | EXPORT_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 | */ |
2084 | struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, | 2086 | struct 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; |
2088 | EXPORT_SYMBOL(br_handle_frame_hook); | ||
2089 | |||
2086 | static inline struct sk_buff *handle_bridge(struct sk_buff *skb, | 2090 | static 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); | |||
5665 | EXPORT_SYMBOL(net_disable_timestamp); | 5669 | EXPORT_SYMBOL(net_disable_timestamp); |
5666 | EXPORT_SYMBOL(dev_get_flags); | 5670 | EXPORT_SYMBOL(dev_get_flags); |
5667 | 5671 | ||
5668 | #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) | ||
5669 | EXPORT_SYMBOL(br_handle_frame_hook); | ||
5670 | EXPORT_SYMBOL(br_fdb_get_hook); | ||
5671 | EXPORT_SYMBOL(br_fdb_put_hook); | ||
5672 | #endif | ||
5673 | |||
5674 | EXPORT_SYMBOL(dev_load); | 5672 | EXPORT_SYMBOL(dev_load); |
5675 | 5673 | ||
5676 | EXPORT_PER_CPU_SYMBOL(softnet_data); | 5674 | EXPORT_PER_CPU_SYMBOL(softnet_data); |