SRv6学习

最近在学习SRv6相关的知识, 实践方面参考这篇 使用 mininet的 博客。我这里使用 core 平台 搭建了个简易场景 体会 SRv6 整个数据的ip包的包装解析。二者都是使用轻量 lxc容器 模拟 SRv6路由器节点,使用quagga构建路由器间的路由表。在实践前 先学习相关理论知识。

SRv6背景

在网络发展初期,ip网络的无连接尽力而为的设计理念战胜了类如采用固定长度信元交换的ATM等面向连接的设计理念的传输技术。随着后续的网络发展,为了满足IP网络QoS能力,开发了LANE,IPoA等,完成的比较好的是 MPLS (Multiprotocol Label Switching)。可以支撑TE (Traffic Engineering)、VPN和FRR等技术,其虚拟标签的的设计为无连接的IP网络保障QoS能力,还具备IP路由的灵活性。

但是随着网络发展 IPv4地址耗尽需要扩展至IPv6,MPLS无法基于全局视角做出全局最优网络决策,数据面与控制面的紧密耦合等问题,逐渐有了SDN即为网络提供可编程能力的想法。

SR技术是SDN竞争压力下的产物,其核心思想是将报文转发路径切割为不同的分段,并在路径起始点往报文中插入分段信息,中间节点只需要按照报文里携带的分段信息转发即可。这样的路径分段,称之为 “Segment” ,并通过SID(Segment Identifier,段标识)来标识。报文在SR技术的转发过程也是类似的。由上可知,SR技术关键在于两点:对路径进行分段 (Segment) 以及在起始节点对路径进行排序成表 (Segment List) ,确定出行路径。

在SR技术中,将代表不同功能的Segment进行组合,可以实现对路径的编程,满足不同路径服务质量的需求。SR技术支持MPLS和IPv6两种转发平面,基于MPLS转发平面的SR称为 SR-MPLS(Segment Routing MPLS),其SID为MPLS标签(Label);基于IPv6转发平面的SR称为 SRv6 ,其SID为IPv6地址。

SRv6 技术使命

  • SRv6兼容IPv6的路由转发,基于IP可达性更加容易实现不同网络互联,不需要像MPLS那样使用额外信令,也不需要全网升级。
  • SRv6基于SRH ( Segment Routing Header, 段路由扩展报文头)能够支持更多种类的封装,可以很好地满足新业务的多样化需求。
  • SRv6对于IPv6的亲和性使得它能够将IP承载网与支持IPv6的应用无缝融合在一起,通过网络感知应用,使运营商可以提供更多可能的增值业务。

SRv6的设计

SRv6将网络比作计算机,类比计算机编程,将网络承载的业务翻译成发给沿途网络设备的一系列转发指令,从而实现网络编程,满足业务的定制化需求。

  • SRH设计

    为基于IPv6转发平面实现SR技术,在IPv6路由扩展头新增SRH(Segment Routing Header)扩展头,该扩展头指定一个IPv6的显式路径,存储IPv6的Segment List信息。Segment List即对段和网络节点进行有序排列得到的一条转发路径。报文转发时,依靠 Segments LeftSegment List 字段共同决定IPv6目的地址(IPv6 DA)信息,从而指导报文的转发路径和行为。

    字段名长度含义
    Next Header8 bit标识紧跟在SRH之后的报文头的类型。常见的几种类型如下。4: IPv4封装。41: IPv6封装。43: IPv6 Routing Header.58: ICMPv6 (Internet Control Message Protocol version6)59: Next Header为空
    Hdr Ext Len8 bitSRH的长度,指不包括前64 bit (前64 bit为固定长度)的SRH的长度
    Routing Type8 bit标识路由扩展报文头类型,标记SRH的值为4
    Segments Left8 bit剩余的Segment数目,简称SL
    Last Entry8 bitsegment List 的最后一个元素的索引
    Flags8 bit预留的标志位,用于特殊的处理,比如OAM
    Tag16 bit标识同组报文
    Segment List[n]128 * n bitSegment List 中的第n个Segment, Segment 的值是IPv6地址的形式
    Optional TLV可变可选TLV (Type Length Value,类型长度值)部分,例如PaddingTLV和HMAC (Hash-based Message Authentication Code,散列消息认证码) TLV
  • Segment List。如前所述,可以将多个Segment组合起来,形成SRv6路径,即路径可编辑。对SRv6 SID 128bit的运用。

    SRv6 Segment定义了SRv6网络编程中的网络指令,指示要去哪,怎么去。标识SRv6 Segment的ID被称为SRv6 SID。SRv6 SID是一个128bit的值,为IPv6地址形式,由Locator、Function和Arguments三部分组成。下图为SID构成

    • Locator:具有定位功能。提供IPv6的路由能力,报文通过该字段实现寻址转发。此外,Locator对应的路由也是可聚合的。

    • Function:用来表达该设备指令要执行的转发动作,不同的转发行为由不同的Function来表达。

    • Arguments:可选字段,是对Function的补充,是指令在执行时对应的参数,这些参数可能包含流、服务或任何其他相关的信息。 SRv6的每个Segment是128bit,可以灵活分为多段,每段功能和长度可以自定义,由此具备灵活编程能力,即业务可编辑。

SRv6 工作流程

SRv6 网络种节点角色基本可以分为三类:

  • SRv6 源节点:生成SRv6报文的源节点,如果list只包含单个SID,无需再报文中添加SRH,只要
  • 中转节点:中转节点是SRv6报文转发路径上不参与SRv6报文处理的节点。可以是普通的IPv6节点也可以是支持SRv6节点。
  • SRv6 段端点节点:在SRv6报文转发过程种,如果节点接收的IPv6地址是目的地址配置的SID,则命中本地SID处理表,进行EndPoint处理。

SRv6 源节点指令介绍:

源节点行为功能简述
H.Insert为接收到的IP报文插入SRH,并查表转发
H.Insert.Red为接收到的IP报文插入Reduced SRH,并查表转发
H.Encaps为接收到的IP报文封装外层IPv6报文头与SRH,并查表转发
H.Encaps.Red为接收到的IP报文封装外层IPv6报文头与Reduced SRH,并查表转发
H Encaps.L2为接收到的二层报文封装外层IPv6报文头与SRH,并查表转发
H.Encaps.L2.Red为接收到的二层报文封装外层IPv6报文头与Reduced SRH,并查表转发

SRv6 段端点指令介绍:

指令功能简述应用场景
End把下一个SID复制到IPv6目的地址,进行查表转发指定节点转发,相当于SR-MPLS的节点标签
End.X根据指定出接口转发报文指定出接口转发,相当于SR-MPLS的邻接标签
End.T在指定的IPv6转发表中进行查表并转发报文用于多转发表转发场景
End.DX6解封装报文,向指定的IPv6三层邻接转发L3VPNv6场景,通过指定的IPv6邻接转发到CE (Customer Edge, 用户网络边缘设备)
End.DX4解封装报文,向指定的IPv4三层邻接转发L3VPNv4场景,通过指定的IPv4邻接转发到CE
End.DT6解封装报文, 在指定的IPv6转发表中进行查表转发L3VPNv6场景
End.DT4解封装报文,在指定的IPv4转发表中进行查表转发L3VPNv4 场景
End.DT46解封装报文,在指定的IPv4或IPv6转发表种进行查表转发L3VPNv4/L3VPNv6场景
End.DX2解封装报文,从指定的二层出接口转发EVPN VPWS (Virtual Private Wire Service, 虚拟专用线路业务)场景
EndDX2V解封装报文,在指定的二层表中用内层VLAN信息进行查表转发EVPN VPLS (Virtual Private LAN Service, 虚拟专用局域网业务)场景
EndDT2U解封装报文,在指定的二层表中学习内层源MAC地址,用内层目的MAC地址进行查表转发EVPN VPLS的单播场景
End.DT2M解封装报文,在指定的二层表中学习内层源MAC地址,排除指定的接口后向其他二层接口转发EVPN VPLS的组播场景
End.B6.Insert插入 SRH,应用指定的SRv6 PolicyInsert 模式下引流入SRv6 Policy,隧道拼接、SD-WAN 选路等
End.B6.Insert.Red插入 Reduced SRH,应用指定的 SRv6 PolieyInsert&Reduce 模式下引流入SRv6 Policy,隧道拼接、SD-WAN 选路等
End.B6.Encaps封装外层IPv6报文头和SRH,应用指定的用指定的SRv6 PolicyEncaps 模式下引流入SRv6 Poliey, 隧道隧道拼接、SD-WAN选路等
End.B6.Encaps.Red封装外层IPv6报文头和Reduced SRH,应用指定的 SRv6 PolicyEnaps&Rcuce模式下引流入SRv6 Pliy,隧道拼接、SD-WAN选路等
End.BM插入MPLS标签栈,应用指定的SR-MPLS PolicySRv6 与SR-MPLS互通场景,引流入SR-MPLS Policy

