BGP 選路原則詳解:13 條選路順序與機房出入方向流量排程
BGP 選路原則可以概括為一句話:同一個字首學到多條路徑時,按固定順序逐項比較屬性,在第一個分出高下的屬性上決出最優路徑,後面的不再比較。順序依次是 Weight(華為為協議首選值)、Local_Pref、本地起源、AS_Path 長度、Origin、MED、eBGP 優於 iBGP、到下一跳的 IGP 開銷,最後用 Router ID 和鄰居位址打破平局。
BGP 選路原則解決的是“同一個目的網段有好幾條路,該走哪一條”。路由器從多個鄰居收到同一個字首時,先排除不可用的路徑,再按固定順序逐項比較路徑屬性:哪一項先分出高下就按哪一項選,後面的屬性不再看。思科的完整順序有 13 步,也就是常說的“BGP 選路原則 13 條”;華為的順序大體相同,用協議首選值(PrefVal)代替 Weight,個別步驟先後不同。讀懂選路結果只需記住一個結構:前三步是本地策略,由你說了算;中間三步(AS_Path、Origin、MED)是鄰居告訴你的路徑資訊;再往後是拓撲上的遠近;最後幾步只是在實在分不出高下時給出一個確定的結果。整個過程不看頻寬、延遲和丟包。
進入選路之前:兩個前提
第一,最長匹配先於 BGP 選路。 BGP 選路只在“同一個字首”的多條路徑之間進行。203.0.113.0/24 和 203.0.113.0/25 是兩個不同的字首,各自選出各自的最優路徑;去往 203.0.113.10 的資料包按最長匹配走 /25 那條,與兩條路由的 BGP 屬性誰高誰低無關。後文用“宣告更長的字首”來排程入方向流量,依據就是這一條。
第二,路徑必須可用。 下一跳要可達:iBGP 鄰居轉來的外部路由,下一跳預設還是運營商一側的互聯位址,本機路由表裡沒有這個位址,路徑就不參與比較。此外,被入方向策略拒絕的、AS_Path 裡出現了自己 AS 號的(防環)、因頻繁抖動被懲罰抑制的路徑,也都不參與比較。
BGP 選路順序:13 條原則對照表
下表按思科的順序排列,華為的對應關係和差異見下一節。
| 順序 | 比較項 | 優選 | 預設值與要點 | 作用範圍 |
|---|---|---|---|---|
| 1 | Weight(華為:協議首選值 PrefVal) | 大者 | 思科從鄰居學到的路由預設 0,本機起源的路由 32768;華為預設 0 | 只在本台裝置,不傳給任何鄰居 |
| 2 | Local_Pref | 大者 | 預設 100 | 透過 iBGP 在本 AS 內傳遞,不傳給 eBGP 鄰居 |
| 3 | 本地起源 | 本機產生的路由 | network、重分發引入或聚合生成的路由,優於從鄰居學到的 | 本台裝置 |
| 4 | AS_Path 長度 | 短者 | AS_SET 不論包含多少個 AS 都按 1 計;聯盟內部的 AS 不計 | 隨路由跨 AS 傳遞 |
| 5 | Origin | IGP(i)優於 EGP(e)優於 Incomplete(?) | network 宣告的為 i,重分發引入的為 ? | 隨路由跨 AS 傳遞 |
| 6 | MED | 小者 | 預設只在來自同一個相鄰 AS 的路徑之間比較;沒帶 MED 的按 0 處理 | 只傳給相鄰 AS,不再往外傳 |
| 7 | 鄰居型別 | eBGP 優於 iBGP | 聯盟內的 eBGP 按 iBGP 一側對待 | — |
| 8 | 到 BGP 下一跳的 IGP 開銷 | 小者 | 即“從離自己最近的出口出去” | — |
| 9 | 等價多路徑 | — | 配置了 maximum-paths 時,前面各步都相同的路徑一起裝入路由表;不改變誰是最優路徑 | — |
| 10 | 路徑新舊(思科) | 兩條都是 eBGP 路徑時,選先收到的 | 避免因 Router ID 比較造成路由來回切換;配置 bgp bestpath compare-routerid 後跳過 |
— |
| 11 | Router ID | 小者 | 經過路由反射的路徑用 ORIGINATOR_ID 代替 | — |
| 12 | Cluster_List 長度 | 短者 | 只在路由反射環境中出現 | — |
| 13 | 鄰居位址 | 小者 | 與同一台裝置建立了多條會話時用到 | — |
幾個容易出錯的地方:
- Weight 與 Local_Pref 的分工。Weight 只在本台裝置上生效,適合臨時改變某一台路由器的選擇;Local_Pref 會透過 iBGP 帶給本 AS 內所有路由器,適合統一整個機房的出口策略。
- MED 的比較範圍。預設只比較來自同一個相鄰 AS 的路徑,A、B 兩家運營商發來的 MED 不會互相比較。要跨 AS 比較,思科用
bgp always-compare-med,華為用compare-different-as-med。沒帶 MED 的路徑預設按 0 處理,反而最優;想把它當作最差,思科用bgp bestpath med missing-as-worst,華為用bestroute med-none-as-maximum。 - AS_Path 按個數算。重複出現的同一個 AS 號逐個計數,這正是 AS_Path 預置能把一條路徑“拉長”的原因。
- IGP 開銷那一步決定了多出口 AS 裡的“就近出口”:同一條路由從兩台邊界路由器都能出去時,內部的每台裝置選離自己近的那台。
華為與思科的選路差異
| 專案 | 華為 VRP | 思科 IOS |
|---|---|---|
| 第一步的本地私有值 | 協議首選值 PrefVal,預設 0,用 peer 位址 preferred-value 值 設定 |
Weight,學到的路由預設 0,本機起源 32768,用 neighbor 位址 weight 值 設定 |
| 本地起源的細分 | 手動聚合優於自動聚合,優於 network,優於 import-route | network、redistribute 引入的優於 aggregate-address 生成的 |
| 兩條 eBGP 路徑前面各步全部相同 | 預設規則裡沒有“比新舊”這一步,繼續比較後面的項 | 先選先收到的那條 |
| Cluster_List 與 Router ID 的先後 | 先比 Cluster_List 長度,再比 Router ID | 先比 Router ID,再比 Cluster_List 長度 |
| 忽略 AS_Path 長度 | bestroute as-path-ignore |
bgp bestpath as-path ignore |
| 等價負載分擔 | maximum load-balancing 條數 |
maximum-paths 條數,iBGP 用 maximum-paths ibgp 條數 |
| 選出的路由進入路由表的優先順序 | BGP 預設優先順序 255,eBGP、iBGP 相同 | eBGP 管理距離 20,iBGP 200 |
| 檢視某個字首的選路結果 | display bgp routing-table 字首 掩碼長度 |
show ip bgp 字首 |
部分裝置版本支援 AIGP 屬性(RFC 7311),會在“本地起源”之後、AS_Path 之前比較它,只在路徑攜帶該屬性時起作用。華為一列的規則依據其公開文件整理,不同產品線和版本可能有差異,以所用裝置版本的手冊為準。
“進入路由表的優先順序”這一行常被忽略:BGP 選出的最優路由,還要和其他協議學到的同一字首比優先順序,數值小的才能裝進路由表。同一條預設路由既從 eBGP 學到、又從內網 OSPF 學到時,華為上 OSPF 外部路由的 150 小於 BGP 的 255,生效的是 OSPF 路由;思科上 eBGP 的 20 小於 OSPF 的 110,生效的是 BGP 路由。兩家裝置混用時,同樣的設計可能得到相反的結果;用浮動靜態路由做兜底時,也要按各自的數值來定靜態路由的優先順序。
用一個字首走一遍選路
機房自有 AS 64500,有兩台邊界路由器:R1 接運營商 A(AS 64496)和運營商 B(AS 64497),R2 接運營商 C(AS 64498),R1 與 R2 之間建 iBGP,並對 iBGP 鄰居把下一跳改為本機位址。目的網段 192.0.2.0/24 屬於 AS 64510,它和三家運營商都有互聯。R1 上這個字首有三條路徑:
| 路徑 | 從誰學到 | AS_Path | Origin | MED | Local_Pref | 鄰居型別 |
|---|---|---|---|---|---|---|
| ① | 運營商 A,198.51.100.2 | 64496 64510 | i | 無 | 100 | eBGP |
| ② | 運營商 B,198.51.100.6 | 64497 64510 | i | 無 | 100 | eBGP |
| ③ | R2,10.255.0.2(來自運營商 C) | 64498 64510 | i | 無 | 100 | iBGP |
逐項比較:Weight 都是 0,Local_Pref 都是 100,都不是本地起源,AS_Path 都是 2 個,Origin 都是 i;三條路徑來自三個不同的相鄰 AS,MED 不比較;到第 7 步,eBGP 優於 iBGP,③ 落選;① 和 ② 的下一跳都是直連位址,IGP 開銷相同。最後:思科選先收到的那條,誰的會話先建立、誰的更新先到就選誰;華為接著比較兩家運營商路由器的 Router ID,小的勝出。
也就是說,不加任何策略時,去往這個網段的流量走 A 還是走 B,取決於會話建立的先後或對方裝置的編號,帶有很大的偶然性,換成另一家廠商的裝置,結果還可能不同。這就是需要用 Local_Pref 明確出口的原因。
在 R1 上對運營商 A 學到的這條路由把 Local_Pref 設為 150,第 2 步就直接選出 ①。R1 再透過 iBGP 把這條路由連同 Local_Pref 150 告訴 R2;R2 上有自己從運營商 C 學到的 eBGP 路徑(Local_Pref 100)和來自 R1 的 iBGP 路徑(150),同樣在第 2 步就選了 R1 這條,儘管第 7 步的“eBGP 優於 iBGP”本來對 C 有利。順序在前的屬性壓過順序在後的,這是理解所有 BGP 策略的關鍵。
出方向:用 Local_Pref 決定從哪家運營商出去
多運營商的 BGP 機房,出方向通常按下面的思路設定 Local_Pref:
- 本網路由走本網:從運營商 A 收到的、由 A 自己的 AS 起源的字首(AS_Path 只有 64496),Local_Pref 設為 200;B、C 同理。去往各家使用者的流量都從對應的運營商出去,不會因為對方的路徑變化而繞到別家。
- 其餘字首指定主出口:第三方網路、境外網路等,按成本和品質在幾家之間分配,例如 A 的其餘路由設 120、B 的設 110。
- 預設路由做兜底:幾家都下發預設路由時,主用的那家 Local_Pref 高一些,備用的低一些。
華為上對運營商 A 的配置:
ip as-path-filter 10 permit ^64496$
#
route-policy FROM-ISP-A permit node 10
if-match as-path-filter 10
apply local-preference 200
route-policy FROM-ISP-A permit node 20
apply local-preference 120
#
bgp 64500
ipv4-family unicast
peer 198.51.100.2 route-policy FROM-ISP-A import
思科上的等價配置:
ip as-path access-list 10 permit ^64496$
!
route-map FROM-ISP-A permit 10
match as-path 10
set local-preference 200
route-map FROM-ISP-A permit 20
set local-preference 120
!
router bgp 64500
neighbor 198.51.100.2 route-map FROM-ISP-A in
正則 ^64496$ 只匹配 AS_Path 恰好是 64496 的路由,即由運營商 A 自己起源的字首。策略配好後執行軟復位讓已有路由重新過一遍策略:華為 refresh bgp 198.51.100.2 import,思科 clear ip bgp 198.51.100.2 soft in。然後檢視結果:
display bgp routing-table 192.0.2.0 24 # 華為:看各路徑的 Local_Pref 與哪條被選為最優
show ip bgp 192.0.2.0 # 思科:Paths 一行會顯示共幾條、最優是第幾條
Local_Pref 一改,整類流量會同時換出口。調整前先估算被移動的流量有多大,確認目標線路在晚高峰還有餘量;按字首分批調整,每批之後觀察一段時間再繼續。
入方向:AS_Path 預置、MED 與更長字首
入方向的流量走哪條線路進來,是別人的路由器按別人的選路結果決定的。你不能直接改別人的 Local_Pref,只能在自己宣告出去的路由上做文章:AS_Path 和 MED 影響別人在第 4 步及之後的比較,更長的字首靠最長匹配生效,團體屬性則是請運營商按約定替你調整:
| 方法 | 原理 | 影響範圍 | 注意 |
|---|---|---|---|
| AS_Path 預置 | 向 B 宣告時額外重複加上本 AS 號,經 B 進來的路徑變長 | 在 AS_Path 這一步做比較的第三方網路 | 運營商通常給自家客戶的路由設定較高的 Local_Pref,B 自己的使用者仍會從 B 進來;一般預置 1 到 3 次,再多往往不會有更多變化 |
| MED | 同一家運營商有兩條互聯時,主鏈路宣告較小的 MED | 隻影響這家運營商在兩條鏈路之間的選擇 | 對方可能不採信或重置 MED,事先和運營商確認 |
| 宣告更長的字首 | 把 /23 拆成兩個 /24,A 只多宣告其中一個 /24,所有線路都宣告 /23 | 最長匹配,全網生效 | 公網上一般不接受長於 /24 的 IPv4 字首;保留覆蓋用的 /23,A 斷開時流量還能從別家進來 |
| 運營商團體屬性 | 按運營商公佈的 Community 值,讓它在內部調低這條路由的優先順序,或不宣告給某些對等方 | 運營商網路內部 | 是否支援、取值和含義以運營商的說明為準 |
華為上向運營商 B 宣告時預置兩次:
ip ip-prefix OWN index 10 permit 203.0.113.0 24
#
route-policy TO-ISP-B permit node 10
if-match ip-prefix OWN
apply as-path 64500 64500 additive
#
bgp 64500
ipv4-family unicast
peer 198.51.100.6 route-policy TO-ISP-B export
思科:
ip prefix-list OWN seq 10 permit 203.0.113.0/24
!
route-map TO-ISP-B permit 10
match ip address prefix-list OWN
set as-path prepend 64500 64500
!
router bgp 64500
neighbor 198.51.100.6 route-map TO-ISP-B out
出方向策略同時也是過濾器:沒有被任何節點匹配的字首不會被宣告。如果原來已經有一條只放行自有位址段的出方向策略,要把預置合並進去,而不是再掛一條把它替換掉。生效後執行 refresh bgp 198.51.100.6 export 或 clear ip bgp 198.51.100.6 soft out,再到公開的路由查詢站點(Looking Glass)看你的字首在其他網路裡的 AS_Path,確認重複的 64500 已經出現。
舉個調整思路(數字為假設):晚高峰運營商 A 的入方向跑到 9 Gbps、接近 10G 連接埠上限,B 只有 4 Gbps。先在 A 上加一次預置(或撤掉 B 上原有的預置),觀察第三方網路的流量轉移了多少;仍不夠,再把流量最大的那個 /24 只在 B 上多宣告一份。這樣做之後要確認 B 斷開時,這個 /24 的流量仍能經 /23 從 A、C 進來。
在機房裡怎麼落地
入方向排程最終落在“哪個 /24 走哪條線路”上,難點是先要知道每個 /24 背後是哪些客戶、各自有多大流量。Toplink DCIM 的 IP 位址管理 按 CIDR 錄入位址段,大段可以自動拆成 /24 分別管理,每個位址分配給了哪台伺服器都有記錄,位址段還能按線路分組、打標籤,標出哪些段參與了單獨宣告。再結合 流量計費 裡各伺服器連接埠的流量統計和 95 值,就能估算出每個 /24 背後的流量,決定先調哪一段;調整前後對比相關連接埠的流量,確認排程效果和預期一致。
常見問題
為什麼有的資料說 BGP 選路原則 11 條,有的說 13 條?
差別在於步驟怎麼拆分:有的把“下一跳可達”算作第一條,有的不單列等價多路徑和“比新舊”,有的把 AIGP 也列進來。各條之間的相對順序基本一致,實際以所用裝置廠商文件的順序為準。
BGP 等價負載分擔需要滿足什麼條件?
預設只選一條最優路徑。配置了 maximum-paths(思科)或 maximum load-balancing(華為)後,從第一步一直到 IGP 開銷都相同的多條路徑才能同時裝入路由表;思科對 eBGP 多路徑還要求 AS_Path 完全一致,除非開啟放寬比較的選項。具體條件以裝置手冊為準。
從 iBGP 鄰居學到的路由,為什麼不會再傳給其他 iBGP 鄰居?
這是 iBGP 的防環規則:路由在 AS 內部傳遞時 AS_Path 不會變長,無法靠它發現環路,所以從 iBGP 學到的路由不再通告給其他 iBGP 鄰居。AS 內的路由器要麼兩兩建立 iBGP(全互聯),要麼使用路由反射器或聯盟;選路表裡的 ORIGINATOR_ID 和 Cluster_List,就是路由反射帶來的屬性。