首先介绍一些背景知识,TCP有一个称为最大分段大小(MSS)的概念。这是TCP协议栈能够接受的最大数据分段。在建立连接时,该值会通过SYN分段向远程对等方进行通告。下面的数据包解码展示了包含TCP MSS选项的SYN分段。 所有TCP选项均采用相同格式:1字节用于标识选项号(此处为2),1字节用于标记选项总长度(4),最后1字节存储选项值(此处为十六进制5b4或十进制1460)。
packet_monitor -interface #sdlmux.m16.11-3 -hex_dump -numeric -time_stamp -verbo +se -pkt_hdr -filter -host 10.64.77.50 dir icmp type + tcp hh:mm:ss.ttt dir len proto source destination src port ds +t port type 10:11:56.751 Xmit Ether Dst 00:23:54:52:18:6e Src 00:00:a8:43:52:22 Type 0800 +(IP) IP Ver/HL 45, ToS 0, Len 2c, ID be0b, Flg/Frg 0, TTL 3c, Prtl 6 Cksum dcdd, Src a404d80, Dst a404d32 TCP from 10.64.77.128.55911 to 10.64.77.50.telnet seq 1305537174, ack n.a., window 8192, 4 data bytes, flags Syn. X/Off 06, Flags 02, Cksum 815d, Urg-> 0000 offset 0 . . . 4 . . . 8 . . . C . . . 0...4...8...C... 0 2 4 5 b4 <<<4
对于连接本地网络主机的通信,STCP采用1460字节的值。加上所有协议开销后,最终形成1518字节的以太网帧——这是以太网帧的最大尺寸。对于连接非本地网段主机的通信,STCP则使用基于min_mss参数计算得出的值。 采用默认 min_mss 值将产生 536 的 MSS 值。该数值是所有基于 IP 的网络设备(如路由器)必须能够不进行 IP 分片转发的最小数据包尺寸。确立 536 为最小值的规范可追溯至 1983 年发布的 RFC 879 标准——《TCP 最大分段长度及相关主题》。
如今,您的所有路由器很可能都能处理更大的数据包。因此,您可以将STCP最小值从536提升至更大数值。关键问题在于提升幅度应为多少。设置过大值的风险在于数据包分片。最糟糕但最易诊断的情况是:路由器会选择丢弃TCP分段而非进行分片处理。此时虽能建立连接,但在传输数据时连接将失败。 发送主机的跟踪记录将显示:大段TCP分段被多次重传直至连接超时。记录中可能还包含丢弃分段的路由器发出的ICMP目标不可达消息。若路由器选择分片处理,其分片过程优先级通常较低,反而可能导致吞吐量下降。此外,分片数量越多,因数据损坏或网络拥塞导致分段丢失的概率就越高。 最简便的验证方法是在模块上运行packet_monitor跟踪。若接收到分片状态的TCP分段,则可确认发生分片处理。
以下三个以太网帧代表一个TCP分段被分割为三部分。可通过Flg/Frg值为2000判断首个帧为分片:数字2表示"更多分片"位已设置,000为分片偏移量——此处0表示该帧为首个分片。数据包监视器实际将后续两个帧标记为分片。 帧2的Flg/Frg值为2048,其中2再次表示"更多分片"位已设置,48则是原始IP数据报中数据的偏移量(以8字节为单位)。第三帧的Flg/Frag值仅为90(更准确地说是0090)。由于"更多分片"位为0,可确定此为最后一个分片。 所有这些分段都属于同一数据包,因为它们都具有相同的IP标识符值2e87。第一个分段中的数据长度指示了应设置的最大分段大小(MSS)值,本例中为556。
15:52:27.081 Rcvd Ether Dst 00:00:a8:43:52:22 Src 00:12:3f:82:57:10 Type 0800 +(IP) IP Ver/HL 45, ToS 8, Len 254, ID 2e87, Flg/Frg 2000, TTL 3f, Prtl 6 Cksum 1422, Src c0a86432, Dst a404d80 TCP from 192.168.100.50.32781 to 10.64.77.128.ftp-data seq 568258166, ack 840605671, window 5440, 556 data bytes, flags Ack. X/Off 05, Flags 10, Cksum d149, Urg-> 0000 offset 0 . . . 4 . . . 8 . . . C . . . 0…4… 8…C… 0 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 * 5678901234567890 10 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 * 1234567890123456 20 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 * 7890123456789012 30 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 * 3456789012345678 40 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 * 9012345678901234 50 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 * 5678901234567890 60 d a 31 32 33 34 35 36 37 38 39 30 31 32 33 34 * <<12345678901234 70 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 * 5678901234567890
15:52:33.793 Rcvd Ether Dst 00:00:a8:43:52:22 Src 00:12:3f:82:57:10 Type 0800 +(IP) IP Ver/HL 45, ToS 8, Len 254, ID 2e87, Flg/Frg 2048, TTL 3f, Prtl 6 Cksum 13da, Src c0a86432, Dst a404d80 TCP from 192.168.100.50. to 10.64.77.128. *fragments*, 576 bytes data offset 0 . . . 4 . . . 8 . . . C . . . 0…4… 8…C… 0 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 * 1234567890123456 10 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 * 7890123456789012 20 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 * 3456789012345678 30 39 30 d a 31 32 33 34 35 36 37 38 39 30 31 32 * 90<<123456789012 40 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 * 3456789012345678 50 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 * 9012345678901234 60 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 * 5678901234567890 70 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 * 1234567890123456
15:52:33.793 Rcvd Ether Dst 00:00:a8:43:52:22 Src 00:12:3f:82:57:10 Type 0800 +(IP) IP Ver/HL 45, ToS 8, Len f8, ID 2e87, Flg/Frg 90, TTL 3f, Prtl 6 Cksum 34ee, Src c0a86432, Dst a404d80 TCP from 192.168.100.50. to 10.64.77.128. *fragments., 228 bytes data offset 0 . . . 4 . . . 8 . . . C . . . 0…4… 8…C… 0 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 * 5678901234567890 10 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 * 1234567890123456 20 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 * 7890123456789012 30 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 * 3456789012345678 40 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 * 9012345678901234 50 35 36 37 38 39 30 d a 31 32 33 34 35 36 37 38 * 567890<<12345678 60 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 * 9012345678901234 70 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 * 5678901234567890
增加MSS值的问题在于,它会同时提升所有TCP连接的MSS值。你无法仅针对单个或少数目标地址进行调整。因此需要谨慎测试此变更,以评估其对所有连接的影响。
您可以通过以下两个命令查看当前MSS值并进行修改:
analyze_system -request_line 'list_stcp_params min_mss' -quit
OpenVOS Release 17.0.1as, analyze_system Release 17.0.1as
Current process is 357, ptep 8FA86000, Noah_Davids.SysAdmin
maximum tcp segment size [500-1480] (min_mss) 556
ready 10:52:07
analyze_system -request_line 'set_stcp_param min_mss 1480' -quit
OpenVOS Release 17.0.1as, analyze_system Release 17.0.1as
Current process is 357, ptep 8FA86000, Noah_Davids.SysAdmin
Changing maximum tcp segment size (min_mss)
from 556 to 1480
ready 10:52:24
参数名称 min_mss 暗示其值为 MSS 值,但实际值为 MSS 值加上 20 字节的 TCP 头长度。对于上述示例,应将 min_mss 值设置为 556+20 或 576。
那么增加MSS值能带来多大提升?由于VPN连接普遍存在额外开销字节,我不建议设置最大值1480(实际TCP MSS为1460)。 建议采用稍小的数值,例如1220字节(实际MSS为1200)。假设发送10兆字节数据时采用536字节分段,将需要18657个帧,总字节数(含开销)为 (8字节以太网前导码+14字节以太网头+20字节IP头+20字节TCP头+4字节以太网尾码+12字节有效以太网帧间间隔)为11,455,246字节。 若采用1200字节分段,则需8334个帧,总字节数为10,650,052,减少约9%。但需注意:MSS值仅是声明可接收的最大分段,发送主机实际无需发送如此大的分段。 但假设发送方确实发送了最大分段且不存在其他瓶颈,此时吞吐量将提升9%。

在UDP方面我们能做些什么?
UDP没有最大分段大小的概念,因此没有可调整该参数的设置。