哈嘍大家好,我是鹹魚
今天我們來聊聊計算機網路中的 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 設定成多少合適呢?
RFC 標準定義乙太網的預設 MTU 值為 1500,為什麼是 1500 ?
這是一個歷史遺留問題
早期的乙太網使用共用鏈路的工作方式,為了保證 CSMA/CD(載波多路複用/衝突檢測)機制,規定了以太幀長度最小為 64 位元組,最大為 1518 位元組
最小 64 位元組是為了保證最極端的衝突能被檢測到,64 位元組是能被檢測到的最小值
最大不超過 1518 位元組是為了防止過長的幀傳輸時間過長而佔用共用鏈路太長時間導致其他業務阻塞
所以說資料框的最大長度被限制為 1518 位元組(包括幀頭、幀尾和CRC校驗)
因此,1500 位元組被定義為乙太網資料框中資料部分的最大長度(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,則就會進行分片操作
要讓最終傳給資料鏈路層的 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 值,以便在資料傳輸過程中進行分片和重組
前面我們介紹了什麼是 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,就會在實際資料內容後面新增填充資料,使得封包總長度達到最小長度要求
TSO(TCP Segmentation Offload)是一種網路傳輸解除安裝技術。TSO 技術將分片過程從 CPU 轉移到網路卡上的專用硬體,網路卡負責將應用程式的大塊資料分段為適當大小的封包,並新增 TCP 首部,然後直接傳送到網路上