quagga源码学习--BGP协议对等体连接建立的状态机
创建完bgp peer之后,就要bgp start了,不然费那么大劲创建出来不做事情就销毁了,就很尴尬了。
那么对等体一旦start起来,就会进入各自的状态,在不同的状态下处理各自的事件消息。
下面列举一些状态和事件的集合:
1 /* BGP finite state machine status. */ 2 #define Idle 1 3 #define Connect 2 4 #define Active 3 5 #define OpenSent 4 6 #define OpenConfirm 5 7 #define Established 6 8 #define Clearing 7 9 #define Deleted 8 10 #define BGP_STATUS_MAX 9 11 12 /* BGP finite state machine events. */ 13 #define BGP_Start 1 14 #define BGP_Stop 2 15 #define TCP_connection_open 3 16 #define TCP_connection_closed 4 17 #define TCP_connection_open_failed 5 18 #define TCP_fatal_error 6 19 #define ConnectRetry_timer_expired 7 20 #define Hold_Timer_expired 8 21 #define KeepAlive_timer_expired 9 22 #define Receive_OPEN_message 10 23 #define Receive_KEEPALIVE_message 11 24 #define Receive_UPDATE_message 12 25 #define Receive_NOTIFICATION_message 13 26 #define Clearing_Completed 14 27 #define BGP_EVENTS_MAX 15
全局变量FSM定义了状态机每个状态下的动作执行之后的下一个状态:
1 /* Finite State Machine structure */ 2 static const struct { 3 int (*func) (struct peer *); 4 int next_state; 5 } FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1]
限于篇幅就不掉书袋了。
下面的bgp_event函数是通用的事件处理流程,通过FSM数组的定义在这里就能看到了化繁为简的效果:
1 /* Execute event process. */ 2 int 3 bgp_event(struct thread *thread) { 4 ...... 5 6 /* Logging this event. */ 7 next = FSM[peer->status - 1][event - 1].next_state; 8 9 /* Call function. */ 10 if (FSM[peer->status - 1][event - 1].func) ret = (*(FSM[peer->status - 1][event - 1].func))(peer); 11 12 /* When function do not want proceed next job return -1. */ 13 if (ret >= 0) { 14 /* If status is changed. */ 15 if (next != peer->status) bgp_fsm_change_status(peer, next); 16 /* Make sure timer is set. */ 17 bgp_timer_set(peer); 18 } 19 return ret; 20 }
上面可以看到bgp_timer_set这个函数,它在bgp_create的时候也会调用,通过它将任务添加到thread消息调度流程中去,维持整个协议流程的运转。
bgp是基于tcp协议的,即包含了tcp协议的优点,因此上面的状态机也就跟tcp连接有一定的关系:
1、tcp连接建立阶段的状态:Idle, Connect, Active
2、tcp连接建立完成之后: OpenSent, OpenConfirm, Established
进入到Established阶段,说明一切正常,可以开始交换路由了。
附录:
BGP有限状态机
BGP有限状态机共有六种状态,分别是Idle、Connect、Active、OpenSent、OpenConfirm和Established。
Idle状态下,BGP拒绝任何进入的连接请求,是BGP初始状态。
Connect状态下,BGP等待TCP连接的建立完成后再决定后续操作。
Active状态下,BGP将尝试进行TCP连接的建立,是BGP的中间状态。
OpenSent状态下,BGP等待对等体的Open消息。
OpenConfirm状态下,BGP等待一个Notification报文或Keepalive报文。
Established状态下,BGP对等体间可以交换Update报文、Route-Refresh报文、Keepalive报文和Notification报文。
在BGP对等体建立的过程中,通常可见的三个状态是:Idle、Active、Established。
BGP对等体双方的状态必须都为Established,BGP邻居关系才能成立,双方通过Update报文交换路由信息。
BGP处理过程
因为BGP的传输层协议是TCP协议,所以在BGP对等体建立之前,对等体之间首先进行TCP连接。BGP邻居间会通过Open消息协商相关参数,建立起BGP对等体关系。
建立连接后,BGP邻居之间交换整个BGP路由表。BGP协议不会定期更新路由表,但当BGP路由发生变化时,会通过Update消息增量地更新路由表。 BGP会发送Keepalive消息来维持邻居间的BGP连接。当BGP检测到网络中的错误状态时(例如:收到不支持的协商能力或者收到错误报文时),BGP会发送Notification消息进行报错,BGP连接会随即中断。