要約

  • OSPFv2は同一LSAの版を、0x80000001から0x7fffffffまでの符号付き32ビット整数で直線的に並べる。最大値から初期値へ直接戻ると、残存する古い最大値の方が新しいと判定される。
  • そのため生成元は、最大値のLSAをMaxAgeとして再フラッディングし、隣接ルーターの確認と安全な削除を待つ。その後にだけ初期値を発行でき、撤回が二つの世代を隔てる。

最初の時間軸は「ロリポップ」だった

1989年10月の RFC 1131 は、OSPF第1版のLSAシーケンス空間を、棒の先に輪が付いた図で示した。起動時は直線部分を進み、やがて循環部分に入る。「ロリポップ型」は、新しく起動したルーターが以前の状態を追い越す必要と、長時間動くルーターが更新を続ける必要を一つの形に収めようとしていた。

1991年7月の RFC 1247 は、OSPFv2でこの輪を捨てた。付録はロリポップ型を第1版から修正した問題として挙げる。新しい順序は符号付き32ビット整数の一本の線である。0x80000000は予約され、最初の有効値0x80000001が最古、0x7fffffffが最新となった。

通常時の比較は単純になった。同じLSAなら数が大きい方を採用すればよい。ただし直線には終点がある。最大値の内容をさらに変えたいとき、何をもって次を「新しい」と呼べるのかが、設計上の独立した問題になった。

ただ一周すると、過去が現在に勝つ

LSAの同一性はLS type、Link State ID、Advertising Routerで決まる。シーケンスはLSDB全体の時計ではなく、その一つの同一性に属する版だけを比べる。

生成元が最大値の次に初期値を送ったとしよう。隣接ルーターが0x7fffffffを一枚でも保持していれば、仕様どおり初期値を古いと判断する。新しい内容は、正しく働くフラッディングによって拒まれる。数値上のwrapは、分散した記憶にとって世代交代ではない。

時間が解決してくれるとも限らない。LS ageは伝送と保存の間に増えるが、全ルーターが共有する時計ではない。古いLSAは再送リストに残ることも、データベース同期の途中で再提示されることもある。何も届かないことは、どこにも残っていないことの証明にはならない。

OSPFv2は循環比較を工夫する代わりに、古い世代を明示的に閉じる手順を置いた。

最大値が自分自身の撤回票になった

RFC 2328 では、MaxSequenceNumberを超える更新が必要になると、生成元は現在の最大値LSAのLS ageをMaxAgeに設定し、もう一度フラッディングする。自然な満了を待たずに年齢を最大にするので、premature agingと呼ばれる。

誰でも使える削除命令ではない。ルーターが早期老化できるのは自分で生成したLSAだけで、他のAdvertising Routerの記録を勝手に消せない。同一性、最大シーケンス、内容のチェックサムはそのままに、ageだけが変わる。Ageは転送中にも変化するため、LSAチェックサムの対象外である。

このMaxAgeは、単に古びたデータではない。シーケンスとチェックサムが同じ二つのインスタンスなら、MaxAgeの方が新しいと扱われる。撤回票は、生きたまま残る双子を上書きできる。

ただし撤回の意味を広げてはならない。消えるのは、そのOSPF LSAインスタンスである。物理リンクの断線、ルーター停止、宛先への全経路消失まで証明するものではない。

消去には隣接ごとの終わりが必要だった

MaxAgeを受け取っても、すぐローカルDBから捨てるわけではない。どれかの隣接ルーターのLink State Retransmission Listに残っていれば保持する。ExchangeまたはLoading中の隣接がいる場合も、同期途中から旧世代が戻り得るため削除しない。

最大シーケンスから再出発する際は、生成元がすべての隣接ルーターから撤回の確認を待つ。最大値のLSAが安全に除去された後で初めて、同じ同一性をInitialSequenceNumberで再生成する。

これにより、最大から最小への見かけ上の逆行が説明可能になる。両方を同じ世代で比べるのではない。旧世代は撤回され、隣接を渡り、同期の対象から外れた。最小値は、その空白の後に始まる別世代の最初の番号である。

RFC 1247はDatabase Description処理も変更した。隣接が古い要約を学んでいる最中にLSAが消え、世代が交差するのを防ぐためだ。全域同時の削除ではないが、各隣接で終わりを確認できる構造になった。

再起動すると、自分の過去を隣から返される

32ビットを自然に使い切る場面は遠い。しかしルーターの再起動は、同じ原理を日常的な距離まで近づける。生成元の揮発状態が失われても、隣接ルーターには再起動前の自己生成LSAが高い番号で残る。隣から見れば、保存した方が正当に新しい。

RFC 2328は、戻ってきた記憶を無視させない。再起動後もそのLSAを生成すべきなら、受信したシーケンスより一つ大きい版を出す。もう生成すべきでなければ、受信した同一性をMaxAgeにして撤回する。受信版がすでに最大なら、先にflushしてから初期値へ進む。

この挙動はしばしばLSA fight-backと呼ばれるが、敵対行為が前提ではない。隣接が、再起動した本人より本人の過去を長く覚えていただけかもしれない。Advertising Routerは著者として更新・撤回できる。一方で、次に使う番号は分散した証拠に拘束される。

新しさには三段階の判定があった

まずシーケンスを比較する。同値ならチェックサムを比べ、大きい符号なし値を新しいとする。両方が同じ場合は、MaxAgeかどうか、さらに規定以上のage差が判断材料になる。Age差が小さければ同じインスタンスである。

各字段の役割は違う。シーケンスは意図的な再生成を表す。チェックサムは同じ番号に異なる内容が載る異常を見分ける。Ageは撤回を生きた双子より優先させつつ、普通の伝搬遅延を無限の版として数えない。

したがって、LSAシーケンスは時刻でもLSDB全体の世代番号でもない。異なるLSAの大小を比べても意味はない。

DoNotAgeは更新費を減らし、撤回権を残した

通常のOSPFv2は、自己生成LSAを30分ごとにrefreshし、1時間のMaxAgeへ自然到達するのを避ける。安定したネットワークでも番号と帯域を使う。需要時だけ接続する回線向けの RFC 1793 はDoNotAgeを導入し、RFC 4136 は安定トポロジーでのrefresh削減を広げた。

DoNotAgeが省くのは、変化のない定期更新である。内容が変われば再生成してフラッディングし、不要になればMaxAgeで撤回する。生成権、版の順序、世代を閉じる責任は残る。

RFC 5340 のOSPFv3も、IPv6に合わせて形式やスコープを変えながら、基本的なフラッディングと新旧判定を維持した。問題の原因はアドレス形式ではなく、複製された記憶である。

同じ名前のシーケンスを混ぜてはいけない

Database Descriptionパケットは、隣接同期のため別のシーケンスを使う。暗号認証されたOSPFパケットにもreplayを抑える番号がある。RFC 6863 は、パケット認証の問題をLSA内部の番号とは別に扱う。

LSAシーケンスは「このルーティング主張のどの版を残すか」を決める。認証シーケンスは「この鍵の文脈で古い保護パケットが再送されたか」を検討する。所有者も寿命もrolloverも異なる。名称だけで同じ監視項目に束ねれば、どちらの状態機械が壊れたか見えなくなる。

消えたこと自体がプロトコルだった

OSPFは番号を増やさず、自然な忘却にも賭けなかった。最大値のLSA自身を撤回として運び、確認・再送・同期状態で旧世代の退場を確かめ、それから最小値に再び「最新」という意味を与えた。

この設計が示す歴史的な要点は、分散システムでの忘却は無言ではないということだ。誰が消すのか、どこまで届いたのか、いつ終わったのかが必要になる。二つの番号列の間の空白は、何もない時間ではなく、合意を壊さずに時間を区切る作業だった。

情報源と証拠の限界

これらの標準が示すのは手順とその変遷であり、現在の実装が最大値へ達する頻度、ベンダー既定値、特定障害の原因ではない。MaxAgeはOSPF内のLSA撤回であり、物理障害や世界的な到達不能の証明ではない。再起動後の自己生成LSAへの反応だけで、悪意ある注入とも断定できない。