深入探讨OSPF环路问题

前言:

OSPF是我们每一个网络工程师都非常熟悉的一个IGP协议,因为其自身的优点(配置简单,分层设计,网络类型丰富等)使得OSPF在现有的网络中部署的非常之多,各种讨论OSPF的文章及案例也层出不穷,所以我就在想,如果我要以OSPF为题写一篇技术型文章,到底写什么样的内容才会让你们有观看的***,绞尽脑汁最后把思路聚焦于环路的问题上。

我们都知道OSPF是基于SPF算法的动态路由协议,SPF算法有一个最大的优点是可以保证网络的绝对无环,但因为OSPF采用的是分区域设计,每一个区域都单独的维护各自的数据库,执行各自的SPF算法,所以SPF可以保证OSPF无环的前提条件是在同一个区域内,即在同一个区域内,OSPF构建的网络是一个绝对无环的网络。但OSPF区域间信息的传递是依靠3 类lsa,而3类lsa里面携带的其实就是路由,所以我们说OSPF在区域间是存在失量形为(直接传递路由的形为称为失量形为)的,因为失量形为的存在,也就导致了OSPF的环路问题。

接下来,我会带领大家进入OSPF环路的世界,也会让大家见识到当初设计OSPF协议的工程师是如何费尽心思的解决OSPF环路问题的。

环路场景:

场景一:OSPF区域间环路

我们都知道,OSPF在设计区域结构的时候有两个非常重要的规则:

规则一、所有非骨干区域都必须与骨干区域相连

规则二、骨干区域不能被分割

因为有这两个规则的存在,说实话大大的限制了OSPF在部署时的灵活性,那协议开发者为什么要设计这两个规则出来呢? 如果没有这两个规则又会带来什么问题?带着这此问题,我们来看两个拓扑:

在这里插入图片描述

如图一所示(假定没有所有非骨干区域都必须与骨干区域相连这条规则):

1、R6上有一个loopback接口,地址为:6.6.6.6/32,宣告进了Area 4.

2、R6会产生关于6.6.6.6的1类lsa,类型为stub,并传递给R2。

3、因为R2位于区域边界,连接两个不同的区域,所以会把1类lsa中描述路由信息的stub转换为3类lsa,并在其它区域传递。

4、在图一中,R1;R3;R4也都位于区域边界,所以当R1收到这份3类lsa时,会传递给R3,R3此时又传递给R7,R7传递给R4,R4同理也会传递给R2。

5、此时R2会认为去往6.6.6.6这个网段有两条路径可达,一条是直接走R6,另一条是走R4,如果R2选择了R4去往6.6.6.6,那就产生了R2-R4-R7-R3-R1-R2这个环路。

总结:因为有了以上环路的风险,所以开发者在设计OSPF时必须解决这个问题,也就有了规则一(所有非骨干区域都必须与骨干区域相连),那协议的设计者是如何保证规则一不被打破的呢? 要明白这个问题,首先需要明白一个非常重要的概念:ABR(区域边界路由器),需要满足以下三个条件才能成为一台真正意义上的ABR:

1、至少连接两个区域

2、连接的区域中有一个是区域零(骨干区域)

3、在区域零中至少有一个活跃的邻居

而定义ABR的作用就在于:只有ABR才能产生3类lsa,如图一所示,R3与R4都连接了两个区域,但他们却都不是ABR(不满足第2第3条),也就是说当R1这台ABR把描述6.6.6.6这条路由的3类LSA传递给R3时,因为R3不是ABR,所以不会把该条3类LSA传递给R7,R4在区域3中也就收不到这份3类lsa,同理R2也不会从区域2中收到关于6.6.6.6网段的3类LSA,也就防止了环路的产生。

接下来我们来研究一下第二个规则的必要性:

在这里插入图片描述

如图二所示:(假定骨干区域能被分割)

1、R2上有一个loopback接口,地址为2.2.2.2/32,宣告进了区域3。

2、R2作为区域2的ABR,所以会向区域2内产生关于2.2.2.2网段的3类LSA

3、R4从区域2中学习到此条3类LSA,因为R4也是一台ABR,所以R4也会向区域0中产生关于2.2.2.2网段的3类LSA。

4、R3从区域0中学习到此条3类LSA,因为R3也是一台ABR,所以R3也会向区域1中产生关于2.2.2.2网段的3类LSA。

5、R1从区域1中学习到此条3类LSA,因为R1也是一台ABR,所以R1也会向区域0中产生关于2.2.2.2网段的3类LSA。

6、此时R2学习到了两条关于2.2.2.2的路由,一条是自己产生的,另一条是R1发过来的,当R2自己产生的2.2.2.2不可达时,就会优选从R1过来的路由,所以就会导致R2访问2.2.2.2时出现R2-R1-R3-R4-R2这样一条环路。

总结:有了环路,一定要想办法规避,所以针对图二的环路问题,协议开发者制定了规则二(骨干区域不能被分割),为了保证规则二不会被打破,OSPF规定:从非骨干区域收到的3类LSA,ABR能接收但不会使用这条3类LSA(此条规定也可以称为OSPF的水平分割原则)。所以在上述的第三步中,R4作为一台ABR,从非骨干区域(Area 2)中收到一条3类LSA,R4是不会处理的(不会参与路由计算,不会泛洪),在上图中R4与R3都无法访问2.2.2.2网段,从而避免了环路。

场景二:OSPF外部路由引起的环路

OSPF的路由可以分为两种,一种是内部路由,由1类,2类,3类LSA形成的路由都是内部路由,即network产生的路由。另外一种是外部路由,由5类,7类LSA形成的称为外部路由,即import产生的路由。内部路由的环路问题可以通过场景一的内容解决,那外部路由是否会有环路问题?以及我们的解决办法又是什么呢? 在正式讲外部路由引起的环路问题时,需要先科普一下OSPF的一些相关知识点:

1、特殊区域:OSPF为了能适应各种环境及路由器的组网,开发了特殊区域这一概念,OSPF的特殊区域可分为两种类型:

A、stub区域:stub区域拒绝5类lsa进入,即拒绝外部路由进入本区域,也不能在本区域下面引入外部路由,区域内的路由器通过ABR下发的默认路由来访问外部网络。

B、NSSA区域:这是一种特殊的stub区域,它保持了stub区域拒绝5类lsa的特点,但是它能允许在该区域引入外部路由,外部路由以7类lsa的形式存在于本区域中,nssa区域的ABR会向其它区域把此7类LSA翻译(转换)成5类LSA(俗称7转5),使其它区域的路由器可以访问此外部路由。

2、外部路由类型:ospf外部路由有两种类型

A、Type 1:也称为E1。路由器在计算type1路由的Cost时,会把此路由的外部cost(ASBR到达目标网段的cost)与内部cost(本路由器到达ASBR的cost)相加。

B、Type 2:也称为E2,引入路由时默认为此类型,路由器在计算type2路由的cost时,只计算外部cost,而忽略内部cost。但当一台路由器收到两条相同的type2路由时,首先会对比外部cost的值,如果一样再对比内部cost值。

3、FA地址:FA的全称为forwarding address,是5类lsa与7类lsa中的一个字段,FA字段可以影响路由器的选路,所以它的作用是用于解决次优与环路。(FA作为OSPF协议中的一个重点与难点,要讲的东西可以有很多,因为本文章我们主要讲解环路,所以FA只会以结论的形式引入)。

4、外部路由的选路问题:大致可分为两种情况

情况一:外部路由中未包含FA地址:此时路由器计算去往ASBR的路径。

情况二:外部路由中包含FA地址:此时路由器直接计算去往FA的路径。

回顾了以上知识点后,我们来看这样一张拓扑图:
在这里插入图片描述

如图三所示:区域1为NSSA区域,各链路的cost如图所示:

1、在R1上把1.1.1.1引入OSPF,此时R1会产生关于1.1.1.1网段的7类LSA。

2、R2与R3作为Area1的ABR,都有责任进行7转5的动作,但OSPF规定默认情况下只有R-ID大的才能进行7转5,R2与R3的R-ID如图所示,即R3会进行7转5的动作,由R3产生关于1.1.1.1的5类lsa,并在Area0中泛洪。

3、R4从Area 0中收到此5lsa,并泛洪给R2。

4、我们来分析R4如何去往1.1.1.1,此时会有两种情况:

情况一:R4收到的这条5类LSA中FA地址为0.0.0.0

根据OSPF外部路由的选路规则,当5类LSA中FA地址为0时,则计算去往ASBR的路径。

