没有数据库的协议
三种不同的「什么都没有」:没有可加入的数据库、一个没人实现的数据库,以及一张有答案却没有输入的表
Michel Wijnberg
前两篇讲的是如何小心地加入一个链路状态协议:进去而不成为一条路径,出来而不留下幽灵。两者都假定 存在某个可以加入的东西。
这一篇讲的是并不存在那种东西的情形,而它们并不是同一种情形。我有三个,它们以三种真正不同的方式 失效。
其一:根本没有数据库
EIGRP 是一种高级距离矢量协议。邻居之间交换可达性与距离信息;它们并不维护一个共享的链路状态数据库。 不存在一份每台路由器都持有的同步副本,因此也就没有可与之同步的对象。前两篇里”加入”这一步在这里 并不存在,因为你要加入的那个东西从来没有被建造出来。
真正存在的,是每台路由器自己的视角:它的邻居,以及它算出来的、带距离的目的地拓扑表。这些通过
SNMP 从 CISCO-EIGRP-MIB 里一台一台读出来,而邻接图是根据每台路由器对自己邻居的陈述重新拼装
出来的。
是拼装,不是读取。网络里没有任何人持有这幅图。它只有在你问过所有人、并把答案拼在一起之后才存在, 这与读取一份 LSDB 是不同的认识论位置,即便拼出来的图看上去一模一样,这一点也值得诚实说明。
那个不肯说自己是谁的邻居
接着是一个具体的问题,而且是个漂亮的问题。
一条 EIGRP 邻居表项会给你邻居的地址。对 IPv6 而言那个地址是链路本地地址,而链路本地地址标识 的是某条链路上的一个接口。它并不标识一台设备。网络两端相隔最远的两台路由器可以携带同一个链路本地 地址而毫无冲突,因为它的作用域就是那条链路。
所以邻居表告诉你那边有个东西,却拒绝告诉你那是什么。
解答来自完全不同的一层:为该设备已经发现好的 LLDP 与 CDP 邻接,按接口建立索引。把 EIGRP 邻居所在 的接口与同一接口上的 L2 邻居对上,你就知道对端是哪台设备了。
这意味着 Osprey 里的一条 EIGRP 边,在底层其实是两个彼此独立的观测取得了一致:路由协议说存在一条 邻接,而链路层说另一端是谁。当 L2 数据缺失时,这个邻居保持未解析。它不会从编址里猜出来,不会 从命名里推断,也不会靠子网去凑。一条无法归属到某台设备的边,就不会成为一条边。
其二:表里有答案,却没有输入
EIGRP 拓扑表正是第二种”什么都没有”的居所,也正是它在产品里催生了一次拒绝。
这张表有十二个可访问的列。它们合起来承载着 DUAL 的各种距离:可行距离、当前计算距离、某个后继报告 的距离,外加后继计数与下一跳状态。这足以向你展示每台路由器此刻相信什么,而 本博客的第一篇展示的正是这个:每台路由器自己的数字,沿着一条链递减。
它不足以计算任何新东西。
要在一次假想变更之后重新计算度量值,你需要那些被报告的距离由之推导而来的分量,以及它们背后的接口
状态。它们在路由器上:向 e-ams1-cr1 请求 show ip eigrp topology 10.64.0.0/15,它会为那个前缀
打印出最小带宽、总时延、可靠性、负载、MTU 和跳数;所以我知道它们存在,而不是靠推断。
它们不在被读取的那张 MIB 表里。那十二列承载的是 DUAL 所决定的结果。路由器保留着 DUAL 据以做出决定 的材料,而并不在这里发布它。
于是 Osprey 拒绝。让它在一个 EIGRP 域里模拟故障,它会谢绝投影一条新的链,并说明理由:它无法预测 DUAL 的再收敛,因为它读到的表承载的是距离,而不是重新计算所需要的度量分量。
关于这次拒绝,有两件事比拒绝本身更重要。
它的范围限定在我们所读取的东西上,而不是这个协议上。 那条消息是这样措辞的:这是数据采集的 天花板,而不是 EIGRP 的性质,因为将来若有从别处读取这些分量的增补器,天花板就会被抬走。一个说 “EIGRP 无法被模拟”的产品,是在悄悄告诉你永远别再问了,而那是一句与”我目前不采集这些输入”截然 不同、也糟糕得多的陈述。
它对何时触发是精确的。 如果模拟的变更是一次纯粹的移除,而被移除的东西可以证明不在观测到的那条 链上,那么真实的链仍会被展示出来,并附一条说明:这次故障并不触及它。在别处收走容量,不可能改善一条 本来就没在用它的距离矢量路径。但一次开销变更或一条新链路可以从任何地方把路径吸引过去,所以那些 永远算作”触及”。引擎在必须拒绝的地方拒绝,而不是一概拒绝,而这个差别正是拒绝的全部价值。
其三:数据库只存在于标准之中,别处都没有
第三种”什么都没有”最令人沮丧,因为它不是任何人的缺陷。
IS-IS 有一个标准 MIB:RFC 4444,位于 .1.3.6.1.2.1.138。Osprey 的 SNMP 发现会先探测那棵树,
只有在此之后才回退到 .1.3.6.1.4.1.9.10.118 的 Cisco 树。两套 OID 共享一套相对基点的列布局,只在
MIB 本身确有差异之处不同,也就是电路列的一处偏移;邻接相关的列完全相同。这个设计是刻意做成厂商中立
的。
那条标准路径从未在真实硬件上得到验证。
不是因为它在单元测试意义上没被测过:它有测试。而是因为我们能够到的每一台设备都只实现了 Cisco 那棵
树。向实验室的路由器探测标准的 .138 树,它返回 No Such Object。那条厂商中立的代码路径只被固定
装置驱动过,此外别无它物;而我宁愿自己写下这句话,也不愿让它被别人发现。
然后 Arista 把事情变得更糟了,而且方式很有教益。在服务舱上探测 vEOS-lab 4.29.2F:标准的 .138
树返回 No Such Object,Cisco 的 .9.10.118 树也一样。两个都没有。这台设备把 IS-IS 讲得
好好的,却根本没有任何一棵 SNMP 树可以拿来询问它。
同一个代理提供 OSPF-MIB 毫无问题,也提供 LLDP-MIB,而且一旦配置了 OSPF 就会动态注册 OSPF 那棵树。 所以对那些节点而言,诚实的答案不是”IS-IS 发现失败了”,更绝不是一张空拓扑。答案是这台设备无法被 问这个问题,于是该舱的叶子改由 OSPF 发现。
我不打算把这变成一句关于市场的断言,因为两家厂商不构成调查。我能说的有边界,但仍然有用:在我们能够 测试的每一台设备上,那个标准 MIB 都没有被实现,而 Cisco 的企业 MIB 是唯一暴露出这些数据的树。一个 我们能够到的东西全都不实现的标准,不是一个可以据以许下承诺的标准。
这份菜单就是本文最诚实的版本。四项报表在这里打不开,因为它们要读的那个数据库并不存在;每一项 变灰的条目在悬停时都会给出自己的理由,而不是打开一张空表。EIGRP 另有自己的条目,因为它能回答的 是另一个问题。
三种”什么都没有”
把它们并排放好,因为一个对三者一视同仁的产品,至少在其中两者上是在撒谎:
| 缺的是什么 | 诱惑 | 它转而做了什么 |
|---|---|---|
| 没有可加入的数据库 | 编造一个拓扑来源 | 从每台路由器自己的视角重建,并如实标注 |
| 缺的是输入,不是答案 | 假定默认带宽与时延 | 拒绝模拟,并指明这个天花板是我们这边的 |
| 缺的是 MIB 本身 | 返回一张空拓扑 | 说明这台设备无法被询问,并改用它确实提供的那棵树 |
请读中间那一列。它们每一个都会产出一个屏幕,而那个屏幕与”数据真的在那里”时得到的屏幕一模一样。 这正是填补空缺的全部问题所在:输出没有任何办法告诉你,它的哪些部分是被观测到的。
要点
本系列前两篇讲的是在别人的协议里做一个谨慎的客人。这一篇讲的是那些压根不让你进的房间。
在那里做个好客人意味着别的东西:不是找到进门的办法,而是精确说出哪一扇门锁着。一条未解析的 EIGRP 边、一次谢绝的模拟、一台无法被询问的设备。三次拒绝,各自点明自己的成因,没有一次被打扮成答案。
本系列的下一篇,也是最后一篇:那个不等人来问、而是自己找上门来的唯一数据源,以及它改变你可以相信 什么的两种方式。推送,别轮询。