本文主要讲解网络通信中MTU,IP MTU和MSS的概念以及它们之间的关系。这三个概念对于网络通信来说非常重要,在实际的网络场景中常常很多网页打不开等问题,往往罪魁祸首都是这几个参数没配置正确导致的。VPP在21.06提交了一个tcp mss clamp的patch,本文主要来学习一下配置及使用。
在以太网链路上的数据包称作以太帧。以太帧起始部分由前导码和帧开始符组成。后面紧跟着一个以太网报头,以MAC地址说明目的地址和源地址。帧的中部是该帧负载的包含其他协议报头的数据包(例如IP协议)。以太帧由一个32位冗余校验码结尾。它用于检验数据传输是否出现损坏:EthernetII 帧结构如下图所示。:
1、前同步码:第一个字段是7个字节的前同步码,1和0交替,作用是用来使接收端的适配器在接收MAC帧时能够迅速调整时钟频率,使它和发送端的频率相同。 2、帧开始定界符:第二个字段是1个字节的帧开始定界符,前六位1和0交替,最后的两个连续1表示告诉接收端适配器:“帧信息要来了,你准备接收吧。 3、帧检验序列FCS(使用CRC校验法):检测该帧是否出现差错。 RFC 1191 中有说明各种不同介质下MTU的数值范围,其中Ethernet是1500 1500 Ethernet Networks RFC 894
MTU(Maximum Transmission Unit),最大传输单元。用来通知对方所能接受数据服务单元的最大尺寸,说明发送方能够接受的有效载荷大小。由于以太网传输电气方面的限制,每个以太网帧最小64字节,最大不能超过1518字节。
小于64字节的报文,不足部分一般网卡会进行补0动作。大于1518字节报文会在网络层进行分片。
由于以太网EthernetII最大的数据帧是1518字节,除去以太网帧的帧头(DMAC:6字节+SMAC:6字节+Type域2字节)14字节和帧尾CRC校验部分4字节(就是上图中FCS),那么剩下承载上层协议的地方也就是Data域最大就只能有1500字节,这个值就称之为MTU。这个MTU是网络层协议非常关心的地方,因为网络层协议比如IP协议会根据这个值来决定是否把上层传下来的数据进行分片。
IP MTU是一个三层概念,它包含了三层头部及所有载荷,根据下层为上层服务的,上层基于下层才能做进一步的扩展的原则,尽管IP MTU的变化范围很大(68-65535),但也不得不照顾以太网MTU的限制,说白了就是IP对以太网的妥协。对于网络层的上层协议而言(以TCP/IP协议族为例),网络层IP协议会检查每个从上层协议下来的数据包的大小,并根据本机MTU的大小决定是否作“分片”处理。分片最大的坏处就是降低了传输性能。对于发送端和接收端都会造成cpu和内存的开销。
IP MTU 也是首次听说,下面是思科网站上查到的一个说明。 IP MTU—Can be configured on an interface or subinterface. If an IP packet exceeds the IP MTU size, then the packet is fragmented.
MSS就是TCP数据包每次能够传输的最大数据分段。为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值确定为这次连接的最大MSS值。
1.主机 A 比较其 MSS 缓冲区 (16K) 和其 MTU (1500 - 40 = 1460),并使用较小的值作为 MSS(1460),以便发送到主机 B 2、主机 B 收到主机 A 的发送 MSS (1460),并将其与出站接口 MTU - 40 的值 (4422) 相比较。主机 B 将较低的值 (1460) 设置为 MSS,以便向主机 A 发送 IPv4 数据报。 3.主机 B 比较其 MSS 缓冲区 (8K) 和其 MTU (4462 - 40 = 4422),并使用 4422 作为 MSS,以便发送到主机 A。 4.主机 A 收到主机 B 的发送 MSS (4422),并将其与出站接口 MTU - 40 的值 (1460) 相比较。 5.主机 A 将较低的值 (1460) 设置为 MSS,以便向主机 B 发送 IPv4 数据报。 6.1460 便是两台主机为彼此选择的发送 MSS 的值。通常 TCP 连接两端的发送 MSS 值相同。
TCP MSS clamping功能以插件的形式合入到vpp分支21.06-rc0。具体合入记录如下:
Author: Neale Ranns <neale.ranns@cisco.com> 2018-10-04 21:40:30
Committer: Damjan Marion <dmarion@me.com> 2021-03-05 18:55:26
Parent: ab9f57355f43976930ef52e6091ef80412b065a0 (api: crchcecker ignore version < 1.0.0 and outside of src directory)
Child: 3efd4e9998192545c32aeb33a9f8f72a1ba085a9 (tests: improve the robustness of process cleanup on INT/TERM signals)
Branches: master, mss_clamp.patch, remotes/origin/master
Follows: v21.06-rc0
Precedes:
mss_clamp: TCP MSS clamping plugin
Type: feature
Configure TCP MSS clamping on an interface as follows:
set interface tcp-mss-clamp [rx|tx] <interface-name>
ip4 [enable|disable|rx|tx] ip4-mss <size>
ip6 [enable|disable|rx|tx] ip6-mss <size>
代码合入记录作者是2018-10-04提交的,最近才合入主线分支。
#server 端配置:
ifconfig ens224 up
ifconfig ens224 192.168.100.2/24
#添加路由
route add -net 192.168.101.0/24 gw 192.168.100.1
#client端配置:
ifconfig ens256 up
ifconfig ens256 192.168.100.2/24
#添加路由
route add -net 192.168.100.0/24 gw 192.168.101.1
#vpp接口配置
set interface state GigabitEthernet13/0/0 up
set interface ip address GigabitEthernet13/0/0 192.168.100.1/24
set interface state GigabitEthernetb/0/0 up
set interface ip address GigabitEthernetb/0/0 192.168.101.1/24
linux下安装iperf3进行测试mss数据:
1、server服务端启动命令
iperf3 -s -B 192.168.100.2
2、client客户端启动命令
iperf3 -c 192.168.100.2 -B 192.168.101.2 -V #-V 显示mss协商后数值
3、vpp 配置修改mss
set interface tcp-mss-clamp GigabitEthernet13/0/0 ip4 enable ip4-mss 1300 ip6 enable ip6-mss 1300
测试结果:如下所以MSS大小为1288.主要是收到tcp可选项的影响。
[root@edge_auto_6 scripts]# iperf3 -c 192.168.100.2 -B 192.168.101.2 -V
iperf 3.1.7
Linux edge_auto_6 3.10.0-957.21.3.el7.x86_64 #1 SMP Tue Jun 18 16:35:19 UTC 2019 x86_64
Control connection MSS 1288
Time: Mon, 29 Mar 2021 12:06:16 GMT
Connecting to host 192.168.100.2, port 5201
Cookie: edge_auto_6.1617019576.833131.4ff56c
TCP MSS: 1288 (default)
[ 4] local 192.168.101.2 port 38135 connected to 192.168.100.2 port 5201
Starting Test: protocol: TCP, 1 streams, 131072 byte blocks, omitting 0 seconds, 10 second test
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 236 MBytes 1.98 Gbits/sec 75 840 KBytes
[ 4] 1.00-2.00 sec 278 MBytes 2.33 Gbits/sec 0 1.02 MBytes
[ 4] 2.00-3.00 sec 284 MBytes 2.38 Gbits/sec 0 1.19 MBytes
[ 4] 3.00-4.00 sec 288 MBytes 2.41 Gbits/sec 0 1.34 MBytes
[ 4] 4.00-5.00 sec 288 MBytes 2.41 Gbits/sec 0 1.47 MBytes
[ 4] 5.00-6.00 sec 289 MBytes 2.42 Gbits/sec 0 1.59 MBytes
[ 4] 6.00-7.00 sec 274 MBytes 2.30 Gbits/sec 208 819 KBytes
[ 4] 7.00-8.00 sec 286 MBytes 2.40 Gbits/sec 0 1.01 MBytes
[ 4] 8.00-9.00 sec 291 MBytes 2.44 Gbits/sec 0 1.18 MBytes
[ 4] 9.00-10.00 sec 289 MBytes 2.42 Gbits/sec 0 1.33 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
Test Complete. Summary Results:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 2.74 GBytes 2.35 Gbits/sec 283 sender
[ 4] 0.00-10.00 sec 2.73 GBytes 2.35 Gbits/sec receiver
CPU Utilization: local/sender 10.9% (0.1%u/10.9%s), remote/receiver 0.1% (0.0%u/0.1%s)
snd_tcp_congestion cubic
rcv_tcp_congestion cubic
iperf Done.
iperf3 测试结果实际mss=1288,而不是1300,抓包确认是因为tcp头中带有12字节可选项。tcp协议“数据偏移”字段,决定了tcp头的最大长度。 该字段占4bit,取最大的1111时,也就是十进制的15,TCP首部的偏移单位为4byte,那么TCP首部长度最长为15*4=60字节。 下图是抓取的报文长度,其中时间戳是10字节,其他是补充字节2个nop选项。
这样看来tcp syn报文中mss长度默认设置为1300,mtu = 1300+20+20 = 1340,IP报文和tcp报文待扩展字段都会导致实际发包报文长度减少。
华为ME60手册中关于tcp mss的应用场景: TCP建链阶段,SYN报文可以携带MSS选项,来告知对端,本端能够接收的最大报文段大小。一般说来,如果没有分片发生,MSS还是越大越好,报文段越大允许每个报文段传送的数据就越多,网络传输效率就越高。但是,过大的MSS选项可能会导致报文在IP层被分片处理,同时,IP层会对分片处理的报文的MSS值直接改小,使TCP报文封装了IP头之后,在端到端传输过程中尽量不分片。用户可以通过配置此命令,对TCP报文的MSS选项进行修改和插入,从而提升网络的利用率。 MSS选项修改:系统收到建立TCP连接的SYN报文时会检查设备上是否配置了MSS选项值,如果配置则检查SYN报文是否携带MSS选项,如果携带则与设备上配置MSS选项进行对比,如果报文携带的MSS选项值大于设备上配置的值则修改报文携带的MSS选项值为设备上配置的MSS选项值,如果小于则不修改报文携带的MSS选项值。 MSS选项插入:系统收到建立TCP连接的SYN报文时会检查该流是否有配置MSS选项,如果配置则检查SYN报文是否携带MSS选项,如果报文未携带MSS选项则增加用户配置MSS选项值到报文字段中。(VPP 目前不支持MSS选项插入) 为保证TCP报文封装了IP头之后,在端到端传输过程中尽量不分片。TCP MSS选项值需要小于接口MTU的值。
# 在HTS实例视图下配置TCP报文MSS值为1000。
<HUAWEI> system-view
[~HUAWEI] hts instance instance1 id 2
[*HUAWEI-hts-instance-instance1] tcp-mss 1000
1、MSS修改不支持带有扩展头的ipv6报文。代码中在偏移tcp头时,未考虑此场景。 2、MSS配置支持单方向设置,但是只能生效一个方向,需要注意。
/*
* fixup the maximum segment size if it's a syn packet
* return 1 if the mss was changed otherwise 0
*/
always_inline u32
mssc_mss_fixup (vlib_buffer_t *b0, tcp_header_t *tcp0, u16 max_mss0)
{
ip_csum_t sum0;
/*判断时TCP syn报文,这里使用分支预测false*/
if (PREDICT_FALSE (tcp_syn (tcp0)))
{
u8 opt_len, opts_len, kind;
const u8 *data;
u16 mss0, new_mss0;
/*获取可选项的最长度*/
opts_len = (tcp_doff (tcp0) << 2) - sizeof (tcp_header_t);
data = (const u8 *) (tcp0 + 1);
for (; opts_len > 0; opts_len -= opt_len, data += opt_len)
{
kind = data[0];
/* Get options length */
if (kind == TCP_OPTION_EOL)
{
break;
}
else if (kind == TCP_OPTION_NOOP)
{
opt_len = 1;
continue;
}
else
{
/* broken options */
if (opts_len < 2)
return 0;
opt_len = data[1];
/* weird option length */
if (opt_len < 2 || opt_len > opts_len)
return 0;
}
if (kind == TCP_OPTION_MSS)
{ /*MSS 可选项*/
mss0 = *(u16 *) (data + 2);
/*当前报文中MSS大于设置数值时,才进行修改*/
if (clib_net_to_host_u16 (mss0) > max_mss0)
{
new_mss0 = clib_host_to_net_u16 (max_mss0);
*((u16 *) (data + 2)) = new_mss0;
sum0 = tcp0->checksum;
sum0 = ip_csum_update (sum0, mss0, new_mss0, tcp_header_t,
checksum);
tcp0->checksum = ip_csum_fold (sum0);
return 1;
}
}
}
}
return 0;
}
按照《MTU工具解析与常见问题汇总-下篇》的方法进行验证MTU大小。
通过手工ICMPPing测试发现最优MTU值。利用ip报文头flag字段DF标识位,设置为不能分片,
[root@edge_auto_6 tmp]# ping 192.168.100.2 -I ens256 -c 1 -M do -s 3000
PING 192.168.100.2 (192.168.100.2) from 192.168.101.2 ens256: 3000(3028) bytes of data.
ping: local error: Message too long, mtu=1500 #显示localerror,说明是本地。MTU为1500
--- 192.168.100.2 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
ping命令参数详解中:-M:设置MTU(最大传输单元)分片策略。 可设置为: 'do':禁止分片,即使包被丢弃; 'want':当包过大时分片; 'dont':不设置分片标志(DF flag); 链接http://aiezu.com/article/linux_ping_command.html
上述场景发现是linux内核接口ens256 mtu设置为1500,所以直接返回了local error。通过命令行·ifconfig ens256 mtu 400·调整接口mtu为4000,再次发起ping报文,发现不会有打印。在vpp上trace流程只收到了arp-request请求报文。具体原因不明。
TCP协议的最大传输报文尺寸,通过在中间防火墙或者路由器干预端到端的TCP-MSS协商从而达到避免链路数据包分片的目的。
#这里使用iperf3工具来发起tcp链接,-V参数会显示MSS的大小。
[root@ scripts]# iperf3 -c 192.168.100.2 -B 192.168.101.2 -V
iperf 3.1.7
Linux edge_auto_6 3.10.0-957.21.3.el7.x86_64 #1 SMP Tue Jun 18 16:35:19 UTC 2019 x86_64
Control connection MSS 1448
Time: Mon, 29 Mar 2021 12:09:23 GMT
Connecting to host 192.168.100.2, port 5201
Cookie: edge_auto_6.1617019763.876855.5be9c6
TCP MSS: 1448 (default)
[ 4] local 192.168.101.2 port 49041 connected to 192.168.100.2 port 5201
Starting Test: protocol: TCP, 1 streams, 131072 byte blocks, omitting 0 seconds, 10 second test
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 250 MBytes 2.10 Gbits/sec 139 724 KBytes
[ 4] 1.00-2.00 sec 290 MBytes 2.43 Gbits/sec 0 983 KBytes
[ 4] 2.00-3.00 sec 332 MBytes 2.79 Gbits/sec 0 1.19 MBytes
[ 4] 3.00-4.00 sec 334 MBytes 2.80 Gbits/sec 0 1.38 MBytes
[ 4] 4.00-5.00 sec 356 MBytes 2.99 Gbits/sec 0 1.56 MBytes
[ 4] 5.00-6.00 sec 348 MBytes 2.91 Gbits/sec 0 1.71 MBytes
[ 4] 6.00-7.00 sec 324 MBytes 2.72 Gbits/sec 150 723 KBytes
[ 4] 7.00-8.00 sec 335 MBytes 2.81 Gbits/sec 0 1018 KBytes
[ 4] 8.00-9.00 sec 330 MBytes 2.77 Gbits/sec 0 1.21 MBytes
[ 4] 9.00-10.00 sec 349 MBytes 2.93 Gbits/sec 0 1.41 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
Test Complete. Summary Results:
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 3.17 GBytes 2.72 Gbits/sec 289 sender
[ 4] 0.00-10.00 sec 3.17 GBytes 2.72 Gbits/sec receiver
CPU Utilization: local/sender 12.5% (0.1%u/12.4%s), remote/receiver 1.7% (0.0%u/1.7%s)
snd_tcp_congestion cubic
rcv_tcp_congestion cubic
iperf Done.
这里需要注意:显示mss是1448,而不是1460,通过抓包发现tcp带有时间戳的可选项占用12字节导致的。
用于TCP/UDP数据包,通过设置初始数据包的DF=1不断试探最佳MTU值,最终发现端到端的最佳MTU值。
来源于百度百科说明:路径MTU发现(PMTUD),用于确定计算机网络中使用互联网协议(IP)主机间的最大传输单元(MTU)的大小,通常目标是避免IP分片。PMTUD原定应用在IPv4的路由器上,然而所有现代操作系统都是在终端应用它。在IPv6中,这个方法只应用在终端之间的会话。对于IPv4包,路径MTU发现通过在传出包的IP头中设置Don't Fragment (DF)标志位来工作。然后,任何路径上MTU小于数据包的设备都将丢弃它,并返回包含其MTU过大的ICMPv4(类型3、代码4)数据包,从而允许源主机适当地减小其路径MTU。
1、TCP-MSS, PMTU 详解- MTU工具解析与常见问题汇总-上篇 https://blog.51cto.com/gingerbeer/1970602 2、TCP-MSS, PMTU 详解- MTU工具解析与常见问题汇总-下篇 https://blog.51cto.com/gingerbeer/1976737 3、一次负载均衡的排障: PMTU https://blog.51cto.com/virtualadc/660901 4、TCPMSS配置过大导致上网慢 https://support.huawei.com/enterprise/zh/knowledge/EKB1000052671 5、TCP选项之MSS (通过内核源码分析mss设置大小及设置来源) https://blog.csdn.net/xiaoyu_750516366/article/details/85316123 6、TCP的分段和IP的分片&MTU和MSS之间的关系 https://blog.csdn.net/h2604396739/article/details/85267374
本文分享自 DPDK VPP源码分析 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!