FRRoutingでSR-MPLSを動かす

**（2019年4月23日追記）**
**Reverse Path Filteringの設定を追加**

## 目的
[FRRouting](https://github.com/FRRouting/frr "FRRouting")に実装されているOSPFのSR拡張と，Linux Kernel 4.3.0より実装されているMPLS機能を用いてSegment Routingを動作させます．
[ospf-srのドキュメント](https://github.com/FRRouting/frr/blob/master/doc/developer/ospf-sr.rst "ospf-sr")を参考に，OSPFによるSID配布を確認した後，iproute2を用いてMPLSのスタティックルートを設定します．

## 実行環境
- Ubuntu16.04
    + Linux kernel 4.15.0-34-generic
- iproute2 4.18.0
- FRRouting 6.1-dev

## 実験トポロジ
トポロジは以下の通りです
![sr_mpls.png](https://qiita-image-store.s3.amazonaws.com/0/221962/dad1984e-3fff-485d-0c18-369d84698ec5.png)


- ルータ間のP2Pアドレスは`172.16.0.x/30`
- ループバックアドレスは`192.168.0.x/32`
- ルータ上の数字はNode SID．frr1ならNode SID `17001`を設定

## 設定
###カーネルの最新化

```
sudo apt install linux-image-extra-4.15.0-15-generic
```

### iproute2の最新化
[@ebikenさんの記事](https://qiita.com/ebiken/items/fc86b054b76442e495f1)を参考にしました．
[2-4.18.0の手順](http://www.linuxfromscratch.org/lfs/view/development/chapter06/iproute2.html)では`rm -v doc/arpd.sgml`は不要になっています．

```
sudo apt install bison flex make
wget https://mirrors.edge.kernel.org/pub/linux/utils/net/iproute2/iproute2-4.18.0.tar.gz
tar xfv iproute2-4.18.0.tar.gz
cd iproute2-4.18.0

sed -i /ARPD/d Makefile
rm -fv man/man8/arpd.8
sed -i 's/.m_ipt.o//' tc/Makefile

make
sudo make DOCDIR=/usr/share/doc/iproute2-4.18.0 install
```

###FRRoutingのインストール
[公式ドキュメント](http://docs.frrouting.org/projects/dev-guide/en/latest/building-frr-for-ubuntu1604.html)を参考に．
daemonsはzebraとospfdを使用します．

以下の説明では，上の手順と重複するところもあります．

### カーネルモジュール設定
```
sudo modprobe mpls_router
sudo modprobe mpls_gso
sudo modprobe mpls_iptunnel
```
を実行し，MPLSに必要なモジュールを読み込ませます．

### sysctl
フォワーディング設定，Reverse Path Filteringの設定，MPLSの転送・ラベル上限の設定を行います．

```
sudo sysctl -w net.ipv4.ip_forward=1
sudo systcl -w net.ipv4.conf.all.rp_filter=0
sudo sysctl -w net.ipv4.conf.lo.rp_filter=0
sudo sysctl -w net.mpls.conf.<参加するインターフェース>.input=1
sudo sysctl -w net.mpls.conf.lo.input=1
sudo sysctl -w net.mpls.platform_labels=1048575
```

### FRRouting設定

OSPF-SRの設定を行います．frr.confの内容は以下の通りです．
ループバックインターフェースをOSPFで広報しましょう．

```:/etc/frr/frr.conf&nbsp;(frr1)
frr version 6.1-dev-MyOwnFRRVersion
frr defaults traditional
hostname frr1
log syslog informational
service integrated-vtysh-config
username cumulus nopassword
!
interface ens3
 ip address 172.16.0.1/30
 ip ospf area 0.0.0.0
!
interface ens4
 ip address 172.16.0.9/30
 ip ospf area 0.0.0.0
!
interface lo
 ip address 192.168.0.1/32
 ip ospf area 0.0.0.0
!
router ospf
 ospf router-id 192.168.0.1
 router-info area 0.0.0.0
 passive-interface lo
 capability opaque
 mpls-te on
 mpls-te router-address 192.168.0.1
 segment-routing on
 segment-routing global-block 16000 19999
 segment-routing node-msd 8
 segment-routing prefix 192.168.0.1/32 index 1001
!
line vty
!
log file /var/log/frr/frr.log
!
```
frr2〜frr4も同様に．

## ラベル確認
ipコマンドを利用しMPLSテーブルを確認します．

```
watal@frr1:~$ ip -M route
17002 via inet 172.16.0.2 dev ens3 proto ospf
17003 as to 17003 via inet 172.16.0.2 dev ens3 proto ospf
17004 via inet 172.16.0.10 dev ens4 proto ospf
50000 via inet 172.16.0.10 dev ens4 proto ospf
50001 via inet 172.16.0.10 dev ens4 proto ospf
50002 via inet 172.16.0.2 dev ens3 proto ospf
50003 via inet 172.16.0.2 dev ens3 proto ospf
```

vtyshに入り，FRRoutingからも確認できます．

```
frr1# show mpls table
 Inbound                            Outbound
   Label     Type          Nexthop     Label
--------  -------  ---------------  --------
   17002       SR       172.16.0.2  implicit-null
   17003       SR       172.16.0.2     17003
   17004       SR      172.16.0.10  implicit-null
   50000       SR      172.16.0.10  implicit-null
   50001       SR      172.16.0.10  implicit-null
   50002       SR       172.16.0.2  implicit-null
   50003       SR       172.16.0.2  implicit-null
```

`show ip ospf database segment-routing`コマンドでSRに関する情報が取れます．

```
frr1# show ip ospf database segment-routing

                OSPF Segment Routing database for ID 192.168.0.1

SR-Node: 192.168.0.4    SRGB (Size/Label): 4000/16000   Algorithm(s): SPF       MSD: 8

    Prefix or Link  Label In  Label Out       Node or Adj. SID  Interface          Nexthop
------------------  --------  ---------  ---------------------  ---------  ---------------
    192.168.0.4/32     17004        pop      SR Pfx (idx 1004)       ens4      172.16.0.10

SR-Node: 192.168.0.2    SRGB (Size/Label): 4000/16000   Algorithm(s): SPF       MSD: 8

    Prefix or Link  Label In  Label Out       Node or Adj. SID  Interface          Nexthop
------------------  --------  ---------  ---------------------  ---------  ---------------
    192.168.0.2/32     17002        pop      SR Pfx (idx 1002)       ens3       172.16.0.2

SR-Node: 192.168.0.1    SRGB (Size/Label): 4000/16000   Algorithm(s): SPF       MSD: 8

    Prefix or Link  Label In  Label Out       Node or Adj. SID  Interface          Nexthop
------------------  --------  ---------  ---------------------  ---------  ---------------
    192.168.0.1/32         0          0      SR Pfx (idx 1001)         lo      192.168.0.1
     172.16.0.9/32     50001        pop    SR Adj. (lbl 50001)       ens4      172.16.0.10
     172.16.0.9/32     50000        pop    SR Adj. (lbl 50000)       ens4      172.16.0.10
     172.16.0.1/32     50003        pop    SR Adj. (lbl 50003)       ens3       172.16.0.2
     172.16.0.1/32     50002        pop    SR Adj. (lbl 50002)       ens3       172.16.0.2

SR-Node: 192.168.0.3    SRGB (Size/Label): 4000/16000   Algorithm(s): SPF       MSD: 8

    Prefix or Link  Label In  Label Out       Node or Adj. SID  Interface          Nexthop
------------------  --------  ---------  ---------------------  ---------  ---------------
    192.168.0.3/32     17003      17003      SR Pfx (idx 1003)       ens3       172.16.0.2
```
各ノードのNode SID情報や各インターフェースにPrimaryとBackupの二つのAdjacency SIDが登録されていることがわかります．

他にも，`show ip ospf database`コマンドでOpaque-LSAのID 4，7，8の情報が．また`show ip ospf database opaque-area`コマンドでその詳細情報が確認できます．

###スタティックルート設定

配布されたラベルを利用し，MPLSで以下のように経路制御を行います．

![sr_mpls_flow.png](https://qiita-image-store.s3.amazonaws.com/0/221962/a309bc7c-d8c4-5ad3-dd6e-406b9cab1300.png)


FRRoutingにはMPLS-TE tunnelの設定が見当たらないので，iproute2でスタティックルートを設定します．
frr1からfrr3への設定

```
watal@frr1:~$ sudo ip route add 192.168.0.3/32 encap mpls 17004/17003 via 172.16.0.2
```

frr3でも同様に

```
watal@frr3:~$ sudo ip route add 192.168.0.1/32 encap mpls 17002/17001 via 172.16.0.18
```

frr1からfrr3へpingを実行し，frr2・frr4でパケットキャプチャを行います．
送信元にloを指定することを忘れずに．

```
watal@frr1:~$ ping 192.168.0.3 -I 192.168.0.1
PING 192.168.0.3 (192.168.0.3) from 192.168.0.1 : 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=63 time=1.31 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=63 time=1.30 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=63 time=1.49 ms
```
frr2・frr4でキャプチャを行いました
`frr2:~$ sudo tcpdump -i ens3 -w frr2.pcap`の結果
<img width="965" alt="Screen Shot 2018-10-17 at 16.09.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/221962/1894a947-d4e7-602a-2774-ba41d84b2998.png">

`frr4:~$ sudo tcpdump -i ens4 -w frr4.pcap`の結果
<img width="962" alt="Screen Shot 2018-10-17 at 16.09.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/221962/9967b6a1-60a2-3242-479c-cb100d4bbc91.png">

MPLSによりセグメントリストとなるラベルスタックが付与され，経路制御が行われたことが確認できます．

## まとめ
- FRRoutingとLinuxカーネルに実装されたMPLSによりSR-MPLSの動作確認
    + OSPF-SRによるSID配布確認
    + OSPF-SRで用いるOpaque-LSAの確認
    + MPLSスタティックルートを用いた経路制御