1. 最小帧长度:CSMA/CD碰撞检测的“自查窗口”
1.1 碰撞检测为什么要“边发边听”
很多刚接触计算机网络的人第一次看到“以太网最小帧长度是64字节”时,脑子里多半有个疑问:帧不就是一包数据吗,为什么还要规定最短长度?难道短一点的数据就不能发了?
要搞懂这个问题,得先回到传统以太网最本质的机制:CSMA/CD,也就是载波侦听多路访问/碰撞检测。早年以太网是共享介质的,一根同轴电缆上挂着好多台机器,谁想发数据谁就发,没有中央调度。这就像一条单车道,所有车都能走,但两个人同时上路就会撞车。
CSMA/CD的流程是:先听信道,没人发就发;发的时候同时监听信道上有没有其他信号;一旦发现有碰撞,立刻停止发送,然后退避一段随机时间再重试。这中间有个关键假设:发送方必须在“还在发送的过程中”就能发现碰撞。如果一帧数据已经完整发完了才听到碰撞,发送方根本不知道自己的帧废了,还会以为发送成功。
但碰撞信号从碰撞点传到发送方是需要时间的。电磁波在电缆里的传播速度大约是200000公里/秒,在一根几百米长的线上,信号一来一回的延迟虽然只有几微秒,但在高速网络里,这几微秒换算成“正在发送的比特数”,就不是一个小数目了。
核心逻辑是:帧的发送时长必须大于信号在网络上往返一趟的最坏情况时间。换句话说,发送方得保证在整帧发完之前,碰撞信号能传回自己耳朵里。如果帧太短,发送方“话还没说完”就已经停了,后面就算撞了车也听不见。
1.2 64字节是怎么算出来的
这个“往返最坏情况时间”,在以太网标准里被定义为时槽(Slot Time),取的是512比特时间,也就是在10Mbps速率下发送512个比特所需的时间:512/10000000秒,也就是51.2微秒。
为什么恰好是51.2微秒?这是因为IEEE 802.3在定义10BASE5(粗缆以太网)时,规定网络最大跨度为2500米,中间最多可以串4个中继器。信号在电缆中以0.77倍光速传播,单向传播时延大约是10.85微秒,再算上中继器、收发器引入的额外延迟,最极端情况下往返时间约49.6微秒。标准委员会取了一个有裕量的整数值:51.2微秒,并且直接规定最小帧长 = 数据速率 × 时槽时间。
10Mbps × 51.2微秒 = 512比特 = 64字节。
如果你在100Mbps快速以太网里再算一次,会发现一个有趣的现象:100Mbps × 51.2微秒 = 5120比特,也就是640字节,但标准里100BASE-T的最小帧长仍然是64字节。为什么矛盾?
因为100BASE-T的网络直径被大幅缩短了,从2500米压缩到了约200米。距离短了,往返时延自然就小了。实际上,100BASE-T的时槽时间仍然是512比特时间,也就是5.12微秒,只是它对应的“物理最大距离”变小了。所以说,最小帧长不是只跟速率有关,还要看介质和拓扑允许的最大传播时延。
1.3 千兆以太网为什么要“补齐”帧长
到了千兆以太网,问题更麻烦了。1Gbps速率下,64字节帧的发送时间只有0.512微秒。要是网络距离再按100BASE-T的200米算,往返时延就有2微秒左右,远远超过0.512微秒。半双工模式下的CSMA/CD直接失效。
千兆以太网处理方法是加了一个载波扩展机制:帧内容不够长没关系,物理层会在帧后面补上一串「扩展符号」,强制让整个发送时长远大于往返时延。所以在半双工千兆模式下,最小发送长度相当于512字节,但真正的以太网帧数据部分还是可以短到64字节,多余的扩展符号不算在CRC校验里,接收方会直接丢弃。
全双工模式出现后,链路两端可以同时收发,不再需要碰撞检测,按理说最小帧长可以直接取消。但标准为了兼容性和统一处理,还是在各种上层协议、网卡驱动和交换机逻辑里保留了64字节的约束。这就是为什么你抓包的时候,几乎永远不会看到一个小于64字节的有效以太网帧。
1.4 小于64字节的帧:runt帧是怎么来的
比64字节短的以太网帧,有个专门的称呼叫runt帧,中文叫“残帧”或“短帧”。这种帧大多出现在碰撞发生后——两个站点同时开发,撞车后信号被截断,产生一个残缺的半截帧;也可能是硬件故障、网卡驱动Bug、线路质量差导致数据被破坏。
runt帧在网络里其实会被接收方直接丢弃,因为网卡判断帧长小于64字节后根本不会把它交给协议栈。但如果你在网络里用抓包工具收到大量runt帧,这通常不是“流量异常”,而是在告诉你物理层出问题了,比如双绞线老化、接口接触不良、网卡端口故障,或者两台设备的协商模式不匹配。
我处理过一个典型案例:某个产线上的一台工控机对外通信时好时坏,排查半天找不到原因,最后在交换机端口上抓包,发现大量30多字节的runt帧。顺着端口查到配线间,发现那根跳线的水晶头有一芯接触不良,用户的流量偶尔能用,但只要一有大流量或者震动,就会有碰撞和信号衰减。换了一根跳线后,runt帧立刻归零,问题消失。
2. 最大帧长度:公平性、缓冲区与效率的平衡
2.1 一个站点不能永远占着信道
如果说最小帧长限制是为了“保护发送方能听到碰撞”,那最大帧长限制又是为了什么?
想象一下,如果一个站点可以一帧塞进10MB数据,发送这一帧需要多久?在10Mbps的共享以太网里,发10MB要8秒钟。这8秒钟内,其他所有站点都在等——信道是共享的,你占着我就不能发。更糟糕的是,CSMA/CD的后退机制是随机的,一个站点发完一帧后,理论上和别的站点是“平等竞争”,但如果它每一帧都特别长,其他站点的等待时间就会被无限拉长,公平性荡然无存。
所以,最大帧长本质上是给“单次信道占用时间”设了一个上限。
那这个上限为什么是1518字节,而不是5KB或者100KB?这就要从历史说起了。DIX以太网规范(由DEC、Intel、Xerox三家制定)当年在设计时就定下了1500字节的最大载荷。802.3后来把这个值原封不动地收进了标准。1500这个数字的由来没有特别神秘的高深理论,更多是当时工程上的权衡:网络接口卡上的内存和处理器性能有限,缓冲区按固定大小分配,1500字节的载荷加上14字节的头部和4字节的CRC校验,总共1518字节,刚好能在一页/几页内存里放下,收发电路也容易设计。
2.2 1518字节的构成和演进来的
我们平时说的以太网帧长度1518字节,是一个很经典的结构:
| 组成部分 | 长度(字节) | 说明 |
|---|---|---|
| 目的MAC地址 | 6 | 接收方地址 |
| 源MAC地址 | 6 | 发送方地址 |
| 类型/长度字段 | 2 | 标识上层协议类型(如0x0800是IPv4,0x86DD是IPv6) |
| 载荷(Payload) | 46 ~ 1500 | 上层数据,最小46字节补齐帧长 |
| 帧校验序列(FCS/CRC) | 4 | 循环冗余校验,检测传输错误 |
注意,前面还有一个8字节的前导码(Preamble + SFD),用于同步接收时钟,但通常不计算在“帧长度”里。大家口语里说的“标准以太网帧最大1518字节”,是指从目的MAC地址开始到FCS结束的部分。
后来为了支持VLAN标签,802.3ac把最大帧长扩展到了1522字节,多了4字节的802.1Q tag。再后来,为了在网络上承载更多协议头开销,一些厂商支持巨型帧(Jumbo Frame),最大可以到9000字节甚至更大。但这属于非标准实现,必须在整条链路上的所有设备都统一配置,否则就会出问题。
2.3 最大帧长与误码率的博弈
还有一个经常被忽视的原因:帧越长,误码后重传的代价越大。
早期以太网跑在同轴电缆上,线缆质量和接口工艺都不如现在,误码率并不是可以忽略不计的。CRC32只能检错,不能纠错,一旦CRC校验失败,整帧数据直接被丢弃,发送方依靠上层协议(比如TCP超时重传或以太网层的重试)来恢复。
如果一帧是1500字节,出错后重传1500字节;如果一帧是100KB,出错后重传100KB。信道的误码率固定时,帧越长,帧损坏的概率越高,浪费的带宽也就越大。也就是说,最大帧长的选择还隐含了一个“传输效率”的权衡:不能只看数据载荷部分的吞吐,更要看出现坏帧后的代价。
1500字节这个值,放在今天来看其实已经偏保守了,这也是有人一直在推动巨型帧的原因。现代光纤链路误码率极低,很多机房内部传输大量数据时都倾向用9000字节的巨型帧来减少每帧的头部开销和CPU中断次数。但标准以太网的1518字节仍然是最稳妥的“默认配置”,因为所有设备都兼容。
2.4 从1500字节MTU到TCP的1460字节MSS
最大帧长在互联网里还有一套连环影响,这也是很多刚接触网络抓包的人会迷糊的地方。以太网最大载荷1500字节,这个值就是通常所说的MTU(最大传输单元)。
当你在TCP/IP网络里传数据时,IP层会把数据切成不超过MTU的 IP分片(或者由TCP层直接控制不分片),IP头通常是20字节,TCP头通常也是20字节,所以TCP能放进去的最大数据段长度是1500 - 20 - 20 =1460字节,这就是TCP MSS的默认来源。
你在Wireshark里看到一个普通的TCP数据包长度是1514字节(14字节以太网头 + 20字节IP头 + 20字节TCP头 + 1460字节数据),一算就完全对上了。如果应用层一次性要发10KB数据,TCP/IP协议栈会把它切成多个段,每一段都要装进一个独立的以太网帧里。换句话说,以太网的1518字节帧长限制,是互联网上几乎所有传输层协议做“分块”设计的最底层约束之一。
3. 帧长度限制在真实网络中的样子
3.1 网卡和驱动是如何处理长短帧的
帧长限制不是只存在于理论标准里,它在每一块网卡的硬件逻辑里都是实打实实现的。现代网卡的MAC控制器里,会有一个寄存器专门配置接收帧的长度过滤阈值,通常默认值就是64到1518字节。
收到一个帧时,网卡会先做几个检查:帧长度是否小于64?如果小于64,直接在硬件层面丢弃,不往驱动或者协议栈上送。FCS是否正确?不正确也丢弃。
这带来一个非常实用的排障技巧:当你怀疑网络里有runt帧时,光看应用层统计可能看不到,一定要看网卡或者交换机的底层计数。
在Linux上,可以通过ethtool -S查看网卡统计:
ethool -S eth0 | grep -E "rx_length_errors|rx_crc_errors|rx_fifo_errors|runt|short"如果rx_length_errors或runt计数持续增长,说明线路上确实有短帧进来。在思科交换机上,对应的命令是show interface输出中的runts和input errors。很多网络工程师习惯只看接口状态和流量速率,忽略了这种底层的错误计数,结果问题持续很久都定位不到。
3.2 抓包实测:如何识别帧长异常
用Wireshark抓包时,以太网帧长度可以直接在数据包列表的Length列看到。正常以太网帧范围应该在64到1518字节之间(不含前导码)。如果你抓到小于64字节的帧,Wireshark通常会标成红色或者显示为malformed,Proto列可能显示成“bad length”之类。
有个容易被忽略的细节:Wireshark默认统计的帧长是包含帧头和FCS的。也就是说,一个标准的IPv4 TCP ACK包(只有40字节的IP头+TCP头),算上14字节以太网头和4字节FCS,实际抓包显示长度是58字节。但以太网要求最小64字节,这个包不管是抓包软件显示的58还是物理链路里的64,网卡和交换机都已经通过填充(Padding)保证整帧长度不低于64字节。协议栈里,TCP ACK这种小包会在IP层下面被补齐到46字节的载荷,所以帧长正好是64字节。
你在抓包软件里看到几十字节的TCP包,并不代表物理线路上也是那么短——真实线上跑的帧有可能是带填充的64字节。如果抓包软件显示一个TCP数据包总长只有50多字节,那多半是抓包点的问题(比如驱动已经提前剥离了填充位),不影响正常传输。
3.3 巨型帧(Jumbo Frame)怎么配、怎么验
巨型帧是现代以太网里最常被问到“能不能不要用”的技术。它把允许的最大帧长从1518字节扩展到9000字节(有些交换机支持到9216字节)。配置巨型帧的核心是整条链路全链路一致:源端网卡、所有经过的交换机端口、目的端网卡,都得允许同一个最大帧长,缺一个都不行。
我建议的配置流程是:
- 先确认链路中各设备的MTU支持能力。Linux网卡可以用
ip link show查看MTU,交换机通常在接口配置命令里设置mtu或jumbo。 - 调整两端网卡的MTU,比如设置为9000。
- 逐跳确认交换机端口的MTU也一致。
- 用不允许分片的大ping测试。
测试命令:
# -M do 表示不允许分片,-s 设置载荷大小 # ICMP头8字节,IP头20字节,要测9000的帧长,ICMP载荷应该是 9000 - 14 - 20 - 8 = 8958 ping -M do -s 8972 192.168.1.1如果你设置的-s超过链路MTU且不允许分片,会直接在终端报错“Local: Operation not permitted”或者收到peer显示的Destination Unreachable: Fragmentation needed。整条链路都通了,这个测试才能全绿。
很多设备上默认是关闭巨型帧的。遇到“千兆局域网拷贝大文件跑不满”这类问题时,先别急着怀疑硬盘或者网线,用上面这个ping -M do测一遍,很多时候答案就出来了。但注意:巨型帧是典型的“局域网内优化手段”,跨路由或者跨运营商链路时绝对不要用,因为广域网的标准MTU几乎都是1500,你这边发9000字节的帧,路由器要么分片要么直接丢。
3.4 全双工时代,为什么帧长度限制还留在标准里
现在绝大多数以太网都是全双工交换网络,两端独占链路,不再有共享冲突域,CSMA/CD早就退休了。那为什么最小帧长和最大帧长的限制依然被坚守?
原因很实在:标准不是为了一台设备而定的,而是为了整个生态的兼容性。
从帧格式、接收方缓冲设计、协议栈处理逻辑,到交换机转发表的老化机制、从二层到三层设备的共同行为,全部都是基于“帧长在64到1518字节之间”这个假设设计的。取消这个限制,新设备之间倒是可以“商量”出新的长度,但老设备、不支持的设备、混杂模式抓包、防火墙分片处理、深度包检测等全都会乱套。以太网之所以能跑遍全世界,最大的功臣不是它的某个先进特性,而是三十年如一日的向后兼容。
车载以太网里有个很有意思的现象:100BASE-T1和1000BASE-T1的物理层和传统以太网完全不同,用的是单对双绞线和差分信号,但它的二层帧格式、帧长度限制全部沿用了标准以太网。原因就是我们上面说的,上层协议栈和中间设备只认标准的以太网帧,你物理层爱怎么变都行,但二层格式一旦变,整个生态就全得跟着改。这就是“帧长限制”这种看似过时的规定,在现代网络里依然生效的原因。
4. 常见问题与排查技巧实录
4.1 帧长相关的故障速查表
我把这几年实际遇到过的帧长相关问题和排查思路整理成一个速查表,遇到类似情况可以直接对着来:
| 现象 | 可能的根因 | 排查命令/工具 | 解决方向 |
|---|---|---|---|
| 抓包看到大量<64字节帧(runt) | 物理层碰撞、接口松动、线缆损坏 | ethtool -S、交换机接口统计runts | 换线、重新压水晶头、检查协商模式 |
| 大文件传输慢,小包通信正常 | 端到端MTU不一致,大帧被丢弃 | ping -M do -s;traceroute | 统一全链路MTU,关闭/启用巨型帧 |
| CRC错误帧持续增长 | 线缆老化、电磁干扰、接口接触不良 | 交换机接口统计CRC errors | 更换线缆、检查接地、更换接口模块 |
| 交换机端口收到超长帧后丢弃 | 部分设备开了巨型帧而另一部分没开 | show interface counters | 统一所有端口MTU |
| 应用层通信偶尔超时,重传多 | 路径上有设备丢弃超长帧但未通知源端 | Wireshark看TCP重传、ICMP type3 code4 | 调整MTU或者TCP MSS |
4.2 用抓包统计快速定位帧长分布异常
Wireshark里有一个很实用的功能:Statistics → Packet Lengths。它会按帧长区间统计抓到的包数量。正常情况下,网络流量里主要分布在几个区间:
- 64字节附近:纯TCP ACK、HTTP确认等控制帧
- 100到300字节之间:各类协议控制报文、RTP小包等
- 1280到1518字节:持续大数据传输时的满帧
如果你看到帧长区间里出现大量60到70字节的包,而传输速率明显不符合预期,先想是不是小包太多导致CPU中断压力大;如果你看到大量超过1518字节的包,那就说明网络上有人开了巨型帧,要重点确认链路是否全程支持。
另外,在抓包时可以根据帧长写显示过滤表达式。Wireshark里frame.len < 64可以直接过滤出所有runt帧,frame.len > 1518则可以过滤出巨型帧。这两个过滤条件在排障时非常好用,能帮你快速判断链路上的帧长结构是否正常。
4.3 一次真实排障:看起来正常的网络为什么频繁丢包
最后分享一个我印象很深的案例。某个朋友的公司内部迁移了一批服务器,之后频繁在业务高峰期出现丢包和TCP重传。服务器配置没问题,交换机也不报警,运维怀疑是防病毒软件或者防火墙策略拦截,查了一天没结果。
我去帮忙看了下,先在核心交换机上看了几个端口的错误计数,发现runts一直不增长,CRC errors也没有,但giants这个计数器在缓慢增长。这就奇怪了,链路上出现了超长帧?查了一圈,发现新服务器里有一台网卡驱动默认开启了巨型帧,MTU从1500被改成了9000。服务器A和服务器B直连交换机的端口都允许巨型帧,但中间还有一台老的三层交换机,它的接口MTU还是1500。于是服务器发出去的超长帧在经过老交换机时,直接被丢弃,TCP协议栈以为网络拥塞,不断降低发送窗口和重传,表现就是“网络慢、偶发丢包”。
把这几台服务器的MTU统一改回1500,或者把老交换机升级为支持巨型帧并统一配置,问题瞬间消失。
这个案例给我最大的体会是:帧长度相关问题最难的点在于,它在应用层看起来“什么都是正常的”——Ping能通、端口是up、流量也有,但就是吞吐量上不去、时延忽高忽低。只有把排查视野下沉到网卡统计和交换机错误计数器这一层,才能找到真正的Root Cause。
我个人排查网络问题时,习惯第一步先做三件事:先看接口错误计数,再抓包看帧长分布,最后用ping -M do验证端到端MTU。这三板斧下来,绝大多数帧长相关的“疑难杂症”都能有一个明确的方向。毕竟以太网帧长度这个事,看起来是标准文档里两个不起眼的数字,但它牵动着碰撞检测、信道公平、缓冲区设计、协议分片、设备兼容性等一整条链路。搞懂它,再去排网络故障,你会觉得整个二层的运行逻辑都清晰了很多。