LWIP協議棧:ICMP協議


1. ICMP協議概述

  • ICMP(Internet Control Message Protocol),因特網控制報文協議。ICMP協議屬於網絡層協議,用於在源主機與路由器之間傳遞控制消息。控制消息對數據報文的傳遞有着重要作用,如:網絡不通、通信超時等消息。
  • ICMP協議也是一種無連接的不可靠數據報交付協議,協議本身不提供任何的錯誤檢查與恢復機制。
  • ICMP協議的主要功能:

    1)差錯通知:反饋數據傳遞過程出現的錯誤的信息至源主機;

    2)信息查詢:源主機向目標主機查詢相關信息。

P.S.:ICMP只能搭配IPv4使用,ICMPv6搭配IPv6使用。

2. ICMP報文

2.1 報文格式

(1)ICMP報文格式

類型:報文的類型,表示產生報文的原因,占8bit;

代碼(code):報文的代碼,表示產生報文的具體原因,占8bit;

校驗和:整個ICMP報文的校驗和

(2)ICMP報文封裝

ICMP數據報封裝在IP數據報中,IP數據報封裝在以太網幀中。

2.2 報文類型

ICMP報文分為兩大類:差錯報告報文、查詢報文。

  • 差錯報告報文:當目標主機或路由器不能正常處理當前的數據報時,目標主機或路由器會反饋一個差錯報告報文到源主機,向源主機表明出差錯的具體原因。
  • 查詢報文:源主機向目標主機發送信息查詢請求,目標主機向源主機作出應答。

2.3 差錯報告報文

差錯報告報文有6中類型:目的不可達、源站抑制、重定向、超時、參數錯誤。

(1)目的不可達

網絡數據報在傳遞過程中出錯,不能到達目標主機,或到達目標主機后無法傳遞至上層協議;此時,路由器或目標主機會反饋一個ICMP目的不可達差錯報文,通知源主機數據發送失敗。

目的不可達報文如下圖所示。

  • ICMP首部剩余的4Byte未使用,為全0。
  • IP數據報首部包含了源IP地址和目標IP地址,源主機可通過該信息判斷是哪個數據報出現差錯。
  • IP數據報數據區域前8Byte包含了傳輸層協議的“port”字段的值,源主機可以將ICMP報文傳遞給對應的上層協議處理。

導致目的不可達的原因有多個,其“code”字段值如下圖所示。LWIP協議棧只實現了前6種。

(2)源站抑制

當出現網絡擁堵,路由器或目標主機會向源主機發送源站抑制報文,同時源主機降低數據報的發送頻率。

源站抑制報文的格式和目的不可達報文相同,但其“code”字段為0。

(3)重定向

源主機剛啟動時,其路由表中只有一個默認路由,所有數據都會發送至默認路由。當默認路由器發現數據是發送給其他路由器時,默認路由器會反饋一個ICMP重定向報文給 源主機,通知源主機更改路由表。下次發送數據時,通過新路由進行發送,從而提高數據發送效率。

P.S.:LWIP協議棧中未對ICMP重定向報文進行處理。

(4)超時

IP數據報首部的“TTL”字段記錄着該數據報的生命值,該數據報每被轉發一次,TTL值減1。當路由器轉發一個TTL為0的數據報時,會丟棄數據報並向源主機反饋一個ICMP超時報文。另外,IP分片重裝未在規定時間完成也會認為它超時。

超時報文的格式和目的不可達報文相同,但其“code”字段有兩個,“code = 0”表示生存時間超時,“code = 1”表示IP數據報分片重裝超時。

(5)參數錯誤

網絡數據報傳輸過程中,會對IP數據報首部進行校驗。若IP首部校驗出錯,則該IP數據報會被丟棄,並向源主機發送ICMP參數錯誤報文。

P.S.:對於攜帶 ICMP 差錯報文的數據報、非第一個分片的分片數據報、具有特殊目的地址的數據報(如環回、多播、廣播),即使是出現了差錯也不會返回對應的差錯報文。

2.4 查詢報文

