計算機網絡那些事之 MTU 篇

哈嘍大傢好,我是咸魚

今天我們來聊聊計算機網絡中的 MTU (Maximum Transmission Unit)

什麼是 MTU ?

MTU(Maximum Transmission Unit)是指數據鏈路層中的最大傳輸單元

通俗點來講,MTU 是指數據鏈路層能夠傳輸的最大數據幀的大小(以字節為單位)

以 CentOS 7 為例,可以通過 ifconfig 命令來查看 MTU 值

為什麼需要 MTU ?

我們知道,數據在數據鏈路層中通常是以數據幀(Frame)的形式來傳輸

因為傳輸的 Frame 不可能無限大(傳小的可以),那麼一次傳多大的 Frame 最合適、最高效就成瞭一個需要考慮的問題

所以說我們要設定一個值(也就是 MTU),這個值用來限制 Frame 的大小

維基百科有這麼一段話

由上面的話可以得出:

  • MTU越大,開銷越小

這句話是很容易理解的,更大的 Frame 意味著包含的有效數據也就更多

我一次能傳更多的數據瞭,那麼傳輸次數就少瞭,在網絡上的開銷就變小瞭

  • 較小的MTU值可以減少網絡延遲

這句話容易讓人引起困惑,為什麼 MTU 值小能夠減少網絡延遲呢?

如果 MTU 設置的很大,意味著一次能傳更大的數據瞭,那占據鏈路的時間就會更長,所以總體上網絡延遲就會變大

而且如果一大段數據裡面有一個 bit 出錯瞭,這一大段就會整個重傳,重傳的代價是很大的

那麼 MTU 設置成多少合適呢?

為什麼 MTU 的值是 1500?

RFC 標準定義以太網的默認 MTU 值為 1500,為什麼是 1500 ?

這是一個歷史遺留問題

早期的以太網使用共享鏈路的工作方式,為瞭保證 CSMA/CD(載波多路復用/沖突檢測)機制,規定瞭以太幀長度最小為 64 字節,最大為 1518 字節

  • 最小 64 字節是為瞭保證最極端的沖突能被檢測到,64 字節是能被檢測到的最小值
  • 最大不超過 1518 字節是為瞭防止過長的幀傳輸時間過長而占用共享鏈路太長時間導致其他業務阻塞

所以說數據幀的最大長度被限制為 1518 字節(包括幀頭、幀尾和CRC校驗)

18 字節用於幀頭和幀尾,其中 CRC 校驗占據 4 字節,剩下的 1500 字節就是最大數據載荷(Payload)

因此,1500 字節被定義為以太網數據幀中數據部分的最大長度(MTU)

雖然技術不斷發展,但這個規定一直沒有更改

發送數據大小超過 MTU 怎麼辦?

以太網的 MTU 默認值是 1500,如果發送 Frame 小於 MTU(例如 1000 字節),直接傳輸就行

如果大於 MTU(payload 為 4000 字節),那就需要進行分片(Fragment)

即第一次發送 1500 字節(IP header 20 字節 + Payload 1480 字節)

第二次發送 1500 字節(IP header 20 字節 + Payload 1480 字節)

第三次 1060 字節(IP header 20 字節 + Payload 1040 字節)

可能有小夥伴問,那我傳的數據大小不夠數據幀規定的最小 64 字節怎麼辦?

答案是:在實際數據內容後面添加填充數據,使得數據包總長度達到最小長度要求。填充數據可以是任意無意義的字節,例如全 0 或全 1 的數據

如何保證發送的數據不超過 MTU ?

前面我們知道,如果發送的數據大於 MTU,則就會進行分片操作

要讓最終傳給數據鏈路層的 Frame 數據大小不超過 1500 bytes,就要保證上層中的每一層的數據都沒有超過這個大小

以 TCP 層(傳輸層)為例子, TCP 層是怎麼知道發送的數據不會超過 MTU 呢?

  1. IP 層(網絡層)問數據鏈路層數據最大傳輸單元( MTU )是多少
  2. TCP 層會問 IP 層數據最大傳輸大小(Maximum packet size)是多少

這樣 TCP 層就會知道自己的最大傳輸數據大小,叫做 MSS(Maximum segment size)

在 TCP 的握手階段,MSS(Maximum Segment Size)是用於指定TCP報文段中數據部分的最大長度

對於 TCP 來說,知道自己的 MSS 沒有什麼用

例如作為接收端來說,收到的包大小取決於發送端,得讓發送端知道自己的 MSS 才行

所以在建立 TCP 連接時,雙方需要協商一個合適的 MSS 值,以便在數據傳輸過程中進行分片和重組

什麼是 TSO

前面我們介紹瞭什麼是 MTU、MSS

如果你去抓一下包看看,你可能會遇到下面這種情況

明明協商瞭 MSS 為 1460 字節,為什麼數據居然有一萬多字節?

在建立 TCP 連接時,雙方需要協商一個合適的 MSS 值,以便在數據傳輸過程中進行分片

但是這個分片過程往往是簡單重復而且計算量比較大的,需要占用較多的 CPU 資源

所以網卡就會對內核說:哥這種小事我來幹就好瞭,不需要麻煩您

然後內核就會把大包發給網卡,網卡來負責分片

這個叫做 TSO(TCP Segment Offload)

我們在抓包的時候看到是還在內核裡的包,後面網卡拆包的過程是看不到的

# 查看網卡上面是否開啟 TSO 功能
# on 表示開啟
[root@root~]# ethtool -k <網卡名稱>
tcp-segmentation-offload: on
tx-tcp-segmentation: on
tx-tcp-ecn-segmentation: on
tx-tcp6-segmentation: on
tx-tcp-mangleid-segmentation: off

赞(0)