📚 第一章 网络基础知识
📄 一句话概括

二层交换机只做三件事:学源 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 秒实验

  1. 把 frames 里的顺序换一下(比如先 A→C 再 C→A),看泛洪次数变不变。
  2. 加一条「同一个源 MAC 从两个不同口进来」的帧,想想交换机会怎么处理(提示:它会改表项, 这就是 MAC 欺骗)。
  3. 把 table 加一个「最后活跃时间」,模拟老化,看表项什么时候被清掉。

常见误区

  1. 以为泛洪就是广播。 泛洪是「不知道目的在哪」,广播是「目的地址全 F」,动作像,原因不同: 泛洪会随学习减少,广播不会。
  2. 以为交换机会验证源 MAC。 它只是被动观察,不验证,所以伪造源 MAC 就能引走流量。
  3. 以为交换机能隔离广播。 它不能,一个 VLAN 就是一个广播域,广播会走遍所有端口。
自测三问(点开对答案) 1. 二层交换机收到一个帧,做哪三件事? —— **学源 MAC 到端口、查目的 MAC、查到就单播/查不到就泛洪。** 「学源」与「查目的」是两件独立的事。 2. 为什么说交换机比集线器高效? —— **集线器永远泛洪,交换机学会之后只发目标端口**,把「共享带宽」变成了「并发」。 3. 表项为什么要有老化时间? —— **设备换端口后旧表项会失效**,不老化流量就会发到老地方。 5 分钟是「学习速度」与「跟随移动」之间的折中。

下一节讲路由器——它多了一个能力:把一段网络接到另一段网络。

相关笔记