Neutron VxLAN + Linux Bridge 環境中的網絡 MTU


 

1. 基礎知識

1.1 MTU

  一個網絡接口的 MTU 是它一次所能傳輸的最大數據塊的大小。任何超過MTU的數據塊都會在傳輸前分成小的傳輸單元。MTU 有兩個測量層次:網絡層和鏈路層。比如,網絡層上標准的因特網 MTU 是 1500 bytes,而在連接層上是 1518 字節。沒有特別說的時候,往往指的是網絡層的MTU。

  要增加一個網絡接口 MTU 的常見原因是增加高速因特網的吞吐量。標准因特網 MTU 使用 1500byte是為了和 10M 和 100M 網絡后向兼容,但是,在目前1G和 10G網絡中遠遠不夠。新式的網絡設備可以處理更大的MTU,但是,MTU需要顯式設置。這種更大MTU的幀叫做“巨幀”,通常 9000 byte 是比較普遍的。 

  相對地,一些可能得需要減少MTU的原因:
  • 滿足另一個網絡的MTU的需要(為了消除UDP分包,以及需要TCP PMTU discover )
  • 滿足 ATM cell 的要求
  • 在搞出錯率線路上提高吞吐量

 MTU 不能和目前任何 Internet 網絡協議混在一起,但是,可以使用一個路由器將不同 MTU 的網段連在一起。

  修改配置網絡接口 MTU 的方式:

  • 自動的:通過 DHCP MTU 廣告。注意,只有 DHCP 租期被續了以后,MTU 設置才會生效。你可以將網絡接口 down 再 up 強制它馬上生效。
  • 手動臨時性的:ifconfig eth0 mtu 9000
  • 永久性的:修改 network interface 定義文件。以 Debian/Ubuntu 為例,
auto eth0
iface eth0 inet static
        address 192.168.0.2
        netmask 255.255.255.0
        mtu 9000

1.2 VxLAN 封包(Mac-in-UDP,以 ping 產生的 ICMP 包為例)和 MTU

步驟 操作/封包 協議 長度 MTU
1 ping -s 1422 ICMP 1430 = 1422 + 8 (ICMP header)  
2 L3 IP 1450 = 1430 + 20 (IP header) VxLAN Interface 的 MTU
3 L2 Ethernet 1464 = 1450 + 14 (Ethernet header)  
4 VxLAN UDP 1480 = 1464 + 8 (VxLAN header) + 8 (UDP header)  
5 L3 IP 1500 = 1480 + 20 (IP header) 物理網卡的(IP)MTU,它不包括 Ethernet header 的長度
6 L2 Ethernet 1514 = 1500 + 14 (Ethernet header)  最大可傳輸幀大小

因此,VxLAN 的 overhead 是1514- 1464 = 50 byte。

1.3 GRE 封包(IP-in-IP,以 ping 產生的 ICMP 包為例)和 MTU

步驟 操作/封包 協議 長度 備注
1 ping -s 1448 ICMP 1456 = 1448 + 8 (ICMP header)  ICMP MSS
2 L3 IP 1476 = 1456 + 20 (IP header) GRE Tunnel MTU
3 L2 Ethernet 1490 = 1476 + 14 (Ethernet header) 經過 bridge 到達 GRE
4 GRE IP 1500 = 1476 + 4 (GRE header)+ 20 (IP header)  物理網卡 (IP)MTU
5 L2 Ethernet 1514 = 1500 + 14 (Ethernet header) 最大可傳輸幀大小

因此,GRE 的 overhead 是 1514 - 1490 = 24 byte(為啥 Neutron 中的 GRE overhead 是 42?)。

 可見,使用 GRE 可以比使用 VxLAN 每次可以多傳輸 1448 - 1422 = 26 byte 的數據。

1.4 IP Fragmentation (分包) 和 Path Maximum Transmission Unit Discovery (PMTUD) 

1.4.1 IP 分包

先談幾個要點:

  • 分包是指將一個IP包分成多個傳輸,在接收端 IP 層重新組裝
  • 一個 IP 包能否分包,取決於它的 DF 標志位:DF bit (0 = "may fragment," 1 = "don't fragment")
  • 分包后,每個分段有 MF 標志位:MF bit (0 = "last fragment," 1 = "more fragments")

分包示例:

第一個表格中:

  • IP 包長度 5140,包括 5120 bytes 的 payload
  • DF = 0, 允許分包
  • MF = 0, 這是未分包

第二個表格中:

  • 0-0 第一個分包: 長度 1500 = 1480 (payload) + 20 (IP Header). Offset(起始偏移量): 0 
  • 0-1 第二個分包: 長度 1500 = 1480 (payload) + 20 (IP Header). Offset: 185 = 1480 / 8 
  • 0-2 第三個分包: 長度 1500 = 1480 (payload) + 20 (IP Header). Offset: 370 = 185 + 1480/8
  • 0-3 第四個分包: 長度 700 =  680 (payload, = (5140 - 20) - 1480 * 3) + 20 (IP Header) . Offset: 555 = 370 + 1480/8

需要注意的是,只有第一個包帶有原始包的完整 IPv4 + TCP/UDP 信息,后續的分包只有 IPv4 信息。

分包帶來的問題:

  • sender overhead:需要消耗 CPU 去分包,包括計算和數據拷貝。
  • receiver overhead:重新組裝多個分包。在路由器上組裝非常低效率,因此組裝往往在接收主機上進行。
  • 重發 overhead:一個分包丟失,則整個包需要重傳。
  • 在多個分包出現順序錯開時,防火牆可能將分到當無效包處理而丟棄。

1.4.2 TCP MSS:TCP Maximum Segment Size (TCP 最大段長)

TCP MSS,是指一個接收方期望在一個 TCP/IP 報文里面接收的數據(payload)的長度。

  MSS 的值受兩個值的約束:發送方和接收方的用於存儲一個 TCP/IP 報文中的TCP數據的buffer 的長度的小者,以及該值和整個傳輸路徑的最小 MTU 減去40 的小者。而最小MTU 由 PMTU 確定。

1.4.3 PMTU 路徑MTU發現

  PMTU 的用途是動態的確定從發送端到接收端整個路徑上的最小 MTU,從而避免分包。注意,PMTU 只支持 TCP,對其他協議比如 UDP 無效。而且,如果發送方已經開啟了 PMTU,那么它發送的所有 TCP/IP 包的 DF 標志都被設置為 1 即不再允許分包。當網絡路徑上某個路由器發現發送者的包因為超過前面轉發路徑的 MTU 而無法發送時,它向發送者返回一個 ICMP  "Destination Unreachable" 消息,其中包含了那個 MTU,然后發送者就會在它的路由表中將該mtu值保存下來,再使用較小的 MTU 重新發出新的較小的包。

 在 Linux 系統上,可以打開或者關閉 PMTU:

/proc/sys/net/ipv4/ip_no_pmtu_disc #0,打開,默認值;1,關閉 (sysctl -w net.ipv4.ip_no_pmtu_disc=1
Set this if you want to disable Path MTU discovery - a technique to determine the largest Maximum Transfer Unit possible on your path. See also the section on Path MTU discovery in the Cookbook chapter.

  一個路由器作為主機包的轉發者的通常做法:

  • 檢查 IP 包的 DF 標志位
  • 檢查 IP 包的 大小是否超過帶轉發端口的 MTU
  • 如果超過,而且 DF = 0 ,則將它分成多個包再發送 (分包)
  • 如果超過,而且 DF = 1,則向發生着返回一個 ICMP 消息,並將包丟棄 (PMTU)
  • 如果不超過,則轉發 (轉發)

例子1:超過 MTU,DF = 0 => 路由器分包、發送,接收主機組裝

例子2:超過,DF = 1 => PMTU,發送者重新以小包發送

更多例子,請參考 Resolve IP Fragmentation, MTU, MSS, and PMTUD Issues with GRE and IPSEC

2. Linux vxlan + bridge 環境中的網絡棧和 MTU

2.1 QEMU/KVM 計算節點上的網絡棧

2.1.1 協議棧

  • 紅線:QEMU/KVM 主機網卡接收外部網絡包並發給虛機
  • 黑線:虛機上的應用發出網絡包經過 QEMU/KVM 主機網卡發出

補充說明一下使用 virtio_net 時客戶機網卡 eth0 和 主機上的 tap 設備之間的關系:

   

  • 虛機的網絡流量是通過 virtio_net queue 發到 QEMU/KVM 主機上的 QEMU 的
  • QEMU 再交給主機上的 tap 設備

可見,eth0 和 tap 設備是不直接連接的,而是需要經過 QEMU。

2.1.2 各個 network interface 的 MTU

每個 network interface 都可以設置不同的 MTU,用來限制經過它的最大 IP payload 的長度。這些 network interface 包括:

  • 虛機 eth0
  • 主機 tap 設備
  • 主機 vxlan interface 
  • 主機 網卡 eth1
網絡接口 MTU 來源 說明
物理網卡 eth0  1500     安裝系統時指定,未指定則使用默認值 1500 用於虛機的數據網絡的物理網卡
vxlan interface 1450 由 linux vxlan 內核模塊創建該interface對應的 ip 設備時指定,其 MTU 為綁定的網卡的MTU 值減去 50  
tap 設備 1450

由 linux bridge 在添加 tap 到 linux bridge 時指定為該 bridge 所有 port 的最小 MTU。

dev_set_mtu(br->dev, br_min_mtu(br))

linux bridge 代碼

和虛機 eth0 通過 QEMU virtio 連接

虛機 eth0 1450 Neutron DHCP 的 advertise_mtu 配置項有設置值時,由該值決定;否則,使用默認的 1500 neutron 代碼

從上圖也可以看出,

  • 主機網卡 eth1 的默認 MTU 是 1500 bytes,當然你可以修改
  • 網絡包經過 vxlan interface 到達 eth1 的過程中,Linux vxlan 內核模塊會將網絡包二層幀封裝成 UDP 包,因此,vxlan interface 必須設置適當的 MTU 來限制通過它的網絡包的大小(從 1.2 章節可以看出,vxlan interface 的 MTU 需要比它所綁定的物理網卡的 MTU 小 50),否則,封裝后的包會被 eth1 丟棄。
  • tap 設備和虛機 eth0 的 MTU 是相同的,因為 QEUM 只是轉發,而沒做封裝之類的處理。而因為 vxlan interface MTU 需要縮小,因此它們的 MTU 也要相應縮小。因為 eth0 到 vxlan interface 之間沒什么包封裝,因此,它們的 MTU 可以一致。

2.2 Neutron 網絡節點上的協議棧

 

網絡接口 MTU 來源 說明
物理網卡 eth0  1500                  安裝系統時指定,未指定則使用默認值 用於虛機的數據網絡的物理網卡
vxlan interface 1450

由 linux vxlan 內核模塊創建該interface對應的 ip 設備時指定,其 MTU 為綁定的網卡的MTU 值減去 50

tap 和 qr/ns/qg 是 veth 的兩端
tap 設備 1450

由 linux bridge 在添加 tap 到 linux bridge 時指定為該 bridge 所有 port 的最小 MTU。因為 vxlan interface 的 MTU 是 

1450, 因此tap 設備的 MTU 也是 1450.

dev_set_mtu(br->dev, br_min_mtu(br))
qr/ns/qg network interface 及對應的tap設備 1500

由 Neutorn 根據其配置項 conf.network_device_mtu 來設置:設置了其值時,設置MTU為該值;否則,不指定時,則使用默認值1500。

可見這里有個問題,這個 MTU 和 tap 的 MTU 應該一致,但是 conf.network_device_mtu 沒有默認值,因此不配置該值的時候,其 MTU 為 1500,這將導致和 tap 的 MTU 不一致。后面會分析該不一致導致的問題。

neutron 代碼
物理網卡 eth1 1500 neutorn 有配置項時使用配置的值,具體見下面的分析;沒有時,使用默認值 1500. 用於訪問外網的物理網卡

 

3. 實驗和分析

3.1 Neutorn 網絡節點的 eth1 使用默認 MTU 1500,其它設備使用 MTU 1450

