转:http://blog.csdn.net/nerdx/article/details/12223547
-
-
-
-
-
-
-
-
-
-
-
1.1 void __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);
-
}
-
-
-
-
-
-
-
-
-
2.1 struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
-
const unsigned char *addr)
-
{
-
struct hlist_node *h;
-
struct net_bridge_fdb_entry *fdb;
-
-
hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) {
-
if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
-
if (unlikely(has_expired(br, fdb)))
-
break;
-
return fdb;
-
}
-
}
-
-
return NULL;
-
}
-
-
-
-
2.2 int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
-
const unsigned char *addr, int is_local)
-
{
-
int ret;
-
-
spin_lock_bh(&br->hash_lock);
-
ret = fdb_insert(br, source, addr, is_local);
-
spin_unlock_bh(&br->hash_lock);
-
return ret;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2.3 static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
-
const unsigned char *addr, int is_local)
-
{
-
struct hlist_node *h;
-
struct net_bridge_fdb_entry *fdb;
-
int hash = br_mac_hash(addr);
-
-
if (!is_valid_ether_addr(addr))
-
return -EADDRNOTAVAIL;
-
-
hlist_for_each_entry(fdb, h, &br->hash[hash], hlist) {
-
if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
-
if (fdb->is_local) {
-
if (is_local)
-
return 0;
-
-
return -EEXIST;
-
}
-
-
if (is_local) {
-
printk(KERN_WARNING "%s adding interface with same address "
-
"as a received packet\n",
-
source->dev->name);
-
goto update;
-
}
-
-
if (fdb->is_static)
-
return 0;
-
-
list_del(&fdb->u.age_list);
-
goto update;
-
}
-
}
-
-
fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
-
if (!fdb)
-
return ENOMEM;
-
-
memcpy(fdb->addr.addr, addr, ETH_ALEN);
-
atomic_set(&fdb->use_count, 1);
-
hlist_add_head_rcu(&fdb->hlist, &br->hash[hash]);
-
-
if (!timer_pending(&br->gc_timer)) {
-
br->gc_timer.expires = jiffies + hold_time(br);
-
add_timer(&br->gc_timer);
-
}
-
-
update:
-
fdb->dst = source;
-
fdb->is_local = is_local;
-
fdb->is_static = is_local;
-
fdb->ageing_timer = jiffies;
-
if (!is_local)
-
list_add_tail(&fdb->u.age_list, &br->age_list);
-
-
return 0;
-
}
-
-
-
-
-
-
-
-
-
-
-
2.5 void br_fdb_cleanup(unsigned long _data)
-
{
-
struct net_bridge *br = (struct net_bridge *)_data;
-
struct list_head *l, *n;
-
unsigned long delay;
-
-
spin_lock_bh(&br->hash_lock);
-
-
-
delay = hold_time(br);
-
-
list_for_each_safe(l, n, &br->age_list) {
-
struct net_bridge_fdb_entry *f;
-
unsigned long expires;
-
-
f = list_entry(l, struct net_bridge_fdb_entry, u.age_list);
-
expires = f->ageing_timer + delay;
-
-
if (time_before_eq(expires, jiffies)) {
-
WARN_ON(f->is_static);
-
pr_debug("expire age %lu jiffies %lu\n",
-
f->ageing_timer, jiffies);
-
fdb_delete(f);
-
} else {
-
mod_timer(&br->gc_timer, expires);
-
break;
-
}
-
}
-
spin_unlock_bh(&br->hash_lock);
-
}
-
-
-
2.6 static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f)
-
{
-
hlist_del_rcu(&f->hlist);
-
if (!f->is_static)
-
list_del(&f->u.age_list);
-
-
br_fdb_put(f);
-
}
-
阅读(593) | 评论(0) | 转发(0) |