如图所示,假设有报文需要从主机1转发到主机2,主机1将报文发送给节点A处理。节点A、B、D、E均支持SRv6,节点C不支持SRv6,只支持IPv6。我们在源节点A上进行网络编程,希望报文经过B-C、C-D链路,送达节点E,由E节点送达主机2。

报文转发流程分为以下几步:

  1. 源节点A将SRv6路径信息封装在SRH中,指定B-C,C-D链路的SID,另外封装E点发布的SID A5::10(此SID对应于节点E的一个IPv4 VPN),共3个SID,按照逆序形式压入SID序列。此时SL(Segment Left)=2,将Segment List[2]值复制到目的地址DA字段,按照最长匹配原则查找IPv6路由表,将其转发到节点B。
  2. 报文到达节点B,B节点查找本地SID表(存储本节点生成的SRv6 SID信息),命中自身的SID(End.X SID),执行SID对应的指令动作。SL值减1,并将Segment List[1]值复制到DA字段,同时将报文从SID绑定的链路(B-C)发送出去。
  3. 报文到达节点C,C无SRv6能力,无法识别SRH,按照正常IPv6报文处理流程,按照最长匹配原则查找IPv6路由表,将其转发到当前目的地址所代表的节点D。
  4. 节点D收报文后根据目的地址A4::45查找本地SID表,命中自身的SID(End.X SID)。同节点B,SL值减1,将A5::10作为DA,并将报文发送出去。
  5. 节点E收到报文后根据A5::10查找本地SID表,命中自身SID(End.DT4 SID),执行对应的指令动作,解封装报文,去除IPv6报文头,并将内层IPv4报文在SID绑定的VPN实例的IPv4路由表中进程查表转发,最终将报文发送给主机2。

SRv6 TE 工作模式

SRv6 TE Policy 利用Segment Routing 的源路由机制,通过在头节点封装一个有序的指令列表来指导报文穿越网络。

SRv6 TE Policy的工作流程主要也可以概括为5个步骤:

  1. 转发器将网络拓扑信息通过 BGP LS. 上报给网络控制器。拓扑信息包括节点(类比交叉路口)、链路信息(类比道路),以及链路的开销(类比流速)、带宽(类比车道)和时延(类比信号灯)等TE属性。
  2. 控制器基 于收集到的拓扑信息,按照业务需求计算路径,符合业务的SLA。
  3. 控制器通过 BGP SR-Policy扩展将路径信息下发给网络的头节点,头节点生成SRv6 TE Policy。 生成的SRv6 TE Policy 包括头端地址、目的地址和Color等关 键信息。
  4. 网络的头节 点为业务选择合适的 SRv6TE Policy 指导转发。
  5. 数据转发时, 转发器需要执行自己发布的SID的指令。

SRv6 BE 工作模式

传统MPLS有LDP和RSVP-TE两种控制协议,其中LDP方式不支持流量工程能力,LDP利用IGP算路结果,建立LDP LSP指导转发。在SRv6里,也有类似的方式,只不过SRv6仅使用一个业务SID来指引报文在IP 网络里进行尽力而为( Best Effort,BE) 的转发,这种方式就是SRv6 BE。下面以 EVPN L3VPNv4 over SRv6 BE介绍。

在VPN概念中,把整个网络中的路由器如下三类:

P(Provider,运营商骨干路由器) PE(Provider Edge、运营商边缘路由器) CE(Customer Edge、客户侧边缘路由器)

  • 在路由发布阶段:

    1. PE2 .上配置Locator,然后PE2通过IGP协议将SRv6 SID对应的 Locator 网段路由2001:DB8:3:/64发布给PE1。PE1安装路由到自己的IPv6路由表。
    2. PE2 在Locator范围内配置VPN实例的End.DT4 SID 2001:DB8:3::C100, 生成本地SID表。
    3. PE2收到CE2发布的私网IPv4路由后,PE2将私网IPv4路由转换成IP Prefix Route形式的EVPN路由,通过BGP EVPN邻居关系发布给PE1 。此路由携带 SRv6 VPN SID属性,也就是VPN实例的End.DT4 SID 2001:DB8::C100。
    4. PE1 接收到EVPN路由后,将其交叉到对应的VPN实例IPv4路由表,然后转换成普通IPv4路由,对CE1发布。
  • 在数据转发阶段:

    1. CE1 向PE1发送一个普通IPv4报文。
    2. PE1 从绑定了VPN实例的接口.上收到私网报文以后,查找对应VPN实例的IPv4路由转发表,匹配目的IPv4前缀,查找到关联的SRv6 VPN SID 以及下一跳信息。然后直接使用SRv6 VPN SID 2001:DB8:3::C100 作为目的地址封装成IPv6报文。
    3. PE1然后按照最长匹配原则,匹配到路由2001:DB8::/64, 按最短路径转发到P设备。
    4. P 设备按照最长匹配原则,匹配到路由2001:DB8:3:/64, 按最短路径转发到PE2。
    5. PE2 使用2001:DB8::C100查找本地SID表,匹配到End.DT4 SID对应的转发动作,将IPv6报文头去除,然后根据End.DT4 SID匹配VPN实例,查找VPN 实例IPv4路由表进行转发。

实践演示

指令介绍

由于 该实验环境使用 iproute2 包实现,不包含全部上述理论介绍SRv6指令,这里按照 iproute2 包的实现来进行介绍,使用 man ip route 可以看到

ip route replace
    encap ENCAPTYPE ENCAPHDR
        attach tunnel encapsulation attributes to this route.
            seg6
                mode inline - Directly insert Segment Routing Header after IPv6
                header

                mode encap - Encapsulate packet in an outer IPv6 header with SRH

                mode l2encap - Encapsulate ingress L2 frame within an outer IPv6
                header and SRH

                SEGMENTS - List of comma-separated IPv6 addresses

                KEYID - Numerical value in decimal representation. See ip-sr(8).

            seg6local
                SEG6_ACTION [ SEG6_ACTION_PARAM ] - Operation to perform on match‐
                ing packets.  The following actions are currently supported (Linux
                4.14+ only).

                SEG6_ACTION [ SEG6_ACTION_PARAM ] - Operation to perform on match‐
                ing packets.  The following actions are currently supported (Linux
                4.14+ only).
                    End - Regular SRv6 processing as intermediate segment endpoint.
                    This action only accepts packets with a non-zero Segments Left
                    value. Other matching packets are dropped.

                    End.X nh6 NEXTHOP - Regular SRv6 processing as intermediate seg‐
                    ment endpoint.  Additionally, forward processed packets to given
                    next-hop.  This action only accepts packets with a non-zero Seg‐
                    ments Left value. Other matching packets are dropped.

                    End.DX6 nh6 NEXTHOP - Decapsulate inner IPv6 packet and forward
                    it to the specified next-hop. If the argument is set to ::, then
                    the next-hop is selected according to the local selection rules.
                    This action only accepts packets with either a zero Segments
                    Left value or no SRH at all, and an inner IPv6 packet. Other
                    matching packets are dropped.

                    End.B6 srh segs SEGMENTS [ hmac KEYID ] - Insert the specified
                    SRH immediately after the IPv6 header, update the DA with the
                    first segment of the newly inserted SRH, then forward the re‐
                    sulting packet. The original SRH is not modified. This action
                    only accepts packets with a non-zero Segments Left value. Other
                    matching packets are dropped.

                    End.B6.Encaps srh segs SEGMENTS [ hmac KEYID ] - Regular SRv6
                    processing as intermediate segment endpoint.  Additionally, en‐
                    capsulate the matching packet within an outer IPv6 header fol‐
                    lowed by the specified SRH. The destination address of the outer
                    IPv6 header is set to the first segment of the new SRH. The
                    source address is set as described in ip-sr(8).

本地SID表在 主机环境种可以使用路由表查看,即为 ip 6 route showip -6 route show 当然也可以使用其他第三方工具。

