BGPの経路属性と選択方針
AS_PATHと優先度を照合し、受信・採用・広告する経路の違いを確認します。
説明
BGPは自律システム(AS)間で到達できるプレフィックスと属性を交換します。経路の選択には運用方針が入り、AS_PATHが短い経路を常に選ぶわけではありません。
同じ/24への三つの広告をPythonの表で比較します。自ASを含む経路を除き、LOCAL_PREFとAS_PATHの条件を変えて採用結果を確認し、最後に外部への広告と経路撤回を調べます。
1三つの受信経路
自ASを65000とします。prefix、peer、path、local_pref、next_hopの順に広告を整理した表です。
local_as=自ASの番号65000; received=受信属性と内部の優先度[dict(prefix="203.0.113.0/24",peer="P1",path=[65100,65300],local_pref=100,next_hop="192.0.2.1"),dict(prefix="203.0.113.0/24",peer="P2",path=[65200,65400,65300],local_pref=200,next_hop="192.0.2.2"),dict(prefix="203.0.113.0/24",peer="P3",path=[65500,65000,65300],local_pref=300,next_hop="192.0.2.3")]; received候補一覧LOCAL_PREFはこのAS内で付けた優先度です。P2はAS_PATHが3個でP1より長い一方、LOCAL_PREFは高くなっています。P3のpathには自AS65000が含まれています。
2自ASを含む経路を除く
通常のASループ検査として、自ASがpathに含まれる候補を除きます。
eligible=自ASを含まない経路[r for r in received if local_as not in r["path"]]; [r["peer"]残った広告元 for r in eligible]P1とP2が残ります。P3は優先度が高くても自ASを含むため採用しません。AS_PATHの検査だけで経路の正当な所有者まで認証できるわけではありません。
3この演習での選択規則
NEXT_HOPはすべて到達可能、他の属性は同等として、LOCAL_PREFの高い順、AS_PATHの短い順で選びます。
def choose(rows):候補から一つ選ぶ
return min優先度とpath長を比較(rows,key=lambda r:(-r["local_pref"],len(r["path"]),r["peer"])) if rows else None同値の最後は教材内の表示を固定するためpeer名を使っています。実機の全タイブレーク規則ではありません。LOCAL_PREFはAS内の方針を表すため、より短いpathより優先される場合があります。
4選ばれた経路を確認
現在の優先度で採用する経路を求めます。
best=choose(eligible)採用する経路; (best["peer"]広告元・AS列・次ホップ,best["path"],best["next_hop"])P2の長いpathが選ばれ、転送の次ホップは192.0.2.2です。AS_PATHは経由するASの情報であり、各パケットが通る全ルーターのIP一覧ではありません。
5LOCAL_PREFをそろえる
P2のLOCAL_PREFを100にして、二経路の方針上の優先度をそろえます。
eligible[1]["local_pref"]=100P2の優先度を変更; best=choose(eligible)再選択; (best["peer"]変化した採用結果,best["path"])今度はpathが短いP1を選びます。同じ宛先でも、設定方針を変えると採用結果が変わります。単なる地理的な近さや回線速度を直接比較しているわけではありません。
6別のASへ広告する情報
採用した経路を別の外部ASへ広告するとき、自ASをAS_PATHの先頭に付ける基本形を確認します。
advertised=外部への広告を作るdict(prefix=best["prefix"],path=[local_as]+best["path"]); advertised自ASを先頭に付けたpath65000、65100、65300の順です。LOCAL_PREFは通常の外部BGP相手へそのまま配る属性ではありません。また、採用した全経路を全相手へ広告するとは限らず、出力ポリシーで制御します。
7選ばれた経路が撤回された場合
P1からの経路が撤回された後、残った候補を選び直します。
eligible=撤回された候補を除く[r for r in eligible if r["peer"]!="P1"]; best=choose(eligible)残った経路を採用; (best["peer"]代替経路の次ホップ,best["next_hop"])P2へ変わります。経路の受信、ループ検査、内部方針による採用、外部広告、転送表への反映はそれぞれ別の段階です。受信一覧に載っていることだけでは、その経路が実際の転送に使われると判断できません。
まとめ
AS_PATHの長さより先に、AS内の方針で候補の優先度が決まる場合があります。
受信した経路、採用した経路、広告する経路、転送する次ホップをそれぞれ確認します。
操作履歴と解説を振り返れます。
Python 3
local_as=65000; received=[dict(prefix="203.0.113.0/24",peer="P1",path=[65100,65300],local_pref=100,next_hop="192.0.2.1"),dict(prefix="203.0.113.0/24",peer="P2",path=[65200,65400,65300],local_pref=200,next_hop="192.0.2.2"),dict(prefix="203.0.113.0/24",peer="P3",path=[65500,65000,65300],local_pref=300,next_hop="192.0.2.3")]; received[{'prefix': '203.0.113.0/24', 'peer': 'P1', 'path': [65100, 65300], 'local_pref': 100, 'next_hop': '192.0.2.1'}, {'prefix': '203.0.113.0/24', 'peer': 'P2', 'path': [65200, 65400, 65300], 'local_pref': 200, 'next_hop': '192.0.2.2'}, {'prefix': '203.0.113.0/24', 'peer': 'P3', 'path': [65500, 65000, 65300], 'local_pref': 300, 'next_hop': '192.0.2.3'}]eligible=[r for r in received if local_as not in r["path"]]; [r["peer"] for r in eligible]['P1', 'P2']
def choose(rows):
return min(rows,key=lambda r:(-r["local_pref"],len(r["path"]),r["peer"])) if rows else Nonebest=choose(eligible); (best["peer"],best["path"],best["next_hop"])('P2', [65200, 65400, 65300], '192.0.2.2')eligible[1]["local_pref"]=100; best=choose(eligible); (best["peer"],best["path"])('P1', [65100, 65300])advertised=dict(prefix=best["prefix"],path=[local_as]+best["path"]); advertised{'prefix': '203.0.113.0/24', 'path': [65000, 65100, 65300]}eligible=[r for r in eligible if r["peer"]!="P1"]; best=choose(eligible); (best["peer"],best["next_hop"])('P2', '192.0.2.2')演習完了