哈嘍大家好,我是咸魚
今天我們來聊聊計算機網絡中的 MTU (Maximum Transmission Unit)
(資料圖片)
MTU(Maximum Transmission Unit)是指數據鏈路層中的最大傳輸單元
通俗點來講,MTU 是指數據鏈路層能夠傳輸的最大數據幀的大小(以字節為單位)
以 CentOS 7 為例,可以通過 ifconfig
命令來查看 MTU 值
我們知道,數據在數據鏈路層中通常是以數據幀(Frame)的形式來傳輸
因為傳輸的 Frame 不可能無限大(傳小的可以),那么一次傳多大的 Frame 最合適、最高效就成了一個需要考慮的問題
所以說我們要設定一個值(也就是 MTU),這個值用來限制 Frame 的大小
維基百科有這么一段話
Larger MTU is associated with reduced overhead. Smaller MTU values can reduce network delay.
由上面的話可以得出:
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 怎么辦?以太網經過幾十年的發展,速度已經從最初的10M被提升到了上百G,速度提高了上萬倍
在這樣高速度的傳輸數據中,如果還是延續經典以太網的最大幀長不超過1518 字節的限制,那么在每秒中傳輸的數據包的個數將很大
于是一些廠商提出了巨型幀(Jumbo Frame)的概念,把以太網的最大幀長擴展到了9K
目前還沒有獲得 IEEE 標準委員會的認可,但是大多數的設備廠商都已經開始支持
以太網的 MTU 默認值是 1500,如果發送 Frame 小于 MTU(例如 1000 字節),直接傳輸就行
如果大于 MTU(4000 字節),那就需要進行分片(Fragment)
即第一次發送 1500 字節(IP header 20 字節 + Payload 1480 字節)
第二次發送 1500 字節(IP header 20 字節 + Payload 1480 字節)
第三次 1000 字節(IP header 20 字節 + Payload 980 字節)
可能有小伙伴問,那我傳的數據大小不夠數據幀規定的最小 64 字節怎么辦?
答案是:在實際數據內容后面添加填充數據,使得數據包總長度達到最小長度要求。填充數據可以是任意無意義的字節,例如全 0 或全 1 的數據
如何保證發送的數據不超過 MTU ?前面我們知道,如果發送的數據大于 MTU,則就會進行分片操作
要讓最終傳給數據鏈路層的 Frame 數據大小不超過 1500 bytes,就要保證上層中的每一層的數據都沒有超過這個大小
如果 MTU 是 1500,那么 IP 層就要保證 IP 層的 Packet 數據不超過 1480 bytes (1500 bytes – 20 bytes IP header),
對于 TCP 來說,它要保證每一個 Segment 數據大小不超過 1460 bytes (1460 bytes – 20 TCP header)
以 TCP 層(傳輸層)為例子, TCP 層是怎么知道發送的數據不會超過 MTU 呢?
IP 層(網絡層)問數據鏈路層數據最大傳輸單元( MTU )是多少
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(TCP Segmentation Offload)是一種網絡傳輸卸載技術,用于減輕主機的網絡數據包分段負擔,提高網絡傳輸性能
我們在抓包的時候看到是還在內核里的包,后面網卡拆包的過程是看不到的
網卡不但能對發送的包進行 offload,也可以對接收的包進行 onload,簡單來說就是網卡會先把一些小的包積攢下來,然后合起來發送給內核
# 查看網卡上面是否開啟 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
最后總結一下:
MTU 是指數據鏈路層能夠傳輸的最大數據幀的大小(以字節為單位)。由于歷史原因,MTU 的值最小為 64 字節,最大為 1518 字節(Payload 則是 46~1500 字節)
如果發送的數據大于 MTU,則就會進行分片操作;如果小于 MTU,就會在實際數據內容后面添加填充數據,使得數據包總長度達到最小長度要求
MSS(Maximum Segment Size)是用于指定 TCP 報文段中數據部分的最大長度。在建立 TCP 連接時,雙方需要協商一個合適的 MSS 值以便在數據傳輸過程中進行分片和重組
TSO(TCP Segmentation Offload)是一種網絡傳輸卸載技術。TSO 技術將分片過程從 CPU 轉移到網卡上的專用硬件,網卡負責將應用程序的大塊數據分段為適當大小的數據包,并添加 TCP 首部,然后直接發送到網絡上
關鍵詞: