要約

  • 0.0.0.0/0と::/0は宛先prefix bitを一つも固定しないが、longest-prefix matchで他の経路が選ばれない全addressに一致する。実効scopeはtable全体の変化で伸縮する。
  • 生成、export、受信、import、RIB選択、FIB実装、packet deliveryは別の状態である。Established sessionと選択済み/0だけでは、neighborの先にある転送能力を証明できない。
  • 最後の委任は、明示的な関係、serviceに近いpredicate、受信側の拒否権、default-only canary、withdrawalとrollbackの実測を揃えた場合にだけ承認すべきである。

AS 64580は小規模なcustomer networkである。AS 64520から地域内の数prefixとIPv4 defaultを受け、full tableは持たない。09時41分、AS 64520の主要transitへ向かうtransportが失われた。しかしcustomer-facing linkは生き、EBGP sessionはEstablishedのまま、別経路上の地域prefixも残った。

defaultは無条件に生成されていた。AS 64520は0.0.0.0/0を送り続け、AS 64580は同じnext hopをbestとしてhardwareへ載せ続けた。provider loopback、地域DNS、more-specificで覆われた二つのserviceへのprobeは成功する。その他のdestinationはdefaultに従ってAS 64520へ入り、失われたegressの手前で止まる。

これはsynthetic incidentだが、protocol上の矛盾はない。BGP sessionは二つのspeaker間のcontrol channelであり、全destinationとのsessionではない。UPDATEは経路がadvertiseされた証拠であって、その経路が要約するdata planeの証明ではない。

/0の権限は他の経路が決める

RFC 1812のforwarding ruleは、宛先に一致するrouteのうち最長prefixを先に残す。203.0.113.0/24が存在すれば、そのblockでは/24が/0に勝つ。/24が消えれば、同じaddressは直ちにdefaultの対象へ戻る。

zero-length prefixは全addressに一致するが、常に使用されるわけではない。defaultが担当するのはresidual set、つまり現在のlocal tableがより具体的に解決できない集合である。この集合は/0自身のattributeではない。

したがってdefault UPDATEが一度も変化しなくても、その実効scopeは拡大できる。more-specificのwithdrawalは、いままで別pathを使っていたtrafficをdefaultへ移す。逆にspecificの追加はscopeを縮める。defaultのuptimeだけを見るmonitorは、この権限移動を見ない。

IPv6の::/0にも同じ分析が必要だが、IPv4の許可から自動で導いてはならない。AFI/SAFI、next hop、policy、probe、failureは別々である。

RFC 4098はdefault routeとdefault-free table、full default-free tableを区別する。defaultだけを受ける構成はstateを減らし、残余宛先の判断をproviderへ集中する。full tableは判断材料をcustomer側へ移すが、memory、CPU、policy運用を増やす。どちらも選択肢であり、同じ証拠を持つ構成ではない。

明示的設定は同意の最小単位

RFC 4632は0.0.0.0/0を実装が受け入れるべきdegenerate prefixとする一方、inter-domain advertisementは明示的に設定された場合だけ送るべきで、未設定のdefault optionとして出してはならないとする。

RFC 7454は関係scopeを加える。特定のcustomer/provider構成以外ではIPv4とIPv6のdefaultを通常accept、advertiseせず、filterすることを推奨する。同時に、customerがfull tableではなくdefaultだけをproviderへ求める正当な設計も認める。

つまり/0は無効なrouteではなく、限定された双方向契約である。一つのcustomerへの許可はpeer、upstream、route server、別tenantへの許可にならない。あるVRFでの利用も別VRFへ継承してよい理由にはならない。

送信側は正確なneighbor listでexportを制限し、受信側はauthorized roleからexact /0だけをimportする。二重controlは無駄ではない。自律networkの一方が誤っても、もう一方がlocal decisionでblast radiusを止める。