1、此时产生此条5类LSA的是R3,所以R3为ASBR,R4可直接通过Area 0到达ASBR(R3)。

2、R3是通过Area 1学习到的1.1.1.1网段,所以R3可通过Area1去往1.1.1.1,即把数据包发送给R2。

3、此时R2可通过两条LSA学习到1.1.1.1的路由

第一条:R1产生的7类LSA。类型为Type2,外部Cost为1(外部cost默认都为1),内部cost为10(内部cost,本路由器到ASBR的cost)

第二条:R3产生的5类LSA,由R4泛洪给R2(参考上面第二步),类型为Type 2,外部Cost为1,内部Cost为2(R2-R4-R3的cost)

4、R2执行选路规则,两条LSA同为Type2类型,先对比外部cost值,都为1,然后对比内部cost值,第一条为10,第二条为2,所以R2会优选第二条(R3产生的5类lsa),即会把数据包转发给R4。

5、环路形成:R4-R3-R2-R4

情况二:R4收到的这条5类LSA中FA地址为10.1.12.1(R1与R2的互联接口)

根据OSPF外部路由的选路规则,当5类LSA中FA地址为非0时,直接计算去往FA地址的路径。

1、在此图中R4收到的5类LSA中FA地址为10.1.12.1,关于10.1.12.1这个地址,R4是通过3类LSA学习到的(10.1.12.1位于Area 1中,R2与R3都为ABR,都会产生关于10.1.12.0网段的3类lsa),R4此时其实可以收到两条10.1.12.0的3类LSA,一条R2产生,一条R3产生,通过计算cost后发现,选择R2去往10.1.12.1更近,所以R4会把数据包转发给R2。

2、R2同样执行选路计算,计算去往FA地址10.1.12.1的路径,此地址是R2的一个直连路由,所以R2会把数据包转发给R1。

3、此时全程的路径为:R4-R2-R1,解决了环路问题。

总结:OSPF针对外部路由可以通过FA地址来防环,7类LSA中一般情况下都会携带FA地址,在执行7转5后FA地址会默认保留,所以在默认情况下面不会出现环路问题。如果我们在做7转5时把FA地址抵制了,就有可能出现上述的环路问题。5类LSA FA地址的填充需要满足一些条件,有机会我再整理一篇文章来单独讲FA地址。

场景三:OSPF Vlink导致的环路问题

我们在场景一的时候讨论过设计区域的两个规则,因为有这两个规则的存在,大大降低了网络部署的灵活性,为了解决这个灵活性问题协议开发者开发了Vlink这个技术。

使用Vlink技术可以很好的解决区域被分割的问题,但Vlink却是一把双刃剑,配置好了可以修复区域分割,但配置错了的话也会导致环路,接下来我们就一起来讨论一下Vlink导致环路的问题。
在这里插入图片描述

如图四所示:此拓扑中Area 2没有与Area 0相连,打破了OSPF区域设计时所有非骨干区域都需要与骨干区域相连的规则,所以在正常情况下,区域0与区域2中的路由器是不能互访的,为了能使这两个区域互访,我们可以在R2与R4之间建立一条Vlink,使得区域2能使用R2与R4之间的这条虚链路连接到区域0,此时我们一步一步的分析下这个拓扑所产生的问题。

1,R5上有一个loopback接口,地址为5.5.5.5/32,宣告进了区域2。

2,R4作为区域2中的ABR(R2与R4之间的Vlink建立起来后,R4就成为了一台ABR),会产生关于5.5.5.5网段的3类LSA,并向区域1与区域0泛洪。

3,此时区域1中的关于5.5.5.5网段的这条3类LSA会传递给R3,R3在区域1中传递给R2。

4,区域0中的关于5.5.5.5网段的这条3类LSA会通过Vlink传递给R2(Vlink使用单播传递LSA),R2经区域0传递给R1,R1经区域0传递给R3(注意R2并不能直接把这条3类LSA传递给R3,因为R2与R3之间的链路在区域1中)。

5,这个时候我们来分析下R3的情况,经第三步与第四步可得知,R3能收到两条关于5.5.5.5网段的3类LSA:

A:由R4产生,在区域0中由R4-R2-R1-R3传递过来

B:由R4产生,在区域1中由R4-R3传递过来

6,根据场景一中所讲的规定,从非骨干区域收到的3类LSA,ABR能接收但不会使用这条3类LSA,即R3虽然能收到两条关于5.5.5.5网段的3类LSA,但它能使用的只有第一条,即由区域0传递过来的这条3类LSA。

7,因为只能使用R1传递给R3的3类LSA,所以当R3要访问5.5.5.5时,会先把数据包转发给R1,R1转发给R2,R2知道去往5.5.5.5的数据包是要转发到R4的,但R2去往R4只能经过区域1传递给R3,所以此时产生了R3-R2-R1-R3的环路。

总结:在华为设备上此环路的解决办法为修改Vlink的邻居建立路由器,在R3与R4之间配置Vlink就可以避免环路。

在思科设备上,除了修改建立邻居的路由器外,还可以通过no capability transit(默认启用)命令来解决此环路。

no capability transit命令解释:

首先得明白transit,transit是指Vlink所建立的区域,在上图中区域1为transit区域。使能这条命令后,当R3在区域0中收到一条3类lsa时,发现此3类LSA的ADV(通知者)为R4,并且R4在transit区域中可达,此时R3会计算从transit区域中去往此ADV-Router的Cost,如果计算结果为经过transit区域去往R4要比走区域0近,那就会选择从transit区域去往目标。如图四所示,R3此时会选择走transit区域去往目标网段,还不走区域0,从而避免了环路。

场景四:OSPF选路规则导致的环路(RFC2328、RFC1583)

OSPF的选路规则对于每一个网络工程师来说都应该能说出几点,选路规则的设计原本是为了让路由器能选择出更好的路由,那为什么会产生环路呢,在探讨这个问题之前,我们先来复习一下OSPF的选路规则有哪些:

1、域内路由优于域间路由:即由1类或者2类lsa生成的路由是优先于3类lsa生成的路由的。

2、域间路由优于外部路由:即由3类lsa产生的路由是优于5类或者是7类产生的路由。

3、如果同为外部路由,则先比较路由的Type,Type1优于Type2

4、如果同为Type1:则比较路由的外部cost与内部cost之和,选择选小的。

5、如果同为Type2:则先比较路由的外部cost值,相同再比较路由的内部cost值,不一样就选择小的。(详情见上篇文章的场景二)。

知道如上选路规则后,再给你们介绍一下OSPF的开发历史:OSPF由IETF在20世纪80年代末期开发,最初的OSPF规范体是在RFC1131中描述的,这称为OSPF的第一个版本,但因为这个OSPF版本1有很多不成熟的地方,所以很快就被新开发的标准所替代,这个新的标准在RFC1247文档中进行描述,RFC1247在稳定性和功能性方面都有了实质性的改进,所以称为OSPF版本2,在后续的发展中,又针对了这个OSPF版本有许多更新文档出现,每一个更新都是对是OSPF的精心改进,这些更新文档包括RFC1583、2178和2328中。目前我们所学习与使用的OSPF版本2中的各种特性都在RFC2328中进行了描述。

有了以上历史知识后,回到我们这个场景主要讨论的两个标准:RFC1583与RFC2328,RFC1583与RFC2328存在着诸多的不一样,这里我们主要讨论下这两个RFC标准中选路规则所涉及的问题:

RFC1583规定:外部路由选路时只需要对比cost值,cost值小的优先,如果cost值相同则负载。

RFC2328规定:外部路由选路时只需要对比区域号大小,而不需要对比cost值,区域号大的将优先使用。

有了以上理论知识后,我们来分析一个拓扑图:
在这里插入图片描述

深入探讨OSPF环路问题(二)-2656969-1

如图五所示:假设R2上运行的OSPF是执行RFC2328的选路规则,其它路由器执行RFC1583选路规则。

1、R3上有一个loopback接口,地址为10.1.3.3,引入进OSPF,产生5类LSA,ASBR为R3。

2、当R2收到这条5类LSA后,经计算会有3条路径去往ASBRR3,分别为:

A、R2-R1-R3:经过区域0,内部cost值为11(如果不清楚内部cost与外部cost区域,请参考场景二)

B、R2-R3:经过区域0,内部cost值为1。

C、R2-R4-R3:经过区域1,内部cost值为21。

