SONiC: FPMメッセージのモニタ方法(dplane_fpm_nl)
FPMとは?
FRRouting (FRR) と SONiC は FPM (Forwarding Plane Manager) を用いて routing 情報のやり取りをしています。
FPM は zebra のプラグインで、従来の fpm と、新しい dplane_fpm_nl の2種類のモジュールがあります。
- fpm: netlink もしくは protobuf encoding に対応
- dplane_fpm_nl: netlink のみ対応
新機能追加時は dplane_fpm_nl には必ず対応しますが、従来の fpm には対応する必要がありません。よって、(SONiCに限らず)今後利用するのであれば dplane_fpm_nl を利用すると良いでしょう。
SONiC では bgp container 内の zebra 起動オプションでどちらを利用するか指定されています。
admin@sonic:~$ docker exec -it bgp bash
root@sonic:/# grep fpm /etc/supervisor/conf.d/supervisord.conf
command=/usr/lib/frr/zebra -A 127.0.0.1 -s 90000000 -M dplane_fpm_nl -M snmp
なお、supervisord.conf
を直接編集してもコンテナ再起動時には以下テンプレート(supervisord.conf.j2
)を元に上書きされます。そのため、変更時にはテンプレートを編集する必要がある事に注意しましょう。
/usr/share/sonic/templates/supervisord/supervisord.conf.j2
FPMメッセージのモニタ手順
netlink は ip monitor コマンドを用いると人間が読める形式(テキスト)にデコード&表示可能です。しかし、FPMは以下のようなヘッダが付属するため、そのままでは ip monitor コマンドでデコードできません。
引用:FRR Docs >> FPM, Frame header:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------+---------------+-------------------------------+
| Version | Message type | Message length |
+---------------+---------------+-------------------------------+
| Data... |
+---------------------------------------------------------------+
有難い事に、このヘッダを取り除く Go program GitHub: fpm-logger が公開されています。
以降、fpm-logger を用いてモニタする手順を解説します。
なお、(SONiCではなく)FRRが動作するコンテナを作成してモニタする方法は、作者による以下記事を参照してください。
fpmsyncd の停止
まず bgp container 内で動作している fpmsyncd を停止します。
fpmsyncd は FRR(zebra) から FPM 経由でルーティング情報を受け取り APPL_DB
に書き込むプロセスです。(逆もあります)
root@sonic:/# ps ax
PID TTY STAT TIME COMMAND
1 pts/0 Ss+ 0:00 /usr/bin/python3 /usr/local/bin/supervisord
28 pts/0 S 0:00 python3 /usr/bin/supervisor-proc-exit-listener --container-name bgp
29 pts/0 Sl 0:00 /usr/sbin/rsyslogd -n -iNONE
33 pts/0 Sl 0:00 /usr/lib/frr/zebra -A 127.0.0.1 -s 90000000 -M dplane_fpm_nl -M snmp
48 pts/0 S 0:00 /usr/lib/frr/staticd -A 127.0.0.1
49 pts/0 Sl 0:00 /usr/lib/frr/bgpd -A 127.0.0.1 -M snmp
51 pts/0 Sl 0:00 /usr/bin/python3 /usr/local/bin/bgpcfgd
55 pts/0 S 0:00 /usr/bin/python3 /usr/local/bin/bgpmon
58 pts/0 Sl 0:00 fpmsyncd
74 pts/1 Ss 0:00 bash
125 pts/1 R+ 0:00 ps ax
この fpmsyncd は supervisord の critical なプロセスとなっており、KILLすると bgp container が再起動します。そのため、まず critical なプロセス一覧 critical_processes
から削除します。
なお、supervisord.conf
と同様に critical_processes
もテンプレート側を変更する必要がある事に注意しましょう。
- critical_processes.j2 から program:fpmsyncd を削除
admin@sonic:~$ docker exec -it bgp bash
root@sonic:/etc/supervisor# cat critical_processes
program:zebra
program:staticd
program:bgpd
program:fpmsyncd
program:bgpcfgd
root@sonic:/# cd /usr/share/sonic/templates/supervisord/
root@sonic:/usr/share/sonic/templates/supervisord# ls
critical_processes.j2 supervisord.conf.j2
root@sonic:/usr/share/sonic/templates/supervisord# cp critical_processes.j2 critical_processes.j2.org
> critical_processes.j2 から program:fpmsyncd を削除
- sonic host にて bgp container を再起動
admin@sonic:~$ docker restart bgp
root@sonic:/# cat /etc/supervisor/critical_processes
program:zebra
program:staticd
program:bgpd
program:bgpcfgd
- fpmsyncd を kill し、port 2620 を解放
> fpmsyncd のプロセスIDを確認
root@sonic:/# ss -nat | grep 2620
LISTEN 0 2 127.0.0.1:2620 0.0.0.0:*
root@sonic:/# ps ax | grep fpmsyncd
60 pts/0 Sl 0:00 fpmsyncd
> fpmsyncd を kill
root@sonic:/# kill 60
root@sonic:/# ss -nat | grep 2620
root@sonic:/#
fpm-logger の入手&起動
次に、公開されている Docker Image を利用して fpm-logger を起動しましょう。
(GitHub の Dockerfile を用いてビルドする事も可能です)
なお、コンテナ起動時には bgp container とネットワークスタックを共有するオプション --network container:bgp
を付けています。
admin@sonic:~$ docker pull yutarohayakawa/fpm-logger
admin@sonic:~$ docker run -it --network container:bgp yutarohayakawa/fpm-logger bash
FPMメッセージをモニタする
- fpm-logger コンテナで fpm-logger を起動
root@sonic:/opt/fpm-logger# fpm-logger | ip monitor all file /dev/stdin
- bgp コンテナで FPMの設定を投入
vtysh は sonic host, bgp container どちらからでも入れます
admin@sonic:~$ vtysh
Hello, this is FRRouting (version 8.2.2).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
sonic# configure
sonic(config)# fpm address 127.0.0.1 port 2620
FPMの設定を投入すると、fpm-logger が受信したメッセージを表示します。
root@sonic:/opt/fpm-logger# fpm-logger | ip monitor all file /dev/stdin
[NEXTHOP]id 160 dev eth0 proto zebra
[NEXTHOP]id 161 via 192.168.122.1 dev eth0 proto zebra
[NEXTHOP]id 162 dev docker0 proto zebra
[NEXTHOP]id 150 dev eth0 proto zebra
[NEXTHOP]id 151 dev Loopback0 proto zebra
[NEXTHOP]id 152 dev Ethernet12 proto zebra
[NEXTHOP]id 153 dev Ethernet8 proto zebra
[NEXTHOP]id 154 dev Ethernet4 proto zebra
[NEXTHOP]id 155 dev Ethernet0 proto zebra
[NEXTHOP]id 156 dev eth4 proto zebra
[NEXTHOP]id 157 dev eth3 proto zebra
[NEXTHOP]id 158 dev eth2 proto zebra
[NEXTHOP]id 159 dev eth1 proto zebra
[ROUTE]0.0.0.0/0 nhid 161 proto kernel metric 20
[ROUTE]192.168.122.0/24 nhid 150 proto kernel metric 20
[ROUTE]fd00::/80 nhid 162 proto kernel metric 20
[ROUTE]fe80::/64 nhid 160 proto kernel metric 20
fpmsyncd を起動したままモニタリングする方法
もちろん fpmsyncd と異なるポート番号を利用すれば KILL する事無くモニタリングが可能です。
- fpm-logger:
main.go
で listen するポートを変更(例:2621)
admin@sonic:~$ git clone https://github.com/YutaroHayakawa/fpm-logger.git
admin@sonic:~$ cd fpm-logger
admin@sonic:~/fpm-logger$ ls
Dockerfile main.go Makefile topo.yaml
> main.go を変更
func main() {
//ln, err := net.Listen("tcp", ":2620")
ln, err := net.Listen("tcp", ":2621")
if err != nil {
panic(err)
}
...snip...
- fpm-logger をビルド&起動
admin@sonic:~/fpm-logger$ sudo apt update
admin@sonic:~/fpm-logger$ sudo apt install golang
admin@sonic:~/fpm-logger$ go build
admin@sonic:~/fpm-logger$ ls
Dockerfile fpm-logger main.go Makefile topo.yaml
^^^^^^^^^^
admin@sonic:~/fpm-logger$ ./fpm-logger | ip monitor all file /dev/stdin
- fpm 設定
sonic host で fpm-logger を起動する場合は address を 192.168.122.169 に設定
admin@sonic:~$ vtysh
sonic# configure
sonic(config)# fpm address 192.168.122.169 port 2621
sonic host 上で表示されます。
admin@sonic:~/fpm-logger$ ./fpm-logger | ip monitor all file /dev/stdin
[NEXTHOP]id 160 dev eth0 proto zebra
[NEXTHOP]id 161 via 192.168.122.1 dev eth0 proto zebra
[NEXTHOP]id 162 dev docker0 proto zebra
[NEXTHOP]id 150 dev eth0 proto zebra
[NEXTHOP]id 151 dev Loopback0 proto zebra
[NEXTHOP]id 152 dev Ethernet12 proto zebra
[NEXTHOP]id 153 dev Ethernet8 proto zebra
[NEXTHOP]id 154 dev Ethernet4 proto zebra
[NEXTHOP]id 155 dev Ethernet0 proto zebra
[NEXTHOP]id 156 dev eth4 proto zebra
[NEXTHOP]id 157 dev eth3 proto zebra
[NEXTHOP]id 158 dev eth2 proto zebra
[NEXTHOP]id 159 dev eth1 proto zebra
[ROUTE]0.0.0.0/0 nhid 161 proto kernel metric 20
[ROUTE]192.168.122.0/24 nhid 150 proto kernel metric 20
[ROUTE]fd00::/80 nhid 162 proto kernel metric 20
[ROUTE]fe80::/64 nhid 160 proto kernel metric 20
Discussion