Lwip IP包分片重組
1. 開發環境
操作系統:SylixOS
編程環境:RealEvo-IDE3.1
硬件平臺:AT9x25開發板
2. 技術實現
SylixOS系統使用的網絡協議棧是Lwip協議棧。Lwip是Light Weight (輕型)IP協議,有無操作系統的支持都可以運行。Lwip實現的重點是在保持TCP協議主要功能的基礎上減少對RAM 的占用,它只需十幾KB的RAM和40K左右的ROM就可以運行,這使Lwip協議棧適合在低端的嵌入式系統中使用。
Lwip協議棧主要關註的是怎麽樣減少內存的使用和代碼的大小,這樣就可以讓Lwip適用於資源有限的小型平臺例如嵌入式系統。為了簡化處理過程和內存要求,Lwip對API進行了裁減,可以不需要復制一些數據。
網絡協議棧是以層的結構來實現的。鏈路層具有最大傳輸單元MTU這個特性,它限制了數據幀的最大長度,不同的網絡類型都有一個上限值。以太網的MTU是1500。如果IP層有數據包要傳,而且數據包的長度超過了MTU,那麽IP層就要對數據包進行分片(fragmentation)操作,使每一片的長度都小於或等於MTU。我們假設要傳輸一個UDP數據包,以太網的MTU為1500字節,一般IP首部為20字節,UDP首部為8字節,數據的凈荷(payload)部分預留是1500-20-8=1472字節。如果數據部分大於1472字節,就會出現分片現象。
本篇文章主要介紹Lwip裏對收到的IP分片報文重組的實現。
2.1 IP報文重組宏觀分析
圖 21 IP包重組框圖
IP包的重組的簡單流程如圖2-1所示。
首先,Lwip協議裏會有一個單向鏈表,每個結點是一個ip_reassdata的結構體,reassdatagrams指向這個鏈表。
ip_reassdata結點用來進行分片包的重組,每個結點對應著一個完整的IP包。這個結構體裏有一個指向pbuf的成員。當一個IP報文通過ip4_input向上層傳輸時,會檢測是否屬於分片包,如果是,則需要進行分片重組。
重組時,會從reassdatagrams鏈表裏查找是否已經有ip_reassdata這個結構體了,如果有,就會改變每個分片包的報頭,這裏是通過一個ip_reass_helper結構體改變的。改變完之後,會把這個分片包根據偏移插入到ip_reassdata這個結構體後面對應的位置。如果在reassdatagrams鏈表裏查找不到對應的ip_reassdata這個結構體,那麽說明這個分片包是收到幀的第一個報文,因此會創建一個新的ip_reassdata結構體,然後再進行後續操作。插入完成後,協議棧會檢測報文是否全部接收並重組完成。如果完成,就會從reassdatagrams鏈表中把ip_reassdata結構體刪除並把重組好的報文返回給ip4_input。
2.2 代碼分析
IP包的分片重組是通過ip4_reass 這個函數來完成的。判斷需要重組時都會調用這個函數,這個函數的主要內容如下:
對收到的IP報文的首部長度檢測,Lwip目前是不支持IP報文頭帶填充位的。
通過IP報文頭,獲得偏移和數據報文的長度。
lwip的一個特性:它對reassdatagrams鏈表上的pbuf的總數是有限制的,因此協議棧會判斷加上收到的這些pbuf的個數後,會不會超過這個限制。
如果超過了,會刪除鏈表中存在時間最長的那個。
從鏈表中尋找對當前的pbuf對應的ip_reassdata結構體。如果沒有,則會新創建一個結構體。
現在應該已經找到一個合適的 ip_reassdata結構體了,此時會做一個判斷:如果當前的這個IP報文的偏移為0並且此時的 ip_reassdata結構體的偏移也不等於0,那麽需要把當前的這個IP分片報文的頭部拷貝到 ip_reassdata結構體中。
檢測當前收到的IP分片報文是不是最後一個,如果是最後一個,那麽,就更新一下當前IP分片報文對應的 ip_reassdata結構體。
上述兩個檢測完成之後,會調用ip_reass_chain_frag_into_datagram_and_validate,找到一個合適的地方,把IP分片包插進去。
檢測當前的報文是否組裝完成,如果完成,返回一個非0的值。否則,返回0。
上述檢測結果如果是沒有完成,則ip4_reass 直接返回。如果完成了,則會對 ip_reassdata結構體的iphdr字段做修改,包括報文總長度、校驗和,並且把iphdr字段全部拷貝到第一個分片包的頭部,這樣,整個IP包的信息就出現在第一個分片包的信息裏。
接下來,把其他的IP分片包的的信息頭刪除,這樣一個完整的IP包就重組完成了。
最後,調用 ip_reass_dequeue_datagram將ip_reassdata結構體從整個鏈表中刪除。 代碼執行到這裏,整個重組基本完成。
3. 參考資料
無
本文出自 “11451177” 博客,請務必保留此出處http://11461177.blog.51cto.com/11451177/1939621
Lwip IP包分片重組