☰
BGP选路规则详解:华为设备13条属性实验与排障实践
2026/10/14 18:45:53 网站建设 项目流程

当年我在现网排查一条双出口链路时,遇到过很典型的场景:两条 BGP 路径都能收到同一段前缀,带宽大的那条却始终不生效,流量全部压在了备用链路上。当时我对 BGP 选路规则的认知停留在“AS 路径短优先”这种粗糙印象上,结果查了半夜,最后才发现是 MED 和 Local_Preference 的组合问题。

后来我决定不糊弄自己,专门在华为设备上把这套选路规则一条一条搭实验验证。做完整套实验之后,很多以前“背过但没懂”的规则都串起来了。这篇文章就把当时的实验过程、对照结果和排障心得整理出来,适合刚接触 BGP 的网工,也适合背过规则但从没动手验证过的老手。

1. 实验拓扑与基础配置:先搭一个能产生“选路分歧”的网络

实验最终目的是让同一台路由器从不同路径学到同一条前缀,然后通过修改单一属性观察选路变化。所以拓扑不能太简单,至少要让一台设备同时从 EBGP 和 IBGP 方向拿到相同路由。

1.1 设备规划和地址表

我用了 4 台设备,模拟两个 AS:AS 100 内部放 R1、R2、R3 三台,AS 200 放 R4 作为外部来源。R1 和 R3 分别和 R4 建立 EBGP 邻居,R2 作为 AS 内部的 IBGP 传递节点。这样 R1 既能从直连 EBGP 学到路由,也能通过 IBGP 从 R3 绕一圈学到同一条路由,选路分歧就出现了。

地址规划如下:

设备AS接口IP 地址对端
R1100G0/0/010.0.1.1/24R4
R1100G0/0/110.0.2.1/24R2
R1100Loopback01.1.1.1/32IBGP 源地址
R2100G0/0/010.0.2.2/24R1
R2100G0/0/110.0.3.2/24R3
R2100Loopback02.2.2.2/32IBGP 源地址
R3100G0/0/010.0.3.3/24R2
R3100G0/0/110.0.4.3/24R4
R3100Loopback03.3.3.3/32IBGP 源地址
R4200G0/0/010.0.1.4/24R1
R4200G0/0/110.0.4.4/24R3
R4200Loopback1172.16.0.1/24模拟业务网段

AS 100 内部跑 OSPF,把三个 Loopback 和互连网段都宣告进去,保证 IBGP 邻居能通过 IGP 找到彼此的 Loopback 地址。

1.2 关键配置:IBGP 全互联 + EBGP 双出口

我在 AS 100 内部做 IBGP 全互联,R1、R2、R3 两两建立 IBGP 邻居,会话源都用 Loopback0。这样做的目的很明确:让 R1 能从 R2 和 R3 两个方向都学到 R4 通告的前缀。华为配置如下:

# R1 bgp 100 peer 2.2.2.2 as-number 100 peer 2.2.2.2 connect-interface Loopback0 peer 3.3.3.3 as-number 100 peer 3.3.3.3 connect-interface Loopback0 peer 10.0.1.4 as-number 200 ipv4-family unicast peer 2.2.2.2 enable peer 3.3.3.3 enable peer 10.0.1.4 enable

R4 侧通告业务网段,用 network 命令把 172.16.0.0/24 放进 BGP:

# R4 interface Loopback1 ip address 172.16.0.1 255.255.255.0 bgp 200 peer 10.0.1.1 as-number 100 peer 10.0.4.3 as-number 100 network 172.16.0.0 255.255.255.0 ipv4-family unicast peer 10.0.1.1 enable peer 10.0.4.3 enable

这里有个很容易踩的坑:华为的network命令要求本地路由表里有精确匹配的路由,不是像某些厂商那样直接宣告一个网段就行。R4 上有 Loopback1 的直连路由 172.16.0.0/24,所以能通告成功。如果换成一台没有直连路由的设备,想通告远端网段,必须先写静态路由指向 null0 或者通过 IGP 引入。

配置完以后在 R1 上查看 BGP 路由表,应该能看到多条指向 172.16.0.0/24 的路径:

display bgp routing-table Total Number of Routes: 3 Network NextHop MED LocPrf PrefVal Path/Ogn *> 172.16.0.0/24 10.0.1.4 0 100 0 200i *>i 172.16.0.0/24 10.0.3.3 0 100 0 200i *>i 172.16.0.0/24 10.0.4.4 0 100 0 200i

*表示有效路由,>表示最优路由。注意 IBGP 学到的路由标记了i,EBGP 直连那条没有i后缀。

2. 第一道门槛:下一跳不可达的路由直接出局

很多人把 BGP 选路规则从 Preferred-Value 开始背,忽略了最前面的一条隐藏规则:下一跳不可达的路由,没有资格参与任何比较。BGP 路由表里可以保留这条路由,但它不会进入 IP 路由表,也不可能被选中为最优。

2.1 实验:人为制造“下一跳黑洞”

我把 R1 的 OSPF 配置里去掉 10.0.4.0/24 网段的宣告,模拟 R1 不知道如何到达 IBGP 路由的下一跳。这时候再看 R1 的 BGP 路由表,会发现从 R3 学到的路由状态变化了:

*> 172.16.0.0/24 10.0.1.4 0 100 0 200i * 172.16.0.0/24 10.0.4.4 0 100 0 200i

那条从 IBGP 学到的路由虽然有*,但没有>,方向是“无效等待”状态。查看 IP 路由表时它也不会出现。BGP 不会把一个下一跳不可达的路径放进转发表,因为那等于把一个需要“空中接力”的包交给一个不存在的接收者。

2.2 为什么这条规则要放在最前面

从工程角度讲,BGP 承载的是“转发的可能性”,一条路径如果下一跳不可达,它连基本的转发条件都不满足,就没有资格和其他路径同台竞技。这就像面试第一轮筛简历,简历写得再漂亮,如果基本资质不满足,后面所有环节都和你无关。

这个实验也解释了为什么 IBGP 邻居之间通常要求 IGP 可达。EBGP 的下一跳是对端直连接口地址,EBGP 建立的前提就是三层直连,所以天然可达;而 IBGP 从 EBGP 学到的路由,默认不会修改下一跳,如果 AS 内部的 IGP 不能到达那个外部下一跳地址,路由就是无效的。排障时遇到display bgp routing-table里一堆*没有>的路由,先查 IGP 到下一跳的路由,不要急着研究策略。

3. 华为私货:Preferred-Value 凭什么排在第一位

接下来进入正式的比较规则。华为把 Preferred-Value 放在第一条,这是设备和思科系的 Weight 类似的东西,但实现细节不同。它只在本地生效,不会随着 BGP 更新报文传给任何邻居,纯粹是“我这台设备说了算”的属性。

3.1 实验:修改 Preferred-Value 抢夺最优路径

在 R1 上,默认最优路径是 EBGP 直连那条,因为它的后续属性足够优秀。现在我在 R1 上对 IBGP 邻居 3.3.3.3 设置一个较大的 Preferred-Value:

bgp 100 peer 3.3.3.3 preferred-value 200

刷新 BGP 路由表,R1 的最优路径立刻变成了下一跳 10.0.4.4 那条 IBGP 路由,说明只要这一条属性有差异,后面所有规则都不需要再看:

*>i 172.16.0.0/24 10.0.4.4 0 100 200 200i *> 172.16.0.0/24 10.0.1.4 0 100 0 200i

注意 PrefVal 列,IBGP 那条显示为 200,EBGP 直连那条还是 0。这个属性是华为的“本地权重”,它不需要经过任何路由策略传递,也不会出现在 BGP Update 报文中。实际运维中,如果某个运营商线路质量差,但 BGP 属性又差不多,直接在入接口的邻居上把这个值调低,就能让另一条链路顶上来。

3.2 难点:Preferred-Value 的不可传递性

我特意强调不可传递,是因为很多人在多台设备上排查时容易糊涂。在 R1 上设置 Preferred-Value,只会影响 R1 自己的选路。R2 和 R3 完全感知不到这个值。如果希望整个 AS 都偏好某条路径,应该用 Local_Preference,而不是 Preferred-Value。只要一条 EBGP 路由进入某台路由器后带上了这个值,它传给 IBGP 邻居时,这个属性瞬间归零,因为 BGP 报文里根本没有这个字段。

4. Local_Preference:AS 内部的统一投票

