LWIP協議棧:ARP協議


1. ARP協議簡介

  • ARP(Address Resolution Protocol),地址解析協議。ARP協議處於網絡層,其主要功能就是通過目標設備的 IP 地址,查詢目標設備的 MAC 地址,從而進行網絡通信。

  • 網絡層中,源主機和目標主機依賴於IP地址進行通信。而鏈路層又有自己的尋址尋址機制(如,以太網依賴於MAC地址進行通信)。ARP的作用在於將IP地址轉換為MAC地址,從而連接網絡層與鏈路層,使得上層可以通過IP地址進行網絡通信。

  • ARP協議的基本運作過程如下:

2. ARP緩存表

2.1 ARP緩存表的定義 

每台主機或路由器在其內存中都存儲着一個ARP緩存表,表中記錄着了<IP 地址,MAC 地址>對,反映着目標主機的IP地址與MAC地址的映射關系。

LwIP協議棧中,使用一個 arp_table 數組描述 ARP 緩存表,數組的內容是表項的內容。
 1 /*lwip/src/netif/etharp.c*/
 2 
 3 enum etharp_state {
 4    ETHARP_STATE_EMPTY = 0,            //空狀態,表示該表項為空
 5    ETHARP_STATE_PENDING,              //掛起狀態,表示該表項還未收到目標主機的ARP應答
 6    ETHARP_STATE_STABLE,               //可用狀態,表示該表項可用
 7    ETHARP_STATE_STABLE_REREQUESTING_1,//過渡狀態
 8    ETHARP_STATE_STABLE_REREQUESTING_2 //過渡狀態
 9  #if ETHARP_SUPPORT_STATIC_ENTRIES
10    , ETHARP_STATE_STATIC
11  #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
12 };
13 
14 struct etharp_entry {
15 #if ARP_QUEUEING
16    /* 指向此ARP表項上掛起的數據包隊列*/
17    struct etharp_q_entry *q;
18  #else /* ARP_QUEUEING */
19    /*指向此ARP表項上掛起的單個數據包 */
20    struct pbuf *q;
21  #endif /* ARP_QUEUEING */
22    ip_addr_t ipaddr;       //目標主機的IP地址
23    struct netif *netif;    //目標主機的網卡信息
24    struct eth_addr ethaddr;//目標主機的MAC地址
25    u8_t state;             //此表項的狀態
26    u8_t ctime;             //此表項的生存時間
27  };
28 
29 static struct etharp_entry arp_table[ARP_TABLE_SIZE]; //LWIP協議棧的ARP緩存表
  • 表項的數據包指針q:指針q指向需要發送至該目標主機的數據包。struct etharp_q_entry *q指向一個數據包隊列,struct pbuf *q指向單個數據包。
  • 表項的生存時間ctime:每個表項都包含一個ctime變量,表示該表項的生存時間。當達到指定的生存時間,該表項會被刪除。

2.2 緩存表的動態處理

ARP協議的核心就是對緩存表的動態處理。因為IP地址可能是動態的,所以ARP緩存表必須動態更新。

ARP協議中,通過發送ARP請求包、接收ARP應答包、ARP緩存表超時處理來實現緩存表的動態更新。

(1)發送ARP請求包

發送數據時,若不存在目標主機的表項,則新建一個表項,並發送ARP請求包;若存在目標主機的表項,對處於ETHARP_STATE_STABLE的表項,會再次發送ARP請求包,以確認目標主機依然在工作狀態。詳見4. ARP協議工作流程。

(2)接收ARP應答包

接收到ARP應答包時,將ARP應答包包含的<IP 地址,MAC 地址>對添加到緩存表。詳見4. ARP協議工作流程。

(3)ARP緩存表超時處理

緩存表的超時處理。周期性(1S)調用 etharp_tmr()函數,動態更新緩存表項的生存時間,以及它的狀態。

在ARP緩存表的動態更新過程中,其表現狀態變化過程如下:

3. ARP報文

ARP協議的請求與應答同時通過ARP報文來實現的。ARP的報文將被封裝在以太網幀中進行發送。

3.1 以太網幀結構

(1)MAC地址

