ARP 協議分析
總的來說,lwip將鏈路層ethernet的協議分組格式分爲ether和etherarp
分開處理。ip分組先進入etharp_ip_input更新一下arp表項,然後直接進入
netif的input傳遞給上層ip層。arp分組直接進入etharp_arp_input。
不送如ip層。
奇怪的是,lwip把ether header的結構定義在etharp中。
-ARP 數據結構
-- arp表狀態
enum etharp_state {
ETHARP_STATE_EMPTY, /* 表項空 */
ETHARP_STATE_PENDING,
ETHARP_STATE_STABLE, /* 穩定狀態表項,該表項中MAC值可直接取出 */
ETHARP_STATE_EXPIRED /* 超時表項 */
};
-- arp表項結構
struct etharp_entry {
struct pbuf *p; /* arp 請求隊列 */
struct ip_addr ipaddr;
struct eth_addr ethaddr;
enum etharp_state state;
u8_t ctime; /* 超時值 */
};
-- ARP 鏈路層協議分組
struct etharp_hdr {
struct eth_hdr ethhdr; /* ether header */
u16_t hwtype;
u16_t proto;
u16_t _hwlen_protolen;
u16_t opcode;
struct eth_addr shwaddr;
struct ip_addr2 sipaddr;
struct eth_addr dhwaddr;
struct ip_addr2 dipaddr;
}
- ARP 函數
void etharp_init();
初始化所有靜態ARP表項,狀態爲EMPTY。
static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
首先排除廣播、多播及any地址。然後,
將ipaddr及ethaddr對加入arp表項中,該表項索引由find_entry獲得。
加入後,將該arp表項中還未發送的IP包(這些IP包是由etharp_ouput函數,在
處理IP包發送時,由於未找到對應ip的mac地址,由etharp_query加入到
pending arp的未發送IP包鏈表中。現在我們得到mac和ip對應值後,就
可以將這些IP包發送出去),發送到netif驅動。
該函數被etharp_ip_input及etharp_arp_input調用。
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
查詢包含ipaddr的表項。
查詢優先級:1. pending 2. stable 3. empty。
find_entry總是根據這些優先級查找是否由匹配項,如果有,立刻返回該項
索引。否則根據優先級產看是否有過期表項,並覆蓋它。
void etharp_ip_input(struct netif *netif, struct pbuf *p);
該函數是再ip分組傳上ip層之前,將ip分組的mac和ip映射到
arp表項中做更新。這樣的設計好像比較浪費。完全可以加大arp
表項,去除該過程
void etharp_arp_input(struct netif *netif,
struct eth_addr *ethaddr, struct pbuf *p);
arp分組到來,直接交給該函數處理。
無論netif的ip地址是否被配置過,都將該ARP分組的源ip和mac地址
加入到ARP表項中。如果一個ARP請求的目的ip地址是本地ip地址。
則發送response ARP分組。
err_t etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
該函數分開處理兩種地址類型的網絡層包,
1)多播及廣播。直接調用netif->linkoutput發送出去,該函數爲網卡驅動。
2)單播。單播的IP包又分三種處理方式。a. 目的ip在arp表項中,並且stable。
則直接構造以太頭,調用網卡驅動,發送以太幀。b. 目的ip不在arp表項中,
修改arp表項狀態爲pending,並調用etharp_request,發送ARP REQUEST。
c. 目的ip在ARP表項中。但狀態爲pending(這個狀態是由b條件引起的,可能
ARP RESPONSE在處理該條件時還爲返回)。將待發送的IP包的緩衝區PBUF_REF
替換成PBUF_POOL或PBUF_RAM(暫時不知道爲啥)。這些包將會在update_arp_input
中被髮送。
- ARP 協議處理流程圖