Ospf中路由器之间存在两种连接关系:邻居关系和邻接关系。本博文将详细介绍这2种关系建立及工作原理。
如果两台路由器之间共享一条公共数据链路(两台路由器中间没有其它路由器,或者两台路由器之间存在虚连接),并且成功协商了hello包中所指定的参数,那么它们就成为邻居。如果两个邻居之间需要同步LSDB,那么它们之间需要建立邻接关系。如果两个路由器之间建立了邻接关系,那么它们的LSDB一定是同步的。LSA只在存在邻接关系的路由器之间传递。
那么邻居关系和邻接关系怎么建立呢?邻居关系通过hello报文来建立。Hello报文中包含如下一些内容:
1、始发路由器的router-id
2、始发路由器接口的area-id
3、始发路由器接口的地址掩码
4、始发路由器接口的authentication type和authentication message
5、始发路由器接口的hello-interval
6、始发路由器接口的router dead-interval
7、路由器优先级
8、指定DR和BDR
9、标识可选性能的5个标志位
10、始发路由器的所有有效neighbor router-id(始发路由器接收到了它们的hello报文)
以两台路由器之间建立邻居关系为例:
1、R1发送hello报文(组播或者单播,链路层类型来定),neighbor字段为空
2、R2收到hello报文,为R1建立一个邻居数据结构,并把R1的邻居状态置为init,然后向R1发送hello报文,neighbor字段中包含R1的rougerID,表示自己收到了R1的hello报文。
3、R1收到R2的hello报文之后,为R2建立一个邻居数据结构,并把邻居状态置为2way,然后向R2发送hello报文,报文的neighbor字段中包含R2的routerID。
4、R2收到R1的hello报文后,把R1的邻居状态置为2way
至此,邻居关系就建立起来了,邻居路由器之间会按时发送hello报文进行保活,如果hello报文超时,那么该路由器就会宣告这里邻居失效。
所有路由器之间都达到2way状态后,它们会根据网络类型判断是否需要选举DR和BDR,如果需要的话就开始选举DR和BDR。
邻居路由器之间会判断是否需要建立邻接关系,怎么判断呢?
1、 如果是point-to-point链路,需要建立邻接关系
2、 如果是point-to-multipoint链路,需要建立邻接关系
3、 如果网络类型是虚链路,需要建立邻接关系
4、 本地路由器是网段上的DR,需要建立邻接关系
5、 本地路由器是网段上的BDR,需要建立邻接关系
6、 邻居路由器是网段上的DR,需要建立邻接关系
7、 邻居路由器是网段上的BDR,需要建立邻接关系
如何建立邻接关系呢?
其实邻接关系的建立过程中就顺带把LSDB同步了。过程如下:
建立邻接关系使用下面三种协议报文:
Hello报文type1、数据库描述数据包type2、链路状态请求报文type3、链路状态更新报文type4、链路状态确认报文type5
1、RT1的一个连接到广播类型网络的接口上激活了OSPF协议,并发送了一个HELLO报文(使用组播地址224.0.0.5)。由于此时RT1在该网段中还未发现任何邻居,所以HELLO报文中的Neighbor字段为空。
2、RT2收到RT1发送的HELLO报文后,为RT1创建一个邻居的数据结构,并且将RT1的邻居状态机置为Init。RT2发送一个HELLO报文回应RT1,并且在报文中的Neighbor字段中填入RT1的Router id,表示已收到RT1的HELLO报文。
3、RT1收到RT2回应的HELLO报文后,为RT2创建一个邻居的数据结构,并将邻居状态机置为Exstart状态。下一步双方开始发送各自的链路状态数据库。
为了提高发送的效率,双方需先了解一下对端数据库中那些LSA是自己所需要的(如果某一条LSA自己已经有了,就不再需要请求了)。方法是先发送DD报文,DD报文中包含了对本地数据库中LSA的摘要描述(每一条摘要可以惟一标识一条LSA,但所占的空间要少得多)。由于OSPF直接用IP报文来封装自己的协议报文,所以在传输的过程中必须考虑到报文传输的可靠性。
为了做到这一点,在DD报文的发送过程中需要确定双方的主从关系。作为Master的一方定义一个序列号seq,每发送一个新的DD报文将seq加一。作为Slave的一方,每次发送DD报文时使用接收到的上一个Master的DD报文中的seq。实际上这种序列号机制是一种隐含的确认方法。如果再加上每个报文都有超时重传,就可以保证这种传输是可靠的。
RT1首先发送一个DD报文,宣称自己是Master(MS=1),并规定序列号为x。I=1表示这是第一个DD报文,报文中并不包含LSA的摘要,只是为了协商主从关系。M=1说明这不是最后一个报文。
4. RT2在收到RT1的DD报文后,将RT1的邻居状态机改为Exstart,并且回应了一个DD报文(该报文中同样不包含LSA的摘要信息)。由于RT2的RouterID较大,所以在报文中RT2认为自己是Master,并且重新规定了序列号为y。
5. RT1收到报文后,同意了RT2为Master,并将RT2的邻居状态机改为Exchange。RT1使用RT2的序列号y来发送新的DD报文,该报文开始正式地传送LSA的摘要。在报文中RT1将MS=0,说明自己是Slave。
6. RT2收到报文后,将RT1的邻居状态机改为Exchange,并发送新的DD报文来描述自己的LSA摘要,需要注意的是:此时RT2已将报文的序列号改为y+1了。
7. 上述过程持续进行,RT1通过重复RT2的序列号来确认已收到RT2的报文。RT2通过将序列号+1来确认已收到RT1的报文。当RT2发送最后一个DD报文时,将报文中的M=0,表示这是最后一个DD报文了
8. RT1收到最后一个DD报文后,发现RT2的数据库中有许多LSA是自己没有的,将邻居状态机改为Loading状态。此时RT2也收到了RT1的最后一个DD报文,但RT1的LSA,RT2都已经有了,不需要再请求,所以直接将RT1的邻居状态机改为Full状态。
9. RT1发送LS Request报文向RT2请求所需要的LSA。RT2用LS Update报文来回应RT1的请求。RT1收到之后,需要发送LS Ack报文来确认。上述过程持续到RT1中的LSA与RT2的LSA完全同步为止。此时RT1将RT2的邻居状态机改为Full状态。
注:
以上过程是两台路由器由相互没有发现对方的存在到建立邻接关系的过程。或者可以理解为网络中新加入一台路由器时的处理情况。当两台路由器之间的状态机都已经达到Full状态之后,如果此时网络中再有路由变化时,就无须重复以上的所有步骤。只由一方发送LS Update报文通知需要更新的内容,另一方发送LS Ack报文予以回应即可。双方的邻居状态机在此过程中不再发生变化。