3、根据RFC2328的选路规则,只比较路径的区域号大小,不比较cost值,所以R2会优先C路径去往R3。此时R2会将数据发送给R4。

4、R4也需要计算到达ASBRR3的路径,此时R4上也有两条路径可达到R3。

A、R4-R1-R3:经过区域0,内部cost值为11。

B、R4-R3:经过区域1,内部cost值为20。

5、根据RFC1583的选路规则,只比较路径的cost值,不比较区域号,所以R4会优选cost值小的路径A。此时R4将数据发送给R1。

6、R1也需要计算到达ASBRR3的路径,此时R1上也有两条路径可达到R3。

A、R1-R3:经过区域0,内部cost值为10。

B、R1-R2-R3:经过区域0,内部cost值为2。

7、根据外部路由选路规则,如果从同一区域收到,则直接比较cost,cost值小的优先,所以R4会优选B路径到达R3,此时数据包会转发给R2。

8、此时环路产生:R2-R4-R1-R2。

由环路现象可知,此环路产生的原因是由于R2上执行的是RFC2328选路规则,而R4上执行的是RFC1583选路规则所致,有环路就必须要有解决此环路的办法,针对此处我们能想到的最简单的办法应该是修改ospf路由器的选路规则,使全网保持一致。这样修改完成后确实可以解决此问题,但是你到底是修改成2328呢还是1583,因为他们都有各自的特点,2328考虑到了骨干区域的负载问题,但没有考虑到cost,而1583考虑到了cost,又没有考虑到区域的问题。如果有一种技术能把这两种选路规则结合起来,那肯定就是最完美的解决方案。其实协议开发者早就想到了这个问题,并且也确实设计了这种完美的解决方案,那就是RFC1583的兼容模式。

默认情况下,华为的设备启用OSPF后都工作在RFC1583兼容模式,此模式的特点为:当一台路由器收到能从不同的路径去往目标外部路由,会先比较路径的cost值,只有在cost值相同的情况下才会进一步比较区域号。如果cost值与区域号都相同,才会形成负载。

华为设备上面可以设置关闭RFC1583的兼容模式:命令为:undo rfc1583 compatible。关闭后将执行RFC2328的选路标准,在上述拓扑中,R2上就是执行了此条命令,所以才出现了环路。

场景五:OSPF在MPLS_v*n中的环路(DN位,Domain-tag)

要看明白此场景,需要各位对MPLS_v*n有一定的认识,MPLS_v*n作为数通的一个难点内容,学习起来确实有一定的难度,我这里尽量会使用一些通俗的语言去解释MPLS_v*n中的技术名词,因篇幅有限,所以不能非常详细的讲解MPLS_v*n中的技术,下次我会写一篇MPLS_v*n的专题,在文章中再详细的介绍相关技术。

对MPLS_v*n熟悉的人都知道,PE与CE之间可运行多种路由协议,如RIP、OSPF、ISIS、BGP并且静态路由也可以使用,在如此多的协议之间到底选择何种协议进行部署,是每个网络工程师都需要慎重考虑的问题,而在众多的协议之中,OSPF因为大众对它的熟悉,及在部署时有非常完善的防环特性而受到广泛的使用,所以我们这个场景就来讨论一下,在PE与CE之间运行OSPF所遇到的环路问题,及解决方法。
在这里插入图片描述

如上图所示:这是一个双PE的组网环境,整个网络已经提前配置好了MPLS_v*n的基础配置,两台PE的关键配置如下:
在这里插入图片描述

1、R3与R4连接的实例为site1,在site1里添加一条静态路由:ip route-static v*n-instance site1 30.30.30.30 255.255.255.255 NULL0 preference 200,下一跳指向Null0,优先级修改为200。此时路由表显示如下:

在这里插入图片描述

2、进入R3的BGP配置下,把30网段network进v*n-instance,配置如下:

bgp 10

ipv4-familyv*n-instance site1

network30.30.30.30 255.255.255.255

import-route ospf1

3、因为R3与R4建立了v*nv4邻居,所以此时30网段的v*nv4路由会传递给R4,在R4上经过路由交叉(mpls-v*n技术名词,简单说是把路由接收进实验路由表)后可以R4的实例路由表查看到此条路由,下一跳为10.1.3.3,通过IBGP学到。

在这里插入图片描述

4、进入R4的实例OSPF中,输入命令:import-route bgp permit-ibgp,默认情况下在PE设备上引入IBGP路由是不需要加入permit-ibgp,但此时我们的设备上配置了一条:v*n-instance-capability simple,此条命令会导致运行OSPF的PE设备丧失PE特性(具体命令细节稍后会介绍),因为在非PE设备上,import-route bgp只能引入ebgp路由(为了防环,有机会再给大家整理一篇BGP环路介绍),所以此处在引入时一定要加入permit-ibgp参数。命令如下:

在这里插入图片描述

5、因R4与R7建立了ospf邻居,所以此时在R7上查看路由表,可查看到R7已经学习到了一条30网段的路由,下一跳指向R4,并为ase路由。

在这里插入图片描述

6、因R7与R6建立了ospf邻居,继续前往R6上查看路由表,发现R6也学习到了一条30网段路由,下一跳指向R7:

在这里插入图片描述

7、因R6与R3建立了OSPF邻居,继续前往R3上查看site1实例路由表,可发现此时实例表中出现的一条ase的30网段路由,优先级为150。回顾第一步的路由表显示可知,此时R3会有两条去往30网段的路由,一条是通过OSPF学习到的优先级为150的ase路由,另外一条是第一步添加的优先为200的静态路由。所以此时R3会优先选择优先级小的ospf路由。
在这里插入图片描述

8、此时就需要了一个R3-R4-R7-R6-R3的路由环路,数据环路则是R3-R6-R7-R4-R1-R3

在这里插入图片描述

从以上分析可知,此环路形成的原因为R3使用了本来就属于R3发送出去的30网段路由,从而形成了环路,为了解决此种路由回灌的问题,OSPF协议开发者在开发协议时设计了两种防环机制:DN位与Route tag。

DN位位于ospf lsa头部的option中,主要用于mpls_v*n场景中3类,5类,7类Lsa的防环,OSPF规定当一条路由从PE发往CE时,LSA中的DN位就会被置位,当一条LSA的DN位被置位了,PE设备将会忽略此条LSA。在以上场景中R4通过v*nv4从R3学习到30网段路由,并且发送给CE-R7,此时DN位就会被置位,当30网段的这条lsa发送回给R3时,R3发现此LSA的DN被置位,所以不会使用此条LSA,从而避免了环路的产生。在上述场景中因为在PE上面配置了v*n-instance-capability simple命令,所以此时PE设备将忽略DN检测,也就导致了上述环路的产生。

Route tag同样位于ospf lsa里,但只存在于5类与7类lsa中,即Route tag只能用于5类与7类的防环。当PE给CE发送LSA时,会在5类与7类lsa中添加tag值,此tag值会以PE设备上BGP的AS号来计算,当此条填充的tag值的lsa传入对端PE时,PE设备会检测此tag中的AS号与本地的AS号是否一致,如一致则会忽略此lsa条目。在上述场景中PE上面配置的v*n-instance-capabilitysimple命令也同样会使PE设备忽略Route tag的检测,从而导致了上述的环路。

当PE与CE之间运行了ospf时,会自动启用这两种防环机制,默认情况下PE设备是会检测DN位与Route-tag的,也就是说默认情况下v*n-instance-capability simple命令并未使能,即默认情况就不会有环路产生。

v*n-instance-capabilitysimple命令详细介绍:

A、在PE上配置v*n-instance-capabilitysimple命令后,如果OSPF没有配置骨干区域0,则该MCE不会成为ABR。(关于此问题需要重新写文章才能详细介绍)

B、配置v*n-instance-capability simple命令后,OSPF进程不可以引入IBGP路由。(所以需要在引入时加入permit-ibgp参数)

C、配置v*n-instance-capability simple命令后,BGP引入的OSPF路由中不会携带OSPFDomain ID、OSPF Route-tag和OSPFRouter ID。(所以在CE上面看到的路由都是以ase的外部路由存在,关于OSPF的RT属性,也需要重新写文章才能详细介绍)

此外要在PE上面关闭DN位检测还可以用如下命令:

dn-bit-checkdisable summary 关闭3类lsa中的dn位检查

dn-bit-checkdisable ase 关闭5类lsa中的dn位检查

dn-bit-checkdisable nssa 关闭7类lsa中的dn位检查