开放路径最短优先协议OSPF基础
对比RIP
对比距离矢量路由协议(RIP),OSPF协议交换的不是路由条目,而是链路信息,并通过SPF算法计算出最佳路由,链路状态信息内含有路由接口、IP地址、掩码、cost值等,进而形成了链路状态通告(LSA)。
基本术语
- 邻居表:也成为邻接数据库,通过Hello包建立邻居关系,包含自己所承认的邻居名单。
- 链路状态数据库(LSDB):OSPF学来的LSA存放处,同一个区域的LSDB一样
- 路由表:使用SPF算法,算出以自己为根,到达目的地最短、最佳无环路径,形成路由表。通常称为转发数据库,达到目的的最佳路径列表。
- 区域边界路由器(ABR):位于不同区域边界上的路由器
- 自治系统边界路由器(ASBR):它连接一个OSPF域与其他路由协议域(比如BGP),简单来说就是沟通OSPF与其他协议的桥梁
OSPF区域
OSPF虽然不受路由器数量限制,但是网络中路由器太多,相互交换的LSA也会增加,随之而来的网络负担也会变大,因此需要给OSPF路由器划分区域。
区域主要分为两种:
- 骨干区域,又叫传输区域
- 常规区域
常规区域主要限制了这一个区域之间的通信,多个常规区域之间一般是相互隔绝的,如果它们之间进行通信需要经过骨干区域转发。因此常规区域一定与骨干区域相连。
OSPF寻路
OSPF寻找最佳路径采用Dijkstra算法,也叫最短路径优先(SPF)算法:
- 在同一个区域每个路由器都有一个相同额链路状态数据库
- 每台路由器建立由本身为根到目的的树(即然是树,则无环)
- 到特定目的总成本最低的链接放入路由表
一段链路的成本或者说度量的计算如下(默认情况):
$$ Cost = \frac{10^8 bps}{Bandwith} $$
到达目的的链路总成本为每段链路成本之和:
$$ TotalCost = \sum_{i=1}^{n} Cost_i $$
此处带宽的单位为bps(比特每秒),其中参考带宽在默认情况下为1E8 bps
这里需要注意,在使用默认值的情况下,我们无法比较百兆带宽和千兆带宽哪个好(本文对于带宽的单位都以比特每秒为基础,例如百兆为100Mbps)。
当带宽为100Mbps的时候,代入公式成本为1;当带宽为1000Mbps的时候成本为0.1,按1算。
可以通过修改参考带宽来区分百兆和前兆网络,在思科路由器上可以采用一下命令:
Router(config)#router ospf 100
Router(config-router)#auto-cost reference-bandwith ref-bw
其中ref-bw为你需要设置的参考带宽的值,范围在1-4294967M/s
还有一种方式是直接设置成本(假设入方向接口为g0/0)
Router(config)#interface g0/0
Router(config-if)#ip ospf cost int-cost
其中int-cost替换为你所需要设置的值,范围在1-65535之间。
关于该算法具体流程请参考数据结构与算法。
OSPF报文格式
OSPF报文头
OSPF报文头如上图所示,包含如下字段:
- Version: OSPF版本,占用1字节,OSPFv2此处为2,OSPFv3此处为3
- Message Type: 报文类型,占1字节。1表示Hello报文,2表示DD报文,3表示LSR报文,4表示LSU报文,5表示LSAck报文。
- Packet Length: OSPF报文总长度(包含头部和主体),占用2字节。
- Router ID: 发送方路由器ID,与IP地址长度一致,占用4字节。
- Area ID: 发送报文路由器接口的所属区域ID,占用4字节。
- Checksum: 除了认证信息以外的报文的校验和,占用4字节。
- AuType: 校验方法,0表示不验证,1表示简单验证,2表示MD5验证,占用2字节。
- Authentication: 认证信息,占用8字节。验证类型为0时未定义,验证类型为1时该字段是密码信息,类型为2时该字段包括Key ID、MD5验证数据长度和序列号的信息。MD5验证数据添加在OSPF报文后面,不包含在Authentication字段中,占用8字节
我们来看下报文内容,以下图片要拼接上上图的报文头才是一段完整的OSPF报文。
Hello报文
Hello报文内容部分(不包括报文头)如上图所示:
- Network Mask:Hello报文发送的路由接口对应的子网掩码,占4字节。
- HelloInterval:表示Hello报文的时间间隔,单位为sec,占用2字节。
- Options:表示可选项,占用1字节。E表示允许泛洪AS-External LSA(5类),MC表示转发IP组播报文,N/P表示处理Type-7 LSA(7类LSA),DC表示处理按需链路,占用1字节。
- Rtr Pri:表示DR优先级,默认为1,如果为0表示不参与DR/BDR选举,占用1字节。
- Router Dead Interval:表示失效时间,在此时间内未收到邻居发来的HELLO报文,则认为邻居失效,占用4字节。
- Designated Router:表示本网段DR的接口地址,占用4字节。
- Backup Designated Router:表示本网段BDR的接口地址,占用4字节。
- Neighbor:表示邻居类表,以router ID的方式呈现,占用4字节。
DD报文(DBD)
- Interface MTU:表示发包接口所能发出的数据包的最大长度,单位为字节,在部分片的情况下,此接口最大可发出的IP报文长度,由OSPF虚链路发出的DD数据包接口的MTU字段必须设置为0,占用2字节。
- Options:可选项,E表示允许泛洪AS-External LSA(5类),MC表示转发IP组播报文,N/P表示处理Type-7 LSA(7类LSA),DC表示处理按需链路,占用1字节。
- I位:表示邻居双方发出的首个DD数据包,当发送多个DD报文的时候,如果这是第一个DD报文,则置为1,否则置为0,占用1位。
- M位:表示DD数据包未发送完毕,当多个DD报文发送时,如果这是最后一个DD报文,则置为0,如果不是则置为1,表示后面还有其他DD报文,占用1位。
- MS位:表示主从,当两台OSPF设备交互DD报文时,需要确定双方主从关系,router-ID大的一方成为主路由器,置为1时表示DD交互过程中,发包路由器为主路由器,置为0时则为从路由器。
- DD sequence number:表示由主路由器设置的唯一序列号,在数据库交换过程中使用,只有主路由器才能增加此字段的值,主从双方利用序列号保证DD报文传输的可靠性和完整性(隐式确认),占用4字节。
- LSA Headers:用于描述本端运行OSPF设备的LSDB信息,在协商主从关系时,发送的DD报文是不包含LSA Headers。
LSR报文
- LS Type:表示指定所需的LSA类型,常见的有6类type-1:Router LSA,type-2:Network LSA,type-3:Network Summary LSA,type-4:ASBR Summary LSA,type-5:AS External LSA,type-7:NSSA LSA,占用4字节。
- Link State ID:LSA标识,用于与LS Type一起描述路由域中唯一一个LSA,占用4字节。
- Advertising Router:表示产生该LSR路由器的Router-ID,占用4字节。
LSU报文
- Number of LSAs:LSA的数量,占用4字节。
- LSAs:回复LSR报文请求的完整LSA信息。
LSAck报文
通过LSA的头部信息确认收到该LSA
OSPF基本原理
LSA
每个LSA在LSDB中都有一个序号。此序号的大小为4个字节,则编号有2的32次方个,数字范围从0x80000001到0x7FFFFFF。
此处我们先来看看0x80000000
的二进制位为1000 0000 0000 0000 0000 0000 0000 0000
,最高位为符号位,后面的31位为序号位,并不是值位,也就是说1后面的31位为000 0000 0000 0000 0000 0000 0000 0000
表示为1,其含义为负数中从小到大的第一个数,即int32类型的最小值-2147483648。
而对于0x7fffffff
来说,符号为为0,是一个正数,而后面的31个序号位都为1,表示2的31次方,也就是2147483647
。
换句话说,LSA编号的范围与int32
类型的范围一致。
我们回到LSA上来,对于LSA有如下情况:
- 每个30分钟路由的LSA进行一次泛洪,以保证LSDB同步,每次序号+1
- 最终一个LSA会从
0x7FFFFFFF
循环回0x80000001
,如果发生这种情况,这个LSA会被路由器将老化时间设置为60分钟,并从LSBD清除。 - 当路由接收到两个一样的LSA,序号最高的就是最新的。
当路由器接收到一条LSU报文的时候,判断LSA在本地是否存在,判断要素有三个:
- LSA类型
- Link ID
- ADV-router(通告路由器)
上述三要素如果存在任何一个不同,那么这条LSA在本地不存在。
如果这条LSA是首次更新,之前不存在,就直接放到数据库表内,回应LSAck报文。如果这路由器外还连接着其他路由,则继续泛洪给其他路由,5秒后,运行SPF算法,更新本地路由表。
如果之前存在,判断是否是最新的,通过序号大小决定是否最新:
- 如果序号不同,序号比现在大则添加到数据库,序号小则不采纳。
- 如果序号相同,则会忽略掉这条LSA,仍然回应LSAck到邻居。
(Tips:判断序号是否相同,不光可以比较序号,还可以看生存时间和校验和)
Hello包
通过发送Hello包,建立邻居关系形成邻居表。Hello发送时间间隔根据网络类型而定:
- 10秒:以太链路、P2P链路(PPP、HDLC、帧中继点对点字接口)
- 30秒:NBMA(非广播-多路访问网络 Non-Broadcast Multiple Access)—— 帧中继字接口或帧中继多点子接口等、点到多点、点到多点非广播
- Dead Time是Hello时间等4倍
多路访问网络(MA网络),是指一条物理信息可以发送给同一个网络上的其他路由器,其类型有两种:
- BMA广播型多路访问网络(如一台二层交换机上连着多个路由器)
- NBMA非广播型多路访问网络
影响邻居建立要素如下:
- Router ID必须不一致
- Hello与dead时间必须一致
- 区域ID一致
- 认证一致
- MTU一致
- 特殊区域字段一致
- MA接口掩码一致
- 两边都放弃选举
两台互联的OSPF路由器不会上来直接交换整个LSA,而是先交换LSA目录,然后根据目录缺少的条目,再向邻居请求。
当路由收到具体的请求内容消息的时候,回应请求的更新,这里面有真正的LSA。当请求方接收到LSA后,要回应确认包,确认包只针对Update包确认,区别于EIGRP。
综上,大致分为5步:
- A-B先通过Hello建立邻居
- 交换LSA目录
- 针对没有的进行具体请求
- 回应邻居的请求,包含具体LSA
- 请求方收到LSA后进行更新并回复确认包
Router ID
每一个路由器都有一个唯一的Router-ID来区分不同路由器,形式类似于IP地址(点分四段十进制数,32位字符串,但不是IP地址)。
Router ID配置有如下优先情况:
- 在OSPF配置模式下,使用Router ID配置一个路由器ID
- 如果回环接口(loopback interface)配置了IP地址,那么该地址为Router-ID。如果有多个回环口,则使用这些接口里最高的IP地址。
- 无回还接口,则ID是路由器上活动接口中最高的IP地址。
我们使用Cisco路由器为例,来进行演示
6Router(config)#interface loopback 0
Router(config-if)#ip address 172.16.17.5 255.255.255.0
Router(config-if)#no shut
Router(config-if)#exit
Router(config)#do show ip ospf
注意如果OSPF进程如果已经运行,要想使配置生效,必须在特权模式下执行clear ip ospf process
重新启动OSPF进程才行。
通过show ip ospf
命令,我们可以看到当前Router ID与我们配置的loopback 0
接口的IP是一致的。
我们再来使用router-id
命令来手动设置ID试一试。
顺带一提,Cisco路由器OSPF默认进程号为100,也就是说要进入进程号为100的OSPF进程配置模式下修改!
进入OSPF进程配置命令如下,这个命令后如果跟别的数字则会激活别的OSPF进程。
Router(config)#router ospf 100
Router(config-router)#router-id 1.1.1.1
Router(config-router)#exit
Router(config)#do clear ip ospf process
Reset ALL OSPF processes? [no]: yes
Router(config)#do show ip ospf
我们可以看到Router-ID已经变成了刚才指定的1.1.1.1
OSPF五种网络类型
数据链路层
我们先来看下数据链路层的一些东西,OSPF网络类型与数据链路层的这些对应。
- Point-to-Point点到点子接口(HDLC,PPP,Frame Relay)
- Multiaccess多访问网络:分为,Broadcast广播的多路访问网络(Ethernet,以太网)和Nonbroadcast multiaccess非广播型多路访问(NBMA)
OSPF网络类型
前三种与数据链路层对应
- P2P点到点
- 广播型多路访问
- 非广播型多路访问
后面两种要想用,只能修改接口连接类型
- 点到多点、点对点的集合
- 点到多点的非广播
其实还有一种特殊的网络类型(五种网络类型有六个不是很正常吗,雾OWO)
- Loopback
我们考虑OSPF网络类型主要是因为以下几种问题:
- 是否需要DR/BDR选举
- 是否自动建立邻居
- 分别使用的目标更新地址
- 五种网络类型的Hello时间间隔
- 32位主机路由的特殊类型
DR/BDR选举
DR/BDR选举可谓OSPF非常重要的一个环节。
为什么需要选择DR和BDR
多接入网络对OSPF的LSA泛洪提出了两项挑战:
- 建立多边邻接关系:以太网可能会在普通链路上出现许多OSPF路由器,不需要也最好不要与每台路由器都建立邻接关系。如果邻接关系过多,则会导致网络内路由器间交换大量LSA。
- LSA大量泛洪:OSPF初始化或者拓扑发生变化时,链路状态路由器就会泛洪自己的LSA,该过程的量和时常可能会非常大,导致网络拥塞。
选举过程
解决上述提到的问题的方案就是选出DR(指定路由器),在存在DR的情况下,如上图右侧,ABCE路由器所有更新信息都会发送给DR,DR将拥有最完整的数据库信息,之后借由DR告知ABCE对应的邻居路由器更新条目。
DR的选举依靠Hello包的优先级和Router-ID:
- 优先级最高的为DR,次高为BDR
- 优先级相同,Router-ID高的为DR,次高为BDR
- 不是DR和BDR的路由器被称为DRother
总之,DR和BDR选举都是通过优先级——RouterID的顺序来进行的。
这里需要注意,在OSPF协议中数值大的就越高,在其他一些协议中有些是数值越小越高。
在Cisco路由器中可以这样来设置优先级:
Router(config-if)# ip ospf priority [number]
命令中的number范围为0-255(包括0和255)。默认情况下优先级为1,不同的接口可能有不同的值,优先级为0的将永远不参与竞选DR和BDR。
当BDR失效后,重新选举BDR。当DR失效,但BDR没有失效,则原来的BDR变成DR,再重新选举BDR。
选举期一般为40秒,在选举期外不存在抢占。
DR与BDR选举完成后,DRother只和DR/BDR存在邻接关系,所有路由器将组播Hello包到地址224.0.0.5
,以便它们能跟踪消息。
对于LSU,DRother只组播到224.0.0.6
,只有DR和BDR会监听这个地址。
维护路由信息
我们来看上图,当A下面的网络变化时,A向224.0.0.6
发送LSU,告知DR,DR向224.0.0.5
发送LSU告知DRother。在这个过程中BDR也是在监听DR与DRother的消息的。
如果BDR不这样做,当DR失效,但是没有来得及通知BDR,导致原BDR称为DR时仍认为A下的网络是有效的。
邻居状态机
介绍
OSPF接口可以处于以下8种状态:
- 停止Down:OSPF没有与任何路由器交换信息
- 尝试Attempt: 仅存在NMBR环境中
- 初始Init:路由器接收到一个Hello分组后进入该状态
- 双向Two-way:在邻居报文中看到自己的ID后进入该状态
- 准启动Exstart:通过第一次DBD报文来确定邻居间的主从关系
- 交换Exchange:通过DBD交换LSA的头部信息
- 加载Loading:发送LSR和LSU
- 完全邻接Full adjacency:完成了邻接关系的完整建立
OSPF状态过渡流程如下图所示
Down状态
本地一旦发出Hello包就立即跳出Down状态,进入下一状态。因此Down状态即为没有启用OSPF状态,邻居失效后也是该状态。
当启用OSPFv2的时候,已经启用的Gigabit Ethernet 0/0
从Down状态变为Init状态。R1开始通过所有启用OSPF协议的接口发送Hello数据包,发现要建立临接关系的OSPF邻居(此时为自动发现邻居模式,此状态看不到;当手动指定邻居的时候可以看到邻居表里有Down状态)。
这里有一个问题,当R1发送Hello包的时候应当是处于哪种状态?其实很简单,R1的G0/0接口在宣告OSPF进程的时候,就会发送Hello包,但是对端没有邻居,所以看不到Down状态(Down是与邻居关系的状态,没邻居看不到此状态)。
第一个Hello包含内容大致如下:
- 自己的Router-ID(不能一致)
- Hello时间(必须一致)
- Dead时间(必须一致)
- 区域(必须一致)
- 特殊区域字段(必须一致)
- 认证(必须一致)
注意对于此Hello包是进行组播到224.0.0.5
,但是对于回包是单播。
Init状态
R2从R1接收Hello数据包,并将R1的Router-ID添加到R2的邻居列表。随后R2向R1发送Hello数据包(单播),数据包在同一接口的邻居列表中包含R2的Router-ID与R1的Router-ID。(在R1收到这个包之前,R1都是Init)
上图中Router-ID为3.3.3.3
的代表R3,4.4.4.4
的为R4,其余同理。
我们来看上方图中R3和R4各自的邻居关系。我们手动指定R4将R3点包过滤掉,但是R3可以接受R4的包。令R3发送Hello包给R4,R4将包丢弃,因此在上图的R4邻居表中是没有R3的信息的。然而R4发送给R3一个Hello包,但是R3能接收到,所以R3的表中有R4的信息,且R4的状态显示为Init状态。
简单来讲,收到一个不包含自己信息的Hello包进入Init状态。
因此对于最上方图中的R1和R2,当R2接受到来自R1的Hello包的时候,R1并不知道R2的表中是否已经包含了R1的Router-ID,所以R1此时状态为Init,直到R1收到我们上方所说的R2的包的时候。
可以看出Init状态是一个很短暂的状态,如果长期处于该状态一般是不正常的。
Two-way状态
R1接收到了来自R2的Hello包后,把R2的Router-ID添加到本地的OSPF邻居表中。另外,R1还看到了R2的邻居表中包含R1的Router-ID,说明双方都知道了各自的Router-ID,此时R1就可以放心地进入Two-way状态了。
总结来讲就是,收到一个包含自己信息的Hello包即进入Two-way状态。
Two-way状态后接下来会怎么做取决于邻居之间的链路:
- 如果它们之间的链路为点对点(P2P)的话,会立刻从Two-way进入ExStart状态
- 如果它们之间通过通用的以太网(严格来讲应该是多访问链路)相互连接,则开始选举DR和BDR,此时Two-way状态会停留40s,也就是我们在前文中提到的40s选举期
这里说明下,之所以进入选举,是因为接下来的状态DBD需要自己确认自己就必须选出Master来主持。
ExStart状态
当Hello数据包用于建立邻接关系的时,在交换和同步LSDB的过程中,使用其它四种类型的OSPF数据包。
在ExStart状态下,这两个路由器确定是哪个路由器首先发送DBD数据包。当处于ExStart状态时,都认为自己是主的,告诉别人自己的Router-ID,并说明准备发送DBD了,在相互传递完信息后,了解到谁的Router-ID大,谁发送DBD。
ExChange状态
使用LSAck数据包确认收到DBD。
R1收到来自主路由R2的DBD后,将收到的信息与其LSDB中的信息进行比较,如果DBD数据包有较新的链路状态条目,路由器将转换为Loading状态。然后,R1将DBD数据包发送到R2,R2确认R1。
在ExChange状态下,两个路由器交换一个或者多个DBD数据包。DBD数据包包括路由器LSDB中显示的LSA条目报文头的相关信息。条目可与链路有关,也可与网络有关。每个LSA条目报头包括关于链路状态类型、通告路由器的地址、链路开销以及序列号信息。
路由器使用序列号来确定接收到的链路状态信息的更新程度。
Loading状态
该状态下使用LSR和LSU用于获取更多的路由信息。路由使用SPF算法进行处理。
当如图所示,R1向R2发送与网络172.16.6.0有关的完整信息,同样,R1接收到LSU时,它会发送LSAck。R1岁后将新的链路状态添加到其LSDB。
Full状态
当所有LSR满足特定路由要求时,邻接路由器被视为已同步并处于Full状态。OSPF路由器只会在以下情况发送LSU更新:
- 发现更改时(增量更新)
- 每30分钟
Full状态表示路由器已经收敛。
关于DBD
DBD实际上是自己确认自己。
- 第一步:当Init状态的时候交互DBD,此时DBD内容是空的。
- 第二部:交互DBD时期,此时含有真正内容的DBD报文,此步骤后进入ExChange状态
再谈LSA
LSA类型
type 1 LSA - Router LSA
type 1 LSA有如下特点:
- 只在本区域洪泛,不会穿越ABR
- 每一个运行OSPF的路由器都会生成一个路由器LSA
- 内容包括路由信息(前缀、掩码)和拓扑信息(另一个路由的Router-ID和自己的IP)
- Link-ID为路由器的Router-ID
type 2 LSA - Network LSA
type 2 LSA有如下特点
- 只在本区域洪泛,不穿越ABR
- 由MA(广播型和NBMA,选DR/BDR的网络)网络的DR产生
- 内容需要联合type 1 LSA一共描述出网络的拓扑与路由
- Link-ID为DR接口的IP地址
type 3 LSA - Network Summary LSA
- 洪泛于整个自治区域
- 起源于ABR,每经过一个ABR通告路由器会发生改变(简单来讲,就是ABR1发送type 3 LSA被ABR2接收到,ABR2替换该LSA中的某些字段为ABR2的信息,这样ABR2区域下的路由就不知道ABR1存在,只知道ABR2)
- type 3 LSA用于通告一个区域的信息给其他区域,包含一条路由信息(这里的意思是,Area1中有几个路由信息就产生几条LSA)
- 描述链路的网络号和掩码
- Link-ID为这条路由信息的前缀
默认情况下,没有路由的自动汇总,type 3 LSA通告每个子网。由于扩散范围广,所以需要手动汇总。一个良好的网络规划,每个区域应该利于做OSPF手动汇总。
type 4 LSA - ASBR Summary LSA
- 原则来讲洪泛于整个OSPF自治区域,但实际上范围与区域结构的设计有关
- 起源于ABR,当一个ABR监测到ASBR存在时,它会生成一个type 4 LSA广播到OSPF所有区域。
- type 4 LSA包含如何到达该ASBR的路由信息,使得其他区域内的路由可以知道该ASBR。
- Link-ID为ASBR接口的Router-ID
type 5 LSA - External Summary LSA
- 洪泛到OSPF所有区域
- 起源于ASBR,当ABR收到该LSA时会转化成type 4 LSA然后洪泛到其他区域
- 包含表示外部路由信息
- Link-ID:通常是目标网络的地址
type 6 LSA - Multicast OSPF LSA
- 当有多个自治系统(AS)时,每个AS可能由多个组织构成,该LSA在组织内部洪泛。
- 该LSA包含AS内部的路由策略和标记等。
type 7 LSA - NSSA LSA
- 只在NSSA内部传播,NSSA是非完全稳定区域,是OSPF的一个扩展,这些区域内部的ASBR生成type 7 LSA而非type 5 LSA
- 起源ASBR,该LSA用于表示外部路由信息
- 当该LSA被NSSA ABR接收,会被转换成type 5 LSA,然后在非NSSA区域进一步洪泛。
- Link-ID通常为对应的外部网络的网络地址。
type 8 LSA - Link Scoped Prefix LSA
- 链路范围前缀LSA,用于传播链路本地地址和链路范围前缀。在链路内部洪泛。
- 在链路上如果有多个节点配置了相同的本地链路地址或者链路范围前缀,为了避免冲突需要type 8 LSA将这些信息传播到其他链路。
- Link-ID为对应接口的接口ID
总结
其实OSPF协议的用法远不止这些,还有很多复杂的问题需要具体分析。诸如6类、8类等LSA对于一般的网络并不常用。