(1)網絡節點上:在 qdhcp network name 中執行 ping 命令:指定數據大小為 1422,加上 ICMP header 8 字節和 IP header 20 字節,共 1450 字節。

root@controller:~# ip netns exec qdhcp-18fc2ba1-057c-4c88-b523-8470fc31ecc1 ping -M do -i 1 -c 2 -s 1422 70.0.0.150
PING 70.0.0.150 (70.0.0.150) 1422(1450) bytes of data.
1430 bytes from 70.0.0.150: icmp_seq=1 ttl=64 time=1.89 ms
1430 bytes from 70.0.0.150: icmp_seq=2 ttl=64 time=1.47 ms

(2)網絡節點上:tap 設備收到的 ethernet frame 長度為 1464 (IP 包總長 1450 字節 + ethernet header 14 字節)

17:21:22.327944 fa:16:3e:32:35:ef > fa:16:3e:85:06:8e, ethertype IPv4 (0x0800), length 1464: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 1450)
    70.0.0.100 > 70.0.0.150: ICMP echo request, id 18979, seq 1, length 1430

(3)網絡節點上:vxlan interface 收到的frame 和 tap 設備收到的是一樣的,長度 1464

17:23:44.027648 fa:16:3e:32:35:ef > fa:16:3e:85:06:8e, ethertype IPv4 (0x0800), length 1464: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 1450)
    70.0.0.100 > 70.0.0.150: ICMP echo request, id 19059, seq 1, length 1430

(4)網絡節點上:用於虛機數據網絡的網卡 eth1 收到的幀長 1514 (1464 + vxlan header 8 + udp header 8 + IP header 20 + ethernet header 14 = 1514 )

17:27:27.577163 52:54:00:7c:c0:79 > fa:80:13:21:6b:56, ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 9573, offset 0, flags [none], proto UDP (17), length 1500) # vxlan 封包幀 10.0.0.10.56309 > 10.0.0.13.8472: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 1074
fa:16:3e:32:35:ef > fa:16:3e:85:06:8e, ethertype IPv4 (0x0800), length 1464: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 1450) #原始二層幀 70.0.0.100 > 70.0.0.150: ICMP echo request, id 19163, seq 2, length 1430

注意:eth1 的 MTU 是 1500,但是 1500 是指 IP 包的最大長度,而不將 ethernet header 計算在內,因此,此幀可以被順利發到物理網絡。

(5)計算節點上:物理網卡 eth1 收到的幀長是 1514

17:46:42.039327 52:54:00:7c:c0:79 > 01:00:5e:00:00:01, ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 1, id 61037, offset 0, flags [none], proto UDP (17), length 1500)
    10.0.0.10.56309 > 224.0.0.1.8472: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 1074
fa:16:3e:32:35:ef > fa:16:3e:85:06:8e, ethertype IPv4 (0x0800), length 1464: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 1450)
    70.0.0.100 > 70.0.0.150: ICMP echo request, id 19375, seq 1, length 1430

(6)計算節點上:vxlan interface 收到的幀長為 1464。可見,它收到的包已經經過 linux vxlan 內核模塊解包了。

17:48:27.051651 fa:16:3e:32:35:ef > fa:16:3e:85:06:8e, ethertype IPv4 (0x0800), length 1464: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 1450)
    70.0.0.100 > 70.0.0.150: ICMP echo request, id 19412, seq 1, length 1430

(7)計算節點上:包順利到底 tap 和 虛機的 eth0,直至 ICMP 協議處理函數。

 3.2 Neutorn 網絡節點的 eth1 使用默認 MTU 1500,其它設備使用默認 MTU,其中 ns 的 MTU 為 1500。有詭異的問題

(1)同樣在 qdhcp namespace 中執行 ping 操作。考慮到其 MTU 為 1500,因此,最大的數據塊長度可以為 1500 - 28 = 1472。但是沒有收到回應包,失敗。

root@controller:~# ip netns exec qdhcp-18fc2ba1-057c-4c88-b523-8470fc31ecc1 ping -M do -i 1 -c 2 -s 1472 70.0.0.150
PING 70.0.0.150 (70.0.0.150) 1472(1500) bytes of data.

