1. 基本概念
概述
ospf使用的算法是:Dijkstra算法,也称SPF(Shortest Path Frist 最短路径优先)。所以ospf的全称为:开放式最短路径优先(Open Shortest Path Frist)。
常见的ospf协议有:OSPFv2、OSPFv3。OSPFv3是面向IPv6的且不兼容IPv4,所以本文主要介绍OSPFv2
特点
链路状态路由协议是层次式的,网络中的路由器并不向邻居传递“路由项”(如RIP协议),而是通告给邻居一些链路状态。运行该协议的路由器把网络中所有路由器分成区域,收集区域内所有路由器的链路状态信息,根据状态信息产生网络拓扑结构,每一个路由器再根据拓扑结构计算出路由。这就对路由器的CPU和内存要求比较高
工作过程
- 每台路由器学习激活的直连网络
- 每台路由器和直接相连的路由器发送hello报文,建立邻居关系
- 每台路由器构建链路状态数据包即 LSA (Link-State Advertisement,链路状态通告)。链路状态通告(LSA)中记录了所有相关的路由器,包括邻路由器的标识、链路类型、带宽等。
- 每台路由器将构建好的LSA泛洪给邻居,并且自己也在本地存储邻居发送过来的LSA,然后再将自己收到的LSA泛洪给所有邻居,直到同一区域中所有路由器收到了所有LSA。每台路由器在本地数据库中保存所有收到的LSA副本,这个数据库被称作“链路状态数据库”(LSDB,Link-State DataBase)
- 每台路由器基本本地的LSDB执行 “最短路径优先算法”(SPF),并以本地路由器为根,生成一个SPF树,基于这个SPF树计算去往每个网络的最短路径,也就得到了最终的路由表
下图演示了ospf协议路由表的生成过程

2. 专业术语
- 链路(Link):当一个接口加入OSPF进程,就被当做是OSPF的一条链路。
- 链路状态(Link-State):包括接口的IP、子网、网络类型、链路花费、链路上的邻居等。
- 路由器ID(Router ID,简称RID):RID是一个用来标识路由器的IP地址,可以在OSPF路由进程中手工指定;如果没有指定,路由器默认选择回环接口中最高的IP作为RID;如果没有回环地址,路由器使用所有激活的物理接口中最高的IP作为RID。
- 邻居(Neighbor):两台或多台路由连接在一个公共的网络上;比如两台路由通过串行线路相连,或多台路由通过以太网相连。
- 邻接(Adjacency):邻接是两台路由器之间的关系,OSPF只与建立了邻接关系的邻居共享路由信息。
- 区域(Area):OSPF通过划分区域来实现分层设计,跨越两个或两个以上区域的路由被称作ABR(Area Border Router,区域边界路由)。所有的区域都和”Area 0″相连,”Area 0″被称作骨干区域,骨干区域路由器具有整个自制系统中所有路由条目,LSA的扩散仅限制在区域内,通过划分多个区域可以减小LSA扩散过程中对硬件的负担。
- 指定路由器(Designated Router,简称DR):当OSPF链路被连接到多路访问的网络中时,需要选择一台指定路由器(DR),每台路由器都把拓扑变化发给DR和BDR,然后由DR通知该多路访问网络中的其他路由器。
- 备用的指定路由器(Backup Designated Router,简称BDR):当DR发生故障的时候,BDR转变成DR,接替DR工作。
- 花费(Cost):OSPF中使用的唯一度量值,使用链路的带宽计算得来。
3. ospf的网络类型
点到点
将一对路由器连接起来的网络,使用的是PPP HDLC协议(Point to Point Protocol)
使用组播224.0.0.5来发送各种数据包
没有DR/BDR的选举,直接形成full邻接关系,不用手动指邻居

广播
多路访问网络,如以太网,需要DR和BDR的选举,不用手动指邻居
通常以组播发送HELLO报文,LSU报文,和LSACK报文,以单播形式发送DD和LSR报文
DR和BDR给非指定路由器发送消息使用的是组播224.0.0.5
非指定路由器给DR和BDR发送消息使用的是组播224.0.0.6

非广播多路访问
NBMA, Non-Broadcast Multiple Access
连接的路由器超过两台但是没有广播功能,帧中继网络和ATM网络
所有数据包均单播发送,有DR的选举,需要手动指定邻居

点到多点
Hello包以组播形式发送,其他类型数据包由单播发送
不选举DR,不用手动指邻居

4. ospf报文类型
ospf直接封装在IP数据包中
Hello包
作用:建立邻居关系
各字段功能:
- Network Mask :发送数据包的源IP地址对应的子网掩码
- Hellointerval:Hello时间间隔,默认10S,失效间隔默认为Hello间隔的3倍
- Rtr Pri:路由器优先级用于选举DR和BDR
- DR:指定路由器的IP地址,开始时为空
- BDR:备份指定路由器的IP地址,开始是也为空
- Neighbor:里面标识了邻居的路由器ID,可以表示多个邻居
- Stub and Flag :末节标识符
邻居关系建立条件:HELLO和失效间隔要一致,区域号要相同,区域末节标识符要相同,有认证的话,认证要相同,区域ID要相同,子网掩码要一致
DBD包(Dadabase Description)
作用:在OSPF邻居关系建立之后,DBD包负责描述本地的LSDB,接收到的路由器通过和自己的LSDB做比对,进而同步区域中的LSDB
各字段功能
- I:该位置1表示这是发送的第一个数据包,开启了LSDB同步过程
- M:该位置1表示之后还有DD包要发送,若置0则表示没有数据包要发送了
- MS:用来表示谁是主(Master)谁是从(Slave)由主路由器引导进行LSDB的同步
- DD Sequence Number:利用序号来确保传输的完整性和可靠性
- LSA Headers:LSA头部信息摘要,可以有多个LSA头部摘要信息
LSR包(Link-State Request)
作用:用来查询本LSDB中没**有或者哪些LSA是已经失效的**
各字段功能:
- LS type:指定所请求的LSA类型,一共有7类
- Link State ID:用来表示LSA,根据LSA种类的不同,有不同的含义
- Advertising Router:用来表示产生此LSA的路由器ID
LSU包(Link-State Update)
作用:对LSR进行回应,或者定时发送LSU来更新区域中的LSDB,发送的是真正需要的LSA的内容
各字段功能:
- Number of LSA:指定此报文中共发送的LSA数量
- LSAs:一条条具体的LSA完整的信息,可以有多个LSA的信息
LSAck包(Link-State Acknowledgedment)
作用:用来在收到对端发送的LSU之后返回的确认报文,内容是需要确认的LSA头部
各字段功能:
- LSA Headers:LSA头部信息
- 一个ACK可以确认多个LSA
5. LSA
Link State Advertisement,链路状态通告,路由器发出的关于网络结构的通告,描述了链路或接口的状态及每条链路的成本
LSA是一种数据结构,保存在LSDB中,承载在LSU中然后发送出去,LSDB中会存储与网络有关的一系列属性。
LSA只能由发起这个LSA的路由器进行操作和更新或者是撤销,别的路由器不得对其进行操作,只能对其进行泛洪,不能阻塞这个LSA,也不能在这个LSA的最大时长计时器前丢弃这个LSA。
6. DR和BDR选举规则
首先用下面的图来说明一下为什么多路访问的以太网中需要选举DR和BDR,选举它们有什么好处:

在上图的多路访问的网络中,如果没有选举DR和BDR,为了交互路由信息,每台路由器都需要和其他路由建立邻接关系,就会有10个邻接关系,如果其中一台路由离开,要和所有的路由断开邻接关系,新的路由加入,也需要和所有路由建立邻接关系,这样会影响收敛效率。
如果选举了DR和BDR,那么所有DROther路由器只需要和DR以及BDR建立邻接关系即可
选举规则:
- OSPF路由器选择网络中接口优先级最高的路由器为DR,接口优先级次高的路由器为BDR,以太网接口默认的优先级都为1,串行线路不需要选举所以是0。也可以手工指定: 进入参加选举的接口,ip ospf priorty 0
- 如果优先级相同,将使用RID最高的为DR,次高的为BDR。
- 先来先是
7. 邻接建立过程
首先对邻居关系,和邻接关系要区分开,两台路由器互相之间的状态是2-way则表明邻居关系建立,当邻居关系为FULL是表明邻接关系建立
关系变换过程
down->init->2-way->exstart->exchange->loading->full
图解:

- down:表示还没有建立起邻接关系,没有检测到活动邻居
- init:表示从对端收到的HELLO包中,没有自己的路由器ID信息
- 2-way:表示从对端收到的HELLO包中,已经有自己的路由器ID信息了,已建立邻居关系可以共享链路状态数据
- exstart:表示正在确定主从关系,即谁先发送DBD
- exchange:在主的带领下开始交换DBD
- loading:请求更详细的信息
- full:已建立完全邻接关系 完成更新过程 其数据库与邻居完全相同
8. 模拟演示
拓扑图:

基本配置
以R1为例:
R1#conf
R1(config)#no ip domain-lookup
R1(config)#line console 0
R1(config-line)#no exec-timeout
R1(config-line)#logging synchronous
R1(config-if)#int lo 0
R1(config-if)#ip add 1.1.1.1 255.255.255.0
R1(config-if)#no shut
R1(config-if)#int s0/0
R1(config-if)#ip add 10.4.1.1 255.255.255.0
R1(config-if)#no shut
R1(config-if)#int e1/0
R1(config-if)#ip add 10.4.2.1 255.255.255.0
R1(config-if)#no shut
R1(config-if)#exit
R1(config)#router ospf 100 // 进程号,只具有本地意义,每个路由器进程号可以不同
R1(config-router)#net 1.1.1.0 0.0.0.255 area 0
R1(config-router)#net 10.4.1.0 0.0.0.255 area 0
R1(config-router)#end
R2、R3配置相同,注意接口IP地址
当你配置完会跳出来这一行命令

由于我使用了环回口,所以R1路由器的两个邻居为:2.2.2.2 和 3.3.3.3;FULL表示已建立邻接状态
路由表

在OSPF中所有的回环接口都被自动宣告成32位的主机路由”/32″,如果想显示回环接口的实际子网掩码,可以使用下面的命令调整:
// 在R1、R2、R3宣告ospf的环回接口上执行下面的命令
R1(config)#int lo 0
R1(config-if)#ip ospf network point-to-point
邻居表

- Pri:接口的优先级,接口优先级用于DR和BDR的选举
-
- 以太网接口接口的默认优先级是1,串行线路不需要选举DR和BDR所以优先级是0
- 0代表不参与选举
- State:邻居路由器状态,FULL代表已经建立临接关系
-
- 斜杠”/“后面是选举的DR或BDR标识,因为串行线路不需要选举,所以是”-“
- ”FULL/BDR“表示R2是BDR,R3是DROTHER,除了DR和BDR的其余路由器都是DROTHER
- 所以R1自己就是DR了
- Dead time:默认的死亡时间是hello时间的4倍,即40秒。
-
- 死亡时间是一个倒计时,计时器为0时,该邻居被删除
这边有些朋友会有疑问:按照上文的DR、BDR选举规则,路由器优先级一样、接口优先级一样、R2的Router ID比R1的大,那么为什么R1是DR呢?
DR选中规则中还有一条:先来先是。我先配的是R1,所以R1是DR;但是如果我同时重启3台路由器的ospf进程,那么DR就是R3
拓扑表

在同一区域中,所有路由器的ospf的拓扑表都是相同的;
原因:
LSA承载在LSU中发送出去,当收到LSR请求后,会发送LSU;
路由器会泛洪所有邻发来的LSA,也会保存一份副本在本地LSDB中;
所以多次交换、更新后,同一区域的LSDB都会一样
Router ID选举规则

默认选举的 ID 是环回口的地址
也可以手工配置
R1(config)#router ospf 100
R1(config-router)#router-id 8.8.8.8

可以看到Router ID 已更改
这时候为啥R2变成DR了呢?
R1 Router ID 不是最大的吗?
因为R2原来是BDR,R1重配Router ID时结束了ospf进程,代表DR出故障。这时候BDR自动升级为DR,DROTHER升级为BDR;
避免重新选举DR占用过多的CPU和内存资源
侧面也可以看出,是先选出BDR,再选出DR
选举规则
- 手工配置
- 没有手工配置,就根据loopback的地址,loopback大的为Router ID
- loopback也没有配置,就根据所有已激活接口的最大地址为Router ID
本文完
敬爱与明天🌹