Protocol in Code · BGP Session 04

Origin Validation Is A Separate Decision

Session 03 で見た best path selection は、「どの path を使うか」を決めるロジックでした。ここでは GitHub 上の validation.py を開いて、「その origin AS が許可されているか」を別の関数として読みます。

IntermediateSession 04authorization logicRFC 6482, 6811, 8210

Session Goal

このセッションで終わらせたいこと

Session 04 のゴールは、best path と origin authorization を混ぜずに説明できるようになることです。ここでは route と VRP を照合し、結果が validinvalidnot_found に分かれる理由を source から読めるようにします。

  • best path selection と origin validation が別ロジックだと説明できる
  • VRP が route を cover する条件を言える
  • valid / invalid / not_found の違いを説明できる
  • origin validation は AS_PATH 全体の検証ではないと説明できる

Core Idea

validate_origin() は authorization の tri-state decision を返す

validation.py では、BGP route と VRP を照合して、結果を validinvalidnot_found の 3 状態で返します。大事なのは、これは Session 03 の best path selection とは別の decision だということです。

「best だから正しい」とは限りません。best path の後で、別の authorization check が走るという読み方に切り替えます。

Design Choice

ここでは概念を先に分けて学びます

この session では、まず bestauthorized を切り分けるために、validation を separate decision として教えています。後ろの integration lesson では、toy pipeline の中で validation が import/policy に先に影響する形も扱います。実装ごとに置き場所は揺れますが、まずは概念分離を優先しています。

Read Order

この順番で読むと迷いにくい

  1. BGPRoute を読んで、BGP 側が持つ情報を掴む
  2. VRP を読んで、authorization 側が持つ情報を掴む
  3. vrp_covers_route() を読んで、prefix coverage と max length を見る
  4. validate_origin() を読んで tri-state decision を追う
  5. walkthrough script を実行して、各 scenario がなぜ valid / invalid / not_found になったか確認する

Read The Source

coverage を先に見て、そのあと origin AS を比べる

src/protocol_in_code/bgp/validation.py
covering_vrps = [vrp for vrp in vrps if vrp_covers_route(route, vrp)]

if not covering_vrps:
    return ValidationState.NOT_FOUND

if any(vrp.origin_as == route.origin_as for vrp in covering_vrps):
    return ValidationState.VALID

return ValidationState.INVALID

読む順番が大事です。まず「covering VRP があるか」を見て、それがなければ not_found。covering VRP があるなら、「origin AS が一致するか」を見て validinvalid に進みます。

Coverage

vrp_covers_route() は prefix と max length を見る

src/protocol_in_code/bgp/validation.py
def vrp_covers_route(route: BGPRoute, vrp: VRP) -> bool:
    route_net = ip_network(route.prefix)
    vrp_net = ip_network(vrp.prefix)
    return route_net.subnet_of(vrp_net) and route_net.prefixlen <= vrp.max_length

ここで見ているのは「その route が VRP の許可範囲に入っているか」です。prefix coverage があっても max length を超えれば cover されません。

States

3 状態を混ぜずに説明する

state意味
validcovering VRP があり、その origin AS が route の origin AS と一致する。
invalidcovering VRP はあるが、origin AS が一致しない。
not_foundcovering VRP が存在しない。まだ判断材料がない。

Walkthrough

valid / invalid / not_found と max length を流す

GitHub repo 側には Session 04 用の walkthrough script を置いてあります。exact match、origin mismatch、no covering VRP、max length の内側、max length 超過を順に見て、authorization result がどう変わるかを確認します。

run locally
cd protocol-in-code
PYTHONPATH=src python3 examples/bgp/session_04_walkthrough.py
実行結果を見るときは、「この route は best か」ではなく、「この route に対して covering VRP があるか」を先に考えると読みやすくなります。

Done Check

Session 04 を終えたと言える条件

  • not_found は「悪い route」ではなく「covering VRP がない状態」だと説明できる
  • invalid は coverage があるのに origin AS が合わない状態だと説明できる
  • max length が route の許可範囲を狭めると説明できる
  • origin validation は origin AS を見るのであって、AS_PATH 全体の検証ではないと説明できる

Next

次は validation result を policy action に渡す

Session 04 では authorization result が validinvalidnot_found に分かれるところまで読みました。次は GitHub 上の policy.py を開いて、その結果を local policy がどう action に変えるかを見ます。