暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Wireshark 中 Len 远远大于 MSS,Why ?

4394

问题描述


正常情况下,TCP 传输的报文应该不会超过 MTU 的大小,一般是1500 bytes,但我们通过 tcpdump 抓包出来后,通过 wireshark 查看的话,有些 Len 远远大于了 MTU 值(这里说的不严谨,应该说是每个数据包的Len 不应该大于 MSS),这是为什么呢?难道说,我们的MTU 不是1500,还是?去服务器上面查看下 MTU值 

[root@vm-os-centos7 ~]# netstat -i
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 8844038 0 0 0 156604 0 0 0 BMRU
lo 65536 626 0 0 0 626 0 0 0 LRU
[root@vm-os-centos7 ~]#


发现MTU确实是1500个字节,按理说,抓包工作不会出现大于1500的Len,才符合 TCP 协议规范。如下图,是 Len 远远大于 MSS 的抓包截图。


(图:Len 远远大小 MSS)

原因分析


这是由于服务器网卡开启了 TCP Segment Offload, TSO 选项导致,在支持 TSO 的网卡上,为了降低 CPU 的负载,提高网络的出口带宽,TSO 提供一些较大的缓冲区来缓存 TCP 发送的包,然后由网卡负责把缓存的大包拆分成多个小于 MTU/MSS 的包,简单来说就是,原本由内核处理的拆包,交给了网卡来处理,而我们通过 tcpdump 抓包工具抓取的是从内核到网卡路径上的数据包,所以会存在上述问题,如果在交换机处抓包,那么对应的大小为MSS值或小于 MSS 值。那么什么是 TSO 呢?


Segmentation offloading 技术


说到 TSO 那么就不得不讲下 Segmentation offloading 技术?随着网络带宽的提升,以太网从最开始的 10M 到现在 100G,提升了10000倍,虽然 CPU 这些年,也有很大的发展,但是单核 CPU 的频率并没有太多的提升,有人会说 CPU 核心数增加了很多,但是把一个网络数据流交给多个 CPU 核心去处理本身有一定的挑战,另一方面计算机需要处理的任务也越来越复杂,尤其是引入了虚拟化之后,计算机上不仅跑应用程序,还需要跑容器、虚拟机、CPU 本身的负荷可以就已经很重。由于 TCP 是双向通信的,大约发送或者接收 1 bit/s 的数据需要 1 赫兹的 CPU 处理能力,当发送和接收各 10 Gbit/s (吞吐量就是 20Gbit/s=20GHz)时,大概需要 8 个 2.5 GHz 的 CPU 内核,如果完全由 CPU 来校验、计算、验证、分包、和组包的话,消耗 CPU 还是相当可观的,为了解决问题,越来越多的技术出现来适应技术的变迁,其中网卡就能够支持将某些 Linux 内核协议栈所承担的计算任务,从协议栈 offload (卸载)到物理网卡。


MSS(Maxium Segment Size):MSS 是 TCP 数据段每次能够传输的最大数据分段的长度。为了达到最佳的传输效能,TCP 协议在建立连接的时候通常要协商双方的 MSS 值,这个值 TCP 协议在实现的时候往往用 MTU 值代替( MSS = MTU - IP 数据包包头大小20Bytes - TCP 数据段的包头大小20Bytes),所以在默认以太网 MTU 为 1500 bytes 时,MSS为 1460。


TCP 分段:当应用程序发给 TCP 的 message 的长度超过 MSS 时,TCP 会对它按照 MSS 的大小将其分为多个小的 packet,并且在每个 packet 上添加 TCP Header 成为一个 TCP 段(segement)。


TSO 是一种利用网卡分割大数据包,减小 CPU 负荷的一种技术,也被叫做 LSO (Large segment offload) ,如果数据包的类型只能是 TCP,则被称之为 TSO,如果硬件支持 TSO 功能的话,也需要同时支持硬件的 TCP 校验计算和分散 - 聚集 (Scatter Gather) 功能。


TSO 就是将由 TCP 协议栈所做的 TCP 分段交给具有这种能力的物理网卡去做,因此网卡具有如下特性:

 1. 物理网卡支持;

 2. Linux 网卡驱动支持(ethtool -K ethX tso on 命令打开网卡和驱动对 TSO 的支持);

 3. 需要 Net:TCP checksum offloading and Net:Scatter Gather 支持。


TSO 就是将 TCP Segmentation 的工作,卸载(offload)到网卡来完成。有了TSO,操作系统只需要传给硬件网卡一个大的 TCP 数据(当然是包在 Ethernet Header和IP Header内,且不超过64K )。网卡会代替 TCP/IP 协议栈完成 TCP Segmentation。这样,就消除了 TCP Segmentation 带来的 CPU 负担。支持TSO的网卡,仍然会按照TCP/IP协议将网络数据包生成好并发送出去,对于外界系统来说,感受不到TSO的存在,下图是使用 TSO 和不使用 TSO 的情形的对比。


(图:使用TSO与不使用TSO对比图 来源网络)


