研究でSRv6のBehaviorをまとめているのですが,記事にも残そうということで書きます.
はじめに
LinuxでSRv6ネットワークを動かしていると,SRv6の挙動を調べたいときがよくあります.
トラブルシューティングのときとかは特に,LinuxのソースコードやRFCを読んでいます.
毎回RFCを漁るのも読んで理解するのも面倒なので,備忘録として残します.LinuxでSRv6を学習している人の一助となれば嬉しいです.
図は,Zashas/Thesis-SRv6-BPFやCiscoの資料を参考に作成しています.
動作確認環境
iproute2のコマンドは,以下の環境で動作確認しています.
- Ubuntu:22.04
- Linux: 6.4.6
- https://kernel.ubuntu.com/mainline/v6.4.6/amd64/ からダウンロードしてインストール
- iproute2: 6.5.0
SRv6 behavior
SRv6のSIDは,以下の構造となっています.
- LOC: SIDを保有するノードへルーティングするための情報
- FUNCT: SIDを保有するノードで実施される処理を指定する値
- ARG: FUNCTで使用される値
このFUNCTで指定できる処理そのものをBehaviorと呼びます.
SR Policy headend behaviors
SR Policy Headend behaivorでは,パケットにSRポリシー(SRH)を関連付けます.
H.Encaps (RFC8986)
H.Encapsでは,パケットをSRHとIPv6ヘッダで新たにカプセル化します.カプセル化するIPv6ヘッダの送信元はH.Encapsを行うノードのアドレスであり,宛先はSegment List[Segment Left] のアドレスです.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6 mode encap segs <segs> dev <intf>
ip -6 route add fd00:beef::/32 encap seg6 mode encap segs fd00:a::,fd00:b::,fd00:c:: dev eth1
H.Insert (draft-filsfils-spring-srv6-net-pgm-insertion-09)
H.Insertは,IPv6パケットに対してSRHを付加します.また,元の宛先は,SegmetList[0]に格納されます.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6 mode inline segs <segs> dev <intf>
ip -6 route add fd00:beef::/32 encap seg6 mode inline segs fd00:a::,fd00:b:: dev eth1
SRv6 Endpoint behavior
Endpoint behaviorとは,パケットで指定されたセグメントを持つノードで行われる処理のことです.
以下で詳細を説明します.なお,説明で使用するFunctionの値は,IANAのSRv6 Endpoint Behaviors Registoryを参考にしています.
End (RFC8986)
Endは,SegmentLeftをデクリメントし,IPv6宛先アドレスを書き換えてFIBから宛先を検索して送信します.
また,以下の以下の場合分けがあります.
- SegmentLeftが0の場合は,SRH処理は行わず,SRH直後のヘッダーを処理します.
- Hoplimitが1以下である場合,Code0でICMP Time Exceededを送信します.
- SRHの更新処理の前に,SRHのLast EntryがSRHより外を参照していないことと,SRHのSegmentLeftがLast Entry + 1を超えていないことを検証し,違反している場合にはCode0のICMP Parameter Problemを送信します.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End [flavors <flavors>] dev <intf>
ip -6 route add fd00:a::1/128 encap seg6local action End dev eth1
ip -6 route add fd00:a::3/128 encap seg6local action End flavors usp dev eth1
ip -6 route add fd00:100::/32 encap seg6local action End flavors next-csid dev eth1
End.T (RFC8986)
End.Tは,SegmentLeftをデクリメントし,IPv6宛先アドレスを書き換えて指定したネクストホップに送信します.また,Endでの場合分け処理もあります.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End.T table <table id> dev <intf>
ip -6 route add fd00:a::9/128 encap seg6local action End.T table 10 dev eth1
End.X (RFC8986)
End.Xは,SegmentLeftをデクリメントし,IPv6宛先アドレスを書き換えて指定したテーブルから宛先を検索して送信します.また,Endでの場合分け処理もあります.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End.X nh6 <next hop> dev <intf>
ip -6 route add fd00:a::5/128 encap seg6local action End.X nh6 fd00::1 dev eth1
End.DX6 (RFC8986)
End.DX6は,SRHを削除して,指定されたIPv6ネクストホップに送信します.End.DX6のSegmentはLast Segment(SegmentList[0]のセグメント)である必要があるため,SegmentLeftが0でない場合は,Code0のICMP Parameter Problemを送信します.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End.DX6 nh6 <next hop> dev <intf>
ip -6 route add fd00:a::10/128 encap seg6local action End.DX6 nh6 fd00::1 dev eth1
End.DX4 (RFC8986)
End.DX4は,SRHを削除して,指定されたIPv4ネクストホップに送信します.End.DX4のSegmentはLast Segmentである必要があるため,SegmentLeftが0でない場合は,Code0のICMP Parameter Problemを送信します.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End.DX4 nh4 <next hop> dev <intf>
ip -6 route add fd00:a::11/128 encap seg6local action End.DX4 nh4 192.168.0.1 dev eth1
End.DT6 (RFC8986)
End.DT6は,SRHを削除して,指定されたIPv6のFIBテーブルから宛先を検索して送信します.End.DT6のSegmentはLast Segmentである必要があるため,SegmentLeftが0でない場合は,Code0のICMP Parameter Problemを送信します.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End.DT6 {table | vrftable} <table id> dev <intf>
ip -6 route add fd00:a::12/128 encap seg6local action End.DT6 table 10 dev eth1
ip -6 route add fd00:a::12/128 encap seg6local action End.DT6 vrftable 10 dev eth1
End.DT4 (RFC8986)
End.DT4は,SRHを削除して,指定されたIPv4のFIBテーブルから宛先を検索して送信します.End.DT4のSegmentはLast Segmentである必要があるため,SegmentLeftが0でない場合は,Code0のICMP Parameter Problemを送信します.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End.DT4 vrftable <table id> dev <intf>
ip -6 route add fd00:a::13/128 encap seg6local action End.DT4 vrftable 10 dev eth1
End.DT46 (RFC8986)
End.DT46は,SRHを削除して,指定されたFIBテーブルから宛先を検索して送信します.End.DT46のSegmentはLast Segmentである必要があるため,SegmentLeftが0でない場合は,Code0のICMP Parameter Problemを送信します.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End.DT46 vrftable <table id> dev <intf>
ip -6 route add fd00:a::14/128 encap seg6local action End.DT46 vrftable 10 dev eth1
End.B6.Encaps (RFC8986)
End.B6.Encapsは,SegmentLeftをデクリメントし,新しいSRHとIPv6ヘッダでカプセル化して送信します.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End.B6.Encaps srh segs <segs> [hmac <key id>] dev <intf>
ip -6 route add fd00:a::e/128 encap seg6local action End.B6.Encaps srh segs fd00:aa::,fd00:bb:: dev eth1
End.B6 (End.B6.Insert) (draft-filsfils-spring-srv6-net-pgm-insertion-09)
End.B6.Insertは,指定されたSegment List (SRH)をパケットに新たに追加します.
End.B6.InsertはLast Segmentでない必要があるので,Segment Leftが0の場合,ICMP Parameter Problemメッセージを送信します.また,IPv6宛先アドレスは,新しいSegmentListで更新され,元のSRHのSegment Leftはデクリメントされません.
iproute2での設定は以下です.
# ip -6 route add <ipv6 prefix> encap seg6local action End.B6 srh segs <segs> [hmac <key id>] dev <intf>
ip -6 route add fd00:a::d/128 encap seg6local action End.B6 srh segs fd00:aa::,fd00:bb:: dev eth1
おわりに
まだL2VPNの挙動など調べきれていない部分があるので,将来的にそのあたりも調べたいと思っています.