Local_Preference 是 BGP 四大公认自决属性之一,默认值是 100,值越大越优先。它的传播范围是整个 AS:无论是从 EBGP 邻居收到时被修改,还是本地自己修改,它都会通过 IBGP 传给 AS 内部的每一台路由器,但绝对不会传到 AS 外面去。

4.1 实验:入方向修改 Local_Preference 影响全 AS

我把 R1 上对 R4 的入方向加一个 route-policy,把从 R4 直连 EBGP 学到的 172.16.0.0/24 的 Local_Preference 改成 150:

route-policy LP_TO_R4 permit node 10 if-match ip-prefix NET_172 apply local-preference 150 ip ip-prefix NET_172 permit 172.16.0.0 24 bgp 100 peer 10.0.1.4 route-policy LP_TO_R4 import

这时再看 R1,最优路径重新切回直连 EBGP 那条,而且 LocPrf 列显示 150。更关键的是,由于 IBGP 会携带这个属性,R2 和 R3 也会看到 LocPrf=150,它们如果收到了这个前缀的其他版本,也会更偏好这个 150 的版本。

在 R2 上执行display bgp routing-table 172.16.0.0,能看到 LocPrf=150 的路径占据最优位置。这说明 Local_Preference 是一个“全 AS 统一的意见表达”,适合做主备出口切换的场景,比如在主线路故障前,在备线路上把所有入口方向的 Local_Preference 调低,或者把主线路调高,让整个 AS 的上行流量全部走主出口。

4.2 最常见的使用误区

很多初学者会在出方向修改 Local_Preference,这其实是不生效的。Local_Preference 只影响本地 AS 对某条外部路由的偏好,应该从 EBGP 入方向注入,或者在一台设备上用 default 命令全局设置。另外要注意,Local_Preference 的传播仅限于 IBGP 会话。如果 R2 把带着 LocPrf=150 的路由通过 EBGP 传给另一个 AS,对端收到的 LocPrf 是默认值 100,而不是 150,这个属性在 EBGP 边界就被重置了。

5. AS_Path 长度:最符合直觉,但最容易被误用

AS_Path 决定了一条 BGP 路由穿越了多少个自治系统。规则是 AS 路径越短越优先。这个规则好理解,但实际排查中总有人把它当成唯一标准,忽略了前面还有 PV 和 LP 两座大山。

5.1 构造不同长度的 AS_Path 路径

在基础实验中,R1 从直连 EBGP 学到的 AS_Path 是 200,从 IBGP 学到的 AS_Path 也是 200。为了看长度差异,我在 R4 上对发往 R3 的出方向加长 AS_Path:

route-policy ADD_ASPATH permit node 10 apply as-path 300 300 additive bgp 200 peer 10.0.4.3 route-policy ADD_ASPATH export

apply as-path 300 300 additive的意思是在原有 AS_Path 后追加两个 300。这样 R3 从 R4 学到的 AS_Path 变成 200 300 300,R3 传给 R1 后,R1 的 IBGP 路径 AS_Path 同样是 200 300 300,比直连那条的 200 长。由于前面属性默认全相等,R1 选路结果还是直连 EBGP 那条。

看 R1 的路由表输出:

*> 172.16.0.0/24 10.0.1.4 0 100 0 200i *>i 172.16.0.0/24 10.0.4.4 0 100 0 200 300 300i

Path/Ogn 列清楚显示了两个候选的 AS_Path 差异。

5.2 AS_Path 加长背后的底层设计

AS_Path 除了参与选路,还有一个几乎同样重要的功能:防环。任何一台 BGP 路由器在收到一条 AS_Path 里包含自己 AS 号的路由时,会直接拒收。这个机制决定了 BGP 能够在一个全网状的自治系统拓扑里不形成环路。所以通过加长 AS_Path 来做流量引导时,要注意别加进去和路径沿途重复的 AS 号,否则可能直接把路由搞丢。实验里我用 300 这种不存在的 AS 号来模拟,实际生产环境也经常用假 AS 号来“惩罚”某条路径。

5.3 一个颠覆直觉的提醒

AS_Path 短不等于网络质量好。比如一条路径经过一个大型骨干 AS,虽然 AS_Path 只有一段,但覆盖的距离可能横跨几千公里;另一条路径绕了几个小 AS,反而延迟更低。选路规则是死的,它只负责在同等条件下选出“属性最优”的路径,不会关心链路质量。想要基于质量选路,得靠 MED、LP 或者本地策略把路径 “掰”过来。

