CEF对BGP负载均衡的影响

前几天做了几个实验,想研究一下BGP的负载均衡。本来BGP的负载均衡实现起来也不难,在特定点环境下,多条到达同一目的地的路由符合选路原则的前八条,并且修改BGP maximum-paths,基本上就可以实现BGP的负载均衡了,下面写一写我做这个实验的一点点心得吧;-)

这是一个:Dual-Homed to one internet service的环境

bgp_load_sharing3 AS 65001中的R1通过两条串行链路连接连接到ISP AS 65023中的两个路由器R2、R3上。其中R1,R3上的LoopBack口代表了两个AS的内部网络,而我们的目的就是让从来自AS 65001的数据流分别通过两个出接口到达ISP内部的网络。

底层配置我就不写了,写一下关键的R1上的配置吧

R1:

router bgp 65001
no synchronization
bgp router-id 1.1.1.1
bgp log-neighbor-changes
network 1.1.1.1 mask 255.255.255.255
neighbor 12.0.0.2 remote-as 65013
neighbor 13.0.0.3 remote-as 65013
maximum-paths 2
no auto-summary

上面的配置中,与平常的BGP配置唯一不同之处就是多了 [maximum-paths 2]这条命令,而这条命令就是修改BGP将多少条到达同一目的地代价相同的路由放进路由表中(需要符合我开始说的那几个条件)。

完成三个路由器的配置后可以发现R1的路由表上到达3.3.3.3的网络拥有两个出口了:

1.0.0.0/32 is subnetted, 1 subnets
C       1.1.1.1 is directly connected, Loopback0
3.0.0.0/32 is subnetted, 1 subnets
B       3.3.3.3 [20/0] via 13.0.0.3, 00:00:08
[20/0] via 12.0.0.2, 00:00:08
12.0.0.0/24 is subnetted, 1 subnets
C       12.0.0.0 is directly connected, Serial1/0
13.0.0.0/24 is subnetted, 1 subnets
C       13.0.0.0 is directly connected, Serial1/1

通常,要验证路由是否发生负载均衡,可以使用Traceroute命令对数据的转发路径进行跟踪,但有一点需要注意的是,我们无法透过该命令知道数据时是去往目的地时经过某地,还是在返程是经过某地。所以,为了更清楚地了解数据的流动情况我们需要进行抓包验证

我们尝试在R1上以LoopBack 0接口地址为源地址ping 3.3.3.3,如无意外是可以ping通的。在cisco的官方文档介绍BGP的负载均衡时,验证BGP负载均衡是否实现的依据是:1.路由表中是否有标记为B并且到达同一目的有多个出口的路由;2.使用traceroute命令时出现了R1上两个物理出口的地址;从上面这两个信息中基本可以判断在路由层面上已经实现了负载均衡了,但是在数据面上呢?接下来我们在R1上分别ping另一个AS内的网络,并在R1的两个出口上抓一下包,看看数据包的流动情况。

我们需要在Dynagen的控制台上使用Capture命令同时抓取R1两个接口上的数据,命令:capture R1 s1/0 r1s0.cap HDLC capture R1 s1/1 r1s1.cap HDLC
然后在R1上:ping 3.3.3.3 source lo0 repet 10
等待ping过程结束后,这时停掉R1上的数据抓取,避免抓取过多无用的数据包。命令:no capture R1 s1/0 no capture R1 s1/1
现在我们来打开两个cap文件,这里推荐你使用wiresshark。

bgp_load_sharing
经过观测可以发现,ping包的走向跟我们预期中的不同(如上图):|!从R1发出的源地址为1.1.1.1的ICMP报文全部经由R1的s1/0口发出,而回包时却是从它的s1/1口收到。开始的时候我以为是BGP的属性引起的选路问题,但根据路由表,BGP已经接受了两条路径,并把它们放进了路由表,可以确定BGP已经实现了负载均衡(在控制面上),所以我只能向更底层去探究了。这时在我脑海中出现了一个东东:CEF!

:?:什么是CEF?CEF全称Cisco Express Forwarding,思科特快转发。该技术是思科私有的用以提高数据转发能力的技术,在配备Supervisor引擎的路由器上CEF甚至可以实现线速的路由转发!简单地说:在普通的数据转发时,IOS判断数据适合使用哪种转发方式转发,最原始的方式就是根据路由表、各接口的连接关系、是否启用了策略等逐一递归,最后得出数据的出口。但这是一个比较费时的过程,而且效率不高。所以,cisco就在每次转发数据的同时,缓存路由的相关递归结果(CEF表),下次再转发同一目的的数据时就不用再进行耗时的递归查找了!直接就可以找到数据出口。CEF是cisco很优秀的技术之一,其中的原理比较复杂,不是我一言两语可以说清的,有兴趣的可以到cisco的官网看看:http://www.cisco.com/en/US/docs/ios/12_1/switch/configuration/guide/xcdcef.html

很明显,在普通的路由转发中,CEF才是最终决定数据转发的依据!我们不妨看看CEF表:
R1#show ip cef
Prefix              Next Hop             Interface
0.0.0.0/32          receive
1.1.1.1/32          receive
3.3.3.3/32          13.0.0.3             Serial1/1
12.0.0.2             Serial1/0
可以看出,在cef上已经实现了负载均衡(一个目的地两个出口),但为什么转发数据时却不是同时从两个出口转发呢?由于手上没有太多关于CEF的资料,只能上cisco官网查阅相关文档,终于被我找到了一份讲述load-sharing with CEF的资料。上面提到,CEF支持两种负载均衡转发:per-destination、per-packet。而默认情况下,CEF是采取per-destination模式进行转发的,对于同一目的地的数据包,将被以同一路径进行转发!而我们刚才在R1上发送的ICMP报文都是到达同一目的地的,所以都被安排从同一路径发出,而回来时,由于R3认为去往1.1.1.1的出口只有一个,就是发给R1的s1/1口,所以就出现了上面发包和回包路径不一样的情况了。那有什么方法可以看到数据包从两个不同的出口同时发出呢?答案就是将数据包出口的load-sharing模式改为per-packet!在接口模式下使用命令:ip load-sharing per-packet(R1上的两个接口都要配置)。好了现在再从新抓包验证一下吧!

bgp_load_sharing2
从抓包的结果可以看出,源地址为1.1.1.1的ICMP报文已经分别由两个接口平均发送了!(回包路径只有一条,因为在R3上去往1.1.1.1的路径只有一条,所以回包时全都经R1的s1/1进入)

:arrow:R1上两个通向ISP接口的配置:

interface Serial1/0
ip address 12.0.0.1 255.255.255.0
ip load-sharing per-packet
serial restart-delay 0
!
interface Serial1/1
ip address 13.0.0.1 255.255.255.0
ip load-sharing per-packet
serial restart-delay 0

:oops:呼~终于写完了,花了一个晚上,还请大家多多支持!如果有任何纰漏,请务必给小弟指出,不胜感激!

:!:本文原创!如需转载请与我联系

分享家:Addthis中国

2 条留言

我要留言
  • 1 F

    丕子  |  2009/11/07 22:09 下午  

    还几幅图片红叉了 :sad:

    [Reply]

    Alvin.J 回复:

    @丕子, 不会吧……可能是空间的速度太慢了吧……晕~ :cry:

    [Reply]

(必填)
(必填,绝不公开)

:wink: :-| :-x :twisted: :) 8-O :( :roll: :-P :oops: :-o :mrgreen: :lol: :idea: :-D :evil: :cry: 8) :arrow: :-? :?: :!: