上周我在eNSP里搭了一个SRv6实验环境,IS-IS邻居全部正常,IPv6路由表也是一片绿色,可到了验证SRv6路径那一步就是不通。排查了大半天,最后发现是IS-IS进程里忘了挂segment-routing ipv6 locator。这个错说出来挺低级的,但后来我发现身边不少同行在学SRv6时都卡在同一个地方:IGP和SRv6之间到底怎么配合,脑子里没有一套完整逻辑。
这篇是系列第三篇,前两篇我们把SRv6的报文结构、SID组成和基础转发原理过了一遍。这一章重点就放在IGP for SRv6:IGP为什么必须为SRv6“加班”,IS-IS和OSPFv3分别是如何实现SRv6扩展的,一条SID从本地生成到全网可见要经历哪些过程,最后结合eNSP实操和排障,把这条线彻底捋清楚。
1. 理解IGP在SRv6网络里承担的三件事
1.1 SRv6 SID和MPLS标签的一个关键区别
很多人刚接触SRv6时会有个习惯性思维:SR-MPLS时代IGP通过Prefix-SID和Adj-SID来分发标签,那SRv6是不是只要把SID当成一群“超长标签”继续分发就行?思路大方向没错,但有一个本质区别容易被忽略:SR-MPLS的SID对应的是一个MPLS标签,标签本身只在本地有意义,需要通过IGP或BGP把标签值和前缀、邻接绑定后通告出去;而SRv6的SID是一个完整的IPv6地址。
一个IPv6地址出现在网里,意味着它天生就自带“路由属性”。当设备收到一个目标地址为某个SID的报文时,它首先要能在IPv6路由表里找到去往这个SID所在节点的路径,然后才谈得上在SRH里执行什么功能。这就带来一个新问题:传统IGP只会发布IPv6前缀路由,它不会告诉你这条前缀下面还挂着一个“具有End功能的SID”,更不会告诉你这个SID支持哪些行为、绑定在哪个出接口上。
打个比方,MPLS标签像仓库里的货架编号,知道编号就能找到货;SRv6 SID则像一张写好了详细地址和配送方式的门牌卡,IGP不仅要帮这张门牌卡找到对应的街道(Locator路由),还要把门牌卡上印的“功能说明”同步给全网。所以,IGP for SRv6的本质不是简单加几个字段,而是让链路状态协议学会分发“带功能的IPv6地址”。
1.2 IGP for SRv6到底要广播什么:三类关键信息
把这个问题拆开看,IGP在SRv6网络里需要通告的信息可以分成三类。
第一类是Locator路由。每台设备都会为自己的SRv6 Locator前缀在IGP里发布一条路由,其他设备看到这条前缀后就知道该往哪个方向发报文。这其实和普通IPv6前缀路由的传播没有太大区别,但需要注意,Locator前缀往往用/64甚至更长的掩码来规划,它不代表一个物理接口网段,而是代表一台设备或一个转发实例的“SID归属空间”。
第二类是SID和Endpoint Behavior的映射关系。比如设备上配置了一个End SID 2001:db8:1111::1,这个SID的Function是什么、执行什么行为(End、End.X、End.DT6等),必须通过IGP扩展告诉全网。只有知道这个映射,头端设备才能在自己的SRv6 Policy列表里正确填充分段列表,中间设备也才能在收到SRH时知道该执行什么操作。
第三类是节点能力和算法属性。包括设备是否支持SRv6、支持哪些Endpoint Behavior、最大可压入的Segment深度(Maximum SID Depth),以及这个Locator是否属于某个Flex-Algo算法。这些能力信息在SR-MPLS时代没有那么突出,但到SRv6时代就变得非常重要,因为SRv6的不同功能变体很多,设备能力不一致时很容易出现“控制面学得到、转发面做不了”的尴尬局面。
1.3 为什么不能靠普通IPv6路由“顺路”解决
有读者可能会问:既然Locator本身是IPv6前缀,IGP原本就会扩散IPv6路由,那SID是不是只要配置成某个接口的IPv6地址,普通路由协议就自动把SID带出去了?实践里确实有人这么干过,把End SID直接配成LoopBack接口地址,然后靠普通IPv6路由让全网可达,但这种方式只能碰巧让报文找到设备,解决不了Segment Routing的控制面要求。
原因有两个。第一,普通IPv6路由只告诉你“这个地址怎么走”,不会告诉你“这个地址是一个SRv6 SID,执行End行为时要把SRH指针移动到下一个Segment”。没有SRv6扩展信息,设备收到目标地址匹配但这个地址不是本地接口地址的报文时,只会在IPv6路由表里做普通转发,根本不会触发SRH处理逻辑。第二,Locator前缀往往配置在LoopBack接口上,和物理链路的IPv6地址不在同一个网段,IGP只靠普通LSA或LSP扩散接口前缀,无法把Locator的聚合语义、算法属性和SID列表完整表达出来。
所以,IGP for SRv6不是锦上添花,而是必须做的一层扩展。下面我们分别看IS-IS和OSPFv3这两条主流技术路线是怎么落地的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 两条技术路线:IS-IS的TLV扩展与OSPFv3的新LSA体系
2.1 IS-IS的扩展思路:TLV里“夹带”SRv6信息
IS-IS是我个人最推荐用来学习SRv6的协议,因为它的TLV结构天生就是为扩展设计的。一条LSP里可以塞进各种TLV,老设备遇到不认识的TLV默认跳过,新设备按新解释处理,兼容性压力比OSPF小很多。
SRv6的IS-IS扩展主要由RFC 9352定义。整体思路是继续沿用IS-IS已有的报文结构,在原有TLV里增加新的Sub-TLV,或者在LSP中新增专门承载SRv6信息的结构。IS-IS需要通告的Locator信息会携带在LSP中,SID和Endpoint Behavior通过SRv6 SID相关的Sub-TLV描述,节点的SRv6能力则挂在Router Capability TLV下。这样全网设备通过泛洪LSP,既能学到Locator前缀,也能把SID和行为绑定关系同步到所有节点。
实际查看IS-IS的SRv6扩展时,重点观察三类字段:一是Router Capability里是否包含了SRv6能力标志和最大SID深度,二是LSP里是否有SRv6 Locator TLV,三是携带的SID Sub-TLV里Endpoint Behavior字段是否正确。抓包时如果能在LSP里看到这些字段,基本可以确认IS-IS的SRv6扩展生效了。
2.2 OSPFv3的选择:用新的LSA类型承载SRv6
OSPFv3走的是另一条路。OSPFv2不支持IPv6,所以SRv6只能基于OSPFv3来做,OSPFv3的SRv6扩展由RFC 9354定义。
OSPFv3本身采用LSA来描述网络拓扑和前缀,SRv6扩展的方式是新增了若干种LSA类型,分别承载SRv6能力、Locator前缀、SID和Endpoint Behavior,以及与链路邻居相关的SID。设备收到这些新LSA后,会像处理普通路由LSA一样把它们放进LSDB,参与SPF计算。
这里有个兼容性问题很值得注意。OSPFv3的LSA头里有一个U bit,用来告诉不支持某种LSA类型的老设备应该怎么处理未知LSA。为了避免SRv6新LSA在骨干网里被老设备直接丢弃,新LSA一般会把U bit设计成“不认识也要继续泛洪”的模式。就是说,老式路由器即使看不懂SRv6 LSA的内容,也不会把LSA丢掉,而是当成未知类型转发出去,保证全网LSDB同步不中断。这个机制在实际存量网络升级时非常关键,升级设备前最好先确认老设备对Unknown LSA的洪泛策略。
2.3 两种方案怎么选:对照与落地建议
经常有朋友问,学SRv6到底该把重心放在IS-IS上还是OSPFv3上?我的建议是:先吃透IS-IS,再用OSPFv3做对照实验。IS-IS的TLV扩展结构清晰、排障直观,新SID字段也能直接在LSP里看到,适合建立控制面模型。
| 对比维度 | IS-IS SRv6扩展 | OSPFv3 SRv6扩展 |
|---|---|---|
| 标准参考 | RFC 9352 | RFC 9354 |
| 信息承载方式 | LSP中新增TLV/Sub-TLV | 新增多种LSA类型 |
| SRv6能力通告 | Router Capability TLV | Router Information LSA |
| Locator通告 | LSP内Locator TLV,随拓扑泛洪 | SRv6 Locator LSA,进入LSDB |
| SID与行为通告 | SID Sub-TLV关联具体SID | SRv6 SID LSA描述SID与行为 |
| 老设备兼容 | 不识别TLV时跳过 | 依赖U bit对未知LSA的处理策略 |
| 适合场景 | 现有IS-IS网络平滑演进 | 现有OSPFv3网络平滑演进 |
实际组网选择主要看存量环境。如果一个网络本来就用IS-IS跑IPv6,没有必要为了SRv6强行引入OSPFv3;反过来域内全是OSPFv3的,也不需要推翻重来。但从零开始学SRv6做实验,我更建议先用IS-IS,因为配置少、字段直观、判断问题链路短。上面提到IS-IS或OSPFv3只是承载协议,SRv6控制面的逻辑是一致的,把一条SID如何从本地变成全网路由这件事弄懂,用哪个协议都只是操作差异。
3. 一条SRv6 SID从配置到全网可见的完整旅程
3.1 本地生成:从Locator到Local SID
理解IGP for SRv6最好的办法,是跟着一条SID走完它的完整生命周期。这条旅程从本地的Locator配置开始。
以华为VRP风格为例,配置一个名为L1的Locator,前缀为2001:db8:1111::/64,代码大致如下:
code复制segment-routing ipv6
locator L1 ipv6-prefix 2001:db8:1111:: 64 static 32
这里前面的2001:db8:1111::/64是Locator前缀,后面的static 32表示静态Opcode空间大小。Locator创建后,设备内部会形成一块SID空间,后续在这个空间里分配的静态Opcode都会成为本机生成的SRv6 Local SID。
实际业务中,工程上通常把Locator前缀同时配置在LoopBack接口上,并把接口和Locator绑定:
code复制interface LoopBack0
ipv6 enable
ipv6 address 2001:db8:1111::1/128
segment-routing ipv6 locator L1
这样LoopBack地址和Locator归属就绑定在一起了。配置完成后,可以用display segment-routing ipv6 local-sid看到本机已经生成了一条End类型的Local SID。此时这台设备的控制面已经“认识”这个SID,但其他设备还不知道它的存在,接下来就要靠IGP把这条SID扩散出去。
3.2 IGP扩散:SPF计算后形成两张表
要让全网都能使用这条SID,必须让IGP把“Locator前缀”和“SID及行为”一起传播出去。以IS-IS为例,在IS-IS进程下绑定Locator:
code复制isis 1
network-entity 49.0001.0000.0000.0001.00
is-level level-2
cost-style wide
ipv6 enable topology ipv6
segment-routing ipv6 locator L1
这条命令是IGP for SRv6配置里的灵魂。少了它,IS-IS邻居再正常、IPv6路由再全,SRv6的SID也不会被IGP携带。我之前在实验里踩的坑就是这里。
配置完成后,设备会把这个Locator和关联的SRv6 SID信息放进LSP里泛洪。其他IS-IS路由器收到LSP后,会把Locator当作一条IPv6前缀放进自己的IPv6路由表,同时把SID和Endpoint Behavior写进自己的SRv6 SID表。这个阶段会形成两张表:
- IPv6路由表:负责告诉转发面“要到
2001:db8:1111::/64这个Locator,下一跳该走哪里”; - SRv6 SID表:负责告诉转发面“
2001:db8:1111::1这个地址是一个SID,功能是End”。
两台设备的协议状态全部正常后,在R2上用display ipv6 routing-table 2001:db8:1111::能看到Locator前缀路由,同时查看SRv6 SID表也能看到远端SID。如果路由表有而SID表没有,大概率是IGP进程没挂Locator,或者收到的LSP里SRv6扩展字段没有被正确处理。
3.3 ECMP和多路径:IGP如何让SRv6复用等价路径
SRv6控制面还有一个特别容易让人困惑的点:Locator前缀在IPv6路由表里有多个等价下一跳时,SID表会不会跟着生成多条SID?答案是不会。SID表里只会有一条远端SID记录,它描述的是“这个SID功能是什么”,而不是“这个SID走哪条路径”。真正决定路径的是IPv6路由表里的Locator前缀。
这个设计和我最早学SR-MPLS时的思路不太一样。SR-MPLS的标签转发表本身包含出标签和下一跳,而SRv6把“怎么走”和“做什么”彻底拆开了。IGP的SPF计算负责算出Locator前缀的等价路径,出接口有两条时IPv6路由表就会装两条;数据面收到SRv6报文后,会先查SRv6 SID表确认要执行的功能,再按普通IPv6报文的方式对Locator前缀做等价负载分担。
这个特性对网络设计其实很友好。SRv6天然继承了IPv6的ECMP能力,不需要像MPLS那样额外考虑负载分担标签,前提是IGP把Locator前缀作为普通IPv6前缀正确计算,所以IGP SPF的算法和拓扑收敛质量,直接影响SRv6负载均衡的稳定性。
3.4 Flex-Algo:IGP为SRv6算出的“定制路径”
IGP for SRv6还不光是把SID发出去那么简单。实际流量工程场景里,我们经常需要IGP按不同约束算出不同路径,这就涉及Flex-Algo(灵活算法)。
Flex-Algo允许管理员定义多个算法实例,比如算法0使用IGP默认Cost,算法128按链路时延计算,算法129要求避开某些链路。每个算法通过IGP通告后,全网设备会分别跑对应的SPF计算。SRv6的Locator可以和具体算法绑定,这样同一个节点就可以在不同算法下有不同的Locator前缀和SID。
举个例子,设备A的Locator同时挂在一个普通算法和一个时延优化算法下,那么设备A会通告两条不同算法属性的Locator前缀。
