一.邻居发现与建立阶段
通过双方交互Hello报文完成邻居发现。一共有三个状态机:
- Down:这是邻居的初始状态,表示没有从邻居收到任何信息。
- Init:在此状态下,路由器已经从邻居收到了Hello报文,但是自己的router-id不在所收到的Hello报文的邻居列表中,表示尚未与邻居建立双向通信关系。在此状态下的邻居要被包含在自己重新产生的Hello报文中,并且发送。
- 2-Way:收到了带有自己RID的Hello包进入的状态。在此状态下,两台路由器已确认可以双向通信,邻居关系已经建立;但是还没有建立邻接关系。这是建立邻接关系以前的最高级状态。如果网络为广播网络或者NBMA网络则选举DR/BDR。如果是P2P和P2MP网络中,则直接进入ExStart状态。
在形成邻居关系过程中,需要对Hello报文携带的参数进行协商,否则无法正常建立邻居关系:
- 如果接收端口的网络类型是广播型,点到多点或者NBMA,所接收的Hello报文中Network Mask字段必须和接收端口的网络掩码一致,如果接收端口的网络类型为点到点类型或者是虚连接,则不检查Network Mask字段,因为NCP协商阶段会生成对端IP的32位路由。
- 所接收的Hello报文中的HelloInterval和RouterDeadInterval字段必须和接收端口的配置保持一致。
- 所接收的Hello报文中的认证字段需要于本机配置一致。
- 区域类型,所接收的Hello报文中的Options字段中的E和N位(表示是否接收外部路由信息)必须和接收端口的相关区域配置保持一致。
- 区域ID,包含在OSPF头部之中。
- 所接收的Hello报文中的区域字段必须和接收端口的配置一致。
- 网络类型最好设置为相同,不是极大可能出现问题,具体在网络类型的章节分析。
- MA网络中不能所有设备优先级都为0,DR选举会不成功。
hello报文抓包内容:
带有hello时间,dead时间,并且有接口的接口优先级用来选举DR和BDR,也有属于的区域和自己已知的邻居路由器。
在广播网络或者NBMA网络中普通路由器需要和DR、BDR建立OSPF邻接关系,普通路由器之间只需要建立邻居关系即可。在P2P和P2MP网络中,设备间建立的都是邻接关系。
补充:DR和BDR的相关内容
选举DR和BDR的作用:
- DR和BDP只会在多路访问环境中存在,也就是NBMA和Broadcast环境中产生,目的是在同一网段中减少链路状态报文泛洪的数量,因为在点到点或者点到多点中,在同一个链路中只需要和很有限的设备建立邻居关系即可,在P2P中只还只需要和对方一个人建立邻居关系,但是在多路访问的环境中,那就完全不一样的了,一个广播网段中可以通过交换机连接很多的设备,这样的话一个网段中交互的链路信息可能会变得很大,严重占用了链路的带宽,所以为了杜绝这件事情的发生,我们选举出DR和BDR作为整个网段中的老大哥和老二哥,其他小弟只需要和老大哥同步LSDB即可,当老大哥出现问题时,再由老二哥进行填补,这样的话就很好的解决了链路状态信息过多的问题。小老弟之间只需要建立普通的邻居关系即可。另外需要注意的是DR和BDR也需要建立LSDB的完全同步。
- SPF算法需要将多路访问链路抽象为点到点的类型进行计算,如下图:
其中N1就是抽象出来的DR,由DR发送出2类LSA来描述和他相连的真实接口。
DR/BDR选举规则:
- DR/BDR由OSPF的Hello协议选举,选举是根据端口的路由器优先级(Router Priority)进行的,也就是比较同一网段中不同路由器的相连接口的优先级。
- 如果Router Priority被设置为0,那么该路由器将不允许被选举成DR或者BDR,默认为1,最大为255。(三层比大,二层比小)
- Router Priority越大越优先。如果相同,Router ID大者优先。
- DR/BDR不能抢占。
- 如果当前DR发生故障,当前BDR自动成为新的DR,网络中重新选举BDR;如果当前BDR发生故障,则DR不变,重新选举BDR。
DR/BDR选举算法:
- 路由器接口数据结构中维持三个集合,分别是:
• DR集合:通过Hello报文学习到的所有DR路由器。
• BDR集合:通过Hello学习到的所有 BDR 由器。
• DRother集合:没有被选举为DR和BDR的路由器(优先级不为0)。 - 算法工作时,在DR集合中选择最好的路由器,使其成为 DR 。在BDR集合中选择最好的路由器,使其成为BDR。
• DR的选举应用以下规则:
如果DR集合为非空,则从中选择最好的路由器成为 DR。
如果DR集合为空,则把当前BDR提升为DR; 而如果BDR集合为空,则要先从DRother集合中选出BDR再将其提升为DR。
• BDR 的选举应用以下规则:
如果BDR集合为非空,则从中选择最好的路由器为BDR。
如果 BDR 集合为空 ,则从DRother集合中选择最好的路由器成为BDR路由器。
DR/BDR选举的过程:
- OSPF路由器在DR/BDR未选举出来之前,Hello报文中关于DR/BDR的字段为 0.0.0.0 。选举完成后, DR/BDR的字段记录已知的DR/BDR的RouterID。路由器接口根据听到的Hello报文,生成邻居表并在接口维持三个集合:
• DR 集合{ }
• BDR 集合{ }
• DRother (非DR/BDR 但是有资格成为DR和BDR的路由器)集合{ } - OSPF接口开启后,在 Hello 报文中设置 DR/BDR 字段为全0 ,此时 DR/BDR未知。同时,Wait timer启动,时长为4倍的Hello间隔,也就是40s。
- 当整个网络中设备都是同时启动的时候,所有发送的hello报文是没有DR和BDR字段的。
- 在waiting阶段,如果收到Hello报文中有DR和BDR,说明这个网络中在本设备接入之前就已经选举了DR和BDR,则不论它的Router ID有多大,都会承认现网中已有的DR和BDR,而不会触发选举。直接离开waiting状态,开始邻接关系同步。
- 在waiting阶段,路由器会将优先级在1-255的设备加入DRother集合中。只有在Wait 计时器超时后,仍未学习到 DR/BDR,才开始 DR/BDR选举。
- 如果 BDR 集合为空,则从DRother集合选举BDR;如果DR集合为空,则从BDR 集合选举DR。据此,如果在没有 DR和BDR的网络上,Wait 计时器超时后,网络上的每台路由器都会先从DRother集合选择BDR再把BDR提升为DR; 再重新从DRother集合选择BDR。至此DR和Dother之间选举结束开始邻接关系建立。
二、邻接关系建立过程
分为两个子阶段:主从关系建立阶段和数据库同步阶段。
子阶段一:主从关系确定阶段
通过双方交互DD(DBD)报文完成。一共有两个状态机,Exstart和Exchange:
- 邻居状态机变为ExStart以后,R1向R2发送第一个空的DD报文,在这个报文中,DD序列号被设置为552A(假设)。其中DB description字段为0x07:Initial比特为1表示这是第一个DD报文,More比特为1表示后续还有DD报文要发送,Master比特为1表示R1宣告自己为主路由器。
- 同样,R2也向R1发送第一个空的DD报文,在这个报文中,DD序列号被设置为5528(假设)。
- R1发现对端Router ID比本端大,所以R2应当为主路由器,这时便确定自己的身份,R1会产生一个NegotiationDone的事件,成为Slave设备,并进入Exchange状态。邻居状态机变为ExStart以后,R1向R2发送第一个带有自己数据库信息(LSA头部内容)的DD报文,在这个新的报文中包含LSDB的摘要信息,序列号设置为R2在第二步里使用的序列号为5528(假设),和Master的一样,目的是做隐式确认。More比特为0表示不需要另外的DD报文描述LSDB,Master比特为0表示R1宣告自己为从路由器。收到这样一个报文以后,R2会产生一个NegotiationDone的事件,因此R2将邻居状态改变为Exchange。
- 邻居状态变为Exchange以后,R2发送一个新的DD报文,该报文中包含LSDB的描述信息,DD序列号设为5529(上次使用的序列号加1)。即使R1不需要新的DD报文描述自己的LSDB,但是做为从路由器,R1需要对主路由器R2发送的每一个DD报文进行确认。所以,R1向R2发送一个新的DD报文,序列号为5529,该报文内容为空。
- 当本端所有LSDB摘要信息被发送完成后,如果本端没有对端的一些LSDB信息,则进入Loading状态,如果都存在,则直接进入Full状态。
隐式确认机制: 也就是通过序列号进行确认,主设备每发送一个DD报文,备设备都会发送同样序列号的DD报文进行确认,保证DD报文不会丢失。
抓包内容: 带有LSA的head字段,DB Description字段、Interface MTU字段等
此阶段中,需要对DD报文携带的MTU参数进行协商,否则无法正常建立邻居关系(也可以忽略检查):
默认情况下,DD报文的interface MTU值为0,表示不执行一致性检查。在华为设备上使用命令ospf mtu-enable后,可以开启接口填充及检查MTU。如果检查MTU值,整个过程协商过程,小的一方停留在Exstart状态,另一方停留在Exchange阶段。
子阶段二:数据库同步阶段
通过双方交互LSR、LSU、LSAck报文完成。一共有两个状态机loading和Full:
- 邻居状态变为Loading之后,R1开始向R2发送LS request报文,请求那些在Exchange状态下通过DD报文发现的,而且在本地LSDB中没有的链路状态信息。
- R2收到LS Request报文之后,向R1发送LS Update报文,在LS Update报文中,包含了那些被请求的链路状态的详细信息。R1收到LS Update报文之后,将邻居状态从Loading改变成Full。
- R1向R2发送LS Ack报文,确认R2发送的LSA已被R1正确接收。LS Ack用来确保信息传输的可靠性。
显式确认机制: LSU对LSR确认,LSAck对LSU确认,具体是通过{type、ls id、advrouter} 字段来判断是否是一条LSA。
隐形确认机制: LSU对于LSU的确认,在MA网络中使用这种方式进行确认,原因是因为DR需要将DRother发送来的LSU,重新通过224.0.0.5这个组播地址发送到整个网段中,此LSU的产生者当然也会收到,就可以当做确认了,否则在MA网络中,DR使用LSAck报文进行确认就太过于繁琐。
抓包内容:
LSR报文:带有需要请求的具体LSA的信息{type、ls id、advrouter}
LSU报文:带有具体的LSA信息
LSAck报文:带有LSA的头部信息
补充:LSA泛洪机制
泛洪的原因:
泛洪的过程是路由器把自己产生或学来的LSA向所有其他邻居或路由器通告的过程。OSPF在区域内通过LSDB中的LSA计算出拓扑和路由信息,为了保证没有环路,每一个区域内的LSDB的内容是相同的,LSDB的一致性及快速同步直接影响OSPF路由的收敛性能。
泛洪的机制:
数据库包含所有LSA,数据库中任何LSA的变化都会触发当前路由器通告该变化给邻居路由器并泛洪至所属区域;如果没有变化,默认每30min会进行一次泛洪。
OSPF的LSU/LSAck可以携带多份LSA,通过在邻居之间泛洪LSU/LSAck,最终通告到全网络。在点到点网络,更新以组播方式发送到224.0.0.5,在点到多点(NBMA)类型和Vlink类型链路上则以单播方式泛洪给邻居。
每台路由器在一个接口收到泛洪的LSA报文,会继续向其他接口泛洪。例如,在MA网段上,若DRother向DR/BDR泛洪,则DR会以组播方式将LSU (包含LSA)向其他DRother泛洪。NBMA网络,上DRother单播给DR/BDR,DR再单播给DRother。泛洪过程是个可靠过程,有确认机制。其中每份泛洪的LSA都必须被确认,确认包括显式或隐含确认, 使用
当一份LSA被泛洪出去,当前路由器会记录在该接口的所有邻居数量并为之维护重传列表,没有收到显示或隐含确认的LSA会在5s后单播重传更新(不管网络类型是什么)。
具体步骤:
每台路由器都有相似的工作行为以生成一致的LSDB。
- 一个接口收到LSA,存放到LSDB后,再从“其他接口”重新泛洪出去,泛洪也有“水平分割”的行为,例外是DR会把从一个DRother收到的LSA通过原接口重新通告给其他DRother路由器。
- 重新通告的LSA和收到的LSA除Age增加1外,其他内容一致, 如checksum等。
- LSA会泛洪到区域的边界。
- 每台接收路由器先判断LSDB中是否已有该LSA,或者是判断本地储存的有没有接收到的新,没有或者接收到的LSA更新则存储且转发,否则忽略。
- 如果接收时没有判断是否已拥有该LSA,或路由器没有停止转发,则会致LSA,在Area内无休止地传递。
- 当1类和2类LSA到达区域边界是不会传输到另外一个区域。
如何判断本地是否存在该LSA:
LSDB中每份LSA都有唯一的身份证ID,由三个参数构成:LSA类型、链路状态ID (Link State ID)和通告路由器的RouterID。如果这三个参数相同,表示是通一个LSA。
如和判断LSA的新旧:
判断相同ID的“新的”LSA要依次比较以下内容:LSA序列号( Sequence Number)、LSA报文校验和(Checksum)和LSA年龄(LSA Age)。
序列号:有符号32位整数,采用线性递增的序列号,初始序列号从08000001到最大值0x7FFFFFF,序列号越大代表越新,LSA会周期(30min) 产生新的LSA,每次产生的LSA序列号都会增加1。到了最大值0x7FFFFFFF会发送AGE标记为60min的lsa,然后全部删掉重新从最小开始0x00000001开始。
Checksum: 16 位数,对刚收到的LSA做计算,Age 字域不在计算内。即使LSA存放在LSDB中,路由器也会每5分钟重新计算一次。
Age: 16 位无符号整数。LSA的最大年龄是3600s,LSA在路由器间泛洪时每经过一跳年龄增加1,在LSDB中存放时年龄也增加1。若LSA的年龄达到3600s(即Maxage),路由器会从LSDB中清除该LSA。在拓扑稳定的场合下,每份存放在LSDB中的LSA间隔30min都会被周期产生的新LSA刷新。
判断LSA新旧的规则如下:
- 序列号越大代表越新。
- 若序列号相同,则Checksum数值越大代表越新。
- 上述一致的情况下,继续比较Age。
• 若LSA的Age为MaxAge,即3600s,则该 LSA被认定更“新”,这是撤销LSA的信息。
• 若LSA间Age差额超过15min,则Age小的LSA被认定更“新”。若LSA Age差额在15min以内,则二者视为相同“新”的LSA, 只保留先收到的一份LSA。
判断LSA是否相同和新旧的参数都在LSA的报头中:
参考资料:华为hedex文档、HCIE学习指南