net: skb->rtable accessor
[safe/jmp/linux-2.6] / net / bridge / br_fdb.c
index 91b0170..cb3e97b 100644 (file)
@@ -5,8 +5,6 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $Id: br_fdb.c,v 1.6 2002/01/17 00:57:07 davem Exp $
- *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
  *     as published by the Free Software Foundation; either version
@@ -15,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/rculist.h>
 #include <linux/spinlock.h>
 #include <linux/times.h>
 #include <linux/netdevice.h>
@@ -36,7 +35,7 @@ int __init br_fdb_init(void)
        br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
                                         sizeof(struct net_bridge_fdb_entry),
                                         0,
-                                        SLAB_HWCACHE_ALIGN, NULL, NULL);
+                                        SLAB_HWCACHE_ALIGN, NULL);
        if (!br_fdb_cache)
                return -ENOMEM;
 
@@ -44,7 +43,7 @@ int __init br_fdb_init(void)
        return 0;
 }
 
-void __exit br_fdb_fini(void)
+void br_fdb_fini(void)
 {
        kmem_cache_destroy(br_fdb_cache);
 }
@@ -121,6 +120,7 @@ void br_fdb_cleanup(unsigned long _data)
 {
        struct net_bridge *br = (struct net_bridge *)_data;
        unsigned long delay = hold_time(br);
+       unsigned long next_timer = jiffies + br->forward_delay;
        int i;
 
        spin_lock_bh(&br->hash_lock);
@@ -129,14 +129,21 @@ void br_fdb_cleanup(unsigned long _data)
                struct hlist_node *h, *n;
 
                hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) {
-                       if (!f->is_static &&
-                           time_before_eq(f->ageing_timer + delay, jiffies))
+                       unsigned long this_timer;
+                       if (f->is_static)
+                               continue;
+                       this_timer = f->ageing_timer + delay;
+                       if (time_before_eq(this_timer, jiffies))
                                fdb_delete(f);
+                       else if (time_before(this_timer, next_timer))
+                               next_timer = this_timer;
                }
        }
        spin_unlock_bh(&br->hash_lock);
 
-       mod_timer(&br->gc_timer, jiffies + HZ/10);
+       /* Add HZ/4 to ensure we round the jiffies upwards to be after the next
+        * timer, otherwise we might round down and will have no-op run. */
+       mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4));
 }
 
 /* Completely flush all dynamic entries in forwarding database.*/
@@ -277,7 +284,11 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf,
 
                        /* convert from internal format to API */
                        memcpy(fe->mac_addr, f->addr.addr, ETH_ALEN);
+
+                       /* due to ABI compat need to split into hi/lo */
                        fe->port_no = f->dst->port_no;
+                       fe->port_hi = f->dst->port_no >> 8;
+
                        fe->is_local = f->is_local;
                        if (!f->is_static)
                                fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->ageing_timer);
@@ -376,13 +387,18 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
        if (hold_time(br) == 0)
                return;
 
+       /* ignore packets unless we are using this port */
+       if (!(source->state == BR_STATE_LEARNING ||
+             source->state == BR_STATE_FORWARDING))
+               return;
+
        fdb = fdb_find(head, addr);
        if (likely(fdb)) {
                /* attempt to update an entry for a local interface */
                if (unlikely(fdb->is_local)) {
                        if (net_ratelimit())
                                printk(KERN_WARNING "%s: received packet with "
-                                      " own address as source address\n",
+                                      "own address as source address\n",
                                       source->dev->name);
                } else {
                        /* fastpath: update of existing entry */