LwIP協(xié)議棧源碼詳解——TCP/IP協(xié)議的實現(xiàn)》ARP層流程

姓名:朱小鵬 ? ?學(xué)號:16010130023

轉(zhuǎn)載:

http://blog.sina.com.cn/s/blog_62a85b950101anvx.html

【嵌牛導(dǎo)讀】:最后要講的一個函數(shù)是update_arp_entry岩喷,該函數(shù)用于更新ARP緩存表中的表項或者在緩存表中插入一個新的表項虏肾。該函數(shù)會在收到一個IP數(shù)據(jù)包或ARP數(shù)據(jù)包后被調(diào)用浪箭。

【嵌牛鼻子】:ARP表的創(chuàng)建,更新课锌,查詢等操作

【嵌牛提問】:LWIP是怎樣進(jìn)行ARP表的創(chuàng)建,更新凸椿,查詢等操作肠槽?

【嵌牛正文】:

最后要講的一個函數(shù)是update_arp_entry,該函數(shù)用于更新ARP緩存表中的表項或者在緩存表中插入一個新的表項阔加。該函數(shù)會在收到一個IP數(shù)據(jù)包或ARP數(shù)據(jù)包后被調(diào)用饵史。該函數(shù)原型如下,

static err_t

update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)

其中重要的兩個參數(shù)ipaddr和ethaddr分別對應(yīng)的ip地址和mac地址胜榔,函數(shù)利用這兩個地址去更新或插入ARP表項胳喷。由于這個函數(shù)代碼量較小,這里就列出源碼來講解夭织,注意這個源碼是經(jīng)過我處理的吭露,已經(jīng)去掉了編譯選項、源碼注釋尊惰、調(diào)試輸出信息等非重點部分讲竿。

static err_t

update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)

{

s8_t i;// 兩個變量泥兰,不解釋

u8_t k;

i = find_entry(ipaddr, flags);// 查找或新建一個ARP表項,返回其索引值

if (i < 0)return (err_t)i;// 如果為不合法的索引值题禀,則更新緩存表失敗

arp_table[i].state = ETHARP_STATE_STABLE; // 否則將對應(yīng)表項狀態(tài)改為stable

arp_table[i].netif = netif;// 記錄下網(wǎng)絡(luò)接口

k = ETHARP_HWADDR_LEN;// 這一段是更新緩存表項中的MAC地址

while (k > 0) {

k--;

arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];

}

arp_table[i].ctime = 0;//生存時間值置0

#if ARP_QUEUEING//該ARP表項上有未發(fā)送的隊列鞋诗,則把這些隊列發(fā)送出去

while (arp_table[i].q != NULL) {// 只要緩沖鏈表中海有數(shù)據(jù)則循環(huán)

struct pbuf *p;

struct etharp_q_entry *q = arp_table[i].q;// 記錄下緩沖鏈表表頭

arp_table[i].q = q->next;// 緩沖鏈表表頭指向下一個節(jié)點

p = q->p;// 取得記錄下的緩沖鏈表表頭指向的數(shù)據(jù)包

memp_free(MEMP_ARP_QUEUE, q);// 釋放記錄下的緩沖鏈表表頭

etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); // 發(fā)送數(shù)據(jù)包

pbuf_free(p);// 釋放數(shù)據(jù)包緩存空間

}

#endif

return ERR_OK;

}

從源程序中可以看出,update_arp_entry的流程如下:先通過調(diào)用find_entry找到對應(yīng)ipaddr對應(yīng)的表項投剥,并設(shè)置相應(yīng)的arp表項的成員(主要是state师脂, netif, ethaddr江锨, cttime)吃警,最后如果定義了ARP_QUEUEING,并且這個arp表項上有未發(fā)送的數(shù)據(jù)包的話啄育,則把這些數(shù)據(jù)全部發(fā)送出去酌心。雖然比較啰嗦,但是還是我們還是根據(jù)不同的ipaddr經(jīng)過find_entry執(zhí)行后挑豌,來看看update_arp_entry運(yùn)行的幾種不同情況安券。