RFC 8212はpolicy不在をEBGPの暗黙許可にしない。しかしpolicy objectが存在するだけでは内容を保証しない。誤ったpeer-groupや広すぎるprefix conditionを明示的に書くことはできる。構文上のexplicitnessと運用上の正当性は別である。

「defaultがある」を七つに分解する

第一にadvertiserがcandidateを作る。synthetic per-neighbor routeかもしれず、static、generated、またはBGP routeかもしれない。第二にoutbound policyがneighborへの送出を許可する。第三にreceiverがUPDATEを受ける。第四にimport policyがacceptする。第五にBGP decisionが他のdefaultと比較する。第六に選択結果がFIBへprogramされる。第七にpacketがneighborの先へ届く。

candidateがあってもfilterされる。受信してもrejectされる。acceptしても低いLOCAL_PREFで負ける。RIBが変わってもhardwareが遅れる。FIBが正しくnext hopを指していても、neighborの先でblackholeになる。

AS_PATHは/0 advertisementが通ったAS列を表し、residual set内の全destination pathを列挙しない。NEXT_HOP recursionはlocal routerが次の一歩を解決できることを示し、それより先のdeliveryを示さない。LOCAL_PREFはlocal intentionであってhealth scoreではない。

RFC 4271のUPDATEにより、sessionを維持したまま/0だけwithdrawできる。最後の約束が壊れたときにneighbor全体をclearする必要はない。全面resetを標準手順にすると、関係ないrouteを失い、原因を示すstateまで消す。

同じdefault-originateでもstate machineは同じではない

現在のCisco IOS文書ではneighbor ... default-originateはper-neighbor actionで、local routerに0.0.0.0がなくてもよい。Nexus文書は、artificial defaultがrouting tableに存在せず、local BGP RIBにも作られなくてよいと説明する。route-mapを付ける場合は、install済みrouteとのmatchを条件にできる。

FRRoutingはrouting tableに0.0.0.0/0があってもdefaultではadvertiseしない。operatorがneighbor単位で明示し、必要ならroute-mapを付ける。

Junosはactive routeとrouting policyを組み合わせる。static、aggregate、generatedなど明示設定routeはexport policyで許可されてBGPへ出る。条件付き例では、supporting routeのactive stateとexport評価が一つのchainになる。

この差は障害時に現れる。local static /0を削除しても、無条件synthetic advertisementは残り得る。一方、generated routeのactive stateに依存する設計では、その消失がwithdrawalを起こす。command名が似ていることをportable contractと考えてはいけない。

deploy済みreleaseでlocal RIB、BGP RIB、advertised-routes、receiver viewを観察する。customer sessionを残したままsupporting conditionを失わせ、再評価、withdrawal、alternate selection、FIB update、packet recoveryを別々にtimestampする。復旧時も逆方向を確認する。

predicateはserviceの代用品にすぎない

conditional advertisementは無条件より良く見える。しかしconditionが証明するのは自分自身であり、/0の全意味ではない。

provider loopbackのreachabilityは一つのloopbackを証明する。interface upはlocal carrierを証明する。static routeのactive stateは設定またはrecursionを証明するだけかもしれない。table countは数であり、egress forwardingではない。BFDは特定peerとのcontinuityである。

先にservice promiseを定義する必要がある。public transitを意味するなら、customer trafficと同じegressを通り、互いに独立した複数networkをprobeする。private WAN exitだけを意味するなら、その閉じたscopeを測る。広い商品名を狭いmetricで代用しない。

複数signalにもtrade-offがある。全ての成功を要求すると一つのprobe target故障で有用なlast pathをwithdrawする。どれか一つでよいとすると、小さな到達島が残るだけで大規模blackholeを維持する。quorum、hysteresis、hold-down、return thresholdはearly withdrawalとlate withdrawalのcost allocationである。

