OSPF(Open Shortest Path First,开放式最短路径优先)是IETF组织开发的一个基于链路状态的内部网关协议。作为链路状态路由协议,OSPF不直接传递各路由器的路由表,而传递链路状态信息,各路由器基于链路状态信息独立计算路由。
所谓链路状态(Link State)指的就是路由器的接口状态。链路信息主要包括:链路的类型、接口IP地址及掩码、链路上所连接的邻居路由器和链路的带宽(开销)。
Router ID是设备通过指定的动态路由协议进行路由交互过程中,唯一标识自身的32位整数。Router ID的格式和IP地址的格式是一样的。如下图所示,每个运行OSPF的路由器都有一个Router ID用于标识自身路由器。
Router ID有手动配置和设备自动选取两种选取方式。在实际网络部署中,考虑到协议的稳定性,建议手工配置Loopback接口的IP地址作为Router ID。
如果指定动态路由协议配置了Router ID,则以该协议自身的配置为准。
如果指定动态路由协议没有配置Router ID,且设备配置了全局Router ID,则以全局Router ID为准。
如果管理员没有手动配置Router ID,设备会从当前接口的IP地址中自动选取一个作为全局Router ID。其选择顺序如下:
如果存在配置了IP地址的Loopback接口,则选择Loopback接口地址中最大的作为全局Router ID。
如果设备上不存在Loopback接口或者存在Loopback接口但没有配置IP地址,则从其他接口的IP地址中选择最大的作为全局Router ID(不考虑接口的UP/DOWN状态)。
OSPF在以下3种情况会进行Router ID的重新选取:
通过命令ospf router-id router-id重新配置OSPF的Router ID,并且重新启动OSPF进程。
重新配置全局Router ID,并且重新启动OSPF进程。
原来被选举为全局Router ID的IP地址被删除并且重新启动OSPF进程。
在OSPF网络中,每台路由器根据自己周围的网络拓扑结构生成链路状态通告LSA(Link State Advertisement),并通过更新报文将LSA发送给网络中的其它路由器。
每台路由器都会收集其它路由器发来的LSA,所有的LSA放在一起便组成了链路状态数据库LSDB(Link State DataBase)。路由器将LSDB转换成一张带权的有向图,这张图便是对整个网络拓扑结构的真实反映。在网络拓扑稳定的情况下,各个路由器得到的有向图是完全相同的。
每台路由器根据有向图,使用SPF算法计算出一棵以自己为根的最短路径树,这棵树给出了到自治系统中各节点的路由。
OSPF的运行机制包括以下5个步骤:
通过交互Hello报文形成邻居关系
路由器运行OSPF协议后,会从所有启动OSPF协议的接口上发送Hello报文。如果两台路由器共享一条公共数据链路,并且能够成功协商各自Hello报文中所指定的某些参数,就能形成邻居关系。
通过泛洪LSA通告链路状态信息
形成邻居关系的路由器之间进一步交互LSA形成邻接关系,如下图所示。每台路由器根据自己周围的网络拓扑结构生成LSA,LSA描述了路由器所有的链路、接口、邻居及链路状态等信息,路由器通过交互这些链路信息来了解整个网络的拓扑信息。
通过组建LSDB形成带权有向图
路由器把收到的LSA汇总记录在LSDB中。LSA是对路由器周围网络拓扑结构的描述,而LSDB是LSA的汇总,是对整个自治系统的网络拓扑结构的描述。最终,所有路由器都会形成同样的LSDB,并通过组建LSDB形成带权有向图。
通过SPF算法计算并形成路由
当LSDB同步完成之后,每一台路由器都将以其自身为根,使用SPF算法来计算一个无环路的拓扑图来描述它所知道的到达每一个目的地的最短路径(最小的路径代价)。这个拓扑图就是最短路径树,有了这棵树,路由器就能知道到达自治系统中各个节点的最优路径。
维护和更新路由表
根据SPF算法得出最短路径树后,每台路由器将计算得出的最短路径加载到OSPF路由表形成指导数据转发的路由表项,并且实时更新。同时,邻居之间交互Hello报文进行保活,维持邻居关系或邻接关系,并且周期性地重传LSA。
OSPF的报文类型可以分为以下五种:
1. Hello报文
Hello报文的主要作用如下:
邻居发现:使能了OSPF功能的接口会周期性地发送Hello报文,与网络中其他收到Hello报文的路由器协商报文中的指定参数,决定是否建立邻居关系。
建立双向通信:如果路由器发现收到的Hello报文的邻居列表中有自己Router ID,则认为已经和对端建立了双向通信,邻居关系建立。
指定DR和BDR:Hello报文包含DR优先级和Router ID等信息,每台路由器将自己选出的DR和BDR写入Hello报文的DR和BDR字段中,然后进行DR和BDR的选举。
保活:在建立邻居关系后,使能OSPF功能的接口仍周期性地发送Hello报文维护邻居关系,如果在一定的时间间隔内没有收到邻居发来的Hello报文,则中断邻居关系。
2. DD报文
两台路由器在邻接关系初始化时,DD报文(Database Description packet)用来协商主从关系,此时报文中不包含LSA的Header。
邻接关系建立之后,路由器使用DD报文描述本端路由器的LSDB,进行数据库同步。DD报文里包括LSDB中每一条LSA的Header,即所有LSA的摘要信息。对端路由器根据LSA Header就可以判断出是否已有这条LSA。
3. LSR报文
两台路由器互相交换过DD报文之后,需要发送LSR报文(Link State Request packet)向对方请求更新LSA。LSR报文里包括所需要的LSA的摘要信息。
4. LSU报文
LSU报文(Link State Update packet)用来向对端路由器发送其所需要的LSA或者泛洪本端更新的LSA,其报文内容是多条完整的LSA的集合。为了实现泛洪的可靠性传输,需要LSAck报文对其进行确认,对没有收到确认报文的LSA进行重传,重传的LSA是直接发送到邻居的。
5. LSAck报文
LSAck报文(Link State Acknowledgment packet)用来对接收到的LSU报文进行确认,内容是需要确认的LSA的Header。一个LSAck报文可对多个LSA进行确认。
OSPF根据链路层协议类型,将网络分为如下四种类型:
1. 广播类型(Broadcast)
当链路层协议是Ethernet或FDDI(Fiber Distributed Digital Interface)时,缺省情况下,OSPF认为网络类型是Broadcast。
在该类型的网络中:
以组播形式发送Hello报文、LSU报文和LSAck报文。其中,224.0.0.5的组播地址为OSPF设备的预留IP组播地址;224.0.0.6的组播地址为OSPF DR/BDR的预留IP组播地址。
以单播形式发送DD报文和LSR报文。
2. NBMA类型(Non-Broadcast Multi-Access)
当链路层协议是帧中继或X.25时,缺省情况下,OSPF认为网络类型是NBMA。
在该类型的网络中,以单播形式发送协议报文(Hello报文、DD报文、LSR报文、LSU报文、LSAck报文)。
3. 点到多点P2MP类型(Point-to-Multipoint)
没有一种链路层协议会被缺省的认为是P2MP类型。点到多点必须是由其他的网络类型强制更改的。
在该类型的网络中:
以组播形式(224.0.0.5)发送Hello报文。
以单播形式发送其他协议报文(DD报文、LSR报文、LSU报文、LSAck报文)。
4. 点到点P2P类型(Point-to-Point)
当链路层协议是PPP、HDLC或LAPB时,缺省情况下,OSPF认为网络类型是P2P。
在该类型的网络中,以组播形式(224.0.0.5)发送协议报文(Hello报文、DD报文、LSR报文、LSU报文、LSAck报文)。
在广播网络和NBMA网络中,任意两台路由器之间都要传递路由信息。如下图所示,网络中有n台路由器,则需要建立n*(n-1)/2个邻接关系。这使得任何一台路由器的路由变化都会导致多次传递,浪费了带宽资源。
为解决这一问题,OSPF定义了DR。通过选举产生DR后,所有其他设备都只将信息发送给DR,由DR将网络链路状态LSA广播出去。为了防止DR发生故障,重新选举DR时会造成业务中断,除了DR之外,还会选举一个备份指定路由器BDR。这样除DR和BDR之外的路由器(称为DR Other)之间将不再建立邻接关系,也不再交换任何路由信息。
在广播网络和NBMA网络中,为了稳定地进行DR和BDR选举,OSPF规定了一系列的选举规则:选举制、终身制、继承制。
选举制是指DR和BDR不是人为指定的,而是由本网段中所有的路由器共同选举出来的。
选举中使用的“选票”就是Hello报文,每台路由器将自己选出的DR写入Hello报文中,发给网段上的其他路由器。DR/BDR的选举是基于接口的,选举规则如下:
当处于同一网段的两台路由器同时宣布自己是DR时,DR优先级高者胜出。
如果优先级相等,则Router ID大者胜出,DR优先级为0的路由器不会被选举为DR或BDR。
终身制也叫非抢占制。每一台新加入的路由器并不急于参加选举,而是先考察一下本网段中是否已存在DR。
如下图所示,如果目前网段中已经存在DR,即使本路由器的DR优先级比现有的DR还高,也不会再声称自己是DR,而是承认现有的DR。
因为网段中的每台路由器都只和DR、BDR建立邻接关系,如果DR频繁更换,则会引起本网段内的所有路由器重新与新的DR、BDR建立邻接关系。这样会导致短时间内网段中有大量的OSPF协议报文在传输,降低网络的可用带宽。终身制有利于增加网络的稳定性、提高网络的可用带宽。
如下图所示,继承制是指如果DR发生故障了,那么下一个当选为DR的一定是BDR,其他的路由器只能去竞选BDR的位置。
由于DR和BDR的数据库是完全同步的,这样当DR故障后,BDR立即成为DR,履行DR的职责,而且邻接关系已经建立,所以从角色切换到承载业务的时间会很短。同时,在BDR成为新的DR之后,还会选举出一个新的BDR,虽然这个过程所需的时间比较长,但已经不会影响路由的计算了。
使能了OSPF功能的接口会周期性地发送Hello报文,与网络中其他收到Hello报文的路由器协商报文中的指定参数,包括区域号、验证模式、发送Hello报文的时间间隔、路由器失效时间等参数。如果协商一致,则在返回的Hello报文的邻居列表中添加发送该Hello报文的设备的Router ID,双方建立双向通信,邻居关系建立。
邻居关系建立后,如果在路由器失效时间内没有收到邻居发来的Hello报文,则中断邻居关系。
OSPF邻居建立阶段有四种状态,具体如下:
Down:邻居会话的初始阶段,表示没有从邻居收到任何信息。在NBMA网络上,此状态下仍然可以以Hello Interval间隔,向静态配置的邻居发送Hello报文。其他网络是不会向失效的邻居路由器发送Hello报文的。
Attempt:此状态只在NBMA网络上存在,表示没有收到邻居的任何信息,但是已经周期性的向邻居发送报文。如果Router Dead Interval间隔内未收到邻居的Hello报文,则转为Down状态。
Init:表示已经收到了邻居的Hello报文,但是收到的Hello报文的邻居列表并没有包含本端的Router ID,双向通信仍然没有建立。
2-Way:互为邻居。本状态表示双方互相收到了对端发送的Hello报文,报文中的邻居列表也包含本端的Router ID,邻居关系建立。如果不形成邻接关系则邻居状态机就停留在此状态。
如下图所示,RTA和RTB的Router ID分别为1.1.1.1和2.2.2.2。在广播网络中,邻居建立过程如下:
当RTA启动OSPF后,RTA会发送第一个Hello报文。此报文中邻居列表为空,此时状态为Down,RTB收到RTA的这个Hello报文,状态置为Init。
RTB发送Hello报文,此报文中邻居列表为空,RTA收到RTB的Hello报文,状态置为Init。
RTB向RTA发送邻居列表为1.1.1.1的Hello报文,RTA在收到的Hello报文邻居列表中发现自己的Router ID,状态置为2-way。
RTA向RTB发送邻居列表为2.2.2.2的Hello报文,RTB在收到的Hello报文邻居列表中发现自己的Router ID,状态置为2-way。
OSPF邻接关系位于邻居关系之上,两端需要进一步交换DD报文、交互LSA信息时才建立邻接关系。
并非所有邻居都会建立邻接关系,是否建立邻接关系主要取决网络类型和DR/BDR。
在P2P链路和P2MP链路上,每一台设备都需要交换LSA信息,因此所有设备均需建立邻接关系。
在广播链路和NBMA链路上,因为DR Other之间不需要交换LSA信息,所以建立的是邻居关系。而DR与BDR之间,DR、BDR与DR Other之间需要交互LSA信息,所以建立的是邻接关系。如下图所示,两台DR Other各有三个邻居,但是分别只有两个邻接。
OSPF邻接建立阶段有四种状态,具体如下:
ExStart:这是形成邻接关系的第一个步骤,邻居状态变成此状态以后,路由器开始向邻居发送DD报文。主从关系是在此状态下形成的;初始DD序列号是在此状态下决定的。在此状态下发送的DD报文不包含链路状态描述。
Exchange:此状态下路由器相互发送包含链路状态信息摘要的DD报文,描述本地LSDB的内容。
Loading:两端设备发送LSR报文向邻居请求对方的LSA,同步LSDB。
Full:两端设备的LSDB已同步,本端设备和邻居设备建立了完全的邻接关系。
在广播网络中,邻接关系的建立过程如下图所示:
当RTA的邻居状态变为ExStart后,RTA会发送第一个DD报文。此报文中,DD序列号被随机设置为X,I-bit设置为1,表示这是第一个DD报文;M-bit设置为1,表示后续还有DD报文要发送;MS-bit设置为1,表示RTA宣告自己为Master。
当RTB的邻居状态变为ExStart后,RTB会发送第一个DD报文。此报文中,DD序列号被随机设置为Y(I-bit=1,M-bit=1,MS-bit=1,含义同上)。由于RTB的Router ID较大,所以RTB将成为真正的Master。收到此报文后,RTA会产生一个Negotiation-Done事件,并将邻居状态从ExStart变为Exchange。
当RTA的邻居状态变为Exchange后,RTA会发送一个新的DD报文,此报文中包含了LSDB的摘要信息,序列号设置为RTB在步骤2中使用的序列号Y,I-bit=0,表示这不是第一个DD报文,M-bit=0,表示这是最后一个包含LSDB摘要信息的DD报文,MS-bit=0,表示RTA宣告自己为Slave。收到此报文后,RTB会产生一个Negotiation-Done事件,并将邻居状态从ExStart变为Exchange。
当RTB的邻居状态变为Exchange后,RTB会发送一个新的DD报文,此报文包含了LSDB的摘要信息,DD序列号设置为Y+1, MS-bit=1,表示RTB宣告自己为Master。
虽然RTA不需要发送新的包含LSDB摘要信息的DD报文,但是作为Slave,RTA需要对Master发送的每一个DD报文进行确认。所以,RTA向RTB发送一个新的DD报文,序列号为Y+1,该报文内容为空。发送完此报文后,RTA产生一个Exchange-Done事件,将邻居状态变为Loading。RTB收到此报文后,假设RTB的LSDB是最新最全的,不需要向RTA请求更新,会将邻居状态变为Full。
RTA开始向RTB发送LSR报文,请求那些在Exchange状态下通过DD报文发现的、并且在本地LSDB中没有的链路状态信息。
RTB向RTA发送LSU报文,LSU报文中包含了那些被请求的链路状态的详细信息。RTA在完成LSU报文的接收之后,会将邻居状态从Loading变为Full。
RTA向RTB发送LSAck报文,作为对LSU报文的确认。RTB收到LSAck报文后,双方便建立起了完全的邻接关系。