前两天一位做网络集成的朋友给我发消息,说他在实验环境里做了一个OSPF与IS-IS双点双向路由引入的验证,结果发现OSPF域里所有路由器的外部LSA数量几乎翻了一倍。更诡异的是,明明只有两台ASBR,可路由表里同一个前缀却出现了两条外部路由,一条来自源边的R1,另一条居然来自另一台ASBR R2——问我是哪里配错了。
这个现象,就是双点双向路由引入里最经典也最容易踩的坑:路由回馈。只要拓扑里出现两个边界点做双向引入,回馈链路几乎是必然形成的。这篇文章我把成因、复现、解决方案和落地经验一次讲透。无论你是刚学路由引入、正在准备网络割接,还是已经在现网里遇到类似诡异现象,这篇文章都能帮你省下不少排查时间。
1. 先看懂回馈链路:双点双向引入里"最不该出现的转发"
1.1 回馈是怎么一步步形成的
先明确一个概念:路由回馈,全称应该叫"路由被重新引入回源协议域"。它和我们常说的路由环路有关联,但又不完全一样。环路是数据包转发层面的死循环,而回馈是路由信息层面的"回流污染"——回馈严重到一定程度,才会演变成真正的环路和路由震荡。
我用OSPF和IS-IS双点双向引入来拆解。假设R1、R2同时运行两种协议,且都配置了双向引入,也就是:
- R1把OSPF路由引入IS-IS,也把IS-IS路由引入OSPF
- R2同样把OSPF路由引入IS-IS,也把IS-IS路由引入OSPF
现在OSPF域内有一条前缀1.1.1.1/32,由R1在OSPF里发布。这条路由在R1上被import-route ospf引入到了IS-IS域,通过IS-IS的LSP传播,R2学到了它。到这里一切正常。
问题出在第二步。R2上面配置了"把IS-IS路由引入OSPF",所以R2在IS-IS域里学到的这条1.1.1.1/32,会被当作一条普通的IS-IS外部路由,再次注入OSPF域。于是OSPF域里出现了两条1.1.1.1/32的外部LSA:一条是R1最初发布的,另一条的通告者变成了R2。
这就是回馈的本质:路由在引出源协议域的那一刻,原始协议的身份信息已经被"格式化"了。IS-IS不会关心这条路由的娘家在OSPF,它只知道自己学到了一条外部路由;OSPF再次接收时,看到的只是一个"由R2新引入的外部路由",完全不知道它原本就来自自己域内。
1.2 为什么"双点"和"双向"缺一不可
我把这个坑拆开讲,是因为很多初学者会问:我只在一台路由器上做双向引入,为什么没有出现回馈?
单点双向引入确实不会形成回馈。因为只有一台ASBR时,路由引出去再引回来,本质上还是同一台设备在处理,它至少能从接口、邻居、路由表状态上判断出这条路由是自己刚引出去的,不会傻到再引回来一遍形成循环。回馈需要两个点参与:一台引出去,另一台引回来,这样才能在协议域之间搭起一条完整的闭环。
双向则是另一个必要条件。如果只有R1做OSPF到IS-IS的引入、R2做IS-IS到OSPF的引入,那么R1引出的OSPF路由会经过IS-IS域到达R2,再由R2引回OSPF。这同样构成回馈。也就是说,严格来说并不需要每一台ASBR都做双向引入,只需要存在"A引出去、B引回来"的交叉路径。只不过实际工程里,为了两个方向的互通性,大家几乎都是两台设备同时做双向引入,所以"双点双向"就成了这个问题最典型的发生场景。
1.3 回馈带来的三种典型危害
回馈不是多了一条路由那么简单,它的危害体现在三个层面。
第一,外部路由表膨胀。OSPF域里每个路由器都会多出一批外部路由表项,原本只有几条外部路由,翻倍甚至翻几倍。设备内存和路由表容量被白白浪费。
第二,次优路径。回馈路由进入OSPF后,会参与选路。如果原始那条1.1.1.1/32是OSPF域内路由,优先级是10,回馈路由是外部路由,优先级是150,正常情况下大家还是会走原始路径,回馈路由只是躺在那不生效。但如果原始路由本身就是外部引入的Type 5路由,优先级同样是150,那两台ASBR就要比metric了。一旦回馈路径的metric算出来比原始路径更小,全网的流量就会莫名其妙被引到对端ASBR去,绕一个大圈。
第三,LSA反复刷新导致全网震荡。这是最隐蔽也最麻烦的。回馈路由在OSPF域里传播后,R1会再次学到那条被R2引回的相同前缀路由。R1的IS-IS域里此时可能还残留着这条路由的旧LSP信息,或者因为路由表变化、cost变化而触发重新引入。两个ASBR之间你来我往,OSPF的Type 5 LSA和IS-IS的LSP不断被刷新,每一次刷新都会触发SPF重算。轻则CPU飙高,重则全网路由震荡,表现就是业务间歇性丢包。
打个比方:你在微信群里发了一条消息,朋友把这条消息截图转发到另一个群,另一个群的人又把截图转发回你的原群,你还以为这是别人发的新内容,于是又转发了一次。消息在几个群之间反复转发刷屏,最后每个人手机里都多了好几份相同内容——这就是路由回馈在协议世界里的即视感。
2. 最小化复现:eNSP里的双ASBR场景搭建与现象确认
理论讲完了,一定要动手复现一次。我建议用eNSP或者GNS3都行,重点是亲眼看到回馈路由是怎么出现的,后面配Route Tag方案时才不会被现象绕晕。
2.1 拓扑与IP规划
整个拓扑不需要复杂,三台设备足够:
- R1与R2通过GE0/0/0互联,这条链路上同时运行OSPF Area 0和IS-IS Level-2
- R1的Loopback0地址是1.1.1.1/32,R2的Loopback0地址是2.2.2.2/32,两个Loopback都宣告进OSPF,代表OSPF域内的业务网段
- R3是OSPF域内的一台普通路由器,接在R1的GE0/0/1上,R3上有一个Loopback0地址3.3.3.3/32,用来观察域内其他路由器视角
设备接口规划如下:
| 设备 | 接口 | IP地址 | 所属协议 |
|---|---|---|---|
| R1 | GE0/0/0 | 10.0.12.1/24 | OSPF Area 0 + IS-IS |
| R1 | GE0/0/1 | 10.0.13.1/24 | OSPF Area 0 |
| R1 | Loopback0 | 1.1.1.1/32 | OSPF Area 0 |
| R2 | GE0/0/0 | 10.0.12.2/24 | OSPF Area 0 + IS-IS |
| R2 | Loopback0 | 2.2.2.2/32 | OSPF Area 0 |
| R3 | GE0/0/0 | 10.0.13.3/24 | OSPF Area 0 |
| R3 | Loopback0 | 3.3.3.3/32 | OSPF Area 0 |
这里说句题外话:一条物理链路上同时跑两种IGP,实验环境里没问题,现网里几乎没人这么干。生产环境一般会分开链路或者用子接口,但复现回馈问题,这样最省设备。
2.2 核心配置:双向引入是关键
R1和R2的OSPF、IS-IS基础配置就不完整贴了,重点看引入部分。R1的关键配置:
ospf 1 router-id 1.1.1.1 import-route isis 1 area 0.0.0.0 network 1.1.1.1 0.0.0.0 network 10.0.12.1 0.0.0.0 network 10.0.13.1 0.0.0.0 # isis 1 is-level level-2 network-entity 49.0001.0000.0000.0001.00 import-route ospf 1 # interface GigabitEthernet0/0/0 isis enable 1 ip address 10.0.12.1 255.255.255.255R2的配置和R1对称,只是router-id和network-entity不同,同时把is-is的网络实体改为49.0001.0000.0000.0002.00,引入方向也保持一致:
ospf 1 router-id 2.2.2.2 import-route isis 1 area 0.0.0.0 network 2.2.2.2 0.0.0.0 network 10.0.12.2 0.0.0.0 # isis 1 is-level level-2 network-entity 49.0001.0000.0000.0002.00 import-route ospf 1 # interface GigabitEthernet0/0/0 isis enable 1R3就只跑OSPF,什么都不引入。
注意:实验时先别急着把引入命令敲上去。先把OSPF、IS-IS邻居都建立好,查看路由表确认没有引入前一切正常,然后再添加
import-route命令,这样出现的现象才是回馈导致的,而不是你基础配置错了。
2.3 两个命令看清回馈现象
配置完成并等OSPF收敛之后,在R3上查看1.1.1.1/32的路由:
<R3>display ip routing-table 1.1.1.1 32 Route Destination: 1.1.1.1/32 Known via "ospf-1", distance: 10, metric: 1, type: intra area Last update : 00:01:23 ago NextHop : 10.0.13.1 Interface: GigabitEthernet0/0/0 Route Destination: 1.1.1.1/32 Known via "ospf-1", distance: 150, metric: 1, type: extern Last update : 00:00:05 ago NextHop : 10.0.12.2 Interface: GigabitEthernet0/0/0看到了吗?同一台路由器上,同一个前缀,出现了一条OSPF域内路由(distance 10,下一跳是R1)和一条OSPF外部路由(distance 150,下一跳是R2)。这条distance 150的外部路由,就是回馈路由。
用OSPF LSDB命令看得更清楚:
<R3>display ospf lsdb ase Type : External LS ID : 1.1.1.1 AdvRouter : 1.1.1.1 LS age : 20 Metric : 1 Tag : 0 Type : External LS ID : 1.1.1.1 AdvRouter : 2.2.2.2 LS age : 200 Metric : 1 Tag : 0同一个LS ID,通告路由器一个写着1.1.1.1,一个写着2.2.2.2。这就是回馈路由最直观的指纹:前缀没变,通告者却换了一台设备。
在这个实验里,因为原始路由是OSPF域内路由(distance 10),优先级高于外部路由(distance 150),所以实际转发不会出问题。但R3的LSDB和路由表已经被污染了。如果原始路由也是外部路由,或者IS-IS域里引入了更大的OSPF域,回馈路由就会开始干扰正常选路,出现次优路径甚至环路。
3. Route Tag标记法:给引出去的路由贴"出生证",再接回来
解决回馈,业界最标准的做法是Route Tag,也就是路由标记。思路一句话:引出去的路由,打上一个约定好的标签;引回来的时候,凡是带这个标签的一律拒绝。
3.1 标记法的核心流程
还是用刚才的实验拓扑,我定义回馈标签值为100,两台设备上的处理逻辑完全对称:
- R1在把OSPF路由引入IS-IS时,给所有引入路由打上Tag 100
- R2从IS-IS学到这些路由时,路由上带着Tag 100
- R2在把IS-IS路由引入OSPF时,凡是匹配Tag 100的路由直接拒绝引入
- R2自己把OSPF引入IS-IS时,同样给路由打上Tag 100
- R1在把IS-IS路由引入OSPF时,同样拒绝Tag 100的路由
这样整个闭环就被切断了:R1引出去的路由带Tag 100,到R2那里想引回OSPF时被拦截;R2引出去的路由带Tag 100,到R1那里想引回OSPF时也被拦截。而OSPF域内那些没有Tag 100的原始路由,仍然可以正常被引入IS-IS,两个协议域的互通不受影响。
这个方案的关键在于"对称"。如果R1检查Tag 100,R2引入回OSPF时却没打Tag、或者打了别的值,那R1的过滤就永远匹配不到东西,回馈照旧。
3.2 华为VRP上的具体配置
R1上的配置如下:
# 打标签的策略:所有放行的路由统一打Tag 100 route-policy TAG_100 permit node 10 apply tag 100 # 拒绝回馈的策略:Tag 100的路由直接拒绝,其余放行 route-policy DENY_TAG_100 deny node 10 if-match tag 100 route-policy DENY_TAG_100 permit node 20 # IS-IS引入OSPF时,打Tag 100 isis 1 import-route ospf 1 route-policy TAG_100 # OSPF引入IS-IS时,拒绝Tag 100 ospf 1 import-route isis 1 route-policy DENY_TAG_100R2上的配置和R1完全一样。对,你没看错,两台ASBR用的是同一套route-policy,这也是运维上推荐的做法:所有边界设备的Tag规则保持一致,降低理解和维护成本。
配置完成后,记得敲一条reset ospf process重置OSPF进程,或者等LSA老化,让OSPF域重新收敛。再回到R3上看路由表和LSDB:
<R3>display ospf lsdb ase Type : External LS ID : 1.1.1.1 AdvRouter : 1.1.1.1 LS age : 15 Metric : 1 Tag : 0现在只剩一条由R1发布的1.1.1.1/32了,R2发布的那条回馈LSA已经消失。R3的路由表里也只剩OSPF域内那条distance 10的路由,一切恢复正常。
3.3 一个隐蔽的坑:Tag会不会在跨协议时丢失
Route Tag方案的理论很干净,但我在真实设备上踩过一个坑,必须提醒你:不同协议对Tag的传递行为有细微差异,不能默认它一定带得过去。
OSPF的外部LSA里,Tag是External Route Tag字段,32位,标准支持。IS-IS的LSP里也有路由Tag TLV。但问题在于,从OSPF引入IS-IS时,Tag会不会从OSPF路由原封不动带进IS-IS?从IS-IS引入OSPF时,IS-IS的Tag又会不会自动填进OSPF外部LSA的Tag字段?不同厂商、不同软件版本的行为不完全一样。
华为设备上实测,OSPF和IS-IS之间的Tag传递基本是可靠保留的,但有些老版本或者跨厂商设备对接时,Tag可能在你没注意到的环节被重置为0。一旦Tag丢了,回馈路由就变成了"无标签路由",你的DENY策略匹配不到,回馈直接漏进来。
稳妥的做法是:**在每一个引入方向上都显式处理Tag,不要指望上一步打好的Tag能自动带过来。**比如引入IS-IS到OSPF时,除了拒绝Tag 100,还可以给所有从IS-IS进入OSPF的路由重新打一个内部管理Tag(比如Tag 200),方便后续运维排查这条路由到底从哪进来的。
# 更稳的写法:拒绝Tag 100的同时,给其他路由打上内部管理标签 route-policy DENY_TAG_100 deny node 10 if-match tag 100 route-policy DENY_TAG_100 permit node 20 apply tag 200 ospf 1 import-route isis 1 route-policy DENY_TAG_100这样即使个别路由的Tag传递有异常,你也可以通过查看最终路由表里的Tag值,快速判断是哪一段丢的。
4. 如果不想用Tag:前缀过滤与AD优先级调整的适用边界
Route Tag是标准解法,但有些场景下你未必能用它。比如设备版本太老不支持跨协议Tag传递,或者你只是临时止血,还没有时间规划Tag方案。这时候有两类替代手段:前缀过滤和AD优先级调整。
4.1 前缀过滤:治标快,但维护成本高
思路很简单:直接在引入方向上,把那些回馈过来的特定前缀拒掉。
# 定义前缀过滤:拒绝1.1.1.1/32,放行其余 ip ip-prefix FILTER_RETURN index 10 deny 1.1.1.1 32 ip ip-prefix FILTER_RETURN index 20 permit 0.0.0.0 0 less-equal 32 # OSPF引入IS-IS时调用 ospf 1 import-route isis 1 route-policy FILTER_RETURN这个方案直观,配置量小,前缀少的时候非常高效。但它的维护成本和Tag方案完全是两回事:每新增一个OSPF域内网段,你都要同步修改所有ASBR上的过滤列表。漏掉一个,回馈就在那个网段上重新出现。而且它只是从方向上阻断回馈路由进入OSPF,如果IS-IS域里本身有一条合法的同前缀路由(比如用户网络规划上刻意让两边有重叠前缀),这种过滤会连同合法路由一起拒掉。
所以我的结论是:前缀过滤只适合解决"明确知道回馈前缀且路由表规模小"的临时场景,不适合作为长期运维手段。
4.2 AD优先级调整:止血可以,根除不行
AD优先级调整的思路是:让回馈路由即使进入了OSPF域,优先级也低于原始路由,永远选不上它。
在华为设备上,可以这样调:
# 把OSPF外部路由优先级从150调大到200 ospf 1 preference ase 200这样回馈路由在OSPF域内选路时,会被原始域内路由或者原始的Type 5路由压住,不会成为最优路径。如果原始路由的优先级也是150,回馈路由进来后两者平级,会去比较metric;把回馈路由所在的协议整体调低,至少能保证回馈路由不会翻盘。
但你要明白,AD调整解决的是"选路结果",解决不了"表项污染"。LSDB里依然会有回馈产生的Type 5 LSA,SPF依然要重算,路由表里依然躺着一条多余的外部路由。该震荡还是震荡,该占内存还是占内存。所以它只适合变更割接期间的临时止血,不能作为最终方案。
4.3 组合拳:割接场景下的最小干预流程
现实里我处理过的一个割接场景是这样的:交接班时发现现网已经出现了明显的回馈现象,OSPF域内LSA刷屏,但这时再从头规划Tag方案已经来不及了。我当时的操作顺序是:
- 先在两台ASBR上同时用前缀过滤,把已经识别的回馈前缀拒掉,先让LSDB稳定下来
- 同时把OSPF ASE优先级调大到200,防止个别漏网的回馈路由影响转发路径
- 观察15分钟,确认LSA不再增长、路由表稳定
- 等第二天变更窗口,再把Tag方案完整落上去,撤掉临时的前缀过滤
这个"临时方案保稳定、正式方案换根因"的思路,在现网里比一上来就推倒重来要实用得多。
5. 方案落地的取舍与几个容易翻车的细节
最后把三种方案放一起做个对比,再讲讲实际操作中我踩过的坑。
5.1 方案对比
| 方案 | 阻断效果 | 运维成本 | 适用场景 | 风险点 |
|---|---|---|---|---|
| Route Tag | 彻底阻断回馈链路 | 中,需全ASBR对称配置 | 长期稳定运行,多ASBR复杂网络 | 跨协议Tag传递依赖设备实现 |
| 前缀过滤 | 按前缀定向阻断 | 高,新增网段要同步维护 | 前缀少、短期方案 | 漏配即回馈复发 |
| AD优先级调整 | 不阻断,仅控制选路 | 低,两条命令 | 临时止血 | 表项污染和震荡仍在 |
5.2 版本差异与协议特性:最容易翻车的地方
先说设备版本差异。不同版本的VRP,route-policy的匹配行为在细节上可能有差异。比如有些版本里if-match tag对引入路由的匹配是只匹配外部路由Tag,有些版本会把内部路由的Tag也带进来。遇到这种情况,最稳妥的办法是先在模拟器里搭一个一模一样的双ASBR拓扑,把Tag方案完整跑通,再上生产设备操作。我坚持的原则是:涉及路由策略的变更,永远先在模拟器里验证一遍,绝不直接在生产设备上试错。
第二是OSPF特殊区域。如果OSPF域里有NSSA或Stub区域,回馈路由和7类LSA的转换逻辑会叠加一层复杂度。比如NSSA区域里,ABR会把7类LSA转换成5类LSA,这个转换过程中Tag字段的保留行为、区域间的ADR,都和普通Area 0不同。只要拓扑里出现NSSA,我建议你把Tag方案仔细推演一遍,重点观察7转5时Tag是否保留。很多回馈问题的"隐藏变种",就藏在这种区域边界转换里。
第三是路由震荡期间的LSDB基线。回馈爆发的时候,LSA序列号会不停自增,你根本看不出"正常的LSA"长什么样。我建议在任何涉及双ASBR引入的变更前,先抓一次LSDB和路由表作为基线,变更后对比外部LSA数量是否和基线一致。我在割接规范里加了一条硬性要求:配置完成后,间隔5分钟统计两次LSDB中ASE数量,两次结果必须一致——这能快速暴露隐藏的回馈循环。
5.3 一个值得养成的设计习惯
说句大实话,回馈问题一旦出现,排查起来最花时间的往往不是敲命令,而是理清"路由到底是从哪个方向、以什么身份进入另一个协议域"的。所以我后来给自己定了一个规矩:任何双点双向引入的拓扑,动手配置前先画一张路由流向图。
这张图上必须标注清楚:
- 有哪些路由前缀需要从OSPF跨到IS-IS
- 有哪些路由前缀需要从IS-IS跨到OSPF
- 每个引入方向使用什么Tag策略(打什么Tag、拒什么Tag)
- 是否存在不需要跨协议的路由(比如纯内部管理网段)
把这张图画完,Tag方案其实就已经设计好了,剩下的配置只是把图画内容翻译成route-policy。这张图同时还是变更评审和排障时的最重要的参考资料。回馈问题看似复杂,捋清楚路由走向之后,解决方案往往就是几行route-policy的事。
我最后再分享一个感受:回馈问题最麻烦的地方不在于技术本身,而在于它总喜欢在你以为一切正常的时候悄悄出现。外部LSA数量缓慢增长、OSPF进程CPU偶发跳高、某些业务路径在割接后才暴露问题——这些"温和"的表象背后,可能都是回馈链路在慢慢发酵。把Tag方案、基线和验证步骤提前固化到流程里,比出了故障再到处翻命令要划算得多。希望这篇文章能帮你少走这些弯路。