从上图可以看到 TSO 带来的提升是明显的,一方面,更多的 CPU 被释放出来完成别的工作,另一方面,网络吞吐量(throughput)不受 CPU 负荷的影响,如果没有 TSO,当 CPU 性能不好或者 CPU 本身负荷已经较大时,CPU 将来不及处理足够的网络数据,会导致网络吞吐量下降,延时上升。


其中大部分的优化是将本来由内核做的操作,交给了网卡,例如 TSO、UFO 和 GSO 是对应网络发送,在接收方向上对应的是 LRO、GRO ,具体含义的话还是自己看吧。

offload传输段还是接收段针对的协议Offloading的位置 网卡/linux内核支持情况备注
TSO(tcp-segmentation-offload)传输段TCPNICLinux 内核从 2.5.33 引入 (2002)网卡普遍支持TSO,是一种利用网卡对TCP数据包分片,减轻CPU负荷的一种技术,有时也被叫做 LSO (Large segment offload) ,TSO是针对TCP的,UFO是针对UDP的。如果硬件支持 TSO功能,同时也需要硬件支持的TCP校验计算和分散/聚集 (Scatter Gather) 功能。命令:ethtool -K eth0 tso on|off

在不支持TSO的网卡上,TCP层向IP层发送数据会考虑mss,使得TCP向下发送的数据可以包含在一个IP分组中而不会造成分片, mss是在TCP初始建立连接时由网卡MTU确定并和对端协商的,所以在一个MTU=1500的网卡上,TCP向下发送的数据不会大于min(mss_local, mss_remote)-ip头-tcp头。
网卡支持TSO时,TCP层会逐渐增大mss(总是整数倍数增加),当TCP层向下发送大块数据时,仅仅计算TCP头,网卡接到到了IP层传下的大数据包后自己重新分成若干个IP数据包,添加IP头,复制TCP头并且重新计算校验和等相关数据,这样就把一部分CPU相关的处理工作转移到由网卡来处理。
UFO(udp-fragmentation-offload)传输段UDPNIClinux 2.6.15 引入 (2006)网卡普遍不支持UFO,是网卡对udp提供的类似TSO的技术。 命令:ethtool -K eth0 ufo on | off
GSO(generic-segmentation-offload)传输段TCP/UDPNIC或者 离开IP 协议栈进入网卡驱动之前GSO/TCP: Linux 2.6.18 中引入(2006)
GSO/UDP: linux 3.16 (2014)
GSO,它比TSO更通用,基本思想就是尽可能的推迟数据分片直至发送到网卡驱动之前,此时会检查网卡是否支持分片功能(如TSO、UFO), 如果支持直接发送到网卡,如果不支持就进行分片后再发往网卡。这样大数据包只需走一次协议栈,而不是被分割成几个数据包分别走,这就提高了效率。命令:ethtool -K eth0 gso on | off
LRO(large-receive-offload)接收段TCPNICLinux 内核 2.6.24 引入(2008)网卡普遍支持LRO,通过将接收到的多个TCP数据聚合成一个大的数据包,然后传递给网络协议栈处理,以减少上层协议栈处理 开销,提高系统接收TCP数据包的能力。
GRO(generic-receive-offload)接收段TCPNIC或者离开网卡驱动进入IP协议栈之前Linux 内核 2.6.18 引入(2006)网卡普遍支持GRO,基本思想跟LRO类似,克服了LRO的一些缺点,更通用。后续的驱动都使用GRO的接口,而不是LRO。


实验验证 TSO


关闭发送方的 TSO 功能,如下所示:

[root@vm-os-centos7 ~]# ethtool -K eth0 tso off
[root@vm-os-centos7 ~]#


通过 ethtool -k 可以查看很多网卡的特性,这里我们查看下,上面设置是否生效;

[root@vm-os-centos7 ~]# ethtool -k eth0|grep tcp-segmentation-offload:
tcp-segmentation-offload: off
[root@vm-os-centos7 ~]#


上面设置已经生效,我们再进行实验,抓包分析如下:

(图Len 大小约等于MSS)


再次抓包后,发现Len没有大于MSS的了,这里为1488,之所以是1488bytes,是因为 Len = 1500(MTU) - 20(IP Header)- 20(TCP Header) -12(TCP 选项) = 1448 bytes。



总结


本文件从原理实验的角度分析并验证了网卡的 TSO 的功能 ,并给出了其它 Segmentation offloading 技术在网卡上面的常用参数设置,例如 TSO、UFO 和 GSO 他们对应是网络发送路径上的优化参数,而在接收方向上对应的是 LRO、GRO ,下图来源于网络。

您的关注是我写作的动力




基础小知识


tcpdump 使用小结

Centos 7.6 内核升级

Centos 7 升级 Python 与 Yum 修改

Centos 7 安装 Redis 5.0.8 单实例

CentOS 7 下 yum 安装 MySQL 5.7 最简教程

kubernetes中部署 nacos,使用外部MySQL存储

你真的了解客户端请求如何到达服务器端的吗

hping 命令使用小结

Linux 网卡 bonding 小知识


专辑分享


kubeadm使用外部etcd部署kubernetes v1.17.3 高可用集群

第一篇  使用 Prometheus 监控 Kubernetes 集群理论篇

文章转载自Linux点滴运维实践,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论