BGP路由聚合原理与华为设备配置实验,解决路由表膨胀问题 BGP路由聚合原理和实验华为设备是我觉得网络工程里特别值得花时间搞透的一块内容。干运维或者做网络设计的都有体会BGP路由表一旦膨胀起来设备CPU、内存、收敛速度全部跟着遭殃。尤其是在多出口、多AS的环境里路由条目几千上万条每台路由器都要维护、都要计算压力非常实在。这篇文章我就从原理到华为设备上的配置实验把BGP路由聚合完整过一遍。不管你是刚接触BGP的新人还是已经被路由表膨胀折磨过的老手应该都能从里面找到有用的东西。我先说清楚这篇要讲什么聚合是什么、为什么能减小路由表、华为设备上如何配置、实验效果怎样、以及聚合之后会踩到哪些坑。重点放在操作和验证不搞那种念PPT式的理论堆砌。1. BGP路由表膨胀时聚合为什么值得做1.1 路由表膨胀带来的真实压力BGP是全球互联网的“寻路系统”但它有个天生的特点路由条目会不停增长。各家运营商、云厂商、企业出口都会宣告自己的网段全球BGP路由表条目数早就突破了九十万条的大关而且还在涨。普通企业网可能没这么夸张但只要你的设备接入运营商运营商下发的路由就可能多达几十万条。我见过一台低端路由器接了运营商的BGP对等体之后路由条目上来设备CPU直接飙到80%以上的情况。BGP本身就是增量更新协议但如果邻居重连、路由策略调整、表项翻动设备需要重新处理大量Update报文。TCAM空间有限路由表放不下就只能软件转发性能断崖式下跌。更麻烦的是路由条目越多BGP收敛越慢。链路一抖动整个网络几十秒甚至几分钟不稳定业务影响就很明显了。路由聚合在这种情况下是成本最低、见效最快的优化手段。它把多个具体网段合并成一条聚合路由对外宣告上游设备只需要维护一条而不是几十条路由表规模瞬间降下来。1.2 聚合的工作逻辑把多条明细合并成一条聚合的本质是用CIDR无类别域间路由规则把一组连续的子网合并成一条更短前缀的路由。比如你内部有172.16.1.0/24、172.16.2.0/24、172.16.3.0/24这三个网段对外完全可以用172.16.0.0/16一条路由来表达。为什么能这么合并因为这三个/24的网段都在172.16.0.0/16这个地址块范围内。路由器转发时按最长前缀匹配只要外部没有更具体的路由发给这些网段的数据都会匹配到172.16.0.0/16这条聚合路由流量就能到达内部网络。打个比方你寄快递的时候不需要写完整的“省-市-区-街道-门牌号”如果收件人集中在一个城市你只写“某省某市”也能保证包裹先送到这个区域再分发。聚合就是这个道理——对外不暴露内部细节只暴露一个足够定位的地址范围。在BGP里做聚合还有一个额外的好处路由条目减少之后链路发生故障时受影响的路由数量也少翻动次数下降网络稳定性自然就上来了。1.3 聚合的代价与适用边界聚合不是越多越好。超网聚合会让路由失去精确性可能带来次优路径甚至黑洞风险。最典型的场景你的AS内有两个不连续的网段比如172.16.1.0/24和172.16.3.0/24分别在不同位置接入。如果强行把它们聚合为172.16.0.0/16对外通告对端路由器会认为172.16.2.0/24这个不存在的网段也在你这里。一旦有流量访问172.16.2.0/24就会全部发给你而你内部并没有这个网段的真实出口数据包只能被丢弃。所以选择在哪里聚合、聚合到什么程度必须结合实际网段规划和真实拓扑来定。在企业出口、AS边界做聚合是主流做法在核心层内部为了精细选路反而要保留明细。2. 华为设备BGP聚合的底层机制2.1 先搞清楚BGP路由是怎么发布的要理解聚合得先知道BGP路由是怎么进入路由表的。华为VRP平台上BGP路由来源主要有两种一是用network命令把IP路由表中的某条路由引入BGP二是用import-route命令把IGP或静态路由引入BGP。用network命令有个硬性条件这条路由必须已经存在于设备的IP路由表中。也就是说设备得先有一条指向某个目标网段的可用路由才能把它“翻译”成BGP路由通告给邻居。用import-route则没有这个限制但它会把路由表中所有匹配的路由都引入控制粒度相对粗一些。BGP路由进入BGP路由表之后设备会运行BGP选路规则选出最优路由然后才通告给邻居。聚合发生的位置就在BGP路由表生成的过程中——设备把多条明细BGP路由汇总成一条聚合路由放进BGP路由表再对外发布。2.2 aggregate命令的完整形态华为设备上手动聚合使用aggregate命令。命令格式如下aggregate ip-address { mask | mask-length } [ as-set | attribute-policy route-policy-name | detail-suppressed | origin-policy route-policy-name | suppress-policy route-policy-name ]常用的可选参数有三个必须理解清楚参数作用使用场景detail-suppressed抑制明细路由的通告只通告聚合路由希望上游只看到一条汇总路由时as-set在聚合路由的AS_PATH中携带所有明细路由的AS号集合明细路由来自多个AS时防止环路attribute-policy为聚合路由设置独立的BGP属性调整MED、LocalPref、Community等如果不加detail-suppressed设备会同时通告聚合路由和明细路由。这样上游路由表里既有汇总条目又有明细条目聚合效果大打折扣。要做“干净的聚合”这个参数是关键。华为设备还有一个summary automatic命令属于自动聚合。它能把BGP路由表里的子网自动聚合为自然类网络。比如172.16.1.0/24、172.16.2.0/24会被自动汇总为172.16.0.0/16B类地址的默认掩码。但它有几个限制只对通过import-route引入的路由生效对network宣告的路由不生效且只能按自然类掩码聚合不能自定义聚合范围。实际工程中手动aggregate用得更多控制粒度更精确。2.3 AS路径属性与防环逻辑BGP防环依赖AS_PATH属性。每条BGP路由经过一个AS该AS号就会被追加到AS_PATH中。收到路由的设备如果发现AS_PATH里包含自己的AS号就知道这条路由绕了一圈回到自己这里会直接丢弃这就是BGP最基本的防环机制。聚合之后问题就来了。假设AS 200里有两条明细路由10.1.1.0/24和10.1.2.0/24分别来自AS 300和AS 400设备把它们聚合为10.1.0.0/16。如果聚合时丢失了这些明细的来源AS信息AS_PATH只剩下一串不完整的序列对端就无法判断这条聚合路由是否经过了某个AS环路检测就失效了。as-set参数就是解决这个问题的。聚合路由会携带一个AS集合把所有被聚合明细路由的AS号都打包进去。在华为VRP的显示中AS_SET部分会用方括号标识。例如* 10.1.0.0/16 192.168.12.1 0 100 0 100 [300 400]i对端看到这个聚合路由时知道它包含了AS 300和AS 400的来源信息如果自己的AS号出现在这个集合中同样可以判定环路并丢弃。所以结论就是只要聚合的明细路由跨越了多个AS就必须带as-set。3. 实验两条命令让路由表大幅瘦身3.1 实验拓扑与地址规划这个实验我建议在模拟环境或者真实设备上都跑一遍不复杂但能完整看到聚合前后的变化。拓扑需要三台路由器R1AS 100模拟内部网络侧下挂多个用户网段R2AS 200模拟外部网络侧作为R1的EBGP邻居R3AS 300辅助验证多AS场景可选但建议加上地址规划如下设备接口IP地址用途R1GE0/0/0192.168.12.1/24连接R2R1LoopBack01.1.1.1/32管理/标识地址R1静态路由172.16.1.0/24、172.16.2.0/24、172.16.3.0/24模拟用户网段R2GE0/0/0192.168.12.2/24连接R1R2LoopBack02.2.2.2/32管理/标识地址为了让network宣告生效需要在R1上先把三个模拟网段的静态路由写好指向Null0即可这样它们会出现在IP路由表中BGP才能引入ip route-static 172.16.1.0 255.255.255.0 NULL0 ip route-static 172.16.2.0 255.255.255.0 NULL0 ip route-static 172.16.3.0 255.255.255.0 NULL0这是实验演示常用的技巧现实中这些网段可能是直连网段或通过IGP学习到的明细路由原理一样。3.2 基础配置与EBGP邻居建立R1的基础配置如下sys sysname R1 interface GigabitEthernet0/0/0 ip address 192.168.12.1 255.255.255.0 interface LoopBack0 ip address 1.1.1.1 255.255.255.255R2的基础配置如下sys sysname R2 interface GigabitEthernet0/0/0 ip address 192.168.12.2 255.255.255.0 interface LoopBack0 ip address 2.2.2.2 255.255.255.255BGP配置R1属于AS 100与R2建立EBGP邻居并宣告三个网段bgp 100 peer 192.168.12.2 as-number 200 network 1.1.1.1 255.255.255.255 network 172.16.1.0 255.255.255.0 network 172.16.2.0 255.255.255.0 network 172.16.3.0 255.255.255.0R2属于AS 200配置EBGP邻居bgp 200 peer 192.168.12.1 as-number 100配置完成后在R2上查看邻居状态display bgp peer正常情况下邻居状态应该是Established。如果一直是Connect或Active先检查地址配置和防火墙策略这是BGP排障最基础的步骤。3.3 宣告明细路由观察聚合前的路由表邻居建立后在R2上查看BGP路由表display bgp routing-table此时应该能看到来自R1的4条路由BGP Local router ID is 2.2.2.2 Status codes: * - valid, - best, d - damped, h - history Network NextHop MED LocPrf PrefVal Path/Ogn * 1.1.1.1/32 192.168.12.1 0 100 0 100i * 172.16.1.0/24 192.168.12.1 0 100 0 100i * 172.16.2.0/24 192.168.12.1 0 100 0 100i * 172.16.3.0/24 192.168.12.1 0 100 0 100i可以看到三条172.16.x.0/24的明细路由Path/Ogn显示100i表示来自AS 100、起源为IGP。此时R2的路由表中维护了三条几乎同源的明细路由。如果上游设备很多这个数量会被无限放大。3.4 配置聚合并验证效果现在在R1上配置手动聚合把三个/24聚合为一个/16同时使用detail-suppressed抑制明细通告并加上as-setbgp 100 aggregate 172.16.0.0 255.255.0.0 detail-suppressed as-set配置完成后在R1上查看BGP路由表display bgp routing-table你会看到BGP路由表中多了一条聚合路由同时原来的三条明细路由仍然存在于BGP路由表中detail-suppressed只是抑制向邻居通告并不删除本地路由表中的明细BGP Local router ID is 1.1.1.1 Status codes: * - valid, - best, d - damped, h - history Network NextHop MED LocPrf PrefVal Path/Ogn * 1.1.1.1/32 0.0.0.0 0 100 0 100i * 172.16.0.0/16 0.0.0.0 0 100 0 100i * 172.16.1.0/24 0.0.0.0 0 100 0 100i * 172.16.2.0/24 0.0.0.0 0 100 0 100i * 172.16.3.0/24 0.0.0.0 0 100 0 100i关键看R2收没收到聚合路由。在R2上再次查看BGP路由表display bgp routing-table此时你会发现三条明细路由都消失了只剩一条聚合路由BGP Local router ID is 2.2.2.2 Status codes: * - valid, - best, d - damped, h - history Network NextHop MED LocPrf PrefVal Path/Ogn * 1.1.1.1/32 192.168.12.1 0 100 0 100i * 172.16.0.0/16 192.168.12.1 0 100 0 100i这就是聚合的直接效果。原来三条明细变成一条聚合R2路由表减少了2条路由。如果实际网络里有几十条、几百条连续网段压缩效果会非常可观。在R2上查看聚合路由的属性display bgp routing-table 172.16.0.0能看到它的AS_PATH等信息。由于三个网段都来自AS 100Path/Ogn显示为100i。如果明细来自多个AS这里就会显示方括号形式的AS集合。3.5 自动聚合实验对比再看华为的自动聚合。在R1上取消手动聚合改用summary automaticbgp 100 undo aggregate 172.16.0.0 255.255.0.0 summary automatic你会发现一个现象network宣告的三条明细完全没有被聚合。因为前面说过summary automatic只对import-route方式引入的路由生效。如果想把实验做完整可以再配一条import-route staticbgp 100 import-route static这时172.16.x.0/24的明细会以import-route方式进入BGPsummary automatic就能把它们自动聚合成172.16.0.0/16。但由于自动聚合只能按照自然类掩码无法精确控制聚合范围实际工程中我很少直接用这个命令手动aggregate才是主流方案。4. 聚合后的故障场景与排查速查4.1 黑洞路由聚合网段内部有空洞前面提过不连续网段强行聚合会产生黑洞。这里给一个具体的实验场景R1只有172.16.1.0/24和172.16.3.0/24两个网段但聚合成了172.16.0.0/16。外部网络R2访问172.16.2.0/24时R2只有一条聚合路由它会把数据发给R1但R1实际上没有172.16.2.0/24的出口数据就被悄悄丢弃。验证方法是在R2上ping目标是不存在的172.16.2.1观察丢包然后在R1上使用tracert或抓包工具定位数据包是否被丢弃。解决套路有三类网段规划时保证被聚合的地址块连续不留空洞在聚合设备上配置指向Null0的黑洞路由让异常流量在本地直接丢弃而不是在网络上漫无目的地绕圈通过路由策略只对实际存在的子网做聚合通告比如使用suppress-policy精确控制哪些明细被抑制华为设备上配置黑洞路由的命令ip route-static 172.16.0.0 255.255.0.0 NULL0这条路由能让匹配聚合网段但无具体出口的流量在本地被丢弃避免更复杂的环路问题。4.2 聚合环路没有as-set很容易翻车聚合环路是最容易踩的坑之一。假设AS 100内有两台边界路由器BR1和BR2都配置了聚合。BR1从AS 200学到了一条明细路由本地聚合后通告给BR2BR2也做了同样的聚合又把聚合路由通告回BR1。如果没有as-setBR1收到BR2的聚合路由时AS_PATH里看不到自己的AS号因为聚合把AS_PATH弄丢了就会把它当作一条全新的路由收下路由信息就可能在两台路由器之间互相传递形成路由环路。判断方法很直接查看BGP路由表如果一条聚合路由的AS_PATH里看不到自己AS应有的位置或者路由表条目反复翻动、AS_PATH不断变化就要怀疑环路。用display bgp routing-table多次间隔查看观察是否出现重复的聚合条目。华为设备上查看路由翻动状态可以用display bgp routing-table statistic如果某条路由的翻动次数异常偏高基本可以确认环路或路由震荡。解决办法就是所有跨AS聚合一律携带as-set参数并且在边界设备上配合BGP路由过滤只接收期望的邻居通告路由。用as-path-filter也能过滤掉包含特定AS号的聚合路由比如ip as-path-filter 10 deny ^100这样能防止来自自己AS的聚合路由被错误接收。4.3 次优路径与属性调整聚合路由的下一跳和属性继承规则有时候会“继承错对象”。当多条明细路由都被聚合时聚合路由默认继承其中最优明细的路径属性。如果内部不同网段的最优出口路径不一致聚合后外部访问某些网段就可能绕远路。比如内部有两个运营商出口网段A走出口1更近网段B走出口2更近。聚合后只保留了一条聚合路由外部流量全部流向同一个出口网段B的流量就可能走次优路径。这时候需要用attribute-policy给聚合路由单独设置路径属性route-policy AGG_ATTR permit node 10 apply med 200 apply local-preference 150 bgp 100 aggregate 172.16.0.0 255.255.0.0 as-set attribute-policy AGG_ATTR通过attribute-policy可以手动调整聚合路由的MED、LocalPref、Community等让选路结果更可控。origin-policy和suppress-policy则用来精确控制哪些明细路由参与聚合、哪些明细被抑制灵活度更高。4.4 排查命令速查聚合相关的日常排障我用得最多的命令就是下面这些命令作用display bgp routing-table查看BGP路由表全貌确认聚合路由是否存在display bgp routing-table 172.16.0.0查看单条聚合路由的详细属性包括AS_PATH、Origin、MEDdisplay bgp routing-table as-set查看所有携带AS_SET的路由检查聚合路由的as-set情况display ip routing-table 172.16.0.0确认聚合路由是否进入IP路由表用于判断黑洞和转发路径display bgp peer verbose查看邻居状态和收发的路由数量统计display bgp routing-table statistic查看路由总数和翻动统计辅助判断环路和震荡terminal debugging bgp update打开BGP更新报文调试慎用生产环境慎开日志量极大用的时候注意display bgp routing-table看到的是BGP路由表display ip routing-table看到的是全局IP路由表两者有区别。聚合路由只有在下一跳可达或者有对应静态路由时才会出现在IP路由表中参与转发。5. 聚合策略设计的几个心得5.1 在哪个设备上做聚合聚合尽量在AS边界设备上做而且越靠近明细路由的源头越好。源头聚合能让明细在最早期被归纳后续传递过程中都不会膨胀。比如内部有很多子网需要对外通告那么在出口路由器或者汇聚路由器上就完成聚合不要让明细一路传到骨干节点。内部核心设备之间不建议随意聚合。核心层本来就需要精确选路如果过早聚合内部路径优化反而变得困难。很多实际故障都是因为在一台不应该做聚合的设备上配置了聚合导致对内对外路由全部失真。5.2 聚合与路由策略配合聚合的威力在配合路由策略时才能完全发挥。针对不同邻居可以宣告不同粒度的路由同一台设备对内部邻居保留明细对外部邻居只通告聚合。用outbound方向的filter-policy就能实现bgp 100 peer 10.0.0.2 as-number 200 peer 10.0.0.2 route-policy EXPORT_AGG export在EXPORT_AGG里用if-match ip-prefix匹配聚合路由放行它抑制明细路由。这样既保证了内部选路精确又让外部路由表保持精简。聚合还可以和Community配合使用。比如给聚合路由打上特定Community在出口设备上识别这个Community来决定是否通告给某个邻居。这种设计在网络规模变大之后会非常实用。最后再分享一个我在实际调试中积累的小技巧。配置聚合之前先统计一下当前BGP路由表的明细条数display bgp routing-table | count聚合生效后再看一次对比两条命令的输出结果你就能直观量化这次聚合给路由表降了多少条。我在好几次网络优化项目里都这么干汇报数据时直接用这个数字比空口说“优化了性能”有说服力得多。BGP聚合这个功能用好了是路由表瘦身的神器用错了也可能引发黑洞和环路。建议你在实验环境把这些命令和场景完整跑一遍特别是as-set和detail-suppressed的区别、自动聚合和手动聚合的差异亲手验证过才不会在真实网络里踩坑。