MAC Address(Media Access Control Address),亦稱為 EHA(Ethernet Hardware Address)、硬件地址、物理地址(Physical Address)、鏈路地址。MAC的值被固化在網卡的ROM中,以唯一標識該網卡。MAC地址長度為 6字節,其前 3個字節(組 織唯一標志符)表示廠家的代碼,后 3個字節(擴展標識符)由廠家自行分配。 目標 MAC地址可以分成三類,單播地址、多播地址和廣播地址。

  • 單播地址:即目標主機的MAC地址,發送數據至特定的目標主機。
  • 多播地址:MAC的第一個字節的bit0為1,發送數據至多個目標主機。
  • 廣播地址:MAC地址為全1,即FF-FF-FF-FF-FF-FF,發送數據至同一子網內的所有主機。

(2)以太網幀結構 

在鏈路層中,數據被封裝為以太網幀結構進行發送。以太網幀結構如下:

  前同步碼:它的作用是實現物理層幀輸入輸出的同步,其值都是 10101010(0x55,大端模式)。

  • 幀開始符:表示着以 太網幀的開始,其值都是 10101011(0xD5, 大端模式)。
  • 目標MAC地址:接收設備的MAC地址。
  • 源MAC地址:發送設備的MAC地址。
  • 類型:表示網絡協議的類型。一台給定的主機可以支持多種網絡層協議,不同的應用采用不同的協議。因此,當以太網幀到達網卡中,網卡需要知道它應該將數據字段的內容傳遞給哪個網絡層協議。如 IP 協議、ARP協議等。 
  • 數據:包含需要被發送的數據(如IP數據包、ARP數據包)。以太網的最大傳輸單元 (MTU)是1500字節,若數據包超過1500字節,則需要分片傳輸;若數據包小於46字節,則需要填充至46字節再發送。
  • CRC:以太網的差錯校驗信息。 

P.S.:當“類型”字段的值小於 1518時,它表示后面數據字段的數據長度,當大於1518的時候才表示遞交給哪個協議。 

3.2 ARP報文結構

(1)ARP報文格式如下:

  • 硬件類型:目標網卡的硬件類型,表明ARP報文可以在哪種類型的網絡上傳輸。1表示以太網地址。
  • 協議類型:硬件地址要映射的協議地址類型。映射IP地址時的值為0x0800.
  • 硬件地址長度:即MAC地址的長度(以太網的MAC地址長度為6)。
  • 協議地址長度:即IP地址的長度。
  • 操作類型:指定本次ARP報文的類型。1:ARP請求報文;0:ARP響應報文。
  • 源MAC地址:發送設備的MAC地址。
  • 源IP地址:發送設備的IP地址。
  • 目標MAC地址:接收設備的MAC地址。在ARP請求報文中,目標MAC地址未知,MAC字段的值為全0(即00-00-00-00-00-00)。
  • 目標IP地址:接收設備的IP地址。

(2)ARP幀格式:

ARP報文將被傳輸到鏈路層,加上以太網的幀頭,形成ARP幀,再通過鏈路層發送出去。ARP幀的格式如下:

  • 目標MAC地址:接收設備的MAC地址。在ARP請求報文中,它的目標為網絡上的所有主機,目標MAC字段的值為FF-FF-FF-FF-FF-FF(廣播地址)。
  • 源MAC地址:發送設備的MAC地址。
  • 幀類型:標識幀封裝的上層協議。此處封裝的為ARP協議,它的值為0x0806。

(3)幀格式的定義

 1 /*lwip2.1.2/src/include/lwip/port/ethernet.h*/
 2 #define ETH_HWADDR_LEN    6     //以太網地址長度
 3 
 4 struct eth_addr    //以太網地址結構體
 5 {    
 6     PACK_STRUCT_FLD_8(u8_t addr[ETH_HWADDR_LEN]); 
 7 } PACK_STRUCT_STRUCT;
 8 
 9 struct eth_hdr    //以太網首部  9 
