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连接会随即中断。

原文地址:https://www.cnblogs.com/danxi/p/6349228.html