场景环境配置

  • Ubuntu18.04 内核版本 4.14及以上
  • iproute2 版本4.9.0 及以上
  • core 版本7.5.1 及以上
  • Quagga 版本1.2.4 及以上

参考这篇博客,设计了一个 IPv4 使用 IPv6 通道的流量工程拓扑。每台路由器都开启 IPforword 和 quagga。

sysctl -w net.ipv4.conf.all.forwarding=1
sysctl -w net.ipv4.conf.default.forwarding=1
sysctl -w net.ipv6.conf.all.forwarding=1
sysctl -w net.ipv6.conf.default.forwarding=1

从主机n1发出的IPv4数据包,到达支持SRv6的路由器 n4 , n4 会根据所配置的操作对数据包进行封装,在外层加上IPv6以及SRH的报头,并进行正常的IPv6转发。在仅支持IPv6的路由器 n5,n5根据IPv6报头基于目的IPv6地址进行转发。在n6,n6路由器根据Segment执行End操作,将Segment Left减1,并根据Segment列表更新IPv6的目的地址,将数据包转发至下一跳n7。在支持SRv6的路由器n7,n7根据Segment执行End.DX4操作,剥掉外层的IPv6报头,将内含的IPv4数据包发给主机n3,完成转发流程。 之后的返回包流程就是 直接从n7 指向 n4。

这里一开始做对 SRv6 理解不够透彻认为 SID 就是单纯的IPv6地址,按照原图的配置 可以看到所有节点的路由 居然是按照 fc00:4::bb 网段操作,可是原场景没有这些网段,这让我非常疑惑。一切如上图配置完毕后,发现从n4开始就没有发出 SRv6 的路由包。也没有报错提示,最后瞎试发现,是中转的例如 fc00:4:bb 没有这个路由系统内核直接处理为不可达,也就没有做 SRv6 转发操作。

一顿折腾后,每一跳都配置好路由后觉得不太对,这每一跳都要设置路由也太蠢了,一定是我配置的问题。

后来在github找到个 onos 做SDN控制器、 mininet做仿真环境的一个开源项目,里面的 issue 作者提到尽量把 sid 与物理接口隔离开,这时我才突然明白,sid 设计的巧妙之处:

sid 长度为128bit,与IPv6地址相同能够在不具备SRv6的节点上作为普通ip地址使用,即将 locator作为路由器网段内前缀,function 字段设计并标识为不同的流量,相应的节点对该sid地址做不同的处理,后面的长度也足够长可以设计同一fuction下的不同Arguments。这就是 路由 + MPLS 的融合的设计思路,设计的SID前缀与主机网络前缀相同使用同一个 locator,之后再加上 定义的 funtion arguments字段,sid 又能做ip地址又能直接对网络进行编程。

这里使用一个新的场景举例说明,对出发流量 fuction 设定为 a,返回的流量 fuction 设定 为 b,arguments 都是233 此处不做处理。其间绿色路由器为普通 IPv6 路由器仅支持igp协议,此处使用的是 quagga 实现的 OSPFv3。

由于网段全部为 64位,fuction设定占用16位,sid 设计为 2001:X:0:0:$fuction:0:0:0:0/80 后面的arguments设定位固定的 233。

不过需要注意,使用SRv6路由定义时不要与原有内核 或 zebra 生成的路由冲突,SRv6的优先级不够高可能永远也无法触发相应end操作,导致节点使用NDP协议去寻找对应物理意义不存在的IPv6地址。

具体配置信息:

开启了IPforword 无所谓指定的dev,不影响最后的结果


# n1配置
ip route add 10.0.6.0/24 encap seg6 mode encap  segs 2001:2:0:0:a::233,2001:6:0:0:a::233 dev eth0
ip -6 route add 2001:0:0:0:b::233/80 encap seg6local action End.DX4 nh4 10.0.0.20 dev eth1

# n2配置
ip -6 route add 2001:1:0:0:b::233/80 encap seg6local action End dev eth1
ip -6 route add 2001:2:0:0:a::233/80 encap seg6local action End.X nh6 2001:2::2 dev eth1# end操作后 按照指定下一跳接口转发ip 不指定会按照路由最短路径走