6. 本地聚合、Origin 与 MED:三张容易被忽略的底牌

PV、LP、AS_Path 之后,选路规则还涉及本地生成路由优先级、Origin 属性和 MED。这三个属性平时不太起眼,但在所有 EBGP 属性都平手时,它们就是决定胜负的底牌。

6.1 本地生成路由优先于从对等体学习

华为的规则里,本地生成路由(包括手动聚合、自动聚合、network 宣告、import 引入)优先于从对等体学来的路由。换句话说,一台路由器上如果同时有自己 network 出来的路由和从 IBGP 学来的同前缀路由,它一定选本地的那条。

这个规则的工程意义很好理解:本地生成的路由表示“这个前缀我这里有根”,可靠性高于转述别人的信息。实验验证很简单,在 R3 上用import-route static把一条静态路由引入 BGP,同时 R3 又通过 IBGP 学到 R1 传来的同前缀路由,看 R3 的 BGP 路由表,最优的一定是 import 引入的那条。

6.2 Origin 属性:IGP > EGP > incomplete

Origin 是 BGP 的公认强制属性,标记路由的来源类型。i(IGP)表示通过 network 命令通告,e(EGP)表示通过 EGP 协议学到,?表示来源不详,通常由 import-route 引入产生。优先级是 i > e > ?。

我在 R4 上把同一前缀分别用 network 和 import-route 两种方式引入。比如 R4 有两条路径可以产生 172.16.0.0/24:一条是 network,Origin 为 i;另一条是静态路由引入,Origin 为 ?。当这两条路径的 AS_Path 和 MED 完全相同时,R1 会优先选择 Origin=i 的那条。

日常排障中,看到display bgp routing-table的 Path/Ogn 末尾是?,就要知道这是 import 进来的。这类路由的精细控制能力通常不如 network 路由,因为 import 会把所有匹配的静态路由都带进来,而 network 是精确匹配。

6.3 MED:只在“同一起跑线”时生效

MED 是可选非传递属性,默认值是 0,值越小越优先。华为的规则里,MED 比较有前提条件:只有当两条路径来自同一个相邻 AS 时,MED 才参与比较;如果来自不同 AS,默认情况下 MED 被忽略,除非全局配置了允许比较不同 AS 的 MED。

实验操作路径:在 R4 上对 R1 出方向把 MED 设为 100,对 R3 方向保持 MED 默认 0,同时去掉之前加的 AS_Path。这时 R1 从直连 EBGP 学到的 MED=100,从 IBGP 学到的 MED=0。由于 AS_Path 相同,MED 小者胜出,R1 的最优路径变成从 R3 转一条的那条:

*>i 172.16.0.0/24 10.0.4.4 0 100 0 200i *> 172.16.0.0/24 10.0.1.4 100 100 0 200i

这个“同一起跑线”的限制很重要。实际组网中,两个运营商出口分别做 MED 调制,由于它们的 AS 号不同,MED 默认不比较,达不到预期的选路效果。排查方法就是看两条路径的 Path 列开头 AS 号是否一致。如果一致但 MED 有差异,检查是不是被优先级更靠前的属性解决掉了。

7. EBGP 优于 IBGP,以及 IGP Metric 的真正含义

选路进行到这里,剩下的是几组比较偏门的规则,但它们恰恰是实验环境里最容易观察到的现象。

7.1 EBGP 与 IBGP 之争

当两条路径的 PV、LP、AS_Path、Origin、MED 全部相同时,华为设备会优先选择 EBGP 学到的路由,而不是 IBGP 学到的。我实验里 R1 的默认状态就是典型:直连 EBGP 那条路径最终胜出,因为它的属性并不比 IBGP 绕行路径差,而在相同条件下 EBGP 的优先级又高于 IBGP。

背后的逻辑是防御环:EBGP 路径通常表示这条路由直接从 AS 外部获取,IBGP 路径则是从 AS 内部其他路由器转述,EBGP 路径更接近源头。这个规则的副作用是,在 AS 内部设计 BGP 路由反射器时,如果反射器同时从 EBGP 和 IBGP 学到同一条路由,它会优先选择 EBGP 那条,这可能导致反射器不会把 IBGP 学到的路由传给其他客户端,需要特别注意。

