bridge(网桥)FDB表中MAC地址的更新
网桥工作在L2,对于网桥而言,最重要的就是网络拓扑中MAC地址的学习和基于MAC地址转发表(FDB- Forwarding database)对数据包的转发。
在br_handle_frame函数处理接到的数据包之后,网桥会根据接受的数据包的包头信息和接受数据包的接口进行FDB更新。对于已经存在的FDB表项,仅更新该表项的时间标记,对于不存在与FDB的表项,调用fdb_create来创建新的表项。
1.对于FDB的创建和更新过程如下图:
2.Linux3.0.34
版本的
br_fdb_update
函数的源代码如下:
void br_fdb_update(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;
/* some users want to always flood. */
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_rcu(head, addr);
if (likely(fdb)) {
/* attempt to update an entry for a local interface */
if (unlikely(fdb->is_local)) {
if (net_ratelimit())
br_warn(br, "received packet on %s with "
"own address as source address. MAC address is %s \n",
source->dev->name, addr);
} else {
/* fastpath: update of existing entry */
//如果FDB中已经存在了该MAC表项,则仅更新最新的时间,用于下次老化查询
fdb->dst = source;
fdb->updated = jiffies;
}
} else {
spin_lock(&br->hash_lock);
if (likely(!fdb_find(head, addr)))
fdb_create(head, source, addr);
//如果FDB中没有该MAC表项,则调用fdb_create来创建新的表项 /* else we lose race and someone else inserts * it first, don't bother updating */ spin_unlock(&br->hash_lock); } }