
1. 路由引入为什么会成为故障高发区路由引入这个操作在纸面上看就是把一种路由协议学到的路由灌进另一种路由协议里去。命令通常也就一两行比如在边界设备上敲一条import-route或者redistribute看起来干净利落。但真正在生产网里干过几年的人都知道路由引入是整张网络里最容易埋雷的地方之一很多莫名其妙丢包时通时不通主备切换后业务中断的锅最后追根溯源都落在引入配置上。我先把结论摆出来路由引入本身不是问题问题在于它打破了协议之间的隔离边界。每种路由协议有自己的度量方式、自己的选路逻辑、自己的收敛节奏。OSPF 看的是开销costIS-IS 看的是度量值BGP 看的是属性组合静态路由看的是优先级。当你把 A 协议的路由引入到 B 协议时原本在 A 协议里有意义的度量值到了 B 协议里就失去了参照系如果不做人为干预接收方只能看到一个种子度量所有引入进来的路由度量值都一样选路就变成了随机或者按引入顺序决定这显然不是我们想要的。更麻烦的是双向引入。单向引入最多是度量失真双向引入如果控制不好会直接形成路由环路。A 协议的路由引入到 BB 协议又把这条路由引回 AA 设备一看这条路由我从 B 学到了于是更新自己的路由表再引出去……环路就这么诞生了。这种环路不一定马上表现为 CPU 飙高有时候它表现为路由频繁抖动有时候表现为某几条特定前缀的流量在两个设备之间来回弹跳排查起来非常折磨人。这篇内容我打算围绕路由引入导致的问题这个主题把常见故障场景、根因分析、排查链路和规避方案完整地捋一遍。适合已经有一定路由协议基础、正在做网络割接或者多协议互联的工程师参考也适合刚接触路由引入、想提前避坑的朋友。我会尽量用实际配置和现象说话少讲空泛的理论。提示路由引入在不同厂商设备上的命令关键字不一样华为设备上常见的是import-route思科体系里叫redistribute本文以华为设备的命令风格为主来展开但原理是通用的。2. 度量值失真引入后选路跑偏的典型现场2.1 种子度量缺失导致的所有路由平权先讲一个我印象很深的场景。某次网络调整一台边界设备同时跑 OSPF 和静态路由工程师为了让 OSPF 域内的设备能访问静态路由指向的网段在 OSPF 进程里加了一条import-route static。命令敲完路由确实通了但过了两天业务侧反馈访问某个外部网段时快时慢traceroute 显示路径在两个出口之间来回跳。排查下来原因很典型引入静态路由时没有指定 costOSPF 用了默认的种子度量值 1。而 OSPF 域内原本有一条到达同一目的地的路由cost 是 10。按理说 cost 1 更优应该稳定走引入的这条。但问题在于这条引入的路由是从静态路由来的静态路由本身可能因为链路状态变化被删除又重建每次重建都会触发 OSPF 重新引入路由表项刷新短暂的路由撤销和重新下发就造成了路径抖动。这里的关键认知是引入路由的度量值不是继承来的而是赋予的。静态路由没有 cost 概念OSPF 引入它的时候必须给一个值不给就用默认值。默认值往往偏小会让引入路由在选路中意外胜出压过域内原本规划好的路径。正确的做法是显式指定种子度量并且这个值要经过规划。比如# 在OSPF进程中引入静态路由指定cost为100 ospf 1 router-id 1.1.1.1 import-route static cost 100 type 2这里type 2表示外部路由类型为 2即只比较外部开销不累加域内开销。如果希望路径选择更精细可以用type 1让外部开销加上域内开销一起比较。选 type 1 还是 type 2取决于你的网络设计意图type 2 适合外部路由开销固定、不随域内路径变化的场景type 1 适合希望选路综合考虑内外总开销的场景。2.2 双向引入时的度量值互相污染单向引入的问题相对好控制双向引入才是真正的深水区。假设有两台边界设备 R1 和 R2R1 连接 OSPF 域和 RIP 域R2 也连接这两个域两台设备上都做了双向引入。这时候一条 OSPF 域内的路由会被 R1 引入到 RIPR2 从 RIP 学到这条路由后又引入回 OSPF。如果 R2 引入回 OSPF 的度量值比原始路由更优OSPF 域内的设备就会把 R2 当作更优的下一跳流量绕行。更隐蔽的情况是这条绕回来的路由在 OSPF 里的 cost 被设得很低导致它反过来又压过了原始路由形成路由被自己的副本打败的荒诞局面。这种问题在路由表里看表现为同一目的地的下一跳在 R1 和 R2 之间反复切换或者干脆稳定在一个明显不合理的路径上。规避的核心手段有三个给不同方向、不同协议的引入设置差异化的、经过规划的度量值让绕回来的路由天然处于劣势。使用路由策略route-policy对引入的路由做过滤只引入必要的路由而不是全量引入。在双向引入的边界设备上打标签tag引入时打上标记反向引入时把带特定 tag 的路由过滤掉从机制上切断环路。打 tag 这个做法我个人非常推荐它相当于给路由发了一张身份证让设备能识别出这条路由是从对面协议来的不能再引回去。配置思路大致如下# 定义路由策略匹配tag为100的路由并拒绝 route-policy DENY_TAG100 deny node 10 if-match tag 100 route-policy DENY_TAG100 permit node 20 # OSPF引入RIP路由时打tag 100 ospf 1 import-route rip 1 tag 100 route-policy DENY_TAG100这样从 RIP 引入到 OSPF 的路由都带 tag 100当 OSPF 的路由要引回 RIP 时策略里把 tag 100 的路由拒掉环路就被切断了。2.3 度量值类型选错引发的次优路径还有一个容易被忽略的点OSPF 外部路由的 type 1 和 type 2 选择。很多工程师配引入的时候随手写个type 2或者干脆不写默认就是 type 2结果在某些拓扑下选出了次优路径。举个具体的例子。OSPF 域内有两条路径到达边界设备 R1路径 A 经过两台设备总 cost 20路径 B 经过一台设备总 cost 10。R1 上引入了一条外部路由种子度量设为 50。如果这条外部路由是 type 2那么域内设备比较的是外部开销 50两条路径的外部开销一样于是比较到 R1 的域内开销路径 B 胜出走 cost 10 的路径总开销 501060。如果设成 type 1那么路径 A 的总开销是 502070路径 B 是 501060还是路径 B 胜出。这个例子里两者结果一样但如果种子度量设得很大比如 200type 2 下两条路径外部开销都是 200还是比域内开销type 1 下路径 A 是 220路径 B 是 210依然路径 B 胜出。真正出现差异的场景是外部路由从多个边界设备引入且各边界设备的种子度量不同。这时候 type 2 只看外部度量可能选了一个域内路径很远但外部度量很小的边界设备type 1 则会综合考虑选出总开销最优的路径。所以选 type 1 还是 type 2本质上是在回答你更信任外部度量还是更信任域内度量这个问题。我的经验是如果外部路由的度量值有明确含义且可信用 type 2如果外部度量只是随便设的种子值用 type 1 让域内开销参与决策更稳妥。3. 路由环路双向引入最危险的后果3.1 环路是怎么一步步形成的路由环路的形成往往不是一步到位的而是一个渐进的过程。我用一个简化但真实的拓扑来说明。假设有三台设备R1 在 OSPF 域R2 是边界设备同时跑 OSPF 和 IS-ISR3 在 IS-IS 域。R2 上做了双向引入。第一步OSPF 域内有一条路由 10.1.1.0/24R2 从 OSPF 学到它通过引入发布到 IS-IS。第二步R3 从 IS-IS 学到 10.1.1.0/24如果 R3 也是一台边界设备比如它同时连了另一个 OSPF 域它可能把这条路由又引入回 OSPF。第三步R2 从 OSPF 又学到了 10.1.1.0/24但这次是从 R3 那边学来的下一跳指向 R3。如果 R2 引入到 IS-IS 的度量值比 R3 引入回 OSPF 的度量值更优R2 就会把下一跳更新为 R3然后再次引入到 IS-IS……环路形成。这个过程中每一台设备单独看自己的配置都没错问题出在组合效应上。这也是路由引入故障难排查的根本原因它不是某一条命令写错了而是多条正确命令叠加出了错误结果。3.2 用 tag 和路由策略切断环路的完整配置切断环路最可靠的手段就是 tag route-policy 的组合。我把它拆成三个动作动作一引入时打 tag。在 R2 上从 OSPF 引入到 IS-IS 的路由统一打上 tag 10。isis 1 import-route ospf 1 tag 10动作二反向引入时过滤带 tag 的路由。在 R2 上从 IS-IS 引入回 OSPF 时把 tag 10 的路由拒掉。route-policy OSPF_DENY_ISIS deny node 10 if-match tag 10 route-policy OSPF_DENY_ISIS permit node 20 ospf 1 import-route isis 1 route-policy OSPF_DENY_ISIS动作三在 R3 上做同样的处理。如果 R3 也做双向引入它也需要类似的 tag 机制确保从 IS-IS 引入到 OSPF 的路由不会带着IS-IS 来源的标记被引回去。这套机制的逻辑是每条路由在跨越协议边界时都会被标记来源任何试图把带标记的路由引回原协议的操作都会被拒绝。这样即使拓扑再复杂环路也无法形成。注意tag 的值需要在全网规划不同协议、不同方向用不同的 tag避免冲突。我一般习惯用两位数区分协议比如 10 代表 OSPF20 代表 IS-IS30 代表 RIP用个位数区分方向。3.3 环路已经形成后的应急处理如果环路已经形成业务正在受影响第一优先级是止损。我的处理顺序是这样的先确认环路范围。在疑似环路的设备上看路由表找那些下一跳指向不该指向的设备的路由。比如 OSPF 域内的路由下一跳却指向了 IS-IS 域的边界设备这就是明显异常。临时断开一条引入方向。比如把 R2 上从 IS-IS 引入到 OSPF 的配置临时注释掉观察路由是否稳定。如果稳定了说明环路就在这个方向。在受影响设备上清除路由表并重新收敛。有时候路由表里残留了错误条目光改配置不够需要reset ospf process或者reset isis process强制重新收敛。这个操作有风险会短暂中断业务要在业务低峰期做。修复配置后逐步恢复。先把 tag 和 route-policy 配好再恢复引入观察路由表是否稳定。这里有个经验环路故障的排查一定要先看路由表再看配置。因为配置是静态的路由表是动态的环路的表现全在路由表的异常条目里。我见过有人一上来就翻配置文件翻了半天没发现问题其实路由表里早就写明了异常下一跳。4. 引入范围失控全量引入带来的连锁反应4.1 为什么全量引入是个坏习惯很多工程师配引入的时候图省事直接import-route static或者import-route direct把整张路由表灌进另一个协议。在小型网络里这没什么问题但在中大型网络里全量引入会带来三个连锁反应。第一个反应是路由表膨胀。假设 OSPF 域内有 5000 条路由全量引入到 BGP 后BGP 邻居要承载这 5000 条路由如果对端还有多个邻居路由更新量会成倍增加。设备的内存和 CPU 都要为这些路由买单收敛时间也会变长。第二个反应是故障域扩大。原本 OSPF 域内的某条路由抖动只影响 OSPF 域。全量引入后这条路由的抖动会传递到 BGP 域引发 BGP 更新甚至触发 BGP 邻居震荡。一个局部问题被放大成了全局问题。第三个反应是选路不可控。全量引入意味着你对引入哪些路由、不引入哪些路由失去了控制权。有些路由本不该出现在另一个协议里比如某些管理网段、某些实验性路由全量引入后它们就泄漏过去了可能引发意想不到的选路问题。4.2 用 route-policy 做精细化引入正确的做法是按需引入用 route-policy 精确控制引入范围。比如只引入特定的几个网段# 定义匹配特定网段的路由策略 route-policy IMPORT_SPECIFIC permit node 10 if-match ip-prefix ALLOW_LIST # 定义IP前缀列表 ip ip-prefix ALLOW_LIST index 10 permit 10.1.0.0 16 ip ip-prefix ALLOW_LIST index 20 permit 10.2.0.0 16 # 引入时应用策略 ospf 1 import-route static route-policy IMPORT_SPECIFIC这样只有 10.1.0.0/16 和 10.2.0.0/16 会被引入其他静态路由不受影响。策略的粒度可以做到很细比如按下一跳、按出接口、按 tag、按 community 等维度过滤。我个人的习惯是任何引入操作都必须带 route-policy哪怕当前只需要引入全部路由也要写一个 permit 全部的策略。这样做的好处是将来需要收紧范围时只需要改策略不用动引入命令变更风险更小。4.3 引入默认路由的特殊处理默认路由0.0.0.0/0的引入是个特例需要单独拿出来说。很多网络设计里边界设备会向内部协议引入一条默认路由让内部设备把所有未知流量都指向边界。这个操作本身没问题但有几个坑。第一个坑是默认路由被意外覆盖。如果内部协议里原本有一条更精确的默认路由比如指向另一台边界设备引入的默认路由可能因为度量值更优而把它覆盖掉导致流量全部涌向一台设备。第二个坑是默认路由形成环路。如果两台边界设备互相引入默认路由A 的默认路由指向 BB 的默认路由指向 A未知流量就会在两台设备之间来回转发直到 TTL 耗尽。这种环路在 traceroute 里表现为最后几跳在两个 IP 之间反复出现。规避方法是在引入默认路由时明确指定度量值并且确保只有一台设备或一组设备中的主设备引入默认路由。如果必须多台设备引入用 tag 或 route-policy 确保它们不会互相学习对方的默认路由。# 只引入默认路由并指定cost ospf 1 import-route static route-policy DEFAULT_ONLY cost 100 route-policy DEFAULT_ONLY permit node 10 if-match ip-prefix DEFAULT_PREFIX ip ip-prefix DEFAULT_PREFIX index 10 permit 0.0.0.0 05. 收敛速度与路由抖动的隐藏关联5.1 引入路由的收敛为什么比域内路由慢路由引入的收敛速度和域内路由不是一个量级。域内路由的收敛由协议本身的机制保证比如 OSPF 的 SPF 计算、IS-IS 的 PRC 计算通常在秒级甚至亚秒级完成。但引入路由的收敛要经过源协议感知变化 → 更新路由表 → 触发引入 → 目标协议重新计算 → 下发路由这一整条链路每一环都有延迟。更关键的是引入路由的收敛往往依赖定时器。比如 OSPF 引入静态路由静态路由本身没有协议报文它的变化只能靠路由表的变化来触发。如果静态路由因为链路故障被删除OSPF 需要等到下一次路由表扫描才能感知这个间隔可能是几秒甚至几十秒。在这段时间里OSPF 域内的设备还在用旧的路由转发流量黑洞就产生了。5.2 用 BFD 和快速收敛机制缩短中断时间要缩短引入路由的收敛时间可以从两个层面入手。层面一让源协议快速感知变化。如果引入的是静态路由考虑用 BFD双向转发检测关联静态路由链路故障时 BFD 能在毫秒级感知并删除静态路由从而触发引入更新。# 静态路由关联BFD ip route-static 10.1.1.0 24 192.168.1.1 bfd enable层面二让目标协议快速收敛。在 OSPF 里可以调整 SPF 计算定时器在 IS-IS 里可以调整 LSP 生成和 CSNP 定时器让协议对路由变化的响应更快。但这些定时器的调整要谨慎调得太激进会增加 CPU 负担可能引发震荡。# OSPF SPF定时器调整谨慎使用 ospf 1 spf-schedule-interval 1 50 100这行的含义是首次 SPF 计算延迟 1 秒两次 SPF 之间最小间隔 50 毫秒最大间隔 100 毫秒。调整前一定要在测试环境验证生产环境直接改可能适得其反。5.3 路由抖动抑制防止引入路由反复刷新如果引入的路由本身不稳定比如源协议的路由频繁抖动引入到目标协议后会造成目标协议的路由表反复刷新严重时引发协议震荡。这时候需要路由抖动抑制route dampening机制。OSPF 本身没有抖动抑制功能但可以通过 route-policy 配合定时器间接实现。BGP 有原生的 dampening 功能可以对频繁抖动的路由进行惩罚抑制其发布。# BGP路由抖动抑制 bgp 100 dampening 15 750 2000 60这行的含义是路由撤销的惩罚值为 750抑制阈值为 2000重用阈值为 750 的一半即 375最大抑制时间为 60 秒。参数需要根据网络实际情况调整设得太严会把正常的路由变化也抑制掉。我的经验是引入路由的稳定性取决于源协议的稳定性。如果源协议本身就不稳定先解决源协议的问题而不是在引入侧加各种抑制。抑制只是治标治本还得从源头抓起。6. 排查路由引入问题的完整链路6.1 从现象到根因的排查顺序路由引入问题的排查我总结了一个固定的顺序基本能覆盖 90% 的场景。第一步确认现象。是丢包、是时通时不通、是路径绕行、还是完全不通不同的现象指向不同的问题类型。丢包通常和黑洞路由有关时通时不通通常和路由抖动有关路径绕行通常和度量值有关完全不通通常是引入没生效或者被策略拒了。第二步看路由表。在受影响设备上display ip routing-table看目标网段的路由是否存在、下一跳是否合理、度量值是多少。如果路由不存在说明引入没生效如果下一跳异常说明选路有问题如果度量值异常说明种子度量没设对。第三步看引入配置。display current-configuration找到引入命令确认引入的协议、引入的策略、引入的度量值。重点看 route-policy 是否匹配、tag 是否正确。第四步看协议邻居和数据库。如果引入配置没问题但路由没出现可能是协议邻居没建立或者路由在协议数据库里但没被引入。display ospf peer、display isis peer、display bgp peer确认邻居状态display ospf lsdb、display isis lsdb确认路由是否在数据库里。第五步抓包验证。如果以上都正常但问题依旧在边界设备上抓包看引入的路由是否真的被发布出去了对端是否收到了。这一步能排除配置看起来对但实际没生效的情况。6.2 几个高频问题的快速定位表现象可能原因快速验证方法引入的路由完全没出现引入命令未生效或策略拒绝检查 route-policy 匹配条件临时去掉策略测试路由出现但下一跳异常度量值设置不当或双向引入污染对比不同来源的路由度量值检查 tag路由频繁抖动源协议不稳定或收敛定时器过激查看源协议的路由变化频率检查定时器配置流量绕行种子度量值过优或 type 选错调整种子度量值切换 type 1/type 2 对比默认路由环路多台设备互相引入默认路由检查默认路由的下一跳是否指向对方这张表是我在实际排查中总结的基本上拿到现象就能缩小范围。当然实际情况可能更复杂多个问题叠加的情况也不少见这时候就需要按顺序逐个排除。6.3 一个真实排查案例的完整复盘最后分享一个我亲身经历的案例。某次割接后业务反馈访问某外部网段时延从 10ms 涨到了 80ms。排查过程如下先看路由表发现目标网段的路由存在但下一跳指向了一台平时不承载该流量的边界设备。对比两台边界设备的引入配置发现新割接的设备上引入静态路由时没有指定 cost用了默认值 1而原设备的引入 cost 是 100。结果新设备的路由因为 cost 更优被选中但新设备的出口链路质量较差导致时延升高。修复方法很简单在新设备的引入命令上补上cost 100让两台设备的引入度量值一致然后通过域内开销决定选路。改完后时延恢复正常。这个案例的教训是引入路由的度量值必须全网统一规划不能各配各的。哪怕当前看起来没问题一旦拓扑变化度量值的不一致就会暴露出来。我现在做任何引入配置都会先画一张度量值规划表把每个引入点、每个方向的度量值都定好再动手配置。7. 引入配置的规划习惯与长期维护7.1 引入前的规划清单在动手配引入之前我建议先回答清楚这几个问题引入哪些路由全量还是按需按需的话用 ip-prefix 还是 tag 还是 community 来匹配引入的度量值是多少种子度量值定多少type 1 还是 type 2这个值和其他引入点是否协调是否需要打 tag打什么 tag反向引入时如何过滤是否需要双向引入如果双向环路怎么防如果单向反向流量怎么走引入的路由稳定性如何源协议是否稳定是否需要抖动抑制收敛时间要求是多少是否需要 BFD 或快速收敛机制把这几个问题回答清楚配置就是水到渠成的事。跳过规划直接配出问题的概率极高。7.2 引入配置的文档化与变更管理路由引入的配置有个特点它散落在各个设备的各个协议进程里很难一眼看全。今天在 R1 的 OSPF 里加一条引入明天在 R2 的 BGP 里加一条引入时间长了没人记得清楚全网有多少个引入点、每个引入点的策略是什么。我的做法是维护一份引入配置台账记录每个引入点的设备、协议、方向、匹配策略、度量值、tag。每次变更都更新台账割接前对照台账检查。这份台账在排查问题时价值极高能快速定位到相关的引入点不用一台台设备去翻配置。台账的格式可以很简单一个表格就够了设备源协议目标协议匹配策略度量值Tag备注R1staticOSPFIMPORT_SPECIFIC10010引入办公网段R2OSPFIS-ISALLOW_LIST5020引入核心网段R3IS-ISBGPDENY_TAG20--反向引入过滤tag207.3 定期审计引入配置的必要性网络是活的引入配置也需要定期审计。我一般每季度做一次引入配置的审计重点看三件事第一有没有多余的引入。有些引入是临时加的用完忘了删时间长了就成了隐患。审计时逐条确认引入是否还有必要没必要的删掉。第二度量值和 tag 是否还符合规划。网络调整后原来的度量值规划可能已经过时需要重新评估。tag 的分配也可能因为新增协议而冲突需要重新规划。第三route-policy 是否还有效。策略里匹配的 ip-prefix、community、tag 可能因为网络变化而失效导致策略实际不生效或者误匹配。审计时要验证策略的匹配结果是否符合预期。审计这个事听起来麻烦但比起出故障后熬夜排查这点时间投入太值了。我见过太多故障是因为一条三年前临时加的引入配置没删导致的这种坑完全可以通过定期审计避免。路由引入这个技术点说难不难说简单也绝不简单。它的难点不在于命令本身而在于对全网路由流向的理解和规划。每一条引入命令背后都应该有明确的意图和经过验证的度量值设计。把规划做在前面把 tag 和策略用起来把台账维护好路由引入就能从故障高发区变成可控的常规操作。我在实际项目中踩过的坑基本都逃不出上面讲的这几类希望这些经验能帮你少走点弯路。