而在對應的 tap 設備上,tcpdump 沒有輸出。因此可以看出,因為 tap 設備的 MTU 是 1450,導致長度為 1500 的包沒法通過。

(2)同樣在 qdhcp namespace 中執行 ping 操作,但是不設置數據長度,其 IP 包長度為 84。成功。這是因為 IP 包長度 84 是在 MTU 范圍之內。

root@controller:~# ip netns exec qdhcp-18fc2ba1-057c-4c88-b523-8470fc31ecc1 ping -M want -i 1 -c 2 70.0.0.150
PING 70.0.0.150 (70.0.0.150) 56(84) bytes of data.
64 bytes from 70.0.0.150: icmp_seq=1 ttl=64 time=1.99 ms
64 bytes from 70.0.0.150: icmp_seq=2 ttl=64 time=1.37 ms

在 tap 設備上的幀長度為 98 = 84 + ethernet header 14 字節

17:47:42.335841 fa:16:3e:32:35:ef > fa:16:3e:85:06:8e, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 26932, offset 0, flags [DF], proto ICMP (1), length 84)
    70.0.0.100 > 70.0.0.150: ICMP echo request, id 19734, seq 1, length 64

(3)從 qrouter 中使用 ssh 連接虛機(第一次連接一個新虛機),ssh 停留在 “debug1: SSH2_MSG_KEXINIT sent”,失敗

root@controller:~/s1# ip netns exec qrouter-b94a203d-5317-4d0b-9833-5c65e01bd76f ssh -i ubuntu.pem ibmcloud@70.0.0.152 -vvv
OpenSSH_6.6.1, OpenSSL 1.0.1f 6 Jan 2014
debug1: Reading configuration data /etc/ssh/ssh_config
...
debug3: load_hostkeys: loading entries for host "70.0.0.152" from file "/root/.ssh/known_hosts"
debug3: load_hostkeys: loaded 0 keys
debug1: SSH2_MSG_KEXINIT sent

在 ns 端口對應的 tap 設備上做 tcpdump,看起來象是客戶端的 ssh 有關數據在發往虛機的過程中被截斷了:

18:40:35.405723 fa:16:3e:32:35:ef > fa:16:3e:3f:3b:2a, ethertype IPv4 (0x0800), length 96: (tos 0x0, ttl 64, id 29605, offset 0, flags [DF], proto UDP (17), length 82)
    70.0.0.100.53 > 70.0.0.152.58164: [bad udp cksum 0x8d4b -> 0x0ff4!] 397 Refused q: A? changelogs.ubuntu.com.openstacklocal. 0/0/0 (54)
18:40:35.406534 fa:16:3e:3f:3b:2a > fa:16:3e:32:35:ef, ethertype IPv4 (0x0800), length 96: (tos 0x0, ttl 64, id 43407, offset 0, flags [DF], proto UDP (17), length 82)
    70.0.0.152.58164 > 70.0.0.100.53: [udp sum ok] 41422+ AAAA? changelogs.ubuntu.com.openstacklocal. (54)

(4)將  qrouter 的 qr inteface 的 MTU 改為 1450,則 ssh 成功。查看成功連接過程中的數據包,只發現下面的包比較可疑,因為它達到了物理網絡的 MTU:

18:51:58.539087 52:54:00:7c:c0:79 > fa:80:13:21:6b:56, ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 31536, offset 0, flags [none], proto UDP (17), length 1500)
fa:16:3e:19:15:fe > fa:16:3e:3f:3b:2a, ethertype IPv4 (0x0800), length 1464: (tos 0x0, ttl 64, id 19222, offset 0, flags [DF], proto TCP (6), length 1450)
    70.0.0.1.56611 > 70.0.0.152.22: Flags [.], cksum 0xd128 (correct), seq 44:1442, ack 42, win 221, options [nop,nop,TS val 25021385 ecr 218717], length 1398

當 MTU 是 1500 的話,該幀的大小將會是 1564,它超過了其它網絡接口的 MTU,因此,它應該無法到達虛機。但是,這只是猜測,具體原因未知,但是修改 MTU 為 1450 確實可以解決問題。

