我在上一篇文章《使用 BGP Auto-Steering 对内网流量进行路径调度》中已经写了 Cisco 平台上使用 SRTE 调度流量的方法,这一次我们在 Juniper 平台上部署 SRTE 并使用它做内网流量的调度。
该实验做完总共使用了 4 天时间。由于实验过程中坑实在是太多,多得差点让我吐血了,所以本篇文章将从头到尾完整写一遍,包括可能遇到的坑以及避免的方法。
实验拓扑如下:
所有链路的 Metric 值(TE/IGP) 以及链路的亲和属性已经标在了图中,我们按照图中参数进行配置。
// 所有路由器的公共配置 root@R1# show chassis network-services enhanced-ip; // 将路由器模式设置为 enhanced-ip 模式,否则不能配置 segment routing,真机也是一样 root@R1# show protocols isis interface ge-0/0/1.0 { level 2 { te-metric 5; // 按照图中所示配置 TE Metric 值 ipv4-adjacency-segment { unprotected label 15001; // 手动从 SRLB 分配一个静态标签作为 Adj-SID } metric 20; // 按照图中所示配置 IGP Metric 值 } point-to-point; // 优化,不要让它出现 IS-IS DIS,只要是两个路由器互联中间没其他设备,建议配上 } interface ge-0/0/4.0 { level 2 { te-metric 2; ipv4-adjacency-segment { unprotected label 15004; } } point-to-point; } interface lo0.0; source-packet-routing { srgb start-label 16000 index-range 8000; // 配置 SRGB,等同于 Cisco 中的 segment-routing global-block 16000 23999 node-segment ipv4-index 1; // 宣告索引号,之前文章已经讲过了 } level 1 disable; // 默认关闭 Level 1,一般都不用 level 2 wide-metrics-only; // 开启 Level 2,而且 Metric 模式为 Wide,否则 SR 信息无法传递 traffic-engineering l3-unicast-topology; // 将链路状态信息下载到 TEDB (流量工程数据库),只需要在头端路由器配置 root@R1# show protocols mpls traffic-engineering; // 启动 MPLS family TE 能力 admin-groups { blue 0; // 定义 bit-position,让 IS-IS 在 sub-TLVs 里面传递链路的亲和属性,用于 SRTE orange 1; } icmp-tunneling; // 开启 icmp 隧道功能,防止 L3VPN 数据传递中间跳不知道怎么回来然后看不见跳数,所有路由器都要配置 label-range { static-label-range 15000 15999; // 配置 SRLB 范围,本地意义 } interface ge-0/0/1.0 { admin-group [ blue orange ]; // 给链路染色,并激活接口的 MPLS 功能 } interface ge-0/0/4.0; // 仅激活接口的 MPLS 功能
配置完毕后,我们来检查一下 IS-IS LSP 以及标签功能:
root@R1> show isis database IS-IS level 1 link-state database: 0 LSPs IS-IS level 2 link-state database: LSP ID Sequence Checksum Lifetime Attributes R1.00-00 0x46 0xd946 1165 L1 L2 R2.00-00 0x48 0xef4 917 L1 L2 R3.00-00 0x49 0x5176 527 L1 L2 R4.00-00 0x48 0x5c9a 942 L1 L2 R5.00-00 0x47 0xaee8 589 L1 L2 R6.00-00 0x49 0xb94e 492 L1 L2 R7.00-00 0x49 0x5afd 928 L1 L2 R8.00-00 0x49 0xd9c5 938 L1 L2 8 LSPs root@R1> show route table inet.3 inet.3: 7 destinations, 7 routes (7 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.2/32 *[L-ISIS/14] 04:33:26, metric 20 > to 10.10.12.2 via ge-0/0/1.0 10.0.0.3/32 *[L-ISIS/14] 04:33:26, metric 40 to 10.10.12.2 via ge-0/0/1.0, Push 16003 > to 10.10.15.5 via ge-0/0/4.0, Push 16003 10.0.0.4/32 *[L-ISIS/14] 04:33:26, metric 60 > to 10.10.15.5 via ge-0/0/4.0, Push 16004 10.0.0.5/32 *[L-ISIS/14] 04:33:26, metric 10 > to 10.10.15.5 via ge-0/0/4.0 10.0.0.6/32 *[L-ISIS/14] 04:33:26, metric 20 > to 10.10.15.5 via ge-0/0/4.0, Push 16006 10.0.0.7/32 *[L-ISIS/14] 04:33:26, metric 30 > to 10.10.15.5 via ge-0/0/4.0, Push 16007 10.0.0.8/32 *[L-ISIS/14] 04:33:26, metric 40 > to 10.10.15.5 via ge-0/0/4.0, Push 16008
邻居已经正常建立,而且 inet.3 已经有了所有人的 loopback 接口地址的标签了。
10.0.0.3/32 负载均衡是因为图中 Metrics 分配所以出现了负载均衡,10.0.0.{2,5}/32 两个没有标签是因为下一跳直连所以会直接 pop 掉,实际已经收到标签为 16002/16005 的标签了。
接下来,我们开始配置 SRTE 动态计算的 Policy.
1. 配置 Juniper 设备的 SRTE Policy
首先我们来配置一个 Policy 名字为 blue 的策略:
root@R1# show compute-profile dynamic_blue { // 创建 compute profile,用于指定约束条件 admin-group include-any blue; // 约束条件1:必须包含链路亲和属性为 blue 的链路,任意包含即可 metric-type { te; // 约束条件2:使用 TE Metric 来做路径的计算 } } source-routing-path blue { // 创建 SRTE Cpath,用于生成 SRTE LSP to 10.0.0.8; // 目的地址:10.0.0.8 color 10; // 指定颜色 (SRTE Header) 10 binding-sid 15555; // 手工从 SRLB 分配 BSID primary { // 指定首选路径(可多个,本实验只写一个) blue { // 名字为 blue compute { // 调用计算模块 dynamic_blue; // 使用 compute-profile 为 blue 预定义约束条件来做计算 } } } }
在做完后,我们来看一下 SRTE LSP:
root@R1> show spring-traffic-engineering lsp detail Name: blue Tunnel-source: Static configuration To: 10.0.0.8-10<c> State: Down Path: blue Outgoing interface: NA Auto-translate status: Disabled Auto-translate result: N/A Compute Status:Enabled , Compute Result:failure , Compute-Profile Name:dynamic_blue Total number of computed paths: 0
嗯?好像有点不太对劲,为什么起不来?是配错了什么吗?
在经过排查后,我发现是因为路由器的 TEDB 根本没包含链路 affinity,这就是导致没法计算出路径的元凶!如果只是使用 TE Metric 来计算,不使用约束条件,那么 LSP 就可以变为 UP 状态。
去 IS-IS database 查看后,验证了我的想法:
root@R1> show isis database R1.00-00 extensive {..snip..} TLVs: {..snip..} IS extended neighbor: R2.00, Metric: default 20 SubTLV len: 34 IP address: 10.10.12.1 Neighbor's IP address: 10.10.12.2 Local interface index: 336, Remote interface index: 334 Traffic engineering metric: 5 P2P IPV4 Adj-SID - Flags:0x34(F:0,B:0,V:1,L:1,S:0,P:1), Weight:0, Label: 15001 P2P IPv4 Adj-SID: 15001, Weight: 0, Flags: --VL-P {..snip..} IP extended prefix: 10.0.0.1/32 metric 0 up 8 bytes of subtlvs Node SID, Flags: 0x40(R:0,N:1,P:0,E:0,V:0,L:0), Algo: SPF(0), Value: 1 IP extended prefix: 10.10.12.0/24 metric 20 up IP extended prefix: 10.10.15.0/24 metric 10 up Router Capability: Router ID 10.0.0.1, Flags: 0x00 {..snip..}
只看到了与 SR Capability 有关的 TLV,没有看到链路亲和属性的 TLVs,难怪 SRTE 会计算不出来正确路径!
可是我已经在 protocol mpls
里面已经定义了啊,怎么可能会没有?而且 Cisco 下只要是定义了就可以在 TLV 里面看到啊?关于这个问题我查了一天也没有头绪,Juniper 官方没有写关于链路 affinity 怎么注入到 IS-IS 进程的提示。
最后躺床上的时候灵光一闪,会不会 Juniper 还在使用远古的 affinity 发送方式,就是用 RSVP 来将链路 affinity 注入进 IS-IS 进程后再让 IS-IS 发送?话不多说,直接所有路由器接口上面激活 RSVP 协议:
root@R1# show protocols rsvp interface all; // 生产环境看情况进行配置,无法设置 Passive interface,我已经试过了
再来查看 IS-IS database:
root@R1> show isis database R1.00-00 extensive {..snip..} IS extended neighbor: R2.00, Metric: default 20 SubTLV len: 86 IP address: 10.10.12.1 Neighbor's IP address: 10.10.12.2 Local interface index: 336, Remote interface index: 334 {..snip..} Administrative groups: 0x3 orange blue P2P IPV4 Adj-SID - Flags:0x34(F:0,B:0,V:1,L:1,S:0,P:1), Weight:0, Label: 15001 P2P IPv4 Adj-SID: 15001, Weight: 0, Flags: --VL-P {..snip..} IP extended prefix: 10.0.0.1/32 metric 0 up 8 bytes of subtlvs Node SID, Flags: 0x40(R:0,N:1,P:0,E:0,V:0,L:0), Algo: SPF(0), Value: 1 IP extended prefix: 10.10.12.0/24 metric 20 up IP extended prefix: 10.10.15.0/24 metric 10 up Router Capability: Router ID 10.0.0.1, Flags: 0x00 {..snip..}
我的想法果然是正确的,Juniper 使用 RSVP 将链路亲和属性注入到 IS-IS 中让 IS-IS 协议来发送,开启 RSVP 后可以看到 TLV 里面被染色的链路已经出现了亲和属性 ( Juniper 的链路 affinity 显示模式就是 Administrative groups)。
接下来,我们再来看看 SRTE LSP:
root@R1> show spring-traffic-engineering lsp detail Name: blue Tunnel-source: Static configuration To: 10.0.0.8-10<c> State: Up Path: blue Outgoing interface: NA Auto-translate status: Disabled Auto-translate result: N/A Compute Status:Enabled , Compute Result:success , Compute-Profile Name:dynamic_blue Total number of computed paths: 1 Computed-path-index: 1 BFD status: N/A BFD name: N/A TE metric: 23, IGP metric: 110; Metric optimized by type: TE computed segments count: 4 computed segment : 1 (computed-node-segment): node segment label: 16002 router-id: 10.0.0.2 computed segment : 2 (computed-node-segment): node segment label: 16003 router-id: 10.0.0.3 computed segment : 3 (computed-adjacency-segment): label: 15003 source router-id: 10.0.0.3, destination router-id: 10.0.0.4 source interface-address: 10.10.34.3, destination interface-address: 10.10.34.4 computed segment : 4 (computed-node-segment): node segment label: 16008 router-id: 10.0.0.8
路径已经计算出来了,而且路径和我期望中一样( R1 -> R2 -> R3 -> R4 -> R8 ),这样子使用链路亲和属性作为计算约束条件的 SRTE LSP 就计算成功了。计算的过程以及原理,详见我的上一篇 SRTE 的文章《使用 BGP Auto-Steering 对内网流量进行路径调度》。
然后我们来创建另外两条 LSP,分别使用 ORANGE affinity,TE Metric(不含 affinity) 作为约束条件计算。配置完毕后,我们来查看路径:
root@R1> show spring-traffic-engineering lsp detail Name: blue Tunnel-source: Static configuration To: 10.0.0.8-10<c> State: Up Path: blue {..snip..} computed segments count: 4 computed segment : 1 (computed-node-segment): node segment label: 16002 router-id: 10.0.0.2 computed segment : 2 (computed-node-segment): node segment label: 16003 router-id: 10.0.0.3 computed segment : 3 (computed-adjacency-segment): label: 15003 source router-id: 10.0.0.3, destination router-id: 10.0.0.4 source interface-address: 10.10.34.3, destination interface-address: 10.10.34.4 computed segment : 4 (computed-node-segment): node segment label: 16008 router-id: 10.0.0.8 Name: orange Tunnel-source: Static configuration To: 10.0.0.8-20<c> State: Up Path: orange {..snip..} computed segments count: 3 computed segment : 1 (computed-node-segment): node segment label: 16002 router-id: 10.0.0.2 computed segment : 2 (computed-node-segment): node segment label: 16003 router-id: 10.0.0.3 computed segment : 3 (computed-adjacency-segment): label: 15000 source router-id: 10.0.0.3, destination router-id: 10.0.0.8 source interface-address: 10.10.38.3, destination interface-address: 10.10.38.8 Name: te Tunnel-source: Static configuration To: 10.0.0.8-30<c> State: Up Path: te {..snip..} computed segments count: 3 computed segment : 1 (computed-node-segment): node segment label: 16007 router-id: 10.0.0.7 computed segment : 2 (computed-node-segment): node segment label: 16003 router-id: 10.0.0.3 computed segment : 3 (computed-adjacency-segment): label: 15000 source router-id: 10.0.0.3, destination router-id: 10.0.0.8 source interface-address: 10.10.38.3, destination interface-address: 10.10.38.8
他们的路径分别是这样的:
- blue – R1 -> R2 -> R3 -> R4 -> R8
- orange – R1 -> R2 -> R3 -> R8
- TE Metrics – R1 -> R5 -> R6 -> R7 -> R3 -> R8
配置完毕,我们来查看 inetcolor.0 路由表(染色后的 SRTE LSP 会被放在该路由表内,Juniper 系统机制)
root@R1> show route table inetcolor.0 inetcolor.0: 10 destinations, 10 routes (9 active, 0 holddown, 1 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.8-20<c>/64 *[SPRING-TE/8] 00:00:08, metric 1, metric2 40 > to 10.10.12.2 via ge-0/0/1.0, Push 15000, Push 16003(top)
嗯?我的 LSP 呢?我那么大两个 LSP 跑哪去了?我们来看看 SRTE LSP 状况:
root@R1> show spring-traffic-engineering lsp To State LSPname 10.0.0.8-10<c> Up blue 10.0.0.8-20<c> Up orange 10.0.0.8-30<c> Up te root@R1> show spring-traffic-engineering route detail label 15555 // 查看对应 LSP 的 binding-SID To : 15555 Tunnel-source : Static configuration Route Nexthop Type: Unusable Route Metric2 : 0 LSP Name: blue {..snip..}
What?为啥 next-hop type 为 Unusable?明明下一跳是直连啊,标签还在 mpls.0 表里面呢?
这个问题我写了很多个 Cpath 来验证我的猜想,包括不限于改变 color 值,约束条件,甚至于改 policy 名字来试试系统是不是 bug 了导致的。实验做了一整天,一点头绪都没有。
不过到第三天的时候,事情出现了转机。最后我发现每次算出来路径的标签数小于等于 3 就没问题,一旦大于 3 后,就立马出现问题,下一跳直接 unusable. 我印象中貌似 Juniper 对接口的标签堆栈数量有严格限制的,而且以前也看到过类似的接口下面有 Max label 的值。我决定试试是不是因为标签数量限制导致下一跳 unusable.
root@R1> show interfaces ge-0/0/1.0 Logical interface ge-0/0/1.0 (Index 336) (SNMP ifIndex 547) {..snip..} Protocol mpls, MTU: 1974, Maximum labels: 3 {..snip..}
果然有限制,那我们把数量放开来会怎样呢?
root@R1# show groups if-group { interfaces { <ge-*> { unit <*> { family mpls { maximum-labels 16; } } } } } apply-groups if-group;
现在已经放开来了,inetcolor.0 的路由会好了吗?我们来查看一下:
root@R1> show interfaces ge-0/0/1.0 Logical interface ge-0/0/1.0 (Index 336) (SNMP ifIndex 547) {..snip..} Protocol mpls, MTU: 1974, Maximum labels: 16 {..snip..} root@R1> show route table inetcolor.0 inetcolor.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.8-10<c>/64 *[SPRING-TE/8] 00:00:52, metric 1, metric2 40 > to 10.10.12.2 via ge-0/0/1.0, Push 16008, Push 15003, Push 16003(top) // 实际发的时候是堆了 4 层标签,第一个是 16002,标签被 pop 掉后发给 R2 10.0.0.8-20<c>/64 *[SPRING-TE/8] 00:00:52, metric 1, metric2 40 > to 10.10.12.2 via ge-0/0/1.0, Push 15000, Push 16003(top) // 同理 10.0.0.8-30<c>/64 *[SPRING-TE/8] 00:00:52, metric 1, metric2 40 > to 10.10.15.5 via ge-0/0/4.0, Push 15000, Push 16003, Push 16007(top) // 这个是 IGP 直接到 16007 然后再进行下一步转发,出去时候并没有 pop 任何标签
果然生效了,将标签堆栈数量放开后,SRTE LSP 下一跳立刻就生效了,三条 LSP 都被安装进了 inetcolor.0 表内,非常棒。
2. 开始调度流量
接下来,我们开始对 L3VPN 的流量进行调度,和之前一样,我们使用 color community 的方式来把流量自动调度到隧道中。L3VPN 的配置和对路由进行染色的配置我们就略过了,我之前的文章有教过配置。染色和普通 community 的配置过程是一样的,不管是在路由发出方向还是路由接受方向均可。
Juniper 的解析机制稍微有点麻烦,需要写 resolution-map 将符合的 Next-hop + color 值的路由从使用 inet.3 路由表解析改成使用 inetcolor.0 路由表进行下一跳解析。关于 Juniper 设备的路由表之间的关系,详情可见 《inet.3 路由表到底是做什么的?》这篇文章。
路由的预定义路径规则如下:
- 100.64.1.0/24 – 使用 Blue LSP 作为转发路径
- 100.64.2.0/24 – 使用 Orange LSP 作为转发路径
- 100.64.3.0/24 – 使用 TE LSP 作为转发路径
我们来配置 resolution-map 以及导入规则:
root@R1# show policy-options {..snip..} policy-statement l3vpn-import { term accept-all { from community l3vpn; then { accept; resolution-map odn; // 调度 resolution-map,让该 VRF 内的符合条件的路由改用 inetcolor.0 路由表来解析下一跳 // 这里指的是下一跳 + 路由携带的 color community 匹配上了 LSP 的 [ destination + color ] 值 } } } resolution-map odn { mode ip-color; // 定义 resolution-map,模式为匹配下一跳 + color 值(标准做法) }
配置完成,我们来检查一下路由表:
root@R1> show route table l3vpn.inet.0 l3vpn.inet.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 100.64.0.0/24 *[Direct/0] 15:14:41 > via ge-0/0/8.0 100.64.0.1/32 *[Local/0] 15:14:41 Local via ge-0/0/8.0 100.64.1.0/24 *[BGP/170] 00:41:52, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified > to 10.10.12.2 via ge-0/0/1.0, Push 16, Push 16008, Push 15003, Push 16003(top) 100.64.2.0/24 *[BGP/170] 15:13:32, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified > to 10.10.12.2 via ge-0/0/1.0, Push 16, Push 15000, Push 16003(top) 100.64.3.0/24 *[BGP/170] 00:26:40, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified > to 10.10.15.5 via ge-0/0/4.0, Push 16, Push 15000, Push 16003, Push 16007(top)
不错,路由已经解析到对应的 inetcolor.0 表里面存放的下一跳了。但是,你以为这样就完了?且慢,我们来做个实验。
首先,我们把 SRTE Cpath 直接给关闭,模拟路径失效后的状况:
root@R1# deactivate protocols source-packet-routing root@R1> show route table inetcolor.0 root@R1> root@R1> show route table l3vpn.inet.0 hidden l3vpn.inet.0: 5 destinations, 5 routes (2 active, 0 holddown, 3 hidden) + = Active Route, - = Last Active, * = Both 100.64.1.0/24 [BGP/170] 00:00:15, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified Unusable 100.64.2.0/24 [BGP/170] 00:00:15, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified Unusable 100.64.3.0/24 [BGP/170] 00:00:15, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified Unusable
咦?LSP Down 后为啥 VRF 内路由全部消失了?因为 TE LSP 挂了后,inetcolor.0 里面路由表存放的 LSP 就消失了。但是 VRF 里面的符合条件的路由还是会去 inetcolor.0 查询下一跳,可表里面已经没条目了,还能解析出下一跳吗?不能!
所以我们需要给它配置 fallback 机制,来保证 LSP 消失后也能解析出下一跳。
root@R1# show | compare [edit protocols isis] + rib-group inet3 inetcolor-fallback; // 调用该 rib-group,将路由 copy 到 inetcolor.0 [edit routing-options rib-groups] + inetcolor-fallback { + import-rib [ inet.3 inetcolor.0 ]; // 配置 rib-group,将 inet.3 的路由(这是 BGP 解析下一跳默认的表)copy 到 inetcolor.0 + }
为什么用 IS-IS 协议来拷贝?因为 inet3 表里面的表项是由 IS-IS 进程生成的,所以需要在 IS-IS 里面操作。同样的,如果标签是 LDP 生成的,则需要在 LDP 进程里面操作。
操作完毕后,我们再来看一下 inetcolor.0 表:
root@R1> show route table inetcolor.0 inetcolor.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.2-0<c>/32 *[L-ISIS/14] 00:00:06, metric 20 > to 10.10.12.2 via ge-0/0/1.0 10.0.0.3-0<c>/32 *[L-ISIS/14] 00:00:06, metric 40 to 10.10.12.2 via ge-0/0/1.0, Push 16003 > to 10.10.15.5 via ge-0/0/4.0, Push 16003 10.0.0.4-0<c>/32 *[L-ISIS/14] 00:00:06, metric 60 > to 10.10.15.5 via ge-0/0/4.0, Push 16004 10.0.0.5-0<c>/32 *[L-ISIS/14] 00:00:06, metric 10 > to 10.10.15.5 via ge-0/0/4.0 10.0.0.6-0<c>/32 *[L-ISIS/14] 00:00:06, metric 20 > to 10.10.15.5 via ge-0/0/4.0, Push 16006 10.0.0.7-0<c>/32 *[L-ISIS/14] 00:00:06, metric 30 > to 10.10.15.5 via ge-0/0/4.0, Push 16007 10.0.0.8-0<c>/32 *[L-ISIS/14] 00:00:06, metric 40 > to 10.10.15.5 via ge-0/0/4.0, Push 16008 10.0.0.8-10<c>/64 *[SPRING-TE/8] 00:00:06, metric 1, metric2 40 > to 10.10.12.2 via ge-0/0/1.0, Push 16008, Push 15003, Push 16003(top) 10.0.0.8-20<c>/64 *[SPRING-TE/8] 00:00:06, metric 1, metric2 40 > to 10.10.12.2 via ge-0/0/1.0, Push 15000, Push 16003(top) 10.0.0.8-30<c>/64 *[SPRING-TE/8] 00:00:06, metric 1, metric2 40 > to 10.10.15.5 via ge-0/0/4.0, Push 15000, Push 16003, Push 16007(top)
很好,inet.3 里面的表项已经转化成 inetcolor.0 格式并拷贝到该表里面了。默认情况下,在 LSP up 的时候,数据会选择 LSP 进行转发,因为 LSP 表项掩码更长。而当 LSP down 的时候,就会 fallback 到 inet.3 拷贝过来的表项进行转发。
我们再次掐掉 SRTE Cpath 来看看情况:
root@R1# run show route table l3vpn.inet.0 l3vpn.inet.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 100.64.1.0/24 *[BGP/170] 00:07:38, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified > to 10.10.15.5 via ge-0/0/4.0, Push 16, Push 16008(top) 100.64.2.0/24 *[BGP/170] 00:07:38, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified > to 10.10.15.5 via ge-0/0/4.0, Push 16, Push 16008(top) 100.64.3.0/24 *[BGP/170] 00:07:38, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified > to 10.10.15.5 via ge-0/0/4.0, Push 16, Push 16008(top)
非常好,所有 colored route 全部 fallback 到 inet.3 拷贝过来的表项上做解析了,数据也是可通的。这样,配置就算是完成了。
但是,我觉得这样太麻烦,如果我来配置模板让路由器自己算路径自己引流会怎样呢?我们来使用 Juniper SR-TE DTM 来让路由器来自动化这个配置过程吧!
3. 使用 Juniper SR-TE DTM 来实现按需生成 SR-Policy
我准备让 BLUE LSP 使用 DTM 功能来自动生成,这样只要匹配到预配置的条件,路由器就会自动生成 SR-TE Policy,这样就非常的方便,在需要创建大量 LSP Policy 的时候尤其节省时间以及减少维护成本,所以我非常喜欢这个功能。
话不多说,现在就开始做:
root@R1# show routing-options dynamic-tunnels ODN-blue { // 创建 DTM Profile,名字叫 ODN-blue spring-te { // 激活为 segment routing TE 动态创建 Policy 的功能 source-routing-path-template { auto_blue color 10; // 调用刚刚配置好的模板,当遇到 color 10 的时候使用该模板创建 Policy } destination-networks { 10.0.0.0/24; // 下一跳为这个范围地址内的时候,动态创建 Policy,与上面调用的 template 互相作用,缺一不可 } } } root@R1# show protocols source-packet-routing compute-profile dynamic_blue { // 这是上面已经配置过的约束条件 admin-group include-any blue; metric-type { te; } } source-routing-path-template auto_blue { // 配置 ODN 模板 auto_blue primary { blue { compute { dynamic_blue; // 指定路径,名字为 blue (其实什么都行),调用 compute-profile dynamic_blue 作为计算时的约束条件 } } } }
配置完 ODN 功能后,我们来看看有没有自动创建隧道,以及 BGP 路由有没有被引入 LSP:
root@R1> show spring-traffic-engineering route To Source SR Override Pref/Pref LSP Name Segment Lists 10.0.0.8-10<c> Dynamic Tunnel Module(DTM) 100 / 100 10.0.0.8:a:dt-srte-ODN-blue blue 10.0.0.8-20<c> Static configuration 100 / 100 orange orange 10.0.0.8-30<c> Static configuration 100 / 100 te te 15666 Static configuration 100 / 100 orange orange 15777 Static configuration 100 / 100 te te root@R1> show route table l3vpn.inet.0 100.64.1.0/24 l3vpn.inet.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 100.64.1.0/24 *[BGP/170] 00:23:35, localpref 100, from 10.0.0.8 AS path: I, validation-state: unverified > to 10.10.12.2 via ge-0/0/1.0, Push 16, Push 16008, Push 15003, Push 16003(top)
可见 Color 10 隧道已经由 Juniper SR-TE DTM 动态创建,由于约束条件和我上面手动创建的 Policy 约束条件一样,所以路径也是一样的,可以由下面 VRF 内路由表项得出结论。
到最后,我们来测试下路由的走向:
root@L3VPN-Client-A:~# mtr 100.64.1.2 -n --report Start: 2021-06-18T14:29:10+0000 HOST: L3VPN-Client-A Loss% Snt Last Avg Best Wrst StDev 1.|-- 100.64.0.1 0.0% 10 2.6 25.4 1.6 230.9 72.2 2.|-- 10.10.12.2 0.0% 10 7.7 23.0 7.5 74.8 26.0 3.|-- 10.10.23.3 0.0% 10 10.5 15.5 7.2 65.6 17.8 4.|-- 10.10.34.4 0.0% 10 17.9 21.5 7.6 73.2 22.1 5.|-- 100.64.1.1 0.0% 10 7.1 70.1 6.5 481.6 151.9 6.|-- 100.64.1.2 0.0% 10 8.1 9.3 7.6 13.4 2.1 // 由 Blue LSP 引流,路径 R1 -> R2 -> R3 -> R4 -> R8,符合题意 root@L3VPN-Client-A:~# mtr 100.64.2.2 -n --report Start: 2021-06-18T14:29:28+0000 HOST: L3VPN-Client-A Loss% Snt Last Avg Best Wrst StDev 1.|-- 100.64.0.1 0.0% 10 1.6 45.3 1.6 387.3 121.1 2.|-- 10.10.12.2 0.0% 10 81.1 18.8 7.5 81.1 22.8 3.|-- 10.10.23.3 0.0% 10 10.6 59.9 5.5 515.3 160.0 4.|-- 100.64.1.1 0.0% 10 20.9 31.7 5.6 213.4 64.4 5.|-- 100.64.2.2 0.0% 10 8.3 8.1 6.5 12.7 1.9 // 由 Orange LSP 引流,路径 R1 -> R2 -> R3 -> R8,符合题意 root@L3VPN-Client-A:~# mtr 100.64.3.2 -n --report Start: 2021-06-18T14:29:45+0000 HOST: L3VPN-Client-A Loss% Snt Last Avg Best Wrst StDev 1.|-- 100.64.0.1 0.0% 10 2.1 15.4 1.9 132.6 41.2 2.|-- 10.10.15.5 0.0% 10 71.4 55.8 8.8 334.2 100.7 3.|-- 10.10.56.6 0.0% 10 9.3 39.9 7.4 210.6 68.2 4.|-- 10.10.67.7 0.0% 10 8.2 41.2 7.3 289.3 88.0 5.|-- 10.10.37.3 0.0% 10 8.0 16.4 7.7 56.0 14.3 6.|-- 100.64.1.1 0.0% 10 10.3 11.1 6.7 37.7 9.4 7.|-- 100.64.3.2 0.0% 10 7.4 9.1 6.4 13.6 2.2 // 由 TE LSP 引流(通过 TE Metric 计算出来的路径,不含亲和属性作为约束条件),路径 R1 -> R5 -> R6 -> R7 -> R3 -> R8,符合题意
到这里,我们就完成了 Juniper 设备的 SRTE 配置,真的是坑死人不偿命啊。
总结:
- 要是使用链路亲和属性作为计算条件,你需要打开 RSVP,否则亲和属性不会注入到 IS-IS TLV 里面,应该是设计问题。
- 亲和属性 include-any 如果路上出现了不包含指定的 affinity 的链路,则计算会失败,应该也是设计问题。Cisco 没有这个毛病。
- 配置 SRTE 前,请将接口的 Max label 调大,否则堆栈标签数超过接口限制会导致下一跳 unusable
- 配置 SRTE Policy 时,一定要记得把 inet.3 copy 到 inetcolor.0 (为了 LSP 挂了后能 fallback)
参考资料:
《[ SR-TE ] 在 Juniper 设备中使用 SR-TE DTM 调度流量》有3个想法
太感謝了,我也是從cisco的SRTE跳到juniper的,這篇對我的幫助極大,感謝分享!!
感谢支持。
请问大佬,您这个网络中color怎么定义的?,能不能提供一个模板?