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,就是路由反射带来的属性。