首先可以肯定的是,update_arp_entry的兩個參數(shù)ipaddr和ethaddr必是互相匹配的氓英,因為它們是從源主機(jī)發(fā)來的IP包或ARP包中解析出來的侯勉,代表了源主機(jī)的MAC地址和IP地址。find_entry利用ipaddr作為參數(shù)執(zhí)行后铝阐,返回一個ARP表項索引址貌。如果該表項處于empty狀態(tài),那么該表項現(xiàn)在一定是新創(chuàng)建的徘键,此時設(shè)置該表項為stable狀態(tài)并設(shè)置該表項其他字段值后即結(jié)束练对。如果該表項是處于pending狀態(tài),由于此時已經(jīng)有了和ipaddr匹配的MAC地址返回吹害,所以該表項也被設(shè)置為stable狀態(tài)并同時設(shè)置該表項其他字段值螟凭。如果該表項是處于stable狀態(tài),其實此時只需要將ctime的值復(fù)位即可它呀,但是LWIP為了節(jié)省代碼量螺男,它還是選擇像上面的情況一樣做相同的處理,這樣雖然有些步驟是多余的纵穿,但并不影響函數(shù)功能烟号。最后都會檢查該表項是否還有數(shù)據(jù)需要發(fā)送,如果有政恍,則將所有數(shù)據(jù)包發(fā)送出去。

現(xiàn)在是時候從宏觀上來看看到底ARP是怎么一個工作流程达传,以及它在整個LWIP協(xié)議棧當(dāng)中發(fā)揮的重要作用篙耗。關(guān)于這點迫筑,不得不借鑒網(wǎng)上某位大俠的了,不過對TA的圖做了一些小小的修改(臉紅宗弯,用畫圖工具改的脯燃,Visio表示不會用)。

該圖簡潔明了的解釋了基本所有LWIP的數(shù)據(jù)包接收與發(fā)送的全過程辕棚。我們可以看到幾個熟悉的身影:etharp_query、etharp_request邓厕、update_arp_entry。在前面已經(jīng)講過了的详恼!

ARP從功能上來說可以簡單的分成兩個部分:當(dāng)有數(shù)據(jù)包輸入時,更新arp表昧互,如果是ip包則遞交給ip層,如果是arp包敞掘,則針對不同的arp包類型做相應(yīng)的響應(yīng);當(dāng)向目的ip發(fā)送一個數(shù)據(jù)包的時候玖雁,需要通過arp實現(xiàn)ip到MAC地址的映射,必要時茄菊,需要發(fā)送廣播數(shù)據(jù)包獲得目標(biāo)機(jī)器的MAC地址。

LWIP利用netif.input指向的函數(shù)接收以太網(wǎng)數(shù)據(jù)包面殖,通常這個函數(shù)是ethernet_input竖哩。注意,這里并不是說ethernet_input直接與底層硬件交互接收數(shù)據(jù)包脊僚,而是更底層的函數(shù)接收到數(shù)據(jù)包后將數(shù)據(jù)包遞交給ethernet_input相叁,ethernet_input再對其進(jìn)行處理。

以太網(wǎng)的幀類型可以是:IP辽幌,ARP增淹,甚至可以是pppoe, wlan等乌企。這里主要分析IP和ARP兩種類型的數(shù)據(jù)包虑润。ethernet_input根據(jù)以太網(wǎng)首部的類型字段判斷收到的數(shù)據(jù)包的類型,如果是IP包加酵,則將該包遞交給etharp_ip_input拳喻,如果是ARP包哭当,則將該包遞交給etharp_arp_input。

對于ip類型的數(shù)據(jù)包冗澈,etharp_ip_input首先檢查是否開啟了ETHARP_TRUST_IP_MAC這個選項钦勘,如果開啟了就是要用這個幀中的信息和update_arp_entry函數(shù)來更新arp表(利用幀首部的源mac地址和幀數(shù)據(jù)中ip報文中的源ip地址),然后丟棄以太網(wǎng)幀首部亚亲,將IP報文通過ip_input函數(shù)遞交給ip層彻采。

對于arp類型的數(shù)據(jù)包,etharp_arp_input函數(shù)首先利用數(shù)據(jù)包頭信息更新arp表的內(nèi)容捌归,

然后再判斷該ARP數(shù)據(jù)包的類型肛响,如果是ARP請求包,則首先判斷這個包是不是給自己的陨溅,如果是給自己的终惑,則在原有包的基礎(chǔ)上重組一個ARP應(yīng)答包發(fā)送出去(注意此處并沒有重新分配一個pbuf,而是借用了原來的緩沖結(jié)構(gòu))门扇。如果不是給自己的雹有,則直接忽略。如果是ARP應(yīng)答包臼寄,主要的工作就是更新arp表霸奕,但是這一步已經(jīng)在arp包剛進(jìn)來的時候就處理了,所以這里不需要再重復(fù)做吉拳,這樣ARP包的處理也完畢质帅。

