Segment Routing 是一种基于源路由(转发路径由流量的源节点预定义)范式的路由技术,其通过在源节点上将称为 Segment 的指令的列表嵌入至数据包中,以此定义数据包的转发路径。

为何选择 Segment Routing

相较其它路由技术,Segment Routing 具有以下优势:

  • 简便:无需额外的信令协议(LDP,RSVP-TE),SR 路由信息可通过具有相关拓展功能的链路状态协议(IS-IS,OSPF)传播。
  • 可拓展性:由于中间节点无需维护路径的状态,只需根据数据包中定义的 Segment 列表执行对应指令,中间节点的资源可得到更大节约。
  • 支持流量工程:Segment Routing 基于源路由范式,可根据具体的需要对转发路径进行编程。
  • 消除 BGP 黑洞:引入内部的第二数据平面(MPLS/SRv6),将数以万计的 BGP 路由映射到数条第二数据平面的路由上,使不运行 BGP 的中间节点能够正常转发网际流量,节约资源。

以下是一些主流路由技术的对比:

名称 简便 可拓展性 支持流量工程 消除 BGP 黑洞
纯 IPv4/IPv6
MPLS 和 LDP
MPLS 和 RSVP-TE
Segment Routing

为何选择 SRv6

主要原因:这篇文章讲的就是 SRv6。

Segment Routing 可直接运行在 MPLS(SR-MPLS)和 IPv6(SRv6)数据平面之上。

Segment Routing over MPLS(SR-MPLS)是一种工作在 MPLS 数据平面之上的 Segment Routing 技术,其通过将 Segment 列表以标签栈的形式编入 MPLS 数据包实现 Segment Routing,无需对 MPLS 协议栈本身做出任何修改。

Segment Routing over IPv6(SRv6)是一种工作在 IPv6 数据平面之上的 Segment Routing 技术,其通过为 IPv6 的 Routing Header 引入新类型:SR Header(SRH)使之具备 Segment Routing 能力。

相较 SR-MPLS,SRv6 是一位更常被提起的“明日之子”,:

  • 更好的兼容性:SRv6 可在现网不全域实施 Segment Routing 的情况下在边缘节点上实施,可以循序渐进地实施,中间节点会将 SRv6 数据包视为普通的 IPv6 数据包传输,而 SR-MPLS 的改造需要整个网域的配合。
  • 更高的流行度:SRv6 更常被大家提到,而 Linux 更是将其集成为网络协议栈的一部分,且无需额外加载内核模块;SR-MPLS 依赖 MPLS,需要额外加载内核模块,这对于使用 LXC 技术的节点是几乎不可能的。
  • 更大的寻址空间:SRv6 基于 IPv6,单个 SRv6 Locator 最小可为一个 /64 大小的网络,其可提供 2^64 个 IPv6 地址以供 SR 网络功能使用,而 SR-MPLS 使用的 MPLS 最多支持 2^20 的寻址空间,其数量略小于全球 IPv4 路由表的规模(当前全球 IPv4 路由表的路由条目数量在一百万条以上),可拓展性相对有限。

目录

1 准备工作

本文对读者有前置知识要求:

本文中出现的所有节点均是以下配置:

  • 运行 Debian
  • 使用 GRE over Wireguard 进行节点间互联
  • 运行 FRR 路由套件
  • 使用 IS-IS 作为 IGP
  • 使用 DN42-GT 和 THIS-AS VRF
  • 使用 DN42-GT 与其它网络互联
  • 将本网路由放在 THIS-AS VRF 中发布

本文所展示的 DN42 over SRv6 L3VPN 部署是在我的真实 DN42 网络基础设施上进行的。

1.1 安装 FRR

目前,想要在 Linux 上实施 SRv6,FRR 是最方便的选择,而且我的基础设施也一直运行着 FRR。

不同的发行版安装各有不同,我的节点大多运行基于 Debian 的发行版,可通过 https://deb.frrouting.org 寻得对应版本的下载方式。

如若您同我一样使用 Debian,不要忘记安装 frr-rpki-rtrlib,它是 FRR 运行 RPKI 协议的依赖,ROA 过滤是 DN42 网络的必选项。

FRR DN42 配置的常规部分可参阅 FRRouting

1.2 修改内核参数

Universal Network Requirements 的基础上,添加:

net.ipv6.seg6_flowlabel=1
net.ipv6.conf.all.seg6_enabled=1
net.vrf.strict_mode=1

注意:net.vrf.strict_mode 是一项关键参数,它决定了不同的 VRF 是否能够共享同一张路由表,当其值为 1 时,每个 VRF 都必须使用独立的路由表。 若其值不为 1,则 SRv6 IPv4 L3VPN 将无法正常工作,相关的 SID 路由将被拒绝。

1.3 配置网络接口和 VRF

net.vrf.strict_mode 会在每次 VRF 添加后重置为 0,为了避免网络运作的中断,请尽可能预先创建好所有需要用到的 VRF。

以下所有指令都不是持久化的,使用何种持久化方案取决于您的选择。

以下是使用 iproute2 创建 DN42-GT 和 THIS-AS VRF 的命令:

ip link add DN42-GT type vrf table 300
ip link add THIS-AS type vrf table 100
ip link set DN42-GT up
ip link set THIS-AS up

IS-IS 需要一个 dummy 接口用于指向 SRv6 Locator 路由(默认名称为 sr0):

ip link add sr0 type dummy
ip link set sr0 up mtu 65536

IS-IS 需要工作在可承载以太网帧(gretap,l2tpv3)或支持 OSI 封装(gre)的隧道上,所以透过 Wireguard 的 IPv4 地址创建 GRE 隧道:

ip link add azj1 type gre local 169.254.24.3 remote 169.254.24.17 nopmtudisc
sysctl -w net.ipv6.conf.azj1.seg6_enabled=1

由于未知的原因,FRR 无法使用 ip6gre 隧道承载 IS-IS 流量,ip6gre 似乎不支持 OSI 封装,所以请不要使用 IPv6 建立 GRE 隧道(但是 ip6gretap 承载的是以太网帧,所以可以)。

2 FRR 配置

在每一个网络节点上进行以下配置,本文以我的 CAN1 节点配置为例。

IP 和 SRv6 Locator 分配:

  • SRv6 Locator:5f00:3947:3::/48
  • lo:
    • fdfa:7906:8262:ffff::3/128,用于 BGP L3VPN 会话建立
    • 5f00:3947:3::1/128,作为 SRv6 源地址使用

2.1 daemons 配置

启用 BGP 和 IS-IS,并启用 RPKI 支持。

# This file tells the frr package which daemons to start.
#
# Sample configurations for these daemons can be found in
# /usr/share/doc/frr/examples/.
#
# ATTENTION:
#
# When activating a daemon for the first time, a config file, even if it is
# empty, has to be present *and* be owned by the user and group "frr", else
# the daemon will not be started by /etc/init.d/frr. The permissions should
# be u=rw,g=r,o=.
# When using "vtysh" such a config file is also needed. It should be owned by
# group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
#
# The watchfrr, zebra and staticd daemons are always started.
#
bgpd=yes
ospfd=no
ospf6d=no
ripd=no
ripngd=no
isisd=yes
pimd=no
pim6d=no
ldpd=no
nhrpd=no
eigrpd=no
babeld=no
sharpd=no
pbrd=yes
bfdd=yes
fabricd=no
vrrpd=no
pathd=yes

#
# If this option is set the /etc/init.d/frr script automatically loads
# the config via "vtysh -b" when the servers are started.
# Check /etc/pam.d/frr if you intend to use "vtysh"!
#
vtysh_enable=yes
zebra_options="  -A 127.0.0.1 -s 90000000"
mgmtd_options="  -A 127.0.0.1"
bgpd_options="   -A 127.0.0.1 -M rpki"
ospfd_options="  -A 127.0.0.1"
ospf6d_options=" -A ::1"
ripd_options="   -A 127.0.0.1"
ripngd_options=" -A ::1"
isisd_options="  -A 127.0.0.1"
pimd_options="   -A 127.0.0.1"
pim6d_options="  -A ::1"
ldpd_options="   -A 127.0.0.1"
nhrpd_options="  -A 127.0.0.1"
eigrpd_options=" -A 127.0.0.1"
babeld_options=" -A 127.0.0.1"
sharpd_options=" -A 127.0.0.1"
pbrd_options="   -A 127.0.0.1"
staticd_options="-A 127.0.0.1"
bfdd_options="   -A 127.0.0.1"
fabricd_options="-A 127.0.0.1"
vrrpd_options="  -A 127.0.0.1"
pathd_options="  -A 127.0.0.1"


# If you want to pass a common option to all daemons, you can use the
# "frr_global_options" variable.
#
#frr_global_options=""


# The list of daemons to watch is automatically generated by the init script.
# This variable can be used to pass options to watchfrr that will be passed
# prior to the daemon list.
#
# To make watchfrr create/join the specified netns, add the the "--netns"
# option here. It will only have an effect in /etc/frr/<somename>/daemons, and
# you need to start FRR with "/usr/lib/frr/frrinit.sh start <somename>".
#
#watchfrr_options=""


# configuration profile
#
#frr_profile="traditional"
#frr_profile="datacenter"


# This is the maximum number of FD's that will be available.  Upon startup this
# is read by the control files and ulimit is called.  Uncomment and use a
# reasonable value for your setup if you are expecting a large number of peers
# in say BGP.
#
#MAX_FDS=1024

# Uncomment this option if you want to run FRR as a non-root user. Note that
# you should know what you are doing since most of the daemons need root
# to work. This could be useful if you want to run FRR in a container
# for instance.
# FRR_NO_ROOT="yes"

# For any daemon, you can specify a "wrap" command to start instead of starting
# the daemon directly. This will simply be prepended to the daemon invocation.
# These variables have the form daemon_wrap, where 'daemon' is the name of the
# daemon (the same pattern as the daemon_options variables).
#
# Note that when daemons are started, they are told to daemonize with the `-d`
# option. This has several implications. For one, the init script expects that
# when it invokes a daemon, the invocation returns immediately. If you add a
# wrap command here, it must comply with this expectation and daemonize as
# well, or the init script will never return. Furthermore, because daemons are
# themselves daemonized with -d, you must ensure that your wrapper command is
# capable of following child processes after a fork() if you need it to do so.
#
# If your desired wrapper does not support daemonization, you can wrap it with
# a utility program that daemonizes programs, such as 'daemonize'. An example
# of this might look like:
#
# bgpd_wrap="/usr/bin/daemonize /usr/bin/mywrapper"
#
# This is particularly useful for programs which record processes but lack
# daemonization options, such as perf and rr.
#
# If you wish to wrap all daemons in the same way, you may set the "all_wrap"
# variable.
#
#all_wrap=""

2.2 配置接口 IP 地址

编辑 /etc/frr/frr.conf,添加以下配置:

lo:

!
interface lo
 ipv6 address 5f00:3947:3::1/128
 ipv6 address fdfa:7906:8262:ffff::3/128
 ipv6 router isis 1
 mpls enable
exit
!

2.3 配置 SRv6 Locator

目前,IANA 已为 SRv6 分配 5f00::/16 作为 SRv6 SID 使用,我取其中的 5f00:3947::/32 作为本网的 SRv6 网络块使用,并为每个节点分配 /48 大小的 5f00:3947:x::/48 作为 SRv6 Locator,使用 usid-f3216 作为 SID 分配格式。

在 /etc/frr/frr.conf 中添加如下配置:

!
segment-routing
 srv6
  encapsulation
   source-address 5f00:3947:3::1
  exit
  locators
   locator MAIN
    prefix 5f00:3947:3::/48 block-len 32 node-len 16
    behavior usid
    format usid-f3216
   exit
   !
  exit
  !
 exit
 !
exit
!

如果您打算使用自己的 DN42 IPv6 地址块作为 SRv6 Locator,为每个节点分配 /64 大小的 SRv6 Locator,请使用 usid-f4816。

2.4 配置 IS-IS SRv6

SRv6 Locator 配置后,还需要配置 IS-IS 去发布 SRv6 Locator 路由。

至于为何使用 IS-IS,因为目前 IS-IS 是 FRR 唯一支持 SRv6 的 IGP。

IS-IS 使用 CLNS 格式的 NET(Network Entity Title)标识节点,其是可变长的,主要由两个部分组成:

  • Area ID(1~13字节)
  • System ID(7字节)
    • Station ID(6字节)
    • Selector(1字节)

Area ID 的格式有以下常见变种:

  • 单个1字节区域标识作为 Area Address
    • 如:00
  • AFI(1字节)+ Area(2字节)
    • 如:49.0000
  • AFI(1字节)+ Domain(2字节)+ Area(2字节)
    • 如:49.0000.0000