7.2 IGP Metric 比的是“到 BGP 下一跳”的路由开销

再看第 8 条规则,比较到 BGP 下一跳的 IGP Metric。注意这里不是比到“目的网段”的 IGP 开销,而是比到“BGP 下一跳地址”的 IGP 开销。这是最容易被误解的一条。

我在 R1 上保留从 R2 和从 R3 两条 IBGP 学到的同前缀路由(都把下一跳指向 10.0.4.4),通过调整 OSPF 的 cost 值来验证:把 R3 到 10.0.4.0/24 的 OSPF 开销调小,或者把 R1 到 R3 的链路 cost 调小,这条路对应的 IGP Metric 就会变小,进而被选中。

我在 R2 和 R3 之间的 OSPF 中把 R3 的 Loopback 宣告 cost 加大,观察 R1 的选路变化。只要到 BGP 下一跳的 OSPF 开销发生变化,BGP 最优路径就会跟着变。这说明 IBGP 域内的流量走向,实际上可以由 IGP 的链路开销间接控制,这也是很多园区网利用 OSPF cost 做 BGP 流量牵引的基础。

8. 平局决胜:Cluster_List、Router ID 和 Originator_ID

当所有属性都对比完毕依然出现平手时,BGP 才进入最后的决胜阶段。这一阶段已经很少被运维人员操控了,但知道它们有助于理解一些“莫名其妙”的选路结果。

8.1 Router ID 越小越优先再往下细分

华为规则里,在比较完 Cluster_List 之后,会比较通告路由的 Router ID,小的优先。这里有一个容易混淆的点:如果路由经过路由反射器,优先看 Originator_ID;如果没有反射器,看通告者的 Router ID。

我做了一个简单实验:在 R1 和 R3 同时向 R2 通告同一前缀,所有属性都一样时,R2 选择 Router ID 最小的设备通告的路由。把 R1 的 Router ID 配置为 4.4.4.4,R3 配置为 3.3.3.3,R2 最终会优选 R3 通告的那条,因为 3.3.3.3 比 4.4.4.4 小。把 R1 的 Router ID 改成 2.2.2.2 再刷新,R2 的优选结果立刻改变。

很多人忽略这条规则的现实影响:当一台路由器同时和多个 RR 建立 IBGP 邻居,收到完全等价的路径时,Router ID 最小的那个 RR 提供的路径会成为最优。这就解释了为什么 RR 的 Router ID 配置要提前规划,否则可能出现流量在反射器之间“一边倒”的现象。

8.2 最后一条:对等体地址最小者胜出

如果前面全部平手,华为设备会优选对等体 IP 地址最小的路由。这是一条兜底规则,在普通网络里几乎不参与决策,但在大型 IBGP 全网状网络里,如果邻接的多个对等体地址经过精心设计,理论上可以微调这条规则来影响选路。不过我对这条规则的实践机会很少,通常前面几步已经分出高下了。

9. 实验后的经验复盘:选路不是打分,是淘汰赛

整套实验做完,最大的感悟是:BGP 选路规则是一套“淘汰赛”,不是“积分赛”。两条路径之间比较时,不需要把所有属性换算成综合分,只要在某一条规则上分出胜负,后面的属性一概不看。这意味着修改选路结果时,只需要找到“当前真正卡住的那一条规则”,把它改掉就行,不需要面面俱到。

排查技巧方面,我会直接用display bgp routing-table看最优路径,然后再对比它和次优路径的 PV、LP、AS_Path、MED 等属性,找到差异点,差异点通常就是选路依据。这个方法比死记硬背选路顺序更高效。

如果遇到“配置了 MED 却不生效”,先检查是不是 AS_Path 不一样;遇到“IBGP 路由收不到”,先查下一跳可达性;遇到“该走的链路没走”,先看是不是本地策略或 LP 被改动过。把这些排查方向和 13 条规则的顺序对应起来,排障效率会提升很多。

最后分享一个小经验:实验做完之后,一定要把策略配置全部清掉再换下一个场景,我中途就有一次忘了删 Preferred-Value 配置,导致后面 LP 实验怎么调都不对。在现网做变更也一样,带上完整的回退方案,再动 BGP 的策略,这是网工的基本素养。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询