Protocol in Code

プロトコルを code として読む。

この講座では、GitHub 上のプロトコルコードを「読み物」として扱い、pathvector.dev 側でその各所を解説します。 現在は BGP と OSPF を公開していて、BGP では policy-heavy な control plane を、OSPF では state machine と graph logic を code の形で読みます。

これは中級者向けの独立コースです。従来の containerlab コースは初級として別に完結させ、こちらは GitHub 上の実コードを読みながら protocol logic を説明することに集中します。

対象
実装者向け理解深化。設定や実験は触れるが、プロトコルをロジックとして説明しきれていない人。
到達点
RFC を読んで、必要な入力、状態遷移、条件分岐を code の形で説明できるようになること。
前提
ネットワーク基礎に触れていること。BGP 編では BGP 基本語彙、OSPF 編では area / LSA / SPF の基本語彙があると入りやすい。containerlab 経験は必須ではない。
非対象
完全初学者向けの導入、資格試験対策、環境構築のハンズオン網羅。

What This Course Is

初級コースと中級コースを完全に分けて置きます。

初級は `containerlab を使って動かしながら学ぶコース`、中級は `Protocol in Code として GitHub 上のロジックを読むコース` として分けます。 どちらも独立して完結する前提にして、混線しないようにします。現在の題材は BGP と OSPF で、今後も他のプロトコルを同じ型で足せるようにします。

中級: Protocol in Code

  • GitHub 上の source file のどこを見るかが分かる
  • protocol に必要な input / state / output を整理できる
  • 仕様の説明を function や if 文に近い形で読める

初級: containerlab course

  • FRRouting や topology を実際に起動して確かめる
  • pcap や route table を自分の環境で観測する
  • hands-on だけで学習を完結できる

Current Track · BGP

BGP sessions: GitHub の実コードを読みながら、1 本の control plane として理解する

最初の題材は BGP です。ここでは「neighbor を張るには何が必要か」と「best path selection はどういう条件分岐か」を中心に、 RFC 4271 の説明を input / state / decision の形にほどいていきます。Session 01-05 で部品を分け、Session 06-10 で control plane の中心をつなぎ、 Session 11-15 で peer gate、event dispatch、speaker loop まで閉じます。コード本体は GitHub の `protocol-in-code` repo に置き、ここではその各所を順番に読みます。

Session 01

What A BGP Neighbor Needs

`session.py` を読み、neighbor を張るために何が必要かを設定項目ではなく関数の入力として読む。AS 番号、peer address、session state、message exchange を整理する。

RFC: RFC 4271 Sections 1.1, 3, 4.2
GitHub: src/protocol_in_code/bgp/session.py
到達点: BGP session を張るのに必要な input を列挙できる
Session shape: source reading + walkthrough script + done check
Session 01 input modeling BGP first
Session 02

How UPDATE Changes State

`update.py` を読み、UPDATE を「route を入れる関数」と「route を消す関数」の両方として読む。announcement、withdrawal、re-advertise を state transition として見る。

RFC: RFC 4271 Sections 3.1, 4.3, 5
GitHub: src/protocol_in_code/bgp/update.py
到達点: Withdrawn Routes と NLRI を state change として説明できる
Session shape: source reading + walkthrough script + done check
Session 02 state transition BGP first
Session 03

Best Path Selection As If Statements

`best_path.py` を読み、best path selection を魔法の優先順位ではなく条件分岐の列として読む。同じ prefix に複数 path が来たとき、どの条件で 1 本に決まるかを考える。

RFC: RFC 4271 Sections 3, 5, 9; RFC 7908
GitHub: src/protocol_in_code/bgp/best_path.py
到達点: competing paths から best path が決まる理由を順番に説明できる
Session shape: source reading + walkthrough script + done check
Session 03 decision logic BGP first
Session 04

Origin Validation Is A Separate Decision

`validation.py` を読み、best path selection のあとに走る origin authorization を別ロジックとして読む。VRP、coverage、max length、valid / invalid / not_found を分けて考える。

RFC: RFC 6482 Section 3; RFC 6811 Sections 2, 2.1; RFC 8210 Sections 1-2
GitHub: src/protocol_in_code/bgp/validation.py
到達点: best path と origin authorization を混ぜずに説明できる
Session shape: source reading + walkthrough script + done check
Session 04 authorization logic BGP first
Session 05

Validation State Does Not Act By Itself

`policy.py` を読み、validation result が local policy によって action へ変換される流れを読む。invalid route が自動で消えるわけではないことを分けて考える。

RFC: RFC 6811 Sections 2.1, 3
GitHub: src/protocol_in_code/bgp/policy.py
到達点: validation result と routing action を混ぜずに説明できる
Session shape: source reading + walkthrough script + done check
Session 05 policy logic BGP first
Session 06

