On Fri, 5 Jun 2009 13:12:12 +0200
Michał Mirosław <[email protected]> wrote:

> 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 for anything else.
> 
> Signed-off-by: Michał Mirosław <[email protected]>
> 
> diff -urpN patched/net/atm/lec.c patched2/net/atm/lec.c
> --- patched/net/atm/lec.c     2009-03-24 00:12:14.000000000 +0100
> +++ patched2/net/atm/lec.c    2009-06-03 12:45:23.000000000 +0200
> @@ -34,7 +34,6 @@
>  
>  /* Proxy LEC knows about bridging */
>  #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
> -#include <linux/if_bridge.h>
>  #include "../bridge/br_private.h"
>  
>  static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
> @@ -528,18 +527,14 @@ static int lec_atm_send(struct atm_vcc *
>       case l_should_bridge:
>  #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
>               {
> -                     struct net_bridge_fdb_entry *f;
> -
>                       pr_debug("%s: bridge zeppelin asks about %pM\n",
>                                dev->name, mesg->content.proxy.mac_addr);
>  
> -                     if (br_fdb_get_hook == NULL || dev->br_port == NULL)
> +                     if (br_fdb_test_addr_hook == NULL)
>                               break;
>  
> -                     f = br_fdb_get_hook(dev->br_port->br,
> -                                         mesg->content.proxy.mac_addr);
> -                     if (f != NULL && f->dst->dev != dev
> -                         && f->dst->state == BR_STATE_FORWARDING) {
> +                     if (br_fdb_test_addr_hook(dev,
> +                                     mesg->content.proxy.mac_addr)) {
>                               /* hit from bridge table, send LE_ARP_RESPONSE 
> */
>                               struct sk_buff *skb2;
>                               struct sock *sk;
> @@ -550,10 +545,8 @@ static int lec_atm_send(struct atm_vcc *
>                               skb2 =
>                                   alloc_skb(sizeof(struct atmlec_msg),
>                                             GFP_ATOMIC);
> -                             if (skb2 == NULL) {
> -                                     br_fdb_put_hook(f);
> +                             if (skb2 == NULL)
>                                       break;
> -                             }
>                               skb2->len = sizeof(struct atmlec_msg);
>                               skb_copy_to_linear_data(skb2, mesg,
>                                                       sizeof(*mesg));
> @@ -562,8 +555,6 @@ static int lec_atm_send(struct atm_vcc *
>                               skb_queue_tail(&sk->sk_receive_queue, skb2);
>                               sk->sk_data_ready(sk, skb2->len);
>                       }
> -                     if (f != NULL)
> -                             br_fdb_put_hook(f);
>               }
>  #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
>               break;
> diff -urpN patched/net/bridge/br.c patched2/net/bridge/br.c
> --- patched/net/bridge/br.c   2009-03-24 00:12:14.000000000 +0100
> +++ patched2/net/bridge/br.c  2009-06-03 12:54:49.000000000 +0200
> @@ -65,8 +65,9 @@ static int __init br_init(void)
>       brioctl_set(br_ioctl_deviceless_stub);
>       br_handle_frame_hook = br_handle_frame;
>  
> -     br_fdb_get_hook = br_fdb_get;
> -     br_fdb_put_hook = br_fdb_put;
> +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
> +     br_fdb_test_addr_hook = br_fdb_test_addr;
> +#endif
>  
>       return 0;
>  err_out4:
> @@ -95,8 +96,9 @@ static void __exit br_deinit(void)
>       synchronize_net();
>  
>       br_netfilter_fini();
> -     br_fdb_get_hook = NULL;
> -     br_fdb_put_hook = NULL;
> +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
> +     br_fdb_test_addr_hook = NULL;
> +#endif
>  
>       br_handle_frame_hook = NULL;
>       br_fdb_fini();
> diff -urpN patched/net/bridge/br_fdb.c patched2/net/bridge/br_fdb.c
> --- patched/net/bridge/br_fdb.c       2009-03-24 00:12:14.000000000 +0100
> +++ patched2/net/bridge/br_fdb.c      2009-06-03 13:43:19.000000000 +0200
> @@ -71,10 +71,17 @@ static inline int br_mac_hash(const unsi
>       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_ge
>       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_
>       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;
> diff -urpN patched/net/bridge/br_private.h patched2/net/bridge/br_private.h
> --- patched/net/bridge/br_private.h   2009-03-24 00:12:14.000000000 +0100
> +++ patched2/net/bridge/br_private.h  2009-06-03 12:56:53.000000000 +0200
> @@ -51,7 +51,6 @@ struct net_bridge_fdb_entry
>       struct net_bridge_port          *dst;
>  
>       struct rcu_head                 rcu;
> -     atomic_t                        use_count;
>       unsigned long                   ageing_timer;
>       mac_addr                        addr;
>       unsigned char                   is_local;
> @@ -154,9 +153,7 @@ extern void br_fdb_delete_by_port(struct
>                                 const struct net_bridge_port *p, int do_all);
>  extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
>                                                const unsigned char *addr);
> -extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
> -                                            unsigned char *addr);
> -extern void br_fdb_put(struct net_bridge_fdb_entry *ent);
> +extern int br_fdb_test_addr(struct net_device *dev, unsigned char *addr);
>  extern int br_fdb_fillbuf(struct net_bridge *br, void *buf,
>                         unsigned long count, unsigned long off);
>  extern int br_fdb_insert(struct net_bridge *br,
> @@ -242,10 +239,9 @@ extern void br_stp_port_timer_init(struc
>  extern unsigned long br_timer_value(const struct timer_list *timer);
>  
>  /* br.c */
> -extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
> -                                                    unsigned char *addr);
> -extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
> -
> +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
> +extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char 
> *addr);
> +#endif
>  
>  /* br_netlink.c */
>  extern int br_netlink_init(void);
> diff -urpN patched/net/core/dev.c patched2/net/core/dev.c
> --- patched/net/core/dev.c    2009-03-24 00:12:14.000000000 +0100
> +++ patched2/net/core/dev.c   2009-06-03 12:36:41.000000000 +0200
> @@ -2062,11 +2062,13 @@ static inline int deliver_skb(struct sk_
>  }
>  
>  #if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
> -/* These hooks defined here for ATM */
> -struct net_bridge;
> -struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
> -                                             unsigned char *addr);
> -void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly;
> +
> +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
> +/* This hook is defined here for ATM LANE */
> +int (*br_fdb_test_addr_hook)(struct net_device *dev,
> +                          unsigned char *addr) __read_mostly;
> +EXPORT_SYMBOL(br_fdb_test_addr_hook);
> +#endif
>  
>  /*
>   * If bridge module is loaded call bridging hook.
> @@ -2074,6 +2076,8 @@ void (*br_fdb_put_hook)(struct net_bridg
>   */
>  struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
>                                       struct sk_buff *skb) __read_mostly;
> +EXPORT_SYMBOL(br_handle_frame_hook);
> +
>  static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
>                                           struct packet_type **pt_prev, int 
> *ret,
>                                           struct net_device *orig_dev)
> @@ -5266,12 +5270,6 @@ EXPORT_SYMBOL(net_enable_timestamp);
>  EXPORT_SYMBOL(net_disable_timestamp);
>  EXPORT_SYMBOL(dev_get_flags);
>  
> -#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
> -EXPORT_SYMBOL(br_handle_frame_hook);
> -EXPORT_SYMBOL(br_fdb_get_hook);
> -EXPORT_SYMBOL(br_fdb_put_hook);
> -#endif
> -
>  EXPORT_SYMBOL(dev_load);
>  
>  EXPORT_PER_CPU_SYMBOL(softnet_data);

Okay by me as long as some with ATM HW has tested this.

Acked-by: Stephen Hemminger <[email protected]>

-- 
_______________________________________________
Bridge mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/bridge

Reply via email to