CAN1 分配 NET 49.0000.1720.2020.9096.00,将以下配置写入 /etc/frr/frr.conf:

!
router isis 1
 is-type level-1
 net 49.0000.1720.2020.9096.00
 lsp-mtu 1277
 segment-routing on
 segment-routing srv6
  locator MAIN
 exit
exit
!

2.5 配置 BGP SRv6

配置通过 IGP 广播 SRv6 路由后,还需配置 BGP 使用对应的 SRv6 Locator,BGP L3VPN 使用该 SRv6 Locator 为 VRF 绑定并生成对应的 SID。

将以下配置写入 /etc/frr/frr.conf 的 BGP 配置块中:

 !
 segment-routing srv6
  locator MAIN
 exit
 !

如果不知道到底该在什么位置插入,可参考稍后部分的完整配置。

2.6 配置 SRv6 L3VPN

在默认 VRF 中配置 BGP L3VPN Peer:

router bgp 4242423947
 bgp router-id 172.20.209.96
 no bgp default ipv4-unicast
 neighbor ibgp peer-group
 neighbor ibgp remote-as 4242423947
 neighbor ibgp update-source lo
 neighbor ibgp capability extended-nexthop
 neighbor fdfa:7906:8262:ffff::1 peer-group ibgp
 neighbor fdfa:7906:8262:ffff::1 description hkg1
 neighbor fdfa:7906:8262:ffff::6 peer-group ibgp
 neighbor fdfa:7906:8262:ffff::6 description fra1

激活 BGP L3VPN Peer:

address-family ipv4 vpn
  neighbor ibgp activate
 exit-address-family
address-family ipv6 vpn
  neighbor ibgp activate
 exit-address-family

如果不知道到底该在什么位置插入,可参考稍后部分的完整配置。

对应 VRF 的 IPv4 单播和 IPv6 单播地址家族配置 VPN 导入导出,RD,RT 导入导出和 SID 绑定:

 address-family ipv4 unicast
  sid vpn export auto
  rd vpn export 172.20.209.96:100
  rt vpn import 4242423947:100 4242423947:300 4242423947:301 4242423947:500
  rt vpn export 4242423947:100
  export vpn
  import vpn
 exit-address-family
 !
 address-family ipv6 unicast
  sid vpn export auto
  rd vpn export 172.20.209.96:100
  rt vpn import 4242423947:100 4242423947:300 4242423947:301 4242423947:500
  rt vpn export 4242423947:100
  export vpn
  import vpn
 exit-address-family

如果不知道到底该在什么位置插入,可参考稍后部分的完整配置。

2.7 CAN1 完整 FRR 配置

我在此提供 CAN1 节点在去除不使用的 route-map 和 eBGP peer 配置后的完整 FRR 配置以供读者参考,其中还包含 VRF RPKI 和 BFD 配置。

frr version 10.6.1
frr defaults traditional
hostname SERNET-CAN1
log syslog informational
service integrated-vtysh-config
!
ip prefix-list dn42-subnet seq 1100 permit 172.20.0.0/14 le 32
ip prefix-list dn42-subnet seq 2001 permit 10.100.0.0/14 le 32
ip prefix-list dn42-subnet seq 2002 permit 10.127.0.0/16 le 32
ip prefix-list dn42-subnet seq 2003 permit 10.0.0.0/8 ge 15 le 24
ip prefix-list dn42-subnet seq 3001 permit 172.31.0.0/16 le 32
ip prefix-list dn42-subnet seq 9999 deny 0.0.0.0/0 le 32
ip prefix-list global seq 1 permit 172.20.209.64/26
ip prefix-list local seq 2 permit 172.20.209.120/29
ip prefix-list local seq 3 permit 172.20.209.96/28
ip prefix-list vrf_local seq 1 permit 169.254.23.0/24 le 32
!
ipv6 prefix-list dn42-subnet seq 1 permit fd00::/8 ge 44 le 64
ipv6 prefix-list dn42-subnet seq 65535 deny ::/0 le 128
ipv6 prefix-list global seq 1 permit fdfa:7906:8262::/48
!
route-map inbound permit 10
 on-match next
 set local-preference 100
exit
!
route-map inbound permit 20
 match as-path adj
 on-match next
 set local-preference +150
exit
!
route-map inbound permit 21
 match community region
 on-match next
 set local-preference +110
exit
!
route-map inbound permit 22
 match community country
 set local-preference +110
