路由选择信息协议(Routing Information Protocol,RIP)作为最早的距离矢量型 IP 路由选择协议依然被广泛使用着,当前存在着两个版本:RIPv1 和 RIPv2,后者对 RIPv1 的功能作了部分增强。RIPv1 和 RIPv2 最主要的区别是,RIPv1 是有类别路有选择协议,而 RIPv2 是无类别路由选择协议。
1982 年,伯克利发布的 UNIX 4.2BSD 版中,通过一个称为 routed 的守护进程实现了 RIP 协议。直到 1988 年才发布了一个 RIP 协议的标准,那时 RIP 已经被广泛使用。该标准就是 RFC1058,是 RIP 协议第 1 版的比较正式的标准。
RIP 协议虽然没有后来一些路由选择协议功能强大,但它简单易用,已被广泛的应用。在小型网络数据链路中,RIP 协议设计的相当单一。在这些限定条件下,尤其是 UNIX 环境下,RIP 协议依然是一个受欢迎的路由选择协议。
RIP 的基本原理与实现
- RIP 协议的处理是通过 UDP 520 端口来操作的,所有的 RIP 消息都被分装在 UDP 用户数据报协议中,源和目的端口字段的值都被设置为 520
- RIP 定义了两种消息类型:请求消息和响应消息。请求消息用来请求邻居路由器发送更新,响应消息用来传送路由更新。
- RIP 的度量是基于跳数的,1 跳表示是与发出通告的路由器直连的网络,16 跳表示网络不可达
- 开始时,RIP 从每个启用 RIP 协议的接口广播 RIP 请求消息,之后,RIP 程序进入一个循环状态,不断侦听来自其他路由器的 RIP 请求或响应消息。而接收到请求的邻居路由器则回送包含它们的路由表的响应消息
- 当发出请求的路由器收到响应消息时,它将开始处理附加在响应消息中的路由更新信息。如果路由更新中的路由条目是新的,路由器则将新的路由连同通告路由器的地址一起加入到自己的路由表中,这里通告路由器的地址可以从更新数据包的源地址字段读取。如果路由条目已经存在于路由表中,那么只有当路由更新通告拥有更小的跳数时才能替换原来已经存在的路由条目
- 如果路由更新通告的跳数大于路由表已记录的跳数,并且更新来自于已记录条目的下一跳路由器,那么该路由将在一个指定的抑制时间段(holddown period)内被标记为不可达。如果在抑制时间超时后,同一台邻居路由器仍然通告这个有较大的跳数的路由,路由器则接受该路由新的度量值
RIP 计时器和稳定性
路由器启动后,平均每隔 30s 从每个启动 RIP 协议的接口不断地发送响应消息。除了被水平分割法抑制的路由条目外,响应消息(或者称为更新消息)包含了路由器的整个路由表。这个周期性的更新由更新计时器进行初始化,并且包含一个随机变量用来防止表的同步。路由更新的目的地址是所有主机的广播地址。
RIP 也使用一些其他的计时器,之前讲过,距离矢量协议用无效计时器(invalidation timer)来限制停留在路由表中的路由的未被更新时间。RIP 称这个计时器为限时计时器(expiration timer)或超时计时器(timeout timer),Cisco IOS 中称为无效计时器。无论何时,当有一条新的路由被建立,超时计时器就会被初始化为 180s,每当收到这条路由的更新消息时,超时计时器又将被重置成计时器的初始值。如果一条路由的更新在 180s(6 个更新周期)内还没有收到,那么这条路由的跳数将变成 16,也就是标记成不可达的路由。
另一种计时器,称为垃圾收集(garbage collection)或刷新定时器(flush timer),它们所设置的时间长度一般比 无效计时器
的时间长,如果垃圾收集计时器也超时了,则该路由将被通告为一条度量值不可达的路由,同时从路由表中删除该路由。
第 3 个计时器是抑制计时器,虽然 RFC 1058 中没有抑制计时器的介绍,但是在 Cisco 路由器中运行的 RIP 协议使用了它们。如果一条路由更新的跳数大于路由表中已记录的该路由跳数(而且是经由同一个下一跳路由器),那么将会引起该路由进入长度 180s(6 个路由更新周期)的抑制状态计时器。
RIP 使用带毒性逆转的水平分割和触发更新。不像普通的定期更新,触发更新只要在有路由的度量值发生改变时就会发生,而且触发更新不会引起接收路由器重置他们的更新计时器。为了避免拓扑改变后造成触发更新风暴,还需要使用另外一个计时器。当一个触发更新传播时,这个计时器被随机地设置为 1-5s,在这个计时器超时前不能发送并发的触发更新。
一些主机可以在 静模式
下使用 RIP,所谓 静模式
主机不产生 RIP 的更新消息,而只侦听 RIP 的更新消息,从而更新它们自己的路由表。
RIP 消息格式
RIP 的消息格式如下,每条消息包含一条命令(Command)、一个版本号和路由条目(最大 25 跳)。每个路由条目包括地址组标识、路由可达的 IP 地址和路由的跳数。一个 RIP 更新消息最多包含 25 条路由条目,而每个路由条目占用 20 字节。RIP 消息头部占用 4 字节,而 RIP 消息封装在 UDP 报文中,因此 RIP 数据包的大小(不包含 IP 头部)最大为 512 字节(4 + 20 * 25 + 8 )。
- 命令:1 表示请求消息,2 表示响应消息。其他的取值都不被使用或保留用作私有用途
- 版本号:对于 RIPv1,该字段的值为 1
- 地址族标识:对于 IP 该项设置为 2。只有一个例外情况,该消息是对路由器(或主机)整个路由表的请求。
- IP 地址:路由的目的地址
- 度量:在 RIP 中指跳数,该字段的取值范围为 1-16 之间
请求消息类型
RIP 请求消息可以请求整个路由表信息,也可以仅请求某些具体路由的信息。对于前一种情况,请求消息含有一个地址族标识字段为 0(地址为 0.0.0.0),度量值为 16 的单条路由,接收到这个请求的设备将通过单播方式发出请求的地址会送它的整个路由表,并遵循一些规则如水平分割和边界汇总。
一些诊断测试过程可能需要知道某个或某些具体路由的信息。这种情况下,请求消息可以与特定地址的路由条目一起发送。接收到该请求的设备将根据请求消息逐个处理这些条目,构成一个响应消息。如果该设备的路由表中已经有请求消息中地址相对应的路由条目,则将路由条目的度量值填入 metric。如果没有,metric 字段就被设置为 16。在不考虑水平分割和边界汇总的情况下,响应消息将正确地告诉这台路由器了解的信息。
RFC 1508 指出,如果一台静主机收到一个来自其他 UDP 端口的请求消息,而不是来自标准的 RIP 520 端口,那么该主机就必须发送一个响应消息。
有类别路由选择
在路由表中,RIP 的管理距离为 120,而度量是基于跳数的。如果到达同一个目的网络有多条跳数相等的路由,那么 RIP 进行等价路径的负载均衡。
RIPv1 是有类别路由选择协议。当一个数据包进入 RIP 路由器后,路由器将执行路由表的查询,逐步排除数据包的路由选择范围,直到只剩下一条唯一的路径:
- 路由器首先读出目的地址的网络部分(基于有类别路有选择协议的主网络号),查看这个网络部分在路由表中是否有其匹配的条目
- 如果没有匹配的主网络,这个数据包就被丢弃,同时发出一个 ICMP 目的不可达的消息给发出该数据包的源
- 如果存在匹配该数据包网络部分的主网络,那么路由表会列出匹配这个主网络的子网,并进一步在这些子网中查询
- 如果能找到一个匹配的子网条目,那么该数据包将可以被路由器转发,否则该数据包被丢弃并发送一个 ICMP 目的不可达的消息
直连的子网络
如下显示的路由表包含了 RIP 得到的路由信息:
1 | MtPilate#show ip route |
需要注意,RIP 协议的消息中并没有随同路由条目一起通告子网掩码,从而路由器也没有和单独的子网相关联的掩码。所以假设当一个路由器收到一个目的地址为 172.25.131.23 的数据包,即使这个地址被完全子网化,路由器也没有确切的方法来识别子网位的结束位置和主机位的开始位置。路由器唯一可以假定的就是,整个网络中,对于同一个主网络地址使用相同的掩码。这个掩码就是配置在与网络 172.25.0.0 相连的某一台路由器接口之上的。在这个例子中,对于目的地址的主网络 172.25.0.0,路由器将使用自己接口上的掩码(172.25.0.0 连接在自己的接口上,所以得到主网络 172.25.0.0 的子网掩码为 255.255.255.0)。
在该 RIP 路由表中也可以看到,如果一个网络是和路由器直连的,那么路由器将在路由表中作为一个标题条目列出该网络和该网络所连接接口的子网掩码,然后列出它所知道的关于这个网络的所有子网。如果一个网络和路由器不是直连的,那么路由器仅仅列出这个网络的主网络而不列出与它相关联的掩码。
由于在有类别路由选择协议进行路由选择的情况下,数据包的目的地址是通过在路由器接口本地配置的子网掩码来识别的,所以在同一个主网络范围中的所有子网掩码应该是一致的。
在边界路由器上的路由汇总
当一台路由器没有一个接口和该目的地址对应的 A 类、B 类、C 类主网络相关,那么该路由器没有办法正确识别出所使用的子网掩码,也没有办法正确地标识该子网。解决办法很简单:如果路由器没有和目的网络直接连接,那么路由器仅仅需要一条简单的路由指向一个直接相连的路由器。
如下所示一台处于两个主网络边界上的路由器,这两个主网络分别是 A 类网络 10.0.0.0 和 C 类网络 192.168.115.0,这台边界路由器不会把其中任何一个主网络的子网的具体信息发送给另一个主网,相反,该路由器执行了自动路由汇总,或称为子网屏蔽,仅把地址 10.0.0.0 通告给网络 192.168.115.0,同样把地址 192.168.1150.0 通告给网络 10.0.0.0。
根据这种方式,在网络 192.168.115.0 内的路由器的路由表中,只包含一个单独的路由条目用来把到达目的网络 10.0.0.0 的数据包转发到边界路由器,而边界路由器则具有和网络 10.0.0.0 直连的接口,因此它具有一个带子网掩码的子网来为网络云内的数据包选路。
但是,当一个主网络被另一个不同的主网络分割成不连续的子网时,RIP、IGRP 等有类别路由选择协议会产生问题,不连续的子网在网络边界会被自动汇总。
小结
有类别路由选择协议的一个基本特征是,在通告目的地址时不能随之一起通告它的地址掩码。因此,有类别路由选择协议首先必须匹配一个与该目的地址对应的 A 类、B 类、C 类的主网络号。对于每一个通过这台路由器的数据包:
- 如果目的地址是一个和路由器相连的主网络的成员,那么该网络的路由器接口上配置的子网掩码将被用来确定目的地址的子网。因此,在该主网络中必须自始至终地统一使用这个相同的子网掩码
- 如果目的地址不是一个和路由器直接相连的主网络的成员,那么路由器将尝试去匹配该目的地址对应的 A 类、B 类、C 类主网络号
配置 RIP
在 Cisco IOS 中,RIP 协议的配置工作是一项比较简单的事情:
- 用一条命令启动 RIP 进程:router rip
- 用另一条命令来指定路由器中运行 RIP 协议的每一个网络:network XXXX
由于 RIP 协议具有有类别路由选择的特性,从而在网络边界上会出现子网屏蔽的情形,这意味着 network 命令中不需要指定子网,而仅仅需要指定相对应的 A 类、B 类 或 C 类的主网络地址。任何一个接口,只要它的配置地址属于 network 命令指定的网络,都将会运行 RIP 协议。
案例研究:被动接口
在如下所示的网络中:
假设不希望路由器 Floyd 和 Andy 之间交换 RIP 协议的通告消息,可以很容易地使用如下命令实现:
1 | router rip |
由于没有包含网络 192.168.12.0 的 network 命令语句,因此路由器 Floyd 不会在接口 192.168.12.66 上发送 RIP 通告。但是对于路由器 Andy,其有两个接口和网络 192.168.12.0 相连,因此网络 192.168.12.0 必须包含在 RIP 中。如果一台路由器接口处于一个启动 RIP 协议的网络的子网中,那么路由器就会在该接口上发出 RIP 广播,为了阻塞这样的 RIP 广播,在 RIP 的处理中就需要添加一条 passive-interface 命令。
路由器 Andy 的配置如下:
1 | router rip |
命令 passive-interface 不是 RIP 协议的专有命令,它可以在所有的 IP 路由选择协议中配置使用。使用该命令实际上可以说是在一条特定的数据链路上,将路由器作为一台静主机看待。它只是在该特定的链路上侦听 RIP 的广播,从而更新自己的路由表。如果希望避免路由器从一条链路上学到路由信息,就必须使用更复杂的路由更新控制才能实现,这种路由更新控制称为 出站更新过滤
。和 静主机
不同的是,路由器并不在被动接口上响应收到的请求消息。
案例研究:配置单播更新
在如下网络中,增加一台路由器 Bea,并连接到路由器 Andy 和 Floyd 之间的以太网共享链路上。在路由器 Andy 和 Floyd 之间的链路上依然保留不启动 RIP 协议的路由策略,但是在路由器 Bea 和 Andy 之间,Bea 和 Floyd 之间都必须交换 RIP 通告消息。
此时,可以在路由器 Andy 的 RIP 处理中增加一条额外的命令 neighbor,使 RIP 协议能够以单播方式向路由器 Bea 的接口发送通告,而此时,路由器 Andy 上的 passive-interface 命令仍继续防止在该链路上广播更新:
路由器 Andy 的配置如下:
1 | router rip |
而路由器 Floyd 现在必须发送 RIP 通告给路由器 Bea,因此也必须增加一条通告 192.168.12.0 的 network 命令,为了防止广播更新,也要增加一条 passive-interface 命令,并增加 neighbor 命令以单播方式通告 RIP 更新给路由器 Bea。Floyd 的配置如下:
1 | router rip |
案例研究:不连续的子网
考虑如下网络:
网络 10.0.0.0 的两个子网络 10.30.0.0/20 和子网络 10.30.32.0/20 分别和路由器 Barney 以及 Ernest_T 直连,这两者之间只有一条唯一的经过网络 192.168.83.0 和 192.168.12.0 的路由路径,而这两个网络并不属于主网络 10.0.0.0,因此网络 10.0.0.0 将变成不连续的。
此时造成的后果是:路由器 Barney 会认为自己是网络 10.0.0.0 和 网络 192.168.83.0 之间的边界路由器;同样地,路由器 Ernest_T 也会认为自己是网络 10.0.0.0 和 网络 192.168.12.0 之间的边界路由器。它们都将通告一条通往网络 10.0.0.0 的汇总路由。结果路由器 Andy 会认为它有两条等价的路径可以到达同一个网络。在这种情况下,路由器 Andy 将在与路由器 Barney 和 Ernest_T 相连的链路上进行负载聚均衡,因此,到达网络 10.0.0.0 的数据包只有一半的机会可以转发到正确的子网上。
像 RIP 和 IGRP 等有类别路由选择协议不能对这种类型的网络拓扑进行路由选择,因为其中网络 10.0.0.0 的子网被不同的主网络分开了。解决办法是在网络 192.168.83.0/24 和 192.168.12.192/27 所在的同一链路上配置网络 10.0.0.0 的子网,这可以通过在路由器接口上配置辅助 IP 地址(secondary IP 地址实现)。
由于路由选择进程会将辅助地址看做是单独的数据链路,所以在 RIP 协议或 IGRP 协议网络的设计中要很小心地用。各自的 RIP 更新会在每一个子网里进行广播,如果路由更新比较多而且物理链路的带宽有限,那么大量的路由更新会造成网络拥塞。
案例研究:控制 RIP 的度量
可以通过命令 off-list 来改变路由的度量,该命令指定一个数值来加大路由的度量值,并且参照一个访问列表(access list)来决定哪些路由条目需要修改。命令语法如下:
1 | off-list {access-list-number | name} {in | out} offset [type number] |
案例研究:最小化更新信息的影响
在具有很多子网的网络中,特别是对于一些较低带宽的链路,路由选择更新会对网络流量产生很大的影响。有两种方式可以使路由选择协议产生的流量最小化,从而降低 RIP 的路由选择的流量。
- 方法 1:调整路由选择协议的计时器以便降低更新的频率,但是这在主要链路发生故障时会引起较长的收敛时间
- 方法 2:配置触发扩展特性来消除周期性的 RIP 更新
在接口模式下的命令 ip rip triggered
可以启动 RIP 协议的触发扩展特性。在一条串行链路的两台路由器都必须确定配置了具有触发扩展特性的 RIP 协议后,路由表的更新将会变得最少,仅仅包括路由表最初的交换信息和路由表发生变化时的更新信息。这条命令仅在串行链路上有效,并且必须在串行链路的两端同时配置才会产生效果。
RIP 故障诊断
RIP 协议的故障诊断相对来说是比价简单的,对于 RIP 这样的有类别路由选择协议来说,最困难的排错就是出现子网掩码配置错误或子网不连续的情况。如果路由表包含了不准确的或被丢失的路由,那么就应该检查邻近的所有子网和所有子网掩码的一致性。