分享

Neutron VxLAN + Linux Bridge 环境中的网络 MTU【下】

eying 2016-1-6 16:18:17 发表于 连载型 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 18860
本帖最后由 eying 于 2016-1-6 16:21 编辑
问题导读:



1.如何设置Neutorn 网络节点的 eth1?
2.
Neutron MTU 方案有哪些?
3.怎样配置VxLAN + Linux bridge 网络环境中的 MTU ?










3. 实验和分析


3.1 Neutorn 网络节点的 eth1 使用默认 MTU 1500,其它设备使用 MTU 1450

(1)网络节点上:在 qdhcp network name 中执行 ping 命令:指定数据大小为 1422,加上 ICMP header 8 字节和 IP header 20 字节,共 1450 字节。

[mw_shl_code=applescript,true]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[/mw_shl_code]

(2)网络节点上:tap 设备收到的 ethernet frame 长度为 1464 (IP 包总长 1450 字节 + ethernet header 14 字节)

[mw_shl_code=applescript,true]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[/mw_shl_code]

(3)网络节点上:vxlan interface 收到的frame 和 tap 设备收到的是一样的,长度 1464

[mw_shl_code=applescript,true]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[/mw_shl_code]

(4)网络节点上:用于虚机数据网络的网卡 eth1 收到的帧长 1514 (1464 + vxlan header 8 + udp header 8 + IP header 20 + ethernet header 14 = 1514 )

[mw_shl_code=applescript,true]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[/mw_shl_code]

注意:eth1 的 MTU 是 1500,但是 1500 是指 IP 包的最大长度,而不将 ethernet header 计算在内,因此,此帧可以被顺利发到物理网络。

(5)计算节点上:物理网卡 eth1 收到的帧长是 1514

[mw_shl_code=applescript,true]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[/mw_shl_code]

(6)计算节点上:vxlan interface 收到的帧长为 1464。可见,它收到的包已经经过 linux vxlan 内核模块解包了。

[mw_shl_code=applescript,true]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[/mw_shl_code]

(7)计算节点上:包顺利到底 tap 和 虚机的 eth0,直至 ICMP 协议处理函数。

3.2 Neutorn 网络节点的 eth1 使用默认 MTU 1500,其它设备使用默认 MTU,其中 ns 的 MTU 为 1500。有诡异的问题。

(1)同样在 qdhcp namespace 中执行 ping 操作。考虑到其 MTU 为 1500,因此,最大的数据块长度可以为 1500 - 28 = 1472。但是没有收到回应包,失败。

[mw_shl_code=applescript,true]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.[/mw_shl_code]

而在对应的 tap 设备上,tcpdump 没有输出。因此可以看出,因为 tap 设备的 MTU 是 1450,导致长度为 1500 的包没法通过。

(2)同样在 qdhcp namespace 中执行 ping 操作,但是不设置数据长度,其 IP 包长度为 84。成功。这是因为 IP 包长度 84 是在 MTU 范围之内。

[mw_shl_code=applescript,true]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[/mw_shl_code]

在 tap 设备上的帧长度为 98 = 84 + ethernet header 14 字节

[mw_shl_code=applescript,true]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[/mw_shl_code]

(3)从 qrouter 中使用 ssh 连接虚机(第一次连接一个新虚机),ssh 停留在 “debug1: SSH2_MSG_KEXINIT sent”,失败

[mw_shl_code=applescript,true]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[/mw_shl_code]

在 ns 端口对应的 tap 设备上做 tcpdump,看起来象是客户端的 ssh 有关数据在发往虚机的过程中被截断了:

[mw_shl_code=applescript,true]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)[/mw_shl_code]

(4)将  qrouter 的 qr inteface 的 MTU 改为 1450,则 ssh 成功。查看成功连接过程中的数据包,只发现下面的包比较可疑,因为它达到了物理网络的 MTU:

[mw_shl_code=applescript,true]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[/mw_shl_code]

当 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


[mw_shl_code=applescript,true]'mtu': {'allow_post': False, 'allow_put': False, 'is_visible': True}[/mw_shl_code]

(2)通过有关配置参数设置 network 的 mtu。目前在 /etc/neutron/plugins/ml2/ml2_conf.ini 中有如下几个相关参数。

[mw_shl_code=applescript,true]# =========== 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 ========= [/mw_shl_code]

physical_network_mtus : 对 provider network 使用,适用于 flat 和 vlan 类型的虚拟网络。

[mw_shl_code=applescript,true]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[/mw_shl_code]

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。

[mw_shl_code=applescript,true]# =========== 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)[/mw_shl_code]

4.2.2 设置 neutron 网络节点上 network namespace 的 qr/ns/qg 以及它们对应的 tap 设备等虚拟网络接口的 MTU

在 neutron.conf 中设置配置项 network_device_mtu 的值来指定这些网络节点的 MTU:

[mw_shl_code=applescript,true]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)[/mw_shl_code]

4.2.3 总结 VxLAN + Linux bridge 网络环境中的 MTU 配置
配置文件配置项默认值需要修改为          生效的虚拟网络接口生效步骤
neutorn 控制节点上的 neutron.confnetwork_device_mtunone(此时 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.inisegment_mtu0 (使用默认 mtu)1500
对 GRE 和 VxLAN 类型的租户
网络适用,
取 (segment_mtu 和 path_mtu)
之间的小者减去 42 或者 50
path_mtu0 (使用默认 mtu)1500见下文示例2
physical_network_mtus空 (使用默认 mtu)1500对 flat 和 vlan 类型的 provider
network 适用,取(segment_mtu  和 physical_network_mtus)
之间的较小值
见下文示例1
neutorn 控制节点上的 neutron.confadvertise_mtufalse (默认不广告 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

[mw_shl_code=applescript,true]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                          |[/mw_shl_code]

示例2:创建 mtu 为 1450 的 VxLAN 租户网络并启动虚机

(1)修改neutorn 控制节点上的 ml2_conf.ini配置文件:path_mtu = 9000 segment_mtu = 1500
(2)重启neutron-server 服务
(3)创建 vxlan 类型的租户网络:

[mw_shl_code=applescript,true]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                                |[/mw_shl_code]

(4)在该网络中创建启用 dhcp 的 subnet

(5)检查 dnsmasq,会发现它已经使用了 dhcp-option-force 参数,其中 mtu 的值就是该网络的 mtu 值

[mw_shl_code=applescript,true]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[/mw_shl_code]

(6)在该子网中创建虚机,其网卡的 mtu 值将是 1450.

(7)注意:目前(Kilo)版本中,网络的 mtu 值计算只在它被创建的时候,也就是说,对于已经存在的网络,无法再修改它的 mtu 值了。

4.3 (Kilo版本之前)设置客户机网卡的 MTU

Kilo 版本之前需要手工修改 dnsmasq 的配置来达到差不多同样的效果,通过下面的步骤:

  • 编辑 /etc/neutron/dhcp_agent.ini 文件,在 [DEFAULT] 部分添加 dnsmasq_config_file = /etc/neutron/dnsmasq-neutron.conf
  • 创建和编辑 /etc/neutron/dnsmasq-neutron.conf 文件,添加 dhcp-option-force=26,1450
  • 杀掉当前 dnsmasq,重启 dhcp agent

和 4.2.1 的区别在于,Kilo 版本中可以计算不同虚机网络的 MTU,而 Kilo 版本之前使用的dnsmasq 配置文件中的配置项只能所有的网络使用同样的 mtu。








没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条