FRRoutingとYAMAHA RTX830のBGP接続性確認

## Introduction

今回の記事では、FRRoutingとYAMAHA RTX830の間でBGPを使用した相互接続性を確認します。  
RTX830とFRRouting（Linux上に構築）の2台間でiBGP接続を確立し、FRRoutingからStatic RouteをBGPに再配送してRTX830に経路学習させます。

FRRoutingはLinux/Unix上で動作するルーティングプロトコルスイートであり、BGP、OSPF、IS-ISなどのルーティングプロトコルをサポートしています。  
FRRoutingの前身はQuagga/Zebraプロジェクトであるため、FRRouting自体には馴染みが無くてもピンとくる方はいるかもしれません。

きっかけは「ルーター（RTX830）の設定はある時点で固定するものの、任意の経路情報だけを外部から注入したい（ただし転送は全てルーターに任せたい）」というユースケースの実現性確認に使ったものですが、ついでに基本となるFRRoutingのインストールからBGP接続確認までの設定・手順を整理しました。  
そのため、今回取り上げる構成例ではFRRoutingをルーターへの経路注入のためだけに利用し、FRRoutingがインストールされたLinuxマシンはパケット転送に関与しません。

## Network topology

使用したバージョンは以下の通りです。

| Device    | Version      |
| --------- | ------------ |
| RTX830    | Rev.15.02.20 |
| FRRouting | 8.4.2        |

接続構成は以下のようにします。

```
+--------+   AS:65500     +-------+
| RTX830 | <--- iBGP ---> | frr01 | < Static 192.168.0.0/24 -> Redistribute BGP
+---+----+                +---+---+
    | .1                      | .81
----+-------+-----------------+--------- 10.100.0.0/24
            | .82
        +---+----+
        | node01 |
        +---+----+
            | .1
         ---+--- 192.168.0.0/24
```

* RTX830とFRRoutingの間はAS:65500でiBGP接続
* node01配下の192.168.0.0/24の経路をFRRoutingにStatic Routeとして設定して再配布

## Install FRRouting

OSにはUbuntu 22.04を用意しました。クラウドイメージから起動しただけのシンプルなものです。

```
$ uname -a
Linux frr01 5.15.0-57-generic #63-Ubuntu SMP Thu Nov 24 13:43:17 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/os-release 
PRETTY_NAME="Ubuntu 22.04.2 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.2 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
```

[Docs » Installation](https://docs.frrouting.org/en/latest/installation.html) を眺めながらインストールします。  
インストールするFRRoutingのバージョンは環境変数 `FRRVER` で指定することが出来ます。

```
curl -s https://deb.frrouting.org/frr/keys.asc | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/frrouting.gpg
# frr-8 or frr-stable
FRRVER="frr-8"
echo deb https://deb.frrouting.org/frr $(lsb_release -s -c) $FRRVER | sudo tee /etc/apt/sources.list.d/frr.list
sudo apt update && sudo apt install frr frr-pythontools
```

FRRoutingのコンソールに入るためのvtyshコマンドの実行にfrr/frrvty権限が必要なので、ログインユーザーでも使えるように設定します。

```
sudo usermod -aG frr $USER
sudo usermod -aG frrvty $USER
```

以降は再ログインしてから作業しましょう。

vtyshコマンド実行時に以下のエラーが出るときは、単に権限不足です。

```
$ vtysh
% Can't open configuration file /etc/frr/vtysh.conf due to 'Permission denied'.
Exiting: failed to connect to any daemons.
Hint: if this seems wrong, try running me as a privileged user!
```

ここまでの手順通りであれば設定済みなので、再ログインすると解消されます。  
`sudo vtysh` もしくは既にユーザーが作成されるので `sudo -u frr vtysh` でも良いでしょう。

## Setup BGP

[Docs » BGP](https://docs.frrouting.org/en/latest/bgp.html) を眺めながら設定します。  
まず、FRRoutingでBGPデーモンを起動するように設定します。

```
sudo sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons 
sudo systemctl restart frr
```

bgpdが動いていればOK。

```
$ ps ax | grep [b]gp
  15632 ?        S<s    0:22 /usr/lib/frr/watchfrr -d -F traditional zebra bgpd staticd
  15650 ?        S<sl   0:03 /usr/lib/frr/bgpd -d -F traditional -A 127.0.0.1
```

パッケージのバージョンと、FRRoutingのバージョン情報を確認します。

```
$ dpkg -l | grep frr
ii  frr                             8.4.2-0~ubuntu22.04.1                   amd64        FRRouting suite of internet protocols (BGP, OSPF, IS-IS, ...)
ii  frr-pythontools                 8.4.2-0~ubuntu22.04.1                   all          FRRouting suite - Python tools
$ vtysh

Hello, this is FRRouting (version 8.4.2).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

frr01# show version
FRRouting 8.4.2 (frr01) on Linux(5.15.0-57-generic).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
configured with:
    '--build=x86_64-linux-gnu' '--prefix=/usr' '--includedir=${prefix}/include' '--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' '--sysconfdir=/etc' '--localstatedir=/var' '--disable-option-checking' '--disable-silent-rules' '--libdir=${prefix}/lib/x86_64-linux-gnu' '--libexecdir=${prefix}/lib/x86_64-linux-gnu' '--disable-maintainer-mode' '--localstatedir=/var/run/frr' '--sbindir=/usr/lib/frr' '--sysconfdir=/etc/frr' '--with-vtysh-pager=/usr/bin/pager' '--libdir=/usr/lib/x86_64-linux-gnu/frr' '--with-moduledir=/usr/lib/x86_64-linux-gnu/frr/modules' '--disable-dependency-tracking' '--enable-rpki' '--disable-scripting' '--enable-pim6d' '--with-libpam' '--enable-doc' '--enable-doc-html' '--enable-snmp' '--enable-fpm' '--disable-protobuf' '--disable-zeromq' '--enable-ospfapi' '--enable-bgp-vnc' '--enable-multipath=256' '--enable-user=frr' '--enable-group=frr' '--enable-vty-group=frrvty' '--enable-configfile-mask=0640' '--enable-logfile-mask=0640' 'build_alias=x86_64-linux-gnu' 'PYTHON=python3'
```

デフォルトのコンフィグは以下のようになっていました。

```
frr01# show running-config 
Building configuration...

Current configuration:
!
frr version 8.4.2
frr defaults traditional
hostname frr01
log syslog informational
no ip forwarding
no ipv6 forwarding
service integrated-vtysh-config
!
end
```

## BGP Configuration

ここから、YAMAHA RTX830とFRRoutingにBGP設定を入れていきます。

### RTX830 BGP configuration

RTXにsshログインして管理者モードに入るところまでは出来る前提で、以下のように設定します。

```
# show config | grep -i bgp
Searching ...
bgp use on
bgp autonomous-system 65500
bgp neighbor 2 65500 10.100.0.81 ignore-capability=on
bgp router id 10.100.0.1
```

:::note info
FRRouting 8.4.2を使用したところ、YAMAHAとのNeighbor確立中に "Unsupported Optional Parameter" が返るので `ignore-capability=on` を設定して無視します。
:::

### FRRouting BGP Configuration

FRRoutingにもRTX830向けのBGP設定を入れます。

まずはBGP Neighborの設定。

```
frr# configure 
frr(config)# router bgp 65500
frr(config-router)# bgp router-id 10.100.0.81
frr(config-router)# neighbor 10.100.0.1 remote-as 65500
frr(config-router)# end
frr# 
```

次に、配布経路の設定を入れます。

```
frr# configure 
frr(config)# ip route 192.168.0.0/24 10.100.0.82
frr(config)# ip prefix-list prefix-static-to-bgp permit 192.168.0.0/24
frr(config)# route-map yamaha permit 10
frr(config-route-map)# match ip address prefix-list prefix-static-to-bgp
frr(config-route-map)# end
frr# 
```

これでひとまず設定は完了です。

:::note info
一般的なiBGP設定では `next-hop-self` を設定しますが、今回のように同一バス上にNexthopがあり、FRRoutingノードがユーザートラフィックの転送に関与しない場合は不要です。
:::

あとは注入する経路を増やしたい場合はStatic Routeとprefix-listを1行ずつ追加するだけです。  
例えば以下のように。

```
frr(config)# ip route 192.0.2.0/24 10.100.0.82
frr(config)# ip prefix-list prefix-static-to-bgp permit 192.0.2.0/24
```

## 動作確認

### RTX830

neighbor状態を確認します。`BGP state = Established` になっていれば良いでしょう。

```
> show status bgp neighbor 10.100.0.81
BGP neighbor is 10.100.0.81, remote AS 65500, local AS 65500, internal link
  BGP version 4, remote router ID 10.100.0.81
  BGP state = Established, up for 00:07:51
  Last read 00:00:51, hold time is 180, keepalive interval is 60 seconds
  Received 9 messages, 0 notifications, 0 in queue
  Sent 11 messages, 0 notifications, 0 in queue
  Connection established 3; dropped 2
  Last reset 00:07:53
Local host: 10.100.0.1, Local port: 179
Foreign host: 10.100.0.81, Foreign port: 33642
```

受信しているBGP経路情報を確認します。今回は `192.168.0.0/24` だけを学習しています。  
`*: valid route` のマークがついているので、ルーティングテーブルにも追加されます。

```
> show status bgp neighbor 10.100.0.81 received-routes 
Total routes: 1
*: valid route
  Network            Next Hop        Metric LocPrf Path
* 192.168.0.0/24     10.100.0.82         0    100 Incomplete
```

ルーティングテーブルにBGPで学習した `192.168.0.0/24` が追加できています。

```
> show ip route 192.168.0.0
宛先ネットワーク    ゲートウェイ     インタフェース  種別  付加情報
192.168.0.0/24     10.100.0.82            LAN1       BGP  path=[]
```

### FRRouting

neighbor状態を確認します。`Up/Down` の列が接続時間の表記になっていれば良いでしょう。  
`show bgp neighbor` コマンドもありますが、少々出力が長いので今回は省略です。

```
frr# show bgp summary

IPv4 Unicast Summary (VRF default):
BGP router identifier 10.100.0.81, local AS number 65500 vrf-id 0
BGP table version 1
RIB entries 1, using 192 bytes of memory
Peers 1, using 725 KiB of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
10.100.0.1      4      65500      1350      1352        0    0    0 00:21:58        NoNeg        1 N/A

Displayed neighbors 1
Total number of neighbors 1
```

送信しているBGP経路情報を確認します。既に受け取る側（RTX830）の確認を済ませていますが、設定したStatic Routeを経路広告していることが分かります。

```
frr# show bgp ipv4 neighbors 10.100.0.1 advertised-routes 
BGP table version is 1, local router ID is 10.100.0.81, vrf id 0
Default local pref 100, local AS 65500
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

    Network          Next Hop            Metric LocPrf Weight Path
 *> 192.168.0.0/24   10.100.0.82              0    100  32768 ?

Total number of prefixes 1
```

FRRouting側のルーティングテーブルはStatic Routeとして表示されます。

```
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

K>* 0.0.0.0/0 [0/0] via 10.100.0.1, eth0, 6d21h13m
C>* 10.100.0.0/24 is directly connected, eth0, 6d21h13m
S>* 192.168.0.0/24 [1/0] via 10.100.0.82, eth0, weight 1, 22:52:21
```

### 別のノードからping

`192.168.0.1` に対する通信は、最初の1回はデフォルトゲートウェイに向かいますが、その後はICMP Redirectに従って `10.100.0.82` がNexthopになります。  
`10.100.0.0/24` のリンク上にいる適当なノードからpingを実行します。

```
$ ip route get 192.168.0.1
192.168.0.1 via 10.100.0.1 dev eth0 src 10.100.0.2 uid 1000 
    cache 
$ ping -c4 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
From 10.100.0.1 icmp_seq=1 Redirect Host(New nexthop: 82.0.100.10)
64 bytes from 192.168.0.1: icmp_seq=1 ttl=63 time=0.322 ms
64 bytes from 192.168.0.1: icmp_seq=2 ttl=63 time=0.268 ms
64 bytes from 192.168.0.1: icmp_seq=3 ttl=63 time=0.264 ms

--- 192.168.0.1 ping statistics ---
3 packets transmitted, 3 received, +1 errors, 0% packet loss, time 2034ms
rtt min/avg/max/mdev = 0.264/0.284/0.322/0.026 ms
```

この時、ICMP Redirectを受信しないように設定している場合はRTXが律儀に転送し続けてくれます。

## (Optional) MD5認証の追加

BGPには接続相手を信用するためのMD5認証があります。  
YAMAHAの場合は以下のよう設定します。

```
bgp neighbor pre-shared-key 2 text some@password
bgp configure refresh 
```

RTX830の場合は、BGP設定を変更したら `bgp configure refresh` で再接続する必要があります。  
残念ながら `soft-reconfiguration` のような設定はありません。  
また、以下の制限もあります。

> なお、OSPFを併用している場合には、 bgp configure refreshコマンドを実行するときに、 OSPFの状態も初期化される点に注意してください。同様に、 ospf configure refreshコマンドを実行すると、OSPFの状態だけでなく、 BGPの状態も同時に初期化されます。 つまり、OSPFとBGPの状態を個別に初期化することはできません。

Ref: http://www.rtpro.yamaha.co.jp/RT/docs/bgp/bgp4-guide.html

FRRoutingの場合は以下のように設定します。

```
router bgp 65500
 neighbor 10.100.0.1 password some@password
end
```

Ref: http://www.rtpro.yamaha.co.jp/RT/docs/bgp/bgp4-command.html#bgp_neighbor_pre-shared-key

## (Optional) RTX830で受信する経路の制限

どんな経路でも受け取ってしまうのはまずいケースもありますので、フィルターで制限してみます。  
例として以下のような条件にしました。

* 受信可能なCIDR
    * 10.0.0.0/8
    * 172.16.0.0/12
    * 192.168.0.0/16
* 許可されている範囲ではあるもの、個別に拒否したいCIDR
    * 10.100.0.0/16
    * 172.31.255.0/24

この場合は以下のように設定します。

```
bgp export filter 1 include 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
bgp export filter 2 reject include 10.100.0.0/16 172.31.255.0/24
bgp export 65500 filter 1 2
bgp configure refresh 
```

無効な経路は、受信できるものの `valid route` として扱われず、ルーティングテーブルには乗りません。  
（以下の経路はfilterの挙動を見るためにFRRoutingから適当に広告したものです。今回の構成ではいずれも到達不可能です）

```
# show status bgp neighbor 10.100.0.81 received-routes 
Total routes: 4
*: valid route
  Network            Next Hop        Metric LocPrf Path
* 10.99.0.0/24       10.100.0.82          0    100 Incomplete
* 192.168.10.0/24    10.100.0.82          0    100 Incomplete
  192.0.2.0/24       10.100.0.82          0    100 Incomplete
  10.100.10.0/24     10.100.0.82          0    100 Incomplete
```

どのfilterにもマッチしなかった場合はrejectされます。  
また、どのルールにマッチするかはロンゲストマッチのようです。

> IP_ADDRESS/MASKでは、ネットワークアドレスを設定する。 複数の設定があるときには、 プレフィックスが最も長く一致する設定が採用される。

Ref: http://www.rtpro.yamaha.co.jp/RT/docs/bgp/bgp4-command.html#bgp_export_filter

## おしまい

FRRoutingとRTX830の間でBGPを使った経路交換が確認できました。  
今回改めてドキュメントを読んでみましたが、YAMAHAルーターのBGPプロトコルサポートは限定的です。  
また、YAMAHA（RTシリーズ）の場合、どのBGP設定変更にも `bgp configure refresh` が必須（かつ、ドキュメントによればOSPFプロセス等もリセットされてしまう）であるため、ルーティングプロトコルの設定を動的に変えたいという要望を実現するには工夫が必要になりそうです。

FRRoutingはKubernetesのMetalLBでも使用されており、現在でも見かけることの多いルーティングソフトウェアです。  
このほかにもYANG/gRPCで動的な設定が可能な [Northbound gRPC](http://docs.frrouting.org/en/latest/grpc.html) なども開発されており、今後も様々な場面で使われる可能性がありそうです。