exit
!
route-map inbound permit 65535
 call rpki
exit
!
route-map local-as-only permit 10
 match as-path self
exit
!
route-map outbound permit 10
 call set-community
 match as-path self
 match rpki valid
exit
!
route-map outbound permit 20
 call rpki
exit
!
route-map redistribute-connected permit 10
 match ip address prefix-list dn42-subnet
exit
!
route-map redistribute-connected permit 20
 match ipv6 address prefix-list dn42-subnet
exit
!
route-map rpki permit 10
 match rpki valid
exit
!
route-map rpki permit 20
 match rpki notfound
 on-match goto 40
exit
!
route-map rpki deny 30
 match rpki invalid
exit
!
route-map rpki permit 40
 match ip address prefix-list dn42-subnet
exit
!
route-map rpki permit 41
 match ipv6 address prefix-list dn42-subnet
exit
!
route-map set-community permit 10
 set community 64511:52 64511:1156
exit
!
ip route 172.20.0.0/14 dn42-service nexthop-vrf THIS-AS
ip route 172.31.0.0/16 dn42-service nexthop-vrf THIS-AS
ip route 172.16.135.0/24 dn42-service nexthop-vrf THIS-AS
ipv6 route fd00::/8 dn42-service nexthop-vrf THIS-AS
ipv6 route fdfa:7906:8262:c530::/64 dn42-service nexthop-vrf THIS-AS
ip router-id 172.20.209.96
!
vrf DN42-GT
 ipv6 route fdfa:7906:8262:c530::/64 dn42-service
 rpki
  rpki cache tcp 169.254.23.1 8082 preference 10
 exit
exit-vrf
!
vrf THIS-AS
 ip route 0.0.0.0/0 ens5 nexthop-vrf default
 ip route 10.0.0.0/8 Null0
 ip route 172.20.0.0/14 Null0
 ip route 10.127.217.0/24 Null0
 ip route 172.20.209.64/26 Null0
 ipv6 route fd00::/8 Null0
 ipv6 route fdfa:7906:8262::/48 Null0
 ipv6 route fdfa:7906:8262:cf00::/56 Null0
 ipv6 route fdfa:7906:8262:c530::/64 dn42-service
 ipv6 route fdfa:7906:8262:cf00::/64 access-hawkins
exit-vrf
!
vrf DN42-PT
exit-vrf
!
vrf NEO-HAWKINS
exit-vrf
!
interface DN42-GT
 ip address 169.254.23.1/32
exit
!
interface THIS-AS
 ip address 10.127.217.66/32
 ip address 172.20.209.96/32
 ipv6 address fdfa:7906:8262:f::3/128
 ipv6 address fdfa:7906:8262:ffff::3/128
exit
!
interface azj1
 ipv6 router isis 1
 isis bfd
 isis bfd profile internet
 isis fast-reroute lfa
 isis network point-to-point
 mpls enable
exit
!
interface ctu1
 ipv6 router isis 1
 isis bfd
 isis bfd profile internet
 isis fast-reroute lfa
 isis network point-to-point
 mpls enable
 link-params
 exit-link-params
exit
!
interface dn42-service
 pbr-policy to-dn42
exit
!
interface fra1
 ipv6 router isis 1
 isis bfd
 isis bfd profile internet
 isis fast-reroute lfa
 isis metric 20
 isis network point-to-point
 mpls enable
 link-params
 exit-link-params
exit
!
interface hkg1
 ipv6 router isis 1
 isis bfd
 isis bfd profile internet
 isis fast-reroute lfa
 isis metric 4
 isis network point-to-point
 mpls enable
 link-params
 exit-link-params
exit
!
interface lo
 ipv6 address 5f00:3947:3::1/128
 ipv6 address fdfa:7906:8262:ffff::3/128
 ipv6 router isis 1
 mpls enable
exit
!
interface sjc1
 ipv6 router isis 1
 isis bfd
 isis bfd profile internet
 isis fast-reroute lfa
 isis metric 20
 isis network point-to-point
 mpls enable
 link-params
 exit-link-params
exit
!
interface tyo1
 ipv6 router isis 1
 isis bfd
 isis bfd profile internet
 isis fast-reroute lfa
 isis metric 15
 isis network point-to-point
 mpls enable
 link-params
 exit-link-params
