1. 先弄明白BGP到底怎么“挑路”
说句大实话,BGP选路这个问题,很多干网络的朋友刚接触时都容易懵。路由表里明明一堆条目,为什么最终只有一条被装进IP路由表?这个“唯一”的赢家是怎么被选出来的?答案就是BGP那套十三条选路规则。
不过真正翻过华为文档的人都知道,文档里的优先级列表又长又抽象,什么“Preferred-Value”、“Local_Preference”、“AS_PATH”……冷冰冰的术语堆在一起,根本记不住。我自己带过不少新人,最有效的学习方法从来不是背规则,而是动手搭一个小实验,让每条规则“亲手”把路由选出来。所以这篇就用eNSP做一个小而全的BGP选路实验,把最常见的几条选路规则挨个验证一遍。
这里先交代一下,这个小实验面向的是已经会基本BGP配置,但选路逻辑还比较模糊的朋友。不会从零教你怎么敲neighbor命令,重点讲“为什么这么配、选路结果怎么变、实际项目中怎么用”。实验本身不大,三台路由器就能跑起来,但覆盖的规则足够应付日常工作中90%的选路场景。
先给个目录感,整个实验会按这个顺序走:
- 搭建一个三台设备的最小BGP拓扑
- 配好基础BGP邻居关系
- 依次验证首选值、Local_Preference、AS_PATH、MED这四条最常用的选路规则
- 最后聊一聊实际项目里选路策略怎么落地
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 实验拓扑与基础配置
2.1 拓扑设计思路
实验拓扑我用了三台AR路由器,本质上是一个不对称的三角网。为什么要三角网?因为只有存在多条可达路径,选路规则才有用武之地。如果只有一条路径,BGP根本没得选。
具体规划是这样的:
- 设备R1、R2、R3,运行OSPF作为底层IGP,保证设备之间TCP可达
- BGP运行在AS 100内,也就是IBGP邻居关系
- R1上宣告一条业务网段100.1.1.0/24
- R2和R3之间直连,R1到R2、R1到R3也都有链路
code复制拓扑示意:
R2
/ \
/ \
R1----R3
R1 -- R2 : 10.1.12.0/24
R1 -- R3 : 10.1.13.0/24
R2 -- R3 : 10.1.23.0/24
R1上宣告业务网段:100.1.1.0/24
这个拓扑下,R2和R3都会从R1学到100.1.1.0/24这条路由,同时因为R2和R3是IBGP邻居,它们彼此之间还会转发这条路由。也就是说,R2看100.1.1.0/24时,会看到两条路径:一条直连从R1来,一条从R3绕过来。这样就有“选路”的空间了。
2.2 基础配置清单
按下面的配置逐台敲就行,先把邻居关系建起来。
R1的基础配置:
text复制sysname R1
interface GigabitEthernet0/0/0
ip address 10.1.12.1 255.255.255.0
interface GigabitEthernet0/0/1
ip address 10.1.13.1 255.255.255.0
interface LoopBack0
ip address 1.1.1.1 255.255.255.255
ospf 1 router-id 1.1.1.1
area 0.0.0.0
network 10.1.12.0 0.0.0.255
network 10.1.13.0 0.0.0.255
network 1.1.1.1 0.0.0.0
bgp 100
router-id 1.1.1.1
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
network 100.1.1.0 255.255.255.0
R2的基础配置:
text复制sysname R2
interface GigabitEthernet0/0/0
ip address 10.1.12.2 255.255.255.0
interface GigabitEthernet0/0/1
ip address 10.1.23.2 255.255.255.0
interface LoopBack0
ip address 2.2.2.2 255.255.255.255
ospf 1 router-id 2.2.2.2
area 0.0.0.0
network 10.1.12.0 0.0.0.255
network 10.1.23.0 0.0.0.255
network 2.2.2.2 0.0.0.0
bgp 100
router-id 2.2.2.2
peer 1.1.1.1 as-number 100
peer 1.1.1.1 connect-interface LoopBack0
peer 3.3.3.3 as-number 100
peer 3.3.3.3 connect-interface LoopBack0
R3的基础配置:
text复制sysname R3
interface GigabitEthernet0/0/0
ip address 10.1.13.3 255.255.255.0
interface GigabitEthernet0/0/1
ip address 10.1.23.3 255.255.255.0
interface LoopBack0
ip address 3.3.3.3 255.255.255.255
ospf 1 router-id 3.3.3.3
area 0.0.0.0
network 10.1.13.0 0.0.0.255
network 10.1.23.0 0.0.0.255
network 3.3.3.3 0.0.0.0
bgp 100
router-id 3.3.3.3
peer 1.1.1.1 as-number 100
peer 1.1.1.1 connect-interface LoopBack0
peer 2.2.2.2 as-number 100
peer 2.2.2.2 connect-interface LoopBack0
这里注意几个细节:
- IBGP邻居用LoopBack接口建立,配置里一定要加
connect-interface,否则BGP会用出接口的地址去建立TCP连接,和peer指定的地址对不上,邻居永远起不来。 - OSPF里要把LoopBack宣告进去,否则LoopBack地址虽然本身是up的,但其他设备路由表里没有它,TCP包就发不过去。
- 三台设备的BGP Router-ID不能冲突,这一点很多人会忽略,Router-ID冲突会导致邻居关系反复震荡。
配置完后,在R2上查看BGP邻居状态:
text复制display bgp peer
看到两个邻居都是Established就说明基础环境没问题了,可以进行下一步实验。
在动手调选路规则之前,先花点时间把R2的BGP路由表完整看一下,这会让你对后续实验有更直观的感受。
在R2上执行:
text复制display bgp routing-table
正常情况下能看到类似下面的输出:
text复制 BGP Local router ID is 2.2.2.2
Status codes: * - valid, > - best, d - damped, h - history
Network NextHop MED LocPrf PrefVal Path/Ogn
*> 100.1.1.0/24 1.1.1.1 0 100 0 i
* 100.1.1.0/24 3.3.3.3 0 100 0 i
这个输出非常关键,看懂它,你就看懂了BGP选路的入口。*>那块是当前选中的最优路由,下一跳是1.1.1.1;*那块也是有效路由,下一跳是3.3.3.3,但没被选中。
思考一下为什么R2会更倾向于从R1学习到的那条路径?因为BGP选规则里,公认必遵的规则在起作用。R2从R1直连学到的路由,下一跳是1.1.1.1,IGP开销更小,所以在“到下一跳的IGP开销”这一步就赢了。
这一步先记住一个概念:BGP选路不是直接看“到目的网段的开销”,而是看“到下一跳地址的开销”。下一跳在IGP里越“近”,路由就越有优势。
3. 逐条验证BGP选路规则
3.1 首选值(Preferred-Value):本地说了算
第一条规则叫Preferred-Value,这是华为特有的属性,只在本地路由器上有意义,不会传给任何邻居。它的取值越高越优先。说白了就是“我本地就是想走这条路径,不需要理由”。
先看看默认状态下,R2去往100.1.1.0/24走的是哪条路径:
text复制display bgp routing-table 100.1.1.0/24
如果不出意外,最优路径的下一跳应该是1.1.1.1。现在我在R2上手动调整,让去往100.1.1.0/24的路径里,下一跳为3.3.3.3的那条拥有更高的Preferred-Value。
在R2上做如下配置:
text复制route-policy PV permit node 10
if-match ip-prefix PV
apply preferred-value 100
#
ip ip-prefix PV index 10 permit 100.1.1.0 24
#
bgp 100
peer 3.3.3.3 route-policy PV import
配置解释一下:先定义一个前缀列表PV,匹配100.1.1.0/24,然后定义路由策略PV,给匹配上的路由设置Preferred-Value为100,最后把这个策略应用到从邻居3.3.3.3收到的路由上。注意这里是import方向,也就是处理“邻居发给我的路由”。
配置完成后,再查看一次R2的BGP路由表:
text复制display bgp routing-table 100.1.1.0/24
这回变化就很明显了:
text复制 BGP Local router ID is 2.2.2.2
Status codes: * - valid, > - best, d - damped, h - history
Network NextHop MED LocPrf PrefVal Path/Ogn
* 100.1.1.0/24 1.1.1.1 0 100 0 i
*> 100.1.1.0/24 3.3.3.3 0 100 100 i
最优路径已经变成了下一跳3.3.3.3那条,因为它的PrefVal(Preferred-Value)是100,明显高于默认的0。选路的第一道关卡就这么直观。
这项工作实际业务中常见的使用场景是在出口路由器上做“本地偏好”,比如两条运营商线路接入,希望内网访问某一特定目的地址时强制走电信线路,就可以用Preferred-Value在本地指定,完全不影响其他设备。
3.2 Local_Preference:区域内的统一意志
Local_Preference(本地优先级)是BGP选路规则里非常常用的一个属性。它是一个AS内部的属性,只在同一个AS内传递,不会传出AS。数值越大越优先。和华为主机相比,它和Preferred-Value的区别在于:Preferred-Value只影响单台路由器,Local_Preference会影响整个AS内所有设备的选路结果。
还是用刚才的拓扑和路由,验证这个规则。
先把R2、R3上之前调的Preferred-Value策略全部清掉,回到初始状态,确保选路结果回到默认最优路径(R2优选下一跳1.1.1.1)。
清策略:
text复制# 在R2上
undo bgp 100
# 重新配置一遍R2的BGP,但这次不加任何路由策略
或者如果你想简单点,重启BGP进程:
text复制reset bgp all
不过注意,reset bgp all只会重置BGP会话,不会清掉策略。如果你之前配了route-policy,还是要手动undo peer掉。
恢复默认后,R2上最优路径应该是下一跳1.1.1.1。现在在R3上修改发往R2的路由的Local_Preference,让R2更倾向于从R3学到的路径。
在R3上配置:
text复制route-policy LP permit node 10
if-match ip-prefix LP
apply local-preference 200
#
ip ip-prefix LP index 10 permit 100.1.1.0 24
#
bgp 100
peer 2.2.2.2 route-policy LP export
重点关注:这里是在R3上配置,方向是export(发给R2的方向),给通往100.1.1.0/24的路由打上Local_Preference 200。
配置完后,回到R2上再看:
text复制display bgp routing-table 100.1.1.0/24
输出应该是:
text复制 Network NextHop MED LocPrf PrefVal Path/Ogn
* 100.1.1.0/24 1.1.1.1 0 100 0 i
*> 100.1.1.0/24 3.3.3.3 0 200 0 i
最优路径切换到了从R3学到的路径。此时你再到R1上去看,R1自己并不是从R3学到的这条“LocPrf=200”的路由。因为Local_Preference不会传给EBGP邻居,IBGP内部是传的。这个特性特别适合用在出口选路场景,比如公司有两条运营商线路,希望所有人访问公网时都走联通,就在联通侧路由上设置更高的Local_Preference,全公司设备自动跟着走。
这里补充一个很多人容易理解错的地方:Local_Preference方向和接收方的关系。当你在R3上对2.2.2.2的export方向应用策略时,R3发给R2的路由就带着这个属性;但如果R2还有其他IBGP邻居,比如R4,R3没有对R4配置这条策略,那么R4收到的路由Local_Preference还是默认的100。所以一个AS里想让所有路由器统一选路,通常是在路由进入AS的边界路由器上统一打属性,让它随IBGP传递到所有内部设备。
3.3 AS_PATH:用路径长度说话
AS_PATH规则可能是BGP选路里最经典的一条,因为EBGP场景下它经常是决定胜负的关键。AS_PATH的长度越短越优。路径短意味着经过的AS少,网络消耗相对小,管理上也更可控。
现实世界中,很多企业会选择少绕路、直连的运营商线路,就是因为路径短。但在IBGP实验里,AS_PATH这个属性默认是空的,因为IBGP内部不追加AS号。为了让实验跑起来,我需要在R3上给路由人为增加AS_PATH长度。
同样,先把R3上的Local_Preference策略清掉,恢复默认状态。然后配置R3增加AS_PATH属性。
在R3上配置:
text复制route-policy ASP permit node 10
if-match ip-prefix ASP
apply as-path 65001 65002 65003
#
ip ip-prefix ASP index 10 permit 100.1.1.0 24
#
bgp 100
peer 2.2.2.2 route-policy ASP export
这里用apply as-path往路由前面追加了三个AS号,此时R2从R3收到的这条100.1.1.0/24路由,AS_PATH长度就从0变成了3。
R2上查看:
text复制display bgp routing-table 100.1.1.0/24
输出:
text复制 Network NextHop MED LocPrf PrefVal Path/Ogn
*> 100.1.1.0/24 1.1.1.1 0 100 0 i
* 100.1.1.0/24 3.3.3.3 0 100 0 65001 65002 65003 i
R2会选择AS_PATH更短的路径,也就是下一跳1.1.1.1那条。和默认状态相比,选路结果没有变,但此时的原因已经从“IGP开销”变成了“AS_PATH长度”——因为加了AS号后,AS_PATH规则排在IGP开销之前。
这里有个很关键的排坑点:很多人搞不清apply as-path是“追加”而不是“覆盖”。华为设备上默认是追加在最前面。如果你不想追加而想覆盖,需要写apply as-path 65001 overwrite。实际业务里,运营商经常会用as-path prepend技术让某条线路“变长”,主动引导流量走另一条路径。
3.4 MED:跨AS的成本度量
MED(Multi-Exit Discriminator)是BGP里专门用来在多个EBGP出口之间做选择的属性。它是告诉对端AS“从我这边进入,开销多大”的度量值。MED越小越优。
但在纯IBGP环境里,MED默认情况下也能参与选路,只是它排在AS_PATH之后。实际生产环境中,最常见的用法是:两个AS之间有两条线路互联,通过调整MED来决定流量从哪条线路进入本AS。
这里模拟一个场景:假设R2模拟成AS 200的边界路由器,R1也属于AS 200(把拓扑稍微调整一下),R3作为AS 100的边界路由器,它与R2、R1之间建立EBGP。不过为了简化实验,我们还是保持IBGP的配置,只验证MED属性本身的作用。
重新调整:R2上给从R1来的路由配置MED=50,给从R3来的路由保持默认MED=0。默认情况下MED值越小越优,所以R2会优先选择从R3学到的路径吗?不对,这里必须想清楚拓扑关系,R2是“本地设备”,它收到的所有100.1.1.0/24路由,下一跳分别是1.1.1.1和3.3.3.3,如果给从R3那边来的路径设置MED=0,从R1那边来的设置MED=50,那么R2优选MED更小的,即从R3学到的路径。
在R2上配置:
text复制route-policy MED permit node 10
if-match ip-prefix MED
apply cost 50
#
ip ip-prefix MED index 10 permit 100.1.1.0 24
#
bgp 100
peer 1.1.1.1 route-policy MED import
这里apply cost就是设置MED值。配置完成后查看R2的BGP选路结果,会发现最优路径变成了下一跳3.3.3.3,因为它的MED=0,比1.1.1.1的MED=50更小。
注意:此时R1那条直连路径的IGP开销本来很低,但MED的优先级排在IGP开销前面,所以即便直连IGP开销小,也架不住MED数值大。这就是MED的威力。
实际项目中MED常用于跨运营商的多出口流量调度。两个AS之间有两条物理链路,一条带宽大、一条带宽小,为了把入流量引到带宽大的链路上,就在小带宽链路上设置较大的MED值,让对端AS优先从大带宽链路进来。需要注意的是,MED默认只在两个AS之间传递,不会传给第三个AS,除非开启了bgp always-compare-med等特殊开关。
3.5 优先级排序:从实验到理解
走完上面四组实验,我把BGP选路规则里最常用的几条按真实优先级顺序整理成一张表,方便你对照实验回忆:
| 优先级 | 规则名称 | 控制方式 | 影响范围 | 实验验证结果 |
|---|---|---|---|---|
| 1 | Preferred-Value | 本地手动指定 | 单台设备 | R2上指定下一跳3.3.3.3路径后,该路径变为最优 |
| 2 | Local_Preference | AS内部传递 | 整个AS | R3给路由打上LP=200后,R2切换到该路径 |
| 3 | AS_PATH | 路径长度对比 | 跨AS可见 | 给R3路径追加AS号后,R2重新选择R1直连路径 |
| 4 | MED | 告诉邻居进入本AS的开销 | 相邻AS之间 | R1路径MED=50后,R2放弃它改走R3路径 |
这四条规则基本覆盖了99%的日常运维和网络优化场景。剩下的什么“EBGP优先于IBGP”、“IGP开销最小”、“Router-ID最小”等规则,多数是前几条比较不出来的时候才轮到它们发言。
4. 实操中的关键细节与避坑指南
4.1 eNSP环境下最容易踩的坑
这个实验我实际在eNSP里跑了好几遍,有几个坑是几乎每次都会遇到的,先列出来给你排雷。
第一坑:设备型号选择不对。AR路由器如果用的是AR201或AR2220等型号,BGP功能是正常的;但如果选错成AR100系列(如AR1000),部分版本可能不支持BGP或者路由策略功能受限。我习惯用AR2220,模拟能力强,不会跑到一半设备CPU爆掉。
第二坑:OSPF邻居起不来,BGP随之起不来。这个坑一般出在没宣告接口或宣告网段错了。检查方法是先在每台设备上display ospf peer看邻居状态,再display ip routing-table看LoopBack地址是否互相可达。
第三坑:BGP邻居状态变成Active或Connect。多半是TCP 179端口不通,原因可能是接口IP配错,也可能是未指定connect-interface。你可以用display bgp peer verbose看详细的错误信息,里面有Last Error字段,方便定位。
第四坑:route-policy没生效。最常见的原因是方向搞反了。华为里peer X.X.X.X route-policy NAME import是处理从邻居收到路由,export是处理发给邻居的路由。很多新手在验证Local_Preference时容易把export参数当import用,结果改的地方不对,策略根本不生效。
4.2 验证选路结果的标准动作
每次配置完策略后,不要急着下结论,用下面这几个命令挨个排查,效率会高很多:
text复制# 1. 查看BGP路由表中的最优路径标记
display bgp routing-table 100.1.1.0/24
# 2. 查看某条路径的详细属性
display bgp routing-table 100.1.1.0/24 verbose
# 3. 查看具体路由策略是否命中
display route-policy
display ip ip-prefix
其中verbose输出会有大段详细信息,你最需要关注的是这四行:
text复制 Preferred-Value: 100
Local-Preference: 200
AS_PATH: 65001 65002 65003
MED: 50
这四个字段就是上面实验里四条规则的直接体现。哪个值和你预期不符,就说明策略配置有问题,回去检查route-policy的方向和匹配条件。
4.3 重新回到默认状态的快捷方式
实验做完后再做下一组实验,我建议你直接清掉BGP配置重新来,比手动一条条undo策略要干净利落。
比较快的重置方法:
text复制# 在每台设备上直接执行
reset bgp all
但注意,reset bgp all不会删除route-policy和peer配置。最彻底的方式:
text复制undo bgp 100
这条命令会把这台设备上的BGP配置全部清空,包括邻居、策略、network宣告,回到未配置状态。然后你重新配一遍基础BGP,用不了几分钟。这种方式最适合做实验时反复练习,而且还能加深你对基础配置的记忆。
不过实际生产环境千万别这么玩,生产设备上执行undo bgp等于把路由表全部撤掉,会造成大面积断网。这只是实验环境下的“一键重置”方案。
5. 常见问题与排查技巧实录
5.1 为什么我改了Local_Preference,选路结果还是没变?
这个问题出现频率非常高。多数情况是查看的路由和修改策略的路由不是同一条,或者策略应用的方向不对。
我见过一个典型的案例:有人想在R2上修改从R3收到的路由的Local_Preference,却在R2上用peer 3.3.3.3 route-policy XX export,这个方向是发给R3的,不是从R3收到的,策略根本不会匹配到R2收到的路由。正确的做法是在R2上用peer 3.3.3.3 route-policy XX import方向。
还有一种可能:你已经改了LP,但因为R2从R1学到的路径在AS_PATH、MED等属性上更有优势,而LP排在前面,理论上LP应该起决定作用。如果改了没生效,请确认你是用display bgp routing-table 100.1.1.0/24 verbose查看的,看到的LocPrf字段是否变成了预期值。如果字段值没变,说明策略没匹配上或没应用上。
5.2 AS_PATH追加后,为什么R2选路结果和预期完全相反?
这个坑我也踩过。在给R3配置apply as-path时,如果写成:
text复制apply as-path 65001 65002 65003
这条命令会把AS号加在现有AS_PATH的最前面。但如果你配置的是IBGP环境,原本AS_PATH为空,追加后变成65001 65002 65003,长度是3。这时R2会比较两条路径的AS_PATH长度,R1那条长度为0,所以R1胜出。
如果你期望R3胜出,就不能用AS_PATH这个规则。在IBGP内部,AS_PATH长度很多时候不管用,因为内部传递的路由本来就很少带AS号。所以AS_PATH规则更多用于EBGP场景。搞懂这一点,就不会在IBGP环境里对着AS_PATH浪费半天时间。
5.3 实验做完后,如何快速验证每条规则是否还有效?
如果你想快速回归一下,看看当前设备上有没有残留策略影响选路,可以用下面这组命令:
text复制# 查看所有BGP邻居上应用的路由策略
display bgp peer verbose | include peer|route-policy
# 查看本设备上定义的所有route-policy
display route-policy
# 查看所有前缀列表
display ip ip-prefix
如果发现哪条策略不需要了,手动undo掉:
text复制undo bgp 100
这相当于把所有策略和邻居全部清空,从零开始,回归干净环境。
6. 从实验到项目:选路策略的真实落地
实验做完了,下一步就是把实验里验证过的知识点变成实际项目里能用的方案。这里我分享三个常见场景,对应着实验里的不同规则。
场景一:内网访问外网的双链路负载与主备切换
公司有电信和联通两条出口,平时流量优先走电信,电信故障时自动切到联通。这种场景不用动态BGP,通常是静态路由加BFD、NQA联动实现。但如果你用的是BGP接入运营商,那么Local_Preference就派上了用场:在接入电信的路由器上,把从电信学到的默认路由Local_Preference调高(比如200),联通那条保持默认100,全公司设备就会自动优先走电信。电信链路断了,BGP邻居消失,相关路由自动撤销,流量自然切换到联通。
场景二:多运营商接入的入站流量调度
公司有两条线路,希望外部用户访问公司服务时优先走其中一条。路由策略可以配置在运营商侧,也可以配置在自建路由器上。如果是自建BGP,可以用MED属性。在两台边界路由器上分别给对端运营商设置不同MED值,MED小的那台更容易被对端选为入站路径。需要说明的是,MED对入方向流量的控制效果取决于对端AS是否愿意尊重你的MED,并不是所有运营商都会配合。
场景三:IBGP环境下的业务流量牵引
很多大型企业内部跑IBGP,业务网段通过BGP发布。如果你希望某台核心设备访问特定业务网段时走指定路径,Preferred-Value是最高效、最不扰民的方式。它只在一台设备上生效,不影响其他人,也不需要全局规划,特别适合临时调整和故障应急。
这三个场景不一定全都会用到,但理解了BGP选路规则本身,到了实际项目里遇到类似需求,你至少知道该用什么属性、在哪台设备上配置、会影响哪些流量。
我个人在实际操作中的体会是:BGP选路实验做一遍,远比看十遍文档管用。很多规则单独看文档都很抽象,只有亲手把Preferred-Value调大、看路由表里那条路径前面多了一个>标记的时候,才真正明白“这个属性优先级最高”是什么意思。如果你刚接触BGP,建议按文中的顺序把这四组实验都做一遍;如果你已经在做BGP相关项目,也可以在模拟器里把需求场景搭出来,先验证再上线,这是我一直坚持的工作习惯,实测下来能少踩很多坑。
