本节书摘来自异步社区《OSPF和IS-IS详解》一书中的第6章,第6.1节,作者 【美】Jeff Doyle,更多章节内容可以访问云栖社区“异步社区”公众号查看
第6章 链路状态数据库同步
OSPF和IS-IS详解
有一句话作者此前曾反复提及,现在再说一遍:链路状态路由协议的“精髓”在于,隶属同一区域的每台路由器都会根据存储在一个公共拓扑数据库里的信息,执行本机路由计算。因此,在同一区域内,每台路由器所存储的拓扑数据库的内容必须完全一样。路由器之间相互同步链路状态数据库的目的正是为此。在OSPF或IS-IS网络中,路由器只要上线运行,就必须与邻居路由器进行数据库同步,以确保各自所持数据库的内容完全相同。若路由器刚接入点到点链路,便会与链路对端的邻居路由器互相同步数据库。若路由器刚接入多路访问网络,则会跟DR或DIS进行数据库同步。在执行完最初的数据库同步任务之后,还有必要采取某些措施,让本机数据库与邻机数据库一直保持同步状态。
请注意,除了跟(直连)邻居路由器同步数据库以外,任何一台路由器都不会与区域内的其他(非直连)路由器进行数据库同步。在每一个区域内,邻居路由器之间就是用“薪火相传”的方式,来执行数据库同步任务。这足能让同一区域内的所有路由器都拥有内容相同的数据库了。当然,这一同步数据库的方式还得有一个前提,那就是区域内的任意两台路由器之间都有路径相连。在一个区域内,只要有一台或多台路由器因“路径中断”而被孤立,便不能确保该区域内的所有路由器都拥有内容相同的数据库。人们把这种情况称为区域分割(partitioned area),第7章会对此加以讨论。目前,读者有必要知道,在某特定区域内,确保所有路由器都拥有内容相同的数据库的一些前提条件。这些条件包括:先通过链路来“串连”所有路由器;再配置路由器,令它们彼此之间建立起“连成一气”的OSPF/IS-IS邻接关系。此外,还要确保不能因单点故障(单条物理链路或单个接口故障)而导致区域内的某台(或某些)路由器与所有其他所有路由器分割开来。
6.1 OSPF数据库同步
OSPF和IS-IS详解
读至本章,读者想必知道,OSPF协议是一种结构性很强的路由协议。既然读者都清楚OSPF数据库同步的可靠性和精确性是如此重要,那么也就不会对用来管理OSPF数据库同步过程的状态机(名为邻居状态机)的复杂程度感到惊讶了。简而言之,在数据库同步过程中,邻居状态机会驱动(OSPF路由器)采取以下“行动”。
1.当相邻的两台路由器决定彼此建立邻接关系时,会进行分工:一台起“主导”作用,另外一台会进行“配合”,这便是所谓的主(master)/从(slave)路由器机制。主路由器会掌控数据库同步的其余过程(即数据库交换过程)。
2.邻居路由器之间会以互发某种OSPF协议数据包的方式,彼此“展示”本机数据库里存储了哪些LSA(即数据库“展示”过程,也有人称其为数据库描述过程)。
3.在数据库“展示”过程中,若一台路由器得知邻居路由器拥有本机所没有的LSA,或得知邻居路由器所持LSA的“版本”新于本机,就会请求邻居路由器发送相关LSA的完整拷贝。
4.邻居路由器之间交换完各自数据库里的LSA,且两者都认为本机数据库与对方相同,则结束数据库同步过程,于是,便建立起了状态为Full的OSPF邻接关系。
本节首先会介绍数据库交换过程中用到的OSPF协议数据包,然后会深入探讨邻居状态机。
6.1.1 数据库同步过程中所使用的OSPF协议数据包
在数据库同步过程中,会用到5种“常规”OSPF协议数据包中的4种:
数据库描述(类型2)数据包;
链路状态请求(类型3)数据包;
链路状态更新(类型4)数据包;
链路状态确认(类型5)数据包。
上一章已经介绍了OSPF路由器之间如何利用链路状态更新数据包,来泛洪“整条”LSA。此外,上一章还提到,为确保LSA泛洪的可靠性,OSPF路由器如何通过包含LSA头部的链路状态确认数据包,来“直接确认”(explicitly acknowledge)收到的LSA。虽然上一章给出过链路状态更新数据包和链路状态确认数据包的格式,但为方便读者参考,图6.1和图6.2再次显示了两者的格式。
与链路状态确认数据包一样,数据库描述(DD)数据包(其格式见图6.3)也只含可完全标识某条LSA或LSA实例的LSA头部。OSPF路由器会以生成DD数据包的方式,向与其建立邻接关系的邻居路由器“展示”本机数据库内包含有哪些LSA。
接口MTU字段,其值指明了生成(DD数据包的)路由器接口所能发送的不分片数据包的最大长度。若(邻居路由器间互连接口的)MTU值不匹配,则不能建立邻接关系。否则,邻居双方中的一方就有可能会发出对方无法接收的“大型”OSPF协议数据包。
选项字段,与Hello数据包以及LSA中的选项字段相同,都用来通告生成(OSPF协议数据包的)路由器所具备的OSPF可选功能。在本章之前的内容中,已经简要介绍过了该字段,下一节会详细介绍其格式与用途。
一般而言,LS数据库的规模都不会太小,在此情形,OSPF路由器只生成一个数据库描述数据包,可能并不足以把本机LS数据库里的所有LSA都“展现”给邻居路由器。因此,协议设计人员在DD数据包中设立了以下两位,意在“告知”邻居路由器:本数据包是否是“一串”DD数据包中的一个。
I(Init)位,该位置1时,表示本数据包是“一串”DD数据包中的第一个。
M(More)位,该位置1时,表示本数据包之后还有后续的DD数据包“跟进”。
以下是对I和M位各种取值方式的解释。
若只用单个DD数据包便能把本机LS数据库里的所有LSA都“交代清楚”,则该DD数据包中的I位置1,M位置0。
若要用“一串”DD数据包才能把本机LS数据库里的所有LSA“交代清楚”,则“一串”当中的首个DD数据包的I位和M位要同时置1;“一串”当中的最后一个数据包的I位和M位需同时置0;首尾之间的数据包I位应置0,M位则要置1。
MS(主/从,Master/Slave)位,其值用来表示生成(DD数据包的)OSPF路由器在数据库交换过程中是起主导(Master)(MS位置1)作用,还是起配合(Slave)(MS位置0)作用,即标明生成(DD数据包的)OSPF路由器是主(Master)路由器还是从(Slave)路由器。主/从路由器之间的关系将在6.1.5节介绍。
DD序列号字段,当用“一串”DD数据包才能把本机LS数据库里的所有LSA都“交代清楚”时,该字段会跟I、M位结合使用。DD序列号字段的用途也将在6.1.5节介绍。
在数据库交换过程中,若OSPF路由器在收到的DD数据包中发现了未知LSA或已知LSA的最新版本,便会发出链路状态请求数据包(其格式见图6.4),请求邻居路由器把相关LSA的完整拷贝发给自己。可发出单个LS(链路状态)请求数据包,向邻居路由器“请求”多条LSA,倘若所要“请求”的LSA的条数过多,则可以发出多个LS请求数据包。邻居路由器可以把多条“受到请求”的LSA,装载进单个链路状态更新数据包,然后外发。
请注意,LS请求数据包并不包含完整的LSA头部,只是包含了LSA头部中的LS类型、LS ID,以及通告(路由的)路由器字段。也就是说,路由器发出LS请求数据包,是要从邻居路由器那儿“实打实”地请求某条(或多条)LSA,而不是某条(或多条)LSA的某个具体实例。收到LS请求数据包的邻居路由器,自然会发出“受到请求”的LSA的最新实例。LS请求数据包的格式之所以会如此设计,其目的是要把这样一种情形也考虑在内,那就是:在某台路由器从生成DD数据包(向邻居路由器“展示”本机数据库里的LSA),到收到(邻居路由器发出的)LS请求数据包,向其请求某条(或多条)LSA的这段时间内,邻居路由器可能已经收到(自己所要请求的)LSA的最新实例,并将之安装进本机数据库了。 总而言之,只要收到LS请求数据包,OSPF路由器必会发出“受到请求”的LSA的最新拷贝。
6.1.2 选项字段
(某几种)OSPF(协议数据包所携带的)选项字段是一个8位的标记集合,每一位都代表着生成(该OSPF协议数据包的)路由器所具备的某项OSPF功能。在上一节介绍过数据库描述数据包之后,含选项字段的各种OSPF协议报文(或信息元素)都已在本书中介绍过了,它们是:
Hello数据包;
数据库描述数据包;
LSA头部。
图6.5所示为选项字段的格式。选项字段中有7位都是当前已启用的标记位,最高位在图中被标记为“*”,写作本书之际,还尚未启用。选项字段那7位中的每一位都表示一种与OSPF有关的功能,路由器只有在具备了相应的功能之后,才会把(自生成的某些OSPF协议数据包的)选项字段中的相关位置1。否则,便会把选项字段中的相关位置0。
本节会简单介绍选项字段中每一位的用途,以供读者做一般性的了解。本书后文会专辟几章分别介绍选项字段中各标记位所代表的相关功能。在还没有学过这些内容之前,读者在阅读本节对选项字段的介绍时,可能会略感吃力。
O位,表示(生成相关OSPF协议数据包的)路由器是否具备解读不透明(Opaque)LSA的功能,第10章会介绍不透明LSA。如本书第1章所述,有了不透明LSA,就能对OSPF的功能进行扩展,令该协议支持其原本所不能支持的应用,比如,流量工程。O位只会在DD数据包中置1,也只有能解读不透明LSA的路由器才能将该位置1,也就是说,路由器是否支持与O位“挂钩”的OSPF功能,只有在数据库交换过程中才能显现出来。此后,不透明LSA将被泛洪给支持不透明功能的路由器(Opaque-capable router)。
DC位,该位置1时,表示(生成相关OSPF协议数据包的)路由器支持按需电路(Demand Circuit)功能,并能够“解读”与该功能有关的“DoNotAge LSA”,这些内容将在第8章讨论。当互连(OSPF路由器的)链路要按流量或时间来计费时,就可以(在OSPF路由器上)开启按需电路功能。此时,可以配置OSPF路由器上的相关接口(比如,ISDN或拨号接口),令这些接口将其所连链路视为按需电路,这样一来,通过按需电路互连的OSPF邻居路由器之间,既不会定期互发Hello数据包,也不会定期刷新LSA,这就避免了按需电路被毫无必要地“接通”,去传递“控制层面”流量,从而起到节省通信成本的目的。能“解读”DoNotAge LSA的路由器,会在自生成的所有LSA中将DC位置1。此类路由器还会通过连接了按需电路的接口,外发DC位置1的Hello和DD数据包。若此类路由器收到了DC位置0的Hello或DD数据包,则表明邻居路由器不支持或未启用按需电路功能,于是便会改发“普通”的Hello数据包,并“正常”执行LSA的刷新机制。若不支持按需电路功能的路由器收到了DC位置1的OSPF协议数据包,则会对DC位置1的情况“视而不见”。
EA位,该位置1时,表示(生成相关OSPF协议数据包的)路由器能解读外部属性LSA(这种LSA的类型字段值为8)。与这种类型的LSA相关联的功能现已过时,且未得到广泛应用。
N/P位,用来支持Not-So-Stubby区域(详见7.3.4节)。在Hello数据包的选项字段内,该位被称为N位,置1时,表示(生成Hello数据包的)路由器支持(连接)Not-So-Stubby区域。在Hello数据包中,若选项字段的N位置1,那么E位(表示支持类型5 LSA)必须置0。若邻居路由器之间不能对上述N位和E位的设置方式达成一致意见,便会丢弃对方发出的Hello数据包,OSPF邻接关系自然也无从建立。在NSSA LSA头部的选项字段中,该位称为P位,同来“通知”NSSA ABR,令其执行LSA类型7/5间的转换。
MC位,该位置1时,表示(生成相关OSPF协议数据包的)路由器支持多播OSPF(MOSPF)功能。MOSPF路由器会在其生成的所有Hello数据包、DD数据包以及LSA的选项字段中将MC位置1。然而,在Hello数据包中,选项字段的MC位只起“通知”作用。在数据库交换过程中,路由器才会真正检查DD数据包中选项字段的MC位,以了解邻居路由器是否支持MOSPF功能,MOSPF组成员(类型6)LSA只会被泛洪给支持MOSPF功能的路由器。
E位,该位置1时,表示(生成相关OSPF协议数据包的)路由器支持外部路由功能。若路由器在自生成的相关OSPF协议数据包的选项字段中,将E位置0,则表示其不接受外部(类型5)LSA。只要在网络中开辟了stub区域(详见7.3.4节),就一定会有完全“委身”于此类区域的路由器,这些路由器会在自生成的相关OSPF协议数据包的选项字段中,将E位置0。在外部LSA的选项字段中,E位必定置1;在隶属于区域0及非stub区域的路由器生成的DD数据包和LSA的选项字段中,E位也总是置1,但是只起“通知”作用。在Hello数据包的选项字段中,E位的设置情况会影响到OSPF邻接关系的建立。交换于相邻路由器之间的Hello数据包中选项字段的E位设置不一致——一方置1,另一方置0——Hello数据包便会遭到对方的丢弃,两者之间将建立不了OSPF邻接关系。
T位,该位置1时,表示(生成相关OSPF协议数据包的)路由器支持ToS路由功能。该功能现已过时,且未得到广泛应用。
6.1.3 OSPF邻居数据结构
当OSPF路由器通过某接口收到Hello数据包,首次“探索”到邻居路由器时,会针对其创建邻居数据结构。邻居数据结构(也被称为邻居列表)会包含本路由器必须知道的有关邻居路由器的所有信息。其中的某些信息收集自邻居路由器发出的Hello和DD数据包,而另外一些信息则来源于本路由器跟邻居路由器挂钩的内部进程。以下所列为邻居数据结构表中的具体表项。
状态(State),记录了本路由器根据自身的邻居状态机(详见6.1.6节)识别出的邻居路由器的状态。请注意,千万别把此处所说的“状态”跟接口数据结构中的“状态”混为一谈,在接口数据结构中,“状态”字段表示的是OSPF接口的状态,以及该接口与邻居路由器(互连)接口之间的关系。
闲置计时器(Inactivity Timer),是一个周期为“RouterDeadInterval”(路由器失效间隔期)的计时器,针对路由器接口所连链路上的邻居路由器而定义。只要收到该邻居路由器发出的Hello数据包,闲置计时器就会归零(重置)。该计时器到期将会触发邻居状态机中的某些事件,这些事件会把该邻居路由器的状态改变为“Down”。
主/从关系(Master/Slave),表示主、从路由器的选举结果,详见6.1.5节。在数据库交换过程中,会牵涉到主、从路由器的选举。
DD序列号(DD Sequence Number),表示在数据库交换过程中,(本路由器)当前发送给邻居路由器的DD数据包的序列号字段值。
最新收到的数据库描述数据包(Last Received Database Description Packet),可根据该表项的内容来确定在数据库交换过程中(与邻居路由器交换数据库时),是否从邻居路由器那里收到了重复的DD数据包。该表项会记录下邻居路由器最近发出的DD数据包中的某些字段值,包括:序列号字段值、选项字段值以及I、M、MS位的设置情况。
邻居ID(Neighbor ID),这一项的内容为邻居路由器的RID,取自邻居路由器发出的Hello数据包,在某些情况下(比如,在NBMA或某些虚拟网络环境中),也可以手工指定。
邻居路由器的优先级(Neighbor Priority),这一项的内容取自邻居路由器发出的Hello数据包的路由器优先级字段值,执行DR/BDR选举时会用到。
邻居路由器(接口)的IP地址(Neighbor IP Address),这一项的内容为邻居路由器用来跟本机互连的接口的IP地址,提取自邻居路由器发出的Hello数据包(包头)的源IP地址字段。当本路由器需以单播方式向邻居路由器发出OSPF协议数据包时,会用该地址作为OSPF协议数据包的目的IP地址。若邻居路由器是网络内的DR,则这一IP地址还会成为本路由器针对该网络生成的路由器LSA的链路ID字段值。
邻居路由器所支持的OSPF可选功能(Neighbor Option),这一项的内容取自邻居路由器发出的Hello数据包(的选项字段),以及在数据库交换过程中发出的DD数据包(的选项字段)。
邻居路由器所知道的备份指定路由器(Neighbor’s Designated Router),这一项的内容取自邻居路由器发出的Hello数据包的指定路由器字段值(即邻居路由器所认为的DR的IP地址)。只有在广播或NBMA网络环境中,其内容才有意义。
邻居路由器所知道的备份指定路由器(Neighbor’s Backup Designated Router),这一项的内容取自邻居路由器发出的Hello数据包的备份指定路由器字段值(即邻居路由器所认为的BDR的IP地址)。同理,也只有在广播或NBMA网络环境中,其内容才有意义。
图6.6所示为一张OSPF邻居表的输出示例。显而易见,其中出现了之前介绍过的大多数邻居表表项及内容。
6.1.4 OSPF路由器在数据库交换和泛洪期间用到的LSA列表
除了上一节所描述的内容之外,邻居数据结构还包括3张表格。这3张与LSA有关的表格,都只会在数据库交换或泛洪过程中“填写”。
链路状态发送列表(Link State Transmission List),列在表里的LSA都已泛洪而出,但尚未获得确认。
数据库汇总列表(Database Summary List),开始(与邻居路由器)执行数据库交换任务时,OSPF路由器会将归属本机及邻机所在OSPF区域的所有LSA,都填入此表。包含于此表的所有LSA都是OSPF路由器要通过DD数据包“秀”给邻居路由器“看”的LSA。
链路状态请求列表(Link State Request List),此表所含LSA均获悉于邻居路由器发出的DD数据包,包含的不是本路由器未知的LSA,就是本路由器已知LSA的最新拷贝。随后,本路由器会发出链路状态请求数据包,请求邻居路由器“传送”表中所包含的LSA。收到邻居路由器发出相关LSA的完整拷贝之后(相关LSA是指,本机请求邻机发送的LSA。邻居路由器会通过链路状态更新数据包,来传送本机请求发送的LSA的完整拷贝),本路由器会将收到的LSA从链路状态请求列表中删除。
6.1.5 管理数据库的交换:主(Master)/从(Slave)路由器机制
(邻居路由器之间)相互交换OSPF数据库的内容(LSA)时,(数据传送的)可靠性非常重要,但LSA的可靠交换并不可能一蹴而就。因此,当两台路由器(拿本机数据库里的LSA,跟对方通过DD报文所“展示”的LSA)进行比对时,其中一台路由器要负责管理LSA(即LS数据库的内容)的交换过程1。应当由哪一台路由器来充当“管理者”(主路由器),其实并不重要,只要邻居双方一致同意就成。RID更高的那台路由器会成为主路由器,从路由器则由RID较低的那台路由器充当。
以下所列为主路由器所肩负的责任。
发出首个DD数据包。
递增DD数据包的序列号字段值。从路由器则没有这个“权限”。
确保每次只能有一个DD数据包“在途”(outstanding)。
在必要时重传DD数据包。从路由器则不能重传DD数据包。
现在,作者以两台相邻的路由器RA和RB为例,来讲解主路由器是如何确定的。RA在验证过本机与RB间具备了双向连通性之后,会立刻决定跟RB建立邻接关系。为此,RA会向RB发出一个空DD数据包(不含LSA头部)。RA会向DD数据包的序列号字段中填入一个独一无二的值;RFC 2328的建议是,根据当日时间来赋值,但有些厂商的OSPF实现也会使用某些其他方法,向(DD数据包的)序列号字段中填入一个起始值。在RA发出的这一空DD数据包中,I、M以及MS位都将置1,表示本数据包是“一串”DD数据包当中的第一个,后面还会有别的数据包“跟进”,RA还同时以主路由器自居(MS位置1)。
收到RA发出的空DD数据包后,RB会检查其中的RID字段值。若RA的RID更高,RB便知其为主路由器,反之,则视其为从路由器。接下来,会发生两件事情。
若RB认为本机为从路由器,便会发出包含本机所持LSA的头部的DD数据包进行回应,这便拉开了数据库交换的序幕。在RB发出的DD数据包中,头部的序列号字段值会跟(RA发出的)DD数据包相同;MS位将置0,这表示本路由器为从路由器,RA为主路由器。在RB发出的首个DD数据包的头部中,I位将会置1,M位置1还是置0,则要取决于RB有没有通过本DD数据包,(一次性)向RA“展示”完本机数据库所保存的所有LSA。
若RB认为本机为主路由器,便会(向RA)发出序列号字段值为自定义,且I、M以及MS位都置1的空DD数据包。收到之后,RA会发出序列号字段值由RB所定义,且MS位置0的DD数据包进行确认,表示本机为从路由器。在这一用来行使确认功能的DD数据包中,会包含RA所持LSA的头部,数据库交换过程也随即开始。在这一DD数据包的头部中,I位将会置0,因为这并非RA发出的第一个DD数据包;M位置0还是置1,则要取决于RA有没有通过该DD数据包,(一次性)向RB“展示”完本机数据库所保存的所有LSA。
在验证过与对方具备了双向连通性之后,RA和RB有可能会几乎同时发出空DD数据包,分别声称自己为主路由器。对于这种情况,相邻两台路由器只要一收到对方发出的DD数据包,就知道谁是“主”,谁是“从”了。此时,会由从路由器来启动数据库的交换过程,具体做法是:发出包含LSA头部的DD数据包,并在其头部的序列号字段中填入邻居路由器所发DD数据包的序列号字段值,且把MS位置0,对邻居路由器发出的空DD数据包进行确认。
6.1.6节会细述(邻居路由器之间)进行数据库交换的完整过程。目前,读者只要知道在确立了主、从路由器之后,由主路由器负责“管理”数据库交换就够了。由于只有主路由器才能增加DD数据包的序列号字段值,因此当主路由器发出序列号字段值为X的DD数据包之后,只要从路由器能够收到,就会发出序列号字段值同为X的DD数据包(其中会包含本机所持LSA的头部),以“间接”的方式进行确认。同理,只有收到了从路由器发出的序列号字段值为X的DD数据包之后,主路由器才能继续发送序列号字段值为X+1的DD数据包。通过上述规则不难发现,(发生在邻居路由器间的)数据库交换行为就是一台路由器“主导”或“主动轮询”(poll),另一台路由器“配合”或“被动响应”的过程,即主路由器轮询,从路由器响应(respond)。
DR必会是主路由器吗
在DR推举过程中,若路由器的优先级全都相同,RID最高的路由器将成为DR。因此,有些读者势必以为,当DROther与DR进行数据库同步时,DR一定会是主路由器。DR在广播或NBMA网络中所承担的职责可能又进一步巩固了上述推理。但事实上,在DROther与DR进行数据库交换时,却颇有可能发生DROther为主,DR为从的现象。请牢记,DR在选定之后,如无意外不会“逊位”。也就是讲,在以太网络中,新上线运行的路由器即便RID高于现有的DR,也不能自动“取而代之”。若此路由器与DR进行数据库交换,则必担当主路由器之职(此路由器的RID更高),而DR一定会成为从路由器。
6.1.6 OSPF邻居状态机
在介绍过用来支撑(OSPF路由器间)数据库交换的所有必要组件之后,现在是时候了解OSPF路由器的各种状态、导致OSPF路由器的状态发生改变的各种事件,以及状态发生改变时,OSPF路由器所采取的动作了。OSPF邻居状态机由一整套状态、事件和动作构成,详情请见RFC 2328的10.8节。
读者需要记住,OSPF路由器会单独针对每一个邻居维护邻接状态信息,这些信息明确了本机与某特定邻居之间目前的关系。在相邻的两台路由器之间(尤其是在建立起状态为Full的邻接关系之前),可能会发生邻接关系状态认知度不统一的情况(比如,甲、乙两台路由器相邻,在甲路由器上,显示其与乙路由器之间为A状态;在乙路由器上,显示其与甲路由器之间为B状态)。以下所列为各种OSPF邻接关系状态。
Down(失效)状态,此乃邻居会话的最初状态。把邻居路由器的状态显示为Down,即表明在最近一次路由器失效间隔期(RouterDeadInterval)内,未收到该邻居路由器发出的Hello数据包。OSPF路由器不会向状态为Down的邻居路由器发送Hello数据包,但NBMA网络环境除外。在NBMA网络环境中,(OSPF路由器)会按一定的频率(数据包的发送间隔时间要远高于一般的Hello间隔时间[Hello Interval]),(定期)向状态为Down的邻居路由器发送Hello数据包。这一在NBMA网络中向(失效的)邻居路由器发送Hello数据包的间隔时间称为PollInterval(轮询间隔时间),其时长通常为2分钟。
Attempt(尝试)状态,此状态只限于NBMA网络环境。把通过NBMA接口相连的邻居路由器显示为Attempt状态,则表明在本机配置中已手工指明了邻居路由器的IP地址,本机会“力争”获得邻居路由器的响应。之所以说“力争获得邻居路由器的响应”,是因为本机在发送Hello数据包“联络”邻居路由器时,发包的间隔时间为HelloInterval(Hello间隔时间,一般为30秒),并非之前提及的PollInterval(轮询间隔时间,一般为2分钟)。
Init(初始)状态,把邻居路由器显示为Init状态,则表明本机已收到邻居路由器发出的Hello数据包,但在其邻居路由器字段中未发现本机的RID(即无法确定与邻居路由器之间是否具备双向连通性)。本路由器会把处于Init状态(或更高级别的状态)的所有邻居路由器的RID,填入自生成的Hello数据包的邻居路由器字段,然后通过相关接口外发。
2-Way(双向通信)状态,把邻居路由器显示为2-Way状态,则表明本机跟邻居路由器之间具备了双向连通性,亦即在邻居路由器发出的Hello数据包的邻居路由器字段中发现了自身的RID。只有处于2-Way或更高级别状态的路由器才有资格参与DR选举。
ExStart(准备交换)状态,把邻居路由器显示为ExStart状态,则表明已经拉开了数据库交换的序幕。在此状态下,邻居路由器会确定“邻里之间”的主/从(Master/Slave)关系,以及用来执行数据库交换的DD数据包的初始序列号(即序列号字段的初始值)。只有把邻居路由器显示为ExStart或更高级别的状态,才能认为本机与邻居路由器建立了邻接关系,不过,在数据库同步进行完之前,还不能说邻接关系建立“齐备”(还未建立起状态为Full的邻接关系)。
Exchange(交换)状态,把邻居路由器显示为Exchange状态,则表明本路由器正在向邻居路由器“秀”(展示)自己的LS数据库,“展示”的方法是:向邻居路由器发出DD数据包,其中包含了存储在本机数据库里的所有LSA的头部。与此同时,本路由器还可以发出链路状态请求数据包,请求邻居路由器发送包含在链路请求列表里的LSA(即在链路请求列表里由链路状态类型、链路状态ID和通告[路由]的路由器这三个字段共同标识的LSA)。当OSPF路由器向邻居路由器泛洪LSA时,邻居路由器必须处于Exchange或更高级别的状态。
Loading(加载)状态,把邻居路由器显示为Loading状态,则表明本路由器已向邻居路由器“秀”完了自己的LS数据库,但还没有从邻居路由器那里“接收”完本机请求发送的LSA,或邻居路由器还没有“接收”完它请求本机发送的LSA。
Full(齐备)状态,把邻居路由器显示为Full状态,则表明本路由器跟邻居路由器之间的邻接关系状态已建立齐备,这样的邻接关系会同时在(双方发出的)路由器LSA或网络LSA中有所体现。
图6.7所示为两台路由器从彼此发现,到互相同步数据库,再到邻接关系建立齐备时,典型的邻居状态变迁的全过程2。图中两台路由器互连接口的OSPF网络类型为broadcast。
以下所列为出现在图6.7中的各个步骤。
1.RA在广播网络内上线运行,发出Hello数据包,宣布自己上线运行。在RA发出的Hello数据包中,DR字段值被设置为0.0.0.0,邻居路由器字段为空,表示RA尚未发现任何邻居路由器。
2.RB收到RA发出的Hello数据包后,会针对RA构建一套邻居数据结构。RB会把RA置为Init状态,因为在RA发出的Hello数据包的邻居路由器字段内,未出现RB的RID。RB向RA发出Hello数据包时,会在邻居路由器字段内填入RA的RID(10.0.0.1)。对于本例,由于RB是该广播网络内的DR,因此会把本机用来连接该广播网络的接口的IP地址(10.1.1.2),填入(发送给RA的Hello数据包的)DR字段。
3.当RA收到RB发出的Hello数据包后,也会针对RB构建一套邻居数据结构。由于在此Hello数据包的邻居路由器字段中发现了自身的RID,因此RA就知道跟RB之间已经具备了双向连通性。此时,RA可以把RB置为2-way状态。但因RB是(该广播网络内的)DR,故RA必须与其进行数据库同步。于是,RA把RB置为了ExStart状态,表示本机开启了主/从路由器的选择,并同时用LSA来填充数据库汇总列表(详见6.1.4节),那些LSA都是要“秀”给RB“看”的LSA。RA向RB发出了空DD数据包(不含LSA头部),在其中提出了自己的“建议”——为序列号字段设置了一个初始值,并同时将MS位置1。由于那个空DD数据包的作用只是“探路”,后面还会有DD数据包“跟进”,因此I、M位同样都被置1。
4.收到RA发出的空DD数据包后,RB会把RA置为ExStart状态,并同时用某些LSA来填充数据库汇总列表,那些LSA都是要给RA“过目”的LSA。然后,向RA发送空DD数据包。由于RB的RID高于RA,因此RB知道本机应作为主路由器,于是会把这一空DD数据包的MS位置1,并自行为序列号字段设置了一个初始值Y。在该DD数据包内,I、M位同样都被置1,表示这是RB发出的首个DD数据包,后面还会有DD数据包“跟进”。
5.收到RB发出的首个(空)DD数据包后,RA便知RB为主路由器了。随着主/从路由器选举完毕,数据库交换的序幕也随即拉开,因此RA会把RB置为Exchange状态。RA会向RB发出DD数据包,其序列号字段值为RB(在空DD数据包内)设置的初始值Y;MS位则置0,表示本机为从路由器。该DD数据包中会包含“刊登”在数据库汇总列表里的多个LSA的头部,“刊登”在数据库汇总列表里的LSA跟RA所持LS数据库里的LSA相同。对于本例,RA要发多个DD数据包,才能向RB完整地展示本机LS数据库(里的LSA),因此,该DD数据包的M位将会置1,表示后面还有DD数据包会“跟进”;而I位则会置0,因为这并不是RA发给RB的第一个DD数据包了。
6.收到RA发出的(含LSA头部的)DD数据包后,RB会把RA置为Exchange状态。对于DD数据包中包含的本机所需要的任何一条LSA,RB都会录入进链路状态请求列表(见6.1.4节)。然后,RB向RA发出DD数据包,其中会包含“刊登”在数据库汇总列表里的多个LSA的头部。身为主路由器,RB要负责把该DD数据包的序列号字段值调整为Y+1。跟RA相同,RB也得发出多个DD数据包,方能向RA完整地展示本机LSA数据库(里的LSA),当然,该DD数据包的M位将会置1。此外,RB还会将通过该DD数据包对外“展示”的LSA录入链路状态重传列表,并启动重传计时器。
7.收到了RB发出的DD数据包后,RA会先从数据库汇总列表中,将此前已向RB展示过的LSA清除,那些LSA的头部都包含在此前RA向RB发出的DD数据包内(详见步骤5)。若RB在该DD数据包中“展示”的LSA有自己所需,RA就会把那些LSA录入链路状态请求列表。然后,RA将继续向RB发送DD数据包,其中会包含“刊登”在数据库汇总列表里的“下一批”LSA的头部。RA也会把该DD数据包中的序列号字段值设置为Y+1。如此一来,RA也就向RB确认了本机已收到其此前发出的DD数据包,以及包内所包含的LSA的头部。
8.收到了RA发出的序列号字段值为Y+1的DD数据包后,RB会停掉之前启动的重传计时器,该计时器是为之前发出的DD数据包中所要“展示”的LSA而启动。此外,RB还会从链路状态重传列表中清除那些LSA。然后,RB会继续向RA发送新的DD数据包,其序列号字段值为Y+2,其中包含了要“秀”给RA“看”的下一批LSA(的头部)。通过该DD数据包,RB也“秀”完了“刊登”在数据库汇总列表里的LSA,因此此包的M将置0,表示后面没有DD数据包“跟进”。
9.收到了RB发出的最后一个DD数据包(其M位置0)后,RA知道RB“秀”完了自己的数据库。但由于RA的链路请求列表里还“刊载”有尚未请求RB发送的LSA,因此RA会把RB置为Loading状态。然后,RA再发出序列号字段值为Y+2的DD数据包,确认已经收到了RB发出的最后一个DD数据包。在此DD数据包中,包含了RA的数据库汇总列表里的最后一批LSA的头部,所以此包的M位会置0。
10.收到RA发出的最后一个DD数据包后,RB会从链路状态重传列表中,清除已得到RA确认的LSA。此时,在RB的链路请求列表中已无任何LSA,这表示RB已对RA数据库里的所有LSA“一清二楚”,于是,便将RA置为Full状态。但RA的链路状态请求列表中还“刊载”有LSA,因此RA会发出链路状态请求数据包,请求RB发送相应的LSA。RB会以链路状态更新数据包进行回应,其中包含了RA所要请求的完整的LSA。当RA的链路状态请求列表为空时,则表示其已从RB那里收到了自己需要的所有LSA,于是,会把RB置为Full状态。
由图6.7可知,OSPF路由器只有在收到(邻居路由器发出的)相关OSPF协议数据包后,才会改变邻居路由器的状态。导致OSPF路由器改变邻居路由器状态的事件包括:收到了邻居路由器发出的OSPF协议数据包,或邻居路由器发出的OSPF协议数据包里的内容发生了改变3。然而,并不是所有导致OSPF路由器改变邻居路由器状态的事件,都与自己收到(邻居路由器发出的)相关OSPF协议数据包有关。
以下所列为会让邻居路由器的状态呈“良性”发展的事件。
HelloReceived(收到Hello数据包)——收到了邻居路由器发出的Hello数据包。
Start(启动)——在Hello间隔时间(Hello Interval)内,应向邻居路由器发送Hello数据包。本事件只对位于NBMA网络中的邻居路由器生效。
2-WayReceived(双向连通性具备)——在邻居路由器发出的Hello数据包(的邻居路由器字段)中,发现了本机RID,这表示本机与邻机之间具备了双向连通性。
NegotiationDone(完成协商)——完成了主/从路由器的协商。
ExchangeDone(完成交换)——两台路由器都通过DD数据包,把本机数据库里的LSA完全展示给了对方。
BadLSRequest(链路状态请求出错)——收到了(邻居路由器发出的)链路状态请求数据包,但其所请求的LSA在本机数据库里没有,这表示在数据库交换过程中发生了错误。
LoadingDone(数据库加载完毕)——数据库交换过程完毕之后,链路状态请求列表也已清空。
AdjOK?(能建立齐备的邻居关系吗?)——这是一个决策点,表示(本路由器在决定)应不应该跟邻居路由器建立或维持邻接关系。
图6.8所示为邻居路由器的状态与事件(是指能使邻居路由器的状态呈“良性”发展的事件)间的关系图。
还有一些事件会使邻居路由器的状态呈“恶性”发展。这些事件大都因错误、故障或计时器到期所致。当邻居路由器处于以下任一状态时,就会发生这些事件。
SeqNumberMismatch(序列号不匹配)——收到了(邻居路由器发出的)DD数据包,但其序列号字段值跟本机预期的不符(不是N+1)、I位设置有误,或选项字段值跟上一次收到DD数据包里的不一样。该事件会导致(本路由器)放弃或重新开始与处于ExStart状态的邻居路由器交换LS数据库。
1-Way(单向连通性)——与邻居路由器之间丧失了双向连通性,其征兆为:在邻居路由器发出的Hello数据包的邻居路由器字段内,未发现本路由器的RID。若邻居路由器处于2-Way或更高级的状态,则(本路由器)会将其置为Init状态。
KillNbr(邻居路由器“失踪”)——与邻居路由器完全失去了“联系”,(本路由器)会将其置为Down状态。
InactivityTimer(计时器闲置)——在最后一次路由器失效间隔时间(RouterDeadInterval)内,未收到邻居路由器发出的Hello数据包,(本路由器)会将其置为Down状态。
LLDown(底层协议状态为Down)——底层协议(lower-level protocol)显示邻居路由器不可达,导致(本路由器)会将其置为Down状态。
6.1.7 OSPF排障方法1:学会解读路由器生成的日志记录及Debug输出信息
OSPF路由器间的数据库交换过程,并不总是像上一节描述的那般“井然有序”。比方说,(OSPF邻居之间)仍然在交换DD数据包的同时,可能还会互相发送链路状态请求和链路状态更新数据包。此外,(一台路由器)接口状态(的改变)也会对邻居路由器的状态产生影响。不管怎样,只要能弄清在建立起状态为Full的OSPF邻接关系的过程中,邻居路由器之间是如何“互动”的,肯定会对排除OSPF故障有极大帮助。
要是相邻两台OSPF路由器之间建立不了邻接关系,那么应首先从哪儿查起呢?
互连接口的IP地址配置正确吗?
能ping通邻居路由器的互连接口的IP地址吗?
OSPF邻居路由器间互连接口的IP地址都隶属于同一OSPF区域吗?
若启用了OSPF认证功能(详见第9章),两“边”的认证信息配置一致吗?密码或密钥匹配吗?
两“边”的OSPF可选功能配置是否一致?
两“边”的各种OSPF计时器配置是否一致?
OSPF邻居路由器间互连接口的MTU值是否匹配?
要是经过一翻排查,上述所有问题的答案都是“是”,但OSPF邻接关系仍“死活”建立不了,那就应该去深究邻居路由器间的“互动”过程。也就是说,需要在路由器上通过任何一款可用的OSPF排障工具,来记录并“破译”邻居路由器间的“会话”。此类排障工具不但能准确地“告诉”网管人员,故障出在邻接关系建立或数据库同步的哪一步,而且还能帮助定位故障的原因,或至少能让人获得一点“蛛丝马迹”。网管人员可根据这些“蛛丝马迹”,来进一步判断故障的原因。
图6.9所示为由一台Juniper路由器生成的日志文件,其内容包括了各种OSPF事件、协议数据包的收发过程以及邻居状态的变迁。作者对这份日志文件(以及图7.10中的Debug输出)做了适当的修订,删去了某些无关信息,比如,记录Hello数据包的收发情况的信息。
这份日志文件记录了(本路由器)与邻居路由器建立状态为Full的OSPF邻接关系的整个过程。乍一看,这份日志文件有好几页纸,让人望而生畏。但只要读者了解了与接口和邻居有关的各种状态,弄清了导致这些状态发生改变的各种事件,同时熟知构建邻接关系所涉及的协议数据包与各种表格(比如,邻居列表、链路状态发送列表、数据库汇总列表等),读懂这份日志文件却也不难。因此,作者并没有逐句解读这份日志文件,而是提出了一些问题,让读者自己寻找答案。以下所列为相关提示信息。
本路由器的RID为192.168.254.6。
本路由器的接口IP地址为192.168.7.1。
本路由器的物理接口为fe-4/0/0.0。
邻居路由器的RID为192.168.254.8。
邻居路由器的接口IP地址为192.168.7.2。
请读者在阅读日志文件的过程中,对时间戳多加注意,此外,请千万不要把接口状态的改变(interface state change)和邻居状态的改变(neighbor state change)混为一谈。以下为作者提出的要求或问题。
首先,应根据状态的“变迁”,把这份日志文件分为几个部分来解读。
从开始发现邻居路由器192.168.254.8,到与其建立起状态为Full的邻接关系,一共经历了多长时间?
请注意,日志文件显示的邻居状态的变化过程是从Init状态到2-Way状态,再到ExStart状态,而非上一节示例中所描述的从Init状态直接过渡到ExStart状态。请仔细阅读与上述邻居状态的改变有关的日志记录,看看能否找到“理论依据”。(提示:请留意与接口状态的改变有关的日志记录。)
数据库交换过程实际要耗时多久?
进行数据库同步时,网络内已经存在DR和BDR了吗?
jeff@Juniper6> show log ospf_state
Dec 28 05:28:49 OSPF Interface fe-4/0/0.0 event Up
Dec 28 05:28:49 OSPF interface fe-4/0/0.0 state changed from Down to Waiting
Dec 28 05:28:49 OSPF trigger router LSA build for area 0.0.0.0
Dec 28 05:28:49 OSPF built router LSA, area 0.0.0.0
Dec 28 05:28:50 OSPF sent Hello 192.168.7.1 -> 224.0.0.5 (fe-4/0/0.0)
Dec 28 05:28:50 Version 2, length 44, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:28:50 checksum 0x3d70, authtype 0
Dec 28 05:28:50 mask 255.255.255.0, hello_ivl 10, opts 0x2, prio 128
Dec 28 05:28:50 dead_ivl 40, DR 0.0.0.0, BDR 0.0.0.0
Dec 28 05:28:51 OSPF rcvd Hello 192.168.7.2 -> 224.0.0.5 (fe-4/0/0.0)
Dec 28 05:28:51 Version 2, length 44, ID 192.168.254.8, area 0.0.0.0
Dec 28 05:28:51 checksum 0x3ded, authtype 0
Dec 28 05:28:51 mask 255.255.255.0, hello_ivl 10, opts 0x2, prio 1
Dec 28 05:28:51 dead_ivl 40, DR 0.0.0.0, BDR 0.0.0.0
Dec 28 05:28:51 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed from Down
to Init
Dec 28 05:28:51 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed by event
HelloRcvd
Dec 28 05:28:52 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed from Init to 2Way
Dec 28 05:28:52 RPD_OSPF_NBRUP: OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed
from Init to 2Way due to Two way communication established
Dec 28 05:28:52 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed by event
2WayRcvd
Dec 28 05:28:52 OSPF Interface fe-4/0/0.0 event NeighborChange
Dec 28 05:29:29 OSPF Interface fe-4/0/0.0 event WaitTimer
Dec 28 05:29:29 OSPF interface fe-4/0/0.0 state changed from Waiting to DR
Dec 28 05:29:29 OSPF trigger router LSA build for area 0.0.0.0
Dec 28 05:29:29 OSPF trigger network LSA build for fe-4/0/0.0
Dec 28 05:29:29 OSPF DR is 192.168.254.6, BDR is 192.168.254.8
Dec 28 05:29:29 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed from 2Way to ExStart
Dec 28 05:29:29 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed by event AdjOK?
Dec 28 05:29:29 OSPF trigger router LSA build for area 0.0.0.0
Dec 28 05:29:29 OSPF sent DbD 192.168.7.1 -> 192.168.7.2 (fe-4/0/0.0)
Dec 28 05:29:29 Version 2, length 32, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:29 checksum 0x881b, authtype 0
Dec 28 05:29:29 options 0x42, i 1, m 1, ms 1, seq 0xc0a0ae8e, mtu 1500
Dec 28 05:29:29 OSPF built router LSA, area 0.0.0.0
Dec 28 05:29:30 OSPF sent Hello 192.168.7.1 -> 224.0.0.5 (fe-4/0/0.0)
Dec 28 05:29:30 Version 2, length 48, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:30 checksum 0xef65, authtype 0
Dec 28 05:29:30 mask 255.255.255.0, hello_ivl 10, opts 0x2, prio 128
Dec 28 05:29:30 dead_ivl 40, DR 192.168.7.1, BDR 192.168.7.2
Dec 28 05:29:31 OSPF rcvd DbD 192.168.7.2 -> 192.168.7.1 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 32, ID 192.168.254.8, area 0.0.0.0
Dec 28 05:29:31 checksum 0xdc16, authtype 0
Dec 28 05:29:31 options 0x42, i 1, m 1, ms 1, seq 0x1b32, mtu 1500
Dec 28 05:29:31 OSPF now slave for nbr 192.168.7.2
Dec 28 05:29:31 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed from ExStart to Exchange
Dec 28 05:29:31 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed by event
NegotiationDone
Dec 28 05:29:31 In sequence
Dec 28 05:29:31 OSPF sent DbD 192.168.7.1 -> 192.168.7.2 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 192, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:31 checksum 0x3a37, authtype 0
Dec 28 05:29:31 options 0x42, i 0, m 0, ms 0, seq 0x1b32, mtu 1500
Dec 28 05:29:31 OSPF rcvd DbD 192.168.7.2 -> 192.168.7.1 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 212, ID 192.168.254.8, area 0.0.0.0
Dec 28 05:29:31 checksum 0x34fe, authtype 0
Dec 28 05:29:31 options 0x42, i 0, m 1, ms 1, seq 0x1b33, mtu 1500
Dec 28 05:29:31 In sequence
Dec 28 05:29:31 Database copy is older
Dec 28 05:29:31 Database copy is older
Dec 28 05:29:31 OSPF rcvd LSReq 192.168.7.2 -> 192.168.7.1 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 84, ID 192.168.254.8, area 0.0.0.0
Dec 28 05:29:31 checksum 0xb70b, authtype 0
Dec 28 05:29:31 OSPF sent LSReq 192.168.7.1 -> 192.168.7.2 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 48, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:31 checksum 0x3b5d, authtype 0
Dec 28 05:29:31 OSPF rcvd LSUpdate 192.168.7.2 -> 192.168.7.1 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 96, ID 192.168.254.8, area 0.0.0.0
Dec 28 05:29:31 checksum 0x9970, authtype 0
Dec 28 05:29:31 adv count 2
Dec 28 05:29:31 OSPF LSA Router 192.168.254.8 192.168.254.8 from 192.168.7.2 newer
than db
Dec 28 05:29:31 OSPF LSA Router 192.168.254.8 192.168.254.8 newer, delayed ack
Dec 28 05:29:31 OSPF LSA Network 192.168.7.1 192.168.254.6 from 192.168.7.2 newer
than db
Dec 28 05:29:31 Our LSA
Dec 28 05:29:31 Removed from LSREQ list
Dec 28 05:29:31 Removed from LSREQ list
Dec 28 05:29:31 OSPF sent DbD 192.168.7.1 -> 192.168.7.2 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 32, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:31 checksum 0xdc1e, authtype 0
Dec 28 05:29:31 options 0x42, i 0, m 0, ms 0, seq 0x1b33, mtu 1500
Dec 28 05:29:31 OSPF sent LSUpdate 192.168.7.1 -> 192.168.7.2 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 200, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:31 checksum 0xd628, authtype 0
Dec 28 05:29:31 adv count 5
Dec 28 05:29:31 OSPF rcvd DbD 192.168.7.2 -> 192.168.7.1 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 32, ID 192.168.254.8, area 0.0.0.0
Dec 28 05:29:31 checksum 0xdc1a, authtype 0
Dec 28 05:29:31 options 0x42, i 0, m 0, ms 1, seq 0x1b34, mtu 1500
Dec 28 05:29:31 In sequence
Dec 28 05:29:31 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed from Exchange
to Full
Dec 28 05:29:31 RPD_OSPF_NBRUP: OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed
from Exchange to Full due to DBD exchange complete
Dec 28 05:29:31 OSPF trigger router LSA build for area 0.0.0.0
Dec 28 05:29:31 OSPF trigger network LSA build for fe-4/0/0.0
Dec 28 05:29:31 OSPF neighbor 192.168.7.2 (fe-4/0/0.0) state changed by event
ExchangeDone
Dec 28 05:29:31 OSPF sent LSUpdate 192.168.7.1 -> 224.0.0.5 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 60, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:31 checksum 0xb25, authtype 0
Dec 28 05:29:31 adv count 1
Dec 28 05:29:31 OSPF rcvd LSUpdate 192.168.7.2 -> 224.0.0.5 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 140, ID 192.168.254.8, area 0.0.0.0
Dec 28 05:29:31 checksum 0x9f55, authtype 0
Dec 28 05:29:31 adv count 4
Dec 28 05:29:31 OSPF LSA Summary 192.168.254.9 192.168.254.8 from 192.168.7.2
newer than db
Dec 28 05:29:31 OSPF LSA Summary 192.168.254.9 192.168.254.8 newer, delayed ack
Dec 28 05:29:31 OSPF LSA Summary 192.168.9.0 192.168.254.8 from 192.168.7.2
newer than db
Dec 28 05:29:31 OSPF LSA Summary 192.168.9.0 192.168.254.8 newer, delayed ack
Dec 28 05:29:31 OSPF LSA Summary 192.168.8.0 192.168.254.8 from 192.168.7.2
newer than db
Dec 28 05:29:31 OSPF LSA Summary 192.168.8.0 192.168.254.8 newer, delayed ack
Dec 28 05:29:31 OSPF LSA ASBRSum 192.168.254.9 192.168.254.8 from 192.168.7.2
newer than db
Dec 28 05:29:31 OSPF LSA ASBRSum 192.168.254.9 192.168.254.8 newer, delayed ack
Dec 28 05:29:31 OSPF sent DbD 192.168.7.1 -> 192.168.7.2 (fe-4/0/0.0)
Dec 28 05:29:31 Version 2, length 32, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:31 checksum 0xdc1d, authtype 0
Dec 28 05:29:31 options 0x42, i 0, m 0, ms 0, seq 0x1b34, mtu 1500
Dec 28 05:29:32 OSPF rcvd LSUpdate 192.168.7.2 -> 224.0.0.5 (fe-4/0/0.0)
Dec 28 05:29:32 Version 2, length 64, ID 192.168.254.8, area 0.0.0.0
Dec 28 05:29:32 checksum 0x60e6, authtype 0
Dec 28 05:29:32 adv count 1
Dec 28 05:29:32 OSPF LSA Router 192.168.254.8 192.168.254.8 from 192.168.7.2
newer than db
Dec 28 05:29:32 OSPF LSA Router 192.168.254.8 192.168.254.8 newer, delayed ack
Dec 28 05:29:32 OSPF sent LSAck 192.168.7.1 -> 224.0.0.5 (fe-4/0/0.0)
Dec 28 05:29:32 Version 2, length 124, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:32 checksum 0x51dc, authtype 0
Dec 28 05:29:32 OSPF rcvd Hello 192.168.7.2 -> 224.0.0.5 (fe-4/0/0.0)
Dec 28 05:29:32 Version 2, length 48, ID 192.168.254.8, area 0.0.0.0
Dec 28 05:29:32 checksum 0xefe4, authtype 0
Dec 28 05:29:32 mask 255.255.255.0, hello_ivl 10, opts 0x2, prio 1
Dec 28 05:29:32 dead_ivl 40, DR 192.168.7.1, BDR 192.168.7.2
Dec 28 05:29:32 OSPF Interface fe-4/0/0.0 event NeighborChange
Dec 28 05:29:32 OSPF interface fe-4/0/0.0 state changed from DR to DR
Dec 28 05:29:32 OSPF DR is 192.168.254.6, BDR is 192.168.254.8
Dec 28 05:29:33 OSPF sent Hello 192.168.7.1 -> 224.0.0.5 (fe-4/0/0.0)
Dec 28 05:29:33 Version 2, length 48, ID 192.168.254.6, area 0.0.0.0
Dec 28 05:29:33 checksum 0xef65, authtype 0
Dec 28 05:29:33 mask 255.255.255.0, hello_ivl 10, opts 0x2, prio 128
Dec 28 05:29:33 dead_ivl 40, DR 192.168.7.1, BDR 192.168.7.2
图6.9 记录了OSPF邻接关系建立全过程的日志文件(由Juniper路由器生成)
每一家厂商的路由器都有自己的一套排障信息生成(提供)方法,其基本原理全都相通,只是输出格式有所不同。只要能够理解底层协议及其运作机制,就应能不费吹灰之力地读懂任何一家厂商的路由器生成的路由协议相关的日志信息。
有一台Cisco路由器,与生成图6.9所示日志记录的那台Juniper路由器相邻,这台Cisco路由器接入该广播网络的物理接口为E0。图6.10所示为该Cisco路由器生成的与OSPF邻接关系的建立、(邻接关系建立过程中发生的)事件以及协议数据包的收发有关的Debug输出。这份Debug输出所覆盖的时间范围跟图6.9所示的日志文件大致相同。
跟之前一样,也应根据状态的“变迁”,把这份Debug输出分为几个部分来解读。
从这份Debug输出中找出与图6.9所示的日志文件中相匹配的事件。
两台路由器的时钟并未同步,可能会有1~2秒的误差。对于两份输出中相匹配的事件,在发生的时间周期上也匹配吗?
根据图6.9和图6.10所提供的信息,像图6.7那样试着画一张图,来描绘出两台路由器之间协议数据包的交换情况,以及邻居状态的变迁过程。
Dec 28 05:28:50: OSPF: rcv. v:2 t:1 l:44 rid:192.168.254.6
aid:0.0.0.0 chk:3D70 aut:0 auk: from Ethernet0
Dec 28 05:28:50: OSPF: Rcv hello from 192.168.254.6 area 0 from Ethernet0 192.168.7.1
00:42: 40: %LINEPROTO-5-UPDOWN: Line protocol on Interface Ethernet0, changed
state to up
Dec 28 05:28:51: OSPF: Interface Ethernet0 going Up
Dec 28 05:28:51: OSPF: Build router LSA for area 0, router ID 192.168.254.8, seq
0x800001D9
Dec 28 05:28:51: OSPF: Build router LSA for area 20, router ID 192.168.254.8, seq
0x800001D4
Dec 28 05:28:52: OSPF: 2 Way Communication to 192.168.254.6 on Ethernet0, state 2WAY
Dec 28 05:28:52: OSPF: End of hello processing
Dec 28 05:29:01: OSPF: rcv. v:2 t:1 l:48 rid:192.168.254.6
aid:0.0.0.0 chk:7EBA aut:0 auk: from Ethernet0
Dec 28 05:29:29: OSPF: rcv. v:2 t:2 l:32 rid:192.168.254.6
aid:0.0.0.0 chk:881B aut:0 auk: from Ethernet0
Dec 28 05:29:29: OSPF: Rcv DBD from 192.168.254.6 on Ethernet0 seq 0xC0A0AE8E opt
0x42 flag 0x7 len 32 mtu 1500 state 2WAY
Dec 28 05:29:29: OSPF: Nbr state is 2WAY
Dec 28 05:29:30: OSPF: rcv. v:2 t:1 l:48 rid:192.168.254.6
aid:0.0.0.0 chk:EF65 aut:0 auk: from Ethernet0
Dec 28 05:29:30: OSPF: Rcv hello from 192.168.254.6 area 0 from Ethernet0 192.168.7.1
Dec 28 05:29:30: OSPF: End of hello processing
Dec 28 05:29:31: OSPF: end of Wait on interface Ethernet0
Dec 28 05:29:31: OSPF: DR/BDR election on Ethernet0
Dec 28 05:29:31: OSPF: Elect BDR 192.168.254.8
Dec 28 05:29:31: OSPF: Elect DR 192.168.254.6
Dec 28 05:29:31: OSPF: Elect BDR 192.168.254.8
Dec 28 05:29:31: OSPF: Elect DR 192.168.254.6
Dec 28 05:29:31: DR: 192.168.254.6 (Id) BDR: 192.168.254.8 (Id)
Dec 28 05:29:31: OSPF: Send DBD to 192.168.254.6 on Ethernet0 seq 0x1B32 opt 0x42
flag 0x7 len 32
Dec 28 05:29:31: OSPF: rcv. v:2 t:2 l:192 rid:192.168.254.6
aid:0.0.0.0 chk:3A37 aut:0 auk: from Ethernet0
Dec 28 05:29:31: OSPF: Rcv DBD from 192.168.254.6 on Ethernet0 seq 0x1B32 opt 0x42
flag 0x0 len 192 mtu 1500 state EXSTART
Dec 28 05:29:31: OSPF: NBR Negotiation Done. We are the MASTER
Dec 28 05:29:31: OSPF: Send DBD to 192.168.254.6 on Ethernet0 seq 0x1B33 opt 0x42
flag 0x3 len 212
Dec 28 05:29:31: OSPF: Database request to 192.168.254.6
Dec 28 05:29:31: OSPF: sent LS REQ packet to 192.168.7.1, length 60
Dec 28 05:29:31: OSPF: rcv. v:2 t:3 l:48 rid:192.168.254.6
aid:0.0.0.0 chk:3B5D aut:0 auk: from Ethernet0
Dec 28 05:29:31: OSPF: rcv. v:2 t:2 l:32 rid:192.168.254.6
aid:0.0.0.0 chk:DC1E aut:0 auk: from Ethernet0
Dec 28 05:29:31: OSPF: Rcv DBD from 192.168.254.6 on Ethernet0 seq 0x1B33 opt 0x42
flag 0x0 len 32 mtu 1500 state EXCHANGE
Dec 28 05:29:31: OSPF: Send DBD to 192.168.254.6 on Ethernet0 seq 0x1B34 opt 0x42
flag 0x1 len 32
Dec 28 05:29:31: OSPF: rcv. v:2 t:4 l:200 rid:192.168.254.6
aid:0.0.0.0 chk:D628 aut:0 auk: from Ethernet0
Dec 28 05:29:31: OSPF: rcv. v:2 t:4 l:60 rid:192.168.254.6
aid:0.0.0.0 chk:B25 aut:0 auk: from Ethernet0
Dec 28 05:29:31: OSPF: rcv. v:2 t:2 l:32 rid:192.168.254.6
aid:0.0.0.0 chk:DC1D aut:0 auk: from Ethernet0
Dec 28 05:29:31: OSPF: Rcv DBD from 192.168.254.6 on Ethernet0 seq 0x1B34 opt 0x42
flag 0x0 len 32 mtu 1500 state EXCHANGE
Dec 28 05:29:31: OSPF: Exchange Done with 192.168.254.6 on Ethernet0
Dec 28 05:29:31: OSPF: Synchronized with 192.168.254.6 on Ethernet0, state FULL
Dec 28 05:29:32: OSPF: Build router LSA for area 0, router ID 192.168.254.8, seq
0x800001DA
Dec 28 05:29:32: OSPF: rcv. v:2 t:5 l:124 rid:192.168.254.6
aid:0.0.0.0 chk:51DC aut:0 auk: from Ethernet0
Dec 28 05:29:33: OSPF: rcv. v:2 t:1 l:48 rid:192.168.254.6
aid:0.0.0.0 chk:EF65 aut:0 auk: from Ethernet0
Dec 28 05:29:33: OSPF: Rcv hello from 192.168.254.6 area 0 from Ethernet0 192.168.7.1
Dec 28 05:29:33: OSPF: Neighbor change Event on interface Ethernet0
Dec 28 05:29:33: OSPF: DR/BDR election on Ethernet0
Dec 28 05:29:33: OSPF: Elect BDR 192.168.254.8
Dec 28 05:29:33: OSPF: Elect DR 192.168.254.6
Dec 28 05:29:33: DR: 192.168.254.6 (Id) BDR: 192.168.254.8 (Id)
Dec 28 05:29:33: OSPF: End of hello processing
Dec 28 05:29:34: OSPF: rcv. v:2 t:4 l:120 rid:192.168.254.6
aid:0.0.0.0 chk:B658 aut:0 auk: from Ethernet0
图6.10 对端路由器(Cisco路由器)生成的建立同一个OSPF邻接关系的Debug输出
6.1.8 OSPF排障方法2:学会比较(不同路由器的)LS数据库
在新型OSPF或IS-IS网络中,导致路由选择故障(数据包不能正确转发)的原因一般都非常常见,不是链路故障,就是路由器配置有误。通常,只要仔细观察路由器的路由信息表和转发信息表,便不难发现故障的根源。因某个区域内(OSPF路由器间的)LS数据库不一致,而造成的路由选择故障非常罕见。说其罕见,是因为倘若一对OSPF邻居路由器在同步过数据库之后,LS数据库还不能保持一致,将会导致邻接关系的“破裂”。此外,区域内的路由器在做出路由决策时,也会将邻接关系建立出现问题的这对路由器之间的路径(链路)排除在外。
然而,(区域内OSPF路由器间)LS数据库不同步的现象却绝对有可能发生。这多半要拜赐于糟糕的OSPF实现,或包含OSPF实现的OS出现了 bug。本节会展示如何比较(不同路由器的)LS数据库,以帮助读者应对某些极端情况。所谓极端情况是指:明知网络中发生了路由选择故障,但不管怎么查,都查不出故障原因。
首先,应比较(不同路由器的)LS数据库汇总信息,以验证存储在每台路由器的数据库里的LSA的类型和数量是否匹配。跟上一节所举示例相同,由不同厂商的路由器生成的LS数据库汇总信息的输出(格式)虽然各不相同,但所反映出的内容却大体相同。图6.11和图6.12分别显示了由Juniper和Cisco路由器(即上一节用来举例的那两台路由器)生成的LS数据库汇总信息。经过比较,可以发现两台路由器在区域0的LS数据库里存储的LSA至少在条数上相同:
4条路由器LSA;
4条网络LSA;
10条网络汇总LSA;
1条ASBR汇总LSA;
2条外部LSA(在Cisco路由器生成的LS数据库汇总信息里,这2条外部LSA出现在“Process 1 database summary”下的“Type-5 Ext”一栏)。
Cisco8#show ip ospf database database-summaty
OSPF Router with ID (192.168.254.8) (Process ID 1)
Area 0 database summary
LSA Type Count Delete Maxage
Router 4 0 0
Network 4 0 0
Summary Net 10 0 0
Summary ASBR 1 0 0
Type-7 Ext 0 0 0
Opaque Link 0 0 0
Opaque Area 0 0 0
Subtotal 19 0 0
Area 20 database summary
LSA Type Count Delete Maxage
Router 2 0 0
Network 1 0 0
Summary Net 12 0 0
Summary ASBR 0 0 0
Type-7 Ext 0 0 0
Opaque Link 0 0 0
Opaque Area 0 0 0
Subtotal 16 0 0
Process 1 database summary
LSA Type Count Delete Maxage
Router 6 0 0
Network 5 0 0
Summary Net 23 0 0
Summary ASBR 1 0 0
Type-7 Ext 0 0 0
Opaque Link 0 0 0
Opaque Area 0 0 0
Type-5 Ext 2 0 0
Opaque AS 0 0 0
Total 37 0 0
Cisco8#
图6.12 Cisco路由器生成的OSPF LS数据库汇总信息
由于那台Cisco路由器(见图6.12)担任ABR一职,固其还持有区域20的LS数据库。但区域20的LS数据库的信息跟本节所要讨论的内容无关,理由是那两台路由器的互连接口都隶属于区域0。
虽然那两台路由器的LS数据库所保存的LSA的条数匹配,但会不会发生一条或多条LSA的实例不一致的现象呢?要想对此加以验证,就得先把那两个LS数据库里的所有LSA的校验和分别相加,然后再进行比较。只要那两个数据库里的LSA实例相同,校验和的相加结果也必定相等。否则,就得到两个数据库中分别比较每条LSA的校验和,以发现不一致的LSA的实例。
图6.13和图6.14分别显示了Juniper路由器和Cisco路由器生成的LSA头部的输出。作者分别把两个数据库里的所有LSA(只限于区域0,不含外部LSA)的校验和累加,得到的结果都是0xB4C0D。
所有路由器LSA的校验和相加:0x2938A。
所有网络LSA的校验和相加:0x24718。
所有网络汇总LSA的校验和相加:0x5F5AE。
所有ASBR汇总LSA的校验和相加:0x7BBD。
jeff@Juniper6> show ospf database
OSPF link state database, area 0.0.0.0
Type ID Adv Rtr Seq Age Opt Cksum Len
Router 192.168.254.5 192.168.254.5 0x80001d0b 2082 0x2 0x96dc 36
Router *192.168.254.6 192.168.254.6 0x80000772 932 0x2 0x826f 96
Router 192.168.254.7 192.168.254.7 0x80001945 1193 0x2 0x7acb 48
Router 192.168.254.8 192.168.254.8 0x800001ef 867 0x22 0xff74 36
Network 192.168.3.2 192.168.254.5 0x80000004 126 0x2 0x9c03 32
Network 192.168.4.2 192.168.254.7 0x80000004 1651 0x2 0x9901 32
Network 192.168.5.2 192.168.254.7 0x80000003 1335 0x2 0x900a 32
Network *192.168.7.1 192.168.254.6 0x80000010 846 0x2 0x820a 32
Summary 192.168.1.0 192.168.254.5 0x800006c9 1168 0x2 0xf1c3 28
Summary 192.168.2.0 192.168.254.5 0x800006c9 1025 0x2 0xe6cd 28
Summary 192.168.6.0 192.168.254.5 0x8000033f 883 0x2 0xe25a 28
Summary 192.168.8.0 192.168.254.8 0x8000001a 867 0x22 0x7cbb 28
Summary 192.168.9.0 192.168.254.8 0x80000018 867 0x22 0xd955 28
Summary 192.168.254.2 192.168.254.5 0x8000033b 1183 0x2 0x1a2d 28
Summary 192.168.254.4 192.168.254.5 0x8000033a 868 0x2 0x83e 28
Summary 192.168.254.5 192.168.254.5 0x80001ce3 725 0x2 0x552e 28
Summary 192.168.254.7 192.168.254.7 0x80001916 1351 0x2 0xd976 28
Summary 192.168.254.9 192.168.254.8 0x80000018 867 0x22 0x93a5 28
ASBRSum 192.168.254.9 192.168.254.8 0x80000018 867 0x22 0x7bbd 28
OSPF external link state database
Type ID Adv Rtr Seq Age Opt Cksum Len
Extern 192.168.120.0 192.168.254.9 0x800001d0 14 0x20 0x3a8d 36
Extern 192.168.220.0 192.168.254.9 0x800001d0 14 0x20 0xe979 36
jeff@Juniper6>
图6.13 Juniper路由器生成的LS数据库里的LSA头部信息
Cisco8# show ip ospf database
OSPF Router with ID (192.168.254.8) (Process ID 1)
Router Link States (Area 0)
Link ID ADV Router Age Seq# Checksum Link count
192.168.254.5 192.168.254.5 1969 0x80001D0B 0x96DC 1
192.168.254.6 192.168.254.6 819 0x80000772 0x826F 6
192.168.254.7 192.168.254.7 1079 0x80001945 0x7ACB 2
192.168.254.8 192.168.254.8 752 0x800001EF 0xFF74 1
Net Link States (Area 0)
Link ID ADV Router Age Seq# Checksum
192.168.3.2 192.168.254.5 12 0x80000004 0x9C03
192.168.4.2 192.168.254.7 1537 0x80000004 0x9901
192.168.5.2 192.168.254.7 1222 0x80000003 0x900A
192.168.7.1 192.168.254.6 733 0x80000010 0x820A
Summary Net Link States (Area 0)
Link ID ADV Router Age Seq# Checksum
192.168.1.0 192.168.254.5 1055 0x800006C9 0xF1C3
192.168.2.0 192.168.254.5 914 0x800006C9 0xE6CD
192.168.6.0 192.168.254.5 772 0x8000033F 0xE25A
192.168.8.0 192.168.254.8 754 0x8000001A 0x7CBB
192.168.9.0 192.168.254.8 754 0x80000018 0xD955
192.168.254.2 192.168.254.5 1072 0x8000033B 0x1A2D
192.168.254.4 192.168.254.5 756 0x8000033A 0x83E
192.168.254.5 192.168.254.5 614 0x80001CE3 0x552E
192.168.254.7 192.168.254.7 1240 0x80001916 0xD976
192.168.254.9 192.168.254.8 755 0x80000018 0x93A5
Summary ASB Link States (Area 0)
Link ID ADV Router Age Seq# Checksum
192.168.254.9 192.168.254.8 755 0x80000018 0x7BBD
Router Link States (Area 20)
Link ID ADV Router Age Seq# Checksum Link count
192.168.254.8 192.168.254.8 755 0x800001E9 0x2256 1
192.168.254.9 192.168.254.9 1173 0x800001D5 0xD4A6 3
Net Link States (Area 20)
Link ID ADV Router Age Seq# Checksum
192.168.8.1 192.168.254.9 1173 0x80000017 0x93CA
Summary Net Link States (Area 20)
Link ID ADV Router Age Seq# Checksum
172.16.1.0 192.168.254.8 756 0x80000016 0x6283
192.168.1.0 192.168.254.8 1004 0x80000003 0xC48
192.168.2.0 192.168.254.8 1004 0x80000003 0x152
192.168.3.0 192.168.254.8 1004 0x80000005 0xE769
192.168.4.0 192.168.254.8 237 0x8000000A 0xD278
192.168.5.0 192.168.254.8 1996 0x80000012 0xB78A
192.168.6.0 192.168.254.8 1004 0x80000003 0xDE6F
192.168.7.0 192.168.254.8 756 0x80000018 0x8BAF
192.168.254.2 192.168.254.8 1004 0x80000003 0xE46
192.168.254.4 192.168.254.8 1004 0x80000003 0xF958
192.168.254.5 192.168.254.8 1004 0x80000003 0xE56C
192.168.254.6 192.168.254.8 756 0x80000016 0xAB93
192.168.254.7 192.168.254.8 237 0x80000003 0xD17E
Type-5 AS External Link States
Link ID ADV Router Age Seq# Checksum Tag
192.168.120.0 192.168.254.9 1948 0x800001D0 0x3C8C 0
192.168.220.0 192.168.254.9 1949 0x800001D0 0xEB78 0
Cisco8#
图6.14 Cisco路由器生成的LS数据库里的LSA头部信息
Juniper路由器和Cisco路由器的两条外部LSA的校验和之和分别为0x12406和0x12804。当然,对于本例,逐一比对两个数据库里的那两条外部LSA的校验和,要比比较两条外部LSA的校验和之和简单得多。不过,要是数据库的规模一大,哪种比较方法更加简单,那就很难说了。让人头痛的是,对于大型网络,路由器控制台显示出的LS数据库的输出,肯定会比图6.11和图6.12长很多,无论使用哪种比较方法都既容易犯错,又枯燥无味。更悲催的是,要是读者在捕获两台路由器的LS数据库输出的间隔期,网络中有路由器刷新了自己的数据库,那么即便那两台路由器的LS数据库的内容一致,相比较的结果也肯定不匹配。
幸运的是,解决方案倒不是没有。无论读者管理什么样的网络,只要网络规模一大,多半都会部署基于SNMP的网管软件。利用以下所列OSPF MIB,就能(通过网管软件)自动采集到LSA的校验和之和,可让网管人员免遭枯燥无味的十六进制数加法计算之苦。
ospfAreaLsaCksumSum 能用来获取一个区域内所有LSA的校验和之和(外部LSA除外)。
ospfExternLsaCksumSum 能用来获取外部(类型5)LSA的校验和之和。
然而,(两台路由器数据库里的)LSA的校验和之和不匹配,只是表明存在数据库同步问题。单凭这些信息,既无法定位导致问题的原因,也肯定搞不清具体是哪条LSA不匹配。退一步来说,一般的网管人员能判断出网络存在OSPF数据库不同步问题,水平也算不俗。在判断出网络存在类似问题之后,网管人员可尝试先手工拆除,再重建邻接关系,让相关OSPF邻居路由器之间重新同步数据库。若症状还未消失,那就赶紧致电设备厂商的技术支持团队,需要由他们来深入分析,并判断OSPF软硬件实现方面是否存在问题。
1译者注:原文是“So when two OSPF neighbors are comparing LSAs, one of the neighbors manages the exchange”。
2本例扩充自RFC 2328 10.10节所举示例,以及Routing TCP/IP, Volume I 445~447页所载示例。
3译者注:原文是“The actual events causing the state changes are discoveries or changes of information included in the packets”。