各signalとcombined decisionのhistoryを残す。predicateがいつfalseになり、UPDATEがいつwithdrawされ、receiverがいつbest pathを変え、FIBがいつ変わり、packetがいつ回復したかを再構成できなければならない。

more-specificは成功も失敗も隠す

冒頭のprobeが成功したのは、対象addressがsurviving more-specificを使ったからである。壊れたdefaultを一度も通っていない。監視先がlocal serviceやpopular prefixへ偏ると、狭い到達島をInternet全体のhealthと誤読する。

逆にhealthy defaultもbroken /24には勝てない。stale specific、誤ったnext hop、route leakが一つのserviceをblackholeにしても、その他trafficは/0で成功する。default healthでspecific alertを閉じてはならない。

canaryはresponseだけでなく、winning prefix、RIB entry、FIB next hop、egressを保存する。specificの出現やwithdrawalで、どのpolicyを検証するprobeかを再分類する。default hashが不変でもtest scopeは変わる。

二つのdefaultも独立性を証明しない。異なるrouterとsessionがmetro fibre、upper transit、controller、health targetを共有できる。一方のsessionをshutdownするtestはsession redundancyを検証するだけで、upstream喪失なのにcustomer sessionが残るscenarioを検証しない。

leakは残余trafficの無断移転である

誤ったrelationshipからdefaultをacceptすると、local tableが具体的に知らない全destinationをそのneighborへ渡す。full tableを持つcoreではresidual setが小さいかもしれない。stub customerではほぼ全external trafficになり得る。

export filterは対象customerだけを列挙し、peer、provider、route server、無関係tenantを除外する。import filterは正しいAFI/SAFIとrouting instanceでexact zero-length prefixだけを許す。peer-group inheritanceとdual-stackの共通設定は一回の変更を多数neighborへ広げるため、結果を確認する。

configurationはintended recipientを示す。Adj-RIB-Outは実際にspeakerが送ったrouteを示す。receiverのpre-policyとaccepted viewは到着と採用を分ける。public collectorは遠方へのescapeを発見できるが、全linkを観察しない。collector不在を漏洩不在と同一視しない。

evidence ledgerをpacketまでつなぐ

各default relationshipについて、最初にservice意味を書く。general Internet transitか、限定external serviceか、private WAN exitか、temporary fallbackか。advertiser、receiver、role、family、VRF、approval owner、withdrawal ownerを結ぶ。

generation model、predicate input、quorum、timer、hysteresis、failure actionを保存する。runtimeではcandidate、post-policy advertisement、receiver pre-policy、accepted route、selection reason、recursive next hop、hardware FIB、competing defaultsをtimestamp付きで残す。

probeは信頼がforwarding actionになるreceiver側から出す。一部のdestinationはdefaultだけに依存させ、別の一部は意図的にspecificで覆う。network依存を分散し、実際のegressを結果に付ける。

failure drillはcustomer sessionを維持し、promiseを支えるupstreamを失わせる。predicate failure、withdrawal、alternate RIB、FIB、packet recoveryを別々に測る。alternateがなければ、死んだproviderへ送り続けずunreachableになることを確認する。

rollbackはcommand一行ではない。generation、condition、timer、neighbor scope、attribute、receiver import preference、probe、alarmを以前のcontractへ戻し、FIBとpacketまで検証して終了する。

薄いcoordinationには強いlocal exitが要る

default routeはminimum shared informationで自治networkを接続する。providerは全destination detailを共有せず、customerはlocal policyでfallback利用を選ぶ。中央の判定者は不要であり、両側が自分のdecisionを変更できる。

しかし薄いstatementは広い権威を証明できない。providerというlabelはdata plane certificateではない。昨日のacceptは明日の服従ではない。UPDATE presenceはSLAではない。

Running-Code Primacyは証拠を順序づける。contractは期待、configurationは意図、UPDATEは送信、RIB/FIBはlocal action、packetはrunning resultを示す。それぞれ必要だが、次のlayerを代行しない。