ネットワークエンジニアのユニットテスト
ネットワーク自身が唯一のオラクルであるとき、トポロジーエンジンをどうテストするか
Michel Wijnberg
トポロジーエンジンのテストには厄介な性質があります。それがやることの大半について、 期待される答えを書き下すことができないのです。
自分ででっち上げたグラフに対して Dijkstra の実装をユニットテストすることはできます。それ で証明できるのは、あなたの Dijkstra が Dijkstra であることだけです。実際の LSDB から構築 したグラフが、ルーターが本当に使っているグラフなのかについては何も言っていません。そして それこそが唯一重要なことであり、面白い形で間違いうる唯一のものです。
そこで問いはこうなります。オラクルは何か。
ルーターがリファレンス実装です
私が落ち着いた答えは、これを 2 つに分けます。RFC 2328 は仕様です。プロトコルが何をするべ きかを述べています。ラボのルーターは振る舞いのオラクルです。実装が実際に問われたときに何 をするかを述べます。Osprey は両方を満たさなければならず、両者が食い違うところでは、その食 い違い自体が発見です。ありがたいのは、そのオラクルがすぐそこにいて、いつでも尋ねられるこ とです。
これで検証はパイプラインになります。
64 台の実機ルーター
↓ show ip route ospf / show ip ospf database summary
正解データ:各ルーター自身がインストールしているテーブル
↓
Osprey の再構成、同じ瞬間、同じスコープ
↓
4,032 の順序付きペアすべてを 4 つの独立したアサーションで比較
これはその比較の再構成側です。あるルーター自身のテーブルを、Osprey が保持している姿です。
428 経路が種別ごとに分かれています(C 直結、O エリア内、O IA エリア間、E2 外部)。
それぞれにメトリック、広告元ルーター、そしてこの後の話にとって重要なネクストホップの完全
な集合が付いています。ですから 172.16.2.31, 172.16.2.32 は、ソート順で先に来たほうでは
なく、実際そうであるとおりの 2 経路 ECMP として現れます。
件数よりも 4 つのアサーションのほうが重要です。
| アサーション | なぜ別立てなのか |
|---|---|
| メトリックが厳密一致 | たまたま長さが合っているだけの誤った経路を捕まえる |
経路種別が厳密一致(intra / inter / external) | 誤ったルールでたどり着いた正しいコストを捕まえる |
| ECMP ネクストホップの完全な集合が同一 | 有効なメンバーを 1 つ選んで答えと称する行為を捕まえる |
終了状態 = 要求した宛先で delivered | 途中で止まってもっともらしく見える探索を捕まえる |
このうちどの 3 つが通っても、モデルが間違っていることはありえます。これは仮定の話ではありま せん。前回の記事のバグが生んだ経路は、端点は正しく、 実際より安いコストでした。もっと怠惰な比較なら、まさにそれを素通りさせたはずです。
現在、4 つすべてが 4,032 ペア中 4,032 で通ります。私が気にしている数字は 4,032 ではありませ ん。4 です。失敗できる独立した経路を、私がいくつ用意したかという数です。
オラクルがないなら、ファジングする
正解データはネットワークに尋ねられるときには機能します。問題のもう半分には機能しません。機器 が不正な形式の、切り詰められた、あるいは単に奇妙なものを送ってきたときにどうなるか、です。
Osprey にはプロトコルパーサーに関する絶対のルールがひとつあり、それはコード品質の努力目標では なく製品上の制約です。**異常はログに残して続行する。決してクラッシュしない。**不正な LSA で死 ぬ監視システムは、まさに何か面白いことが起きているその瞬間に、あなたの可視性を奪います。
ベンダーがどう驚かせてくるかを列挙することはできません。だからファジングします。
make fuzz # every target, 10s each
make fuzz FUZZTIME=60s # longer
make fuzz FUZZPKG=./internal/isis/ # one package
このリポジトリでの現在の数は次のとおりです。
| ファズターゲット | 110 |
| テストファイル | 419 |
| ベンチマーク | 98 |
110 のファズターゲットは見栄えのための指標ではありません。攻撃者やバグのあるエージェントがバイ トを支配するパース境界ごとに、おおむね 1 つという数です。OSPFv2 と OSPFv3 のパケットとすべての LSA タイプ、IS-IS の PDU と TLV、BGP のメッセージとパス属性、BMP のヘッダー、SNMP の varbind デ コード。そのどれもが、「この機器は私に何を送ってくるのか」という問いへの正直な答えが「まったく 分かりません」である場所です。
ベンチマークが存在するのは、それと関連した理由からです。プロトコルパーサーはホットパス上にあり、
バッファに sync.Pool を使ってパケットあたりゼロアロケーションで書かれています。そして
b.ReportAllocs() 付きのベンチマークだけが、次に誰かが便利な fmt.Sprintf を足したときにそれが
黙って退行するのを止めてくれます。
本物のデータベースを必要とするテスト
第 3 のカテゴリは、そのどちらの手法も受け付けません。Osprey の難しいクエリは、集約と複数結合を伴 う CTE です。「アクティブなのに一度もポーリングされていない機器はどれか」「分断されているエリアは どれか」「時刻 T 時点のグラフを再構成せよ」。それをテストするためにデータベースをモックしても、証 明できるのはモックが自分の期待と一致することだけです。
そこでそれらは testcontainers を通じて本物の PostgreSQL に対して走ります。プロジェクトのルールは明 示的です。CTE / 集約 / 複数結合のクエリには本物の DB テストが必須であり、空集合、NULL、境界条 件、そしていちばん多くのバグを捕まえるもの、すなわち相互排他性を網羅します。あるクエリが機器を カテゴリに振り分けるなら、カテゴリの合計は総数と一致しなければなりません。それが一致しないことがど れほど多いか、そして、どの数字も単体ではもっともらしく見えるダッシュボード上でそれがどれほど見えな いかは、驚くほどです。
ベンダーは RFC を読み聞かせてはくれません
最後のカテゴリは、どれだけ内部でテストしても見つからないものであり、ラボがその働きぶりで元を取る場 所です。実機は、あなたが読んだ標準を実装していません。それに隣接する何かを実装しています。
このラボからいくつか。どれも実際に時間を食いました。
**存在しない MIB。**ラボの EVPN サービスポッドにある vEOS のリーフは、IS-IS ではなく OSPF で発見せ ざるをえませんでした。まったく華のない理由で、vEOS は ISIS-MIB のツリーをどちらも実装していないので す。部分的に、ではありません。まったくです。正しい SNMP コードをいくら書いても直りません。唯一正し い対応は、機器が実際にサポートしているプロトコルで発見し、その理由を文書に残すことです。
標準以前の方言。MPLS L2VPN の疑似ワイヤーには標準 MIB があり、RFC 5601 です。実機の IOS はその代 わりに標準以前の Cisco 方言を積んでいます。そこでポーラーは両方を実装し、自動でフォールバックします。 そして「両方に対応しています」はまさに腐りやすい種類の主張なので、2 つのドライバーはパリティゲート に縛られ、標準 MIB のパスが Cisco のパスから黙って乖離できないようにしてあります。
**時代に忘れられた暗号。**ここのルーターは 2 つの IOL イメージで動いています(124 台が IOS 15.2(4)S7、
残り 68 台が 15.4(2)T4)。そしてそのすべてが、SHA-1 の鍵交換と ssh-rsa のホスト鍵しか提供しません。
15.2 の一群はさらに、暗号方式が CBC 止まりです。素の現代的な OpenSSH クライアントは鍵交換の時点で拒否
するので、接続は認証を試みる前に死にます。Osprey の SSH クライアントはレガシーのフォールバックを明示的
に抱えています。そうしない場合の代替が、「ベンダーのスライドでは動くが、顧客の実際の設備では動かない」
ターミナル機能だからです。
**一度も起動されていなかったサーバー。**このラボの以前の 64 ルーター構成では、どこにも
ip ssh version 2 が設定されていながら RSA 鍵が一度も生成されておらず、SSH サーバーは単に動いていませ
んでした。全ノードで、しかも見えない形で。show ip ssh は Disabled と表示し、設定は完成しているよう
に見えていました。
どれも仕様を読んで見つかるものではありません。自分のコードを実機に向け、それが失敗するのを見ることで見 つかるものです。
トポロジーエンジンとは本当は何なのか
検証ハーネスを作っている途中のどこかで、この対象の形が私にははっきり見えてきました。
入力: 雑然として、部分的で、矛盾したネットワーク状態
出力: 決定論的なモデル
オラクル:ルーターそのもの
それはほとんどコンパイラです。そう考えることの有用な帰結は、コンパイラがもっともらしさではなく 適合性で判断されるということです。「生成されたコードはだいたい正しそうに見えます」を受け入れる人は いません。
推測を拒む製品についてシリーズを書けるのは、私がとりわけ高潔だからではありません。求めればいつでも私に 反論してくれる機械が 64 台あり、それらすべてに一度に尋ねるハーネスがあるからです。
それがなければ、「Osprey はパスを正しく計算する」は意見です。それがあれば、4 つのアサーションについて 4,032 分の 4,032 であり、火曜日の午後に再現できます。
違いはそれがすべてです。
これがシリーズ 2 の最終回です。シリーズ 1 の 3 つの IGP、1 枚の地図、 ゼロフットプリント、 ホップバイホップの真実、 Osprey が推測を拒むこと は、今回テストにかけた原則そのものを扱って います。