
干了这么多年网络运维和开发我发现一个很有意思的现象很多人能背出TCP/IP五层模型能把三次握手说得头头是道但真遇到问题——比如“交换机端口亮着灯ping就是不通”、“两台机器直连明明都是千兆传文件却只有百兆速度”一下子就抓瞎了。以太网是我们天天打交道的网络底座它的工作原理尤其是链路层那几个关键机制才是排障时真正救命的细节。这篇“以太网及网络工作原理二”就顺着第一篇的基础往下走把以太网帧结构、交换机的转发逻辑、一次完整通信的旅程都拆开揉碎讲清楚最后附上一些我实际踩过的坑和排查方法。不管是做开发的、做运维的还是刚准备网络方向面试的朋友读完后你至少能搞清楚数据在网线里跑的时候到底是以什么形态存在的每个环节又是谁在做决定。我习惯把整条网络通信链路分成两个视角来看一个视角是“数据面”即数据从网卡出去之后变成什么样的比特流经过哪个设备怎么被转交到下一跳另一个视角是“控制面”即交换机、路由器怎么决定“下一步把数据交给谁”。这两个视角在以太网里其实都集中在链路层交换上所以把握好帧格式和MAC地址表等于抓住了链路层的两只手。2. 以太网帧数据在网线上跑起来时的“最小单位”2.1 帧结构一个“标准快递包裹”的八个栏目很多人以为数据包到了链路层就是“加了一个MAC头”这个事情对了一半。真正发到网线上的以太网帧远比想象中要啰嗦。我直接以最常见的Ethernet II帧为例给你拆一下它在网线上实际存在的样子字段长度字节作用前导码7收发双方同步时钟让对方知道“数据来了”帧起始定界符1标识真正的帧内容从这里开始目的MAC地址6收件人地址接收网卡的唯一匹配依据源MAC地址6发件人地址交换机学习MAC表的数据来源类型/长度2告诉上层这个包里装的是什么协议数据载荷46–1500上层传下来的IP包或其他协议数据FCS校验4循环冗余校验用来检查数据在传输过程中有没有被破坏前导码和SFD在抓包软件里通常不显示因为它们属于物理层同步过程网卡已经处理掉了。但你在分析线路质量、看光电转换器状态时前导码的抖动情况往往能反映链路的稳定性这是很多朋友容易忽略的地方。把这个帧当成一份快递就好理解了目的MAC是“收件人门牌号”源MAC是“寄件人门牌号”类型字段是你选择的“快递服务类型”比如这个包裹是衣服还是文件数据载荷就是包裹里真正的商品FCS则像快递公司的“验视单”收货时如果单子和实物对不上盒子就有问题。有个细节值得多说一句类型字段如果小于等于15000x05DC那它表示的是“长度”这是IEEE 802.3格式的用法如果大于等于15360x0600则表示“上层协议类型”。常见的类型值包括0x0800代表IPv4、0x0806代表ARP、0x86DD代表IPv6。抓包时候你看到Type字段是0x0800那基本可以确定这个是发往IP协议栈的数据不需要再猜。2.2 为什么最小帧长是64字节一段容易被忽略的历史遗留很多搞开发的朋友第一次看到“数据载荷最短46字节、整个帧最小64字节”这个规定时第一反应是“浪费空间”。如果你传输的数据只有一个字节光填满最小载荷就要补45个字节的填充。这个规则确实让人难受但它背后是半双工以太网的碰撞检测机制。早期的以太网用同轴电缆所有设备共享同一条物理链路发数据之前必须“先听再说”如果两个设备同时发就会产生冲突。为了避免冲突发生后才发完一帧的尴尬网络协议设计了一个约束一个站必须在发完一帧之前就能检测到最远端发生了碰撞并停下来重传。这要求最长距离内的往返传播时间必须小于发完一帧的时间。拿经典的10Mbps以太网来算一下假设最大冲突域直径约2500米信号在电缆里的传播速度大约是真空中光速的2/3也就是约200,000公里/秒那最远两端往返一次大约需要25微秒。在10Mbps速率下要保证一个站点在发送过程中能听到碰撞它至少要持续发送25微秒也就是250比特约等于31.25字节。再加上一些余量最后就以64字节作为最小帧长。后来100Mbps、1000Mbps变成主流后网络直径变小但64字节的帧长规定一直保留了下来。说实话现在全网都是全双工交换机碰撞机制已经基本退场但这个64字节的约束还深深嵌在芯片设计里理解它对于你阅读老一些的网络文档、理解以太网控制器参数还是有帮助的。2.3 FCS校验链路层是怎么发现“快递被挤变形”的FCS字段用CRC32算法对帧里的目的MAC、源MAC、类型、数据载荷整体计算一个4字节的校验值。网卡收到一个帧后会重新算一遍如果和帧尾带的FCS不一致这个帧会被直接丢弃。我为什么单独挑FCS来讲因为在抓包、排障时很多人看到协议分析器里报“FCS错误”就以为抓包软件算错了其实不然。正常的成熟抓包工具比如常见的Wireshark、tcpdump默认会开启网卡驱动的校验和卸载功能也就是网卡计算校验和而不是由CPU计算并塞进帧里。当你在一台正常的PC上抓包FCS显示错误的帧几乎可以不看因为那是网卡自己的收包流程问题但你在交换机端口上看到大量CRC错误计数持续增加时这就必须当成物理层故障来处理了。CRC错误连续增加通常对应这几种原因网线太长超出规范、网线受到强电磁干扰、水晶头氧化或卡扣松动、光模块收发功率异常。如果CRC错误只在特定一段时间出现还有个很容易被忽略的原因——网线两端协商出来的速率不一致导致一边在按千兆速率发送一边在按百兆速率接收帧被撕裂。3. 交换机视角下的以太网MAC地址表的“读、写、删”3.1 从Hub到Switch为什么说交换机才是链路层的“角色”如果把Hub集线器比作一个大型广播现场你喊一句话所有人都会听到交换机就是一个“电话总机”它记录每个电话分机的号码你说要打给谁它就帮你接通谁不再惊动所有房间。Hub是物理层设备它不读取任何帧信息进来的比特流原封不动从所有其他端口发出去。这意味着整个Hub下的所有设备共享同一个冲突域和广播域一台机器发送垃圾广播全网络都跟着遭殃。交换机则不一样它工作在链路层能解析以太网帧里的目的MAC然后根据MAC地址表只把帧从对应端口转发出去。这就是“链路层角色”的含义交换机掌握了网络拓扑中每个设备“从哪个门进出”的映射关系决策的依据就是MAC地址表。3.2 MAC地址表的学习与老化一台交换机是怎么变聪明的很多人以为交换机的MAC地址表是出厂就配好的这是个大误会。一台新交换机插上电MAC地址表是空的它完全是靠“看源MAC地址”来动态学习。举例来说Host A接在交换机Port 1Host B接在Port 2。Host A第一次向Host B发包交换机收到这个帧后先看源MAC发现这个MAC是从Port 1进来的于是把“MAC A - Port 1”记到表里。此时它还不知道Host B在哪个端口于是把这个帧从除Port 1以外的所有端口都发一遍这个动作叫“泛洪”。Host B收到这个帧后回了个包交换机从Port 2收到源MAC是Host B于是又学会了“MAC B - Port 2”。这样一来一回两张表项就齐全了。MAC地址表的关键参数还有一个“老化时间”。绝大多数交换机默认老化时间是300秒也就是5分钟。如果5分钟内这个MAC没有再产生任何流量表项就被删掉下次再通信又得重新泛洪一次。你把老化时间调得很短会频繁泛洪占用带宽调得很长又能让那些经常移动的设备“滞留”在错误端口。实际维护中当遇到“设备换个交换机接口之后还持续丢包几分钟”的情况基本就是老化表项没来得及刷新的例子。3.3 三种转发行为泛洪、转发、丢弃交换机对每一个收到的帧查完MAC地址表后只有三种处理方式。转发查表命中目的MAC所在的端口直接从那个口发出去。泛洪查表没命中或者目的MAC是广播地址FF:FF:FF:FF:FF:FF就向所有端口复制发送一份。丢弃查表发现目的端口跟接收端口是同一个口说明主机在和自己说话的帧其实如果送给自己理论上到主机上就被网卡过滤了交换机直接丢弃此外当目的MAC是一个组播地址且该交换机没有启用组播侦听时也会按广播方式泛洪这是很多网络慢的问题根源。有个经典疑问如果交换机接了一台PCPC的网卡到底会不会收到发给别人的帧会而且不仅会收到它还要把这个帧从链路层一路解析上来直到发现目的MAC和自己不匹配才丢弃。所以某些安全工具可以设置“混杂模式”就是为了连目的MAC不匹配的帧也一并收下来分析。这个原理搞清楚了你就理解为什么在以太网里做抓包分析基本都能看到邻居之间的流量。4. 一次Ping包请求的完整链路层旅程4.1 ARP以太网通信的第一步不是填报文而是“问路”你现在在电脑上Ping一个IP地址比如192.168.1.8你觉得第一个动作是发ICMP报文吗不对第一步永远落在链路层你的机器要先搞清楚“目的IP对应的MAC地址是什么”。IP地址是逻辑寻址数据帧必须填物理MAC地址二者中间需要一座桥这座桥就是ARP协议。ARP的工作方式很符合现实逻辑Host A在本地网络里广播一条“谁是192.168.1.8请告诉你的MAC地址”这个广播帧的目的MAC是FF:FF:FF:FF:FF:FF意味着所有同网段主机都会收到。正常情况下只有目标IP的主机会应答它发一个单播ARP Reply告诉Host A“我是192.168.1.8我的MAC是xx:xx:xx:xx:xx:xx”。Host A收到后把这个映射写进自己的ARP缓存然后才真正发起ICMP Echo Request。ARP缓存的默认有效期各异Windows一般是2分钟Linux一般更长所以你在排障时如果改了IP地址记得先用命令清ARP缓存不然就可能拿着旧映射去发数据通信自然失败。4.2 帧从Host A到Host B的完整细节走完ARP这一步后链路层旅程正式展开。第一步Host A的网卡驱动把ICMP报文封装成IP包再交给以太网驱动。以太网驱动会填上目的MAC刚通过ARP得到的Host B MAC、源MAC本机MAC、类型0x0800并计算FCS然后通过网线发送出去。第二步交换机收到这个帧从源MAC学习到Host A在某个接收端口再查目的MAC。如果MAC表里已经有Host B的对应关系它就精准转发到Host B端口如果没有就泛洪。Host B的网卡收到后先看目的MAC是不是自己是则接收并且往上送交给IP协议栈。第三步Host B收到ICMP Echo Request生成ICMP Echo Reply。这个回包在链路层也需要目的MAC和源MAC它正好知道源IP是Host A、源MAC也已经在刚才收到的帧里了直接回填即可。整个过程看起来只是“Ping通了”但里面至少涉及两次以上的ARP查询或缓存命中、一次帧封装、一次交换机查表、一次链路层校验。我想强调的是在抓包看这个流程时你应该能看到ARP请求、ARP应答、然后是连续的ICMP请求和回复。如果只看到请求没有回复问题大概率在Host B侧的应用层或防火墙如果连ARP都完不成那问题就在二层你要开始怀疑VLAN配置、交换机端口隔离、MAC地址表错误这些链路层元素。4.3 千兆以太网的自协商物理层和链路层之间的协作除了帧格式和转发逻辑链路层真正“落地”时还逃不开物理层的协作这个点在第二篇里不能不讲。自协商是现代以太网最常用的一个机制两个设备对接时先交换各自的能力比如速度、双工模式然后自动选择一个双方都支持的最佳参数。自协商出问题的场景非常典型一边是千兆全双工另一边却协商成百兆半双工双工不一致带来的后果就是高延迟、大量碰撞重传网速衰减到接近不可用。而这种现象的根源往往不是配置错误而是某根网线里有一对线断掉了——四对线里只通了两对千兆肯定起不来回退到百兆还能勉强工作。这就是我开头说的“明明都是千兆网卡传文件却只有百兆速度”的最大原因。真正确认问题是否出在链路层最直接的办法是看两端的协商结果。在Linux下用ethtool就能看到当前速率和双工模式Windows在网卡属性页面里也能看到。如果一边显示千兆全双工一边显示百兆半双工那你已经定位到物理层或线缆的问题了。5. 链路层排障实录现象、原因与对策5.1 端口电亮着但Ping不通先从链路层找“卡点”这是个很常见的“闹鬼”故障交换机端口指示灯显示正常网卡也一样可网络就是不通。经验不足的人会直接去查IP地址、防火墙但如果问题真在链路层就算你把协议栈翻个底朝天也查不到。遇到这种问题我建议你按这个顺序来先用命令行看端口状态包括端口是否被管理性关闭、是不是进入错误禁用状态。再看端口收发计数特别是CRC错误、FCS错误和“自协商失败”计数。如果这些错误在持续增长链路肯定有问题。关键点在于线路接口本身物理通则代表不了“链路协议正常”。比如某些光模块虽然收光正常但对端的光模块工作在错误模式会导致收端CRC持续报错。5.2 抓包看到“FCS错误帧”该怎么办线缆和光模块的检查清单我之前提过抓包工具对FCS的处理这里再讲一下真正判断物理层时该怎么看。现场排障时如果交换机统计的CRC错误持续走高我第一步会换一根网线。注意不要换劣质的三类或五类网线千兆环境里最少也要用正规渠道的六类线并且水晶头制作工艺很关键很多CRC错误其实来自压线时没有把八根线按顺序压到位。第二步是检查长度。以太网U型线缆通常不建议超过100米这个长度包含跳线、墙壁面板的连线、配线架跳线全部在内。如果布线超过100米任何交换机都不保证能正常工作CRC错误、丢包都算正常现象。第三步是检查环境干扰把网线从高压线缆、配电箱附近挪开很大程度上能消除掉“时段性”的CRC错误。如果以上都排除掉再看光模块包括收光功率、发光功率是否在正常范围。光模块是个娇贵的东西灰尘污染是最容易忽略的隐性故障源用光纤清洁笔清理后再看计数是否归零很多时候问题就解决了。5.3 MAC地址表老化引起的“间歇性丢包”还有一种让人抓狂的故障表现为设备运行一段时间后网络突然卡一下然后又恢复卡的时间没有规律。这种问题排查IP层完全无效因为往返延迟你根本看不出来Ping丢包率也不高。实际上这就是典型的MAC地址表抖动。常见触发因素有两个一个是网络中存在环路导致交换机收到重复帧源MAC在两个端口之间不停“漂移”MAC表被反复修改另一个是有设备做了端口聚合或者虚拟机迁移MAC地址从一个端口跳到另一个端口哪怕只是瞬间也可能引发一段时间的学习混乱。如果网管系统支持查看MAC地址漂移记录优先去看有没有端口一直在变化不支持的话就在现场用命令行过滤指定MAC看它到底出现在哪几个端口。确认是漂移而不是老化第一步是找环路、排查冗余线路而不是去调MAC老化时间。5.4 排查链路层的几个常用命令和习惯这里分享几个我在各种系统中都能直接用的命令纯属个人经验。Linux下ip link show看网卡状态ethtool eth0看协商结果和统计ip neighbor show看ARP缓存。Windows下ipconfig /all确认IP和MACarp -a查看ARP缓存getmac /v查看设备物理地址。交换机侧通用的“show interface”看收发统计“show mac address-table”看MAC表“show logging”看是否有端口抖动记录。不同厂商命令虽然略有不同但大同小异永远是先看物理层再看链路层最后才看网络层。排障的第一步永远是“确认物理层协商和统计计数”这句话我每带新人就要强调一次。不是因为它能让故障消失而是因为绝大部分链路层故障都藏在这里绕开这一步去翻IP层的配置十个里面八个白忙活。6. 关于以太网我最后想说的几点6.1 对“链路层已死”这种说法保持警惕这几年软件定义网络、VXLAN这些概念火起来后经常听到一种论调链路层已经简化到“转发就完事了”不值得深入研究。但我实际项目里遇到的故障十次里有六次出在二层——不是VLAN配置错就是MAC地址漂移又或者自协商和PDU问题。说到底上层的一切可靠传输、精准路由都要建立在一个能稳定交付每个以太网帧的基座上。你说链路层“简单”没问题但说它“不重要”我是绝不认同的。6.2 一个高效的模拟思路自己搭最小拓扑练“抄作业”如果你想把这篇里的内容真正变成自己的技能建议别只看文档搭一个最小拓扑练一遍两台服务器或两台电脑直连中间用一台支持命令行配置的交换机串起来。在一台机器上抓包观察ARP请求、ARP应答和ICMP报文流。在交换机上看MAC地址表的变化发几个Ping之后查表过几分钟再看表项是否存在。手动把网线拔掉一端观察MAC表老化时间和“未知单播泛洪”现象。故意用一根只有四芯通的网线看两端自协商结果怎么变化体会一下物理层是怎么反馈到链路层的。这套实验做下来你对前面所有概念的记忆会深刻很多。别问我怎么知道的我当年就是靠这种方式从“背协议栈”进阶到“真正看懂了网络”。技术这东西看过再多原理都不如亲手拆一次包、拔一次线来得直观。