ネットワーク勉強の続き - 2: FRRouting(FRR)/OSPF入門
ネットワーク勉強まとめのスクラップ:
このスクラップについて
上記のスクラップまででLinuxのNetwork Namespaceを使って基本的な?ネットワークを使って、Static Routeでルーティングを設定するというのは最低限体験した。
んでCNIの仕組みの話をしていくとBGPみたいなルーティングプロトコルなるものの話が出てくることが多いので、比較的簡単な(気がした)OSPFというのを試そうというやつ。
(Network Namespaceを使ってOSPFを試すというので良い記事を見つけたという理由も大きい)
あとはtinetというコンテナでネットワーク構成を検証するアプリケーションがあるんだけど、これのルーティングをFRRoutingというソフトウェアを使ってやっているケースが多いのだけど、こういうルーティングプロトコルを喋るアプリケーション?を動かすのも初めてなので併せてどんなものか理解できるようにしていきたい。
flannelの仕組みを理解するだけならルーティングプロトコルについては知らなくても理解できそうな気もしたけどせっかくなので試していく。
ということでFRRouting/OSPFに入門するためのベースとなる記事は下記のもの:
図もあってネットワーク初心者でもどんなものを作るのかイメージしやすく、コマンドをコピペするだけで動いて動作確認したりする方法とその検証結果も書かれているのでどんな仕組みになっているのかを理解しやすくてとてもありがたい。
一方でFRRouting/OSPF自体については多分なんとなく知っている前提で書かれているので、まず先にそのあたりについて調べた情報をまとめつつ実際に記事の内容を自分で試してみたメモを書こうかなと思ってる。
FRRouting/OSPF自体について調べる過程でChatGPTに質問しまくったので、可能な範囲で自分で調べて裏取りするようにはしたつもりだけど、もしこのスクラップを参考にする人がいたら雰囲気でメモを書いてる箇所もあることに注意してもらえると。
OSPFについて
OSPF(Open Shortest Path First)とは下記のようなものとのこと:
- ルーティングプロトコルの一種
- 内部ゲートウェイプロトコル(IGP)として広く使用されているらしい
- OSPFは、ネットワーク上の経路情報を交換し、最適な経路を計算してデータパケットの転送を制御するために使用される
要は今回最終的に作りたい↓の図みたいな構成でr1-s1
から r4-s1
に通信する場合
-
router1 → router2 → router4
とかrouter1 → router3 → router4
って経路で行けばr4-s1
までたどり着けて -
r4-s1
まで行くためにはrouter1 → router2 → router4
とrouter1 → router3 → router4
のどっちの経路を優先してつかったら良いの?とか(今回の構成だと同じだと思うけど)
みたいのを計算してルーター(Linuxのルーティングテーブルとか)に経路情報を設定していい感じの経路でr1-s1
から r4-s1
に通信できるように設定してくれるための仕様がOSPFだって理解した。
OSPFの仕様とバージョン
仕様はRFC2328にある(こちらに日本語訳を書かれてるがある)
OSPFにはv1-3の3つのバージョンがあるっぽくて
- v1はもうあまり使われてないっぽい?
- 上記RFCもv2だけど、現在だとIPv4でのOSPFというのは一般的にはv2を指してるっぽい
- v3はIPv6用のものっぽい
ゲートウェイプロトコル
概要のところで
内部ゲートウェイプロトコル(IGP)として広く使用されているらしい
って書いたけど
- 内部ゲートウェイプロトコル(IGP)
- 外部ゲートウェイプロトコル(EGP)
と呼ばれる2種類に区分されるっぽい。
OSPFは内部ゲートウェイプロトコル(IGP)に区分されるもので、要は多分データセンターの内部ネットワーク構築とかで使われるやつで、OSPF以外には
- RIP
- IS-IS
といったプロトコルがあるらしい。
外部ゲートウェイプロトコル(EGP)はインターネット上の経路情報を交換するためのプロトコルらしく、EGPに区分される中で主に使われてるのはほぼほぼBGPというプロトコルのみであるらしい。
EGPとBGPのついてはまだ詳しく理解できてないのでそれは別途調べるのでここではこれ以上は書かない。
OSPFの概要
上記のRFCの翻訳の Abstract
によるとOSPFは下記のようなものであるとのこと。
- リンクステートルーティングプロトコルであり
- 単一の自律システムの内部で実行されるように設計されていて
- 各OSPFルーターは、自律システムのトポロジーを記述する同一のデータベースを維持していて
- このデータベースから、最短経路ツリーを構築することによってルーティングテーブルが計算されるようになっている
リンクステートルーティングプロトコルがどういうものかは自分で説明をかけるほどわかってないのでスキップするけど、一番はじめに書いたような経路情報を計算~設定してくれるものであるのはあってそうだった。
リンクステートルーティングプロトコルについて知りたい方はこことかこのあたりで説明されている。
ふわっとしたOSPFの動作イメージの理解
最終的には実際のネットワーク構成を作ってOSPFを試すときにはFRRを使うのだけど、その際に設定するOSPFの設定はこんな感じになる。
router1# conf t
router1(config)# router ospf
router1(config-router)# network 10.0.0.0/8 area 0
router1(config-router)# end
router1# write
router1# exit
OSPFの設定そのものををしている箇所は network 10.0.0.0/8 area 0
の行だけになる。
network 10.0.0.0/8
の部分でOSPFで経路設定を行うルーターのCIDRを設定してるだけということになる。
areaというのはOSPFの論理的なセグメントみたいなものらしいが、今回はエリアは0しか使わない。
ちなみにエリア0はバックボーンエリアという特別なエリアとして扱われるらしい。
エリアについてもうちょい知りたい方はこの記事とかがイメージしやすいかもしれない。
ともかく、上記のOSPF設定を各ルーター上のFRRで行うだけでルーター同士がいい感じに経路交換してくれて、r1-s1 → router1 → router2 → router4 → r4-s1
といった経路を通って r1-s1
から r4-s1
の通信ができるようにしてくれる。
上記の設定をすることで各ルーターの内部では下記のような処理を行うことで経路設定を行ってくれるよう。
- Helloパケットというのを送りあって隣接するルーター(neighbor)を探す(構成にもよるみたいだけどHelloパケットはブロードキャストなどで接続してるネットワークの各ルータに送られるよう)
- Helloパケットを受信したルーターは、送信元とのネットワークタイプ(ブロードキャスト、ポイントツーポイント、仮想リンクなど)が一致しているかどうかを確認する
- 一致した場合はルーター間でマスタ/スレーブの選出が行われ、ネイバーシップが確立される(マスタはDR(Designated Router)、スレーブはBDR(Backup Designated Router)と呼ばれ、ルーターIDの大きさやルーターに設定された優先度、IPアドレスの値の大きさなどに基づきDRが選出されるとのこと)
- ネイバーシップが確立されたらリンクステート情報を交換し、ルーターごとにリンク状態データベース(LSDB)を構築する
- LSDBを参照し、各経路に対する最短経路を計算を行う(最短経路はホップ数やインターフェイスの帯域幅、OSPFに設定した優先度などに基づいて決定されるよう)
- 計算結果に基づいて各ルーターのルーティングテーブルを設定する(
ip route add
コマンドでStatic Routeを設定するみたいなのを自動でやってくれる)
Helloパケットの中身については下記の記事が参考になった。
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 # | 1 | Packet length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Router ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Area ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | AuType |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Authentication |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Authentication |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Network Mask |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| HelloInterval | Options | Rtr Pri |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RouterDeadInterval |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Designated Router |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Backup Designated Router |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Neighbor |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ... |
上記の図はRFCより
また、後で実際に試すFRRのOSPFで下記のような感じでネイバー情報やルーティング情報が見れるんだけど、このあたりの情報がリンク状態データベース(LSDB)に保存されてるデータってことで良いのかな?
$ ip netns exec router1 vtysh -N router1 -c 'show ip ospf neighbor'
Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
10.0.24.2 1 Full/Backup 1d02h48m 34.864s 10.0.12.2 e1:10.0.12.1 0 0 0
10.0.34.3 1 Full/Backup 1d02h46m 34.864s 10.0.13.3 e2:10.0.13.1 0 0 0
$ ip netns exec router1 vtysh -N router1 -c 'show ip ospf route'
============ OSPF network routing table ============
N 10.0.12.0/24 [10] area: 0.0.0.0
directly attached to e1
N 10.0.13.0/24 [10] area: 0.0.0.0
directly attached to e2
N 10.0.24.0/24 [20] area: 0.0.0.0
via 10.0.12.2, e1
N 10.0.34.0/24 [20] area: 0.0.0.0
via 10.0.13.3, e2
N 10.0.91.0/24 [10] area: 0.0.0.0
directly attached to e0
N 10.0.92.0/24 [30] area: 0.0.0.0
via 10.0.12.2, e1
via 10.0.13.3, e2
============ OSPF router routing table =============
============ OSPF external routing table ===========
今回OSPFについて調べたのはだいたいこのあたりまでで、このあたりまで理解できてなんとなくOSPFの仕組みをふわっとイメージすることができたので納得できた。
FRRouting(FRR)
FRRoutingはオープンソースのルーティングソフトウェアで、OSPFやBGPなど様々なプロトコルをサポートしているLinuxなどで動作するソフトウェアのよう。
また、FRRoutingはQuaggaというソフトウェアのforkらしい。
- 公式サイト: https://frrouting.org/
- GitHubリポジトリ: https://github.com/FRRouting/frr
- ドキュメント: https://docs.frrouting.org/en/latest/index.html
- ディベロッパーガイド: https://docs.frrouting.org/projects/dev-guide/en/latest/
FRRoutingがサポートしてるプロトコルはこちらにマトリクスで紹介されているが、ネットワーク初心者の自分からすると多すぎてよくわからん。
FRRoutingのアーキテクチャ
FRRoutingのアーキテクチャは
- 各プロトコルごとに独自のdaemonが動作して
- カーネルにルーティングテーブルを実際に書き込んだりする仲介デーモンである
zebra
がいる - これらのdaemonの設定などを行うCLIとして
vtysh
がある
という仕組みになっているようで、公式ドキュメントのシステムアーキテクチャにあるように下記のようになっているらしい。
+----+ +----+ +-----+ +----+ +----+ +----+ +-----+
|bgpd| |ripd| |ospfd| |ldpd| |pbrd| |pimd| |.....|
+----+ +----+ +-----+ +----+ +----+ +----+ +-----+
| | | | | | |
+----v-------v--------v-------v-------v-------v--------v
| |
| Zebra |
| |
+------------------------------------------------------+
| | |
| | |
+------v------+ +---------v--------+ +------v------+
| | | | | |
| *NIX Kernel | | Remote dataplane | | ........... |
| | | | | |
+-------------+ +------------------+ +-------------+
FRRの設定ファイルについてはこのページで解説されていて、Network Namespaceで動かすこともできるようになっている。
その他
このページを見るとカーネル ルーティング テーブルの操作などを行うために
- ioctl
- sysctl
- proc filesystem
- routing socket / Netlink
が利用されているとのことで、下記の記事に書いたように少し前にNetlinkとioctlを軽く触ったんだけどsysctlとproc filesystemからもネットワーク関連操作が可能なのか。
このあたりまで理解してFRRoutingがどんな感じのソフトウェアかなんとなくイメージできた。
他にもBirdなどネットワークで使うソフトウェアはいくつもありそうだけど、とりあえずFRRoutingが使えればそれなりにいろんなネットワークの検証ができそう。
Network Namespaceを使ってOSPFを試す
ということでFRRoutingとOSPFについての概要がイメージできたので下記の記事を試していく。
(実際には下記の記事を試しながらChatGPTに質問したり調べたりしてたんだけど、スクラップの流れ的に先にFRRoutingとOSPFについて調べたことをまとめた)
この先は上記の記事の内容を試しつつわからないことをメモしするといった内容なので、OSPFを試して動作確認などをするだけなら上記記事をそのままやっていただく方が簡単でわかりやすいと思う。
まずはネットワーク構成を作ってOSPFを設定する
上記のネットワーク構成はだいたいこんな感じ
(ネットワークインターフェイス名とかは違うので注意)
設定するIPアドレスなどを一覧で見たいので論理NW構成図は引用させていただいた
元記事に従って環境構築する
基本元記事の通りにコマンドを実行しただけなんだけど、FRRのインストールやsedの処理など、自分の環境ではうまく行かなかった部分があるので実行したコマンドを下記にまとめて書く。
(fib_multipath_hash_policyについては試してない)
# create network namespaces
ip netns add host1
ip netns add router1
ip netns add router2
ip netns add router3
ip netns add router4
ip netns add host2
# create cable(veth pairs)
ip link add eth0 netns host1 type veth peer name e0 netns router1
ip link add e1 netns router1 type veth peer name e0 netns router2
ip link add e2 netns router1 type veth peer name e0 netns router3
ip link add e1 netns router2 type veth peer name e0 netns router4
ip link add e1 netns router3 type veth peer name e1 netns router4
ip link add e2 netns router4 type veth peer name eth0 netns host2
# set IP address: host1
ip netns exec host1 ip addr add 10.0.91.100/24 dev eth0
# set IP address: router1
ip netns exec router1 sysctl -w net.ipv4.ip_forward=1
ip netns exec router1 ip addr add 10.0.91.1/24 dev e0
ip netns exec router1 ip addr add 10.0.12.1/24 dev e1
ip netns exec router1 ip addr add 10.0.13.1/24 dev e2
# set IP address: router2
ip netns exec router2 sysctl -w net.ipv4.ip_forward=1
ip netns exec router2 ip addr add 10.0.12.2/24 dev e0
ip netns exec router2 ip addr add 10.0.24.2/24 dev e1
# set IP address: router3
ip netns exec router3 sysctl -w net.ipv4.ip_forward=1
ip netns exec router3 ip addr add 10.0.13.3/24 dev e0
ip netns exec router3 ip addr add 10.0.34.3/24 dev e1
# set IP address: router4
ip netns exec router4 sysctl -w net.ipv4.ip_forward=1
ip netns exec router4 ip addr add 10.0.24.4/24 dev e0
ip netns exec router4 ip addr add 10.0.34.4/24 dev e1
ip netns exec router4 ip addr add 10.0.92.4/24 dev e2
# set IP address: host2
ip netns exec host2 ip addr add 10.0.92.100/24 dev eth0
# linkup & set routes (routes can not be set before linkup.)
ip netns exec host1 ip link set lo up
ip netns exec host1 ip link set eth0 up
ip netns exec host1 ip route add default via 10.0.91.1
ip netns exec router1 ip link set lo up
ip netns exec router1 ip link set e0 up
ip netns exec router1 ip link set e1 up
ip netns exec router1 ip link set e2 up
ip netns exec router2 ip link set lo up
ip netns exec router2 ip link set e0 up
ip netns exec router2 ip link set e1 up
ip netns exec router3 ip link set lo up
ip netns exec router3 ip link set e0 up
ip netns exec router3 ip link set e1 up
ip netns exec router4 ip link set lo up
ip netns exec router4 ip link set e0 up
ip netns exec router4 ip link set e1 up
ip netns exec router4 ip link set e2 up
ip netns exec host2 ip link set lo up
ip netns exec host2 ip link set eth0 up
ip netns exec host2 ip route add default via 10.0.92.4
# install frr
curl -s https://deb.frrouting.org/frr/keys.asc | sudo apt-key add -
echo deb https://deb.frrouting.org/frr $(lsb_release -s -c) frr-stable | sudo tee -a /etc/apt/sources.list.d/frr.list
sudo apt update
sudo apt install -y frr
# setup frr
for i in `seq 1 4`
do
if [ ! -d "/etc/frr/router${i}" ]; then
mkdir "/etc/frr/router${i}"
fi
# generate config file for network namespace
cat <<__EOF__ > /etc/frr/router${i}/vtysh.conf
no service integrated-vtysh-config
hostname router${i}
__EOF__
sed -e 's/^ospfd=.*/ospfd=yes/' -e 's/#watchfrr_options=""/watchfrr_options="--netns"/' < /etc/frr/daemons > /etc/frr/router${i}/daemons
chown -R frr.frr "/etc/frr/router${i}"
# start frr
/usr/lib/frr/frrinit.sh start "router${i}"
# ospf setting
ip netns exec router${i} vtysh -N router${i} -E <<__EOF__
conf t
router ospf
network 10.0.0.0/8 area 0
end
write
__EOF__
done
動作確認
動作確認も元記事と似たような感じで行う
(一部書き換えてたりする)
host1 - host2への通信
ip netns exec host1 ping -c 3 10.0.92.100
PING 10.0.92.100 (10.0.92.100) 56(84) bytes of data.
64 bytes from 10.0.92.100: icmp_seq=1 ttl=61 time=0.052 ms
64 bytes from 10.0.92.100: icmp_seq=2 ttl=61 time=0.063 ms
64 bytes from 10.0.92.100: icmp_seq=3 ttl=61 time=0.065 ms
--- 10.0.92.100 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2026ms
rtt min/avg/max/mdev = 0.052/0.060/0.065/0.005 ms
host1 - host2への通信時の経路確認
ip netns exec host1 traceroute 10.0.92.100
traceroute to 10.0.92.100 (10.0.92.100), 30 hops max, 60 byte packets
1 10.0.91.1 (10.0.91.1) 0.037 ms 0.004 ms 0.004 ms
2 10.0.12.2 (10.0.12.2) 0.015 ms 0.004 ms 0.004 ms
3 10.0.24.4 (10.0.24.4) 0.018 ms 0.006 ms 0.005 ms
4 10.0.92.100 (10.0.92.100) 0.017 ms 0.007 ms 0.007 ms
ちなみに↓と同様に通信経路が分散されているのが確認できた
リンクダウンによる経路切り替え
リンクダウンによる経路切り替えはそのまま試して無くて、単に片方のリンクをダウンさせたらその状態が反映されてもう片方のルートだけが使わるようになったのを確認しただけ。
# show ip routeすると10.0.92.0/24の経路が10.0.12.2と10.0.13.3の2つあるのが確認できる
ip netns exec router1 vtysh -N router1 -c 'show ip 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
O 10.0.12.0/24 [110/10] is directly connected, e1, weight 1, 1d04h14m
C>* 10.0.12.0/24 is directly connected, e1, 1d04h16m
O 10.0.13.0/24 [110/10] is directly connected, e2, weight 1, 1d04h14m
C>* 10.0.13.0/24 is directly connected, e2, 1d04h16m
O>* 10.0.24.0/24 [110/20] via 10.0.12.2, e1, weight 1, 1d02h37m
O>* 10.0.34.0/24 [110/20] via 10.0.13.3, e2, weight 1, 1d04h09m
O 10.0.91.0/24 [110/10] is directly connected, e0, weight 1, 1d04h14m
C>* 10.0.91.0/24 is directly connected, e0, 1d04h16m
O>* 10.0.92.0/24 [110/30] via 10.0.12.2, e1, weight 1, 1d02h37m
* via 10.0.13.3, e2, weight 1, 1d02h37m
# 片方の経路をリンクダウンすると、ダウンした経路がshow ip routeの10.0.92.0/24から消える
ip netns exec router2 ip link set e1 down
ip netns exec router1 vtysh -N router1 -c 'show ip 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
O 10.0.12.0/24 [110/10] is directly connected, e1, weight 1, 1d04h15m
C>* 10.0.12.0/24 is directly connected, e1, 1d04h16m
O 10.0.13.0/24 [110/10] is directly connected, e2, weight 1, 1d04h15m
C>* 10.0.13.0/24 is directly connected, e2, 1d04h16m
O>* 10.0.34.0/24 [110/20] via 10.0.13.3, e2, weight 1, 1d04h09m
O 10.0.91.0/24 [110/10] is directly connected, e0, weight 1, 1d04h15m
C>* 10.0.91.0/24 is directly connected, e0, 1d04h16m
O>* 10.0.92.0/24 [110/30] via 10.0.13.3, e2, weight 1, 00:00:05
# host1 - host2への通信は成功してtracerouteするとrouter3経路としてが使われているのがわかる
ip netns exec host1 ping -c 3 10.0.92.100
PING 10.0.92.100 (10.0.92.100) 56(84) bytes of data.
64 bytes from 10.0.92.100: icmp_seq=1 ttl=61 time=0.063 ms
64 bytes from 10.0.92.100: icmp_seq=2 ttl=61 time=0.075 ms
64 bytes from 10.0.92.100: icmp_seq=3 ttl=61 time=0.072 ms
--- 10.0.92.100 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2042ms
rtt min/avg/max/mdev = 0.063/0.070/0.075/0.005 ms
ip netns exec host1 traceroute 10.0.92.100
traceroute to 10.0.92.100 (10.0.92.100), 30 hops max, 60 byte packets
1 10.0.91.1 (10.0.91.1) 0.032 ms 0.004 ms 0.003 ms
2 10.0.13.3 (10.0.13.3) 0.016 ms 0.004 ms 0.004 ms
3 10.0.34.4 (10.0.34.4) 0.019 ms 0.006 ms 0.006 ms
4 10.0.92.100 (10.0.92.100) 0.022 ms 0.010 ms 0.010 ms
# ダウンしたリンクをアップしてから少し待って確認するとrouter2の経路が復活してるのがわかる
ip netns exec router2 ip link set e1 up
# ちょっと待つ
ip netns exec router1 vtysh -N router1 -c 'show ip 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
O 10.0.12.0/24 [110/10] is directly connected, e1, weight 1, 1d04h17m
C>* 10.0.12.0/24 is directly connected, e1, 1d04h19m
O 10.0.13.0/24 [110/10] is directly connected, e2, weight 1, 1d04h17m
C>* 10.0.13.0/24 is directly connected, e2, 1d04h19m
O>* 10.0.24.0/24 [110/20] via 10.0.12.2, e1, weight 1, 00:01:04
O>* 10.0.34.0/24 [110/20] via 10.0.13.3, e2, weight 1, 1d04h11m
O 10.0.91.0/24 [110/10] is directly connected, e0, weight 1, 1d04h17m
C>* 10.0.91.0/24 is directly connected, e0, 1d04h19m
O>* 10.0.92.0/24 [110/30] via 10.0.12.2, e1, weight 1, 00:00:15
* via 10.0.13.3, e2, weight 1, 00:00:15
ルーターに設定されたネイバーシップ情報の確認
ip netns exec router1 vtysh -N router1 -c 'show ip ospf neighbor'
Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
10.0.24.2 1 Full/Backup 1d07h14m 30.285s 10.0.12.2 e1:10.0.12.1 0 0 0
10.0.34.3 1 Full/Backup 1d07h13m 30.285s 10.0.13.3 e2:10.0.13.1 0 0 0
ip netns exec router2 vtysh -N router2 -c 'show ip ospf neighbor'
Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
10.0.91.1 1 Full/DR 1d07h14m 33.913s 10.0.12.1 e0:10.0.12.2 0 0 0
10.0.92.4 1 Full/DR 3h02m33s 37.030s 10.0.24.4 e1:10.0.24.2 0 0 0
ip netns exec router3 vtysh -N router3 -c 'show ip ospf neighbor'
Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
10.0.91.1 1 Full/DR 1d07h14m 34.318s 10.0.13.1 e0:10.0.13.3 0 0 0
10.0.92.4 1 Full/Backup 1d07h13m 32.143s 10.0.34.4 e1:10.0.34.3 0 0 0
ip netns exec router4 vtysh -N router4 -c 'show ip ospf neighbor'
Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
10.0.34.3 1 Full/DR 1d07h13m 32.577s 10.0.34.3 e1:10.0.34.4 0 0 0
10.0.24.2 1 Full/Backup 3h03m04s 35.694s 10.0.24.2 e0:10.0.24.4 0 0 0
ルーティングテーブルの確認
OSPFとLinuxのルーティングテーブルを見比べるとだいたい対応してるっぽい
ip netns exec router1 vtysh -N router1 -c 'show ip 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
O 10.0.12.0/24 [110/10] is directly connected, e1, weight 1, 1d07h24m
C>* 10.0.12.0/24 is directly connected, e1, 1d07h26m
O 10.0.13.0/24 [110/10] is directly connected, e2, weight 1, 1d07h24m
C>* 10.0.13.0/24 is directly connected, e2, 1d07h26m
O>* 10.0.24.0/24 [110/20] via 10.0.12.2, e1, weight 1, 03:08:15
O>* 10.0.34.0/24 [110/20] via 10.0.13.3, e2, weight 1, 1d07h18m
O 10.0.91.0/24 [110/10] is directly connected, e0, weight 1, 1d07h24m
C>* 10.0.91.0/24 is directly connected, e0, 1d07h26m
O>* 10.0.92.0/24 [110/30] via 10.0.12.2, e1, weight 1, 03:07:26
* via 10.0.13.3, e2, weight 1, 03:07:26
ip netns exec router1 ip route
10.0.12.0/24 dev e1 proto kernel scope link src 10.0.12.1
10.0.13.0/24 dev e2 proto kernel scope link src 10.0.13.1
10.0.24.0/24 via 10.0.12.2 dev e1 proto ospf metric 20
10.0.34.0/24 via 10.0.13.3 dev e2 proto ospf metric 20
10.0.91.0/24 dev e0 proto kernel scope link src 10.0.91.1
10.0.92.0/24 proto ospf metric 20
nexthop via 10.0.12.2 dev e1 weight 1
nexthop via 10.0.13.3 dev e2 weight 1
あと↓の部分を見るとrouter2とrouter3のweightはどちらも1なので基本的には50:50で経路になるよう。
weightは使用する経路の優先度で値が大きいほど優先度が高くなる設定のよう。
10.0.92.0/24 proto ospf metric 20
nexthop via 10.0.12.2 dev e1 weight 1
nexthop via 10.0.13.3 dev e2 weight 1
自分で追加で調べたこと
一部はFRRoutingやOSPF自体のページにも書いてあるけど書ききれなかったやつ
show ip ospf neighbor
のフィールドの意味
vtyshの ip netns exec router1 vtysh -N router1 -c 'show ip ospf neighbor'
Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
10.0.24.2 1 Full/Backup 1d02h48m 34.864s 10.0.12.2 e1:10.0.12.1 0 0 0
10.0.34.3 1 Full/Backup 1d02h46m 34.864s 10.0.13.3 e2:10.0.13.1 0 0 0
Field | Description |
---|---|
Neighbor ID | 隣接しているルーターのユニークなID |
Pri | 隣接ルーターが設定した優先度(Priority) |
State | 隣接ルーターの状態(Exstart、Exchange、Fullなど) |
Dead Time | 隣接ルーターが不活性と判断されるまでの残り時間 |
Address | 隣接ルーターのIPアドレス |
Interface | 隣接しているインターフェース |
CISCOの資料とかで確認できた
FRRのOSPCが設定するLinuxのルーティングテーブルは手動でも設定できるの?
結論から言うと問題無くできるっぽい。
例えばrouter1だとOSPFによって下記のような設定になっている。
ip netns exec router1 ip route
10.0.12.0/24 dev e1 proto kernel scope link src 10.0.12.1
10.0.13.0/24 dev e2 proto kernel scope link src 10.0.13.1
10.0.24.0/24 via 10.0.12.2 dev e1 proto ospf metric 20
10.0.34.0/24 via 10.0.13.3 dev e2 proto ospf metric 20
10.0.91.0/24 dev e0 proto kernel scope link src 10.0.91.1
10.0.92.0/24 proto ospf metric 20
nexthop via 10.0.12.2 dev e1 weight 1
nexthop via 10.0.13.3 dev e2 weight 1
それを手動で設定するのであれば下記のような感じでやれば設定可能のよう。
sudo ip netns exec router1 ip route add 10.0.24.0/24 via 10.0.12.2 dev e1
sudo ip netns exec router1 ip route add 10.0.34.0/24 via 10.0.13.3 dev e2
sudo ip netns exec router1 ip route add 10.0.92.0/24 nexthop via 10.0.12.2 dev e1
sudo ip netns exec router1 ip route add 10.0.92.0/24 nexthop via 10.0.13.3 dev e2
ちなみに proto ospf
の proto <value>
の部分は任意の値を設定できるらしく、下記のようにすれば任意の値を proto
に設定できるラベルのようなものとのことだった。
sudo ip route add 10.0.0.0/24 via 192.168.1.1 proto XYZ
結局各ルーターはなんで経路設定をいい感じにできたの?
各ルーターに設定した設定は全部同じで
conf t
router ospf
network 10.0.0.0/8 area 0
end
write
という設定をしただけだった。
んで network 10.0.0.0/8
という設定があると思うんだけど、これがはじめに↓でOSCPについて書いたところにも書いたけど、この設定によってそれぞれのルーターは 10.0.0.0/8
のレンジ内にHelloパケットなるものをブロードキャストしてOSCPのルーター?がいることを広告してる。
このHelloパケットを受け取ると、お互いにネイバーシップを確立し合うという処理を行うので、結果的に隣接するルーター同士がお互いにネイバーシップを確立することで、通信し合うことが可能な経路設定が自動で行われるということだと理解してる。
vtyshで show ip ospf route
コマンドを叩くと↓みたいな感じの出力になるんだけど、これを見ると隣接したルーターの情報以外も情報が入っているので、こういった情報を元に自身のルーティングテーブルをいい感じに設定してるのかな?と想像してる。
ip netns exec router1 vtysh -N router1 -c 'show ip ospf route'
============ OSPF network routing table ============
N 10.0.12.0/24 [10] area: 0.0.0.0
directly attached to e1
N 10.0.13.0/24 [10] area: 0.0.0.0
directly attached to e2
N 10.0.24.0/24 [20] area: 0.0.0.0
via 10.0.12.2, e1
N 10.0.34.0/24 [20] area: 0.0.0.0
via 10.0.13.3, e2
N 10.0.91.0/24 [10] area: 0.0.0.0
directly attached to e0
N 10.0.92.0/24 [30] area: 0.0.0.0
via 10.0.12.2, e1
via 10.0.13.3, e2
============ OSPF router routing table =============
============ OSPF external routing table ===========
FRRoutingの設定は何をしてたの?
このあたりはだいたい元記事に書いてあると思うけどとりあえずまとめておく
/etc/frr/router${i}
を作ってた理由は?
FRRoutingはNetwork Namespaceをサポートしていて、/etc/frr/<namespace>/
のディレクトリを作ることで各Network Namespaceごとに設定をすることができるから
/etc/frr/router${i}/daemons
ファイルって何?
FRRoutingの概要をまとめたところでも書いたけど、FRRoutingはプロトコルなどでプロセスが別れていてこの daemons
ファイルで起動するdaemonを設定してあげたりする必要があった。
また、watchfrr_options
に動作するNetwork Namespaceも指定してあげる必要がある。
なので、デフォルトのNetwork Namespaceの設定ファイルである /etc/frr/daemons
をsedで書き換えたものを /etc/frr/router${i}/daemons
に設置してた。
/etc/frr/router${i}/vtysh.conf
ファイルって何?
名前の通り vtysh
の設定ファイル。
各Network Namespace用に下記のような設定ファイルを作ってた。
no service integrated-vtysh-config
hostname router${i}
今回はOSPFの設定を行ったが、デフォルトではそれらの設定は frr.conf
というファイルに設定が書き込まれるが、下記でその設定を無効にしてたよう
no service integrated-vtysh-config
元記事では下記のような理由で無効化していたとのこと。
frrはospfdだけではなくbgpdやripdなど他のダイナミックルーティングプロトコルデーモンを動作させることができます。通常は各デーモンごとにospfd.conf, bgpd.conf, ripd.confと別々のファイルにコンフィグが保存されます。
service integrated-vtysh-configを設定するとfrr.confというファイルにすべて保存してくれて便利… となるはずなのですが、network namespace環境で使おうとするからなのか、うまく動作しないのでnoをつけて無効化しています。
hostname router${i}
はまんまhostnameを設定してるよう
お掃除
for i in `seq 1 4`
do
/usr/lib/frr/frrinit.sh stop "router${i}"
# delete frr namespace files
if [ -d "/etc/frr/router${i}" ]; then
rm -r "/etc/frr/router${i}"
fi
done
ip netns del host1
ip netns del router1
ip netns del router2
ip netns del router3
ip netns del router4
ip netns del host2
まとめ
- はじめにも書いた通りFRRoutingとOSPFの基礎の基礎くらいをNetwork Namespaceを使って学ぶことができた
- ついでに復数のルーターを経由する構成を初めて試したので勉強になった
- いちいちStatic Routeを設定しなくても良いので楽だなというのもちょっと実感できた
- vtyshのCISCO風?のコンソールにいまいち慣れない
- ChatGPTに質問しまくりながら検証したり調べるのはかなり有効だと思った
- 次はflannelか、tinetのCloseネットワークの例でBGPの勉強をしたいなと思った