IS-IS缺省路由生成机制详解:ATT位、手工注入与防环实践
做网络的人都清楚OSPF 的末梢区域想拿到缺省路由靠的是 ABR 上敲一条 default-route-advertise或者直接把区域配成 stub。可要是抱着同样的思路去对付IS-IS 缺省路由十有八九要翻车。我上次在某机房做一次区域拆分把一批接入设备划进 Level-1 区域满以为缺省路由会自动出现结果业务一收敛路由表一敲干净得像刚拆封的设备。IS-IS 缺省路由的生成机制跟 OSPF 完全不是一个套路。这篇文章就把这套机制彻底拆开讲清楚Level-1 区域内的路由器靠什么自动生成缺省路由ATT 位在里面扮演什么角色手工下发默认路由有哪些命令和参数部署中常见的次优路径和环路坑以及验证排查的完整思路。适合正在啃 IS-IS 的网工也适合准备做区域化改造的运维同学。1. IS-IS 里的缺省路由和 OSPF 那套完全是两码事1.1 链路状态协议为什么需要一张“兜底网”IS-IS 和 OSPF 一样都是链路状态协议区域内每台路由器通过泛洪 LSP 构建出一份完全一致的 LSDB再用 SPF 算法算出自己的路由表。这套机制对已知前缀非常精确但对“未知前缀”极其冷漠。你在一台纯 Level-1 路由器上查路由表正常情况下只能看到本区域内的明细路由区域外一个前缀都看不到连默认路由都可能没有。问题就来了Level-1 区域内部的主机要访问区域外的网络L1 路由器上根本没有明细路由报文往哪丢IS-IS 的设计方案是每个 Level-1 区域都会至少有一台 L1/L2 路由器充当区域出口而 L1 路由器必须拥有一条指向这台出口路由器的缺省路由作为兜底。这就像小区里没有每家每户的详细门牌号但你至少知道所有快递该送到小区门口的驿站。这里有个根本矛盾链路状态协议的核心是维护一张无环、精确的拓扑图而缺省路由本身就是一种“模糊匹配”。要是每台路由器都拍着胸脯跟邻居说“我什么都知道不知道的流量都给我”区域之间很快就会被互相宣告的默认路由打成环路。所以 IS-IS 没有采用 OSPF 那套“区域边界路由器主动下发默认路由”的做法而是在 LSP 里安排了一个专门的标志位让缺省路由的生成有严格的触发条件。这个标志位就是 ATT 位也就是 Attach Bit附着位。1.2 ATT 位路由器宣告“我有出口”的唯一标记ATT 位位于 LSP PDU 头部属于 LSP 标志字段的一部分。IS-IS 的 LSP Flags 里主要有 P 位、ATT 位和 OL 位。OL 位Overload过载大家在排障时见得最多路由器过载时置位告诉其他路由器别拿自己当中转而 ATT 位管的就是缺省路由。当一个 L1/L2 路由器确认自己已经和骨干区域Level-2建立了可用的邻接关系之后它会在自己生成的 Level-1 LSP 里把 ATT 位置 1。这个位的含义翻译成大白话就是“我是一台连着上级区域的路由器本区域的其他兄弟们你们可以把默认路由指向我。”收到带 ATT 位的 LSP 的 L1 路由器就会以该 LSP 的源 ID 作为下一跳设备自动生成一条缺省路由。这是 IS-IS 缺省路由最核心的内置机制全过程不需要任何手工配置。三个细节容易忽略第一只有 L1/L2 路由器才有资格置位 ATT纯 L1 路由器没有这个能力第二置位的真正条件是存在可用的 Level-2 邻居不是配置了 level-2 进程就自动置位L2 邻居没起来LSP 里的 ATT 位依然是 0第三ATT 位只出现在 Level-1 LSP 里Level-2 LSP 一般不携带因为 L2 区域本身就是全网骨干不需要再设定一个“上级出口”。1.3 三条产生缺省路由的途径为了后面章节好展开这里先把 IS-IS 里缺省路由的三种来源归纳清楚ATT 位自动生成L1 路由器根据收到的带 ATT 位的 L1 LSP 自动产生默认路由这是最基础、最轻量的方式。手工注入通告网络出口设备上配置缺省路由通告命令把一条默认路由注入 Level-2 或 Level-1 区域适合需要精细控制出口的场景。路由泄露配合把 Level-2 区域的默认路由通过泄露机制引入 Level-1通常需要指定放行默认路由并配合策略控制。三种途径各有适用场景也各有坑。下面逐一展开。2. ATT 位自动生成默认路由机制、开销与路由表表现2.1 一个经典拓扑区域内的 L1 路由器如何拿到出口假设某个网络划分出区域 10区域内有一台纯 Level-1 路由器 R1两台 L1/L2 路由器 R2、R3R2 和 R3 同时和骨干区域 Area 0 里的 L2 路由器 R4、R5 建立了邻接关系。R1 和 R2、R3 之间都有直连链路。当 R2 与 R4 完成 Level-2 邻接建立后R2 会在自己生成的 Level-1 LSP 里把 ATT 位置 1。R3 同理也会在它自己的 L1 LSP 里置位。此时 R1 的 LSDB 里能看到 R2 和 R3 的 L1 LSP 都带着 ATT 位于是 R1 的 IS-IS 路由表里就会出现一条缺省路由。下一跳指向谁取决于开销计算。这里有一个很多网工在 OSPF 下形成的惯性思维默认路由的 metric 应该是通告方指定的一个固定值。但 IS-IS 的 ATT 默认路由不一样它的开销等于本路由器到那台 L1/L2 设备的 SPF 开销。也就是说缺省路由的 metric 不是常量而是由链路开销叠加出来的。默认开销类型下各接口 cost 通常默认是 10实际的默认值看开销类型和平台差异R1 会算清楚到 R2 和到 R3 两条路径的累计开销选数值小的那个作为缺省路由的出口。2.2 多条候选默认路由时的选路逻辑继续用上面的拓扑。假设 R1 到 R2 的单条链路开销是 10R1 到 R3 的单条链路开销也是 10那么 R1 会认为两条候选路径完全等价路由表里出现两条等开销缺省路由下一跳分别是 R2 和 R3触发负载分担。如果 R1 到 R2 之间拉了两条链路R2 侧叠加开销变成 20而到 R3 还是 10那 R1 的缺省路由就只会指向 R3。这个特性非常实用实际区域设计中很多工程师正是利用开销控制让 Level-1 区域的所有默认流量集中走一台高性能出口设备另一台 L1/L2 只在主出口出故障时才被选上。做法很简单把备用出口方向的链路口开销调大主出口保持默认或调小即可。注意 ATT 默认路由没有类似 OSPF 的“尽量不切换”机制只要 SPF 算出来路径变了默认路由的下一跳立刻跟着变。另外要说清楚路由表里的关系缺省路由是兜底明细路由优先级永远更高。R1 上如果既有 ATT 生成的默认路由又通过路由泄露拿到了某个区域外前缀的明细路由那么访问那个前缀时走明细访问其他未知名前缀才走默认。这个逻辑在路由表里是由最长前缀匹配天然保证的。2.3 ATT 位没有置位的排查点ATT 位机制看着简单实际运维里最容易出问题的恰恰是“L1 路由器没有缺省路由”这种事。常见原因我列一下L1/L2 路由器没有配置 Level-2 进程或者 L2 邻接没有建立。这是最普遍的原因L2 邻居不起来ATT 位不可能置 1。L2 接口状态 down 或被动抑制。接口没起来邻接自然建立不了。邻居双方区域 ID 不一致导致 L2 邻接起不来。IS-IS 的 L2 邻接要求区域地址匹配区域 ID 不同L2 关系就是建立不了。平台差异或版本限制。极少数版本的实现里对 ATT 位的处理有细微差异特别是针对 metric 的计算方式。排查时不要直接盯着路由表猜先看 LSDB。用类似下面这条命令查看 L1 LSP 的头部标志位display isis lsdb level-1 verbose输出里找到那台 L1/L2 路由器的 LSP确认 Flags 区域的 ATT 位是否等于 1。如果 ATT 位是 0那问题一定在 L2 邻接层面回到 IS-IS 邻居状态去查。这一步顺序反了很容易在错误的方向上浪费大量时间。3. 手工下发默认路由命令、场景与策略控制3.1 常见部署场景ATT 机制虽然方便但存在两个限制一是默认路由的 metric 由 SPF 算出来不能直接改二是只能由 L1/L2 设备向 L1 区域“送”没法在 L2 骨干区域内制造一条全局默认路由。很多场景下必须靠手工注入。主流设备上的命令字眼大概是 default-route-advertise 或者 default-information originate不同厂商略有差异但思路完全一致。三个典型场景供参考场景配置位置命令思路注意事项全网出口在 L2 区域边缘核心出口路由器通告默认路由进入 L2 区域出口必须有真实默认路由否则黑洞L1 区域需要精细控制默认路由L1/L2 边界设备定向通告默认路由进入 L1与 ATT 默认路由共存时确认优先级多出口主备切换多台出口路由器配合策略只允许主出口通告备出口故障时能自动接管典型的第一类场景长这样整个 IS-IS 网络是二层结构核心路由器连着外部网络本地路由表里有一条静态默认路由指向运营商。为了让骨干区域里所有 L2 路由器都能访问外部网络核心路由器上配置一条默认路由通告把这条默认路由注入 L2 区域。L2 路由器收到后所有去外部网络的流量全部指向核心出口。3.2 always 参数和路由策略的坑手工注入默认路由时命令后面经常可以带一个 always 类似的参数这也是全网工踩得最狠的坑。不带 always 时的语义是只有本地路由表里真的存在一条缺省路由时才向 IS-IS 区域通告默认路由。比如你有一条静态默认路由指向出口或者在 BGP 里学到了一条默认路由IS-IS 才会通告。这时通告行为是“跟着现实走”出口断了静态那条路由从路由表消失IS-IS 的默认路由通告也自动停止。这个行为非常健康。带 always 时的语义则是不管本地有没有默认路由强制向区域通告。这个参数的设计初衷是应对某些特殊场景比如出口设备的默认路由依赖动态检测、间歇性消失但业务上希望 IS-IS 区域始终保留这条兜底路由。可一旦用错后果很直接设备本身没有默认路由却向下游通告了默认路由下游所有未知流量全甩给它它再查表又是一脸茫然直接把包丢掉。整片业务表现为“路由正常但有去无回”。我的建议是尽量不要裸敲 always。如果出口链路存在可用性检测配合策略做条件通告远比 always 稳妥。很多主流设备支持给 default-route-advertise 挂路由策略例如“只有当静态默认路由下一跳可达时才通告”这样既有兜底又不会引入黑洞。3.3 把默认路由泄露进 L1 的注意事项正常情况下 L1 区域靠 ATT 位自动拿默认路由。但 ATT 默认路由的 cost 不受手工控制如果你希望 L1 区域收到的默认路由带一个明确的、可控的代价可以考虑通过 L2 到 L1 的路由泄露来实现。需要留意的第一个坑大多数平台在执行 L2 到 L1 路由泄露时默认会过滤掉默认路由你必须在泄露策略里显式放行前缀 0.0.0.0/0否则配置半天一点效果都没有。第二个坑泄露进来的默认路由和 ATT 自动生成的默认路由可能同时在路由表里。两者的优先级、metric 都可能不一样最后优选哪个完全取决于平台实现和你调的参数。为了避免混乱实践中通常会给泄露的默认路由打上路由标记tag再在边界用入方向策略控制传播范围。第三个坑环路。把默认路由泄露进 L1 区域之前一定要想清楚这台 L1/L2 路由器本身会不会又把这个默认路由重新注入 L2。如果它同时在 L2 区域里学习到了其他设备通告的默认路由再把它注入 L1而 L1 内另一台 L1/L2 又把它重新引入 L2两边反复互指环路就成了。防环的思路就是靠 tag 过滤在一侧入方向拒绝带有特定 tag 的默认路由。4. 次优路径与环路缺省路由最容易翻车的地方4.1 默认路由与明细路由并存时的选路冲突缺省路由本来是为“查不到明细”准备的但在实际网络里它经常会抢明细路由的流量。举一个真实常见的例子区域 10 内R1 的默认路由通过 ATT 位指向 R3因为 R3 方向开销小。R2 是另一台 L1/L2它通往数据中心有一条低延迟链路数据中心前缀也做了路由泄露到 L1。按道理 R1 访问数据中心应该走 R2但这里有个前提数据中心的部分前缀没有被泄露只存在于 L2 区域。R1 查不到这些前缀的明细只能匹配默认路由于是本该从 R2 走的数据中心流量全部拐到 R3再经 R3 绕回 R2 所连的数据中心。路径拉长不说R3 出口还有拥塞风险。这种次优路径的本质是默认路由视野太宽而明细路由覆盖面不全。修复手段无非三种把关键目的前缀从 L2 完整泄露到 L1让 L1 路由器有精确路由可查调开销让默认路由自然指向正确的出口改成手工注入默认路由附加策略和路由优先级精确控制默认路由的方向。不要以为只有 L1 区域才会遇到这个问题。L2 区域手工注入的默认路由一样会吸流量骨干里明明存在开销更低的外部明细路径但因为默认路由 metric 设得小所有流量都往默认出口灌。所以手工注入默认路由时设置一个合理偏大的 cost通常比设成最优值更安全宁可使用明细路径也不让默认路由把所有流量都“吸”过来。4.2 环路是怎么形成的缺省路由的环路核心是两个“默认路由叠加”的场景。第一个场景在 L2 骨干区域里最常见。两台设备 R2、R3 互为邻居都配置了默认路由通告彼此的 LSP 里都带默认路由。R2 学到 R3 通告的默认路由下一跳是 R3R3 学到 R2 通告的默认路由下一跳是 R2。一旦出现某条未知前缀的流量R2 交给 R3R3 又交回 R2TTL 耗尽流量黑洞。这种问题在“全网多出口、每台出口都想当然宣告默认路由”的网络里反复出现。第二个场景和路由泄露有关。一台 L1/L2 设备 A 把 L2 区域的默认路由泄露进 L1另一台 L1/L2 设备 B 在 L1 区域学到这条默认路由后又在自己的 L2 进程里把它重新引入 L2。A 随即在 L2 区域学到 B 通告回来的默认路由发现开销更优于是 L1 的默认路由变成了 A 和 B 互指的状态。ATT 位产生的默认路由天然不会从 L1 回注到 L2相对安全但手工泄露引入的默认路由没有这个保护机制。防环的思路归根结底就是两个原则第一默认路由通告不要无条件第二明确标记默认路由的来源在区域边界入方向做过滤。凡是自己泄露进 L1 的默认路由都应该打上特定 tag凡是带有这个 tag 的默认路由在进入 L2 之前一律拒绝。4.3 通过路由渗透修正次优路径接着说怎么修正 4.1 里的那个场景。既然问题的根源是 R1 查不到数据中心的明细那就让数据中心的明细路由进入 L1。IS-IS 的路由渗透Route Leaking标准做法是在 L1/L2 边界设备上把 L2 学到的部分或全部路由重新引入 L1 区域同时配合过滤策略控制范围避免把整个骨干路由表都塞给 L1。实际操作中有两个参数值得关注一个是是否放行默认路由另一个是是否附带 tag。默认情况下泄露明细即可缓解大多数次优路径问题如果连默认路由也一起放行就要额外确认不会和 ATT 默认路由冲突避免在路由表里出现两条同前缀不同来源的默认路由互相打架。如果不想做路由渗透也可以通过调整开销让默认路由指向正确出口。比如把 R3 方向链路口开销从 10 调到 20R1 的 ATT 默认路由下一跳就会变成 R2数据中心流量自然走 R2。这种办法最省事但副作用是整个 L1 区域的默认出口全变了不只有数据中心流量。所以究竟是泄露明细还是调开销要看你想“精准修正某条路径”还是“整体调整区域出口”针对性不同方案也得分开选。5. 验证方法、排错清单与实际操作心得5.1 从 LSP 到路由表验证命令怎么读验证 IS-IS 缺省路由切忌直接看 IP 路由表要从源头一步步往下捋。完整的验证链路应该是先看 LSP 标志位再看 IS-IS 路由表最后确认 IP 路由表。第一步确认 L1/L2 路由器的 LSP 里 ATT 位是否置 1display isis lsdb level-1 verbose在输出的 LSP 头部 Flags 区域找到 ATT 位。如果 ATT 是 0就不用去看路由表了直接回头查 L2 邻接状态。第二步查 IS-IS 路由表里的缺省路由display isis route level-1这里能看到缺省路由的下一跳和 metricmetric 的值可以帮助确认开销计算是否符合预期。第三步看最终的 IP 路由表display ip routing-table重点看默认路由条目的优先级和出接口确认它和设计一致。如果这里出现了两条默认路由比如一条来自 IS-IS另一条来自静态配置就要对照路由优先级决定最终生效的是哪一条。5.2 一张排错清单把常见现象、可能原因和检查点整理成一张表排查的时候直接按表索骥现象可能原因检查点L1 路由器没有默认路由ATT 位未置位L1/L2 设备的 L2 邻接是否已建立、LSP Flags 里 ATT 是否为 1默认路由指向了不想要的出口ATT 多候选路径开销不对链路 cost 配置、到各 L1/L2 的累计开销下游全走某设备但业务不通手工注入默认路由时带 always 且本地无真实默认路由该设备路由表里是否有真正的默认路由、出口链路状态业务时通时不通或出现环路默认路由互指、泄露路由回注 L2tag 过滤配置、泄露方向、LSDB 里默认路由的来源手工注入的默认路由没生效通告条件未满足、路由策略过滤策略条件是否匹配、路由表里源默认路由是否存在5.3 我的几条实战体会这套东西折腾过几轮之后我留下几个比较深的印象写在这里当个参考。先说开头那个机房的案例最后查到根本不是配置问题而是那台 L1/L2 路由器在区域拆分之后和骨干的 L2 邻接一直没起来ATT 位从头到尾就是 0所以整个 L1 区域都拿不到默认路由。把 L2 邻接恢复之后的瞬间所有 L1 路由器几乎同时冒出缺省路由。从那以后我养成了一个习惯凡是涉及区域结构变更先看 LSP 的标志位再谈路由表里缺什么。手工注入默认路由这条我踩过 always 的坑。现在我的原则是能不带 always 就不带必须带的时候必须同时挂条件策略确保设备真有出口才通告。这不是保守是黑洞故障太难看整片业务断掉还找不到原因。还有一个容易被忽视的点缺省路由和 BGP 默认路由之间的优先级关系。在有外部互联的网络里出口路由器上通常同时跑着 IS-IS 内部协议和 BGP 外部协议IS-IS 内部默认路由优先级往往高于 BGP如果不注意内部注入的默认路由可能把 BGP 学到的更优出口路由顶掉所有流量全部压到内部默认出口上。这种问题隐藏得很深路由表看着都是通的实际路径完全不对。最后建议所有准备在现网做 IS-IS 区域化改造的同学先在模拟器或者测试环境里把 ATT 位的行为完整验证一遍特别是多台 L1/L2 并存时的开销计算。不同平台的细节实现不完全一致别拿生产环境当试验场那晚的教训我到现在还记得。