4. Neutron MTU 方案

Neutron 這個 ticket  Linux Bridge MTU bug when the VXLAN tunneling is used 解釋了這個問題,並給出了方案。再簡單總結一下問題和原因:

  • 默認地,物理網卡的 MTU 為 1500 字節。
  • Linux vxlan 在創建 vxlan interface 時,設置其 MTU 為所綁定物理網卡 MTU 減去 50,即 1450.
  • Linux bridge 上的其它 tap 設備,包括虛機的網卡、network namespace (包括 l3 和 dhcp)的 interface 相應的 tap 設備的 MTU 都是 1450.
  • 默認情況下,虛機的網卡、network namespace (包括 l3 和 dhcp)的 interface 的 MTU 都是 1500。
  • 因此,虛機和 network namespace 中的軟件產生的數據包在通過這些 network interface 轉發到 vxlan interface 時如果其數據幀超過 (1450 + 14 = 1464)字節時將會被丟棄,這將導致一些奇怪的問題,比如上面談到的 ssh 無法連接等。

下面分別介紹兩個workaround。

4.1 增加物理網卡和相關 linux bridge interface 的 MTU 

在虛機網絡接口使用默認 MTU 1500 時,

(1)需要設置物理網卡和相關 linux bridge interface 的 MTU 為 1550。

(2)OpenStack 的自動化配置工具 Juju 在做自動化配置物理網卡 MTU 的一些工作,有個 ticket Setting mtu of phy NICs and veth devices to support configuring VM's MTU>=1500 中有些介紹,但是該工作尚未完成(到2015/12月)。因此,使用這個 workaround 需要對物理網卡做手工配置。

(3)另外,如果你的物理網絡已經使用巨幀(jumbo frame),那么虛機網絡接口的 MTU 的問題自動被規避了。

4.2(Kilo版本中)降低虛擬網絡接口(virtual network interface)的 MTU

虛擬網絡接口包括兩種,分別有不同的配置方法:

4.2.1 虛機網卡的 MTU 設置:使用 MTU selection and advertisement 機制

  包括以下步驟:

(1)在 network 中增加 mtu 屬性,目前該屬性對於 Neutron API 只可見,不可以修改,默認值為 0 。ticket

'mtu': {'allow_post': False, 'allow_put': False, 'is_visible': True}

(2)通過有關配置參數設置 network 的 mtu。目前在 /etc/neutron/plugins/ml2/ml2_conf.ini 中有如下幾個相關參數。

# =========== items for MTU selection and advertisement ============= 
31 # (IntOpt) Path MTU. The maximum permissible size of an unfragmented
32 # packet travelling from and to addresses where encapsulated Neutron
33 # traffic is sent. Drivers calculate maximum viable MTU for
34 # validating tenant requests based on this value (typically,
35 # path_mtu - max encap header size). If <=0, the path MTU is
36 # indeterminate and no calculation takes place.
37 # path_mtu = 0
38
39 # (IntOpt) Segment MTU. The maximum permissible size of an
40 # unfragmented packet travelling a L2 network segment. If <=0,
41 # the segment MTU is indeterminate and no calculation takes place.
42 # segment_mtu = 0
43
44 # (ListOpt) Physical network MTUs. List of mappings of physical
45 # network to MTU value. The format of the mapping is
46 # <physnet>:<mtu val>. This mapping allows specifying a
47 # physical network MTU value that differs from the default
48 # segment_mtu value.
49 # physical_network_mtus =
50 # Example: physical_network_mtus = physnet1:1550, physnet2:1500
51 # ======== end of items for MTU selection and advertisement ========= 

 physical_network_mtus : 對 provider network 使用,適用於 flat 和 vlan 類型的虛擬網絡。

def get_mtu(self, physical_network):
        seg_mtu = super(FlatTypeDriver, self).get_mtu()
        mtu = []
        if seg_mtu > 0:
            mtu.append(seg_mtu)
        if physical_network in self.physnet_mtus:
            mtu.append(int(self.physnet_mtus[physical_network]))
        return min(mtu) if mtu else 0