exit
!
interface wds1
 ipv6 router isis 1
 isis bfd
 isis bfd profile internet
 isis fast-reroute lfa
 isis network point-to-point
 mpls enable
 link-params
 exit-link-params
exit
!
router bgp 4242423947
 bgp router-id 172.20.209.96
 no bgp default ipv4-unicast
 neighbor ibgp peer-group
 neighbor ibgp remote-as 4242423947
 neighbor ibgp update-source lo
 neighbor ibgp capability extended-nexthop
 neighbor fdfa:7906:8262:ffff::1 peer-group ibgp
 neighbor fdfa:7906:8262:ffff::1 description hkg1
 neighbor fdfa:7906:8262:ffff::6 peer-group ibgp
 neighbor fdfa:7906:8262:ffff::6 description fra1
 !
 segment-routing srv6
  locator MAIN
  no srv6-only
 exit
 !
 address-family ipv4 unicast
  label vpn export auto
  sid vpn export auto
  rd vpn export 172.20.209.96:0
  rt vpn export 4242423947:100
  export vpn
 exit-address-family
 !
 address-family ipv4 vpn
  neighbor ibgp activate
 exit-address-family
 !
 address-family ipv6 unicast
  label vpn export auto
  sid vpn export auto
  rd vpn export 172.20.209.96:0
  rt vpn export 4242423947:100
  export vpn
 exit-address-family
 !
 address-family ipv6 vpn
  neighbor ibgp activate
 exit-address-family
exit
!
router bgp 4242423947 vrf DN42-GT
 bgp router-id 172.20.209.96
 no bgp enforce-first-as
 no bgp default ipv4-unicast
 no bgp network import-check
 !
 address-family ipv4 unicast
  neighbor ebgp-DN42-GT activate
  neighbor ebgp-DN42-GT route-map inbound in
  neighbor ebgp-DN42-GT route-map outbound out
  neighbor ebgp4-DN42-GT activate
  neighbor ebgp4-DN42-GT route-map inbound in
  neighbor ebgp4-DN42-GT route-map outbound out
  neighbor ebgp6-DN42-GT activate
  sid vpn export auto
  rd vpn export 172.20.209.96:300
  rt vpn import 4242423947:100 4242423947:300 4242423947:301 4242423947:500
  rt vpn export 4242423947:300
  export vpn
  import vpn
 exit-address-family
 !
 address-family ipv6 unicast
  neighbor ebgp-DN42-GT activate
  neighbor ebgp-DN42-GT route-map inbound in
  neighbor ebgp-DN42-GT route-map outbound out
  neighbor ebgp6-DN42-GT activate
  neighbor ebgp6-DN42-GT route-map inbound in
  neighbor ebgp6-DN42-GT route-map outbound out
  sid vpn export auto
  rd vpn export 172.20.209.96:300
  rt vpn import 4242423947:100 4242423947:300 4242423947:301 4242423947:500
  rt vpn export 4242423947:300
  export vpn
  import vpn
 exit-address-family
exit
!
router bgp 4242423947 vrf THIS-AS
 no bgp default ipv4-unicast
 neighbor 172.16.135.2 remote-as 4242423947
 neighbor 172.16.135.2 description exabgp
 neighbor fdfa:7906:8262:c530::2 remote-as 4242423947
 neighbor fdfa:7906:8262:c530::2 description exabgp
 !
 address-family ipv4 unicast
  network 10.127.217.0/24
  network 10.127.217.2/32
  network 10.127.217.66/32
  network 172.16.128.0/24
  network 172.20.209.64/26
  network 172.20.209.96/32
  redistribute connected route-map redistribute-connected
  neighbor 172.16.135.2 activate
  sid vpn export auto
  rd vpn export 172.20.209.96:100
  rt vpn import 4242423947:100 4242423947:300 4242423947:301 4242423947:500
  rt vpn export 4242423947:100
  export vpn
  import vpn
 exit-address-family
 !
 address-family ipv6 unicast
  network fdfa:7906:8262::/48
  network fdfa:7906:8262:f::3/128
  network fdfa:7906:8262:c500::/64
  network fdfa:7906:8262:c530::/64
  network fdfa:7906:8262:cf00::/56
  redistribute connected route-map redistribute-connected
  neighbor fdfa:7906:8262:c530::2 activate
  sid vpn export auto
  rd vpn export 172.20.209.96:100
  rt vpn import 4242423947:100 4242423947:300 4242423947:301 4242423947:500
  rt vpn export 4242423947:100
  export vpn
  import vpn
 exit-address-family
