BGP路径属性详解:从LOCAL_PREF、MED到选路排障的完整指南
只要跟BGP打过交道就绕不开“BGP路径属性”这四个字。不管是排查一个跨AS的访问故障还是给客户规划双线冗余翻来翻去最终都要落到路径属性上LOCAL_PREF为什么是200不是100MED到底该发给哪个邻居AS_PATH前面多出来的那几位是哪来的。这篇文章我把这套概念从“它到底解决什么问题”到“选路时怎么参与”再到“日常排障怎么读”完整梳理一遍。适合刚接触BGP的网工也适合已经会配策略、但经常被属性细节卡住的人。看完你至少能明白属性不是一堆需要背的参数而是一套有设计逻辑的“路由签证系统”。1. 先说清楚路径属性到底是干什么的和IGP的路由度量有什么区别1.1 没有路径属性的BGP就是没有行李标签的航班很多教材一上来就讲BGP是路径矢量协议但“路径矢量”这四个字没多少人真正琢磨过。距离矢量协议告诉你“我离目标还有多少跳”链路状态协议告诉你“全网拓扑长什么样”而BGP告诉你的是这条前缀为了到达你这里已经经过了哪些AS、带上了哪些条件和标记。做个类比。你坐飞机转机托运行李上会贴一串标签出发地、经停站、目的地、有没有加急标记。中转站的工作人员不需要打开箱子重新称重只看标签就能决定行李该走哪条传送带。BGP也是这样——一个AS把前缀交给邻居时会把“这趟旅程的背景信息”写在路径属性里。下一个AS收到后先看自己的策略再决定是接受、修改还是拒绝这条路由。所以路径属性不是“锦上添花”的备注它就是BGP路由本身的组成部分。一条BGP路由前缀下一跳这一整套属性缺了属性选路和策略都无从谈起。1.2 路径属性不是“参数大杂烩”而是策略表达的语言理解了属性是什么还要理解为什么需要它。IGP比如OSPF、IS-IS选路看的是单一的技术度量开销最小、带宽最大、跳数最少。但BGP所在的互联网是由成千上万个自治域组成的AS与AS之间除了技术约束还有商业关系客户到运营商、运营商到运营商、对等互联。这些关系用“最短路径”表达不了。举个例子。某个运营商可能明确希望“客户路由永远优先于对等体路由”哪怕对等体路径在AS_PATH上更短。这种偏好是技术度量算不出来的只能通过路径属性来表达。BGP之所以能成为互联网的“粘合剂”靠的不是算法多精妙而是这套属性体系为策略提供了标准化的表达方式。记住这个定位IGP的度量是一条公式算出来的标量BGP的路径属性是一组可被策略读取、修改、传递的向量。理解了这个差别接下来看四个分类组就不会觉得枯燥了。2. 属性的四大家族强制/可选、传递/非传递背后的设计逻辑2.1 一张表看懂属性分类路径属性按两组维度分类一组是“知名还是可选”另一组是“传递还是非传递”。中间再套一个“强制还是自决”。所有属性都可以放进下面这张表里类别包含属性核心特征通俗理解知名强制ORIGIN、AS_PATH、NEXT_HOP每个BGP Update都必须携带所有路由器必须识别路由的“身份三件套”少一个都不行知名自决LOCAL_PREF、ATOMIC_AGGREGATE所有路由器都认识但不强制每次携带可按需出现的“高级选项”可选传递COMMUNITIES、AGGREGATOR不认识也能原样转发可以跨AS旅行的“贴纸标签”可选非传递MED、ORIGINATOR_ID、CLUSTER_LIST不认识就丢弃且不应传出本AS只在局部范围内有效的“内部备忘录”这张表不是随便划的每一格都对应一个设计意图。2.2 为什么要分“知名强制”和“可选非传递”从路由环回到策略边界先说“知名强制”。ORIGIN、AS_PATH、NEXT_HOP这三个属性承担的是BGP最基本的职责保证可达、防止环路、告诉邻居下一站是谁。如果某些路由器不认识这些属性整个BGP体系就崩塌了所以它们必须被所有实现识别且每条路由都必须携带。再说“可选传递”和“可选非传递”的差别这是最有意思的设计。当一台路由器收到一个它不认识的属性时规则是如果这个属性是传递的它必须原样转发给邻居如果不是传递的它可以直接丢弃。为什么这样设计因为互联网上有大量不同厂商、不同版本、不同自定义功能的设备在协同工作谁也无法保证所有设备都认识所有属性。Community就是典型的可选传递属性。它能在AS之间做约定我在入口给路由贴个标签你在出口匹配这个标签做动作。中间可能有几台老设备完全不认识Community但规则要求它们必须原样带过所以约定才能跨AS生效。而MED是可选非传递它表达的偏好只对“相邻的这一个AS”有意义你凭什么把自己的意见强加给第三个AS所以它在穿过边界后基本会被丢弃。这个边界意识是理解BGP属性最关键的一把钥匙。3. 四个每天都在用的核心属性逐一拆解3.1 ORIGIN路由来源的“出身证明”ORIGIN是最容易被忽略、但几乎每条路由上都带有的属性。它有三种取值IGP显示为i值0、EGP显示为e值1早期外部网关协议时代遗留现在基本绝迹、INCOMPLETE显示为?值2。用network命令通告的路由ORIGIN是IGP用redistribute把静态路由或直连网段导入BGP的ORIGIN是不完整?。这个“?”不带贬义只是表示“来源不是通过BGP的network方式显式声明的”。为什么要在意它因为选路时ORIGIN的优先级是IGP优于EGP优于INCOMPLETE也就是0小于1小于2。日常策略里ORIGIN很少单独成为决策因素因为它在选路十步里排得比较靠后。但实战中你会看到这种情况同一前缀有两条路径前几步的AS_PATH、LOCAL_PREF都完全一样最后是ORIGIN定的胜负。如果其中一条用redistribute引入另一条用network声明那i那条会胜出。所以别小看这个“出身”它是隐性决胜项。有个小经验在大型网络里用network声明自己的用户段是“政治正确”的做法它除了让ORIGIN好看还意味着你是显式、有意识地通告这个前缀。用redistribute虽然省事但后续排障时看到一堆“?”前缀你很难分清哪些是故意引入的、哪些是误操作维护成本很高。3.2 AS_PATH防环路的路由“签证记录”AS_PATH记录的是这条路由经过的AS序列形式上一左一右排开最左边的AS号是最近一次把路由通告给你的那个AS。每次路由跨越AS边界通告方的路由器都会把自己的AS号加到AS_PATH最前面就像护照上盖一个入境章。它的第一职责是防环。当一台路由器收到一条BGP路由发现AS_PATH里已经包含了自己的AS号说明这条路由自己之前已经发出去过了现在又绕了回来直接丢弃即可。这个机制简单、可靠是整个BGP防环体系的基础。AS_PATH的第二大用途是流量工程也就是AS PATH Prepending。做法是在通告给邻居的时候手动多插入几个自己的AS号让这条路径在别人看来“变长”。比如向某个邻居通告路由时set as-path prepend 64500 64500远端选路走到“最短AS_PATH”这一步时会觉得这条路径更长从而不太愿意选它。这常被用来做入站流量的主备切换。但这里有个绝大多数人都踩过的坑AS_PATH长度只是选路十步里的第四步。如果远端邻居在前面几步比如LOCAL_PREF已经决定了偏好你prepend得再多也没用。换句话说prepend是“投票”而不是“一锤定音”它只在远端没有更强策略时才能发挥作用。另外做路由聚合时一定要注意AS_SET。如果你用aggregate-address聚合路由但不带as-set聚合路由的AS_PATH会丢失成分路由的路径信息等于放弃了一个维度的环路检测。带了as-set路由器会把成分路由的AS号放进一个AS_SET集合环路防得更稳代价是AS_PATH长度会变长、可能影响选路。这个取舍要心里有数。3.3 NEXT_HOP跨AS寻路的“下一站”NEXT_HOP讲起来简单但它是BGP里最容易出“学了不用”问题的属性。BGP的NEXT_HOP规则是从eBGP学到的路由通告给iBGP时默认保留eBGP的下一跳地址从iBGP学到的路由通告给eBGP时改成自己的地址。这意味着iBGP域内的所有路由器都必须能通过IGP或直连路由到达这个“外部下一跳”BGP路由才会被放入路由表。这也是为什么大型网络里几乎必配next-hop-self。把所有iBGP会话都配上next-hop-self通告出去的下一跳统一改成自身设备的地址避免IGP里还需要同步一大堆外部下一跳地址。你可以想象一下如果不这么做每一台从eBGP学到外部路由的边界路由器都要想办法让全网IGP认识它那个外部对端的地址拓扑一复杂就是灾难。BGP还有一个硬性规则下一跳必须在IGP或直连可达否则路由根本不进路由表。我见过太多次“show bgp里明明有这条路由但路由表里没有”查到最后就是下一跳不可达。后面排障部分我会再详细讲这条排查链路。3.4 LOCAL_PREFAS内部唯一的“出口偏好”LOCAL_PREF是AS内部选路最重要的属性没有之一。默认值是100取值范围0到2的32次方减1数值越大越优。它只在AS内部传递绝不会跨eBGP会话通告出去所以它管的是“我这个AS怎么出去”而不是“别人怎么进来”。典型用法是这样边界路由器从上游A和上游B各收到一条去往同一目标的路由在入方向策略里给上游A的路径打LOCAL_PREF 200给上游B的打100。因为LOCAL_PREF会随iBGP通告到AS内所有路由器所以整个AS的转发路径就会统一偏好A作为出口A故障时才切到B。这就是多出口出口选路的标准做法。很多人分不清LOCAL_PREF和Weight。Weight是主流设备厂商的私有属性只对单台路由器生效不出iBGP、不出eBGP价值在于“在本设备上优先选某条路”。LOCAL_PREF是标准属性能随iBGP扩散到整个AS。如果你的网络只有一台边界路由器用Weight当然省事只要有两台以上设备想让全网行为一致就必须用LOCAL_PREF。4. MED与COMMUNITIES一个管“入口”一个管“标签”4.1 MED多出口场景下的入站流量引导MEDMulti-Exit Discriminator多出口鉴别属性是可选非传递属性数值越小越优。它一般由“前缀所属的那个AS”发出来作用是告诉邻居如果你想访问我我这好几个入口里你最好从哪一个进。举个例子。你的AS与某运营商有两条互联链路你想引导对方回程流量走主链路。做法是在向对方通告自己的前缀时主链路上带的MED是50备链路上带200。对方选路走到MED这一步会比较这两条路径选择MED较低的50于是回程流量就走主链路。这就是入站流量工程的标准姿势。但MED有几个边界条件必须搞清楚否则策略做了等于白做。第一默认情况下只有来自同一个邻居AS的路由之间才会比较MED。两个不同邻居AS给你通告的路由MED默认不互相比较需要配置always-compare-med才比。第二MED是非传递的它传到相邻AS就到头了绝对不会继续往第三个AS传。第三路由没带MED时不同厂商的处理方式可能完全不同很多商用设备的默认行为是按0处理也就是当成最优另一部分厂商按无穷大处理当成最差。跨厂商对接时这个差异能直接让你的主备调度完全反向。我自己的习惯是凡是依赖MED做入站调度的场景先把双方对“缺失MED”的处理方式对齐再上线策略。别问我怎么知道的这个坑我至少跳过两次。4.2 COMMUNITIES给路由贴的“群体标签”Community是可选传递属性标准Community是32位数值通常写成AA:NN格式比如65400:100。它本身不影响选路只是一张贴在路由上的标签。真正干活的是策略路由器匹配到某组Community后再执行改LOCAL_PREF、过滤、改下一跳等动作。Community的魅力在于“标签”和“动作”可以完全分离。边界路由器入方向给路由打标签核心路由器出方向按标签做决策打标签和在策略位置不用是同一台设备。因为是可选传递属性不认识它的中间设备也会原样带过所以Community能跨AS使用。运营商之间大量使用Community做路由策略的标准化比如“给客户打上某个Community表示这条路由要优先处理”。有几个公认的知名Community值要记住no-export表示这条路由不要传出本ASno-advertise表示不要通告给任何BGP邻居包括iBGPlocal-as表示不要传出本联盟nopeer表示不要发给对等体。用途上no-export最常用比如你把某条路由从客户那边接收后希望它只在本地AS内传播不打到上游去就打no-export。要特别提醒Community不会自动跟着Update走你必须在对端会话上配置send-community。这个参数在iBGP和eBGP上都要显式开很多人配了策略、打了标签结果对端show bgp里完全没有Community查到最后就是忘了send-community一个字。另外老格式16位AS号已经不够用了新网络建议直接考虑大Community的兼容性规划。4.3 实际配置中MED和Community的“配合演出”MED和Community经常一起出现。一个比较有代表性的场景是运营商同时接入多个上游给不同上游的入方向路由打不同的Community比如65400:100表示A上游、65400:200表示B上游然后在中转/出口策略上针对这些Community统一调整路由的LOCAL_PREF或过滤动作。这样无论新增多少条链路策略只需要在“标签定义”和“动作策略”两层维护不用逐条前缀去配。这背后是一个工作方式的转变从“逐条改路由”变成“按属性分组改路由”。Community就是分组的手段。等你维护的网络大了前缀多了就会理解为什么说“BGP策略的本质是属性操作”。5. 聚合与反射场景下的“配角”属性ATOMIC_AGGREGATE、AGGREGATOR、ORIGINATOR_ID、CLUSTER_LIST5.1 路由聚合后的两个标记ATOMIC_AGGREGATE与AGGREGATOR这四个属性不像前面几个那么高频但在特定场景下能救命。先说ATOMIC_AGGREGATE。当一台路由器把多条具体路由聚合成一条聚合路由时如果各成分路由携带的属性不一致比如AS_PATH、MED各不相同聚合路由必然丢失部分信息。此时路由器会带上ATOMIC_AGGREGATE标记等于向所有下游宣告这条路由是聚合结果属性信息不完整你们不要再试图还原里面的细节了。它是知名自决属性大家都能识别但只有聚合场景才出现。AGGREGATOR是可选传递属性记录聚合操作是谁干的聚合者的AS号和Router-ID。排障时如果你看到某条聚合路由有明显异常先show bgp找到AGGREGATOR定位到具体设备再去检查它的聚合配置。这个排在选路里虽然不起作用但对运维查问题价值极大。有一个场景能把这两个属性串起来你发现某条前缀被聚合后“吞掉”了更优的路径下游选路结果莫名其妙。这时先看聚合路由上有没有ATOMIC_AGGREGATE如果有说明聚合时确实丢了细节属性属于预期内损失如果没有说明聚合配置可能有问题比如as-set没带。属性在这里就是诊断线索。5.2 路由反射器的两个防环令牌ORIGINATOR_ID与CLUSTER_LISTiBGP为了扩展性会部署路由反射器但反射拓扑会带来环路风险。ORIGINATOR_ID和CLUSTER_LIST就是专门为反射器设计的防环工具。ORIGINATOR_ID是可选非传递属性。当路由反射器从客户端收到一条路由并反射给其他客户端时它会把这条路由的原始发起者的Router-ID写进ORIGINATOR_ID。如果一台反射器收到了ORIGINATOR_ID等于自己Router-ID的路由说明这条路由是它自己发出去的又绕了回来直接丢弃。CLUSTER_LIST是可选非传递属性存的是一个“簇ID列表”。每个路由反射器可以配置自己的Cluster-ID反射时把自己的Cluster-ID加入列表并传给下游。如果某台设备收到的路由里CLUSTER_LIST中包含了自己所在簇的Cluster-ID说明形成了反射环丢弃。在分层反射器架构里CLUSTER_LIST就是防止跨簇环路的令牌。这两个属性一般不会出现在日常策略里但它们决定了路由反射器拓扑能不能稳定工作。配置多级反射时如果不理解这两个属性很容易出现“路由对外明明是通的内部却莫名震荡”的诡异故障。6. 从属性到决策BGP选路十步的完整链路6.1 主流实现选路顺序全表属性讲完了现在把它们串成完整链路。BGP收到同一条前缀的多个路径时会按固定顺序比较一旦某一步分出胜负后面几步就不比了。主流商用设备的顺序大致如下顺序比较内容比较方向备注1Weight越大越优设备私有属性仅本设备有效2LOCAL_PREF越大越优AS内部选路的核心开关3本地起源路径优先network、aggregate、redistribute产生的路由4AS_PATH越短越优prepend可改变长度5ORIGINIGP优于EGP优于INCOMPLETE值0优于1优于26MED越小越优默认只在同一邻居AS间比较7eBGP优于iBGPeBGP优先部分实现细节略有差异8到NEXT_HOP的IGP度量越小越优下一跳必须是IGP可达的9老路由优先/等价多路径细节因厂商而异eBGP下通常先学到者优先10Router-ID越小越优最终裁决用来保证一定能分出结果这张表的顺序理解比背诵重要。排在前面的属性一旦分出胜负后面的属性连比较的机会都没有。所以做策略时先想清楚你想让“哪个环节”定胜负想引导整个AS的出口选择就改LOCAL_PREF想引导对端回程就改MED或AS_PATH想对单台设备做局部偏好就改Weight。用错了环节策略再复杂都是空转。有个细节值得单独说第8步“到NEXT_HOP的IGP度量”。很多人在eBGP/iBGP多链路场景下忽略它。即使前面AS_PATH和MED完全一样路由器还是会选择“去往下一跳的IGP度量最小”的路径。在某些双归场景下这会导致流量从你没想到的路径出去纯粹因为IGP这边更近。6.2 两个最容易踩的选路认知误区第一个误区“AS_PATH越短越好所以我疯狂prepend就能改变对端选路。”前面已经说过AS_PATH只是第四步远端如果有LOCAL_PREF策略、有本地起源路由它根本轮不到AS_PATH出场。prepend是对“没有更强策略的环境”生效的工具不是万能遥控器。第二个误区“MED越低越好所以我给所有路径都调低。”这里有两个问题。首先默认情况下不同邻居AS的MED根本不比较你调半天可能等于没调。其次MED是“你提的意见”对端完全可以不理——它可以在入方向直接忽略MED或者用LOCAL_PREF把你要的效果覆盖掉。在跨运营商场景对方的选路策略你是控制不了的。所以做选路设计时正确的思路是先判断你要影响的是“本AS”还是“对端AS”。本AS用LOCAL_PREF加Weight对端AS用MED加AS_PATH。方向搞反了哪怕配置写得再漂亮实际流量也不会按你想的走。7. 调属性时的实操心得和排查工具7.1 先把命令学明白show bgp怎么读属性策略调得再顺最后都要落到命令行验证上。以常见的BGP路由表输出为例Network Next Hop Metric LocPrf Weight Path * 10.1.0.0/16 192.0.2.1 100 0 64500 65000 i每一列对应一个核心属性Network是前缀Next Hop是NEXT_HOPMetric列是MED空白表示对端没带MEDLocPrf是LOCAL_PREFWeight是WeightPath是AS_PATH结尾的i表示ORIGIN是IGP。展开单条前缀用show bgp ipv4 unicast加具体前缀能看到更完整的属性列表包括Community、聚合相关信息。看表时有个习惯要养成先看LocPrf列再看Path列最后才看Metric。因为选路顺序里LOCAL_PREF排在AS_PATH和MED前面它才是多数情况下真正决定胜负的属性。很多人一上来盯着MED看看半天看不明白为什么自己的MED更小却不被选中——因为前面几步已经分完胜负了。另外很多设备上received-routes这个命令默认查不到内容要在邻居配置里提前打开soft-reconfiguration inbound或启用BGP表策略。advertised-routes一般不需要这些前置条件可以直接用。我见过有人以为路由没收到最后发现只是没开soft-reconfiguration虚惊一场。7.2 常见误配置和排查链路这里分享几个经典问题的完整排查链路。问题一iBGP路由“学到了但不生效”。第一步show bgp查这条前缀确认它确实在BGP表里且路径状态是有效的。第二步看该条路由的NEXT_HOP字段。第三步show ip route查这个下一跳在不在路由表里。如果不在大概率就是IGP没有同步这个外部下一跳地址或者iBGP没有配置next-hop-self。第四步如果下一跳可达但路由还是不生效再查是不是有入方向路由策略把这条前缀过滤了。问题二MED调了但回程流量不切换。第一步确认对端设备与你是不是同一个邻居AS。如果不是默认不会比较MED需要协调或开always-compare-med。第二步确认对端有没有忽略MED的策略。有些运营商在入方向会直接忽略MED或按自己的策略覆盖。第三步抓取对端收到的路由属性确认MED确实传过去了、没被中间策略删掉。很多时候不是你的MED没生效而是它根本没出现在对端的BGP表里。问题三Community在跨设备后“神秘消失”。第一步在本端show bgp看路由的Community还在不在。第二步show bgp neighbor看 advertise给对端的路由里Community在不在。第三步检查邻居会话有没有开send-community以及出方向的route-map里有没有对Community做删除动作。Community消失九成原因就这两个没开send-community或者route-map里有配置把它清掉了。还有一类高频错误和AS_PATH正则表达式有关。比如要用正则匹配“从哪个AS起源的路由”初学者容易写成_65000_这个表达式匹配的是AS_PATH里任意位置含65000不一定表示“起源”。想表达“起源于AS65000”要写成_65000$想表达“本AS直接邻居是65000”要写成^65000_。正则写错策略可能匹配到完全不是你预期的那批路由危害比不匹配更大。7.3 一点经验之谈做了几年网络运维我对路径属性最大的感受是它们本身不难真正难的是“在设计阶段想清楚每个属性应该在哪里发挥作用”。每次做策略我都会先写下这个问题的答案我要影响的是本AS的出口还是对端的回程决定好方向再决定用哪个属性、在哪台设备、哪个方向应用。还有一个建议是给属性值做统一规划。LOCAL_PREF用哪些数值段表示主用、哪些表示备用MED用哪些数值段区分主备链路Community用哪些编码区分客户等级都写成一份规划表。前期看起来多余等到网络大了、策略多了这份表就是你的救命稻草。否则半年后你自己看到一条LOCAL_PREF 150的路由都想不起来当初为什么是150。最后说个小技巧变更属性策略前先把BGP表的基线留一份。属性一变选路会重新计算结果可能波及大量前缀。我在一次调整MED的操作里就因为没留基线改了参数后发现回程流量翻动得厉害却分不清哪些是预期变化、哪些是意外。现在凡是涉及MED、LOCAL_PREF、AS_PATH、Community的变更我都先抓全局BGP表改完再diff一次。这个习惯帮我省下的排障时间远超抓基线的那几分钟。