Protocol in Code · BGP Session 10

One Route Through The Whole Pipeline

Session 10 では GitHub 上の pipeline.py を読み、1 本の route 追加をきっかけに、received state から validation、import policy、best-path、local action、Loc-RIB install、export までどう再計算されるかを end-to-end で追います。

IntermediateSession 10integrationtoy control plane

Session Goal

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

Session 10 のゴールは、ここまで分けてきた部品が 1 本の route に対してどう連結されるかを説明できるようになることです。これで BGP の toy control plane が、部品集ではなく function chain として見えるようになります。

  • 1 本の route が通る関数列を説明できる
  • validation と policy action を混ぜずに end-to-end で話せる
  • Adj-RIB-In、Loc-RIB、Adj-RIB-Out の変化点を説明できる
  • どこで drop される可能性があるか説明できる

Bridge

Session 01-09 を 1 本に束ねる

Session 01-09 では、neighbor、UPDATE、best path、validation、policy、RIB、import/export、recompute を分けて読みました。Session 10 はそれらを再接続して、「これらをくっつけると小さい BGP 実装の骨格になる」という感覚を作るための integration lesson です。

ここでの狙いは、新しい概念を足すことよりも、既に見た部品がどの順で呼ばれるかを見えるようにすることです。

Design Choice

これは single-message で prefix 全体を recompute する toy pipeline です

この integration は、`受けた 1 本をそのまま install` するものではありません。1 本の route 追加をきっかけに、その prefix に残っている複数 candidate を集め直し、validation と import/policy を通したうえで best-path を選びます。real router の full event loop ではありませんが、ここでは object flow を end-to-end で見えるようにしています。

Read Order

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

  1. PipelinePoliciesPipelineResult を読む
  2. evaluate_candidate() を読む
  3. apply_policy_action() を読む
  4. process_single_route() を最初から最後まで追う
  5. received route の評価結果と、prefix 全体の selected outcome を分けて読む

Read The Source

1 本の route 追加が prefix 全体の best-path を組み直す

src/protocol_in_code/bgp/pipeline.py
store_received_path(adj_rib_in, peer_id, prefix, attributes)
for _, received_attributes in received_attributes_for_prefix(adj_rib_in, prefix):
    validation_state, action, installable = evaluate_candidate(prefix, received_attributes, vrps, policies)
if not installable_candidates:
    remove_best_path(loc_rib, prefix)
    withdraw_staged_advertisement(adj_rib_out, export_peer_id, prefix)
best = select_best_path(installable_candidates)
install_best_path(loc_rib, best)
exported = prepare_export(best, export_peer_type, policies.export_policy)

ここでは、受け取った 1 本だけを見るのではなく、その prefix に残っている candidate を集め直して best-path を決めています。これで Session 03 の comparison と Session 06 の received state が、end-to-end の integration に戻ってきます。

State Changes

1 本の route 追加で prefix 全体がどう変わるか

step変化
receiveAdj-RIB-In に received attributes が保存される。
validate各 candidate に valid / invalid / not_found が付く。
importcandidate ごとに rewrite または drop が走る。
policyaccept / deprioritize / reject が candidate ごとに決まる。
best-path残った candidate から 1 本を比較して選ぶ。
installLoc-RIB に best path が置かれる。
exportAdj-RIB-Out 用の route に変換される。

Walkthrough

2 本の candidate から winner が決まるところまで通す

walkthrough では先に 1 本の candidate を入れてから、2 本目の valid route を追加し、validation、import rewrite、best-path comparison、Loc-RIB install、eBGP export を順に確認します。出力は、received route の評価結果と prefix 全体の selected outcome を分けて表示します。

run locally
cd protocol-in-code
PYTHONPATH=src python3 examples/bgp/session_10_walkthrough.py

Done Check

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

  • 1 本の route 追加が prefix 全体の recompute を呼ぶと説明できる
  • validation result と action を end-to-end でも混ぜずに話せる
  • import rewrite と export rewrite を区別できる
  • 最後の installed path が surviving candidate の comparison から決まると説明できる
  • surviving candidate が 0 本なら stale state も withdraw されると説明できる

Next Session

ここから先は event loop 側を足すフェーズです

Session 10 で toy pipeline の中心は見えました。次はこの pipeline の前後に、peer state が UPDATE を gate すること、peer down のあとに export refresh が走ること、event loop が announce/withdraw/peer_down を dispatch することを足します。