以BGP为代表的路由协议,从设计之初,就关注路由表的正确性,因为这是确保整个网络系统正常工作的最基本要求。因此每个BGP路由器,总是会以最快的速度收敛到整个网络最新的状态上。当一个BGP peer的BGP连接断开时,当前BGP路由器会认为BGP peer已经不能工作,进而会以最快的速度删除之前从这个BGP peer收到的路由。
但这样敏感的机制其实有一些问题:
首先,BGP连接断开了不一定代表路由器不能工作了。可能只是BGP所基于的TCP连接有问题,也可能是BGP keepalive消息丢了,但是路由器还是具备正常转发的能力。如果仅以BGP断连来判断路由器不能工作有时候会误伤。其次,路由器上的BGP进程可能正在重启,所以BGP连接只是短暂的断开,马上又能重连回来。如果一断开就删路由,重新建连又添加路由,会造成BGP路由器上路由反转,进而产生短时间的路由环路或者黑洞路由。这样一个路由反转可能会传递到整个数据中心,不仅消耗了路由器控制平面的计算能力,甚至会引起整个网络的抖动。
优雅重启机制的引入:
这在之前的硬件BGP设备中不是严重的问题,因为硬件设备设计就是一直运行,不需要重启。但是对于软件BGP来说,软件维护需要经常的重启BGP进程。为了解决这个问题,RFC4724为BGP(包括传统的BGP-4和MP-BGP)增加了一种新的能力,也就是Graceful Restart,它能在BGP短时间断连的时候,不删除相应的路由信息,从而确保网络的稳定性。从协议上来看,Graceful Restart在BGP协议的基础上增加了两个部分:End-of-RIB和Graceful Restart Capability。
BGP协议是由4类消息组成的。End-of-RIB从格式上看就是一种特殊的Update消息,它没有可达的Network Layer Reachability Information(NLRI),同时带的撤回NLRI也是空的。End-of-RIB就是一个空的Update消息,按照正常的处理逻辑是没有意义,并且不会产生任何影响。BGP路由器在启动的时候,会计算本地路由并发布到与之相连的BGP peer。这个过程结束之后,BGP路由器就是断断续续的接收一些更新事件,再将路由redistribute到BGP peer。所以,BGP路由器启动之后,过程可以分为两个部分,一个是初始化路由发布,另一个是正常工作时的路由发布。对于一个支持Graceful Restart的路由器来说,End-of-RIB的作用就是区分这两个部分,它会在初始化路由发布完之后,正常工作之前发布
1、BGP路由器重启,BGP连接断开。
2、存储在RIB中的之前的BGP route标为stale状态,仅此而已。在生成实际路由表时,stale状态的BGP route不应该区别对待。
3、BGP路由器启动,重新建立BGP连接,发送OPEN Message,在其中的Graceful Restart Capability中,Restart Flags中第1bit置1,表明刚刚经历了重启。
4、对于每个BGP Address Family,如果在重启过程中,BGP route保留了,那么相应的
5、重新建立BGP连接,接收对端发来的BGP路由。但是当前路由器并不立即进行路由选择算法来更新本地路由表。
6、等到下面两个条件之一满足时再进行路由选择算法:
* 从所有的BGP peer都收到了End-of-RIB。
但是这里要排除在Open Message中,将Restart Flag设置为1的peer,因为它们也在等当前路由器
的End-of-RIB,而当前路由器只有在收完BGP peer的End-of-RIB并且进行完本地的路由选择算法
之后才会发送自己的End-of-RIB,所以如果这里互相等待的话就会死锁。
* 路由选择算法等待时间超时了。
为了避免当前路由器无尽的等待而不进行路由选择算法,支持Graceful Restart的BGP路由器,
必须支持配置这个超时时间(Selection_Deferral_Timer)。
7、进行完路由选择算法之后,如果本地标为stale的BGP 路由没有从任何一个BGP peer收到更新,那么说明这条路由真的不存在了,必须被删除。
8、发布计算之后的路由到BGP peer。
9、发布End-of-RIB。
支持Graceful Restart的路由器,最主要的能力就是在BGP重启的过程中,保留之前的BGP route,同时保留自身的转发能力。在BGP 重新建立连接之后,再更新相应的BGP route
1、识别之前已经发送了Graceful Restart Capability的路由器,如果是支持Graceful Restart的路由器断开连接,那么执行下面的操作。
2、保留从peer路由器接收的BGP route,并标记成stale状态。仅此而已。在生成实际路由表时,stale状态的BGP route不应该区别对待。如果在这一步中,BGP route已经是stale,那么BGP route会被删除。也就是对端连续重启可能会造成本地相应的路由删除。
3、对端重新建立BGP连接,在当前BGP 路由器发送的Open Message中,其中Graceful Restart Capability中,Restart Flags中第1bit置0,除非当前BGP路由器也刚刚重启。如果在之前的Graceful Restart Capability中“Restart Time”到达之后,BGP还没有重新建连,那么stale状态的BGP route必须删除。所以,最多为对端保留路由4095秒。
4、对于每个BGP Address Family,如果在peer重启过程中,BGP route保留了,那么相应的
5、但是在从peer BGP路由器收到的Graceful Restart Capability中,如果满足下面三个条件之一,表明peer BGP在重启过程中没有保留BGP route,那么需要立即删除相应的stale 状态的BGP route。
* 对应的Address Family中的Flags for Address Family第1bit为0;
* 没有相应的Address Family;
* 根本就没有Graceful Restart Capability
6、当前BGP 路由器发送End-of-RIB
7、在收到peer BGP重新发送过来的BGP route时,更新本地的stale状态BGP route。
8、当收到peer BGP发送的End-of-RIB时,删除相应Address Family中仍然为stale的BGP route。
支持Graceful Restart的路由器,在同样支持Graceful Restart的peer BGP路由器重启过程中,会保留之前的BGP route,仍然相信peer BGP具备转发能力。在BGP 重新建立连接之后,再更新相应的BGP route。
BGP优雅重启,实际上就是将作为控制平面的BGP和转发平面解耦开。这样,就算控制面BGP断开了,也不影响数据面的转发能力。
示例来源:kube-router
https://github.com/cloudnativelabs/kube-router/blob/master/pkg/controllers/routing/bgp_peers.go
使用gobgp库进行建立bgp连接的时候,可以参考一下示例打开bgp优雅重启机制
if nrc.bgpGracefulRestart {
n.GracefulRestart = &gobgpapi.GracefulRestart{
Enabled: true,
RestartTime: uint32(nrc.bgpGracefulRestartTime.Seconds()),
DeferralTime: uint32(nrc.bgpGracefulRestartDeferralTime.Seconds()),
LocalRestarting: true,
}
if nrc.isIpv6 {
n.AfiSafis = []*gobgpapi.AfiSafi{
{
Config: &gobgpapi.AfiSafiConfig{
Family: &gobgpapi.Family{Afi: gobgpapi.Family_AFI_IP6, Safi: gobgpapi.Family_SAFI_UNICAST},
Enabled: true,
},
MpGracefulRestart: &gobgpapi.MpGracefulRestart{
Config: &gobgpapi.MpGracefulRestartConfig{
Enabled: true,
},
State: &gobgpapi.MpGracefulRestartState{},
},
},
}
} else {
n.AfiSafis = []*gobgpapi.AfiSafi{
{
Config: &gobgpapi.AfiSafiConfig{
Family: &gobgpapi.Family{Afi: gobgpapi.Family_AFI_IP, Safi: gobgpapi.Family_SAFI_UNICAST},
Enabled: true,
},
MpGracefulRestart: &gobgpapi.MpGracefulRestart{
Config: &gobgpapi.MpGracefulRestartConfig{
Enabled: true,
},
State: &gobgpapi.MpGracefulRestartState{},
},
},
}
}
}