Mininet 1 の中でSRv6 L3VPNを動かす実験をやってみた。 スクリプトはこちら。
ひとまず図のような小さな構成で動かすことができたのでここで紹介したい。 2台のルータ(r1とr2)がSRv6によるEncap/Decapを担当しており、 r1-r2間でL3VPNに関する情報をeBGPで交換する。 r1とr2はそれぞれ2つのVRF(vrf10とvrf20)を持っており、 VRFごとにテナントが分けられている(Tenant10とTenant20)。 もちろんテナントごとにL3の疎通性はなくIPレンジの重複は許されているので、 ここでは同じPrefixを割り当てている。
r1とr2ではBGPデーモンとしてFRRを使っている。設定の一部を抜粋するとこんな感じ。 FRRの設定ファイル(frr.conf)全体についてはmininetlab 2 に記載している。 FRR本体のテストコード 3 が非常に簡潔で綺麗にまとまっているので、それを参考にした。 FRRではSRv6 L3VPNの開発は活発に行われているので、できれば新しいバージョンをおすすめする。 ここではFRR 8.5を使った。
mininet> r1 vtysh -c "show running-config"
# 一部抜粋
router bgp 65001
bgp router-id 203.0.113.1
bgp default ipv4-vpn
bgp default ipv6-unicast
bgp bestpath as-path multipath-relax
no bgp network import-check
neighbor r1-eth0 interface remote-as external
!
segment-routing srv6
locator default
exit
exit
!
router bgp 65001 vrf vrf10
bgp router-id 203.0.113.1
!
address-family ipv4 unicast
redistribute connected
sid vpn export 16
rd vpn export 65001:10
rt vpn both 0:10
export vpn
import vpn
exit-address-family
exit
!
segment-routing
srv6
locators
locator default
prefix 2001:db8:1:1::/64 block-len 40 node-len 24 func-bits 16
!
end
SRv6ではEncap時に宛先をSID(Segment ID)のリストで表現する。
SIDはIPv6フォーマットで記載できLocator、Function、Argumentの3つのフィールドから構成される。
Locatorは普通ルータごとに個別の値を与えるのでr1には2001:db8:1:1::/64
を割り当てた。
ルータのASNとrouter idは全てのvrfで共通でr1では65001と203.0.113.1とした。
VPNを有効にするにはDefault VRFにおいて、
全てのneighborで有効化する bgp default ipv4-vpn
を設定するか、
あるいは address-family ipv4 vpn
の中で neighbor ごとに個別で設定する必要がある。
sid vpn export
はSIDのfunctionに相当するのでVRFごとに個別の値を設定する。
VPNで広報するIP Prefixは、VRFの設定における address-family ipv4 unicast
で設定する。
Mininetには各ホストに入ってコマンドを発行できる便利なCLI機構があるので、 下のように追加して色々みていく。
$ git diff
diff --git a/mininetlab/srv6_l3vpn.py b/mininetlab/srv6_l3vpn.py
index 4a7c4a9a3f94..d3185398e252 100644
--- a/mininetlab/srv6_l3vpn.py
+++ b/mininetlab/srv6_l3vpn.py
@@ -2,6 +2,7 @@
from mininet.net import Mininet
from mininet.log import setLogLevel
+from mininet.cli import CLI
import time
frr_conf = '''
@@ -185,6 +186,8 @@ def run():
loss_rate = net.ping(hosts=[c11, c21]) + net.ping(hosts=[c12, c22])
+ CLI(net)
+
for h in [r1, r2]:
h.cmd("/usr/lib/frr/frrinit.sh stop")
まずはVPN内通信をざっくりチェックしてみる。 c11とc12は異なるテナントに所属しているため、 例え宛先IPアドレスが一緒であっても異なるホスト宛への通信となる。
mininet> c11 curl 192.168.2.1
c21
mininet> c12 curl 192.168.2.1
c22
続いてr1において、Default VRFとTenant10それぞれのルーティングテーブルを確認してみる。
proto bgp
が付与されているエントリはBGPによって設定されたもの。
Default VRFではSID宛の通信に対してDecapを行い、
vrf10やvrf20に対してEnd.DT4アクションが適用される。
Tenant10に対応するVRFでは、192.168.2.0/24
への経路として、
r2のSID 2001:db8:2:2:10::
でEncapするアクションが適用されている。
このようにBGPを使ってEncap/Decapのルーティングを設定することができる。
# Default VRF.
mininet> r1 ip -6 route show
2001:db8:1:1::1 dev lo proto kernel metric 256 pref medium
2001:db8:1:1:10:: nhid 11 encap seg6local action End.DT4 vrftable 10 dev vrf10 proto bgp metric 20 pref medium
2001:db8:1:1:20:: nhid 12 encap seg6local action End.DT4 vrftable 20 dev vrf20 proto bgp metric 20 pref medium
2001:db8:2:2::/64 nhid 22 via fe80::98de:31ff:fe2d:6903 dev r1-eth0 proto bgp metric 20 pref medium
fe80::/64 dev r1-eth0 proto kernel metric 256 pref medium
# VRF for Tenant10.
mininet> r1 ip -4 route show vrf vrf10
192.168.1.0/24 dev r1-eth1 proto kernel scope link src 192.168.1.254
192.168.2.0/24 nhid 23 encap seg6 mode encap segs 1 [ 2001:db8:2:2:10:: ] via inet6 fe80::98de:31ff:fe2d:6903 dev r1-eth0 proto bgp metric 20
SRv6パケットについても見ていく。
これはc11からpingをうちながらr1でパケットキャプチャすることで確認できる。
意図した通り SID 2001:db8:2:2:10::
宛にSRv6パケットが送られている。
mininet> c11 ping 192.168.2.1 &
mininet> r1 tshark -i r1-eth0 -V host 2001:db8:2:2:10::
Frame 2: 162 bytes on wire (1296 bits), 162 bytes captured (1296 bits) on interface r1-eth0, id 0
Ethernet II, Src: 1a:4c:3e:9d:f7:09 (1a:4c:3e:9d:f7:09), Dst: 9a:de:31:2d:69:03 (9a:de:31:2d:69:03)
Internet Protocol Version 6, Src: 2001:db8:1:1::1, Dst: 2001:db8:2:2:10::
Next Header: Routing Header for IPv6 (43)
Source Address: 2001:db8:1:1::1
Destination Address: 2001:db8:2:2:10::
Routing Header for IPv6 (Segment Routing)
Next Header: IPIP (4)
Length: 2
[Length: 24 bytes]
Type: Segment Routing (4)
Segments Left: 0
Last Entry: 0
Flags: 0x00
Tag: 0000
Address[0]: 2001:db8:2:2:10::
Internet Protocol Version 4, Src: 192.168.1.1, Dst: 192.168.2.1
0100 .... = Version: 4
Protocol: ICMP (1)
Source Address: 192.168.1.1
Destination Address: 192.168.2.1
Internet Control Message Protocol
Type: 8 (Echo (ping) request)
BGP UPDATEメッセージも見てみる。新たに192.168.5.0/24
をr1 vrf10に追加してみる。
RFC 9252 - BGP Overlay Services Based on Segment Routing over IPv6 (SRv6)
で記載されている TLV の形式と合致している。
mininet> r1 bash -c "sleep 10; ip addr add 192.168.5.254/24 dev r1-eth1" &
mininet> r1 tshark -i r1-eth0 -V port 179
Frame 6: 250 bytes on wire (2000 bits), 250 bytes captured (2000 bits) on interface r1-eth0, id 0
Ethernet II, Src: 9a:de:31:2d:69:03 (9a:de:31:2d:69:03), Dst: 1a:4c:3e:9d:f7:09 (1a:4c:3e:9d:f7:09)
Internet Protocol Version 6, Src: fe80::98de:31ff:fe2d:6903, Dst: fe80::184c:3eff:fe9d:f709
Transmission Control Protocol, Src Port: 179, Dst Port: 34248, Seq: 20, Ack: 163, Len: 164
Border Gateway Protocol - UPDATE Message
Path attributes
...
Path Attribute - MP_REACH_NLRI
Flags: 0x90, Optional, Extended-Length, Non-transitive, Complete
Type Code: MP_REACH_NLRI (14)
Address family identifier (AFI): IPv4 (1)
Subsequent address family identifier (SAFI): Labeled VPN Unicast (128)
Next hop: RD=0:0 IPv6=fe80::98de:31ff:fe2d:6903 RD=0:0 Link-local=fe80::98de:31ff:fe2d:6903
Route Distinguisher: 0:0
IPv6 Address: fe80::98de:31ff:fe2d:6903
Route Distinguisher: 0:0
Link-local Address: fe80::98de:31ff:fe2d:6903
Number of Subnetwork points of attachment (SNPA): 0
Network Layer Reachability Information (NLRI)
BGP Prefix
Prefix Length: 112
Label Stack: 256 (bottom)
# "rd vpn export 65001:10" より。
Route Distinguisher: 65001:10
# 今回VPNに追加したPrefix 192.168.5.0/24
MP Reach NLRI IPv4 prefix: 192.168.5.0
...
Path Attribute - BGP Prefix-SID
Type Code: BGP Prefix-SID (40)
SRv6 L3 Service
# L3なら5、L2なら6とする。「2. SRv6 Services TLVs」より。
Type: SRv6 L3 Service (5)
SRv6 Service Sub-TLVs
SRv6 Service Sub-TLV - SRv6 SID Information
#「3.1. SRv6 SID Information Sub-TLV」より。
Type: SRv6 SID Information (1)
# r1 vrf10のSID
SRv6 SID Value: 2001:db8:1:1::
SRv6 SID Flags: 0x00
# https://www.iana.org/assignments/segment-routing/segment-routing.xhtml より。
SRv6 Endpoint Behavior: End.DT4 (0x0013)
Reserved: 00
SRv6 Service Data Sub-Sub-TLVs
SRv6 Service Data Sub-Sub-TLV - SRv6 SID Structure
# 「3.2.1. SRv6 SID Structure Sub-Sub-TLV」より。
Type: SRv6 SID Structure (1)
# Locatorのビット数
Locator Block Length: 40
Locator Node Length: 24
Function Length: 16
Argument Length: 0
Transposition Length: 16
Transposition Offset: 64
ざっくりとした挙動を理解することができた。 今後はSR Domainを複雑にしてみたり、 テナントごとにNetwork Functionを生やしたりしてみたい。 おしまい。