10 {
11     PACK_STRUCT_FLD_S(struct eth_addr dest);  //以太網目標 MAC 地址
12     PACK_STRUCT_FLD_S(struct eth_addr src);   //以太網源 MAC 地址 
13     PACK_STRUCT_FIELD(u16_t type);            //幀類型 
14 } PACK_STRUCT_STRUCT; 
15 
16 
17 /*lwip2.1.2/src/include/lwip/port/etharp.h*/
18 struct etharp_hdr               //ARP 報文
19 {
20     PACK_STRUCT_FIELD(u16_t hwtype);    //硬件類型 
21     PACK_STRUCT_FIELD(u16_t proto);     //協議類型
22     PACK_STRUCT_FLD_8(u8_t  hwlen);     //硬件地址長度 
23     PACK_STRUCT_FLD_8(u8_t  protolen);  //協議地址長度 
24     PACK_STRUCT_FIELD(u16_t opcode);    //op 字段 
25     /* 以上是 ARP 報文首部 */ 
26     
27     PACK_STRUCT_FLD_S(struct eth_addr shwaddr);            //源 MAC 地址
28     PACK_STRUCT_FLD_S(struct ip4_addr_wordaligned sipaddr);//源 ip 地址
29     PACK_STRUCT_FLD_S(struct eth_addr dhwaddr);            //目標 MAC 地址 
30     PACK_STRUCT_FLD_S(struct ip4_addr_wordaligned dipaddr);//目標 ip 地址 
31 } PACK_STRUCT_STRUCT;  
32 
33 enum etharp_opcode    //op 字段操作 
34 {
35     ARP_REQUEST = 1,     //請求包 33     
36     ARP_REPLY   = 2      //應答包 34 
37 };
ARP報文格式定義

4. ARP協議工作流程

(1)數據包接收流程說明:

  • 硬件網卡接收到數據之后,會調用ethernet_input()函數來處理接收到的數據包。ethernet_input()函數根據數據包中的以太網首部的幀類型進行分別處理;當幀類型為IP協議,則該數據包為IP數據包,調用ip4_input()函數進行處理;當幀類型為ARP協議,則該數據包為ARP數據包,調用 etharp_input()函數進行處理。
  • etharp_input()函數對ARP數據包進行處理。首先調用 etharp_update_arp_entry()更新ARP緩存表。然后判斷ARP數據包類型。如果是ARP請求包,且是發送給本機的,則調用 etharp_raw()函數發送ARP應答包;如果不是發送給本機的ARP請求包,則丟棄。
  • etharp_update_arp_entry()對ARP緩存表進行更新。首先查找或創建ARP表項,設置新建表項的信息。然后檢查改表項是否含有未發送的數據包,若存在,則調用ethernet_output()函數發送該表項上的數據。

(2) 數據包接收流程說明:

  • 上層調用etharp_output()函數來發送IP數據包。對於廣播、多播數據包,調用ethernet_output()函數直接發送數據包。對於單播數據包,若源主機與目標主機不在同一個子網,則修改IP地址為網關地址;然后遍歷ARP緩存表,如果存在與目標IP地址對應的表項,且表項狀態>=ETHARP_STATE_STABLE,則調用 etharp_output_to_arp_index()函數發送IP數據包;若不存在,則調用etharp_query()函數。
  •  etharp_output_to_arp_index()函數用來發送IP數據包。(此時表項狀態必須>=ETHARP_STATE_STABLE)首先,更新該表項信息,確認目標主機是否在工作狀態。當表項還有15s到期,調用(etharp_request()函數以廣播方式發送ARP數據包;當表項還有30秒到期,調用etharp_request_dst()函數以單播方式發送ARP請求包。若表項有效期大於30s,則調用ethernet_output()函數發送IP數據包。
  • 當ARP表中沒有與目標IP地址對應的表項,或表項的狀態為ETHARP_STATE_PENDING,則etharp_query()函數被調用。etharp_query()函數首先調用 etharp_find_entry()函數查詢或創建新的表項,當該表項為新建表項,或該表項的數據隊列為空時,調用etharp_request()函數發送ARP請求。然后判斷表項的狀態,當表項狀態>=ETHARP_STATE_STABLE,則調用ethernet_output函數發送數據包;當表項狀態為ETHARP_STATE_PENDING,則將數據包插入該表項的數據包隊列。

5. 參考資料

[1] 野火《LwIP應用開發實戰指南》。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM