
上个月被拉去看一个机房的 OSPF 邻居表。六台核心交换机挂在同一对堆叠的二层设备上跑在同一个广播域里show ip ospf neighbor一敲DR 是一位两年前就该退役的老设备上行链路只有千兆其他几台都是双万兆捆绑。问了一圈没人配过优先级全是默认值 1谁先上电谁当 DR这台老机器因为一次计划外断电后最先恢复位置一坐就是两年。这个场景里冒出来的两个缩写就是本文要拆开讲的东西多路访问网络里的 DR 和 BDR。它们不是一条命令也不是一个开关而是 OSPF 在一段共享介质上建立的一套代言人机制——谁负责汇总这个网段的拓扑、谁负责把变化转发给所有人、谁在代言人挂掉之后立刻顶上。搞不清楚这套机制你会在排错时反复怀疑链路、怀疑配置、怀疑设备唯独怀疑不到选举上。这篇内容面向已经会敲 OSPF 基础配置、但在多路访问环境里踩过坑或者正在做网络设计的人从选举的判定链条讲到接口优先级怎么钉、网络类型怎么选、邻居卡在 2WAY 到底该不该管最后落到设计层面该不该人为干预。命令以 Cisco IOS 语法为准思路通用。1. 多路访问网络里为什么非得推一个发言人出来1.1 从 n(n-1)/2 这个数字说起先算一笔账。假设一段广播网络上有 10 台路由器如果要求两两之间都建立完整的邻接关系、同步链路状态数据库那需要维护的邻接关系数量是 10×9/2 45 条。每台路由器都要向另外 9 台分别发送 Hello、发送 LSA 更新、等待确认、维护重传队列。20 台就是 190 条50 台是 1225 条。这个增长曲线不是线性的是平方级的。OSPF 的设计者很清楚这件事。链路状态协议的核心开销不在于算路而在于把变化可靠地通知到所有该知道的人。点对点链路上只有两端天然只有一条邻接关系没什么可优化的但以太网、帧中继这类共享介质上只要设备数量稍微上去一点泛洪就会变成灾难。所以协议规定在具备广播能力或者多路访问能力的网络上先选出一台指定路由器Designated RouterDR和一台备份指定路由器Backup Designated RouterBDR所有非 DR/BDR 的路由器DROTHER只和这两台建立完全邻接DROTHER 之间停留在 2WAY 状态。这一步把邻接关系的数量从 n(n-1)/2 压到了 2n-3 的量级。10 台设备只需要 17 条左右的完全邻接而不是 45 条。省下来的不只是 CPU 和带宽还有收敛时的抖动——一个网段里某台接入设备反复起落只要能保证 DR 和 BDR 不动整个区域的 SPF 重算范围就被限制住了。注意DR/BDR 是接口级的概念不是设备级。同一台路由器在 VLAN 10 的接口上可能是 DR在 VLAN 20 的接口上可能是 DROTHER在一条串口上根本没有角色。排错时一定要落到具体接口去看别拿show ip ospf的全局输出下结论。1.2 DR、BDR、DROTHER 三种角色的实际分工角色分工不是名义上的它直接决定了组播地址的监听行为和 LSA 的产生权。角色监听组播地址与谁建立 FULL 邻接产生 Type 2 LSAHello 中的 DR/BDR 字段DR224.0.0.5 与 224.0.0.6所有邻居是填自己的接口地址BDR224.0.0.5 与 224.0.0.6所有邻居否仅接替后产生填 DR 地址与自己地址DROTHER仅 224.0.0.5仅 DR 与 BDR否填已知的 DR 与 BDR 地址224.0.0.5 是 AllSPFRouters所有运行 OSPF 的接口都监听224.0.0.6 是 AllDRouters只有 DR 和 BDR 监听。DROTHER 要把 LSU 送给 DR 和 BDR就发到 224.0.0.6DR 要把更新泛洪给所有人就发到 224.0.0.5。这个分流设计的妙处在于DROTHER 之间根本不需要互相发送更新因为它们的状态本来就只有 2WAY数据库同步的责任全部压在 DR 身上。BDR 平时看起来什么都不干它不产生 Type 2 LSA也不主动泛洪。但它在做一件很重要的事——全程和 DR 保持完全同步。DR 一挂BDR 立刻转正因为数据库里什么都有不需要重新同步收敛时间几乎为零。这也是为什么选举时协议坚持先选 BDR 再选 DR而不是反过来。1.3 2类LSADR替整个网段代言的方式理解 DR 的价值绕不开 Type 2 LSA也就是 Network LSA。在 OSPF 的 SPF 计算里一段广播网络被抽象成一个伪节点pseudo-node这个伪节点就是由 DR 代表的。DR 会产生一条 Type 2 LSALink State ID 是自己的接口 IP 地址里面列出这个网段上所有与之建立完全邻接的路由器包括 DR 自己的 Router ID。所有路由器在算 SPF 时先把自己连到伪节点上再从伪节点连到其他路由器。这样一来网段内部的拓扑细节被压缩成一个节点 一组叶子任何一台 DROTHER 的增减只会引起 Type 2 LSA 的重新生成和局部重算不会引发整个区域内所有路由器的 Router LSA 连环变化。如果没有 DR每台路由器的 Type 1 LSA 里都要列出网段上所有邻居任何一台设备抖动区域内每一台路由器都要重算 SPF。这就是 DR 存在的根本理由——它不是为了减少邻居数量而是为了把拓扑变化的爆炸半径控制住。用show ip ospf database network能看到这条 LSA 的全貌包括 Advertising Router、LS Age、Seq Number以及下面挂着的 Attached Router 列表。当你怀疑某个网段的路由算错时先看这条 LSA 是否由预期的设备产生再看 Attached Router 是否齐全比盲目查路由表快得多。2. 选举的判定链条优先级、Router ID 和那个40秒的等待窗口2.1 优先级是第一道闸门0是明确的弃权票接口下的ip ospf priority取值范围是 0 到 255默认 1。数值越大越优先。这个参数只影响本接口所在网段的选举不影响其他接口也不影响 Router ID 的产生。值为 0 时含义非常明确这台路由器在这个网段上永不参选 DR 和 BDR。它发出去的 Hello 包里DR 和 BDR 字段都填 0.0.0.0等于举手声明我不参加。这个特性在实际工程里用得很多——把边缘接入设备、服务器网关、或者单纯的过路设备设成 0让它们老老实实当 DROTHER避免设备重启后意外抢到 DR 位置。举一个我实际遇到的例子。某园区网的核心层和接入层跑在同一个 OSPF 区域接入层交换机有十几台全部默认优先级 1。有一次批量升级固件十几台设备先后重启最先起来的那台接入交换机因为接口先 UP抢到了 DR。结果整个 VLAN 里所有核心之间的流量都要绕到这台接入交换机上同步数据库它的 CPU 直接被打到 80% 以上OSPF 邻居反复超时。后来把接入层的接口统一配成ip ospf priority 0问题再没复现过。配置本身很简单interface GigabitEthernet0/1 ip address 10.10.10.2 255.255.255.0 ip ospf priority 0但要记住优先级改完不会立即生效后面 3.3 节会详细说这个时机问题。2.2 优先级打平之后比的是 Router ID优先级相同的情况下比较 Router ID大者胜。这条规则听起来简单坑却不少因为很多人对Router ID 是什么存在误解。Cisco 设备选择 Router ID 的顺序是手工配置的router-id优先没有手工配置时取所有 Loopback 接口中最高的 IP 地址连 Loopback 都没有才取所有活动物理接口中最高的 IP 地址。注意最后一条——是活动接口但如果 OSPF 进程启动时某个接口还没 UP它的地址不会参与比较等接口后来 UP 了Router ID 也不会自动改。这就引出一个非常隐蔽的问题一台设备重启时如果它的 Loopback 接口因为某些原因起得比物理接口晚OSPF 进程可能已经用物理接口地址定下了 Router ID后面 Loopback 起来也没用。表现就是这台设备在所有邻居眼里的 Router ID 和你预期的完全不一样选举结果自然也不一样。更麻烦的是 Router ID 冲突。两台设备如果手工配了相同的router-id或者在接口地址规划上撞了车邻居关系会反复建立又断开日志里刷的是%OSPF-4-DUP_RTRID_NBR。这类问题在虚拟化环境里特别常见——克隆出来的虚拟机模板带着相同的 Loopback 地址就上线了。我的习惯是所有参与 OSPF 的设备无条件手工配置router-id取值用规划好的 Loopback 地址绝不放任它自动选。多打一行命令省掉未来若干个深夜。router ospf 1 router-id 10.0.0.12.3 先选BDR再选DR这个顺序不是随便定的选举的实际过程比大多数人想的要绕。当一个接口刚启用 OSPF或者网段上原本没有 DR 需要重新选举时路由器不会立刻投票而是启动一个 Wait Timer广播网络上等于 Dead Interval也就是 40 秒Hello 10 秒 × 4。在这 40 秒里所有参与选举的路由器都在自己的 Hello 包里把 DR 字段填成自己的接口地址BDR 字段填 0.0.0.0意思是我自荐当 DR。40 秒一到每台路由器检查自己收到的所有 Hello 包按下面的顺序判定先看有没有人声明自己是 BDR。在所有没有声明自己是 DR的路由器里选优先级最高的当 BDR优先级相同比 Router ID。再看有没有人声明自己是 DR。同样按优先级、Router ID 排序胜出者当 DR。如果某一台路由器同时被选为 DR 和 BDR比如它自荐了 DR 但最终只能当 BDR则 BDR 位置重新按规则补选。这个顺序的关键在于DR 的候选池是所有没当上 BDR 的路由器而不是所有路由器。所以理论上存在一种看似荒谬但完全合规的结果——优先级最高的那台反而当了 BDR优先级第二的当了 DR。这种情况在等待窗口内 Hello 包丢失、或者设备加入时间错开时确实会出现。我在一个跨厂商互联的项目里就见过某台设备因为接口刚 UP 就发了 Hello自荐 DR而另一台优先级更高的设备晚了两秒才开始发 Hello等它加入时对方的 DR 声明已经被其他设备认可了。最终高优先级设备只能去竞争 BDR。这种结果不是 bug是协议的先到先得 非抢占特性共同作用的产物。2.4 非抢占后来的高优先级设备只能看着这是 DR/BDR 选举里最容易被误解的一条选举结果一旦确定不会因为新加入一台更高优先级的路由器而改变。具体表现是一台优先级 200 的设备接入已经稳定运行的网段它会在 Hello 里声明自己是 DR但现有的 DR 不会退位。几个 Hello 周期之后这台新设备发现网段上已经有一个公认的 DR于是放弃自荐退回 DROTHER。如果此时 BDR 位置是空的它可以去当 BDR如果 BDR 也已经有人它就只能是 DROTHER邻居状态显示为2WAY/DROTHER。想要强行改变结果只有三条路在现有 DR 上执行clear ip ospf process让整个网段重新选举把现有 DR 的接口shutdown再no shutdown强制它放弃角色把现有 DR 的接口优先级改成 0然后同样需要重启进程或者等它失效才生效。第一种最常用但代价最大——clear ip ospf process会清空整个 OSPF 进程的所有邻居和数据库不只是这一个接口。在一台承载几十个 VLAN 的核心设备上执行这条命令等于把整个路由域重启一遍。生产环境里做这件事务必先确认有没有备用路径、有没有 VRRP/HSRP 之类的网关冗余在兜底。提示如果你的目标是让某台设备成为 DR正确做法不是把它的优先级调高然后等着而是把所有设备的优先级都规划好然后在一个维护窗口里统一重启 OSPF 进程。优先级决定的是选举结果不是切换动作。3. 把某台设备钉在DR位置上配置流程与验证方法3.1 动手之前先把现场信息摸清楚直接上去改优先级是最容易出问题的做法。我习惯先做三件事确认当前角色、确认候选者清单、确认业务影响面。第一条命令看接口级状态show ip ospf interface GigabitEthernet0/1输出里会明确给出Designated Router (ID)和Backup Designated router (ID)注意括号里写的是 ID也就是 Router ID不是接口地址。同时还能看到Timer intervals configured, Hello 10, Dead 40, Wait 40, Retransmit 5这个 Wait 40 就是选举等待窗口直接印证了前面说的机制。最后一行Neighbor Count is 5, Adjacent neighbor count is 2也很关键——如果邻居数是 5 而邻接数只有 2说明有三台是 DROTHER处于 2WAY这是正常的。第二条命令看邻居清单show ip ospf neighbor Neighbor ID Pri State Dead Time Address Interface 10.0.0.2 1 FULL/DR 00:00:38 10.10.10.2 Gi0/1 10.0.0.3 1 FULL/BDR 00:00:36 10.10.10.3 Gi0/1 10.0.0.4 1 FULL/DROTHER 00:00:39 10.10.10.4 Gi0/1 10.0.0.5 1 2WAY/DROTHER 00:00:37 10.10.10.5 Gi0/1这张表一眼就能看出谁是什么角色。Pri列是邻居的接口优先级改完之后要确认这一列真的变了而不是只看本地配置。第三条是评估影响。如果当前 DR 承载着几十个网段的数据库同步贸然切换会导致短暂的路由黑洞。稳妥的做法是先确认 BDR 是谁、BDR 的资源和带宽是否够用、切换窗口内有没有关键业务。这些判断没法靠命令完成得看网络的实际承载情况。3.2 接口优先级与全局 Router ID 的配置细节配置分两个层面别搞混。接口层面控制的是这台设备在这个网段上的参选意愿interface GigabitEthernet0/1 ip ospf priority 200全局层面控制的是平局时谁赢router ospf 1 router-id 10.0.0.1实际规划中我通常按这样的原则分配优先级设备角色接口优先级说明核心层主设备200期望成为 DR核心层次设备150期望成为 BDR汇聚层设备100参与但不主导接入层设备0永不参选服务器网关/边缘接口0减少无谓泛洪这个梯度留出了足够的余量未来加设备时不用重新规划。不要用 255 和 254 这种贴边的值一旦有临时设备需要插队就没空间了。另外一个容易被忽略的点ip ospf priority只对广播和 NBMA 网络类型有效。如果接口是 point-to-point 类型这条命令配了也不起作用因为点对点链路上根本不选举。有人在串口上配了优先级发现没效果回头怀疑设备 bug其实就是网络类型不对。3.3 改完为什么没生效重启进程的时机与代价优先级改完show running-config里能看到show ip ospf interface里也能看到新值但邻居表里的角色纹丝不动。这不是配置没生效是选举不重来。前面说过DR/BDR 是非抢占的。改优先级只是改变了下一次选举时的投票权重不会触发一次新的选举。要让它生效必须让当前 DR 或 BDR 失效。最直接的做法clear ip ospf process系统会弹一个确认提示输入 yes 之后OSPF 进程重启所有邻居断开重来。在一个只有几台设备的实验环境里这没什么但在生产网关上执行之前务必想清楚三件事这台设备上跑着几个 OSPF 进程clear ip ospf process不带进程号会清掉所有进程。有没有静态路由或者备用协议能在这几十秒内兜住流量邻居设备会不会因为同时重连而产生短暂的 CPU 峰值更精细一点的做法是指定进程号clear ip ospf 1 process只清进程 1影响范围小一些。如果设备上还跑着第二个 OSPF 实例用于其他业务这一条能救你一命。还有一种温柔的做法先在一台非关键设备上把优先级调成 0等它退出 BDR 竞争再调另一台逐步引导。这个过程慢但每一步的影响都可控适合对中断极度敏感的场景。缺点是整个过程中间态可能不太符合设计预期需要有人盯着。我个人的经验是优先级规划应该在上线前就做完而不是运行两年后再来纠正。一旦网络稳定运行任何一次强制重选都是一次风险事件。真要做就约在业务低谷提前通知准备好回滚配置。3.4 三条验证命令与它们的预期输出改完之后怎么确认真的成了我固定用三条命令交叉验证。第一条看接口角色show ip ospf interface GigabitEthernet0/1 | include Designated期望输出里Designated Router (ID)后面跟的应该是本机的 Router ID。第二条看邻居状态show ip ospf neighbor期望看到其他设备对本机的认知是FULL/DR或FULL/BDR具体取决于本机角色。注意这里的 State 列是邻居眼中的本机不是本机眼中的邻居——这个视角很容易搞反排错时尤其要注意。第三条看 Type 2 LSA 是否由本机产生show ip ospf database network如果本机是 DR应该能看到一条 Link ID 等于本接口地址的 Network LSAAdvertising Router 等于本机 Router ID下面 Attached Router 列表里挂着网段上所有建立完全邻接的设备。三条都对上才算真正完成。只改配置不看验证等于没做。4. 网络类型才是选举的舞台广播、NBMA、点对点该怎么选4.1 五种网络类型的默认行为对照OSPF 接口的网络类型决定了三件事要不要选举、用什么方式发现邻居、Hello 和 Dead 定时器取什么值。Cisco 平台支持五种默认行为和适用场景差别很大。网络类型是否选举邻居发现Hello/Dead典型场景broadcast是组播 224.0.0.510/40以太网、VLAN 接口non-broadcast是单播需手工 neighbor30/120帧中继主接口、X.25point-to-point否组播 224.0.0.510/40串口、点对点子接口point-to-multipoint否组播 224.0.0.530/120星型 Hub-Spoke 拓扑point-to-multipoint non-broadcast否单播需手工 neighbor30/120不支持组播的星型拓扑最容易踩的坑是物理接口类型决定了默认网络类型。一条 Serial 接口默认是 point-to-point一个 Frame Relay 主接口默认是 non-broadcast一个 Ethernet 接口默认是 broadcast。这些默认值在简单拓扑里没问题一旦拓扑变复杂就会出岔子。比如一条千兆以太网点对点互联两台设备直连默认是 broadcast 类型会走完整的 DR 选举流程40 秒等待窗口、Type 2 LSA、伪节点计算一个不少。而这条链路上明明只有两台设备根本不存在多路访问的语义。把它改成 point-to-point邻居立刻变成 FULL没有 DR/BDR没有 40 秒等待收敛更快LSA 更少。interface GigabitEthernet0/1 ip ospf network point-to-point这个优化在大规模数据中心互联里几乎是标配。我见过的每一套 Spine-Leaf 架构层间互联全部是 point-to-point 类型没有人让它在一条两点的链路上跑选举。4.2 NBMA 环境里 hub 必须坐稳 DR帧中继、ATM 这类非广播多路访问网络现在虽然少见但仍有一些专线场景在用而且它的选举逻辑比广播网络更依赖人工干预。NBMA 的核心问题是它没有广播能力OSPF 无法通过组播发现邻居必须手工指定neighbor。默认网络类型是 non-broadcastHello 30 秒、Dead 120 秒、Wait 120 秒。在中心-分支Hub-Spoke拓扑里所有分支设备都只和 Hub 有 PVC分支之间没有直连电路。这种拓扑下如果让分支设备当了 DR会发生什么DR 需要和网段上所有路由器建立完全邻接但分支之间根本通不了邻接关系建不起来整个网段的数据库同步就废了。所以规则很明确Hub 必须是 DR而且必须是唯一有资格当 DR 的设备。配置上分两步。Hub 侧把优先级调到最高interface Serial0/0 ip ospf network non-broadcast ip ospf priority 200分支侧把优先级设成 0彻底放弃参选interface Serial0/0 ip ospf network non-broadcast ip ospf priority 0然后 Hub 上把所有分支的地址手工指出来router ospf 1 neighbor 10.1.1.2 neighbor 10.1.1.3 neighbor 10.1.1.4分支上只需要指回 Hub 一个地址。这里有个细节如果分支的优先级是 0它不会参与 DR 选举但它仍然需要和 DR 建立完全邻接所以neighbor指向 Hub 就够了。如果分支之间需要互通流量必须经过 Hub 转发这也是 Hub 必须资源充足的原因。4.3 把链路改成 point-to-point 之后发生了什么我做过一次对比测试同一条千兆直连链路分别用 broadcast 和 point-to-point 类型跑观察邻居建立时间和数据库规模。指标broadcastpoint-to-point邻居进入 FULL 的时间约 40 秒等待窗口约 8 秒数据库中的 Type 2 LSA1 条0 条邻居状态显示FULL/DR 或 FULL/BDRFULL/-链路抖动时的 SPF 触发网段内所有路由器仅两端40 秒 vs 8 秒的差距主要来自 Wait Timer。在 broadcast 类型下接口 UP 后必须等满 40 秒才做选举选举完成后才开始交换 DD 包。point-to-point 没有这一步Hello 交换完直接进 ExStart。Type 2 LSA 的差别看着只有一条但在一个几百台设备的大区域里每条 Type 2 LSA 都意味着伪节点参与 SPF 计算累积起来对 CPU 是有实际影响的。更关键的是广播类型下如果两端之一重启另一端会经历邻居超时—重新选举—重新同步的完整流程point-to-point 下只有邻居超时和重新同步没有选举这一步。需要提醒的是改成 point-to-point 之后接口的 Hello/Dead 定时器仍然是 10/40但不再有 Wait Timer。两端必须都改一端改一端不改会导致 Hello 参数不匹配邻居卡在 INIT 或者直接起不来。这个不对称配置是实际排错中非常高频的问题尤其是割接只做了一半的时候。4.4 点对多点与隧道接口的特殊之处point-to-multipoint 类型是为星型拓扑设计的它把一条物理链路逻辑上拆成若干条点对点链路因此不选举 DR/BDR每对邻居独立建立邻接。它的好处是不需要手工配置neighbor用组播就能发现缺点是每条逻辑链路都会产生一条主机路由/32路由表会膨胀。在 GRE 多点隧道mGRE场景里这个特性特别有用。中心节点一个 Tunnel 接口多个分支节点各自建 tunnel 指向中心中心侧把 tunnel 接口配成 point-to-multipoint分支侧也配成 point-to-multipoint全网就能自动建立邻接不需要 DR 选举也不需要手工 neighbor。但这里有个性能陷阱point-to-multipoint 的 Hello 是 30 秒、Dead 是 120 秒收敛速度比 broadcast 慢不少。如果分支数量多、链路质量差邻居超时误判的概率会上升。我见过一个 40 分支的星型网络用默认的 120 秒 Dead每天都有几台分支因为瞬时丢包被判死日志里全是%OSPF-5-ADJCHG。后来把定时器调成ip ospf hello-interval 10和ip ospf dead-interval 40两端同步改抖动才压下去。提示任何修改 Hello/Dead 的操作必须保证同一网段内所有设备的取值完全一致否则邻居关系根本建立不起来。这不是建议是硬性前提。5. 现场排查链路从2WAY卡死到DR频繁漂移5.1 2WAY 到底是正常状态还是故障信号新手看到邻居表里有2WAY/DROTHER第一反应往往是邻居没建起来。这个判断在多数情况下是错的。广播网络中DROTHER 与 DROTHER 之间的邻居状态就是 2WAY这是设计使然不是故障。它们已经互相收到了 Hello确认了对方的存在只是协议规定它们不需要交换完整的数据库。判断标准很简单只要网段上有正常的 DR 和 BDR其他设备显示 2WAY/DROTHER 就是健康状态。真正需要警惕的是全部都是 2WAY。如果所有邻居都停在 2WAY没有任何一个 FULL/DR 或 FULL/BDR说明这个网段上根本没有选出 DR。最常见的原因是所有设备的接口优先级都被配成了 0。这种情况在做过统一把接入层优先级清零操作之后特别容易发生——如果连核心层也被误配成 0整个网段就没人当 DR 了邻居永远停在 2WAY路由学不到。排查路径是这样的show ip ospf interface GigabitEthernet0/1先看Designated Router (ID)那一行是不是0.0.0.0。如果是说明没有 DR。再看本接口的优先级是不是 0。然后再逐台确认邻居的优先级。这个链条走完问题基本就定位了。还有一种少见但确实存在的情况网段上只有一台路由器。这时它会成为 DR但没有任何邻居show ip ospf neighbor是空的接口状态里 DR 字段填的是它自己。有人看到这个会以为配置错了其实完全正常——没有第二台设备选举结果就是它自己。5.2 优先级配了却不生效的三类原因第一类网络类型不对。前面提过point-to-point 和 point-to-multipoint 类型下不选举优先级命令配了也是摆设。用show ip ospf interface看Network Type一栏如果是 P2P 或者 P2MP优先级问题根本无从谈起。第二类改的是错误的接口。一台设备有十几个接口ip ospf priority只作用于配置它的那个接口。有人在本地的 Gi0/1 上配了 200结果发现 Gi0/1 根本没跑 OSPF或者跑 OSPF 的是另一个子接口。用show ip ospf interface brief列出所有参与 OSPF 的接口逐个核对。第三类也是最隐蔽的一类优先级生效了但选举没重来。前面反复说过的非抢占特性。配置本身没问题show ip ospf interface里优先级确实是 200但 DR 还是别人。这时候不需要改配置需要触发一次重新选举。判断方法是看邻居表里的Pri列如果那一列已经是 200而 State 还是 DROTHER那就纯粹是时机问题。这三类原因排查顺序建议从第三类往前查因为它的概率最高而且验证成本最低——只需要看一眼邻居表的 Pri 列。5.3 MTU 不一致卡在 EXSTART 的完整排查过程这件事发生在一次跨机房互联割接里。两端设备配置完全对称优先级、区域、认证、网络类型全部核对过但邻居就是卡在 EXSTART一卡就是几个小时日志里反复刷%OSPF-5-ADJCHG: Nbr ... from EXSTART to DOWN。排查过程我按这个顺序走的第一步确认基础参数。show ip ospf interface对比两端的 Hello/Dead、Area ID、网络类型、认证方式全部一致。第二步确认二层连通性。两端的接口地址能互 ping 通ARP 表正常说明三层可达没问题。第三步抓包看 DD 包。这一步是关键。抓下来的包显示一端发出的 DD 包里 MTU 字段是 1500另一端回应的 DD 包里 MTU 字段是 9000。EXSTART 阶段双方交换的 DD 包里携带 MTU 信息如果发现对方 MTU 比自己大就会拒绝继续邻居关系卡死。根因很快找到了一端是普通千兆接口MTU 1500另一端是新上线的设备接口默认 MTU 配成了 9000之前为存储网络调的负责割接的同事只核对了 IP 和 OSPF 参数没人想到去看 MTU。修复有两个方向。一是把两端 MTU 对齐这是正解但涉及接口重启有中断。二是临时加忽略命令interface GigabitEthernet0/1 ip ospf mtu-ignore这条命令让 OSPF 在 DD 交换时忽略 MTU 差异邻居能正常建立。但要注意它只是让协议装作没看见实际的 MTU 不一致问题依然存在——如果链路上真的跑 9000 字节的大包小 MTU 那一端会丢包或者分片。所以mtu-ignore只适合作为临时手段长期还得把 MTU 统一。注意MTU 不匹配的症状是卡在 EXSTART 或 EXCHANGE日志反复 DOWN和认证失败、Router ID 冲突的症状很像。区分方法是看日志里有没有%OSPF-4-DUP_RTRID_NBR或者%OSPF-5-ADJCHG ... BADSEQ没有的话优先怀疑 MTU。5.4 DR 切换瞬间的流量黑洞与规避手段DR 挂掉BDR 立刻接替这个切换本身很快。但快不等于无感。切换瞬间会发生几件事原 DR 产生的 Type 2 LSA 需要重新生成由新 DR 产生Age 归零Seq Number 重新开始所有 DROTHER 需要和新 DR 重新同步数据库期间如果有流量正在经过原 DR 转发会出现短暂中断。我实测过一个中等规模的广播域8 台路由器DR 强制切换造成的中断大约在 3 到 8 秒之间具体取决于数据库大小和设备的 CPU。这个时间对普通办公网无感对交易类业务就是事故。规避手段有三条按有效性排序第一条不让 DR 挂。给 DR 设备配上冗余电源、冗余上行、双机堆叠从物理层面减少单点故障。这是最根本的。第二条把关键网段的网络类型改成 point-to-point从设计上消灭 DR 这个角色。两点互联的链路本来就不该选举改完之后没有 DR 切换这回事链路断了就是断了恢复就是恢复逻辑简单得多。第三条接受切换但把中断窗口控制在业务可容忍范围内。具体做法是提前把 BDR 的资源配足CPU、内存、上行带宽确保它接替后不会因为负载过高而二次抖动。同时用 BFD 加速故障检测把 Dead 时间从 40 秒压到毫秒级让切换发生得更早、更干脆而不是让流量在一个已经死掉的 DR 上耗着。6. 设计层面的取舍什么时候该人为干预选举6.1 必须手工干预的几种典型场景默认优先级 1 加上谁先起来谁当 DR的机制在小型网络里通常不会出问题因为设备性能差不多谁当都一样。但下面这几种场景不干预就是给自己埋雷。核心与接入混跑同一个广播域。接入层设备数量多、性能弱、重启频繁如果让它们参与选举某次批量重启后很可能由一台接入交换机当上 DR。前面 2.1 节那个 CPU 打到 80% 的案例就是这种情况。解决办法是把接入层全部设为优先级 0。主备核心性能差距明显。主核心是高端框式设备备核心是几年前的型号两者带宽和会话数差好几倍。默认选举有可能让备机当上 DR导致所有跨网段流量都要经过备机同步数据库长期运行在亚健康状态。这时必须用优先级把主机钉在 DR 位置上。存在跨厂商设备。不同厂商对 Router ID 的选取习惯不同自动选举的结果往往不可预测。我参与过一个项目某厂商设备默认用管理口地址当 Router ID而这个地址在所有设备上都是同一网段的不同尾数结果选举结果每次重启都变。最后只能全网手工配router-id加优先级才算稳定下来。有明确的流量路径设计要求。比如要求某个网段的所有流量必须经过防火墙那防火墙直连的那台设备就必须是 DR否则 DROTHER 之间的 2WAY 关系会让部分流量绕过预期的路径。这种情况不干预就是架构缺陷。6.2 用优先级做流量的软牵引DR 除了控制 LSA 泛洪还有一个副作用它是这个网段上所有 DROTHER 的数据库同步源所有 DROTHER 的 LSU 都往它那里送。这意味着 DR 所在设备的接口入向流量会比其他设备高出一截。利用这个特性可以做一些软牵引。比如在双核心架构里你希望主核心承担更多的东西向流量那就让它当 DR同时把它的上行链路配得更宽。这样即使没有策略路由流量也会自然地向主核心倾斜一部分。反过来如果你希望某台设备尽量少承载流量就把它的优先级设成 0让它彻底退出 DR 竞争。它在网段上只做最基本的路由转发不承担任何数据库汇总的职责。这种牵引是软的因为它只影响 OSPF 的数据库同步流量不影响实际的用户数据转发路径。用户数据走哪条路还是由路由表和底层拓扑决定。所以别指望靠调优先级来解决带宽不均的问题那是 QoS 和流量工程该干的事。优先级能做的是把控制面的负载放到你希望的设备上。6.3 广播域规模与DR负担的平衡DR 承担的责任和广播域内的路由器数量成正比。一个网段里有 5 台设备DR 要维护 4 条完全邻接有 30 台就是 29 条。每条邻接都意味着独立的 Hello 定时器、重传队列、数据库副本。30 台设备的广播域DR 的 OSPF 进程内存占用和 CPU 开销会明显高于其他设备。所以设计上有一条不成文的经验单个广播域内的 OSPF 路由器数量尽量不要超过 20 台。超过这个量级考虑用 VLAN 或者子接口做分割把一个大广播域拆成几个小的。这既是 OSPF 的要求也是二层网络本身的要求——广播域太大STP 收敛、ARP 广播、未知单播泛洪都会跟着出问题。另一个角度是要不要让服务器接入端口跑 OSPF。服务器网段通常只有一台路由器网关其他都是主机不参与路由。这种情况下让网关接口跑 OSPF 是可以的但它会成为 DR因为它是唯一的 OSPF 路由器并且周期发送 Hello。如果不希望这些无谓的报文占用带宽用passive-interface把它关掉router ospf 1 passive-interface GigabitEthernet0/2被 passive 的接口仍然会宣告网段但不发 Hello、不建邻居自然也就不参与选举。这个操作在收敛优化里非常常见尤其是那些只有服务器、没有其他路由器的下行接口。最后提一个容易被忽略的细节二层交换机上的 IGMP Snooping。OSPF 的 Hello 发往 224.0.0.5 和 224.0.0.6这些是组播地址对应固定的组播 MAC。如果接入交换机开了 IGMP Snooping 又没有配置 querier这些组播报文可能被当成没人订阅的组播而丢弃表现就是部分邻居时通时不通或者干脆建不起来但 ping 是通的。这个坑我在两个不同的项目里遇到过排查时抓包能看到 Hello 从源发出但对端收不到。解决办法是在 VLAN 上配置 IGMP querier或者干脆关掉 Snooping或者静态绑定组播 MAC。这类问题和 OSPF 配置本身毫无关系但症状和 OSPF 邻居故障一模一样值得在排查清单里留一个位置。我个人在实际操作中的体会是DR/BDR 这套机制理解了为什么要有和什么时候不会重选这两点剩下的大部分问题都能自己推出来。真正难的不是命令而是在一个已经跑了两年的网络里判断某次角色异常到底是历史遗留、是设计缺失还是刚刚发生的一次意外重启造成的。做这类判断靠的不是记命令是心里有一张清晰的选举时序图。