exit
!
router isis 1
 is-type level-1
 net 49.0000.1720.2020.9096.00
 lsp-mtu 1277
 segment-routing on
 segment-routing srv6
  locator MAIN
 exit
exit
!
bgp as-path access-list adj seq 5 permit ^[0-9]*$
bgp as-path access-list always-send seq 1 permit ^$
bgp as-path access-list self seq 5 permit ^$
!
bgp community-list standard country seq 1 permit 64511:1156
bgp community-list standard region seq 1 permit 64511:52
bgp extcommunity-list standard no-import-rt seq 1 permit rt 4242423947:0
bgp extcommunity-list standard premium-rt seq 1 permit rt 4242423947:100
bgp extcommunity-list standard premium-rt seq 2 permit rt 4242423947:301
!
pbr-map to-dn42 seq 1
 match dst-ip fd00::/8
 set vrf THIS-AS
exit
!
pbr-map to-dn42 seq 2
 match dst-ip 10.0.0.0/8
 set vrf THIS-AS
exit
!
pbr-map to-dn42 seq 3
 match dst-ip 172.20.0.0/14
 set vrf THIS-AS
exit
!
pbr-map to-dn42 seq 4
 match dst-ip 172.31.0.0/16
 set vrf THIS-AS
exit
!
pbr-map to-dn42 seq 5
 match dst-ip 172.16.128.0/24
 set vrf THIS-AS
exit
!
segment-routing
 srv6
  encapsulation
   source-address 5f00:3947:3::1
  exit
  locators
   locator MAIN
    prefix 5f00:3947:3::/48 block-len 32 node-len 16
    behavior usid
    format usid-f3216
   exit
   !
  exit
  !
 exit
 !
 traffic-eng
 exit
exit
!
bfd
 profile internet
  detect-multiplier 5
  transmit-interval 1000
  receive-interval 1000
 exit
 !
exit
!

3 验证

接下来的验证步骤将在一台通过 CAN1 节点接入 DN42 网络的 PC 机上进行。

3.1 抓包

使用 Wireshark 的 SSH 远程抓包功能在 CAN1 节点上进行抓包,抓取连接 HKG1 节点的链路 hkg1。

为了方便读者更直观地看到 SRv6 相关的抓包内容,配置 PCAP 过滤器: pcap filter

随后可以启动抓包。

3.2 Ping 网内地址

172.20.209.64 配置在 HKG1 节点上,它必然会经过 hkg1 链路。

PS C:\Users\haksr> ping 172.20.209.64

Pinging 172.20.209.64 with 32 bytes of data:
Reply from 172.20.209.64: bytes=32 time=22ms TTL=63
Reply from 172.20.209.64: bytes=32 time=24ms TTL=63
Reply from 172.20.209.64: bytes=32 time=24ms TTL=63
Reply from 172.20.209.64: bytes=32 time=24ms TTL=63

Ping statistics for 172.20.209.64:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 22ms, Maximum = 24ms, Average = 23ms

3.3 ing 跨节点网外地址

wiki.dn42 (172.23.0.80) 的流量也会经过 hkg1 链路:

Pinging 172.23.0.80 with 32 bytes of data:
Reply from 172.23.0.80: bytes=32 time=29ms TTL=63
Reply from 172.23.0.80: bytes=32 time=28ms TTL=63
Reply from 172.23.0.80: bytes=32 time=32ms TTL=63
Reply from 172.23.0.80: bytes=32 time=26ms TTL=63

Ping statistics for 172.23.0.80:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 26ms, Maximum = 32ms, Average = 28ms

3.4 访问 wiki.dn42

wiki.dn42

3.5 抓包内容一览

packet capture srv6_2026-07-30-1838

4 已知限制

4.1 NAT

当流量的目的地址的路由带有 SRv6 封装时,流量不会触发 netfilter 的 SNAT 规则,而是直接封装成 SRv6 流量发送过去。

4.2 路由器 IPv6 地址无法访问

由于未知原因,IPv4 和 IPv6 的 SRv6 解包调用路径并不一样,IPv4 回程流量能够正常切换到目标 VRF 查表,IPv6 流量却不能。不过不影响转发流量,只影响源或者目的地址在路由器上的流量。