← 記事一覧

トポロジーに嘘をつかれた日

自社製品に対するエンジニアリングのポストモーテムと、それを捕まえたラボ

Michel Wijnberg

ネットワークについて本当のことを教えてもらうために、私は Osprey を作りました。そしてそれ が私に嘘をついていたと知りました。自信たっぷりに、文字で、人にデモして回っていたキャンバ スの上で。

何が起きたのか、どうやって気づいたのか、何を変えたのかを書きます。このシリーズでいちばん 役に立つ回です。誠実さについて私が書いてきたことはすべて、監査対象が自分自身の仕事になる までは安っぽいからです。


私が信じていたこと

Osprey のパスエンジンは、ほとんどのパスツールがやっていることをやっていました。送信元と宛 先を与えると、OSPF トポロジー上で送信元からエリアを意識した Dijkstra を走らせ、いちばん安 い経路を描く。

信用するだけの理由はありました。私が気にしていた RFC 2328 のルールは尊重していました。エリ ア内をエリア間より優先し、エリア間はバックボーンを経由し、E1 を E2 より先に、ECMP はまとめ ずに列挙する。テストもありました。ラボについての私のメンタルモデルとも合っていました。ルー ターを 2 つクリックすれば、それらしいパスが光りました。

同時にそれは、エリア間クエリ 8 回に 1 回、どのパケットも決して通らない経路を描いていました。


どうやって気づいたか

バグ報告からではありません。雑用からです。

まったく別のもののために検証ハーネスを作っていて、それを突き合わせる正解データセットが欲し かったのです。ラボには AS 200 に 64 台のルーターがあり、すべて SSH で届き、すべて自分のルー ティングテーブルを喜んで印字してくれます。そこで愚直で明白なことをしました。64 台すべてにロ グインし、全台から show ip route ospf をダンプしたのです。

そのうえで、目視で眺める代わりに、各ルーターの実際のテーブルを、Osprey のパスエンジンがパス だと主張する内容と、4,032 の順序付き送信元/宛先ペアすべてについて比較しました。

そのうち 360 が食い違いました。

「コストが少しずれている」ではありません。描かれたパスに、パケットが証明可能に一度も訪れない ルーターが含まれていたのです。


代表的なケース

ひとつ挙げます。各行はモデル化ではなく実機で計測したものです。

ルーター宛先についての言い分転送先
dfw1-gw2metric 20031, type inter areadfw1-cr1
dfw1-cr1metric 30001, type intra areaord1-cr1dfw2-cr1 ではない
ord1-cr1metric 20001, type intra areajfk1-cr1
jfk1-cr1metric 10001, type intra arealhr1-cr1
lhr1-cr1metric 1, connected到達

Osprey はこう描きました。

dfw1-gw2 → dfw1-cr1 → dfw2-cr1 → iad2-cr1 → ams1-cr1 → lhr1-cr1

パケットは dfw2-cr1 に決して届きません。Osprey のパスはより安いものでした。ただ、どの ルーターも組み立てない経路だったというだけです。

RFC 2328 の独立した 2 つのルールが dfw1-cr1 にその安い回廊を拒ませます。そして私は、個々の 中間ルーターのレベルでは、そのどちらも実装していませんでした。

§16 ステップ (3) / §16.2 第 1 段落:バックボーンのゲート。複数のエリアに接続するルーター は、バックボーンの summary-LSA だけを検査します。dfw2-cr1 のコスト 20011 という安いほ うの summary は、確かに dfw1-cr1 のエリア 4.6.23.0 のデータベースに存在します(自分でも信じ られなかったので show ip ospf database summary で確認しました)。しかしそれは候補ではあり ませんdfw1-cr1 が ABR であり、その summary がエリア 0 経由で届いたものではないからです。 RFC 3509 §2.1/§2.2、つまりこれらの実機で実際に動いている Cisco の ABR 挙動は、これをアクティ ブなバックボーン接続があることに条件づけており、dfw1-cr1 はそれを持っています。

§16.2 ステップ (6):エリア内がエリア間に勝つ、以上。 “If the paths present in the table are intra-area paths, do nothing with the LSA.” dfw1-cr1 はすでにメトリック 30001 のエリア 内経路を持っています。20011 の summary はそれに負けます。メトリックは比較にすら入りません。 これは経路の種別についてのルールです。

どちらか一方のルールだけでもこの回廊は死にます。私のエンジンはそのどちらも見られませんでした。 dfw1-cr1 に何ひとつ尋ねなかったからです。送信元ルーターの世界観を尋ね、そのうえで他の 8 台のルーターを貫く線を、まるでそれを共有しているかのように引いたのです。


間違いの形

具体的な OSPF の詳細より、それが属するカテゴリのほうが面白いので、正確に名前を付けておく価値 があります。

私はひとつのパスをモデル化していました。ネットワークが実装しているのは独立した判断の 連なりです。この 2 つは、道中のすべてのルーターが同じ入力集合に対して同じ判断ルールを使う かぎり、ぴったり一致します。単一の OSPF エリア内ではそれが成り立ちます(同じ LSDB、同じアル ゴリズム、同じ結果)。だからこそエリア内ペアの欠陥数はこうなりました。

1,193 中 0。

