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


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