讲链路层,得先回到 1970 年代的夏威夷。Aloha 网要让散布在各岛的终端共享一个无线电频道,谁想发就发,撞车了就退避重试。这个「共享介质、随机接入」的思路后来被 Metcalfe 带到施乐,长成了以太网:早期以太网是一根同轴电缆串起整栋楼,像一根总线,任何人发数据,全楼都听得见,目标设备收下,其他设备丢弃。两台同时开口,信号叠加成废料,这叫冲突。
总线时代早就结束了,但它留下了本章几乎所有的主角:用来区分「全楼谁是谁」的 MAC 地址,用来裁决「谁能开口」的 CSMA/CD,还有把总线切成一个个独立端口的交换机。
MAC 地址 48 位,写成 86:4b:57:de:56:09,前 24 位是厂商号(OUI),后 24 位厂商自己排。它烧在网卡里,习惯上当作硬件身份——不过现在手机连 Wi-Fi 默认用随机化的 MAC(每 SSID 一个假地址),防的是商场靠 MAC 追踪你的行迹,顺便给校园网认证这类「绑定 MAC」的老系统制造了一点麻烦。
每个学网络的人都会在某个时刻问:IP 已经全网寻址了,为什么链路层还要一套自己的地址?我自己的答案分两层。
第一层是历史与现实:链路技术从来不止以太网一种,Wi-Fi、PPP、光纤通道各有各的帧格式和寻址方式。IP 的野心是跑在一切链路上,那它就不该假设任何一种链路的地址格式;每种链路保留自己的本段寻址,IP 只负责「从源网络到目的网络」,分工反而干净。ARP(6.4 节)就是 IP 和以太网之间的那名翻译。
第二层更实在:两者的作用域完全不同。IP 地址是逻辑身份,按网络拓扑分配,跨网段通信时端到端不变;MAC 是本段身份,只在同一个局域网里有效,每经过一个路由器就换一副新面孔。你可以把它类比成寄快递:IP 是收件地址,全国通用;MAC 是派送员眼里的门牌,出了这个小区就作废。
┌─────────┬─────────┬──────┬──────────┬────────────┬───────┐
│ 前导码 │ 目的MAC │ 源MAC │ 类型/长度 │ 数据 │ FCS │
│ 7+1字节 │ 6 字节 │6 字节│ 2 字节 │46–1500字节 │ 4 字节│
└─────────┴─────────┴──────┴──────────┴────────────┴───────┘
几个字段各有一句话可说。前导码 7 字节加帧定界符,帮接收方对齐时钟,严格说它不算帧的一部分,但抓包时它确实在线上。类型字段告诉接收方载荷是什么:0x0800 是 IPv4,0x0806 是 ARP,交换机和网卡靠它把包递给正确的上层。FCS 是帧尾 4 字节 CRC,硬件算,校验失败整帧丢弃,链路层不重传,丢了就丢了(修不修是上层的事,这是「尽力而为」贯穿始终的又一例)。
数据长度 46 到 1500,下限 46(即整个帧最短 64 字节)是总线时代留下的规矩:CSMA/CD 要边发边听,冲突信号传回来时发送方必须还没发完,否则检测不到是自己的帧出了事。按 10 Mbps 的时序倒推,这个窗口要求帧至少 64 字节。今天全双工交换网络没有冲突了,64 字节下限照旧保留,算是一座活着的化石。上限 1500 就是 MTU,超出得由 IP 层分片(第 5 章),这也是第 5 章 MTU 黑洞问题的物理根源。
集线器是喇叭:收到比特,原样复制到所有其他端口,谁该听谁自己判断,带宽全楼共享,冲突照旧。交换机干的事本质一样简单,但聪明:按 MAC 地址表定向转发。
表的建立完全自动,这叫自学习,值得手推一遍。设交换机四个端口 1、2、3、4,分别插着 A、B、C、D,开机时表为空:
1. A 发帧给 C:交换机查表,不认识 C → 泛洪到 2、3、4;
顺手记录:A 在端口 1(帧的源 MAC 是 A,且从端口 1 进来)
2. C 回帧给 A:查表,A 在端口 1 → 只从端口 1 发出;
记录:C 在端口 3
3. 之后 A、C 互发,定向转发,B、D 的链路完全不受打扰;
每端口独享带宽,全双工,冲突消失
源 MAC 天然可信吗?大体可信(你从哪个口收到它,它就在哪个口),但可被伪造,所以交换机还有端口安全、MAC 表条目上限这类加固手段。另外表会老化,几分钟没流量就删,人挪走、线重插都能自动适应。
广播帧(目的 MAC 全 1,即 ff:ff:ff:ff:ff:ff)交换机永远泛洪,ARP 就靠它活着。交换机不隔离广播域,一个交换网络就是一个广播域;隔离广播要靠路由器(第 5 章),按端口划分广播域的东西叫 VLAN,这里不展开。
以太网帧要填目的 MAC,但应用程序手里只有 IP,翻译工作由 ARP 完成。第一次在 Wireshark 里亲眼看到它,有种看人打电话问路的既视感——真实报文就一句话:
广播: Who has 192.168.1.1? Tell 192.168.1.103
单播: 192.168.1.1 is at 86:4b:57:de:56:09
请求必须广播(还不知道对方的 MAC,只能喊全楼),应答是单播。双方把结果缓存进 ARP 表,不至于每次发包都喊一嗓子。Linux 上看 ARP 表用 ip neigh,我机器上的真实输出:
10.99.188.18 dev wlo1 lladdr 86:4b:57:de:56:09 REACHABLE
fe80::844b:57ff:fede:5609 dev wlo1 lladdr 86:4b:57:de:56:09 router REACHABLE
第一列是 IP,lladdr 是 MAC,最后的状态列很传神:REACHABLE 表示最近确认过可达,一段时间没来往会退化成 STALE(旧数据,下次用之前要重新确认),表项不是永久缓存。
跨网段时有个新手必知的细节:帧的目的 MAC 填的是网关的 MAC,不是最终服务器的。你的机器查路由表(第 5 章)知道下一跳是网关,ARP 问到的也是网关,包到了网关再重新 ARP 下一跳。所以抓包时会看到荒谬的一幕:访问地球另一端的服务器,帧头上的目的 MAC 却是你家路由器。
ARP 的无认证是个明牌的软肋:同一网段里谁都可以狂发「网关 IP 在我这」的假应答,把别人的流量先引到自己手里再转发,这就是 ARP 欺骗,局域网中间人攻击的标准起手式(第 8 章的 TLS 才是真正的解药)。
总线死了,但它的裁决规则值得留三行:发前先听(载波监听),有人在发就等;边发边听(冲突检测),撞了立刻停发、发干扰信号、按二进制指数退避随机重试。这套规则让没有中央调度的一根电缆也能有条不紊。交换式全双工以太网让冲突物理上不可能发生,CSMA/CD 随之退役;Wi-Fi 捡起了它的半截思想,改成 CSMA/CA(冲突避免),因为无线电是半双工且没法边发边听(自己的发射信号会淹没接收),只能靠 ACK 和随机退避事后兜底。这两段是考试重灾区,工程上你知道「它为什么存在、为什么退役」就够了。
ip neigh show 挑一条表项删掉(ip neigh del <ip> dev <网卡>),再 ping 它,立刻再看表,观察状态从什么变到什么。