1、背景
我们都知道,任何新技术的诞生,都是有它一定的自然规律的。绝逼不是凭白无故的产生。所以,龙哥希望大家学习一个技术时,学会多关联相关协议,联想他们各自的特点,学会把知识串联起来,这样你就不会觉得学技术好难啊,就不会总是跟龙哥抱怨:总是记不住怎么办呢?
会有链路状态协议的OSPF产生,是因为前面距离矢量路由协议存在两个非常严重的问题:
1、收敛速度缓慢,就是太磨叽了;
2、容易产生路由环路。
OSPF,全称OpenShortestPathFirst,即开放最短路径优先,是由IETF的OSPF工作组在年10月开发的,发表的RFC为,OSPFv1从此诞生,该协议是基于著名的DijKstra算法。不过版本1一直都是在实验室中使用,未推广成功。版本2才开始被广泛使用,在RFC说明。
注:
IETF:国际互联网工程任务组(TheInternetEngineeringTaskForce,简称IETF。年年底成立。
2、LSDB
LSDB,全称是LinkStateDataBase,链路状态数据库。为啥会有它呢?还不是因为距离矢量路由协议RIP,是个“传言”路由协议,在距离矢量路由协议中,邻居说有啥路由,你就信啥,你心中自己都没有一张地图,就很容易经常被骗,所以会导致环路。所以OSPF干脆就给区域内每台路由器都搞一张地图,这样就不会上当受骗了,这个地图就是LSDB,这样就使得OSPF可以保证区域内无环,区域间无环,通过一些规则来限制,这样区域内外都能保证无环。下面,简单介绍一下:
简单说明一些,区域内路由器一旦配置了OSPF,每台路由器就会开始泛洪LSA(包含IP地址、掩码、开销、网络类型等信息),每台都能收到LSA,会构建一张数据库,即LSDB。
然后每台路由器都会以自己为根节点,构建一颗最短路径树,然后从这棵树中计算路由,将最优的放进路由表,用于指导业务数据转发。
可能上图小白看着会觉得有点抽象,很难受。行吧,那龙哥动手搭个环境,联系实际场景,可能就会更好理解了。
现在我登录到每台设备给大家演示一下如何查看LSDB(链路状态数据库):
从以上截图来看,相信大家应该发现一个现象了,那就是每台路由器的LSDB是一样的,说明区域内每台路由器的“地图”都是长一个样的。
然后我再每台路由器都创建loopback0,都宣告到OSPF,目的是验证计算路由。不然上述环境,直连路由优先OSPF路由,所以查看路由表是不会看到OSPF路由的。
创建后随便登录一台路由器就可以了(因为每台路由器LSB都是一样的),去查看1类LSA(1类LSA每台路由器都会产生的)
然后我们在R1查看路由表中的OSPF路由:
我们可以看到只有2条OSPF路由,10.10.10.10没有在里面,是因为它不是最优的,因为它是直连路由,直连路由(优先级0)比OSPF(优先级10)优。
3、报文类型
不管你学什么协议,都绕不开学习报文。报文,就是协议之间互相交付的数据内容。
OSPF在层次模型中,是基于IP层之上的,协议号是89。
上图看完,我们是不是就可以定位出OSPF其实也是跟TCP、UDP同一传输层级别的协议了。
现在,是不是明白了,为啥OSPF报文需要LSAck了吧?因为OSPF不是基于TCP,TCP有确认机制,所以OSPF如果要确认机制,就需要开发一个报文类型,用来做确认,即LSAck。
现在,我们来总结一下OSPF的报文类型有:
Hello报文:用于发现、建立、维护邻居关系。DBD报文:链路状态数据库的目录,即摘要信息。LSR报文:发现自己缺少哪些摘要信息的,就去请求缺少的LSA。LSU报文:完整的LSA信息。LSAck报文:确认收到LSA。
本期主题龙哥于大家分享的是OSPF邻居状态机,所以重点介绍一下OSPF的Hello报文。
有些人遇到OSPF邻居不能建立成功,总是不知所措;或者有些考试应付考试,来问龙哥,影响OSPF邻居建立因素好几条,总是记不住怎么办呀?
其实,这个问题很简单,就是你没有把Hello报文格式内容给了解透彻。
你细品Hello报文,再去看影响OSPF邻居建立的因素,就清晰多了:
(1)routerid
(2)areaid(虚链路的areaid可以不一致,什么意思)
(3)认证
(4)hello/dead
(5)区域类型(option位,e=1、n=0为普通/骨干区域,e=0、n=0为stub区域,e=0、n=1为nssa区域)
(6)接口的地址掩码(ma网络,LSA2的掩码描述接口的掩码,如果掩码不一致会认为有两台DR,p2p没有问题)
不在hello包
(7)接口mtu(邻接关系出问题)
(8)ospf进程下静默
现在我们来解释Hello里的几个字段:
(1)routerid:建立邻居的OSPF,两边路由器routerid不能相同,否则即使建立成功了,也会有问题。
①两台路由器直连,RouterID一样,邻居无法建立。
两台路由器RouterID配一样,路由会提示你冲突了:
抓包看到他们确实已发Hello包,但是呢,就是建立不起来。
可能有人就会问,协议程序都是人为控制的,routerid一样,你允许它们建立邻居不就好了。
我们来假设一下,如果两台直连routerid一样能建立邻居关系,那到了exstar状态时需要选举DD报文的主从关系,主从关系是根据routerid最大来确定为主路由器的。如果都一样,就无法选举,从而就无法进行LSDB信息交换了。
既然到了exstart状态会有问题,那专家们设计协议时就认为在一开始的建立邻居的时候就扼杀掉不就好了,没必要浪费时间。
②两台路由器非直连,RouterID一样,邻居可以正常建立,但路由会振荡。
现在,龙哥打算在R4起个loopback口,配置10.10.10.10/24,然后宣告到OSPF。
假设R4宣告一条路由10.10.10.0/24,R4会把这条LSA(adv=4.4.4.4,type=1,LSID=4.4.4.4,seq=)发送给R5,R5收到后会发给他的邻居R6,R6收到发现通告者是4.4.4.4,但是自己又没有这个网段,于是会给R5发送一个自己的LSA1(age=1s,seq=),R5收到后会与之前adv=4.4.4.4的LSA1进行比较,选择这条seq更大的LSA1,然后也会转发给R4,R4收到后发现自己有这个网段,又会发送一条新的LSA1(seq=),会一直出现这样重复的情况,而导致路由动荡
路由动荡具体表现什么样的?我们可以长ping一下,就知道了,会发现偶尔不通。
现在,我们继续在R4采用引入的方式,引入外部路由20.20.20.20,再看看。
R4引入一条路由20.20.20.0/24,R4会把这条LSA(adv=4.4.4.4,type=5,LSID=20.20.20.0,seq=)发送给R5,R5收到后会发给他的邻居R6,R6收到发现通告者是4.4.4.4,但是自己又没有这个网段,于是会给R5发送一个(age=s,seq=)的LSA5,R5收到后,会与之前收到的LSA5进行比较,因为seq和checksum与之前的一样,所以会优选age=s的,然后也会转发给R4,R4收到后发现自己有这个网段,又会发送一条新的LSA5(seq=),会一直出现这样重复的情况,而导致路由动荡。
抓包可以看到,R4和R5一直在更新LSA:
抓包可以看到,R6和R5一直在更新LSA:
③不同区域的两台路由器,Routerid一样,邻居可以建立,路由会振荡。
可以上次,邻居是可以建立的。
如果R4和R6不引入外部路由的话,是不会出现问题的。因为ospf在区域间使用LSA3,LSA3是由区域的ABR根据LSA1、LSA2产生的,adv是ABR的router-id,区域间路由只是被当成叶子挂在ABR上,本区域内的spt树上不会出现在有相同router-id的节点,也就不会出现问题。但是如果在相同router-id的设备上做引入的时候就会出现问题了,因为asbr的router-id是需要被ospf域内的所有路由器所知道的,如果发现asbr的router-id与本设备的router-id一样时,会出现问题.
现在我们也在R4引入一条路由20.20.20.0/24,R4会把这条LSA(adv=4.4.4.4,type=5,LSID=20.20.20.0,seq=)发送给R5,R5收到后会发给他的邻居R6,R6收到发现通告者是4.4.4.4,但是自己又没有这个网段,于是会给R2发送一个(age=s,seq=)的LSA5,R5收到后,会与之前收到的LSA5进行比较,因为seq和checksum与之前的一样,所以会优选age=s的,然后也会转发给R4,R4收到后发现自己有这个网段,又会发送一条新的LSA5(seq=),会一直出现这样重复的情况,而导致路由振荡。
路由动荡具体表现什么样的?我们可以长ping一下,就知道了,会发现偶尔不通。
(这里我加了-t25是为了更明显看出丢包,路由振荡,修改了超时时间。)
(2)Area-id:OSPF是基于接口划分区域的,所以建立邻居关系的路由器必须在同一区域,即区域id需要一直。
(3)认证:建立邻居关系的两端必须保证认证类型和认证数据要一致。
(4)掩码:在MA/NBMA掩码要一致,P2P没限制。
(5)Hello/Dead时间:时间参数要一致
(6)Option:其中重点参考Option中的N和Ebit位,N/E必须置为相同(N/E主要表示两端路由器在什么样的区域)
N=1E=0:NSSA
N=0E=1:普通区域
N=0E=0:STUB区域
(7)DD报文中的有个MTU字段,两端需要一致(只会影响LSDB的同步,从2-way到full;华为设备默认不比较该参数,但不一致,后面可能会卡在exchange或loading,可以通过在接口下配置ospfmtu-enable命令使能检查邻居DD报文所携带的MTU是否超过本端的MTU值)
4、状态机
接下来,就是本期要介绍的OSPF状态机,介绍之前,我觉得有必要先理解一下:邻居关系和邻接关系。
邻居关系:OSPF设备启动后,会通过OSPF接口向外发送Hello报文,收到Hello报文的OSPF设备会检查报文中所定义的参数,如果双方一致就会形成邻居关系,两端设备互为邻居。
邻接关系:形成邻居关系后,如果两端设备成功交换DD报文和LSA,才建立邻接关系
邻居关系,就是好比你家附近,最近搬了一个新邻居,你们彼此经常路上都会遇到,你也知道她住哪的,她也知道你住哪的,只是你们没有彼此深入了解,交流。
邻接关系,也是好比你家附近,最近搬了一个新邻居,你们不仅彼此知道对方住哪的,你们因为又一次小区活动,得以认识,于是互相交流,了解对方喜好,哪里人等等,那这个时候你们就是邻接关系。
简单说,就是互相眼熟,互不打招呼的就是邻居关系;互相眼熟,还经常互相打招呼,深入聊天,就是邻接关系。
OSPF共有8种状态机,分别是:Down、Attempt、Init、2-way、Exstart、Exchange、Loading、Full。
Down:邻居会话的初始阶段,表明没有在邻居失效时间间隔内收到来自邻居路由器的Hello数据包。
Attempt:该状态仅发生在NBMA网络中,表明对端在邻居失效时间间隔(deadinterval)超时前仍然没有回复Hello报文。此时路由器依然每发送轮询Hello报文的时间间隔(pollinterval)向对端发送Hello报文。
Init:收到Hello报文后状态为Init。
2-way:收到的Hello报文中包含有自己的RouterID,则状态为2-way;如果不需要形成邻接关系则邻居状态机就停留在此状态,否则进入Exstart状态。
Exstart:开始协商主从关系,并确定DD的序列号,此时状态为Exstart。
Exchange:主从关系协商完毕后开始交换DD报文,此时状态为Exchange。
Loading:DD报文交换完成即Exchangedone,此时状态为Loading。
Full:LSR重传列表为空,此时状态为Full。
接下来,我们来聊聊几个主要的状态:
1、Init
每台路由器只与启用了OSPF,接口宣告到OSPF进程,就会开始发OSPF报文。
当收到别人发过来的Hello报文,
一开始,R5收到R4发过来的Hello包,查看,只看到R4的routerid4.4.4.4,没有看到自己,所以状态置为init状态,并且R5已发现自己有个邻居是R4。
R4收到R5发过来的Hello包,查看,只看到R5的routerid5.5.5.5,没有看到自己,所以状态置为init状态,并且R4已发现自己有个邻居是R5。
R5再次收到R4发过来的Hello包,查看,看到R4的routerid4.4.4.4,还看到自己R5的routerid5.5.5.5,认为双向通信没问题,所以状态置为2-way。
同理,R4再次收到R5发过来的Hello包,查看,看到R5的routerid5.5.5.5,还看到自己R5的routerid4.4.4.4,认为双向通信没问题,所以状态置为2-way。
到这里,OSPF的邻居状态就算建立完成。如果要交付LSA信息,还得继续建立邻接关系,才能交付,然后再去计算路由。
当链路两端的设备都进入2-way状态后,如果是MA或NBMA网络,会进行DR/BDR的选举。该选举是为了减少广播型网络和NBMA网络中建立邻接关系的数量。
如果存在DR的情况下,其他DR-Other只会和DR建立邻接关系,DR-Other之间建立邻居关系,但是不会建立邻接关系,状态一直处于2-way状态。
DR/BDR的选举规则:
1、比较路由器优先级,大的优先;
2、比较routerid。大的优先;
当选举出DR后,网络内的DR-Other和DR开始建立邻接关系,进入下一个状态Exstart。
这个阶段,两端设备通过交互DD报文,来选举主从关系,主从的目的,就是选举谁是老大,后续的DD报文序列号以他为准,作为参考点进行更新。
龙哥要画重点了,注意了,第一个DD报文,是没有携带LSA头部信息的。
现在我们来了解一下,主从关系是通过什么选举出来的呢?
DD报文有个三位很重要,I,M,MS位。
I是表示该报文是初始报文,第一个DD报文。
M表示后面还有DD报文,如果是0,表示没有DD报文了。
MS置1表示该报文为主,0表示为从。
所以第一个DD报文,都各自认为自己是主,所以MS都置1。
R4:发现自己的routerid比R5小,所以认怂了,为从,置为0:
R5:发现自己的routerid比R4大,所以嘚瑟了,为主,置为1,序列号+1
主从设备选举完后,设备的状态从Exstart状态变为Exchange状态,从设备(R4)会使用主设备(R5)的序列号,发送携带摘要信息的DD报文。
如果R5从R4发送的摘要信息中发现存在本身没有的LSA信息,则会向AR1发送LSR报文请求该LSA,此时状态由exchange变为loading状态。R4收到AR5的LSR请求报文,便会回复一个LSU报文携带AR2要请求的LSA明细信息。R5收到LSU报文同步完成后进入FULL状态,并且向R5发送LSAck报文表示确定收到了LSU报文且同步完成,R4也会进入FULL状态。该LSAck报文,就是因为OSPF是基于IP的,IP没有确认机制,所以OSPF需要设置自身的确认机制。
以上就是OSPF的邻居状态机。