MTU(Maximum Transmission Unit),即最大傳輸單元,意思是在網絡通信協議里規定最大傳輸的字節數量,通常是1500字節(不同網絡大小不一樣,可使用ifconfig查看),最小是46。
但是抓包軟件抓出來會發現有些數據包長度會大於MTU,理論上當IP包大於MTU時,會對包進行分片。既然會分片,那么這個包大於MTU是幾個意思?
原因是這個分片不是發生在IP協議上,而是在TCP協議上,有個東西叫tso(tcp segment offload),意思是如果網卡支持tso,操作系統發送大的tcp包時,不需要消耗CPU來計算分片,而是將整個包發送到網卡,由網卡的NPU來進行分片處理。而抓包軟件抓的僅僅是CPU處理后的信息,也就是說在發送方抓的時候還沒到網卡就被CPU抓了,而真正的分片是由后面的網卡才分片{但是在接收端抓就會抓到已經分片的包了}
查看你網卡是否支持tso,請使用如下命令:
ethtool --show-offload eth0
這時候我們來禁用一下tso,只需要執行如下命令
ethtool -K eth0 tso off
再來一輪抓包測試,發現數據包終於正常了,不再會大於MTU了。
其實無論服務器發送的包多大,反正最終都會被分片,可能是操作系統,可能是網卡,因此客戶端收到的包都是小於MTU的。
分片
為什么ip有分片了,tcp還要再搞一個分片呢?因為ip層不保證數據成功送達,並且ip層分片可能發生在源主機,也可能在路由器上,一旦有分片丟失,將會造成整個ip包重傳(其實這個重傳是tcp層發起的,因為目標機器沒有收到完整的ip包,也不會有ack,那么源機器在一定時間內就會發起重傳,導致整個tcp包又被傳了一次),因此就有了tcp分片,當一片數據丟失,只需要重傳丟失的那一片即可。
結論
抓包的數據是在包送到網卡之前的信息,所以在tcpdump里面的包大小可能會大於MTU,但是一旦數據進入網卡后的處理信息在tcpdump里面是反應不了的,因此數據包被分片這樣的消息自然是沒辦法知道,只有在目標方才能反應出具體的分包細節。所以這次發現tcp/ip包長大於MTU其實算是個“假象”,因為在真正的鏈路層上傳輸數據時是不會大於MTU的。