Where Routes Live

ribs.py を読み、Adj-RIB-In、Loc-RIB、Adj-RIB-Out を別の store として読む。Session 02 の received state と Session 03 の best-path input をどこでつないでいるかを見る。

RFC: RFC 4271 Sections 1.1, 3, 9.1
GitHub: src/protocol_in_code/bgp/ribs.py
到達点: route が router の中でどこに住むかを分けて説明できる
Session shape: source reading + walkthrough script + done check
Session 06 RIB structure BGP core
Session 07

Import Policy Rewrites Inputs

import_policy.py を読み、best-path selection の前に local policy が candidate をどう書き換え、どう early drop するかを見る。comparison に入る前の入力を明確にする。

RFC: RFC 4271 Section 9.1; operational local policy
GitHub: src/protocol_in_code/bgp/import_policy.py
到達点: best-path が見るのは import 後の candidate だと説明できる
Session shape: source reading + walkthrough script + done check
Session 07 import policy BGP core
Session 08

Export Policy Decides What Leaves

export_policy.py を読み、local に install された route が、そのまま全 peer に出るわけではないことを見る。deny、next-hop-self、AS_PATH prepend を outbound logic として読む。

RFC: RFC 4271 Sections 3, 9.1; operational export behavior
GitHub: src/protocol_in_code/bgp/export_policy.py
到達点: installed route と exported route を分けて説明できる
Session shape: source reading + walkthrough script + done check
Session 08 export policy BGP core
Session 09

Session Loss And Recompute

recompute.py を読み、peer down によって per-peer state が消えたあと、affected prefix ごとに best-path recompute が走る流れを見る。backup path が best に上がる条件を追う。

RFC: RFC 4271 Sections 3, 9.1
GitHub: src/protocol_in_code/bgp/recompute.py
到達点: peer loss と Loc-RIB recompute の関係を説明できる
Session shape: source reading + walkthrough script + done check
Session 09 recompute BGP core
Session 10

One Route Through The Whole Pipeline

pipeline.py を読み、received state から validation、import policy、policy action、Loc-RIB install、export までを 1 本の function chain として追う。ここで小さい BGP 実装の骨格が見えるようにする。

RFC: RFC 4271 + RPKI sessions as integrated reading
GitHub: src/protocol_in_code/bgp/pipeline.py
到達点: toy BGP control plane を end-to-end で説明できる
Session shape: source reading + walkthrough script + done check
Session 10 integration BGP core
Session 11

Peer State Gates UPDATE

peer_state.py を読み、peer が Established になって初めて UPDATE が Adj-RIB-In に入ることを gate として読む。Session 01 の state machine を route flow の前提条件に戻す。

RFC: RFC 4271 Sections 3, 8
GitHub: src/protocol_in_code/bgp/peer_state.py
到達点: peer state と route acceptance を分けて説明できる
Session shape: source reading + walkthrough script + done check
Session 11 peer gate BGP advanced core
Session 12

Export Refresh After Recompute

export_refresh.py を読み、Loc-RIB の変化が peer ごとの advertise / withdraw にどう変換されるかを読む。Adj-RIB-Out を reconciliation の結果として見る。

RFC: RFC 4271 Sections 3, 9.1; operational export behavior
GitHub: src/protocol_in_code/bgp/export_refresh.py
到達点: export refresh を best-path 後の別 pass として説明できる
Session shape: source reading + walkthrough script + done check
Session 12 Adj-RIB-Out BGP advanced core
Session 13

Event Dispatch

events.py を読み、announce、withdraw、peer down がそれぞれどの control-plane branch を通るかを event dispatch として読む。

RFC: RFC 4271 Sections 3, 9.1
GitHub: src/protocol_in_code/bgp/events.py
到達点: event type ごとに route 処理の順序が違うと説明できる
Session shape: source reading + walkthrough script + done check
Session 13 event flow BGP advanced core
Session 14

One Prefix Becomes A Decision Set

decision_process.py を読み、1 prefix に集まる複数 path を validation と policy を通した decision set として読み、best-path がそのあとに走ることを確認する。

RFC: RFC 4271 + RFC 6811 as integrated decision flow
GitHub: src/protocol_in_code/bgp/decision_process.py
到達点: policy-aware candidate set の上で best-path が走ると説明できる
Session shape: source reading + walkthrough script + done check
Session 14 candidate set BGP advanced core
Session 15

Build The Toy Speaker Loop

speaker.py を読み、peer state、RIBs、decision set、event handlers、export refresh を 1 つの speaker object にまとめる。ここで BGP core 15 sessions が閉じる。