ABR が絡んだ瞬間、入力集合は共有されなくなります。ABR は周囲のルーターとは異なる LSA の 集合を、意図的に見るからです。私のモデルにはその事実を置く場所がありませんでした。私のモデル にはグラフ 1 枚と Dijkstra 1 回があるだけで、それぞれに意見を持つ 64 台のルーターはなかったの です。

ペア数どのルーターも通らないホップを含むもの
エリア内1,1930
エリア間2,839360(12.68%)
全体4,032360(8.93%)

直し方と、それが効いたと分かる理由

エンジンは今、チェーンをたどります。各ホップで、そのルーター自身の LSDB、エリア所属、ABR 状 態、アドミニストレーティブディスタンスの組み合わせを使って、そのルーター自身が宛先アドレスに 向けてインストールしている経路を評価し、そのルーターが実際に選んだネクストホップをたどり、こ れを繰り返します。

そして同じ 4,032 ペアを、同じ正解に対してもう一度走らせました。

チェック結果
ルーター自身のメトリックを正確に再現4,032 / 4,032
経路種別(エリア内 / エリア間 / 外部)が完全一致4,032 / 4,032
インストール済み ECMP ネクストホップの集合全体が同一4,032 / 4,032
要求した宛先でチェーンが delivered で終了4,032 / 4,032

「改善した」ではありません。すべてのペアで同一であり、任意に選んだ 1 メンバーではなく等コスト ネクストホップの完全な集合を含めて同一です。

修正後のパス:各ルーター自身のエリア、ポート、コストを載せた 10 ホップの表
修正後のパス:各ルーター自身のエリア、ポート、コストを載せた 10 ホップの表

これは、かつてホップをでっち上げていたのと同じクエリです。いまは実際に判断を下すすべてのルータ ー、判断が行われたエリア、そして両側の物理ポートを表示しています。合計の 30061 は送信元自身が インストールしているメトリックであり、文字どおり lax1-gw1show ip route が印字する数字で す。

そしてチェーンが計算できない場合(OSPFv3、IS-IS、EIGRP、部分的なスコープ、仮想リンクを持つ エリア)、エンジンは黙って古い絵に戻ったりしません。理由を名指しする model_note を添えて送信 元を根とするビューを返し、それ自体を説明ステップとして描画します。その拒否は 第 4 回の主題であり、このバグがあったからこそ存在します。


バランスのために、もっと小さいものを

自傷がすべてアルゴリズムとは限りません。私に午後を 1 つ失わせた、2 行のものをご紹介します。

Osprey の GRE レコーダーは本物の OSPF 隣接を張るので、Router-LSA を生成しなければなりません。 初期のころ、それはトンネルの内側サブネットをスタブネットワークとして広告していました。正しそう に見え、RFC 上も適法で、まったく理にかなっています。

するとエリア内のすべてのルーターがトンネルのプレフィックス宛の経路をインストールしました。その 経路は、GRE トンネル自身が乗っていたアンダーレイ経路を上書きしました。外側のトランスポートが壊 れました。隣接が落ちました。レコーダーは再接続し、LSA を再生成し、また同じことをしました。

修正は今ではコードコメントに書いてあります。誰かがうっかり消さないようにです。

// Only the P2P link is advertised. NO stub network for the tunnel
// inner subnet. Advertising the tunnel subnet (even at max cost) causes SPF
// on other routers to install a route for the tunnel prefix, which can
// disrupt the GRE outer path and kill the adjacency.

監視しているものを自分で落としてしまう監視ツールというのは、特別な種類のばつの悪さであり、そし て図面の上では見つけられなかったはずのものです。


ラボの本当の役割

私はかつてラボを「Osprey をデモする場所」と説明していました。それは職務記述として間違っていて、 そこを正したことで作り方が変わりました。

ラボは Osprey をよく見せるためにあるのではありません。Osprey が間違っていることを証明するため にあります。

つまりラボは、私に反論できる度合いにおいてのみ価値があります。だから意図的に扱いにくく作ってあ ります。プロトコルを何ひとつ共有しない 3 つのキャリア。3 つのほうがデモ映えするのに 15 ある OSPF エリア。level-1 エリアが 17 ある IS-IS ドメイン。リンクステートデータベースをそもそも持たず、 OSPF のコードが置いている前提をことごとく壊す EIGRP。そして 124 本すべてで v4 と v6 のコストが 10 倍違うデュアルスタックリンク。

どれもスクリーンショットを美しくはしません。どれも何かを捕まえてきました。

360 本の架空の回廊は、注意深く読んで見つけたのでも、事前に書けるほど私が賢かったテストで見つけた のでもありません。実際に何を考えているか尋ねられる本物のルーターが 64 台あり、抜き取りで確認した 2、3 台を信じる代わりに、ようやく全台に一度に尋ねたから見つかったのです。

そこから当然の問いが出てきます。それが次回の主題です。モデルが正しいかどうかを教えてくれるのがネ ットワークだけだとしたら、それをどうやってテストスイートに変えるのか。


次回:ネットワークエンジニアのユニットテスト

Osprey は自社運用型のネットワーク可視化・エンジニアリング基盤です。32 台まで無料でお試しいただけます。他の記事を読むこともできます。