LWIP協議棧中只實現了ICMP回顯請求報文、回顯應答報文。ping命令使用的是ICMP回顯請求報文、回顯應答報文。ping是一個應用程序,該程序發送一份 ICMP 回顯請求報文給目標主機,並等待目標主機返回 ICMP 回顯應答報文。ping命令執行成功,說明鏈路層、網絡層、傳輸層都能通信正常。

ICMP回顯請求報文、回顯應答報文格式,如下圖所示。
  • “標識符”表示ping程序的編號,同一台主機可同時運行多個ping程序。
  • “序號”表示回顯請求的編號,每發送一個回顯請求,其值加1。

ping程序執行后,會打印出每個回顯請求的序列號及其回顯應答,從而可以判斷數據報是否丟失、失序、重復。

2.5 報文數據結構

LWIP協議棧中定義了“icmp_echo_hdr”結構體來描述ICMP報文首部的數據結構。同時定義了ICMP報文的“type”、“code”字段的宏,以及對其進行讀取和操作的宏。

P.S.:“icmp_echo_hdr”結構體實際上描述的回顯報文的首部,但由於ICMP各個類型的報文類似,因此可以用其描述其余報文的數據結構。

PACK_STRUCT_BEGIN
struct icmp_echo_hdr
{
    PACK_STRUCT_FLD_8(u8_t type);      //類型
    PACK_STRUCT_FLD_8(u8_t code);      //代碼
    PACK_STRUCT_FIELD(u16_t chksum);   //校驗和
    PACK_STRUCT_FIELD(u16_t id);       //標志符
    PACK_STRUCT_FIELD(u16_t seqno);    //序號
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END

3. ICMP報文的發送與接收

3.1 ICMP報文的發送

LWIP協議棧中,只實現了“目的不可達報文、超時報文”的發送。實現代碼位置:lwip_2_1_2/src/core/ipv4/icmp.c

(1)發送“目的不可達報文”

調用“icmp_dest_unreach()”函數發送目的不可達報文。當IP層無法向傳輸層傳遞數據報,ip_input()函數將會調用此函數發送“目的不可達報文”;當UDP協議無法向應用層傳遞數據報,udp_input()也將會調用此函數發送“目的不可達報文”。

/**
 *   功能:發送目的不可達報文。
 *    參數:
 *        struct pbuf *p:指向引起ICMP報文的IP數據報;
 *        enum icmp_dur_type t:報文“code”字段的值。
 *
 */
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);

(2)發送“超時報文”

調用“icmp_time_exceeded()”函數發送超時報文。當IP數據報TTL值為0時,ip_forward()函數在轉發數據報時會調用此函數;或者IP數據報分片重裝超時,也將調用此函數發送超時報文。

/**
 *    功能:發送超時報文。
 *    參數:
 *        struct pbuf *p:指向引起ICMP報文的IP數據報;
 *        enum icmp_dur_type t:報文“code”字段的值。
 *
 */
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);

icmp_dest_unreach()、icmp_time_exceeded()函數實際調用此函數完成ICMP報文的發送。

/**
 * 功能:發送ICMP報文。
 *
 *    參數:
 *        struct pbuf *p:指向引起ICMP報文的IP數據報;
 *        u8_t type:報文“type”字段的值
 *        u8_t code:報文“code”字段的值。
 *
 */
void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);

3.2 ICMP報文的接收

LWIP協議棧中,只對回顯報文進行處理。當IP層收到一個ICMP報文,“ip_input()”函數將調用“icmp_input()”函數對其進行處理(只處理回顯報文)。

實現代碼位置:lwip_2_1_2/src/core/ipv4/icmp.c

/**
 *    功能:處理接收到的回顯報文,並向源主機發送回顯報文應答。
 *
 *    參數:
 *        struct pbuf *p:指向引起ICMP報文的IP數據報;
 *        struct netif *inp:接收ICMP報文的netif。
 *
 */
void    icmp_input(struct pbuf *p, struct netif *inp);

4. 參考資料

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


免責聲明!

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



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