path_mtu:設置租戶網絡的最大可能 MTU。

segment_mtu :租戶網絡的默認 MTU

三個配置參數結合不同的租戶網絡類型來確定其 MTU:

  • Flat/VLAN:Minimum of (segment_mtu or physical_network_mtus)
  • GRE: Minimum of (segment_mtu, path_mtu) 減去 42
  • VXLAN: Minimum of (segment_mtu, path_mtu) 減去 50

配置這些 MTU 參數后,neutron net-show 命令就可以顯示每個網絡的 mtu 了。

注意:這些 MTU 設置不能僅對某一個租戶網絡使用,而是適合於同類型的所有網絡。

(3)在 neutron.conf 中增加配置項 advertise_mtu,默認值為 false。在設置為 true 后,DHCP 將想申請/renew的固定地址的網卡廣告 network 的 mtu。 

# =========== items for MTU selection and advertisement =============
# Advertise MTU.  If True, effort is made to advertise MTU
# settings to VMs via network methods (ie. DHCP and RA MTU options)
# when the network's preferred MTU is known.
# advertise_mtu = False
# ======== end of items for MTU selection and advertisement =========
if cfg.CONF.advertise_mtu:
    mtu = self.network.mtu #network.mtu 由第(2)步確定
    # Do not advertise unknown mtu
    if mtu > 0:
        cmd.append('--dhcp-option-force=option:mtu,%d' % mtu)

4.2.2 設置 neutron 網絡節點上 network namespace 的 qr/ns/qg 以及它們對應的 tap 設備等虛擬網絡接口的 MTU

在 neutron.conf 中設置配置項 network_device_mtu 的值來指定這些網絡節點的 MTU:

if self.conf.network_device_mtu:
            root_veth.link.set_mtu(self.conf.network_device_mtu)
            ns_veth.link.set_mtu(self.conf.network_device_mtu)

4.2.3 總結 VxLAN + Linux bridge 網絡環境中的 MTU 配置

