不同的乙太網接入裝置,一幀能傳輸的資料量是有差異的。
普通的乙太網卡,一幀最多能夠傳輸 1500 位元組的資料;而某些虛擬裝置,傳輸能力要打些折扣。此外,鏈路層除了乙太網還有其他協議,這些協議中資料幀傳輸能力也有差異。
最大傳輸單元
如果待傳送的資料超過幀的最大承載能力,就需要先對資料進行分片,然後再通過若干個幀進行傳輸。
下面是一個典型例子,待傳送的資料總共 4000 位元組,假設乙太網裝置一幀最多隻能承載 1500 位元組。很明顯,資料需要劃分成 3 片,再通過 3 個幀進行傳送:
換句話講,我們需要知道接入裝置一幀最多能傳送多少資料。這個引數在網路領域被稱為 最大傳輸單元 ( maximum transmission unit ),簡稱 MTU 。MTU 描述鏈路層能夠傳輸的最大資料單元。
檢視、設定MTU
我們知道,在 Linux 系統可以用 ifconfig 或者 ip 這兩個命令來檢視網路卡資訊,其中包括 MTU 。
接下來,我們開啟 docker 進入 netbox 環境進行演示:
docker run --name netbox --rm -it --privileged --cap-add=NET_ADMIN --cap-add=SYS_ADMIN -v /data -h netbox fasionchan/netbox:0.5 bash /script/netbox.sh
先以 ifconfig 命令為例:
root@netbox [ ~ ] ➜ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.2 netmask 255.255.255.0 broadcast 0.0.0.0
ether 5a:ff:7e:28:81:bc txqueuelen 1000 (Ethernet)
RX packets 24 bytes 2165 (2.1 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27 bytes 2164 (2.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ip 命令也可以,我們更推薦使用這個:
root@netbox [ ~ ] ➜ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/tunnel6 :: brd ::
6: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 5a:ff:7e:28:81:bc brd ff:ff:ff:ff:ff:ff link-netnsid 0
我們可以用 ip 命令,來修改 eth0 的 MTU , 以修改 eth0 網路卡 MTU 為例:
root@netbox [ ~ ] ➜ ip link set eth0 mtu 68
不同的接入裝置,支援的 MTU 範圍不一樣。如果我們將 MTU 設定得太小,裝置將報錯:
root@netbox [ ~ ] ➜ ip link set eth0 mtu 40
Error: mtu less than device minimum.
MTU 對傳送環節的影響
我們以兩臺用網線直接相連的主機作為實驗環境,來觀察網路卡 MTU 對傳送、接收乙太網幀的影響:
實驗環境同樣通過 docker 來啟動:
docker run --name mtu-lab --rm -it --privileged --cap-add=NET_ADMIN --cap-add=SYS_ADMIN -v /data -h mtu-lab fasionchan/netbox:0.5 bash /script/cable-lab.sh
我們將 ant 主機 eth0 網路卡的 MTU 設定成 68 ,發現資料大於 68 位元組的乙太網幀將無法傳送:
root@ant [ ~ ] ➜ ip link set eth0 mtu 68
root@ant [ ~ ] ➜ sendether -i eth0 -t 32:65:21:d3:01:2f -d 'hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!'
Fail to send ethernet frame: : Message too long
將 MTU 恢復為預設值 1500 以後,可以成功傳送:
root@ant [ ~ ] ➜ ip link set eth0 mtu 1500
root@ant [ ~ ] ➜ sendether -i eth0 -t 32:65:21:d3:01:2f -d 'hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!'
這就是 MTU 對傳送環節的影響:如果資料量大於 MTU ,則無法通過單個乙太網幀傳送出去,只能以 MTU 為單位對資料進行分片,再封裝成若干個幀進行傳送。
MTU 對接收環節的影響
那麼,MTU 對接收環節有什麼影響呢?
我們將 bee 主機 eth0 網路卡的 MTU 設定成 68 ,並啟動 tcpdump 進行抓包:
root@ant [ ~ ] ➜ ip link set eth0 mtu 68
root@ant [ ~ ] ➜ tcpdump -ni eth0
接著,我們在主機 ant 上,向主機 bee 傳送一個資料大於 68 位元組的乙太網幀:
root@ant [ ~ ] ➜ sendether -i eth0 -t 32:65:21:d3:01:2f -d 'hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!'
然而,主機 ant 上的 tcpdump 程式告訴我們,eth0 網路卡並沒有收到這個幀!由此可見,乙太網幀資料長度一旦大於接收裝置 MTU ,將被丟棄。
結論
- 待傳送乙太網幀資料長度大於傳送裝置 MTU ,則無法傳送;
- 待接收乙太網幀資料長度大於接收裝置 MTU ,則無法接收;
【小菜學網路】系列文章首發於公眾號【小菜學程式設計】,敬請關注: