前のシリーズの先の話で、リンクの状態を全員で共有する世界に踏み込んだ。けれど、その情報を配る相手は誰なのか、その相手はどうやって見つけるのか、という渇きが残ったままだ。
OSPF は起動すると自分のインターフェースから Hello を投げて隣を見つける。けれど、これは「Hello で挨拶して隣を見つけたら終わり」という 1 回きりの動作ではない。
Hello は最初の挨拶ではない。Hello は定期的に交わし続けられ、隣のルータがいまも動いていることを伝え続ける生命線だ。
Hello が届いている間だけ neighbor が生きていて、Hello が止まれば数十秒のうちに静かに失効する。


考えてみよう
OSPF は最初、どんな仕組みで隣のルータを見つけると思うだろうか。一度見つけた隣は、その後もずっと「隣」のままだろうか。それとも、関係を維持し続けるための仕組みが別にあるのだろうか。
1. 隣はどうやって見つけるのか
各ルータが自分の周りのリンクの状態を断片として全員に配り、受け取った側は断片を集めて地図に組み上げ、そこから距離を計算する。この発想の転換を受け取った直後、問いが立ち上がる。
自分の周りのリンクの状態を全員に配る相手とは、具体的に誰のことなのか。
距離ベクタの世界では、ケーブルで直接つながっている相手がそのまま隣になった。隣に自分の辞書を渡すだけで終わる。
リンクステートの世界では、それだけでは足りない。隣がいるかどうかだけでなく、その隣との間のリンクがいまも生きているかどうかという情報まで共有しなければならない。隣を一度見つけるだけでなく、見つけた隣を生かし続ける仕組みも要る。
OSPF を動かしているルータは、起動すると自分のインターフェースから Hello というパケットを投げる。リンクでつながれた R1 と R2 という 2 台のルータがいるとする。
R1 が Hello を投げる。R2 はそれを受け取り、「ここに R1 という相手がいる」と認識して、自分も Hello を投げ返す。R1 もそれを受け取り、「ここに R2 がいる」と認識する。お互いの Hello を確認し合った瞬間、R1 と R2 の間に neighbor と呼ばれる関係が成立する。
2. Hello による定期的な生存性確認
Hello で隣を見つける流れを知ると、「Hello は最初に 1 回だけ投げて、隣が見つかればそれで終わり。一度成立した neighbor 関係は、その後ずっとそのまま続いていく」と予想したくなるはずだ。
この予想は半分当たり、半分ずれている。Hello は最初の挨拶として働くだけでなく、隣が見つかったあとも 10 秒オーダーの周期で R1 と R2 の間を絶えず往復し続ける。
なぜ繰り返すのか。リンクステートの世界では、リンクが今生きているか、落ちているかという情報そのものを各ルータが配る。隣のルータが故障して止まったのに、地図には「生きている」と書かれたままでは正しい経路計算ができない。だから各ルータは、隣のルータが今も確実に動いているかを知り続けていなければならない。
Hello が R1 から R2 へ届けば、R1 は「R2 はまだ生きている」と分かる。R2 から R1 へ届けば、R2 は「R1 はまだ生きている」と分かる。Hello が定期的に交わされている間だけ、お互いに相手の生存を確かめ合っている。


3. Hello が止まれば neighbor は静かに死ぬ
R1 と R2 の間で Hello が定期的に往復している平常時、ルータ上で show ip ospf neighbor を打つと R2 の行が表示される。「ここに R2 という隣がいて、いま生きている」と読み取れる。
ある瞬間、R2 自体が止まったり、R2 から R1 への Hello だけが届かなくなったりしたとする。R1 側のインターフェースは up のままなのに、Hello だけが来ない。
このとき、R1 はすぐには「R2 が死んだ」とは判定しない。ネットワークの揺らぎで一時的に届かないことはある。1 回届かなかっただけで判定してしまえば、揺らぎのたびに neighbor 関係が失効し、安定した運用にならない。
そこで OSPF は、Hello timer の数倍、数十秒オーダーの長さを持つ Dead timer を置いている。
Hello が来なくなると、R1 の内部で Dead timer がカウントダウンを始める。カウントがゼロになる前に次の Hello が届けば、タイマーはリセットされ、neighbor は生きたまま続く。だが、Dead timer が切れるまで Hello が一度も来なかったら、そのときに初めて R1 は「この隣は死んだ」と判定する。
その瞬間、R1 から見た R2 の neighbor は失効する。show ip ospf neighbor を打っても、R2 の行は消えている。


OSPF の動作をリアルタイムで画面に出力する debug ip ospf を使うと、平常時は「Hello を受信」というメッセージが定期的に流れているが、障害が起きるとそれがぴたりと止まる。そして Dead timer が切れた瞬間に「Dead と判定」というメッセージが出力される。ルータが内部でどう判断を下しているかが、出力の流れとして見える。
ただし、debug ip ospf は本番運用では慎重に扱うコマンドだ。画面に出力処理をするためにルータの負荷が上がる。検証環境やラボで先に試して、出力の感じを掴んでおくのがよい。
neighbor には 3 つの場面がある。
- 成立する:
Helloを交わしてお互いを認識した瞬間 - 生きている:
Helloが定期的に交わされ続けている間 - 失効する:
Helloが止まり、Dead timerが切れた瞬間
4. 隣は固定された設定ではなく、生きている動的な関係
OSPF の neighbor は、設定ファイルに固定的に書かれた相手ではない。
どのインターフェースで OSPF を有効にするか、どの範囲で OSPF を動かすかといった静的な設定は行う。だが、その設定が決めているのは「ここで OSPF を喋ります」という宣言までで、具体的に誰と neighbor になるかまでは決めていない。
実際に誰と neighbor になるかは、Hello を交わした結果として動的に決まる。Hello が往復した相手が neighbor になり、Hello が止まった相手は neighbor の一覧から消える。
隣は、固定された設定ではない。Hello に支えられて生きている、動的な関係だ。
リンクの状態を全員で共有する世界では、状態は刻々と変わる。あるリンクが落ちたら、その情報はすぐに全員へ伝わらなければならない。リンクの両端のルータどうしの neighbor 関係も、リンクが落ちたら速やかに失効しなければならない。だからこそ、Hello による定期的な生存確認と、Dead timer による適切な猶予期間が組み合わされている。10 秒オーダーで投げ続け、数十秒オーダーで死亡判定するという桁感は、速やかに反応することと揺らぎで誤判定しないことの折り合いとして置かれている。
現場で「neighbor が突然 down した」というアラートを見たとき、まず疑う観点は 2 つだ。
Helloが来なくなったのか(リンクが落ちた / 相手が止まった /Helloが経路上で届かなくなった、など)Dead timerが切れたのか(Helloが一定時間届かなかった結果として失効した、など)
この 2 つの観点で読み始めれば、単なるエラー発生ではなく、タイマーが切れるまでの間に何が起きていたのかという時間軸に沿って、現場の症状を読み解ける。
隣を見つけて生かし続ける仕組みは、わかった。けれど、隣たちは、自分の周りの状態を、どうやって伝え合うのだろう。
この問いに、次の話で正面から向き合う。