前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >learning:tcp mss clamp

learning:tcp mss clamp

作者头像
dpdk-vpp源码解读
发布2023-03-07 17:26:50
1.7K1
发布2023-03-07 17:26:50
举报
文章被收录于专栏:DPDK VPP源码分析

本文主要讲解网络通信中MTU,IP MTU和MSS的概念以及它们之间的关系。这三个概念对于网络通信来说非常重要,在实际的网络场景中常常很多网页打不开等问题,往往罪魁祸首都是这几个参数没配置正确导致的。VPP在21.06提交了一个tcp mss clamp的patch,本文主要来学习一下配置及使用。

MTU、MSS简介

在以太网链路上的数据包称作以太帧。以太帧起始部分由前导码和帧开始符组成。后面紧跟着一个以太网报头,以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

1、MTU

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协议会根据这个值来决定是否把上层传下来的数据进行分片。

2、IP MTU

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.

3、MSS

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-clamp测试

TCP MSS clamping功能以插件的形式合入到vpp分支21.06-rc0。具体合入记录如下:

代码语言:javascript
复制
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提交的,最近才合入主线分支。

1、测试组网
2、相关配置
代码语言:javascript
复制
#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
3、测试结果:

linux下安装iperf3进行测试mss数据:

代码语言:javascript
复制
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可选项的影响。

代码语言:javascript
复制
[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报文待扩展字段都会导致实际发包报文长度减少。

4、华为设备的实现:

华为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的值。

代码语言:javascript
复制
# 在HTS实例视图下配置TCP报文MSS值为1000。
<HUAWEI> system-view
[~HUAWEI] hts instance instance1 id 2
[*HUAWEI-hts-instance-instance1] tcp-mss 1000
5、存在问题:

1、MSS修改不支持带有扩展头的ipv6报文。代码中在偏移tcp头时,未考虑此场景。 2、MSS配置支持单方向设置,但是只能生效一个方向,需要注意。

核心代码

代码语言:javascript
复制
/*
 * 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工具解析与常见问题汇总-下篇》的方法进行验证MTU大小。

1、手工测试

通过手工ICMPPing测试发现最优MTU值。利用ip报文头flag字段DF标识位,设置为不能分片,

代码语言:javascript
复制
[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请求报文。具体原因不明。

2、利用tcp报文mss标识测试。

TCP协议的最大传输报文尺寸,通过在中间防火墙或者路由器干预端到端的TCP-MSS协商从而达到避免链路数据包分片的目的。

代码语言:javascript
复制
#这里使用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字节导致的。

3、Path MTU Discovery(链路MTU自动发现协议)

用于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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DPDK VPP源码分析 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MTU、MSS简介
    • 1、MTU
      • 2、IP MTU
        • 3、MSS
        • Tcp-mss-clamp测试
          • 1、测试组网
            • 2、相关配置
              • 3、测试结果:
                • 4、华为设备的实现:
                  • 5、存在问题:
                  • 核心代码
                  • MTU工具测试
                    • 1、手工测试
                      • 2、利用tcp报文mss标识测试。
                        • 3、Path MTU Discovery(链路MTU自动发现协议)
                        • 巨人的肩膀
                        相关产品与服务
                        负载均衡
                        负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档