← 全部文章

同一台路由器,三个不同的真相

一台物理设备,多重路由身份,以及为什么一张点边图装不下它们

Michel Wijnberg

这个系列的前四篇讲的是信任:正确地建模网络、安全地观测它、诚实地复现转发行为,以及 拒绝猜测。这一篇开启第二组,讲的是真要守住那条线到底需要什么。

而它的开头,正是那件在大多数拓扑工具还没走到有意思的问题跟前就把它们撂倒的事:一台路由 器不是一样东西。


一台什么都有两份的路由器

这是我实验室里的 nrt1-cr1

nrt1-cr1 的设备面板,OSPFv2 和 OSPFv3 各有一套独立的 ABR·ASBR 徽标
nrt1-cr1 的设备面板,OSPFv2 和 OSPFv3 各有一套独立的 ABR·ASBR 徽标

看右上角。不是一个角色徽标,是两个

OSPFv2   ABR·ASBR
OSPFv3   ABR·ASBR

下面的 Protocols & Areas 里:

协议实例区域角色
OSPFv2 · 进程 1 (ipv4)0.0.0.014.18.20.0ABR · ASBR
OSPFv3 · 进程 1 (ipv6)0.0.0.014.18.20.0ABR · ASBR

看起来像是重复。它不是。这是两个独立的协议实例,带着两份独立的链路状态数据库,而 nrt1-cr1在每一个里各自因为连接了那个实例里的多个区域而挣得 ABR 这个头衔的。 区域标号一致,是因为有人特意把它们编成一样,不是因为它们是同一个对象。在数据库里它们的 UUID 不同,因为 OSPFv2 的区域 14.18.20.0 和 OSPFv3 的区域 14.18.20.0 是两个碰巧同名 的不同区域。

这个区分听起来很迂腐,直到两者出现分歧为止。而事实证明,它们总是有分歧。


一根线,两个开销,百分之百的情况下

这是两台路由器之间的一条物理链路:

lax1-gw1 到 lax1-gw2 的链路面板,带 Physical、OSPFv2 和 OSPFv3 三个页签以及不同的开销
lax1-gw1 到 lax1-gw2 的链路面板,带 Physical、OSPFv2 和 OSPFv3 三个页签以及不同的开销

一根线缆。Et0/3Et0/3,10G,同时承载 172.24.2.13/30 fddb:10:24:2::6/127。Osprey 把它画成一条边,因为它在物理上就是一条边,然后给它按协议分 页签。

现在看开销:

OSPFv2   Area 12.1.24.0   cost 10
OSPFv3   Area 12.1.24.0   cost 1

同一根线。同一个区域号。度量值不同。

这不是我为截图特意摆出来的。之后我把 AS 200 里所有双栈链路都查了一遍,结果比这个单独的例 子更有意思:

AS 200 里的双栈链路124
…其中 OSPFv2 与 OSPFv3 开销不同124(100%)
落在 (v2 = 10, v3 = 1)85
落在 (v2 = 10000, v3 = 10)39

每一条都不同,但请看这两组:39 条链路相差 1000 倍,85 条相差 10 倍。这个不对称才是有意思的 地方,而要解释它,得去问路由器。

Routing Process "ospf 1"     Reference bandwidth unit is 100000 mbps
Routing Process "ospfv3 1"   Reference bandwidth unit is 100 mbps

是一个设置项,不是两个。开销等于参考带宽除以接口带宽,所以两个进程是在用相差正好 1000 倍 的数字去缩放同一批线路。在 10 Mbps 的链路上,这个差异原封不动地体现出来:10000 对 10。在 10 Gbps 的链路上,OSPFv3 算出 100/10000 = 0.01,而路由器能通告的最小开销是 1。下限把剩下的 部分吃掉了。

所以这个扭曲不是均匀的,而这恰恰是它危险的地方。均匀缩放是无害的:把一个拓扑里所有开 销都乘同一个常数,最短路径不会挪动。而这里的常数在一部分链路上是 1000,在另一部分上是 10, 因为中间有一个下限插了一脚。于是这两个协议对同一批链路的相对排序不同,IPv4 和 IPv6 流量 可以在这张网里走不同的路径。哪些会走不同,肉眼看不出来。您必须把两个都算出来。

一个画”一条链路,一个开销”的工具必须在这两个数字里挑一个。不管它挑哪个,有一半的时候是错 的,而且它永远不会告诉您您现在处在哪一半。


为什么这套层级是承重结构

这就是为什么 Osprey 的数据模型不是 NodeEdgeProtocol

Network → Autonomous System → Routing Domain → Protocol Instance → Area → Device
                                                                      ↳ Interface

每一层之所以存在,是因为网络里有东西会在这一层上产生差异:

  • Network:租户边界。同一台物理设备可以在两个租户下被监控,用不同的凭据,看到不同的 视图。
  • Autonomous System:BGP 身份,也是一路 BMP 数据流所归属的范围。
  • Routing Domain:全局表、某个 VRF 或某个 L3VPN。同一台路由器,不同的路由表,真正不同 的可达性。
  • Protocol Instance:在(路由域、协议、进程号、地址族)上唯一。正是这一层让 nrt1-cr1 变成了两台路由器。
  • Area:LSDB 真正所在之处,因而也是 SPF 真正运行之处。
  • Device:与区域之间是多对多,通过一张成员表。不是外键。外键会逼出”一台路由器只住在一 个区域里”这个谎。

而接口是按 (device_id, if_index, area_id) 划界的,因为同一个物理端口会同时参与多个协议实 例,在每一个里都有不同的开销、不同的邻居状态和不同的地址族。

派生出来的角色是从这个结构里长出来的,而不是当成标签存起来:

  • ABR = 在某个实例内连接了多个区域
  • ASBR = 路由器自身 LSA 里置位的 E 位(RFC 2328 §A.4.2),也就是路由器自己声明它产生外 部路由信息。不是数成员数量:一台路由器可以只住在一个区域里而仍然是 ASBR,也可以横跨多个 实例却不是 ASBR
  • VRF-Lite = 出现在多个路由域里

这就是为什么 nrt1-cr1 可以两次成为 ABR,也是为什么那个徽标被画了两遍。没有人在任何地方 敲过”ABR”。它是成员关系的推论,从 LSDB 重新算出来的。


这些拓扑同时都是真的

思考这件事有用的方式是:根本不存在那个拓扑。存在好几个,它们同时为真,而且回答的是不 同的问题:

拓扑由什么构建回答什么
物理LLDP / CDP、IP-MIB什么和什么之间有线
二层桥/VLAN 邻接什么共享一个广播域
IGP(按实例)每协议每区域的 LSDB每个协议相信什么
BGPBMP RIB什么可达、经由谁可达
转发每台路由器自己的表一个报文实际会去哪

“A 和 B 连着吗?“有五个各自正确的答案,取决于您问的是哪一个。两台路由器可以共享一根线缆却 没有 IGP 邻接。它们可以有 IGP 邻接却从不互相转发报文。它们可以是 BGP 对等体,而中间那条路 径跨过了两者都看不见的三台设备。

第三篇文章其实是在论证最后那两行:IGP 拓扑和转发拓扑不是同一张 图,把它们当成一张图,八次里就会产生一次虚构的路径。这一篇是同一个论证往下一层:物理 拓扑和协议拓扑同样不是一张图,而我实验室里的 124 条链路用一个十倍的因子把它证明了。


这要付什么代价

对这件事诚实是有成本的。它意味着:

  • 别人只走一份 LSDB,我们要走两份
  • 用成员表而不是外键
  • 角色是重新算出来的,而不是存下来的
  • 每一次路径查询都必须知道自己被问的是哪个实例、哪个地址族
  • 界面上一条链路要显示一排页签,而不是一个数字

另一条路是:一张渲染更快、演示更好看的图,然后在您网络里每一条双栈链路上悄悄从两个开销里 挑一个。

我运维过 IPv4 和 IPv6 路径已经分岔、但几个月都没人发现的网络,因为墙上每一个工具都在两台路 由器之间画一条线。那条线并不错。它只是回答了一个没有人问过的问题。


下一篇:当这些来源正面互相矛盾时会发生什么: 当网络自己跟自己不一致