------------------------------------------------------------------------------------------
以下是我根据 linux-2.6.23.9版本内核源代码所做阅读笔记,属个人兴趣而为,希望找到有共同兴趣
的朋友一起讨论和研究,有谬误之处,笔者水平有限,欢迎大家拍砖:)
------------------------------------------------------------------------------------------
CAM表的更新
static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
const unsigned char *addr)
{
struct hlist_head *head = &br->hash[br_mac_hash(addr)];
struct net_bridge_fdb_entry *fdb;
//检查地址的有效性,这个地址不能是广播地址,也不能是
//为0的地址
if (!is_valid_ether_addr(addr))
return -EINVAL;
//从链表头开始查找需要插入的fdb已经存在
fdb = fdb_find(head, addr);
if (fdb) {
//如果需要插入的是本机的MAC地址,则不需要更新
if (fdb->is_local)
return 0;
printk(KERN_WARNING "%s adding interface with same address "
"as a received packet\n",
source->dev->name);
//删除已经存在的表项,后面会创建新的表项用以替代
fdb_delete(fdb);
}
//创建新的fdb
if (!fdb_create(head, source, addr, 1))
return -ENOMEM;
return 0;
}
CAM表的查找
内核使用 __br_fdb_get() 函数来进行CAM表的查找,找到并返回相对应的net_bridge_fdb_entry结构
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;
//遍历net_bridge->hash
hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) {
//如果MAC地址和fdb中的地址相同并且fdb没有超时,
//就说明找到了相应的fdb
if (!compare_ether_addr(fdb->addr.addr, addr)) {
if (unlikely(has_expired(br, fdb)))
break;
return fdb;
}
}
return NULL;
}
|