LWIP利用netif.output指向的函數(shù)發(fā)送IP數(shù)據(jù)包,通常這個函數(shù)是etharp_output留攒。注意煤惩,這里并不是說etharp_output直接與底層硬件交互發(fā)送數(shù)據(jù)包,而是將數(shù)據(jù)包做相應(yīng)的處理炼邀,最終遞交給netif.linkoutput函數(shù)來發(fā)送的魄揉。

etharp_output函數(shù)接收IP層要發(fā)送的數(shù)據(jù)包,并將數(shù)據(jù)包發(fā)送出去拭宁。由于是發(fā)送ip數(shù)據(jù)包洛退,所以函數(shù)一開始需要增加緩沖區(qū)大小,大小為以太網(wǎng)的數(shù)據(jù)首部的大小杰标。然后檢查ip地址,可以分為廣播包腔剂,多播包,單播包(單播包又分為是局域網(wǎng)內(nèi)部還是局域網(wǎng)外面)谅畅。

廣播包:判斷目的IP地址是不是為全1噪服,或者是全0(老版本中使用的)粘优,如果是廣播包則目的IP的MAC地址不需要查詢arp表雹顺,直接將MAC地址設(shè)置為全1發(fā)送即可廊遍,即MAC六個字節(jié)值為0xff,0xff没酣,0xff裕便,0xff偿衰,0xff改览,0xff。

多播包:判斷目的ip地址是不是d類地址视事,即0xexxxxxxx郑口,如果是多播的話盾鳞,mac地址也是確定的腾仅,即將MAC地址01-00-5e-00-00-00的低23位設(shè)置為IP地址的低23位。對于以上的兩種數(shù)據(jù)包鹤耍,etharp_output直接調(diào)用函數(shù)etharp_send_ip將數(shù)據(jù)包發(fā)送出去。

單播包:要比較目的IP和本地IP地址喊衫,看是否是局域網(wǎng)內(nèi)的族购,不是局域網(wǎng)內(nèi)的陵珍,則將目的IP地址設(shè)置為默認(rèn)網(wǎng)關(guān)的地址,然后再統(tǒng)一調(diào)用etharp_query函數(shù)將數(shù)據(jù)包發(fā)送出去瑟幕,注意這些數(shù)據(jù)包在這種情況下可能被連接在相關(guān)ARP表項的發(fā)送鏈表上只盹,等待發(fā)送愤兵。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秆乳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子肛冶,更是在濱河造成了極大的恐慌扯键,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馅笙,死亡現(xiàn)場離奇詭異董习,居然都是意外死亡皿淋,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門疯暑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妇拯,“玉大人散址,你說我怎么就攤上這事。” “怎么了吏祸?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵贡翘,是天一觀的道長砰逻。 經(jīng)常有香客問我,道長踊东,這世上最難降的妖魔是什么闸翅? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任菊霜,我火速辦了婚禮鉴逞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘液南。我一直安慰自己贺拣,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布闪幽。 她就那樣靜靜地躺著盯腌,像睡著了一般陨瘩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帚湘,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天大诸,我揣著相機(jī)與錄音贯卦,去河邊找鬼。 笑死贿堰,一個胖子當(dāng)著我的面吹牛啡彬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播注簿,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼诡渴,長吁一口氣:“原來是場噩夢啊……” “哼妄辩!你這毒婦竟也來了山上?” 一聲冷哼從身側(cè)響起佩憾,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤干花,失蹤者是張志新(化名)和其女友劉穎池凄,沒想到半個月后肿仑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尤慰,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伟端,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年荔泳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昧港。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡达舒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巩搏,到底是詐尸還是另有隱情贯底,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布禽捆,位于F島的核電站胚想,受9級特大地震影響浊服,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜愁憔,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一惩淳、第九天 我趴在偏房一處隱蔽的房頂上張望思犁。 院中可真熱鬧激蹲,春花似錦江掩、人聲如沸学辱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽策泣。三九已至,卻和暖如春抬吟,著一層夾襖步出監(jiān)牢的瞬間萨咕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工火本, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留危队,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓钙畔,卻偏偏與公主長得像茫陆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子擎析,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容