はじめに
普段はSegment Routing over IPv6 (SRv6)を扱っていたのですが,SR-MPLSも勉強しないとということでFRRoutingとMinientを使ってSR-MPLS動かしてみた話です.多くの記事ではOSPFを使っているので,逆張りでIS-ISを使ってSR-MPLSを動かします.
構築するネットワーク
- ルータのループバックは10.0.0.0/24
- Segment Routing Global Block (SRGB) を16000~23999とし,NodeSIDとしてルータごとに100単位でindexを割り当て
- IGPはIS-ISを使用
環境設定
FRRoutingとMinientを使ったツールを用いて,ネットワークを構築します.
FRRoutingのインストール
sudo apt install -y frr
MPlSの設定
LinuxにMPLSのモジュールを読み込む必要があるので,以下のコマンドを実行します.
sudo apt install linux-modules-extra-`uname -r`
sudo modprobe mpls_router
sudo modprobe mpls_gso
sudo modprobe mpls_iptunnel
Mininetのインストール
Mininetをインストールしていきます.
git clone https://github.com/mininet/mininet
cd mininet
git tag # list available versions
git checkout -b mininet-2.3.0 2.3.0 # or whatever version you wish to install
cd ..
mininet/util/install.sh -a
sudo apt -y install openvswitch-switch
sudo service openvswitch-switch start
MinientでFRRoutingを使うには工夫が必要です.
今回は,自分が作成したipnet_mininet
を使います.
このツールは,Mininetでルーティングプロトコルを動かせるように,拡張やヘルパーを追加したツールです.
git clone https://github.com/shu1r0/ipnet_mininet.git
cd ipnet_mininet/
sudo pip install -r requirements.txt
sudo pip install .
FRRoutingの設定
例としてR1の設定を示します.IPアドレスの設定は別の所でやります.
すべてのインターフェースでIS-ISを有効にします.IS-ISでMPLS-TEとSR-MPLSの設定を行います.
NodeSIDの設定でのindexは100単位で与えます.
interface r1_h1
ip router isis 1
interface r1_r2
ip router isis 1
interface lo
ip address 10.0.0.1/32
ip router isis 1
router isis 1
net 49.0000.0000.0000.0001.00
is-type level-1
mpls-te on
mpls-te router-address 10.0.0.1
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 10.0.0.1/32 index 100
exit
R2
interface r2_r1
ip router isis 1
interface r2_r3
ip router isis 1
interface r2_r6
ip router isis 1
interface lo
ip address 10.0.0.2/32
ip router isis 1
router isis 1
net 49.0000.0000.0000.0002.00
is-type level-1
mpls-te on
mpls-te router-address 10.0.0.2
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 10.0.0.2/32 index 200
exit
R3
interface r3_r2
ip router isis 1
interface r3_r4
ip router isis 1
interface r3_r5
ip router isis 1
interface lo
ip address 10.0.0.3/32
ip router isis 1
router isis 1
net 49.0000.0000.0000.0003.00
is-type level-1
mpls-te on
mpls-te router-address 10.0.0.3
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 10.0.0.3/32 index 300
exit
R4
interface r4_r3
ip router isis 1
interface r4_h3
ip router isis 1
interface lo
ip address 10.0.0.4/32
ip router isis 1
router isis 1
net 49.0000.0000.0000.0004.00
is-type level-1
mpls-te on
mpls-te router-address 10.0.0.4
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 10.0.0.4/32 index 400
exit
R5
interface r5_h2
ip router isis 1
interface r5_r6
ip router isis 1
interface lo
ip address 10.0.0.5/32
ip router isis 1
router isis 1
net 49.0000.0000.0000.0005.00
is-type level-1
mpls-te on
mpls-te router-address 10.0.0.5
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 10.0.0.5/32 index 500
exit
R6
interface r6_r2
ip router isis 1
interface r6_r5
ip router isis 1
interface r6_r7
ip router isis 1
interface lo
ip address 10.0.0.6/32
ip router isis 1
router isis 1
net 49.0000.0000.0000.0006.00
is-type level-1
mpls-te on
mpls-te router-address 10.0.0.6
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 10.0.0.6/32 index 600
exit
R7
interface r7_r3
ip router isis 1
interface r7_r6
ip router isis 1
interface r7_r8
ip router isis 1
interface lo
ip address 10.0.0.7/32
ip router isis 1
router isis 1
net 49.0000.0000.0000.0007.00
is-type level-1
mpls-te on
mpls-te router-address 10.0.0.7
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 10.0.0.7/32 index 700
exit
R8
interface r8_r7
ip router isis 1
interface r8_h4
ip router isis 1
interface lo
ip address 10.0.0.8/32
ip router isis 1
router isis 1
net 49.0000.0000.0000.0008.00
is-type level-1
mpls-te on
mpls-te router-address 10.0.0.8
segment-routing on
segment-routing global-block 16000 23999
segment-routing node-msd 8
segment-routing prefix 10.0.0.8/32 index 800
exit
トポロジの設定
LinuxでMPLSを扱う際には,インターフェースで有効にする必要があります.
sudo sysctl -w net.mpls.platform_labels=1048575
sudo sysctl -w net.mpls.conf.<インターフェース>.input=1
ipnet_mininet
では自動で設定されるようにしています.
トポロジの設定を行います.
from mininet.log import setLogLevel
from ipnet import IPNetwork, IPNode, CLIX, MPLSRouter
def setup() -> IPNetwork:
setLogLevel("info")
net = IPNetwork()
# FRRouting Router
r1 = net.addFRR("r1", enable_daemons=["isisd"], cls=MPLSRouter)
r2 = net.addFRR("r2", enable_daemons=["isisd"], cls=MPLSRouter)
r3 = net.addFRR("r3", enable_daemons=["isisd"], cls=MPLSRouter)
r4 = net.addFRR("r4", enable_daemons=["isisd"], cls=MPLSRouter)
r5 = net.addFRR("r5", enable_daemons=["isisd"], cls=MPLSRouter)
r6 = net.addFRR("r6", enable_daemons=["isisd"], cls=MPLSRouter)
r7 = net.addFRR("r7", enable_daemons=["isisd"], cls=MPLSRouter)
r8 = net.addFRR("r8", enable_daemons=["isisd"], cls=MPLSRouter)
# host
h1: IPNode = net.addHost("h1", cls=IPNode)
h2: IPNode = net.addHost("h2", cls=IPNode)
h3: IPNode = net.addHost("h3", cls=IPNode)
h4: IPNode = net.addHost("h4", cls=IPNode)
# config link
net.addLink(r1, h1,
intfName1="r1_h1", params1={"ip": "192.168.1.1/24"},
intfName2="h1_r1", params2={"ip": "192.168.1.2/24"})
net.addLink(r1, r2,
intfName1="r1_r2", params1={"ip": "192.168.12.1/24"},
intfName2="r2_r1", params2={"ip": "192.168.12.2/24"})
net.addLink(r2, r3,
intfName1="r2_r3", params1={"ip": "192.168.23.1/24"},
intfName2="r3_r2", params2={"ip": "192.168.23.2/24"})
net.addLink(r2, r6,
intfName1="r2_r6", params1={"ip": "192.168.26.1/24"},
intfName2="r6_r2", params2={"ip": "192.168.26.2/24"})
net.addLink(r3, r4,
intfName1="r3_r4", params1={"ip": "192.168.34.1/24"},
intfName2="r4_r3", params2={"ip": "192.168.34.2/24"})
net.addLink(r3, r7,
intfName1="r3_r7", params1={"ip": "192.168.37.1/24"},
intfName2="r7_r3", params2={"ip": "192.168.37.2/24"})
net.addLink(r4, h3,
intfName1="r4_h3", params1={"ip": "192.168.3.1/24"},
intfName2="h3_r4", params2={"ip": "192.168.3.2/24"})
net.addLink(r5, h2,
intfName1="r5_h2", params1={"ip": "192.168.2.1/24"},
intfName2="h2_r5", params2={"ip": "192.168.2.2/24"})
net.addLink(r5, r6,
intfName1="r5_r6", params1={"ip": "192.168.56.1/24"},
intfName2="r6_r5", params2={"ip": "192.168.56.2/24"})
net.addLink(r6, r7,
intfName1="r6_r7", params1={"ip": "192.168.67.1/24"},
intfName2="r7_r6", params2={"ip": "192.168.67.2/24"})
net.addLink(r7, r8,
intfName1="r7_r8", params1={"ip": "192.168.78.1/24"},
intfName2="r8_r7", params2={"ip": "192.168.78.2/24"})
net.addLink(r8, h4,
intfName1="r8_h4", params1={"ip": "192.168.4.1/24"},
intfName2="h4_r8", params2={"ip": "192.168.4.2/24"})
h1.add_default_route_cmd("h1_r1", "192.168.1.1")
h2.add_default_route_cmd("h2_r5", "192.168.2.1")
h3.add_default_route_cmd("h3_r4", "192.168.3.1")
h4.add_default_route_cmd("h4_r8", "192.168.4.1")
その後ネットワークを実行します.詳細はgithubのexamples/mpls/sr_mpls_isis_12.py
を参照.
動作確認
SR-MPLSによるネットワークを体験したいので以下のルートを設定しておきます.
r1.cmd("ip route add 192.168.2.2/32 encap mpls 16400/16800/16500 via 192.168.12.2")
r1.cmd("ip route add 192.168.3.2/32 encap mpls 16500/16800/16400 via 192.168.12.2")
r1.cmd("ip route add 192.168.4.2/32 encap mpls 16400/16500/16800 via 192.168.12.2")
例えばh1からh2にpingするときには,r4とr8を経由するように遠回りさせます.
R1のルーティングテーブル
ルーティングテーブルを確認すると,IS-ISでルートが学習できていることがわかります.
R1のMPLSテーブル
h1 -> h2のping
h1からh2へpingを実行します.その後,パケットを確認します.
16400
,16800
,16500
のラベルが積まれていることがわかります.
r4_r3
でのパケットでは,上のラベルから16400
がpopされていることがわかります.
おわりに
以上,SR-MPLSを試してみた話でした.