二层交换机只做三件事:学源 MAC、查目的 MAC、转发或泛洪。 它会「学会」,所以建表只花几帧,之后全是单播——这就是它比集线器高效的全部原因。
1.9.3 的中继器「不缓存、不懂地址」,交换机两样都会。 网桥与交换机是同一个东西的两个时代:网桥是软件实现的,交换机是硬件实现的。
一、三件事
收到一个帧,它只做三件事:
| 步骤 | 动作 | 为什么 |
|---|---|---|
| 1 | 学源 MAC → 端口 | 知道「这个人在哪个口」 |
| 2 | 查目的 MAC | 知道「该往哪个口送」 |
| 3a | 查到了 → 单播 | 只发那一个口 |
| 3b | 查不到 → 泛洪 | 发给除来源口外的所有口 |
第一步「学源」是整套机制的关键:交换机从「谁发的」推断出「谁在哪」,而不是靠配置。 所以它不需要任何管理协议、插上电就能工作。 这种「被动观察」的设计,是二层网络部署极简的原因。 第四行那个「泛洪」是很多人误解的地方: 泛洪不等于广播——广播是「目的地址是全 F」,泛洪是「不知道目的在哪」。 结果是动作一样(都往所有口发),但原因不同、优化方式也不同。 泛洪会随着表的学习而减少,广播不会。
二、建表只花几帧
跑一遍真实的建表过程:
| 帧 | 源 MAC | 动作 | 新学到 |
|---|---|---|---|
| A→B | AA-..-01 |
泛洪 | 是 |
| C→A | AA-..-03 |
单播到端口 1 | 是 |
| A→C | AA-..-01 |
单播到端口 3 | 无 |
| D→B | AA-..-04 |
泛洪 | 是 |
| B→D | AA-..-02 |
单播到端口 4 | 是 |
第三行是唯一「没有新条目」的一行:因为 A 和 C 的地址在第一、二帧里都已经学到了。 这一行正好说明「学习是幂等的」——同一个源地址重复出现,只会刷新老化计时,不会新增表项。 「建表只花几帧」这句话的分量在这里: 集线器永远泛洪(它本质就是一根电线),交换机学会之后就不再打扰无关的端口。 所以同样的带宽,交换机能把「有效吞吐」提高几倍——因为它把「共享」变成了「并发」。
三、老化时间与无状态学习
表项不是永久的:
| 设计 | 数值/做法 | 为什么 |
|---|---|---|
| 老化时间 | 通常 5 分钟 | 设备换口后旧表项要失效 |
| 学习方式 | 被动观察 | 不参与任何协商 |
| 没有确认 | —— | 所以可能学到错的口 |
第一行那个 5 分钟是个折中: 太短,表一直学不满,泛洪多;太长,设备换了口之后流量还发到老地方。 这个值可以调,但调的依据是「设备移动频率」。 第三行是这套机制的真实弱点:交换机只是「看到源 MAC 从某口来」就记下来,不验证。 所以有人伪造源 MAC,就能把流量引到自己这儿—— 这是「MAC 欺骗」的原理,也是「MAC 泛洪攻击」的基础。 二层没有认证,这是设计上的取舍,不是漏洞。 对比一下路由器:路由器是「主动协商」的(跑路由协议、交换路由表), 交换机是「被动观察」的。 前者能适应变化,后者只能靠老化兜底——这就是「大网络要三层到边缘」的深层原因。
四、动手 Demo:二层交换机靠一张表转发
模拟五个帧进出,看 MAC 表怎么长出来。 重点是「哪一帧没有新条目」。
table = {}
port_of = {'AA-00-00-00-00-01': 1, 'AA-00-00-00-00-02': 2,
'AA-00-00-00-00-03': 3, 'AA-00-00-00-00-04': 4}
frames = [('A->B', 1, 2), ('C->A', 3, 1), ('A->C', 1, 3),
('D->B', 4, 2), ('B->D', 2, 4)]
for tag, sport, dport in frames:
src = [k for k, v in port_of.items() if v == sport][0]
dst = [k for k, v in port_of.items() if v == dport][0]
new = src not in table
table[src] = sport
if dst in table:
act = '单播到端口 %d' % table[dst]
else:
act = '泛洪到所有端口'
print('%-6s %-20s %-16s %s' % (tag, src, act, '是' if new else '—'))
print('表项 %d 条' % len(table))
实跑输出:
--------------------------------------------------------------------
二层交换机靠一张表转发
--------------------------------------------------------------------
**交换机做的事只有三件:学源 MAC、查目的 MAC、转发或泛洪。**
下面真跑一遍这张表怎么长出来。
帧 源 MAC 动作 新学到
------------------------------------------------------------
A→B AA-00-00-00-00-01 **泛洪到所有端口** 是
C→A AA-00-00-00-00-03 单播到端口 1 是
A→C AA-00-00-00-00-01 单播到端口 3 —
D→B AA-00-00-00-00-04 **泛洪到所有端口** 是
B→D AA-00-00-00-00-02 单播到端口 4 是
**最后一列除了第三行全是「是」**——**第三行 A→C 时两端的 MAC 都已经在表里了,所以没有新条目。**
**建表只花了几帧,之后全部单播**——**这就是交换机比集线器高效的全部原因**:
**集线器永远泛洪(它就是根电线),交换机学会之后就不再打扰别人。**
**表项有老化时间**(通常 5 分钟)**:**设备换了端口,旧表项得自动失效**,否则流量会发错地方。
**这条设计说明交换机的「学习」是无状态的、靠时间兜底的**——**它不参与任何协商,只被动观察。**
最后一列除了第三行全是「是」:第三行 A→C 时两端的地址都已经在表里了,所以没有新条目。 前两帧是泛洪、后三帧全是单播:这就是「学会之后就不再打扰别人」。 集线器做不到这一点,它永远泛洪。 注意第一帧 A→B 时,交换机已经学到了 A 的端口, 但 B 还不在表里,所以仍然泛洪——「学源」和「查目的」是两件独立的事,不要混。
30 秒实验
- 把
frames里的顺序换一下(比如先 A→C 再 C→A),看泛洪次数变不变。 - 加一条「同一个源 MAC 从两个不同口进来」的帧,想想交换机会怎么处理(提示:它会改表项, 这就是 MAC 欺骗)。
- 把
table加一个「最后活跃时间」,模拟老化,看表项什么时候被清掉。
常见误区
- 以为泛洪就是广播。 泛洪是「不知道目的在哪」,广播是「目的地址全 F」,动作像,原因不同: 泛洪会随学习减少,广播不会。
- 以为交换机会验证源 MAC。 它只是被动观察,不验证,所以伪造源 MAC 就能引走流量。
- 以为交换机能隔离广播。 它不能,一个 VLAN 就是一个广播域,广播会走遍所有端口。
自测三问(点开对答案)
1. 二层交换机收到一个帧,做哪三件事? —— **学源 MAC 到端口、查目的 MAC、查到就单播/查不到就泛洪。** 「学源」与「查目的」是两件独立的事。 2. 为什么说交换机比集线器高效? —— **集线器永远泛洪,交换机学会之后只发目标端口**,把「共享带宽」变成了「并发」。 3. 表项为什么要有老化时间? —— **设备换端口后旧表项会失效**,不老化流量就会发到老地方。 5 分钟是「学习速度」与「跟随移动」之间的折中。下一节讲路由器——它多了一个能力:把一段网络接到另一段网络。
- ☐ (本节完,下一节 1.9.5 路由器/3层交换机)