Linux从用户层到内核层系列 - TCP/IP协议栈部分系列3: bridge(网桥)FDB表中MAC地址的更新

题记:本系列文章的目的是抛开书本从源代码和使用的角度分析Linux内核和相关源代码,byhankswang和你一起玩转linux开发

轻松搞定TCP/IP协议栈,原创文章欢迎交流, [email protected]微笑

欢迎加入到CHLK - Linux开发交流群 QQ:327084515 讨论Linux开发相关问题


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);
}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章