# n6配置
ip -6 route add 2001:6:0:0:a::233/80 encap seg6local action End.DX4 nh4 10.0.6.20 dev eth1
ip route add 10.0.0.0/24 encap seg6 mode encap segs 2001:1:0:0:b::233,2001:0:0:0:b::233 dev eth0

抓包分析

主机n7 ping n8 在n4 n9使用tcpdump可以看到SRv6数据包,出发的路径 segment list是逆序的,指令指定的是正序。为2001:2:0:0:a::233,2001:6:0:0:a::233

路由信息走到节点n2命中本地SID表后执行 END.X 不仅将 segment left - 1 修改目的地址,还转发至指定下一跳2001:2::2。之后到达n3后 由于不存在 SRv6 处理能力,单纯按照网段最长前缀匹配路由。最后转发到n6后执行解包操作拆分出原始的 IPv4 报文。返回数据包的操作类似,不过是走路由的最短路经过上面的路由器转发SRv6数据。

在无 SRv6 路由器上的转发。在n2使用wireshark具体分析包结构

这里给出我搭建的场景链接,新版的core需要使用 legacy ui 打开。仿真一开始可能ping不通,需要等待中间绿色节点的ospf路由生成。

扩展场景

该场景链接

场景如上所示,主机n1到主机n2的流量,在n4上添加SRH要求经由n6进行转发,因此原流量路径如图黑色路径所示。 在n6路由器上,修改End操作为End.B6.Encaps操作,将流量先引导到 IDS n8进行处理,再回到n6进行正常转发流程。对应的新的流量路径如图绿色路径所示。最后通过绿色路径返回n1。

End.B6.Encaps就是在在现有IPv6数据包上再封装一个新的IPv6的报头,并添加新的SRH报头;而End.B6操作则不会添加新的IPv6报头,而是直接插入新的SRH报头到现有的IPv6报头当中。这两种操作本质上都相当于是Binding-SID。

这些 sid 设计如上面场景一样。 即为2001:X:0:0:$fuction:0:0:0:0/80 。locator 为路由器网段前缀,fuction 对应 a, aa, b 三种操作。

具体配置如下所示。

# n4配置
ip route add 10.0.2.0/24 encap seg6 mode encap  segs 2001:8:0:0:a::233,2001:6:0:0:a::233 dev eth0
ip -6 route add 2001:0:0:0:b::233/80 encap seg6local action End.DX4 nh4 10.0.1.20 dev eth1

# n7配置
ip -6 route add 2001:6:0:0:a::233/80 encap seg6local action End.DX4 nh4 10.0.2.20 dev eth1
ip route add 10.0.1.0/24 encap seg6 mode encap  segs 2001:0:0:0:b::233 dev eth1

# n8配置
ip route add fc:4:0:0:aa::aa via 2001:8::1
ip -6 route add fc:8:0:0:aa::aa encap seg6local action End dev eth0

# n6配置
ip -6 route add fc:8:0:0:aa::aa/80 via 2001:8::2 #由于该节点相邻 需要使用特殊网段 防止优先匹配了2001:8网段导致无法转发
ip -6 route add 2001:8:0:0:a::233/80 encap seg6local action End.B6.Encaps srh segs fc:8:0:0:aa::aa,fc:4:0:0:aa::aa dev eth1
ip -6 route add fc:4:0:0:aa::aa/80 encap seg6local action End.DX6 nh6 :: dev eth1

还可以修改优先级 做处理 使得先进行SRv6 sid 的处理 避免链路路由处理 使用ntp寻找不存在的ip。n6 n8 配置的修改如下所示。

# n6配置
ip -6 route add 2001:8:0:0:aa::aa via 2001:8::2 metric 255
ip -6 route add 2001:8:0:0:a::233/80 encap seg6local action End.B6.Encaps srh segs 2001:8:0:0:aa::aa,2001:4:0:0:aa::aa dev eth1
ip -6 route add 2001:4:0:0:aa::aa/80 encap seg6local action End.DX6 nh6 :: dev eth1

# n8配置
ip route add 2001:4:0:0:aa::aa via 2001:8::1 metric 255
ip -6 route add 2001:8:0:0:aa::aa encap seg6local action End dev eth0

抓包数据大都相同,这里分别抓取 n5 n8 n9 的数据包: