路一断,RIP 会「互相骗」到 16 才停,这段时间流量全在空跑。 四招缓解:水平分割、毒性逆转、触发更新、抑制时间。
7.3.1 讲了计数到无穷的原理,这一节讲 RIP 具体怎么掐它。 这四招都是「补信息」或「加延迟」,没有一招能根治。
一、问题回顾:两个人都以为对方还有路
A—B—C 串成一条链,C 后面挂着网段 X。 X 断了,C 立刻知道,但 B 还记着「经 C 到 X 只要 1」。 B 丢掉经 C 的那条,改成经 A——可 A 的那条本来也是经 B 学来的。 于是两个人都以为对方还有路,距离一轮涨一跳,涨到 16 为止。 一共 15 轮,每轮 30 秒,就是七分半。 这七分半里,所有发往 X 的包都在往一个死胡同里送。 注意这不只是「慢」——它还会造成「次优路径」: 如果 X 其实从另一个方向还能到,RIP 也会因为「距离还没涨完」而选错。
二、第一招:水平分割
思路最朴素:从哪条线学来的,就别从那条线说回去。 B 记得「到 X 的路是从 A 学来的」,所以它不向 A 通告这一条。 A 收不到「我这儿还有路」的假消息,两边第一轮就直接置成 16。 这一招为什么有效:因为计数到无穷的前提是「A 从 B 那里听到了一条本来来自 A 的路」。 水平分割直接掐掉了这个前提。 它不是「打补丁」,是「补上一条本来该有的信息」—— 也就是 7.4.2 说的「下一跳记了但来源没记」。 但它有个前提:拓扑必须是「树」。 如果 A 和 B 之间有两条链路(形成环), B 从另一条链路学到的路由,还是会从这条说回去——水平分割只看「这条线」,不看「整个环」。 所以「有环的拓扑里水平分割不够用」。
三、第二招:毒性逆转
水平分割是「不说」,毒性逆转是「明确说不可达」。 B 向 A 通告「到 X 的距离是 16」——不是沉默,是主动告诉「这条路没了」。 为什么「说」比「不说」好:因为「沉默」在 RIP 里就是「我这儿没有这条路」, 而 A 可能还有别的来源(比如另一台邻居),它不会因为 B 沉默就把 B 那条删掉。 明确说 16,A 才知道「经 B 这条路真的没了」。 代价是「报文变大」:本来不该说的那条现在要说,一个包 25 条的上限就更紧。 而且「毒性逆转」和「水平分割」经常一起配—— 这叫「带毒性逆转的水平分割」(split horizon with poisoned reverse)。 很多设备的默认配置就是这个。
四、第三招和第四招:触发更新与抑制时间
触发更新:一有变化立刻发,不等 30 秒。 这一招直接把「一轮」从 30 秒压到「毫秒级」,计数到无穷的 15 轮就变成了 15 个毫秒级间隔。 代价是「可能抖」: 如果一条链路「时通时断」(比如接触不良),触发更新就会不停地发,把整网搅得不安宁。 所以触发更新通常要配一个「最小间隔」——比如「同一条路由 5 秒内最多触发一次」。 抑制时间:坏消息先压住一阵再采信。 收到「某条路由不可达」之后,先把它标成「抑制」状态,一段时间内不采信关于它的任何好消息。 这是为了防「好了坏了」反复横跳——因为「抖动」比「一直坏」更伤网络:一直坏至少是稳定的。 但抑制时间有个副作用:它会「压住真正恢复了的好消息」,所以抑制期设太长,恢复就慢。 工程上这个值通常设几十秒到两分钟,是个经验值。
五、四招合起来,还是治不好
把四招全开,计数到无穷基本不会发生了,但「收敛慢」这件事没解决: 超时还是 180 秒,一轮还是 30 秒。 网络大了,这些时间加起来依然不可接受。 根本原因是「信息不足」: RIP 的每台路由器只知道邻居说了什么,不知道「这条消息最初是谁说的」。 补丁能缓解症状,改不了这个本质。 所以要根治,只能换算法——也就是 7.3.2 的链路状态:每台手里有全图,不靠传闻。 这也是一条通用的工程规律:当「信息结构」不够时,补丁只能缓解;要根治,必须改信息结构。 RIP 到 OSPF 的演进,本质就是「从传闻改成地图」,而不是「把传闻传得更快」。
六、动手 Demo:水平分割怎么掐住计数到无穷
不开水平分割,距离从 2/3 一路抬到 16,共 15 轮。 开了之后,第一轮就直接置成 16。
INF = 16
a, b = 2, 3
for rnd in range(1, 30):
print('第 %2d 轮 A=%2d B=%2d' % (rnd, a, b))
if a >= INF and b >= INF:
break
a, b = min(b + 1, INF), min(a + 1, INF)
# 开了水平分割:B 记得这条路是从 A 学的,不向 A 通告
print('开了之后:第一轮 A=16 B=16')
实跑输出:
--------------------------------------------------------------------
水平分割怎么掐住计数到无穷
--------------------------------------------------------------------
**7.3.1 那个「互相骗」的问题,RIP 用四招治**。**最有效的一招叫「水平分割」。**
**思路很朴素:从哪条线学来的,就别从那条线说回去。**
轮次 不开水平分割 A 不开水平分割 B 开了之后
------------------------------------------------------------
第 1 轮 2 3 16 / 16
第 2 轮 4 3 —
第 3 轮 4 5 —
第 4 轮 6 5 —
第 5 轮 6 7 —
第 6 轮 8 7 —
第 7 轮 8 9 —
第 8 轮 10 9 —
第 9 轮 10 11 —
第 10 轮 12 11 —
第 11 轮 12 13 —
第 12 轮 14 13 —
第 13 轮 14 15 —
第 14 轮 16 15 —
第 15 轮 16 16 —
**一共花了 15 轮才把距离抬到 16**(也就是 RIP 的「无穷大」)。**
**这期间所有发往那个网段的包,都还在往一个已经不通的方向送。**
**开水平分割之后**:
**B 记得「到那个网段的路是从 A 学来的」,所以它不向 A 通告这一条**——
**A 收不到「我这儿还有路」的假消息,两边第一轮就直接置成 16。**
**最后一列全是 16,就是这个意思。**
**还有三招**:
机制 做法 代价
---------------------------------------------------------------------------------
**毒性逆转** **把「不可达」明确说出来** **比不说更狠,但要占带宽**
**触发更新** **一有变化立刻发,不等 30 秒** **收敛快,但可能抖动**
**抑制时间** **坏消息先压住一阵再采信** **防止「好了坏了」反复横跳**
**这四招合起来才让 RIP 能用**,
**但它们都只是「缓解」,不是「根治」**——**距离向量「只认识邻居」这个信息局限,靠补丁补不回来。**
**要根治,就得换算法**(下节的链路状态)。
一共花了 15 轮才把距离抬到 16(也就是 RIP 的「无穷大」)。 这期间所有发往那个网段的包,都还在往一个已经不通的方向送。 开水平分割之后: B 记得「到那个网段的路是从 A 学来的」,所以它不向 A 通告这一条—— A 收不到「我这儿还有路」的假消息,两边第一轮就直接置成 16。 注意「15 轮」这个数不是巧合:从 2 涨到 16 正好 14 步,加上最后一步确认,就是 15 轮。 如果 RIP 把上限定成 32,那就是 30 轮—— 所以「16」这个数字本身就是「用缩短上限来换收敛速度」的取舍。
30 秒实验
- 算一下:15 轮乘以 30 秒,一共多少分钟?
- 想一下:为什么「有环的拓扑里」水平分割不够用?
- 想一下:抑制时间设太长,会有什么副作用?
常见误区
- 以为「水平分割能根治计数到无穷」。 只能缓解,有环拓扑里还是会发生。
- 以为「沉默就等于说不可达」。 沉默会被理解成「我这儿没有」, 所以毒性逆转要「明确说 16」。
- 以为「触发更新越快越好」。 链路抖动时它会不停发,必须配最小间隔。
自测三问(点开对答案)
1. 水平分割的原理是什么? —— **从哪条线学来的,就不从那条线说回去。**掐掉「互相骗」的前提。 2. 毒性逆转和水平分割有什么区别? —— **一个是不说,一个是明确说「距离 16」**,后者更狠但占带宽。 3. 为什么这四招治不好收敛慢? —— **超时 180 秒、周期 30 秒都没变**,信息结构没改,只能缓解。下一节看 RIP2 怎么把「掩码」和「认证」补上。
- ☐ (本节完,下一节 7.4.5 RIP2)