RFC: RFC 4271 + RPKI sessions as speaker-shaped reading
GitHub: src/protocol_in_code/bgp/speaker.py
到達点: readable toy speaker loop を end-to-end で説明できる
Session shape: source reading + walkthrough script + done check
Session 15 speaker loop BGP advanced core

Flow Review

Session 01-15 で、BGP の部品を speaker loop として閉じます。

流れは `neighbor formation` → `UPDATE mutations` → `best path decision` → `origin authorization` → `policy action` → `RIB placement` → `import rewrite` → `export decision` → `peer loss recompute` → `whole pipeline` → `peer gate` → `export refresh` → `event dispatch` → `prefix decision set` → `speaker loop` です。 ここで大事なのは、best path、authorization、local action、RIB placement、import/export を一つに潰さず、 最後の Session 15 で初めて 1 つの speaker object と event flow として再接続することです。

Current Track · OSPF

OSPF sessions: Hello, LSDB, SPF, area summary を code として読む

OSPF 編では、Hello の gate、adjacency state machine、DR / BDR election、Router-LSA object、flooding、LSDB、SPF、route derivation、 cost-based winner selection、topology recompute、area summary、speaker loop を 12 sessions で閉じます。コード本体は GitHub の `protocol-in-code` repo に置き、ここではその source file を順番に読みます。なおこの最初の OSPF arc は router-only graph を使う teaching model で、Network-LSA と transit network vertex は意図的に省いています。

Session 01

Hello Starts The Neighbor

Hello packet が neighbor relationship の最初の gate になることを読む。

Open Session 01
Session 02

Neighbor State Machine

accepted Hello が `Init`, `2-Way`, `Full` にどう変わるかを読む。

Open Session 02
Session 03

DR And BDR Election

priority と router ID が DR / BDR election にどう入るかを読む。

Open Session 03
Session 04

LSA As An Object

Router-LSA を flood と SPF の共通入力 object として読む。

Open Session 04
Session 05

Flooding Decides Where The LSA Goes

newer LSA がどの interface へ進むかを読む。

Open Session 05
Session 06

LSDB Keeps The Version

Router-LSA が area ごとの store でどう置き換わるかを読む。

Open Session 06
Session 07

SPF Turns The LSDB Into A Tree

LSDB が graph を経由して shortest-path tree になるところを読む。

Open Session 07
Session 08

The Tree Becomes Routes

SPF tree が reachable route に変わるところを読む。

Open Session 08
Session 09

Cost Picks The Winner

同じ prefix の route candidates から winner を選ぶところを読む。

Open Session 09
Session 10

Topology Change Recomputes The RIB

changed Router-LSA が route table recompute をどう起こすかを読む。

Open Session 10
Session 11

Area Boundaries Rewrite The View

summary route が area boundary で見え方を書き換えることを読む。

Open Session 11
Session 12

Build The Toy OSPF Speaker Loop

Hello, LSDB, SPF, area summary を 1 つの speaker loop へ戻す。

Open Session 12

Flow Review

Session 01-12 で、OSPF を state machine と graph の speaker loop として閉じます。

流れは `Hello gate` → `adjacency state` → `DR/BDR election` → `Router-LSA object` → `flooding` → `LSDB replace` → `SPF tree` → `route derivation` → `cost winner` → `topology recompute` → `area summary` → `speaker loop` です。 BGP 編が policy-heavy な control plane をほどくのに対して、OSPF 編は packet gate と graph logic を段階的に接続します。Session 03 と 05 は broadcast segment / flood scope の branch lesson で、Session 12 ではそれも speaker の state と receive path に戻します。

Future Tracks

次は IS-IS、DNS、TCP、TLS、HTTP、QUIC も同じ読み方で追加できます。

BGP と OSPF は最初の題材です。今後は IS-IS の level / TLV / SPF、DNS の resolution flow、TCP の state machine、TLS の handshake、HTTP/QUIC の stream 処理も、 同じく function / state / if 文として読めるように足していけます。

Beginner Track

初級は従来の containerlab コースで完結します。

こちらは初級者向けの独立レーンです。環境を立てて、route を見て、pcap を見て、hands-on の流れだけで理解を積み上げる前提にします。

Lab 01

One Prefix Announcement You Can Explain

2 router 構成で 1 本の route を観測する、初級コースの入口。

Open beginner lab
Lab 02

Route Appearance, Withdrawal, and Return

withdrawal と re-advertise を手元で見る、初級コースの 2 本目。

Open beginner lab
Lab 03

Competing Origins and the First Route-Leak Question

competing origins を topology 上で再現する、初級コースの 3 本目。

Open beginner lab