配置文件 配置項 默認值 需要修改為           生效的虛擬網絡接口 生效步驟
neutorn 控制節點上的 neutron.conf network_device_mtu none(此時 mtu 為 1500,這會帶來詭異的問題,見上面 3.2 部分的描述 1450

neutron 網絡節點上的 qdhcp 和 qrouter network namespace

的 qr,qg 和 ns 接口以及對應的 veth tap 設備;

還需要在 dhcp_agent.ini 和 l3_agent.ini 文件中設置

 interface_driver = neutron.agent.linux.interface.BridgeInterfaceDriver

對存在的 qdhcp 和 qrouter netns:

1. 修改 neutron.conf 文件

2. 確定 qrouter 的 interface

3. stop dhcp 和 l3 agent

4. 刪除已有的 qdhcp 和 qrouter network name

5. 刪除 qrouter 所有interface 對應的 veth 設備,其名稱為 'tap' +interafce name 去掉前綴

6. 啟動 dhcp 和 l3 agent

7. 檢查 qdhcp 和 qrouter netns 中的 interface 的 mtu

對修改后新建的netns,自動生效。

neutorn 控制節點上的 ml2_conf.ini segment_mtu 0 (使用默認 mtu) 1500

對 GRE 和 VxLAN 類型的租戶網絡適用,

取 (segment_mtu 和 path_mtu)之間的小者減去 42 或者 50

 
path_mtu 0 (使用默認 mtu) 1500 見下文示例2
physical_network_mtus 空 (使用默認 mtu) 1500 對 flat 和 vlan 類型的 provider network 適用,取(segment_mtu  和 physical_network_mtus)之間的較小值 見下文示例1
neutorn 控制節點上的 neutron.conf advertise_mtu false (默認不廣告 mtu 給客戶機網卡) true 使得 DHCP 能對虛機的網卡廣告所在網絡 MTU 值  

 示例1:創建 mtu 為 1600 的 flat 類型的provider network:

(1)修改neutorn 控制節點上的 ml2_conf.ini配置文件:physical_network_mtus = physnet1:1600 flat_networks = external, physnet1

(2)重啟neutron-server 服務

(3)創建 flat 類型網絡:neutron net-create --provider:network_type flat --provider:physical_network physnet1 flatextnet2

root@controller:~# neutron net-create --provider:network_type flat --provider:physical_network physnet1 flatextnet2
Created a new network:
+---------------------------+--------------------------------------+
| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | True                                 |
| id                        | 9270a2bf-7e63-4001-884c-4c48e1b0f5e5 |
| mtu                       | 1600                                 |
| name                      | flatextnet2                          |

示例2:創建 mtu 為 1450 的 VxLAN 租戶網絡並啟動虛機

(1)修改neutorn 控制節點上的 ml2_conf.ini配置文件:path_mtu = 9000 segment_mtu = 1500

(2)重啟neutron-server 服務

(3)創建 vxlan 類型的租戶網絡:

root@controller:~# neutron net-create test111
Created a new network:
+---------------------------+--------------------------------------+
| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | True                                 |
| id                        | 901a5ba3-be92-440f-b7ca-ff277b527ea5 |
| mtu                       | 1450                                 |
| name                      | test111                              |
| provider:network_type     | vxlan                                |

(4)在該網絡中創建啟用 dhcp 的 subnet

(5)檢查 dnsmasq,會發現它已經使用了 dhcp-option-force 參數,其中 mtu 的值就是該網絡的 mtu 值

nobody   18930     1  0 10:45 ?        00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=ns-9022f50c-a8 --except-interface=lo --pid-file=/var/lib/neutron/dhcp/901a5ba3-be92-440f-b7ca-ff277b527ea5/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/901a5ba3-be92-440f-b7ca-ff277b527ea5/host --addn-hosts=/var/lib/neutron/dhcp/901a5ba3-be92-440f-b7ca-ff277b527ea5/addn_hosts --dhcp-optsfile=/var/lib/neutron/dhcp/901a5ba3-be92-440f-b7ca-ff277b527ea5/opts --dhcp-leasefile=/var/lib/neutron/dhcp/901a5ba3-be92-440f-b7ca-ff277b527ea5/leases --dhcp-range=set:tag0,20.0.0.0,static,86400s --dhcp-option-force=option:mtu,1450 --dhcp-lease-max=256 --conf-file=/etc/neutron/dnsmasq.conf --domain=openstacklocal

(6)在該子網中創建虛機,其網卡的 mtu 值將是 1450.

(7)注意:目前(Kilo)版本中,網絡的 mtu 值計算只在它被創建的時候,也就是說,對於已經存在的網絡,無法再修改它的 mtu 值了。

4.3 (Kilo版本之前)設置客戶機網卡的 MTU

Kilo 版本之前需要手工修改 dnsmasq 的配置來達到差不多同樣的效果,通過下面的步驟:

  1. 編輯 /etc/neutron/dhcp_agent.ini 文件,在 [DEFAULT] 部分添加 dnsmasq_config_file = /etc/neutron/dnsmasq-neutron.conf
  2. 創建和編輯 /etc/neutron/dnsmasq-neutron.conf 文件,添加 dhcp-option-force=26,1450
  3. 殺掉當前 dnsmasq,重啟 dhcp agent

 和 4.2.1 的區別在於,Kilo 版本中可以計算不同虛機網絡的 MTU,而 Kilo 版本之前使用的dnsmasq 配置文件中的配置項只能所有的網絡使用同樣的 mtu。

 

參考鏈接:

http://www.cubrid.org/blog/dev-platform/understanding-tcp-ip-network-stack/

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/net/bridge/br_if.c#n402

https://review.openstack.org/#/c/63312/3/doc/config-reference/networking/section_networking-plugins-ml2.xml

https://review.openstack.org/#/c/105989/8/specs/kilo/mtu-selection-and-advertisement.rst

https://access.redhat.com/documentation/en/red-hat-enterprise-linux-openstack-platform/7/networking-guide/chapter-16-configure-mtu-settings

http://www.cisco.com/c/en/us/support/docs/ip/generic-routing-encapsulation-gre/25885-pmtud-ipfrag.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM