路由器运行OSPF协议,并通过Network命令使能接口的OSPF功能后,该接口便会发送Hello报文。
Hello报文就像和新邻居打招呼一样,主要有两个作用,一是双方互相都打了招呼,并且相关参数协商一致,看对眼了,那么就建立起邻居关系;如果有的参数不一致,那双方也是有缘无份,邻居关系建不起来。二是周期性发送来保持邻居关系,双方每隔一定时间(Broadcast和P2P网络是10秒,NBMA和P2MP是30秒)要互相串个门,维护和保持邻居关系。如果超过邻居失效时间(4倍Hello周期)没有收到邻居发来的Hello报文,则认为邻居失效,邻居关系中断。
这是OSPF协议的报文头,所有OSPF报文都有这个东西,当然Hello也不例外。
双方要建邻居关系,在这个报文头里,要协商三个参数:
Source OSPF Router:发送hello报文的路由器RID,双方一定不能相同;
Area ID:区域ID,毫无疑问这个必须要相同,双方接口不在同一个区域可不行;
Auth Type和Auth Data:验证类型和验证数据,双方肯定必须要一样啦。
Auth Type为0表示不验证,Auth Data填0;为1表示简单密码验证,Auth Data填写密码信息;为2表示MD5验证,Auth Data填写KeyID、MD5验证数据长度、序列号,验证数据不在这里,在报文后面。
这是在Header后面的真正的Hello,这里也要协商四个参数:
Network Mask:子网掩码。除P2P网络类型外,双方接口配置的IP子网号和掩码必须相同;
Hello Interval:Hello报文发送周期,根据不同网络类型,默认有10秒和30秒。双方必须相同(这个很好理解,比如俩邻居约定每周聚一下,聚会时间肯定要相同。我说5天一聚,你说7天一聚,那聚不了);
Router Dead Interval:邻居失效时间,默认是4倍hello周期时间,这个也要相同。
Options中的N位和E位:这两个标志位双方也必须相同。N位为1表示双方都处于NSSA区域,都支持Type-7类LSA,此时E位一定为0;E位为1表示双方都允许Type-5类外部路由存在,为0表示双方都是Stub区域或者都是NSSA区域。
以上七个参数协商成功,双方邻居关系迁移到2-way状态,表示邻居建立成功。
当然,这是正常情况。我们有时还会看到其他邻居状态:
Init状态,如果本端收到了别人发的Hello,但是里面的邻居表(Active Neighbor)里没有自己的RID时,为Init状态。Init一般是一个瞬时状态,如果长时间停留在此状态,可能网络有故障或有其他错误配置。
Attempt状态:这个状态只存在于NBMA网络中,如果本端正常发送Hello,但没有收到任何人发的Hello时,为Attempt状态。
OSPF协议最大的特点是,在一个区域中,所有路由器都拥有一个完全相同的本区域所有的链路状态信息,保存在链路状态数据库(LSDB)中,每台路由器通过LSDB,自己计算去往任何一个网段的路由,加入到路由表中。
这就好像地图,我们每个人手里的地图是完全相同的,但要导航去相同的一个地方,每个人又可能因为出发地不同,路线可能也不同。即使同一个人,可能也会有多个路线方案。OSPF会选择开销(cost)最小的。
因此,OSPF实际上有两个工作:一个是怎么让区域内所有路由器收集整个区域的所有链路状态信息,让大家的地图都一样;二是怎么把LSDB中的信息计算成路由加入路由表中。只有地图也不行,还要能导航。
双方通过发送互相Hello报文建立了邻居关系,进入2-way状态后,如果双方都是MA网络中的DRother,则停在此状态不动了。否则邻居状态会继续迁移。为什么还要迁移?当然是为了交换并同步链路状态信息,完成OSPF的第一个工作。
可是,OSPF是基于IP的,就是说OSPF的报文由IP协议负责传递。而IP又不太靠谱,所以需要OSPF自己想办法,提高可靠性。
你可能会问,既然IP不靠谱,为什么OSPF不考虑用TCP来保证可靠性,而直接让IP负责呢?
这是因为,所有内部网关路由协议,包括OSPF,目的是为了能自动发现和计算路由,所以,它们都是以广播或组播的形式发送协议报文。如果用了TCP,那就不能自动发现了,因为TCP不支持广播和组播(如果你了解BGP,想想怎么建邻居的,BGP的路由又是哪来的)。
小Q:Hello报文Options选项中的N位什么情况下还会变成P位?