跳转至

第4章 网络层

第 4 章 网络层

本章讨论网络互连问题。在介绍网络层提供的两种服务和两个层面后,就进入本章的核心内容 —— 网际协议 IP,这是本书的一个重点内容。只有深入地掌握了协议 IP 的主要内容,才能理解互联网是怎样工作的。本章还要讨论网际控制报文协议 ICMP、几种常用的路由选择协议、IPv6 的主要特点、IP 多播的概念等。在讨论虚拟专用网 VPN 和网络地址转换 NAT 后,最后简单介绍多协议标签交换 MPLS 和软件定义网络 SDN 的基本概念。

本章最重要的内容是:

4.1 网络层的几个重要概念

4.1.1 网络层提供的两种服务

在计算机网络领域,网络层应该向运输层提供怎样的服务(“面向连接” 还是 “无连接”)曾引起了长期的争论。争论焦点的实质就是:在计算机通信中,可靠交付应当由谁来负责?是网络还是端系统?

有些人认为应当借助于电信网的成功经验,让网络负责可靠交付。大家知道,传统电信网的主要业务是提供电话服务。电信网使用昂贵的程控交换机(其软件也非常复杂),用面向连接的通信方式,使电信网络能够向用户(实际上就是电话机)提供可靠传输的服务。因此他们认为,计算机网络也应模仿打电话所使用的面向连接的通信方式。当两台计算机进行通信时,也应当先建立连接(但在分组交换中是建立一条虚电路 VC (Virtual Circuit) \(^{①}\) ),以预留双方通信所需的一切网络资源。然后双方就沿着已建立的虚电路发送分组。这样的分组的首部不需要填写完整的目的主机地址,而只需要填写这条虚电路的编号(一个不大的整数),因而减少了分组的开销。这种通信方式如果再使用可靠传输的网络协议,就可使所发送的分组无差错按序到达终点,当然也不丢失、不重复。在通信结束后要释放建立的虚电路。图 4-1 (a) 是网络提供虚电路服务的示意图。主机 \(H_{1}\)\(H_{2}\) 之间交换的分组都必须在事先建立的虚电路上传送。

但互联网的先驱者却提出一种崭新的网络设计思路。他们认为,电信网提供的端到端可靠传输的服务对传统的电话业务无疑是很合适的,因为那时电信网的终端(电话机)非常简单,没有智能,更没有差错处理能力。因此电信网必须负责把用户电话机话筒产生的话音信号可靠地传送到对方的电话机,使其耳机发出的声音符合话音质量的技术规范要求。但计算机网络的端系统是有智能的计算机。计算机有很强的差错处理能力(这点和传统的电话机有本质上的差别)。因此,互联网在设计上就采用了和电信网完全不同的思路。

互联网采用的设计思路是这样的:网络层要设计得尽量简单,向其上层只提供简单灵活的、无连接的、尽最大努力交付的数据报服务 \(^{①}\) 。这里的 “数据报”(datagram) 是互联网的设计者最初使用的名词,其实数据报(或 IP 数据报)就是我们经常使用的 “分组”。在本书中,IP 数据报和 IP 分组是同义词,可以混用。

网络在发送分组时不需要先建立连接。每一个分组(也就是 IP 数据报)独立发送,与其前后的分组无关(不进行编号)。网络层不提供服务质量的承诺。也就是说,所传送的分组可能出错、丢失、重复和失序(即不按序到达终点),当然也不保证分组交付的时限。由于传输网络不提供端到端的可靠传输服务,这就使网络中的路由器比较简单,且价格低廉(与电信网的交换机相比较)。如果主机(即端系统)进程之间需要进行可靠的通信,那么就由主机中的运输层负责(包括差错处理、流量控制等)。采用这种设计思路的好处是:网络造价大大降低,运行方式灵活,能够适应多种应用。互联网能够发展到今日的规模,充分证明了当初采用这种设计思路的正确性。

图 4-1 (b) 给出了网络提供数据报服务的示意图。主机 \(H_{1}\)\(H_{2}\) 发送的分组各自独立地查找路由器中的转发表,逐跳传送到目的主机。在分组传送的过程中有丢失的可能。

c2b229f3ac736a0c4e6324f07a30331a458b93e425f3be66d6e493ff9e23abae.jpg

a904cf49e42beaddfc7db23d1f9a1739dd8205791960e6da1ffee7d16b31fbdd.jpg

OSI 体系的支持者曾极力主张在网络层使用可靠传输的虚电路服务,也曾推出过网络层虚电路服务的著名标准 ——ITU-T 的 X.25 建议书。但现在 X.25 早已成为历史文献了。

表 4-1 归纳了虚电路服务与数据报服务的主要区别。

表 4-1 虚电路服务与数据报服务的对比

对比的方面虚电路服务数据报服务
思路可靠通信应当由网络来保证可靠通信应当由用户主机来保证
连接的建立必须有不需要
终点地址仅在连接建立阶段使用,每个分组使用短的虚电路号每个分组都有终点的完整地址,即IP地址
分组的转发属于同一条虚电路的分组均按照同一路由进行转发每个分组独立查找转发表进行转发
当节点出故障时所有通过出故障的节点的虚电路均不能工作出故障的节点可能会丢失分组,一些路由可能会发生变化
分组的顺序总是按发送顺序到达终点到达终点的顺序不一定按发送的顺序
端到端的差错处理和流量控制可以由网络负责,也可以由用户主机负责由用户主机负责

4.1.2 网络层的两个层面

在上面 4.1.1 节中,我们已经讲过,不同网络中的两个主机之间的通信,要经过若干个路由器转发分组来完成,分组查找路由器中的转发表,从指明的接口转发到下一个路由器。但转发表是怎样得出的呢?是从路由表导出的,而路由表又是由互联网中许多的路由器,按照共同选定的路由选择协议,通过许多次的相互交换路由信息而产生的。由此可见,在路由器之间传送的信息有以下两大类:

第一类是转发源主机和目的主机之间所传送的数据,把源主机所发送的分组,像接力赛跑那样从一个路由器转发到下一个路由器,最后把分组传送到目的主机。

第二类则是传送路由信息,是根据路由选择协议所使用的路由算法,彼此不断地交换路由信息分组,目的是为了在路由器中创建路由表,并由此导出为转发分组而用的转发表。这一类信息的传送是为第一类数据的传送服务的。

用图 4-2 的方法来描述,也就是把网络层抽象地划分为数据层面(或转发层面)和控制层面。这里所说的 “层面 (plane)” 和体系结构中的 “层次 (layer)” 很相似,都是抽象的概念。此处的 plane 目前国内尚无标准译名,也可以译为 “面”。曾有人译为 “平面”,但本书不采用这个译名,因为这容易联想到是几何学中的平面(其实与这种平面并无关联)。名词 “层面” 是目前文献中通用的抽象术语。在一个路由器实体中,显然无法看见这种抽象的层面。

1b6c9e380dc64a994891be71bf8ab7c308f72a27a1affe8424424158b23c90a8.jpg

这两个层面的机制相差很大。在数据层面中,每一个路由器根据本路由器生成的转发表,把收到的分组,从查找到的对应接口转发出去。为了加快转发的速率,现在的路由器通常都采用硬件进行转发,转发一个分组的时间为纳秒( \(10^{-9}\) 秒)数量级。但在控制层面中的情况则不同。一个路由器不可能独自创建出路由表。路由器必须和相邻的路由器经常交换路由信息,然后才能创建出本路由器的路由表。根据路由选择协议所用的路由算法计算路由要使用软件,这就慢多了,一般是秒的数量级。从以上所述不难看出,数据层面的问题比较单纯,因为路由器在转发分组时,是独立地根据本路由器的转发表转发分组的,但控制层面就比较复杂,因为路由器要创建路由表,就必须依靠许多路由器协同动作。不同的路由选择协议定义了不同的协同动作方式。路由器的生产厂家在制造路由器时,已经在路由器内部嵌入了路由选择的通信模块,使得路由器之间能够按照路由选择算法进行相互之间的通信。

从互联网诞生之日起,路由器就是按照图 4-2 所示的模式工作的。本教材过去的几个版本在讲解路由器的结构时,虽然没有使用控制层面和数据层面的概念,但已经把路由器划分为路由选择和分组转发两大部分。其实这两部分的位置就分别处在图 4-2 所示的控制层面和数据层面之中。现在介绍网络层中控制层面和数据层面的概念,是因为最近在网络界提出的软件定义网络 SDN (Software Defined Network) \(^{①}\) ,正在对这两个层面的结构进行了重大的改变。图 4-3 就是 SDN 提出的这两个层面的构成。

b605c2bdc6cf2c8f4c4c058ac2617931e1745b2b1a85e80c3ad17964233925d9.jpg

我们注意到,在传统的互联网中,每一个路由器中,既有转发表又有路由选择软件,因此在图 4-2 中所画的虚线长方形方框也强调了这个特点。也就是说,每个路由器中,既有数据层面也有控制层面。但在图 4-3 所示的 SDN 结构中,所有的路由器都变简单了。路由器中的路由选择软件都不存在了,因此路由器之间不再相互交换路由信息。在网络的控制层面有一个在逻辑上集中的远程控制器(但在物理上可以由不同地点的多个服务器组成)。远程控制器掌握各主机和整个网络的状态,能够为每一个分组计算出最佳的路由,然后在每一个路由器中生成其正确的转发表。路由器的工作很单纯,即收到分组,查找转发表,转发分组

这样,网络又变成为集中控制的。本来互联网是分散控制的,为什么现在又提出集中控制呢?其实,软件定义网络 SDN 的提出,并非现在要把整个互联网都改造为如图 4-3 所示的集中控制模式,这是不现实的。然而在某些具体条件下,特别是像一些大型的专用数据中心之间的广域网,若使用 SDN 模式来建造,就可以使网络运行的效率提高,同时还可以获得更好的经济效益。因此,建议读者关注这一新动向。在本书 4.10 节将简要介绍 SDN。

下面我们仍然按照传统互联网的机制,陆续介绍属于数据层面的协议 IP,然后再讨论

属于控制层面的各种路由选择协议。

4.2 网际协议 IP

网际协议 IP (Internet Protocol) 是 TCP/IP 体系中两个最主要的协议之一 [STE V94] [COME06][FORO10],也是最重要的互联网标准协议之一 [RFC 791, STD5]。网际协议 IP 又称为 Kahn-Cerf 协议,因为这个重要协议正是 Robert Kahn 和 Vint Cerf 二人共同研发的。这两位学者在 2004 年获得图灵奖(其地位相当于计算机科学领域的 “诺贝尔奖”)。严格来说,这里所讲的 IP 其实是 IP 的第 4 个版本,记为 IPv4。但在讲述协议 IP 的各种原理时,常省略 IP 后面的版本号。在后面的 4.5 节我们再介绍较新的版本 IPv6(版本 1~3 和版本 5 都未曾使用过。顺便指出,所谓的 IPv9 只不过是某些人故意的炒作而已,不值一提)。

与协议 IP 配套使用的还有三个协议:

本来还有一个协议叫作逆地址解析协议 RARP (Reverse Address Resolution Protocol),是和协议 ARP 配合使用的,但现在已被淘汰不使用了。

图 4-4 画出了这三个协议和网际协议 IP 的关系。在这一层中,ARP 画在最下面 \(^{①}\) ,因为 IP 经常要使用这个协议。ICMP 和 IGMP 画在这一层的上部,因为它们要使用协议 IP。这三个协议将在后面陆续介绍。由于网际协议 IP 是用来使互连起来的许多计算机网络能够进行通信的,因此 TCP/IP 体系中的网络层常常被称为网际层 (internet layer),或 IP 层。使用 “网际层” 这个名词的好处是强调了这是由很多网络构成的互连网络。目前比较普遍使用 “网络层” 这个名词。

5456a4af26134ca764a126522f0d6f28d6d84eef92de9db86667b15212218b61.jpg

在讨论网际协议 IP 之前,必须了解什么是虚拟互连网络。

4.2.1 虚拟互连网络

我们知道,如果要在全世界范围内把数以百万计的网络都互连起来,并且能够互相通信,那么这样的任务一定非常复杂。其中会遇到许多需要解决的问题,如:

能不能让大家都使用相同的网络,这样可使网络互连变得比较简单。答案是不行的。因为用户的需求是多种多样的,没有一种单一的网络能够适应所有用户的需求。另外,网络技术是不断发展的,网络的制造厂家也要经常推出新的网络,在竞争中求生存。因此客观讲在市场上总是有很多种不同性能、不同网络协议的网络,供不同的用户选用。

从一般的概念来讲,将网络互相连接起来要使用一些中间设备。根据中间设备所在的层次,可以有以下四种不同的中间设备:

当中间设备是转发器或网桥时,这仅仅是把一个网络扩大了,而从网络层的角度看,这仍然是一个网络,一般并不称之为网络互连。网关由于比较复杂,目前使用得较少。因此现在我们讨论网络互连时,都是指用路由器进行网络互连和路由选择。路由器其实就是一台专用计算机,用来在互联网中进行路由选择。由于历史的原因,许多有关 TCP/IP 的文献曾经把网络层使用的路由器称为网关(本书有时也这样用),对此请读者加以注意。

图 4-5 (a) 表示有许多计算机网络通过一些路由器进行互连。由于参加互连的计算机网络都使用相同的网际协议 IP (Internet Protocol),因此可以把互连以后的计算机网络看成为如图 4-5 (b) 所示的一个虚拟互连网络 (internet)。所谓虚拟互连网络也就是逻辑互连网络,它的意思就是互连起来的各种物理网络的异构性本来是客观存在的,但是我们利用协议 IP 就可以使这些性能各异的网络在网络层上看起来好像是一个统一的网络。这种使用协议 IP 的虚拟互连网络可简称为 IP 网(IP 网是虚拟的,但平常不必每次都强调 “虚拟” 二字)。使用 IP 网的好处是:当 IP 网上的主机进行通信时,就好像在一个单个网络上通信一样,它们看不见互连的各网络的具体异构细节(如具体的编址方案、路由选择协议,等等)。如果在这种覆盖全球的 IP 网的上层使用 TCP 协议,那么就是现在的互联网 (Internet)。

279c92d891324282053342118f91945403e289b099df5560fefa196de0e5ac4f.jpg

d3a47c570c37f24df73d09d1e8b03f7c31561987c98c5663a16a8af31fec9c29.jpg

当很多异构网络通过路由器互连起来时,如果所有的网络都使用相同的协议 IP,那么在网络层讨论问题就显得很方便。现在用一个例子来说明。

在图 4-6 所示的互联网中的源主机 \(H_{1}\) 要把一个 IP 数据报发送给目的主机 \(H_{2}\) 。根据第 1 章中讲过的分组交换的存储转发概念,主机 \(H_{1}\) 先要查找自己的转发表,看目的主机 \(H_{2}\) 是否就在本网络上。如是,则不需要经过任何路由器而是直接交付,任务就完成了。如不是,则必须把 IP 数据报发送给某个路由器(图中的 \(R_{1}\) )。 \(R_{1}\) 在查找了自己的转发表后,知道应当把数据报转发给 \(R_{2}\) 进行间接交付。这样一直转发下去,最后由路由器 \(R_{5}\) 知道自己是和 \(H_{2}\) 连接在同一个网络上,不需要再使用别的路由器转发了,于是就把数据报直接交付目的主机 \(H_{2}\) 。总之,分组从源节点 A 发送到目的节点 B,若中间必须经过一个或几个路由器(这表示 A 和 B 不在同一个网络上),则是间接交付。但若不需要经过路由器(这表示 A 和 B 在同一个网络上),则是直接交付。

a6cac94ba37242e75ca2c44e52433519e49851f118d4ff09751c56a3937450b3.jpg

在图中画出了源主机、目的主机以及各路由器的协议栈。我们注意到,主机的协议栈共有五层,但路由器的协议栈只有下三层。图中还画出了数据在各协议栈中流动的方向(用黑色粗线表示)。我们还可注意到,在 \(R_{4}\)\(R_{5}\) 之间使用了卫星链路,而 \(R_{5}\) 所连接的是个无线局域网( \(R_{5}\) 和主机 \(H_{2}\) 都在同一个局域网中)。在 \(R_{1}\)\(R_{4}\) 之间的三个网络则可以是任意类型的网络。总之,这里强调的是:互联网可以由多种异构网络互连组成。

有时可以把问题简化。我们可以想象 IP 数据报就在网络层中传送,传输路径可省略路由器之间的网络以及连接在这些网络上的许多无关主机。图 4-7 表示了这样的传输路径。

c93bf75fde0a5f975cb09632f12827cf4050b5b5b831200d47579e1b343038c2.jpg

在互联网的词汇中,分组在传送途中的每一次转发都称为一 “跳 (hop)”。也有人把 hop 译为跃点。路由器在转发分组时也常常使用 “下一跳 (next hop)” 的说法。例如, \(\mathbb{R}_1\) 的下一跳是 \(\mathbb{R}_2\) ,而 \(\mathbb{R}_4\) 的下一跳是 \(\mathbb{R}_5\) 。对于本例, \(\mathrm{H}_{1}\)\(\mathrm{H}_{2}\) 发送分组需要经过 6 跳。我们还注意到,每一跳两端的两个节点都必定直接连接在同一个网络上。例如,在图 4-7 中从 \(\mathbb{R}_2\)\(\mathbb{R}_3\) 的一跳,其两端的两个节点 \(\mathbb{R}_2\)\(\mathbb{R}_3\) 都是连接在同一个网络上的。在上面所举的例子中,前 5 跳都是间接交付,只有最后一跳是直接交付。

4.2.2 IP 地址

在 TCP/IP 体系中,IP 地址是一个最基本的概念。一个连接在互联网上的设备,如果没有 IP 地址,就无法和网上的其他设备进行通信。因此应当首先学好有关 IP 地址的内容。

1. IP 地址及其表示方法

整个的互联网就是一个单一的、抽象的网络。IP 地址就是给连接到互联网上的每一台主机(或路由器)的每一个接口,分配一个在全世界范围内是唯一的 32 位的标识符。IP 地址的结构使我们可以在互联网上很方便地进行寻址。IP 地址现在由互联网名字和数字分配机构 ICANN (Internet Corporation for Assigned Names and Numbers) 进行分配 \(^{①}\)

对主机或路由器来说,IP 地址都是 32 位的二进制代码。为了提高可读性,我们常常把 32 位的 IP 地址中的每隔 8 位插入一个空格(但在机器中并没有这样的空格)。为了便于人们书写和记忆,常用其等效的十进制数字表示,并且在每段数字之间加上一个小数点。这就叫作点分十进制记法 (dotted decimal notation)。图 4-8 是一个 IP 地址表示方法的例子。显然,把 IP 地址用 4 段十进制数字来表示是个很好的方法。

957ac1477cd42be07ca0e21b904dd3067351889bc74804ad0f97c3fbaf77c393.jpg

前面所讲的给每个主机(或路由器)的接口分配一个 IP 地址,其含义就是这个 IP 地址不但标志了这个主机(或路由器),而且还标志了此接口所连接的网络。因此,32 位的 IP 地址采用两级结构,由两个字段组成。第一个字段是网络号,它标志主机(或路由器)所连接到的网络。一个网络号在整个互联网范围内必须是唯一的。第二个字段是主机号,它标志该主机(对路由器来说,就是标志该路由器)。一个主机号在所连接的网络(即前面的网络号所指明的网络)中必须是唯一的。由此可见,一个 IP 地址在整个互联网范围内是唯一的。因此,IP 地址可以记为:

\[ \text { IP 地址 } \quad : := \{\langle \text { 网络号 } >, \langle \text { 主机号 } > \} \tag {4-1} \]

式 (4-1) 中的符号 “::=” 表示 “定义为”。IP 地址中包含网络号就表明,不连网的主机就没有 IP 地址。一定要记住,IP 地址指明了连接到某个网络上的一个主机(或路由器)。为简单起见,当不涉及路由器时,后面我们都以主机为例来介绍 IP 地址。

图 4-9 表示 IP 地址中的网络号和主机号的位置。具体的规定是:IP 地址中的前 n 位是主机所连接的网络号,而 IP 地址中后面的 \((32 - n)\) 位是主机号。现在的问题是,当我们看到一个 IP 地址时,怎样知道它的网络号的位数 n 是多少?下面我们就来讨论这个问题。

953db2e6651338aaf65d14fc7847326690ee80339189230f915a87f4f746efb9.jpg

2. 分类的 IP 地址

在互联网发展早期采用的是分类的 IP 地址,也就是在图 4-9 中的 n 是固定的几个数之一。分类的方法如图 4-10 (a) 所示。分类的方法非常简单。这里 A 类 \((n = 8)\) 、B 类 \((n = 16)\) 和 C 类 \((n = 24)\) 地址都是单播地址(一对一通信),是最常用的。D 类是多播地址(一对多通信,我们将在 4.7 节讨论 IP 多播),而 E 类是保留地址。

32 位的 IP 地址空间共有 \(2^{32}\) (即 4294967296,接近 43 亿)个地址。A 类地址空间共有 \(2^{31}\) 个地址,占整个 IP 地址空间的 50%。B 类地址空间共有 \(2^{30}\) 个地址,占整个 IP 地址空间的 25%。整个 C 类地址空间共有 \(2^{29}\) 个地址,占整个 IP 地址的 12.5%。D 类和 E 类地址各占整个 IP 地址的 6.25%。图 4-10 (b) 给出了各类地址占 IP 地址总数的比例。

从图 4-10 (a) 可以看出,如果给出一个二进制数表示的 IP 单播地址,那么就可以很容易知道是哪类地址,并且也能看出这个二进制数表示的网络号和主机号。

例如,给出一个 IP 地址 10000000 00001110 00100011 00000111。对比一下图 4-10 (a),不难看出,这是一个 B 类地址,前 16 位是网络号,后 16 位是主机号。

e1db31e948ab12ab767b6341d0ea8702943114ff811278191dfa1cfc5f02d5fa.jpg

A 类地址的网络号字段占 1 个字节,只有 7 位可供使用(该字段的第一位已固定为 0)。但要注意,第一,网络号为全 0 的 IP 地址有特殊的用途,它表示 “本网络”;第二,网络号为 127(即 01111111)保留作为本地软件环回测试 (loopback test) 本主机的进程之间的通信之用。若主机发送一个目的地址为环回地址(例如 127.0.0.1)的 IP 数据报,则本主机中的协议软件就处理数据报中的数据,而不会把数据报发送到任何网络。因此 A 类地址可指派的网络号是 126 个(即 \(2^{7}-2\) )。

本书的前几个版本曾提到,B 类地址中的网络地址 128.0.0.0 和 C 类地址中的网络地址 192.0.0.0 都是规定不指派的。但现在这两个网络地址都已经可以指派了 [RFC 6890]。

表 4-2 给出了一般不指派的特殊 IP 地址,这些地址只能在特定的情况下使用。

表 4-2 一般不指派的特殊 IP 地址

网络号主机号源地址使用目的地址使用代表的意思
00可以不可在本网络上的本主机(见6.6节DHCP协议)
0X可以不可在本网络上主机号为X的主机
全1全1不可可以只在本网络上进行广播(各路由器均不转发)
Y全1不可可以对网络号为Y的网络上的所有主机进行广播
127非全0或全1的任何数可以可以用于本地软件环回测试

这里要指出,由于近年来已经广泛使用无分类 IP 地址进行路由选择,A 类、B 类和 C 类这种分类地址已成为历史 [RFC 1812]。由于很多文献和资料现在都仍然引用传统的分类的 IP 地址,因此我们对分类的 IP 地址还要进行简单的叙述。

把 IP 地址划分为 A 类、B 类、C 类三个类别,当初是这样考虑的:各种网络的差异很大,有的网络拥有很多主机,而有的网络上的主机则很少。把 IP 地址划分为 A 类、B 类和 C 类是为了更好地满足不同用户的需求。

这种分类的 IP 地址由于网络号的位数是固定的,因此管理简单、使用方便、转发分组迅速,完全可以满足当时互联网在美国的科研需求。后来,为了更加灵活地使用 IP 地址,出现了划分子网的方法,在 IP 地址的主机号中,插入一个子网号,把两级的 IP 地址变为三级的 IP 地址。但是,谁也没有预料到,互联网在 20 世纪 90 年代突然迅速地发展起来了。互联网从美国专用的科研实验网演变到世界范围开放的商用网!互联网用户的猛增,使得 IP 地址的数量面临枯竭的危险。这时,人们才注意到原来分类的 IP 地址在设计上确实有很不合理的地方。例如,一个 A 类网络地址块的主机号数目超过了 1677 万个!当初美国的很多大学都可以分配到一个 A 类网络地址块。一个大学怎么会需要这样多的 IP 地址?但在互联网出现早期,人们就是认为 IP 地址是用不完的,不需要精打细算地分配。又如,一个 C 类网络地址块可指派的主机号只有 254 个。但不少单位需要有 300 个以上的 IP 地址,那么干脆申请一个 B 类网络地址块(可以指派的主机号有 65534 个),宁可多要些 IP 地址,把多余的地址保留以后慢慢用。这样就浪费了不少的地址资源。即使后来采用了划分子网的方法,也无法解决 IP 地址枯竭的问题

于是,在 20 世纪 90 年代,当发现 IP 地址在不久后将会枯竭时,一种新的无分类编址方法就问世了。这种方法虽然也无法解决 IP 地址枯竭的问题,但可以推迟 IP 地址用尽的日子。下一节就介绍现在已普遍采用的这种编址方法。

3. 无分类编址 CIDR

这种编址方法的全名是无分类域间路由选择 CIDR (Classless Inter-Domain Routing, CIDR 的读音是 “sider”) [RFC 4632], 其要点有以下三个。

(1) 网络前缀

CIDR 把图 4-9 中的网络号改称为 “网络前缀” (network-prefix)(或简称为 “前缀”),用来指明网络,剩下的后面部分仍然是主机号,用来指明主机。在有些文献中也把主机号字段称为后缀 (suffix)。CIDR 的记法是:

\[ \text { IP 地址 } \quad : := \{< \text { 网络前缀 } >, < \text { 主机号 } > \} \tag {4-2} \]

图 4-11 说明了 CIDR 的网络前缀和主机号的位置。看起来,这和图 4-9 也没有什么不同,只是把 “网络号” 换成为 “网络前缀”。其实不然。这里最大的区别就是网络前缀的位数 n 不是固定的数,而是可以在 0\~32 之间选取任意的值。

467241d25fbddd3c0f06865d1caaa171041a4120115cd0b94f193924254b88db.jpg

CIDR 使用 “斜线记法” (slash notation),或称为 CIDR 记法,即在 IP 地址后面加上斜线 “/”,斜线后面是网络前缀所占的位数。例如,CIDR 表示的一个 IP 地址 128.14.35.7/20,二进制 IP 地址的前 20 位是网络前缀(相当于原来的网络号),剩下后面 12 位是主机号。

(2) 地址块

CIDR 把网络前缀都相同的所有连续的 IP 地址组成一个 “CIDR 地址块”。一个 CIDR 地址块包含的 IP 地址数目,取决于网络前缀的位数。我们只要知道 CIDR 地址块中的任何一个地址,就可以知道这个地址块的起始地址(即最小地址)和最大地址,以及地址块中的地址数。例如,已知 IP 地址 128.14.35.7/20 是某 CIDR 地址块中的一个地址,现在把它写成二进制表示形式,其中的前 20 位是网络前缀(用粗体和下划线表示出),而前缀后面的 12 位是主机号:

\[ 1 2 8. 1 4. 3 5. 7 / 2 0 = \underline {{\textbf {1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0}}} \textbf {0 0 1 1} \textbf {0 0 0 0 0 1 1 1} \]

可以很方便地得出这个地址所在的地址块中的最小地址和最大地址:

最小地址128.14.32.010000000 00001110 00100000 00000000
最大地址128.14.47.25510000000 00001110 00101111 11111111

这个地址块的 IP 地址共有 \(2^{12}\) 个,扣除主机号为全 0 和全 1 的地址(最小地址和最大地址)后,可指派的地址数是 \(2^{12}-2\) 个。我们常使用地址块中的最小地址和网络前缀的位数指明一个地址块(不必每次都减 2 算出可指派的地址数,这样做太麻烦)。显然,上面导出的最小地址并不是该地址块 128.14.32.0/20 的网络地址。

也可以用二进制代码简要地表示此地址块:10000000 00001110 0010*。这里的星号 * 代表了主机号字段的所有的 0。星号前的二进制代码的个数,就是网络前缀的位数。

在不需要指明网络地址时,也可把这样的地址块简称为 “/20 地址块”。

请读者注意:

128.14.32.7 是 IP 地址,但未指明网络前缀长度,因此不知道网络地址是什么。

128.14.32.7/20 也是 IP 地址,但同时指明了网络前缀为 20 位,由此可导出网络地址。

128.14.32.0/20 是包含多个 IP 地址的地址块或网络前缀,或更简单些,就称为前缀,同时也是这个地址块中主机号为全 0 的地址。请注意,上面地址块中 4 段十进制数字最后的 0 有时可以省略,即简写为 128.14.32/20。

我们不能仅用 128.14.32.0 来指明一个网络地址,因为无法知道网络前缀是多少。例如 128.14.32.0/19 或 128.14.32.0/21,也都是有效的网络地址。128.14.32.0 也可能是一个可以指派的 IP 地址(如果网络前缀的位数不超过 18)。

早期使用分类的 IP 地址时,A 类网络的前缀是 8 位,B 类网络的前缀是 16 位,而 C 类网络的前缀是 24 位,都是固定值,因此不需要重复指明其网络前缀。例如在使用分类地址时,一看 15.3.4.5 就知道是个 A 类地址,其网络地址为 15.0.0.0。但在使用 CIDR 记法时,15.3.4.5/30 则是一个很小的地址块 15.3.4.4/30 中的、不属于任何类别的一个 IP 地址。

总之,无分类编址 CIDR 具有很多优点,但一定要记住,采用 CIDR 后,仅从斜线左边的 IP 地址已无法知道其网络地址了。在这一点上,原来的分类地址还是比较方便的。

(3) 地址掩码

CIDR 使用斜线记法可以让我们知道网络前缀的数值。但是计算机看不见斜线记法,而是使用二进制来进行各种计算时就必须使用 32 位的地址掩码 (address mask) 能够从 IP 地址迅速算出网络地址。

地址掩码(常简称为掩码)由一连串 1 和接着的一连串 0 组成,而 1 的个数就是网络前缀的长度。地址掩码又称为子网掩码 \(^{①}\) 。在 CIDR 记法中,斜线后面的数字就是地址掩码中 1 的个数。例如,/20 地址块的地址掩码是:11111111 11111111 11110000 00000000(20 个连续的 1 和接着的 12 个连续的 0)。这个掩码用 CIDR 记法表示就是 255.255.240.0/20。

对于早期使用的分类 IP 地址,其地址掩码是固定的,常常不用专门指出。例如:

A 类网络,地址掩码为 255.0.0.0 或 255.0.0.0/8。

B 类网络,地址掩码为 255.255.0.0 或 255.255.0.0/16。

C 类网络,地址掩码为 255.255.255.0 或 255.255.255.0/24。

把二进制的 IP 地址和地址掩码进行按位 AND 运算,即可得出网络地址。图 4-12 说明了 AND 运算的过程。AND 运算就是逻辑乘法运算,其规则是:1 AND 1 = 1, 1 AND 0 = 0, 0 AND 0 = 0。点分十进制的 IP 地址是 128.14.35.7/20,前缀长度是 20(见图中的灰色背景)。请注意,从点分十进制的 IP 地址并不容易看出其网络地址。要使用二进制地址来运算。在本例中把二进制 IP 地址的前 20 位保留不变,剩下的 12 位全写为 0,即可得出网络地址。

79faa9c00346c501cca5cc5fb95cd16f6e7945c6f5bf318287238734dd0ca4c4.jpg

从上面的运算结果可以知道,IP 地址 128.14.35.7/20 所在的网络地址是 128.14.32.0/20。

表 4-3 给出了最常用的 CIDR 地址块。表中的 K 表示 \(2^{10}\) 即 1024。网络前缀长度在 13 到 27 之间是最常用的。在 “包含的地址数” 中把全 1 和全 0 的主机号都计算在内了。

表 4-3 常用的 CIDR 地址块

网络前缀长度点分十进制包含的地址数相当于包含分类的网络数
/13255.248.0.0512 K8个B类或2048个C类
/14255.252.0.0256 K4个B类或1024个C类
/15255.254.0.0128 K2个B类或512个C类
/16255.255.0.064 K1个B类或256个C类
/17255.255.128.032 K128个C类
/18255.255.192.016 K64个C类
/19255.255.224.08 K32个C类
/20255.255.240.04 K16个C类
/21255.255.248.02 K8个C类
/22255.255.252.01 K4个C类
/23255.255.254.05122个C类
/24255.255.255.02561个C类
/25255.255.255.1281281/2个C类
/26255.255.255.192641/4个C类
/27255.255.255.224321/8个C类

CIDR 地址中还有三个特殊地址块,即:

从表 4-3 可看出,每一个 CIDR 地址块中的地址数一定是 2 的整数次幂。除最后几行外,CIDR 地址块都包含了多个 C 类地址(是一个 C 类地址的 \(2^{n}\) 倍,n 是整数),因此在文献中有时称 CIDR 编址为 “构造超网”。

使用 CIDR 的一个好处就是可以更加有效地分配 IP 地址空间,可根据客户的需要分配适当大小的 CIDR 地址块。然而在使用分类地址时,向一个部门分配 IP 地址,就只能以 /8, /16 或 /24 为单位来分配。这显然是很不灵活的。

一个大的 CIDR 地址块中往往包含很多小地址块,所以在路由器的转发表中就利用较大的一个 CIDR 地址块来代替许多较小的地址块。这种方法称为路由聚合 (route aggregation),它使得转发表中只用一个项目就可以表示原来传统分类地址的很多个(例如上千个)路由项目,因而大大压缩了转发表所占的空间,减少了查找转发表所需的时间。

图 4-13 给出的是 CIDR 地址块灵活分配的例子。假定某 ISP 已拥有地址块 206.0.64.0/18(相当于有 64 个 C 类网络)。现在某大学需要 800 个 IP 地址。ISP 可以给该大学分配一个地址块 206.0.68.0/22,它包括 1024(即 \(2^{10}\) )个 IP 地址,相当于 4 个连续的 C 类 / 24 地址块,占该 ISP 拥有的地址空间的 1/16。这个大学可灵活地对本校各系继续分配地址块,而各系还可再划分本系各教研室的小地址块。CIDR 的地址块的地址范围有时不易看清,这是因为网络前缀和主机号的界限不是恰好出现在整数字节处。但只要写出地址的二进制表示,弄清网络前缀的位数,就能够知道地址块的范围。

图 4-13 表示这个 ISP 共拥有 64 个 C 类网络。如果不采用 CIDR 技术,则在与该 ISP 的路由器交换路由信息的每一个路由器的转发表中,就需要有 64 行,每一行指出了到哪一个网络的下一跳。但采用地址聚合后,在转发表中只需要用一行来指出到 206.0.64.0/18 地址块的下一跳。这个大学共有 4 个系。在 ISP 内的路由器的转发表中,也仅需用 206.0.68.0/22 这一个项目,就能把外部发送到这个大学各系的所有分组,都转发到大学的路由器。这个路由器好比是大学的收发室。凡寄给大学任何一个系的邮件,邮递员都不必送到大学的各个系,而是把这些邮件集中投递到大学的收发室,然后由大学的收发室再进行下一步的分发。这样就加快了邮递员的投递工作(相当于缩短了转发表的查找时间)。

从图 4-13 的表格中可看出,网络前缀越短的地址块所包含的地址数就越多。

99b4473b15074e026829c5554a65ee3297b5a02b8b8fc904c1ddc369140f9edd.jpg

单位地址块二进制表示的地址块相当于C类网络数
ISP206.0.64.0/1811001110 00000000 01*64
大学206.0.68.0/2211001110 00000000 010001*4
一系206.0.68.0/2311001110 00000000 0100010*2
二系206.0.70.0/2411001110 00000000 01000110 *1
三系206.0.71.0/2511001110 00000000 01000111 0*1/2
四系206.0.71.128/2511001110 00000000 01000111 1*1/2

图 4-13 CIDR 地址块划分举例

4. IP 地址的特点

IP 地址具有以下一些重要特点。

图 4-14 画出了三个局域网( \(LAN_{1}\)\(LAN_{2}\)\(LAN_{3}\) )通过三个路由器( \(R_{1}\)\(R_{2}\)\(R_{3}\) )互连构成的一个互连网络。其中局域网 \(LAN_{2}\) 是由两个网段通过以太网交换机互连的。图中的小圆圈表示需要有一个 IP 地址。这是为了强调,IP 地址是标志一个主机连接在网络上的接口。如果我们把某条连接线断开,那么相应的 IP 地址也就不存在了。但通常为了方便,这

样的小圆圈可以不必画出。

b6b6a52ae50480d62081d19e263f1a914a6b36122976f965c21fede1886eba26.jpg

我们应当注意到:

4.2.3 IP 地址与 MAC 地址

在学习 IP 地址时,很重要的一点就是要弄懂主机的 IP 地址与 MAC 地址的区别。在局域网中,由于 MAC 地址已固化在网卡上的 ROM 中,因此常常将 MAC 地址称为硬件地址或物理地址。在本书中,物理地址、硬件地址和 MAC 地址常常作为同义词出现。物理地址的反义词就是虚拟地址、软件地址或逻辑地址,IP 地址就属于这类地址。

图 4-15 说明了这两种地址的区别。从层次的角度看,MAC 地址是数据链路层使用的地址,而 IP 地址是网络层和以上各层使用的地址,是一种逻辑地址(称 IP 地址为逻辑地址是因为 IP 地址是用软件实现的)。

c5d1761abbe339c38648fc9116c1d7cc54de88915ba887f8c8c174bfed6839cd.jpg

在发送数据时,数据从高层下到低层,然后才到通信链路上传输。使用 IP 地址的 IP 数据报一旦交给数据链路层,就被封装成 MAC 帧。MAC 帧在传送时使用的源地址和目的地址都是 MAC 地址,这两个 MAC 地址都写在 MAC 帧的首部中。

连接在通信链路上的设备(主机或路由器)在收到 MAC 帧时,根据 MAC 帧首部中的 MAC 地址决定收下或丢弃。只有在剥去 MAC 帧的首部和尾部后把 MAC 层的数据上交给网络层后,网络层才能在 IP 数据报的首部中找到源 IP 地址和目的 IP 地址。

总之,IP 地址放在 IP 数据报的首部,而 MAC 地址则放在 MAC 帧的首部。在网络层和网络层以上使用的是 IP 地址,而数据链路层及以下使用的是 MAC 地址。在图 4-15 中,当 IP 数据报插入到数据链路层的 MAC 帧以后,整个的 IP 数据报就成为 MAC 帧的数据,因而在数据链路层看不见数据报的 IP 地址。

图 4-16 (a) 画的是三个局域网用两个路由器 \(R_{1}\)\(R_{2}\) 互连起来。现在主机 \(H_{1}\) 要和主机 \(H_{2}\) 通信。这两台主机的 IP 地址分别是 \(IP_{1}\)\(IP_{2}\) ,而它们的 MAC 地址分别为 \(MAC_{1}\)\(MAC_{2}\) 。通信的路径是: \(H_{1} \rightarrow\) 经过 \(R_{1}\) 转发 → 再经过 \(R_{2}\) 转发 → \(H_{2}\) 。路由器 \(R_{1}\) 因同时连接到两个局域网上,因此它有两个 MAC 地址,即 \(MAC_{3}\)\(MAC_{4}\) 。同理,路由器 \(R_{2}\) 也有两个 MAC 地址 \(MAC_{5}\)\(MAC_{6}\)

图 4-16 (b) 特别强调了 IP 地址与 MAC 地址所使用的位置的不同。表 4-4 归纳了这种区别。

表 4-4 图 4-16 (b) 中不同层次、不同区间的源地址和目的地址

在网络层写入IP数据报首部的地址在数据链路层写入MAC帧首部的地址
源地址目的地址源地址目的地址
从 $H_1$ 到 $R_1$ $IP_1$ $IP_2$ $MAC_1$ $MAC_3$
从 $R_1$ 到 $R_2$ $IP_1$ $IP_2$ $MAC_4$ $MAC_5$
从 $R_2$ 到 $H_2$ $IP_1$ $IP_2$ $MAC_6$ $MAC_2$

871f5fda03b7aaecc65864743da6f7c0151ec636a31a9c9adbd64442aabdcd5c.jpg

35719602bf7de6db98b3a02e6d488afdb7f0bf058d494ee3169e325e98faa195.jpg

这里要强调指出以下几点:

以上这些概念是计算机网络的精髓所在,对这些重要概念务必仔细思考和掌握。

细心的读者会发现,还有两个重要问题没有解决:

第一个问题就是下一节所要讲的内容,而第二个问题将在后面的 4.5 节详细讨论。

4.2.4 地址解析协议 ARP

在实际应用中,我们经常会遇到这样的问题:已经知道了一个机器(主机或路由器)的 IP 地址,需要找出其相应的 MAC 地址。地址解析协议 ARP [RFC 826, STD37] 就是用来解决这样的问题的。图 4-17 说明了协议 ARP 的作用。

ade4762dc1a7a76a2d3a9bf560c17bb01a65b24cd32e3234773f80723c3db245.jpg

还有一个旧的协议叫作逆地址解析协议 RARP,它的作用是使只知道自己 MAC 地址的主机能够通过协议 RARP 找出其 IP 地址。现在的协议 DHCP(见第 6 章的 6.6 节)已经包含了协议 RARP 的功能。因此本书不再介绍协议 RARP。

下面就介绍协议 ARP 的要点。

我们知道,网络层使用的是 IP 地址,但在实际网络的链路上传送数据帧时,最终还是必须使用链路层的 MAC 地址。IP 地址和下面链路层的 MAC 地址之间由于格式不同而不存在简单的映射关系(例如,IP 地址有 32 位,而链路层的 MAC 地址是 48 位)。此外,在一个网络上可能经常会有新的主机加入进来,或撤走一些主机。更换网络适配器也会使主机的 MAC 地址改变(请注意,主机的 MAC 地址实际上就是其网络适配器的 MAC 地址)。地址解析协议 ARP 解决这个问题的方法是在主机的 ARP 高速缓存中存放一个从 IP 地址到 MAC 地址的映射表,并且这个映射表还经常动态更新(新增或超时删除)。

每一台主机都设有一个 ARP 高速缓存 (ARP cache),里面存有本局域网上的各主机和路由器的 IP 地址到 MAC 地址的映射表,这些都是该主机目前知道的一些 MAC 地址。那么主机怎样知道这些 MAC 地址呢?我们可以通过下面的例子来说明。

当主机 A 要向本局域网上的某台主机 B 发送 IP 数据报时,就先在其 ARP 高速缓存中查看有无主机 B 的 IP 地址。如有,就在 ARP 高速缓存中查出其对应的 MAC 地址,再把这个 MAC 地址写入 MAC 帧,然后通过局域网把该 MAC 帧发往此 MAC 地址。

也有可能查不到主机 B 的 IP 地址。这可能是主机 B 才入网,也可能是主机 A 刚刚加电,其高速缓存还是空的。在这种情况下,主机 A 就自动运行 ARP,然后按以下步骤找出主机 B 的 MAC 地址。

(1) ARP 进程在本局域网上广播发送一个 ARP 请求分组(具体格式可参阅 [COME06] 的第 23 章)。图 4-18 (a) 是主机 A 广播发送 ARP 请求分组的示意图。ARP 请求分组的主要内容是:“我的 IP 地址是 209.0.0.5,MAC 地址是 00-00-C0-15-AD-18。我想知道 IP 地址为 209.0.0.6 的主机的 MAC 地址。”

(2) 在本局域网上的所有主机上运行的 ARP 进程都收到此 ARP 请求分组。

(3) 主机 B 的 IP 地址与 ARP 请求分组中要查询的 IP 地址一致,就收下这个 ARP 请求分组,并向主机 A 发送 ARP 响应分组,同时在这个 ARP 响应分组中写入自己的 MAC 地址。由于其余所有主机的 IP 地址都与 ARP 请求分组中要查询的 IP 地址不一致,因此都不理睬这个 ARP 请求分组,如图 4-18 (b) 所示。ARP 响应分组的主要内容是:“我的 IP 地址是 209.0.0.6,我的 MAC 地址是 08-00-2B-00-EE-0A。” 请注意:虽然 ARP 请求分组是广播发送的,但 ARP 响应分组是普通的单播,即从一个源地址发送到一个目的地址。

61f1a91c69e11328323b1fdd8a33c08aa0235ce4b3872cff07d6565626f1801d.jpg

d1c1a3f19e66eaa1a719a719f2bea1bb296043810dcc2b4130b797944a77a83a.jpg

(4) 主机 A 收到主机 B 的 ARP 响应分组后,就在其 ARP 高速缓存中写入主机 B 的 IP 地址到 MAC 地址的映射。

当主机 A 向 B 发送数据报时,很可能以后不久主机 B 还要向 A 发送数据报,因而主机 B 也可能要向 A 发送 ARP 请求分组。为了减少网络上的通信量,主机 A 在发送其 ARP 请求分组时,就把自己的 IP 地址到 MAC 地址的映射写入 ARP 请求分组。当主机 B 收到 A 的 ARP 请求分组时,就把主机 A 的这一地址映射写入主机 B 自己的 ARP 高速缓存中。以后主机 B 向 A 发送数据报时就很方便了。

可见 ARP 高速缓存非常有用。如果不使用 ARP 高速缓存,那么任何一台主机只要进行一次通信,就必须在网络上用广播方式发送 ARP 请求分组,这就会使网络上的通信量大大增加。ARP 把已经得到的地址映射保存在高速缓存中,这样就使得该主机下次再和具有同样目的地址的主机通信时,可以直接从高速缓存中找到所需的 MAC 地址而不必再用广播方式发送 ARP 请求分组。

ARP 对保存在高速缓存中的每一个映射地址项目都设置生存时间(例如,10~20 分钟)。凡超过生存时间的项目就从高速缓存中删除掉。设置这种地址映射项目的生存时间是很重要的。设想有一种情况:主机 A 和 B 通信。A 的 ARP 高速缓存里保存有 B 的 MAC 地址,但 B 的网络适配器突然坏了,B 立即更换了一块,因此 B 的 MAC 地址就改变了。假定 A 还要和 B 继续通信。A 在其 ARP 高速缓存中查找到 B 原先的 MAC 地址,并使用该 MAC 地址向 B 发送数据帧。但 B 原先的 MAC 地址已经失效了,因此 A 无法找到主机 B。但是过了一段不长的生存时间,A 的 ARP 高速缓存中已经删除了 B 原先的 MAC 地址,于是 A 重新广播发送 ARP 请求分组,又找到了 B。

请注意,ARP 用于解决同一个局域网上的主机或路由器的 IP 地址和 MAC 地址的映射问题。如果所要找的主机和源主机不在同一个局域网上,例如,在前面的图 4-16 中,主机 \(H_{1}\) 就无法解析出另一个局域网上主机 \(H_{2}\) 的 MAC 地址(实际上主机 \(H_{1}\) 也不需要知道远程主机 \(H_{2}\) 的 MAC 地址)。主机 \(H_{1}\) 发送给 \(H_{2}\) 的 IP 数据报首先需要通过与主机 \(H_{1}\) 连接在同一个局域网上的路由器 \(R_{1}\) 来转发,因此主机 \(H_{1}\) 必须知道路由器 \(R_{1}\) 的 IP 地址。于是 \(H_{1}\) 使用 ARP 把路由器 \(R_{1}\) 的 IP 地址 \(IP_{3}\) 解析为 MAC 地址 \(MAC_{3}\) ,然后把 IP 数据报传送到路由器 \(R_{1}\) 。以后, \(R_{1}\) 从转发表知道应把 IP 数据报转发到路由器 \(R_{2}\) ,再使用 ARP 解析出 \(R_{2}\) 的 MAC 地址 \(MAC_{5}\) ,把 IP 数据报转发到路由器 \(R_{2}\) 。路由器 \(R_{2}\) 用同样方法解析出目的主机 \(H_{2}\) 的 MAC 地址 \(MAC_{2}\) ,使 IP 数据报最终交付主机 \(H_{2}\)

从 IP 地址到 MAC 地址的解析是自动进行的,主机的用户对这种地址解析过程是不知道的。只要主机或路由器要和本网络上的另一个已知 IP 地址的主机或路由器进行通信,协议 ARP 就会自动地把这个 IP 地址解析为链路层所需要的 MAC 地址,然后插入到 MAC 帧中。

下面我们归纳出使用 ARP 的四种典型情况(如图 4-19 所示)。

ecbbb50116e84098d60493a219fdda6de2a5fe80873b244b0b3c05b86d921bd6.jpg

(1) 发送方是主机(如 \(H_{1}\) ),要把 IP 数据报发送到同一个网络上的另一台主机(如 \(H_{2}\) )。这时 \(H_{1}\) 发送 ARP 请求分组(在网络 \(N_{1}\) 上广播),找到目的主机 \(H_{2}\) 的 MAC 地址。

(2) 发送方是主机(如 \(H_{1}\) ),要把 IP 数据报发送到另一个网络上的一台主机(如 \(H_{3}\)\(H_{4}\) )。这时 \(H_{1}\) 发送 ARP 请求分组(在网络 \(N_{1}\) 上广播),找到 \(N_{1}\) 上的一个路由器 \(R_{1}\) 的 MAC 地址。剩下的工作由路由器 \(R_{1}\) 来完成。 \(R_{1}\) 要做的事情是下面的 (3) 或 (4)。

(3) 发送方是路由器(如 \(\mathbf{R}_1\) ),要把 IP 数据报转发到与 \(\mathbf{R}_1\) 连接在同一个网络 \(\mathbf{N}_2\) 上的主机(如 \(\mathbf{H}_3\) )。这时 \(\mathbf{R}_1\) 发送 ARP 请求分组(在 \(\mathbf{N}_2\) 上广播),找到目的主机 \(\mathbf{H}_3\) 的 MAC 地址。

(4) 发送方是路由器(如 \(R_{1}\) ),要把 IP 数据报转发到网络 \(N_{3}\) 上的一台主机(如 \(H_{4}\) )。 \(H_{4}\)\(R_{1}\) 不是连接在同一个网络上的。这时 \(R_{1}\) 发送 ARP 请求分组(在 \(N_{2}\) 上广播),找到连接在 \(N_{2}\) 上的一个路由器 \(R_{2}\) 的 MAC 地址。剩下的工作由这个路由器 \(R_{2}\) 来完成。

在许多情况下需要多次使用 ARP,但这只是以上几种情况的反复使用而已。

有的读者可能会产生这样的问题:既然在网络链路上传送的帧最终是按照 MAC 地址找到目的主机的,那么为什么我们还要使用两种地址(IP 地址和 MAC 地址),而不直接使用 MAC 地址进行通信?只用一个 MAC 地址进行通信似乎可以免除使用 ARP。

这个问题必须弄清楚。

由于全世界存在着各式各样的网络,它们使用不同的 MAC 地址。要使这些异构网络能够互相通信就必须进行非常复杂的 MAC 地址转换工作,因此由用户或用户主机来完成这项工作几乎是不可能的事。即使是对分布在全世界的以太网 MAC 地址进行寻址,也是极其困难的。然而 IP 编址把这个复杂问题解决了。连接到互联网的主机只需各自拥有一个 IP 地址,它们之间的通信就像连接在同一个网络上那样简单方便,即使必须多次调用 ARP 来找到 MAC 地址,但这个过程都是由计算机软件自动进行的,对用户来说是看不见的。

因此,在虚拟的 IP 网络上用 IP 地址进行通信给广大的计算机用户带来了很大的方便。

4.2.5 IP 数据报的格式

IP 数据报的格式说明协议 IP 都具有什么功能。在协议 IP 的标准中,描述首部格式的宽度是 32 位(即 4 字节)。图 4-20 是 IP 数据报的完整格式 [RFC 791, STD5]。

ad5ebcd50355db8c69bb9aa6158df1059dfa7a7019c22e091a5de3d1fb195736.jpg

8ce28289497081a0614e4fa69273e825d72155d6a220e29f771c228f2edfcf44.jpg

从图 4-20 可看出,一个 IP 数据报由首部和数据两部分组成。首部的前一部分长度是固定的,共 20 字节,是所有 IP 数据报必须具有的。在首部的固定部分的后面是一些可选字段,其长度是可变的。下面介绍首部各字段的意义。

1. IP 数据报首部的固定部分中的各字段

(3) 区分服务 占 8 位,用来获得更好的服务。这个字段在旧标准中叫作服务类型,但实际上一直没有被使用过。1998 年 IETF 把这个字段改名为区分服务 DS (Differentiated Services)。只有在使用区分服务时,这个字段才起作用(见 8.4.4 节)。在一般的情况下都不使用这个字段 [RFC 2474, RFC 3168, RFC 3260]。

(4) 总长度 总长度指首部和数据之和的长度,单位为字节。总长度字段为 16 位,因此数据报的最大长度为 \(2^{16} - 1 = 65535\) 字节。然而实际上传送这样长的数据报在现实中是极少遇到的。

我们知道,在 IP 层下面的每一种数据链路层协议都规定了一个数据帧中的数据字段的最大长度,这称为最大传送单元 MTU (Maximum Transfer Unit)。当一个 IP 数据报封装成链路层的帧时,此数据报的总长度(即首部加上数据部分)一定不能超过下面的数据链路层所规定的 MTU 值。例如,最常用的以太网就规定其 MTU 值是 1500 字节。若所传送的数据报长度超过数据链路层的 MTU 值,就必须把过长的数据报进行分片处理。

虽然使用尽可能长的 IP 数据报会使传输效率得到提高(这样每一个 IP 数据报中首部长度占数据报总长度的比例就会小些),但数据报短些也有好处。IP 数据报越短,路由器转发的速度就越快。为此,协议 IP 规定,在互联网中所有的主机和路由器必须能够接受长度不超过 576 字节的数据报。这是假定上层交下来的数据长度有 512 字节(合理的长度),加上最长的 IP 首部 60 字节,再加上 4 字节的富余量,就得到 576 字节。当主机需要发送长度超过 576 字节的数据报时,应当先了解一下,目的主机能否接受所要发送的数据报长度。否则,就要进行分片。

在进行分片时(见后面的 “片偏移” 字段),数据报首部中的 “总长度” 字段是指分片后的每一个分片的首部长度与该分片的数据长度的总和。

(5) 标识 (identification) 占 16 位。IP 软件在存储器中维持一个计数器,每产生一个数据报,计数器就加 1,并将此值赋给标识字段。但这个 “标识” 并不是序号,因为 IP 是无连接服务,数据报不存在按序接收的问题。当数据报由于长度超过网络的 MTU 而必须分片时,这个标识字段的值就被复制到所有的数据报片的标识字段中。相同的标识字段的值使分片后的各数据报片最后能正确地重装成为原来的数据报。

(6) 标志 (flag) 占 3 位,但目前只有两位有意义。

- 标志字段中的最低位记为 MF (More Fragment)。MF = 1 即表示后面 “还有分片” 的数据报。MF = 0 表示这已是若干数据报片中的最后一个。

- 标志字段中间的一位记为 DF (Don't Fragment),意思是 “不能分片”。只有当 DF = 0 时才允许分片。

(7) 片偏移 占 13 位。片偏移指出:较长的分组在分片后,某片在原分组中的相对位置。也就是说,相对于用户数据字段的起点,该片从何处开始。片偏移以 8 个字节为偏移单位。这就是说,除最后一个数据报片外,其他每个分片的长度一定是 8 字节(64 位)的整数倍。

下面举一个例子。

【例 4-1】一个数据报的总长度为 3820 字节,其数据部分为 3800 字节长(使用固定首部),需要分片为长度不超过 1420 字节的数据报片。因固定首部长度为 20 字节,因此每个数据报片的数据部分长度不能超过 1400 字节。于是分为 3 个数据报片,其数据部分的长度分别为 1400, 1400 和 1000 字节。原始数据报首部被复制为各数据报片的首部,但必须修改有关字段的值。图 4-21 给出分片后得出的结果(请注意片偏移的数值)。

3c0287099e8329ef95a20ce6787867032ad2ade916de75ed2441a7ee26690fcc.jpg

表 4-5 是本例中数据报首部与分片有关的字段中的数值,其中标识字段的值是任意给定的(12345)。具有相同标识的数据报片在目的站就可无误地重装成原来的数据报。

表 4-5 IP 数据报首部中与分片有关的字段中的数值

总长度标识MFDF片偏移
原始数据报382012345000
数据报片1142012345100
数据报片214201234510175
数据报片310201234500350

现在假定数据报片 2 经过某个网络时还需要再进行分片,即划分为数据报片 2-1(携带数据 800 字节)和数据报片 2-2(携带数据 600 字节)。那么这两个数据报片的总长度、标识、MF、DF 和片偏移分别为:820, 12345, 1, 0, 175;620, 12345, 1, 0, 275。

(8) 生存时间 占 8 位,生存时间字段常用的英文缩写是 TTL (Time To Live), 表明这是数据报在网络中的寿命。由发出数据报的源点设置这个字段。其目的是防止无法交付的数据报无限制地在互联网中兜圈子(例如从路由器 \(R_{1}\) 转发到 \(R_{2}\) , 再转发到 \(R_{3}\) , 然后又转发到 \(R_{1}\) ), 因而白白消耗网络资源。最初的设计以秒作为 TTL 值的单位。每经过一个路由器时,就把 TTL 减去数据报在路由器所消耗掉的一段时间。若数据报在路由器消耗的时间小于 1 秒,就把 TTL 值减 1 。当 TTL 值减为零时,就丢弃这个数据报。

然而随着技术的进步,路由器处理数据报所需的时间不断在缩短,一般都远远小于 1 秒,后来就把 TTL 字段的功能改为 “跳数限制”(但名称不变)。路由器在每次转发数据报之前就把 TTL 值减 1。若 TTL 值减小到零,就丢弃这个数据报,不再转发。因此,现在 TTL 的单位不再是秒,而是跳数。TTL 的意义是指明数据报在互联网中至多可经过多少个路由器。显然,数据报能在互联网中经过的路由器的最大数值是 255。若把 TTL 的初始值设置为 1,就表示这个数据报只能在本局域网中传送。因为这个数据报一传送到局域网上的某个路由器,在被转发之前 TTL 值就减小到零,所以会被这个路由器丢弃。

(9) 协议 占 8 位,协议字段指出此数据报携带的数据使用何种协议,以便使目的主机的 IP 层知道应将数据部分上交给哪个协议进行处理。

常用的一些协议和相应的协议字段值如下 [W-IANA] \(^{①}\) :

协议名ICMPIGMPIP2TCPEGPIGPUDPIPv6ESPAHICMP-IPv6OSPF
协议字段值124689174150515889

(10) 首部检验和 占 16 位。这个字段只检验数据报的首部,但不包括数据部分。这是因为数据报每经过一个路由器,路由器都要重新计算一下首部检验和(一些字段,如生存时间、标志、片偏移等都可能发生变化)。不检验数据部分可减少计算的工作量。为了进一步减少计算检验和的工作量,IP 首部的检验和不采用复杂的 CRC 检验码而采用下面的简单计算方法:在发送方,先把 IP 数据报首部划分为许多 16 位字的序列,并把检验和字段置零。用反码算术运算 \(^{③}\) 把所有 16 位字相加后,将得到的和的反码写入检验和字段。接收方收到数据报后,把首部的所有 16 位字再使用反码算术运算相加一次。将得到的和取反码,即得出接收方检验和的计算结果。若首部未发生任何变化,则此结果必为 0,于是就保留这个数据报;否则即认为出差错,并将此数据报丢弃。图 4-22 说明了 IP 数据报首部检验和的计算过程。

117d547d3f5fc7ca66ad889c6c1502a712c870bfd7bc7099c440ec6f159f7aa0.jpg

2. IP 数据报首部的可变部分

IP 数据报首部的可变部分就是一个选项字段。选项字段用来支持排错、测量以及安全等措施,内容很丰富。此字段的长度可变,从 1 字节到 40 字节不等,取决于所选择的项目。某些选项项目只需要 1 字节,它只包括 1 字节的选项代码。而有些选项需要多个字节,这些选项一个个拼接起来,中间不需要有分隔符,最后用全 0 的填充字段补齐为 4 字节的整数倍。

增加首部的可变部分是为了增加 IP 数据报的功能,但这同时也使得 IP 数据报的首部长度成为可变的。这就增加了每一个路由器处理数据报的开销。实际上这些选项很少被使用。很多路由器都不考虑 IP 首部的选项字段,因此新的 IP 版本 IPv6 就把 IP 数据报的首部长度做成固定的了。这里就不讨论这些选项的细节了。有兴趣的读者可参阅 RFC 791。

4.3 IP 层转发分组的过程

4.3.1 基于终点的转发

我们在图 4-7 中已经描述了分组在互联网中逐跳转发的概念。分组在互联网上传送和转发是基于分组首部中的目的地址的,因此这种转发方式称为基于终点的转发。

51c4dfe6f07b214393ea5866e37b6d64ad63b5ae2bd0f5daac06fc9340dad3bd.jpg

因此,分组每到达一个路由器,路由器就根据分组中的终点(目的地址)查找转发表,然后就得知下一跳应当到哪一个路由器。

但是,路由器中的转发表却不是按目的 IP 地址来直接查出下一跳路由器的。这是因为互联网中的主机数目实在太大了。如果用目的地址直接查找转发表,那么这种结构的转发表就会非常庞大,使得查找过程非常之慢。这样的转发表也就没有实用价值了。因此必须想办法压缩转发表的大小。

我们知道,32 位的 IP 地址是由两级组成的。前一部分是前缀,表示网络,后一部分表示主机。所以可以把查找目的主机的方法变通一下,即不是直接查找目的主机,而是先查找目的网络(网络前缀),在找到了目的网络之后,就把分组在这个网络上直接交付目的主机。由于互联网上的网络数远远小于主机数,这样就可以大大压缩转发表的大小,加速分组在路由器中的转发。这就是基于终点的转发过程。

读者可能还会想到一个问题,就是分组首部中没有地方可以用来指明 “下一跳路由器的 IP 地址”,那么待转发的分组又怎样能够找到下一跳路由器呢?

当路由器收到一个待转发的分组,在从转发表得出下一跳路由器的 IP 地址后,不是把这个地址填入分组首部,而是送交数据链路层的网络接口软件。网络接口软件负责把下一跳路由器的 IP 地址转换成 MAC 地址(必须使用 ARP),并将此 MAC 地址放在链路层的 MAC 帧的首部,然后利用这个 MAC 地址传送到下一跳路由器的链路层,再取出 MAC 帧的数据部分,交给网络层。由此可见,当发送一连串的分组时,上述的这种查找转发表、调用 ARP 解析出 MAC 地址、把 MAC 地址写入 MAC 帧的首部等过程,都是必须做的(当然都是由机器自动完成的)。

那么,能不能在转发表中不使用 IP 地址而直接使用 MAC 地址呢?不行。我们一定要弄清楚,使用抽象的 IP 地址,本来就是为了隐蔽各种底层网络的复杂性而便于分析和研究问题,这样就不可避免地要付出些代价,例如在选择路由时多了一些开销。但反过来,如果在转发表中直接使用 MAC 地址,那就会带来更多的麻烦,甚至无法找到对方的机器。

下面用具体例子来说明分组的转发过程。

【例 4-2】图 4-23 中有三个子网通过两个路由器互连在一起。主机 \(H_{1}\) 发送出一个分组,其目的地址是 128.1.2.132。现在源主机是 \(H_{1}\) 而目的主机是 \(H_{2}\) 。试讨论分组怎样从源主机传送到目的主机。

61ad971b6ee0989525294308a1efeff026734f4ded16d854ad0899a1c3adb4f1.jpg

【解】主机 \(H_{1}\) 首先必须确定:目的主机是否连接在本网络上?如果是,那么问题很简单,就直接交付,根本不需要利用路由器;如果不是,就间接交付,把分组发送给连接在本网络上的路由器,以后要做的事情都由这个路由器来处理。

主机 \(H_{1}\) 先把要发送的分组的目的地址和本网络 \(N_{1}\) 的子网掩码按位进行 AND 运算,得出运算结果。如果运算结果等于本网络 \(N_{1}\) 的前缀,就表明目的主机连接在本网络上;否则,就必须把分组发送到路由器 \(R_{1}\) ,由路由器 \(R_{1}\) 完成后续的任务。

由于采用了 CIDR 记法,转发表中给出的都是网络前缀,而没有明显给出子网掩码。其实只要细心观察斜线后面的数字,就可知道相应的子网掩码。例如,/26 的子网掩码就是点分十进制的 255.255.255.192。现在,要发送的分组的目的地址是 128.1.2.132,本网络的掩码是 26 个 1,后面有 6 个 0。如图 4-24 (a) 所示,按位 AND 运算的结果是 128.1.2.128,不等于本网络 \(N_{1}\) 的前缀。这说明目的主机没有连接在本网络上。源主机 \(H_{1}\) 必须把分组发送给路由器 \(R_{1}\) ,让路由器 \(R_{1}\) 根据其转发表来处理这个分组。

图 4-24 目的地址和本网络的子网掩码按位进行 AND 运算

(a)目的主机IP地址128.1.2.192/26的掩码10000000000000010000001010000100
11111111111111111111111111000000
按位AND运算10000000000000010000001010000000
得出结果128.1.2.128/26
(b)目的主机IP地址128.1.2.132
10000000000000010000001010000100
128.1.2.128/26的掩码11111111111111111111111111000000
按位AND运算10000000000000010000001010000000
得出结果128.1.2.128/26

路由器 \(R_{1}\) 的部分转发表已在图 4-23 右上方给出了。转发表中第 1 列就是 “前缀匹配”,这是因为查找转发表的过程就是寻找前缀匹配的过程。

现在先检查路由器 \(\mathbf{R}_1\) 的转发表中的第 1 行。

源主机 \(\mathrm{H}_{1}\) 要发送的分组的目的地址是 128.1.2.132。本网络 128.1.2.192/26 的前缀有 26 位,因此本网络的掩码是 26 个 1,后面是 6 个 0。目的地址和子网掩码按位 AND 运算的结果是 128.1.2.128/26(见图 4-24 (a))。很明显,AND 运算结果与转发表第 1 行的前缀不匹配。

接着检查路由器 \(R_{1}\) 的转发表中的第 2 行。运算结果是 128.1.2.128/26,如图 4-24 (b) 所示。这个结果和转发表第 2 行的前缀相匹配。因此按照转发表第 2 行指出的,在网络 \(N_{2}\) 上进行分组的直接交付(通过路由器 \(R_{1}\) 的接口 1)。这时路由器 \(R_{1}\) 调用 ARP,解析出目的主机 \(H_{2}\) 的 MAC 地址,再封装成链路层的帧,直接交付连接在本网络 \(N_{2}\) 上的目的主机 \(H_{2}\)

如果按照同样的方法,检查路由器 \(\mathbb{R}_1\) 的转发表中的第 3 行,不难得出不匹配的结果。

从以上例子可看出,查找转发表的过程就是逐行寻找前缀匹配的过程。我们再看下一个例子。

4.3.2 最长前缀匹配

【例 4-3】假定在图 4-25 的例子中,路由器 \(\mathbb{R}_1\) 收到一个目的地址为 128.1.24.1 的分组,请给出分组的转发接口。请注意,公司 B 包含三个子网,但这些网络前缀并没有出现在路由器 \(\mathbb{R}_1\) 的转发表中。这是因为公司 B 采用了路由聚合,把三个子网的所有地址聚合为一个网络前缀 128.1.24.0/22。

f3ce4bc717ca55c43d54e7388341098b11158dd148ff3763de2a180c6f0ee015.jpg

【解】我们把进入路由器 \(R_{1}\) 的分组的目的地址分别和路由器 \(R_{1}\) 的转发表第 1 行、第 2 行子网掩码进行按位 AND 运算。运算结果都是 “匹配”(建议读者自行验算一下)。那么,哪一个结果是正确的呢?现在就来分析这个问题。

网络前缀 128.1.24.0/22 可以划分为 4 个更小的 / 24 前缀(图 4-26)。其中的一个前缀 128.1.24.0/24 分配给公司 A,另外 3 个前缀分配给公司 B。公司 B 把得到的 3 个前缀聚合成一个更大的前缀 128.1.24.0/22,作为路由器 \(R_{1}\) 的转发表中的一个项目。请注意,这个前缀和原来的前缀在形式上是一样的,但实际的区别是很大的:在图 4-26 左边的网络前缀中包含地址 128.1.24.1,但公司 B 的聚合后的网络前缀则不包含这个地址。因此在本例中,即分组应当从接口 1 转发到公司 A。

那么为什么地址 128.1.24.1 不在公司 B 的聚合前缀 128.1.24.0/22 中,但匹配运算的结果却是匹配呢?这是因为在转发表中的项目 128.1.24.0/22 并未说明是由哪几个子网聚合而成的。

433ecf5bf3d92ad3f5a4863caa5ff703e171988baf158d48c63d6bb7f384e31f.jpg

十分明显,进入路由器 \(R_{1}\) 的分组的目的地址 128.1.24.1 处于公司 A 拥有的地址范围中,而不在公司 B 的地址范围内。分组应当通过接口 1 转发到公司 A。

为了减少路由器 \(\mathbb{R}_1\) 中的项目数,公司 B 采用了地址聚合,把三个地址块聚合为一个地址块 128.1.24.0/22。这个聚合后得出的前缀和图中左边所示的前缀在形式上是一样的。这样就导致图 4-26 所示的出现和两个网络前缀都匹配的现象。

我们可以注意到,现在公司 B 三个地址块得出的聚合地址块是 128.1.24.0/22,但如果公司 B 只分到两个地址块 128.1.25.0/24 和 128.1.26.0/24,那么其聚合地址块仍然是 128.1.24.0/22。如果把公司 A 和公司 B 的地址块都聚合起来,得出的聚合地址块还是 128.1.24.0/22。这样的地址聚合可以发生在路由器 R2 中。

因此,在采用 CIDR 编址时,如果一个分组在转发表中可以找到多个匹配的前缀,那么就应当选择前缀最长的一个作为匹配的前缀。这个原则称为最长前缀匹配 (longest prefix match)。网络前缀越长,其地址块就越小,因而路由就越具体 (more specific)。为了更加迅速地查找转发表,可以按照前缀的长短,把前缀最长的排在第 1 行,然后按前缀长短的顺序往下排列。用这种方法从第 1 行前缀最长的开始查找,只要检查到匹配的,就不必再继续往下查找,可以立即结束查找。

实际的转发表有时还可能增加两种特殊的路由,就是主机路由和默认路由。

主机路由 (host route) 又叫作特定主机路由,这是对特定目的主机的 IP 地址专门指明的一个路由。采用特定主机路由可使网络管理人员更方便地控制网络和测试网络,同时也可在需要考虑某种安全问题时采用这种特定主机路由。在对网络的连接或转发表进行排错时,指明到某一台主机的特殊路由就十分有用。假定这个特定主机的点分十进制 IP 地址是 a.b.c.d,那么在转发表中对应于主机路由的网络前缀就是 a.b.c.d/32。我们知道,/32 表示的子网掩码是 32 个 1。实际的网络不可能使用 32 位的前缀,因为没有主机号的 IP 地址是没有实际意义的。但这个特殊的前缀却可以用在转发表中。不难看出,32 个 1 的子网掩码和 IP 地址 a.b.c.d 按位进行 AND 运算后,得出的结果必定是 a.b.c.d,也就是说,找到了匹配。这时就把收到的分组转发到转发表所指出的下一跳。主机路由在转发表中都放在最前面。

还有一种特殊路由是默认路由 (default route)。这就是不管分组的最终目的网络在哪里,都由指定的路由器 R 来处理。这在网络只有很少的对外连接时非常有用。在实际的转发表中,用一个特殊前缀 0.0.0.0/0 来表示默认路由。这个前缀的掩码是全 0(/0 表示网络前缀是 0 位,因此掩码是 32 个 0)。用全 0 的掩码和任何目的地址进行按位 AND 运算,结果一定是全 0,即必然是和转发表中的 0.0.0.0/0 相匹配的。这时就按照转发表的指示,把分组送交下一跳路由器 R 来处理(即间接交付)。

综上所述,可归纳出分组转发算法如下(假定转发表按照前缀的长短排列,把前缀长的放在前面):

若运算结果与本行的前缀匹配,则查找结束,按照 “下一跳” 所指出的进行处理(或直接交付本网络上的目的主机,或通过指定接口发送到下一跳路由器)。

否则,若转发表还有下一行,则对下一行进行检查,重新执行 (3)。

否则,执行 (4)。

(4) 若转发表中有一个默认路由,则按照指明的接口,把分组传送到指明的默认路由器;否则,报告转发分组出错。

可以用一个简单的比喻来说明查找转发表和转发分组的过程。例如,从家门口开车到机场,但没有地图,不知道应当走哪条路线。好在每一个道路岔口都有一个警察可以询问。因此,每到一个岔口(相当于到了一个路由器),就问:“到机场应当朝哪个方向走?”(相当于查找转发表)。该警察并不告诉你去机场的详细路径。他仅仅指出到机场途经的下一个警察位置的方向。其回答可能是:“向左转方向走。” 你左转到了下一个岔口,再询问警察,回答可能是:“直行。” 这样,每到一个岔口,就询问下一步走的方向。这样,在没有地图的情况下,我们最终也可以到达目的地 —— 机场。

顺便指出,在过去使用分类地址时,不存在最长前缀匹配的问题。在转发表中,不会出现目的地址和转发表中的两行或两行以上的网络地址匹配的情况。

4.3.3 使用二叉线索查找转发表

使用 CIDR 后,由于不知道目的网络的前缀,使转发表的查找过程变得更加复杂了。当转发表的项目数很大时,怎样设法缩短转发表的查找时间就成为一个非常重要的问题。例如,连接路由器的线路的速率为 10 Gbit/s,而分组的平均长度为 2000 bit,那么路由器就应当平均每秒钟能够处理 500 万个分组(常记为 5 Mpps)。或者说,路由器处理一个分组的平均时间只有 200 ns( \(1 \text{ ns} = 10^{-9} \text{ s}\) )。因此,查找每一个路由所需的时间是非常短的。可见在转发表中必须使用很好的数据结构和先进的快速查找算法,这一直是人们积极研究的热门课题。

对无分类编址的转发表的最简单的查找算法就是对所有可能的前缀进行循环查找,从最长的前缀开始查找。例如,给定一个目的地址。对每一个可能的网络前缀,进行目的地址和子网掩码的按位 AND 运算,得出一个网络前缀,然后逐行查找转发表中的网络前缀。所找到的最长匹配就对应于要查找的路由。

这种最简单的算法的明显缺点就是查找的次数太多。最坏的情况是转发表中没有这个路由。在这种情况下,算法仍要进行 32 次(第 1 次用 32 位的前缀查找转发表中所有的行,第 2 次用 31 位的前缀查找所有的行,这样一直查找下去)。

为了进行更加有效的查找,通常是把无分类编址的转发表存放在一种层次的数据结构中,然后自上而下地按层次进行查找。这里最常用的就是二叉线索 (binary trie) \(^{①}\) ,它是一种特殊结构的树。IP 地址中从左到右的比特值决定了从根节点逐层向下层延伸的路径,而二叉线索中的各个路径就代表转发表中存放的各个地址。

图 4-27 用一个例子来说明二叉线索的结构。图中给出了 5 个 IP 地址。为了简化二叉线索的结构,可以先找出对应于每一个 IP 地址的唯一前缀 (unique prefix)。所谓唯一前缀就是在表中所有的 IP 地址中,该前缀是唯一的。这样就可以用这些唯一前缀来构造二叉线索。在进行查找时,只要能够和唯一前缀相匹配就行了。

32 位的 IP 地址唯一前缀
01000110 00000000 00000000 000000000100
01010110 00000000 00000000 000000000101
01100001 00000000 00000000 00000000011
10110000 00000010 00000000 0000000010110
10111011 00001010 00000000 0000000010111

d16d0a08df402065e38fc243d15f634bd6eac647195c4a9c387ab9da77354dbe.jpg

从二叉线索的根节点自顶向下的深度最多有 32 层,每一层对应于 IP 地址中的一位。一个 IP 地址存入二叉线索的规则很简单:先检查 IP 地址左边的第一位,如为 0,则第一层的节点就在根节点的左下方;如为 1,则在右下方。然后再检查地址的第二位,构造出第二层的节点。依此类推,直到唯一前缀的最后一位。由于唯一前缀一般都小于 32 位,因此用唯一前缀构造的二叉线索的深度往往不到 32 层。图中较粗的折线就是前缀 0101 在这个二叉线索中的路径。二叉线索中的小圆圈是中间节点,而在路径终点的小方框是叶节点(也叫作外部节点)。每个叶节点代表一个唯一前缀。节点之间的连线旁边的数字表示这条边在唯一前缀中对应的比特是 0 或 1。

假定有一个 IP 地址是 10011011 01111010 00000000 00000000,需要查找该地址是否在此二叉线索中。我们从最左边查起。很容易发现,查到第三个字符(即前缀 10 后面的 0)时,在二叉线索中就找不到匹配的,说明这个地址不在这个二叉线索中。

以上只是给出了二叉线索这种数据结构的用法,而并没有说明 “与唯一前缀匹配” 和 “与网络前缀匹配” 的关系。显然,要将二叉线索用于转发表中,还必须使二叉线索中的每一个叶节点包含所对应的网络前缀和子网掩码。当搜索到一个叶节点时,就必须将寻找匹配的目的地址和该叶节点的子网掩码进行按位 AND 运算,看结果是否与对应的网络前缀相匹配。若匹配,就按下一跳的接口转发该分组。否则,就丢弃该分组。

总之,二叉线索只是提供了一种可以快速在转发表中找到匹配的叶节点的机制。但这是否和网络前缀匹配,还要和子网掩码进行一次逻辑 AND 运算。

为了提高二叉线索的查找速度,广泛使用了各种压缩技术。例如,在图 4-27 中的最后两个地址,其最前面的 4 位都是 1011。因此,只要一个地址的前 4 位是 1011,就可以跳过前面 4 位(即压缩了 4 个层次)而直接从第 5 位开始比较。这样就可以减少查找的时间。当然,制作经过压缩的二叉线索需要更多的计算,但由于每一次查找转发表时都可以提高查找速度,因此这样做还是值得的。

4.4 网际控制报文协议 ICMP

为了更有效地转发 IP 数据报和提高交付成功的机会,在网际层使用了网际控制报文协议 ICMP (Internet Control Message Protocol) [RFC 792, STD5]。ICMP 允许主机或路由器报告差错情况和提供有关异常情况的报告。ICMP 是互联网的标准协议。但 ICMP 不是高层协议(看起来好像是高层协议,因为 ICMP 报文装在 IP 数据报中,作为其中的数据部分),而是 IP 层的协议。ICMP 报文作为 IP 层数据报的数据,加上数据报的首部,组成 IP 数据报发送出去。ICMP 报文格式如图 4-28 所示。

446264458cef9081446f12932409ccaa4d21d0fbe126b237cd1370b8fd15df35.jpg

4.4.1 ICMP 报文的种类

ICMP 报文有两种,即 ICMP 差错报告报文和 ICMP 询问报文。

ICMP 报文的前 4 字节是统一的格式,共有三个字段:类型、代码和检验和。接着的 4 字节的内容与 ICMP 的类型有关。最后面是数据字段,其长度取决于 ICMP 的类型。表 4-6 给出了几种常用的 ICMP 报文类型。

表 4-6 几种常用的 ICMP 报文类型

ICMP 报文种类类型的值ICMP 报文的类型
差错报告报文3终点不可达
11时间超过
12参数问题
5改变路由(Redirect)
询问报文8 或 0回送(Echo)请求或回送回答
13 或 14时间戳(Timestamp)请求或时间戳回答

ICMP 标准在不断更新。已不再使用的 ICMP 报文有:“信息请求与回答报文”“地址掩码请求与回答报文”“路由器请求与通告报文” 以及 “源点抑制报文”[RFC 6633]。

ICMP 报文的代码字段用于进一步区分某种类型中的几种不同情况。检验和字段用来检验整个 ICMP 报文。我们应当还记得,IP 数据报首部的检验和并不检验 IP 数据报的内容,因此不能保证经过传输的 ICMP 报文不产生差错。

表 4-6 给出的 ICMP 差错报告报文共有四种,即:

(1) 终点不可达 当路由器或主机不能交付数据报时就向源点发送终点不可达报文。

下面对改变路由报文进行简短的解释。我们知道,在互联网的主机中也要有一个转发表。当主机要发送数据报时,首先查找主机自己的转发表,看应当从哪一个接口把数据报发送出去。在互联网中主机的数量远大于路由器的数量,出于效率的考虑,这些主机不和连接在网络上的路由器定期交换路由信息。在主机刚开始工作时,一般都在转发表中设置一个默认路由器的 IP 地址。不管数据报要发送到哪个目的地址,都一律先把数据报传送给这个默认路由器,而这个默认路由器知道到每一个目的网络的最佳路由(通过和其他路由器交换路由信息)。如果默认路由器发现主机发往某个目的地址的数据报的最佳路由应当经过网络上的另一个路由器 R,就用改变路由报文把这情况告诉主机。于是,该主机就在其转发表中增加一个项目:到某某目的地址应经过路由器 R(而不是默认路由器)。

所有的 ICMP 差错报告报文中的数据字段都具有同样的格式(如图 4-29 所示)。把收到的需要进行差错报告的 IP 数据报的首部和数据字段的前 8 个字节提取出来,作为 ICMP 报文的数据字段。再加上相应的 ICMP 差错报告报文的前 8 个字节,就构成了 ICMP 差错报告报文。提取收到的数据报的数据字段前 8 个字节是为了得到运输层的端口号(对于 TCP 和 UDP)以及运输层报文的发送序号(对于 TCP)。这些信息对源点通知高层协议是有用的(端口的作用将在 5.1.3 节中介绍)。整个 ICMP 报文作为 IP 数据报的数据字段发送给源点。

7318f220f4af671ed6b2f5b5ef9a32c505b1d3d67972158d97b2e9beba8a77cd.jpg

下面是不应发送 ICMP 差错报告报文的几种情况:

常用的 ICMP 询问报文有两种,即:

(1) 回送请求或回送回答 ICMP 回送请求报文是由主机或路由器向一个特定的目的

主机发出的询问。收到此报文的主机必须给源主机或路由器发送 ICMP 回送回答报文。这种询问报文用来测试目的站是否可达以及了解其有关状态。

(2) 时间戳请求或时间戳回答 在 ICMP 时间戳请求报文发出后,就能够收到对方响应的 ICMP 时间戳回答报文。利用在报文中记录的时间戳(如报文的发送时间和接收时间),发送方很容易计算出当前网络的往返时延。

4.4.2 ICMP 的应用举例

ICMP 的一个重要应用就是分组网间探测 PING (Packet InterNet Groper),用来测试两台主机之间的连通性。PING 使用了 ICMP 回送请求与回送回答报文。PING 是应用层直接使用网络层 ICMP 的一个例子。它没有通过运输层的 TCP 或 UDP。

Windows 操作系统的用户可在接入互联网后转入 MS DOS(点击 “开始”,点击 “运行”,再键入 “cmd”)。看见屏幕上的提示符后,就键入 “ping hostname”(这里的 hostname 是要测试连通性的主机名或它的 IP 地址),按回车键后就可看到结果。

图 4-30 给出了从南京的一台 PC 到新浪网的邮件服务器 mail.sina.com.cn 的连通性的测试结果。PC 一连发出 4 个 ICMP 回送请求报文。如果邮件服务器 mail.sina.com.cn 正常工作而且响应这个 ICMP 回送请求报文(有的主机为了防止恶意攻击就不理睬外界发送过来的这种报文),那么它就发回 ICMP 回送回答报文。由于往返的 ICMP 报文上都有时间戳,因此很容易得出往返时间。最后显示出的是统计结果:发送到哪个机器(IP 地址),发送的、收到的和丢失的分组数(但不给出分组丢失的原因),以及往返时间的最小值、最大值和平均值。从得到的结果可以看出,第三个测试分组丢失了。

另一个非常有用的应用是 traceroute(这是 UNIX 操作系统中的命令),用来跟踪一个分组从源点到终点的路径。在 Windows 操作系统中这个命令是 tracert。下面简单介绍这个命令的工作原理。

traceroute 从源主机向目的主机发送一连串的 IP 数据报,数据报中封装的是无法交付的 UDP 用户数据报 \(^{①}\) 。第一个数据报 \(P_{1}\) 的生存时间 TTL 设置为 1。当 \(P_{1}\) 到达路径上的第一个路由器 \(R_{1}\) 时,路由器 \(R_{1}\) 先收下它,接着把 TTL 的值减 1。由于 TTL 等于零了,因此 \(R_{1}\) 就把 \(P_{1}\) 丢弃,并向源主机发送一个 ICMP 时间超过差错报告报文。

源主机接着发送第二个数据报 \(\mathrm{P}_2\) ,并把 TTL 设置为 2。 \(\mathrm{P}_2\) 先到达路由器 \(\mathbb{R}_1\)\(\mathbb{R}_1\) 收下后把 TTL 减 1 再转发给路由器 \(\mathbb{R}_2\)\(\mathbb{R}_2\) 收到 \(\mathbb{P}_2\) 时 TTL 为 1,但减 1 后 TTL 变为零了。 \(\mathbb{R}_2\) 就丢弃 \(\mathbb{P}_2\) ,并向源主机发送一个 ICMP 时间超过差错报告报文。这样一直继续下去。当最后一个数据报刚刚到达目的主机时,数据报的 TTL 是 1。主机不转发数据报,也不把 TTL 值减 1。但因 IP 数据报中封装的是无法交付的运输层的 UDP 用户数据报,因此目的主机要向源主机发送 ICMP 终点不可达差错报告报文(见 5.2.2 节)。

这样,源主机达到了自己的目的,因为这些路由器和最后目的主机发来的 ICMP 报文正好给出了源主机想知道的路由信息 —— 到达目的主机所经过的路由器的 IP 地址,以及到达其中的每一个路由器的往返时间。图 4-31 是从南京的一个 PC 向新浪网的邮件服务器 mail.sina.com.cn 发出 tracert 命令后所获得的结果。图中每一行有三个时间出现,是因为对应于每一个 TTL 值,源主机要发送三次同样的 IP 数据报。

我们还应注意到,从原则上讲,IP 数据报经过的路由器越多,所花费的时间也会越长。但从图 4-31 可看出,有时正好相反。这是因为互联网的拥塞程度随时都在变化,也很难预料到。因此,完全有这样的可能:经过更多的路由器反而花费更短的时间。

30dd84c8950f0e72cd13ceee5a597a0a7654fecb15a40b0d9449014b1983ece8.jpg

4.5 IPv6

协议 IP 是互联网的核心协议。现在使用的协议 IP(即 IPv4)是在 20 世纪 70 年代末期设计的。互联网经过几十年的飞速发展,在 2011 年 2 月 3 日,IANA 开始停止向地区互联网注册机构 RIR 分配 IPv4 地址,因为 IPv4 地址已经全部耗尽了。不久,各地区互联网地址分配机构也相继宣布地址耗尽。我国在 2014 年至 2015 年也逐步停止了向新用户和应用分配 IPv4 地址,同时全面开始商用部署 IPv6。

解决 IP 地址耗尽的根本措施就是采用具有更大地址空间的新版本的 IP,即 IPv6。经过多年的研究和试验,2017 年 7 月终于发布了 IPv6 的正式标准 [RFC 8200, STD86]。

4.5.1 IPv6 的基本首部

IPv6 仍支持无连接的传送,但将协议数据单元 PDU 称为分组 (packet),而不是 IPv4 的数据报 (datagram)。为方便起见,本书仍采用数据报这一名词([KURO17] 和 [TANE11] 也是这样做的)。实际上,在本书中一直把分组和数据报看成是同义词。

IPv6 所引进的主要变化如下:

IPv6 数据报由两大部分组成,即基本首部 (base header) 和后面的有效载荷 (payload)。有效载荷也称为净负荷。有效载荷允许有零个或多个扩展首部 (extension header),再后面是数据部分(如图 4-32 所示)。但请注意,所有的扩展首部并不属于 IPv6 数据报的基本首部。

f863e338567692e30d6a9c98bfadfe0347e6fe9bcd0dec87d315d9b756cdf57e.jpg

与 IPv4 相比,IPv6 对首部中的某些字段进行了如下的更改:

路层对检测出有差错的帧就丢弃。在运输层,当使用 UDP 时,若检测出有差错的用户数据报就丢弃。当使用 TCP 时,对检测出有差错的报文段就重传,直到正确传送到目的进程为止。因此在网络层的差错检测可以精简掉。

- 取消了选项字段,而用扩展首部来实现选项功能。

由于把首部中不必要的功能取消了,使得 IPv6 首部的字段数减少到只有 8 个(虽然首部长度增大了一倍)。

下面解释 IPv6 基本首部中各字段的作用(参见图 4-33)。

2eb6900c7a42522ddc9cf7aec83bb9bab93477310a165ac3ffbef6759d587fac.jpg

- 当 IPv6 数据报没有扩展首部时,下一个首部字段的作用和 IPv4 的协议字段一样,它的值指出了基本首部后面的数据应交付 IP 层上面的哪一个高层协议(例如:6 或 17 分别表示应交付运输层 TCP 或 UDP)。

- 当出现扩展首部时,下一个首部字段的值就标识后面第一个扩展首部的类型。

(6) 跳数限制 (hop limit) 占 8 位。用来防止数据报在网络中无限期地存在。和 IPv4 的生存时间字段相似。源点在每个数据报发出时即设定某个跳数限制(最大为 255 跳)。每个路由器在转发数据报时,要先把跳数限制字段中的值减 1。当跳数限制的值为零时,就要把这个数据报丢弃。

(7) 源地址 占 128 位。是数据报的发送端的 IP 地址。

(8) 目的地址 占 128 位。是数据报的接收端的 IP 地址。

下面我们简单介绍一下 IPv6 的扩展首部。

在 RFC 8200 中定义了以下六种扩展首部:(1)逐跳选项;(2)路由选择;(3)分片;(4)鉴别;(5)封装安全有效载荷;(6)目的站选项。

每一个扩展首部都由若干个字段组成,它们的长度也各不同。但所有扩展首部的第一个字段都是 8 位的 “下一个首部” 字段。此字段的值指出了在该扩展首部后面的扩展首部是什么。当使用多个扩展首部时,应按以上的先后顺序出现。高层首部总是放在最后面。

大家知道,IPv4 的数据报若在其首部中使用了选项,则在数据报转发路径中的每一个路由器,都必须检查首部中的所有选项,看是否与本路由器相关。这必然要花费相当的时间。IPv6 把原来 IPv4 首部中选项的功能都放在扩展首部中。IPv6 数据报若使用了扩展首部,则其基本首部的 “下一个首部” 字段会指出,在 “有效载荷” 字段中使用了何种扩展首部。而所有扩展首部的第一个字段都是 “下一个首部”,用来指出在后面还有何种扩展首部。这就使得路由器能够迅速判断待转发的 IPv6 数据报有无需要本路由器处理的选项。

4.5.2 IPv6 的地址

一般来讲,一个 IPv6 数据报的目的地址可以是以下三种基本类型地址之一:

IPv6 把实现 IPv6 的主机和路由器均称为节点。由于一个节点可能会使用多条链路与其他的一些节点相连,因此一个节点可能有多个与链路相连的接口。这样,IPv6 给节点的每一个接口(请注意,不是给某个节点)指派一个 IPv6 地址。一个具有多个接口的节点可以有多个单播地址,而其中任何一个地址都可当作到达该节点的目的地址。不过有时为了方便,若不会引起误解,也常说某个节点的 IPv6 地址,而把某个接口省略掉。

在 IPv6 中,每个地址占 128 位,地址空间大于 \(3.4 \times 10^{38}\) 。如果整个地球表面(包括陆地和水面)都覆盖着计算机,那么 IPv6 允许每平方米拥有 \(7 \times 10^{23}\) 个 IP 地址。如果地址分配速率是每微秒分配 100 万个地址,则需要 \(10^{19}\) 年的时间才能将所有可能的地址分配完毕。可见在想象到的将来,IPv6 的地址空间是不可能用完的。

为了体会一下 IPv6 的地址有多大,可以看一下目前已经分配出去的最大的地址块。法国电信 France Telecom 和德国电信 Deutsche Telekom 各分配到一个 / 19 地址块,相当于各有 \(35 \times 10^{12}\) 个地址,远远大于全部的 IPv4 地址(IPv4 地址还不到 \(4.3 \times 10^{9}\) 个)。

巨大的地址范围还必须使维护互联网的人易于阅读和操纵这些地址。IPv4 所用的点分十进制记法现在也不够方便了。例如,一个用点分十进制记法的 128 位的地址为:

为了使地址再稍简洁些,IPv6 使用冒号十六进制记法 (colon hexadecimal notation, 简写为 colon hex),它把每个 16 位的值用十六进制值表示,各值之间用冒号分隔。例如,如果前面所给的点分十进制数记法的值改为冒号十六进制记法,就变成了:

68E6:8C64:FFFF:FFFF:0:1180:960A:FFFF

在十六进制记法中,允许把数字前面的 0 省略。上面就把 0000 中的前三个 0 省略了。

冒号十六进制记法还包含两个技术使它尤其有用。首先,冒号十六进制记法可以允许零压缩 (zero compression),即一连串连续的零可以为一对冒号所取代,例如:

FF05:0:0:0:0:0:B3

可压缩为:

FF05::B3

为了保证零压缩有一个不含混的解释,规定在任一地址中只能使用一次零压缩。该技术对已建议的分配策略特别有用,因为会有许多地址包含较长连续的零串。

其次,冒号十六进制记法可结合使用点分十进制记法的后缀。我们下面会看到这种结合在 IPv4 向 IPv6 的转换阶段特别有用。例如,下面的串是一个合法的冒号十六进制记法:

0:0:0:0:0:0:128.10.2.1

请注意,在这种记法中,冒号所分隔的每个值是两个字节(16 位)的值,但点分十进制每个部分的值是一个字节(8 位)的值。再使用零压缩即可得出:

::128.10.2.1

下面再给出几个使用零压缩的例子。

1080:0:0:0:8:800:200C:417A 记为 1080::8:800:200C:417A

FF01:0:0:0:0:0:0:101(多播地址)记为 FF01::101

0:0:0:0:0:0:0:1(环回地址) 记为 ::1

0:0:0:0:0:0:0:0(未指明地址) 记为:

CIDR 的斜线表示法仍然可用。例如,60 位的前缀 12AB00000000CD3(十六进制表示的 15 个字符,每个字符代表 4 位二进制数字)可记为:

12AB:0000:0000:CD30:0000:0000:0000:0000/60

或 12AB::CD30:0:0:0:0/60

或 12AB:0:0:CD30::/60

但不允许记为:

12AB:0:0:CD3/60(不能把 16 位地址 CD30 块中的最后的 0 省略)

或 12AB::CD30/60(这表示 12AB:0:0:0:0:0:0:CD30/60)

或 12AB::CD3/60(这表示 12AB:0:0:0:0:0:0:0CD3/60)

但是,IPv6 取消了子网掩码。

斜线的意思和 IPv4 的情况相似。例如,

CIDR 记法的 2001:0DB8:0:CD30:123:4567:89AB:CDEF/60,表示

IPv6 的地址是:2001:0DB8:0:CD30:123:4567:89AB:CDEF

而其子网号是:2001:0DB8:0:CD30::/60

IPv6 的地址分类如表 4-7 所示 [RFC 4291]。

表 4-7 IPv6 的常用地址分类

地址类型地址块前缀前缀的CIDR记法
未指明地址00···0(128位)::/128
环回地址00···1(128位)::1/128
多播地址11111111FF00::/8
本地站点单播地址1111111011FEC0::/10
本地链路单播地址1111111010FE80::/10
全球单播地址见图4-34

对表 4-7 所列举的几种常用地址简单解释如下。

未指明地址 这是 16 字节的全 0 地址,可缩写为两个冒号 “::”。这个地址不能用作目的地址,而只能将某台主机当作源地址使用,条件是这台主机还没有配置到一个标准的 IP 地址。这类地址仅此一个。

环回地址 IPv6 的环回地址是 0:0:0:0:0:0:0:1,可缩写为::1。它的作用和 IPv4 的环回地址一样。这类地址也是仅此一个。

多播地址 功能和 IPv4 的一样。这类地址占 IPv6 地址总数的 1/256。

本地站点单播地址 (cite-local unicast address) 有些单位的内部网络使用 TCP/IP 协议,但并没有连接到互联网上。连接在这样的内部网络上的主机都可以使用这种本地站点地址进行通信,但不能和互联网上的其他主机通信。这类地址占 IPv6 地址总数的 1/1024,其用途和和 IPv4 的专用地址是一样的。

本地链路单播地址 (link-local unicast address) 这种地址是在单一链路上使用的。当一个节点启用 IPv6 时就自动生成本地链路地址(请注意,这个节点现在并没有连接在某个网络上)。当需要把分组发往单一链路的设备而不希望该分组被转发到此链路范围以外的地方时,就可以使用这种特殊地址。这类地址占 IPv6 地址总数的 1/1024。

全球单播地址 IPv6 的这一类单播地址是使用得最多的一类。曾提出过多种方案来进一步划分这 128 位的单播地址。根据 2006 年发布的草案标准 RFC 4291 的建议,IPv6 单播地址的划分方法非常灵活,可以是如图 4-34 所示的任何一种。这就是说,可把整个的 128 位都作为一个节点的地址。也可用 n 位作为子网前缀,用剩下的 \((128 - n)\) 位作为接口标识符(相当于 IPv4 的主机号)。当然也可以划分为三级,用 n 位作为全球路由选择前缀,用 m 位作为子网前缀,而用剩下的 \((128 - n - m)\) 位作为接口标识符。

图 4-34 IPv6 的单播地址的几种划分方法

节点地址(128 bit)
子网前缀(n bit)接口标识符(128-n)bit
全球路由选择前缀(n bit)子网标识符(m bit)接口标识符(128-n-m)bit

4.5.3 从 IPv4 向 IPv6 过渡

由于现在整个互联网的规模太大,因此,“规定一个日期,从这一天起所有的路由器一律都改用 IPv6”,显然是不可行的。这样,向 IPv6 过渡只能采用逐步演进的办法,同时,还必须使新安装的 IPv6 系统能够向后兼容。

这就是说,IPv6 系统必须能够接收和转发 IPv4 分组,并且能够为 IPv4 分组选择路由。

下面介绍两种向 IPv6 过渡的策略,即使用双协议栈和使用隧道技术 [RFC 2473, 2529, 3056, 4038, 4213]。

1. 双协议栈

双协议栈 (dual stack) 是指在完全过渡到 IPv6 之前,使一部分主机(或路由器)同时装有 IPv4 和 IPv6 这两种协议栈。因此双协议栈主机(或路由器)既能够和 IPv6 的系统通信,又能够和 IPv4 的系统通信。双协议栈的主机(或路由器)记为 IPv6/IPv4,表明它同时具有 IPv6 地址和 IPv4 地址(如图 4-35 所示)。

4f96eba04c474c3f3d7435bd0d63840e3cb3ac473ad88146b9f2a3f78985bdb6.jpg

双协议栈的主机在和 IPv6 主机通信时采用 IPv6 地址,而和 IPv4 主机通信时则采用 IPv4 地址。但双协议栈主机怎样知道目的主机是采用哪一种地址呢?它是使用域名系统 DNS 来查询的。若 DNS 返回的是 IPv4 地址,则双协议栈的源主机就使用 IPv4 地址。但当 DNS 返回的是 IPv6 地址,源主机就使用 IPv6 地址。

双协议栈需要付出的代价太大,因为要安装上两套协议。因此在过渡时期,最好采用下面的隧道技术。

2. 隧道技术

向 IPv6 过渡的另一种方法是隧道技术 (tunneling)。图 4-36 给出了隧道技术的工作原理。这种方法的要点就是在 IPv6 数据报要进入 IPv4 网络时,把 IPv6 数据报封装成为 IPv4 数据报。现在整个的 IPv6 数据报变成了 IPv4 数据报的数据部分。这样的 IPv4 数据报从路由器 B 经过路由器 C 和 D,传送到 E,而原来的 IPv6 数据报就好像在 IPv4 网络的隧道中传输,什么都没有变化。当 IPv4 数据报离开 IPv4 网络中的隧道时,再把数据部分(即原来的 IPv6 数据报)交给主机的 IPv6 协议栈。图中的一条粗线表示在 IPv4 网络中好像有一个从 B 到 E 的 “IPv6 隧道”,路由器 B 是隧道的入口而 E 是出口。请注意,在隧道中传送的数据报的源地址是 B 而目的地址是 E。

175661d9c580fb5371dfd2a24cc80ea8321c422b364b6840e1f23bea69d06699.jpg

要使双协议栈的主机知道 IPv4 数据报里面封装的数据是一个 IPv6 数据报,就必须把 IPv4 首部的协议字段的值设置为 41(41 表示数据报的数据部分是 IPv6 数据报)。

4.5.4 ICMPv6

和 IPv4 一样,IPv6 也不保证数据报的可靠交付,因为互联网中的路由器可能会丢弃数据报。因此 IPv6 也需要使用 ICMP 来反馈一些差错信息。新的版本称为 ICMPv6,它比 ICMPv4 要复杂得多。地址解析协议 ARP 和网际组管理协议 IGMP 的功能都已被合并到 ICMPv6 中(如图 4-37 所示)。

1801b88a7b1de046238bdf04fed4e56a0d6de69579ef804b5a622211263504cc.jpg

643643329dc221ee662700b703bbeded1b25441509f057eb2aee9c24fd04bfc3.jpg

ICMPv6 是面向报文的协议,它利用报文来报告差错,获取信息,探测邻站或管理多播通信。ICMPv6 还增加了几个定义报文功能及含义的其他协议。在对 ICMPv6 报文进行归类时,不同的文献和 RFC 文档使用了不同的策略,有的把其中的一些报文定义为 ICMPv6 报文,而把另一些报文定义为邻站发现 ND (Neighbor-Discovery) 报文或多播听众交付 MLD (Multicast Listener Delivery) 报文。其实所有这些报文都应当是 ICMPv6 报文,只是功能和作用不同而已。因此我们把这些报文都列入 ICMPv6 的不同类别。使用这种分类方法的原因是所有这些报文都具有相同的格式,并且所有报文类型都由 ICMPv6 协议处理。其实,像 ND 和 MLD 这样的协议都是运行在 ICMPv6 协议之下的。基于这样的考虑,可把 ICMPv6 报文分类,如图 4-38 所示。请注意,邻站发现报文和组成员关系报文分别是在 ND 协议和 MLD 协议的控制下进行发送和接收的。

bbd82caf97cb088c5107dc4a9c09374c3322036e78a36430a86babdc02c30393.jpg

关于 ICMPv6 的进一步讨论可参阅 [FORO10],这里从略。

4.6 互联网的路由选择协议

本节将讨论几种常用的路由选择协议,也就是要讨论转发表中的路由是怎样得出的。按照 4.1.2 节所述的观点,路由选择协议属于网络层控制层面的内容。不过本节仍然按传统的思路进行讨论,也就是说,路由选择协议规定了互联网中有关的路由器应如何相互交换信息并生成出路由表。

4.6.1 有关路由选择协议的几个基本概念

1. 理想的路由算法

路由选择协议的核心就是路由算法,即需要何种算法来获得路由表中的各项目。一个理想的路由算法应具有如下的一些特点 [BELL86]:

一个实际的路由选择算法,应尽可能接近于理想的算法。在不同的应用条件下,对以

上提出的 6 个方面也可有不同的侧重。

应当指出,路由选择是个非常复杂的问题,因为它是网络中的所有节点共同协调工作的结果。其次,路由选择的环境往往是不断变化的,而这种变化有时无法事先知道,例如,网络中出了某些故障。此外,当网络发生拥塞时,就特别需要有能缓解这种拥塞的路由选择策略,但恰好在这种条件下,很难从网络中的各节点获得所需的路由选择信息。

倘若从路由算法能否随网络的通信量或拓扑自适应地进行调整变化来划分,则只有两大类,即静态路由选择策略与动态路由选择策略。静态路由选择也叫作非自适应路由选择,其特点是简单和开销较小,但不能及时适应网络状态的变化。对于很简单的小网络,完全可以采用静态路由选择,用人工配置每一条路由。动态路由选择也叫作自适应路由选择,其特点是能较好地适应网络状态的变化,但实现起来较为复杂,开销也比较大。因此,动态路由选择适用于较复杂的大网络。

2. 分层次的路由选择协议

互联网采用的路由选择协议主要是自适应的(即动态的)、分布式路由选择协议。由于以下两个原因,互联网采用分层次的路由选择协议:

为此,可以把整个互联网划分为许多较小的自治系统 (autonomous system),一般都记为 AS。自治系统 AS 是在单一技术管理下的许多网络、IP 地址以及路由器,而这些路由器使用一种自治系统内部的路由选择协议和共同的度量。每一个 AS 对其他 AS 表现出的是一个单一的和一致的路由选择策略 [RFC 4271]。这样,互联网就把路由选择协议划分为两大类,即:

自治系统之间的路由选择也叫作域间路由选择 (interdomain routing),而在自治系统内部的路由选择叫作域内路由选择 (intradomain routing)。

图 4-39 是两个自治系统互连在一起的示意图。每个自治系统自己决定在本自治系统内部运行哪一个内部路由选择协议(例如,可以是 RIP,也可以是 OSPF)。但每个自治系统都有一个或多个路由器(图中的路由器 \(R_{1}\)\(R_{2}\) )除运行本系统的内部路由选择协议外,还要运行自治系统间的路由选择协议(BGP-4)。

2dc8a8dcbcd62f88ba0c27bedea8821fd6b1b92af534a65bd1a31840c5aff394.jpg

这里我们要指出两点:

总之,使用分层次的路由选择方法,可将互联网的路由选择协议划分为:

对于比较大的自治系统,还可将所有的网络再进行一次划分。例如,可以构筑一个链路速率较高的主干网和许多速率较低的区域网。每个区域网通过路由器连接到主干网。当在一个区域内找不到目的站时,就通过路由器经过主干网到达另一个区域网,或者通过边界路由器到别的自治系统中去查找。下面对这两类协议分别进行介绍。

4.6.2 内部网关协议 RIP

1. 协议 RIP 的工作原理

RIP (Routing Information Protocol) 是内部网关协议 IGP 中最先得到广泛使用的协议 [RFC 1058],它的中文译名是路由信息协议。RIP 是一种分布式的基于距离向量的路由选择协议,是互联网的标准协议,其最大优点就是简单。

RIP 协议要求网络中的每一个路由器都要维护从它自己到其他每一个目的网络的距离记录(因此,这是一组距离,即 “距离向量”)。协议 RIP 将 “距离” 定义如下:

从一路由器到直接连接的网络的距离定义为 1。从一主机到非直接连接的网络的距离定义为所经过的路由器数加 1。“加 1” 是因为到达目的网络后就进行直接交付(不需要再经过路由器),而到直接连接的网络的距离已经定义为 1。

协议 RIP 的 “距离” \(^{①}\) 也称为 “跳数” (hop count),并且每经过一个网络,跳数就加 1。RIP 认为好的路由就是它通过的网络数目少,即 “距离短”。RIP 允许一条路径最多只能包含 15 个网络。因此 “距离” 等于 16 时即相当于不可达。可见 RIP 只适用于小型互联网。

例如在前面的图 4-7 中,主机 \(H_{1}\) 经过 5 个路由器连接到另一个主机 \(H_{2}\) ,中间经过了 6 个网络或经过 6 跳。或者说, \(H_{1}\)\(H_{2}\) 的距离是 6。在图中并没有画出网络。在讨论路由选择问题时,在主机和路由器之间或在路由器之间的网络,往往都用一条线段来表示。需要注意的是,到直接连接的网络的距离也可定义为 0。但这两种不同的定义对实现协议 RIP 并无影响,因为这对选择最佳路由的过程其实是一样的。

RIP 不能在两个网络之间同时使用多条路由。RIP 选择一条具有最少网络数的路由(即最短路由),哪怕还存在另一条高速(低时延)但网络数较多的路由。

本节讨论的 RIP 协议和下一节要讨论的 OSPF 协议,都是分布式路由选择协议。它们的共同特点就是每一个路由器都要不断地和其他一些路由器交换路由信息。我们一定要弄清以下三个要点,即和哪些路由器交换信息?交换什么信息?在什么时候交换信息?

协议 RIP 的特点是:

这里要强调一点:路由器在刚刚开始工作时,它的路由表是空的。然后路由器就得出到直接相连的几个网络的距离(这些距离定义为 1)。接着,每一个路由器也只和数目非常有限的相邻路由器交换并更新路由信息。但经过若干次的更新后,所有的路由器最终都会知道到达本自治系统中任何一个网络的最短距离和下一跳路由器的地址。

看起来协议 RIP 有些奇怪,因为 “我的路由表中的信息要依赖于你的,而你的信息又依赖于我的。” 然而事实证明,通过这样的方式 ——“我告诉别人一些信息,而别人又告诉我一些信息。我再把我知道的更新后的信息告诉别人,别人也这样把更新后的信息再告诉我”,最后在自治系统中所有的节点都得到了正确的路由选择信息。在一般情况下,协议 RIP 可以收敛,并且过程也较快。“收敛” 就是在自治系统中所有的节点都得到正确的路由选择信息的过程。

路由表中最主要的信息就是:到某个网络的距离(即最短距离),以及应经过的下一跳地址。路由表更新的原则是找出到每个目的网络的最短距离。这种更新算法又称为距离向量算法。下面就是协议 RIP 使用的距离向量算法。

2. 距离向量算法

对每一个相邻路由器发送过来的 RIP 报文,执行以下步骤:

若原来的路由表中没有目的网络 Net,则把该项目添加到路由表中(见解释 2)。

否则(即在路由表中有目的网络 Net,这时就再查看下一跳路由器地址)。

若下一跳路由器地址是 X,则把收到的项目替换原路由表中的项目(见解释 3)。

否则(即这个项目是:到目的网络 Net,但下一跳路由器不是 X)。

若收到的项目中的距离 d 小于路由表中的距离,则进行更新(见解释 4),

否则什么也不做(见解释 5)。

(3) 若 3 分钟还没有收到相邻路由器的更新路由表,则把此相邻路由器记为不可达的路由器,即把距离置为 16(距离为 16 表示不可达)。

(4) 返回。

上面给出的距离向量算法的基础就是 Bellman-Ford 算法(或 Ford-Fulkerson 算法)。这种算法的要点是这样的:

设 X 是节点 A 到 B 的最短路径上的一个节点。若把路径 A→B 拆成两段路径 A→X 和 X→B,则每一段路径 A→X 和 X→B 也都分别是节点 A 到 X 和节点 X 到 B 的最短路径。

下面是对上述距离向量算法的五点解释。

解释 1:这样做是为了便于进行本路由表的更新。假设从位于地址 X 的相邻路由器发来的 RIP 报文的某一个项目是:“Net2, 3, Y”,意思是 “我经过路由器 Y 到网络 Net2 的距离是 3”,那么本路由器就可推断出:“我经过 X 到网络 Net2 的距离应为 \(3 + 1 = 4\)”。于是,本路由器就把收到的 RIP 报文的这一个项目修改为 “Net2, 4, X”,作为下一步和路由表中原有项目进行比较时使用(只有比较后才能知道是否需要更新)。读者可注意到,收到的项目中的 Y 对本路由器是没有用的,因为 Y 不是本路由器的下一跳路由器地址。

解释 2:表明这是新的目的网络,应当加入到路由表中。例如,本路由表中没有到目的网络 Net2 的路由,那么在路由表中就要加入新的项目 “Net2, 4, X”。

解释 3:为什么要替换呢?因为这是最新的消息,要以最新的消息为准。到目的网络的距离有可能增大或减小,但也可能没有改变。例如,不管原来路由表中的项目是 “Net2, 3, X” 还是 “Net2, 5, X”,都要更新为现在的 “Net2, 4, X”。

解释 4:例如,若路由表中已有项目 “Net2, 5, P”,就要更新为 “Net2, 4, X”。因为到网络 Net2 的距离原来是 5,现在减到 4,更短了。

解释 5:若距离更大了,显然不应更新。若距离不变,更新后得不到好处,因此也不更新。

【例 4-4】已知路由器 \(R_{6}\) 有表 4-8 (a) 所示的路由表。现在收到相邻路由器 \(R_{4}\) 发来的路由更新信息,如表 4-8 (b) 所示。试更新路由器 \(R_{6}\) 的路由表。

表 4-8 (a) 路由器 \({\mathrm{R}}_{6}\) 的路由表

目的网络距离下一跳路由器
Net23 $R_{4}$
Net34 $R_{5}$
.........

表 4-8 (b) \({\mathrm{R}}_{4}\) 发来的路由更新信息

目的网络距离下一跳路由器
Net13 $R_1$
Net24 $R_2$
Net31直接交付

【解】如同路由器一样,我们不需要知道该网络的拓扑。

先把表 4-8 (b) 中的距离都加 1,并把下一跳路由器都改为 \(R_{4}\) ,得出表 4-8 (c)。

表 4-8 (c) 修改后的表 4-8 (b)

目的网络距离下一跳路由器
Net14 $R_{4}$
Net25 $R_{4}$
Net32 $R_{4}$

把这个表的每一行和表 4-8 (a) 进行比较。

第一行在表 4-8 (a) 中没有,因此要把这一行添加到表 4-8 (a) 中。

第二行的 Net2 在表 4-8 (a) 中有,且下一跳路由器也是 \(R_{4}\) 。因此要更新(距离增大了)。

第三行的 Net3 在表 4-8 (a) 中有,但下一跳路由器不同。于是就要比较距离。新的路由信息的距离是 2,小于原来表中的 4,因此要更新。

这样,得出更新后的 \(R_{6}\) 的路由表如表 4-8 (d) 所示。

表 4-8 (d) 路由器 \({\mathrm{R}}_{6}\) 更新后的路由表

目的网络距离下一跳路由器
Net14 $R_{4}$
Net25 $R_{4}$
Net32 $R_{4}$
.........

协议 RIP 让一个自治系统中的所有路由器都和自己的相邻路由器定期交换路由信息,并不断更新其路由表,使得从每一个路由器到每一个目的网络的路由都是最短的(即跳数最少)。这里还应注意:虽然所有的路由器最终都拥有了整个自治系统的全局路由信息,但由于每一个路由器的位置不同,它们的路由表当然也应当是不同的。

现在较新的 RIP 版本是 1998 年 11 月公布的 RIP2 [RFC 2453, STD57],新版本协议本身并无多大变化,但性能上有些改进。RIP2 可以支持无分类域间路由选择 CIDR。此外,RIP2 还提供简单的鉴别过程支持多播。

图 4-40 表明 RIP 报文作为运输层用户数据报 UDP 的数据部分进行传送(使用 UDP 的端口 520。端口的意义见 5.2.2 节)。

0724064390886b6c53d84149cb486565d46c474f83d58ea5bb7a06e990d34d2f.jpg

RIP 报文由首部和路由部分组成。在路由部分要填入自治系统号 ASN (Autonomous

System Number) \(^{①}\) ,这是考虑使 RIP 有可能收到本自治系统以外的路由选择信息。还要指出目的网络地址(包括网络的子网掩码)、下一跳路由器地址以及到此网络的距离。一个 RIP 报文最多可包括 25 个路由。如超过,必须再用一个 RIP 报文来传送。

3. 坏消息传播得慢

RIP 存在的一个问题是当网络出现故障时,要经过比较长的时间才能将此信息传送到所有的路由器。我们可以用图 4-41 的简单例子来说明。设三个网络通过两个路由器互连起来,并且都已建立了各自的路由表。图中路由器交换的信息只给出了我们感兴趣的一行内容。路由器 \(R_{1}\) 中的 “Net1, 1, 直接” 表示 “到网 Net1 的距离是 1, 直接交付”。路由器 \(R_{2}\) 中的 “Net1, 2, \(R_{1}\)” 表示 “到网 Net1 的距离是 2, 下一跳经过 \(R_{1}\)”。

20d34e34c2b69941e0131e8fde8a7bf16a20137c64574db1f99a538088fe0004.jpg

现在假定路由器 \(R_{1}\) 到网 Net1 的链路出了故障, \(R_{1}\) 无法到达网 Net1。于是路由器 \(R_{1}\) 把到网 Net1 的距离改为 16,表示不可达,因而在 \(R_{1}\) 的路由表中的相应项目变为 “Net1, 16, 直接”。但是,很可能要经过 30 秒钟后 \(R_{1}\) 才把更新信息发送给 \(R_{2}\) 。然而 \(R_{2}\) 可能已经先把自己的路由表发送给了 \(R_{1}\) ,其中有 “Net1, 2, \(R_{1}\)” 这一项。

\(R_{1}\) 收到 \(R_{2}\) 的更新报文后,误认为可经过 \(R_{2}\) 到达网 Net1,于是把收到的路由信息 “Net1, 2, \(R_{1}\)” 修改为:“Net1, 3, \(R_{2}\)”,表明 “我到网 Net1 的距离是 3,下一跳经过 \(R_{2}\)”,并把更新后的信息发送给 \(R_{2}\)

同理, \(R_{2}\) 接着又更新自己的路由表为 “Net1, 4, \(R_{1}\)”,以为 “我到网 Net1 距离是 4,下一跳经过 \(R_{1}\)”。

这样的更新一直继续下去,直到 \(R_{1}\)\(R_{2}\) 到网 Net1 的距离都增大到 16 时, \(R_{1}\)\(R_{2}\) 才知道原来网 Net1 是不可达的。协议 RIP 的这一特点叫作:好消息传播得快,而坏消息传播得慢。网络出故障的传播时间往往较长(例如数分钟)。这是 RIP 的一个主要缺点。

但如果一个路由器发现了更短的路由,那么这种更新信息就传播得很快。

为了使坏消息传播得更快些,可以采取多种措施。例如,让路由器记录收到某特定路由信息的接口,而不让同一路由信息再通过此接口向反方向传送。

总之,协议 RIP 最大的优点就是实现简单,开销较小。但协议 RIP 的缺点也较多。首先,RIP 限制了网络的规模,它能使用的最大距离为 15(16 表示不可达)。其次,路由器之间交换的路由信息是路由器中的完整路由表,因而随着网络规模的扩大,开销也就增加。最后,“坏消息传播得慢”,使更新过程的收敛时间过长。因此,对于规模较大的网络就应当使用下一节所述的 OSPF 协议。然而目前在规模较小的网络中,使用协议 RIP 的仍占多数。

4.6.3 内部网关协议 OSPF

1. 协议 OSPF 的基本特点

这个协议的名字是开放最短路径优先 OSPF (Open Shortest Path First)。它是为克服 RIP 的缺点在 1989 年开发出来的。OSPF 的原理很简单,但实现起来却较复杂。“开放” 表明 OSPF 协议不是受某一家厂商控制,而是公开发表的。“最短路径优先” 是因为使用了 Dijkstra 提出的最短路径算法 SPF。现在使用的协议 OSPF 是第二个版本 OSPFv2 [RFC 2328, STD54]。关于 OSPF 可参阅专著 [MOY98], [HUIT95]。

请注意:OSPF 只是一个协议的名字,它并不表示其他的路由选择协议不是 “最短路径优先”。实际上,所有的在自治系统内部使用的路由选择协议(包括协议 RIP)都是要寻找一条最短的路径。

OSPF 最主要的特征就是使用链路状态协议 (link state protocol),而不是像 RIP 那样的距离向量协议。协议 OSPF 的特点是:

(1) 向本自治系统中所有路由器发送信息。这里使用的方法是洪泛法 (flooding),这就是路由器通过所有输出端口向所有相邻的路由器发送信息。而每一个相邻路由器又再将此信息发往其所有的相邻路由器(但不再发送给刚刚发来信息的那个路由器)。这样,最终整个区域中所有的路由器都得到了这个信息的一个副本。更具体的做法后面还要讨论。我们应注意,协议 RIP 是仅仅向自己相邻的几个路由器发送信息。

(2) 发送的信息就是与本路由器相邻的所有路由器的链路状态,但这只是路由器所知道的部分信息。所谓 “链路状态” 就是说明本路由器都和哪些路由器相邻 \(^{①}\) ,以及该链路的 “度量”(metric)。OSPF 将这个 “度量” 用来表示费用、距离、时延、带宽,等等。这些都由网络管理人员来决定,因此较为灵活。有时为了方便就称这个度量为 “代价”。我们应注意,对于协议 RIP,发送的信息是:“到所有网络的距离和下一跳路由器”。

(3) 当链路状态发生变化或每隔一段时间(如 30 分钟),路由器向所有路由器用洪泛法发送链路状态信息。

从上述的前两点可以看出,OSPF 和 RIP 的工作原理相差较大。

由于各路由器之间频繁地交换链路状态信息,因此所有的路由器最终都能建立一个链路状态数据库 (link-state database),这个数据库实际上就是全网的拓扑结构图。这个拓扑结构图在全网范围内是一致的(这称为链路状态数据库的同步)。因此,每一个路由器都知道全网共有多少个路由器,以及哪些路由器是相连的,其代价是多少,等等。每一个路由器使用链路状态数据库中的数据,构造出自己的路由表(例如,使用 Dijkstra 的最短路径路由算法)。我们注意到,协议 RIP 的每一个路由器虽然知道到所有的网络的距离以及下一跳路由器,但却不知道全网的拓扑结构(只有到了下一跳路由器,才能知道再下一跳应当怎样走)。

OSPF 的链路状态数据库能较快地进行更新,使各个路由器能及时更新其路由表。OSPF 的更新过程收敛得快是其重要优点。

为了使 OSPF 能够用于规模很大的网络,OSPF 将一个自治系统再划分为若干个更小的范围,叫作区域 (area)。图 4-42 就表示一个自治系统划分为四个区域。每一个区域都有一个 32 位的区域标识符(用点分十进制形式表示)。当然,一个区域也不能太大,在一个区域内的路由器最好不超过 200 个。

划分区域的好处就是把利用洪泛法交换链路状态信息的范围局限于每一个区域而不是整个的自治系统,这就减少了整个网络上的通信量。在一个区域内部的路由器只知道本区域的完整网络拓扑,而不知道其他区域的网络拓扑的情况。为了使每一个区域能够和本区域以外的区域进行通信,OSPF 使用层次结构的区域划分。在上层的区域叫作主干区域 (backbone area)。主干区域的标识符规定为 0.0.0.0。主干区域的作用是用来连通其他在下层的区域。从其他区域来的信息都由区域边界路由器 (area border router) 进行概括。在图 4-42 中,路由器 \(R_{3}\)\(R_{4}\)\(R_{7}\) 都是区域边界路由器,而显然,每一个区域至少应当有一个区域边界路由器。在主干区域内的路由器叫作主干路由器 (backbone router),如 \(R_{3}\)\(R_{4}\)\(R_{5}\)\(R_{6}\)\(R_{7}\) 。一个主干路由器可以同时是区域边界路由器,如 \(R_{3}\)\(R_{4}\)\(R_{7}\) 。在主干区域内还要有一个路由器专门和本自治系统外的其他自治系统交换路由信息。这样的路由器叫作自治系统边界路由器(如图 4-42 中的 \(R_{6}\) )。

d48234c60e08cf012b12228d20a4a7e9f5f69f06aa7199747909ac464492fa42.jpg

采用分层次划分区域的方法虽然使交换信息的种类增多了,同时也使 OSPF 协议更加复杂了。但这样做却能使每一个区域内部交换路由信息的通信量大大减小,因而使 OSPF 协议能够用于规模很大的自治系统中。这里,我们再一次地看到划分层次在网络设计中的重要性。

除了以上的几个基本特点外,OSPF 还具有下列的一些特点:

(1) OSPF 允许管理员给每条路由指派不同的代价。例如,高带宽的卫星链路对于非实时的业务可设置为较低的代价,但对于时延敏感的业务就可设置为非常高的代价。因此,OSPF 对于不同类型的业务可计算出不同的路由。链路的代价可以是 1 至 65535 中的任何一个无量纲的数,因此十分灵活。商用的网络在使用 OSPF 时,通常根据链路带宽来计算链路

的代价。这种灵活性是 RIP 所没有的。

2. OSPF 的五种分组类型

OSPF 共有以下五种分组类型:

OSPF 分组是作为 IP 数据报的数据部分来传送的(如图 4-43 所示)。OSPF 不用 UDP 而是直接用 IP 数据报传送(其 IP 数据报首部的协议字段值为 89)。OSPF 构成的数据报很短。这样做可减少路由信息的通信量。数据报很短的另一好处是可以不必将长的数据报分片传送。分片传送的数据报只要丢失一个,就无法组装成原来的数据报,而整个数据报就必须重传。

8591fd1c1f6fa87a09e59e7788608a503c482fa0aa196fda7f5f6d0d36094577.jpg

OSPF 规定,每两个相邻路由器每隔 10 秒钟要交换一次问候分组。这样就能确知哪些邻站是可达的。对相邻路由器来说,“可达” 是最基本的要求,因为只有可达邻站的链路状态信息才存入链路状态数据库(路由表就是根据链路状态数据库计算出来的)。在正常情况下,网络中传送的绝大多数 OSPF 分组都是问候分组。若有 40 秒钟没有收到某个相邻路由器发来的问候分组,则可认为该相邻路由器是不可达的,应立即修改链路状态数据库,并重新计算路由表。

其他的四种分组都是用来进行链路状态数据库的同步。所谓同步就是指不同路由器的链路状态数据库的内容是一样的。两个同步的路由器叫作 “完全邻接的”(fully adjacent) 路由器。不是完全邻接的路由器表明它们虽然在物理上是相邻的,但其链路状态数据库并没有达到一致。

当一个路由器刚开始工作时,它只能通过问候分组得知它有哪些相邻的路由器在工作,以及将数据发往相邻路由器所需的 “代价”。如果所有的路由器都把自己的本地链路状态信息对全网进行广播,那么各路由器只要将这些链路状态信息综合起来就可得出链路状态数据库。但这样做开销太大,因此 OSPF 采用下面的办法。

OSPF 让每一个路由器用数据库描述分组和相邻路由器交换本数据库中已有的链路状态摘要信息。摘要信息主要就是指出有哪些路由器的链路状态信息(以及其序号)已经写入了数据库。经过与相邻路由器交换数据库描述分组后,路由器就使用链路状态请求分组,向对方请求发送自己所缺少的某些链路状态项目的详细信息。通过一系列的这种分组交换,全网同步的链路数据库就建立了。

在网络运行的过程中,只要一个路由器的链路状态发生变化,该路由器就要使用链路状态更新分组,用洪泛法向全网更新链路状态。OSPF 使用的是可靠的洪泛法,其要点如图 4-44 所示。设路由器 R 用洪泛法发出链路状态更新分组。图中用一些小的箭头表示更新分组。第一次先发给相邻的三个路由器。这三个路由器将收到的分组再进行转发时,要将其上游路由器除外。可靠的洪泛法是在收到更新分组后要发送确认(收到重复的更新分组只需要发送一次确认)。图中的空心箭头表示确认分组。

c4ca44d5c4717d0f61eab4941dee2c47d649d3b20bcd41c3118c60ce398ea2fc.jpg

为了确保链路状态数据库与全网的状态保持一致,OSPF 还规定每隔一段时间,如 30 分钟,要刷新一次数据库中的链路状态。

由于一个路由器的链路状态只涉及与相邻路由器的连通状态,因而与整个互联网的规模并无直接关系。因此当互联网规模很大时,OSPF 协议要比距离向量协议 RIP 好得多。由于 OSPF 没有 “坏消息传播得慢” 的问题,据统计,其响应网络变化的时间小于 100 ms。

\(N\) 个路由器连接在一个以太网上,则每个路由器要向其他 \((N - 1)\) 个路由器发送链路状态信息,因而共有 \(N(N - 1)\) 个链路状态要在这个以太网上传送。OSPF 协议对这种多点接入的局域网采用了指定的路由器 (designated router) 的方法,使广播的信息量大大减少。指定的路由器代表该局域网上所有的链路向连接到该网络上的各路由器发送状态信息。

4.6.4 外部网关协议 BGP

1. 协议 BGP 的主要特点

在外部网关协议(或边界网关协议)BGP 中,现在使用的是第 4 个版本 BGP-4(常简写为 BGP)。虽然最近陆续发布了不少 BGP-4 的更新文档,

76f234b465d1ebab751a097aaf05b57555fb50e84edc7f27dbce381c432d66aa.jpg

但目前 BGP-4 仍然是草案标准 [RFC 4271]。协议 BGP 对互联网非常重要。我们知道,前面两节所介绍的路由选择协议 RIP 和 OSPF,都只能在一个自治系统 AS 内部工作。因此,若没有协议 BGP,那么分布在全世界数以万计的 AS 都将是一个个没有联系的孤岛。正是由于有了 BGP 这种黏合剂,才使得这么多的 AS 孤岛能够连接成一个完整的互联网。从这个意义上考虑,协议 BGP 应当是所有路由选择协议中最为重要的一个。

我们首先应当弄清,在不同自治系统 AS 之间的路由选择为什么不能使用前面讨论过的内部网关协议,如 RIP 或 OSPF?

我们知道,内部网关协议(如 RIP 或 OSPF)主要是设法使数据报在一个 AS 中尽可能有效地从源站传送到目的站。在一个 AS 内部也不需要考虑其他方面的策略。然而 BGP 使用的环境却不同。这主要是因为以下的两个原因:

第一,互联网的规模太大,使得自治系统 AS 之间路由选择非常困难。连接在互联网主干网上的路由器,必须对任何有效的 IP 地址都能在转发表中找到匹配的网络前缀。目前在互联网的主干网路由器中,一个转发表的项目数甚至可达到 50 万个网络前缀。如果使用链路状态协议,则每一个路由器必须维持一个很大的链路状态数据库。对于这样大的主干网用 Dijkstra 算法计算最短路径时花费的时间也太长。另外,由于自治系统 AS 各自运行自己选定的内部路由选择协议,并使用本 AS 指明的路径度量,因此,当一条路径通过几个不同 AS 时,要想对这样的路径计算出有意义的代价是不太可能的。例如,对某 AS 来说,代价为 1000 可能表示一条比较长的路由。但对另一 AS,代价为 1000 却可能表示不可接受的坏路由。因此,对于自治系统 AS 之间的路由选择,要用 “代价” 作为度量来寻找最佳路由也是很不现实的。比较合理的做法是在自治系统之间交换 “可达性” 信息(即 “可到达” 或 “不可到达”)。例如,告诉相邻路由器:“到达网络前缀 N 可经过自治系统 AS \(_{x}\)”。

第二,自治系统 AS 之间的路由选择必须考虑有关策略。由于相互连接的网络的性能相差很大,根据最短距离(即最少跳数)找出来的路径,可能并不合适。也有的路径的使用代价很高或很不安全。还有一种情况,如自治系统 AS \(_{1}\) 要发送数据报给自治系统 AS \(_{2}\) ,本来最好是经过自治系统 AS \(_{3}\) 。但 AS \(_{3}\) 不愿意让这些数据报通过本自治系统的网络,即使 AS \(_{1}\) 愿意付一定的费用。但另一方面,自治系统 AS \(_{3}\) 愿意让某些相邻自治系统的数据报通过自己的网络,特别是对那些付了服务费的某些自治系统更是如此。因此,自治系统之间的路由选择协议应当允许使用多种路由选择策略。这些策略包括政治、安全或经济方面的考虑。例如,我国国内的站点在互相传送数据报时不应经过国外兜圈子,特别是,不要经过某些对我国的安全有威胁的国家。这些策略都是由网络管理人员对每一个路由器进行设置的,但这些策略并不是自治系统之间的路由选择协议本身。还可举出一些策略的例子,如:“仅在到达下列这些地址时才经过 AS \(_{x}\)”,“AS \(_{x}\) 和 AS \(_{y}\) 相比时应优先通过 AS \(_{x}\)”,等等。显然,使用这些策

略是为了找出较好的路由而不是最佳路由。

由于上述情况,边界网关协议 BGP 只能是力求选择出一条能够到达目的网络前缀且比较好的路由(不能兜圈子),而并非要计算出一条最佳路由。这里所说的 BGP 路由,是指经过哪些自治系统 AS 可以到达目的网络前缀。当然,这选择出的比较好的路由,也有时不严格地称为最佳路由。BGP 采用了路径向量 (path vector) 路由选择协议,它与距离向量协议(如 RIP)和链路状态协议(如 OSPF)都有很大的区别。

2. BGP 路由

在一个自治系统 AS 中有两种不同功能的路由器,即边界路由器(或边界网关)和内部路由器。一个 AS 至少要有一个边界路由器和相邻 AS 的边界路由器直接相连。在讨论协议 BGP 时,应特别注意边界路由器的作用。正是由于有了边界路由器,AS 之间才能利用协议 BGP 交换可达性路由信息。

当两个边界路由器(例如图 4-45 (a) 中的 \(R_{1}\)\(R_{2}\) )进行通信时,必须先建立 TCP 连接(端口号为 179,TCP 连接将在第 5 章中学习),这种 TCP 连接又称为半永久性连接(即双方交换完信息后仍然保持着连接状态)。像 \(R_{1}\)\(R_{2}\) 之间的这种连接称为 eBGP 连接,但通常就简称为 eBGP,e 表示外部 external。现在,边界路由器 \(R_{1}\) 可通过 eBGP 向对等端 \(R_{2}\) 发送 BGP 路由 “X, AS \(_{1}\) , R \(_{1}\)”,意思是 “从 \(R_{1}\) 经 AS \(_{1}\) 可到达 X”。这样,通过 eBGP 连接,AS \(_{2}\) 中的边界路由器 \(R_{2}\) 就知道了到达 AS \(_{1}\) 中的前缀 X 的 BGP 路由。

e344e9ec8ef4adbcdd55d73cf8d2580b0c51ff8c6b8190cc3c85fc6b71ae7853.jpg

但是,仅有边界路由器 \(\mathbb{R}_2\) 知道 “到 \(\mathrm{AS}_1\) 的前缀 X 的 BGP 路由” 是远远不够的。边界路由器 \(\mathbb{R}_2\) 应当把获得的 BGP 路由,再转发给 AS 内部的其他路由器。为此,协议 BGP 规定,在 AS 内部,两个路由器之间还需要建立 iBGP(也就是 iBGP 连接,i 表示内部 internal),iBGP 也使用 TCP 连接传送 BGP 报文。图 4-45 (b) 中表示边界路由器 \(\mathbb{R}_2\) 在三个 iBGP 连接上,向 \(\mathrm{AS}_2\) 内部的其他三个路由器转发自己收到的 BGP 路由。至此, \(\mathrm{AS}_2\) 内的所有路由器都知道了这条 BGP 路由信息。由此可见,协议 BGP 并非仅运行在 AS 之间,而且也要运行在 AS 的内部。

协议 BGP 规定,在一个 AS 内部所有的 iBGP 必须是全连通的。即使两个路由器之间没

有物理连接,但它们之间仍然有 iBGP 连接(如图 4-46 所示)。

02ddb9cca9f40ce210a0045036a99a8e075817f8dbca1c1d4f8999511dac460f.jpg

这里要说明一下。图 4-45 (a) 中的边界路由器 \(R_{1}\) 通告给边界路由器 \(R_{2}\) 的 BGP 路由可能有很多条(在图中只画出了一条)。但 \(R_{2}\) 根据本 AS 管理员所规定的策略,可以拒绝某些路由(收到这种路由后即删除掉),而在 iBGP 连接上仅转发符合规定策略的 BGP 路由。

我们还需要指出,虽然 eBGP 和 iBGP 的最后一个字母 P 是代表 “协议 (Protocol)”,但 eBGP 和 iBGP 并不是两个不同的协议。根据 RFC 4271,eBGP 是在不同 AS 的两个对等端之间的 BGP 连接,而 iBGP 是同一 AS 的两个对等端之间的 BGP 连接。在这两种不同连接上传送的 BGP 报文,都遵循同样的协议 BGP,使用同样的报文格式和具有同样的属性类型。唯一的不同点就是在发送 BGP 路由通告时的规则有所不同。这就是,从 eBGP 对等端收到的 BGP 路由,可通过 iBGP 告诉同一 AS 内的对等端。反过来也是可以的,即从 iBGP 对等端收到的 BGP 路由,可通过 eBGP 告诉在不同 AS 的对等端。但是,从 iBGP 对等端收到 BGP 路由,不能转告给同一个 AS 内不同 iBGP 的对等端。

图 4-47 形象地说明了 eBGP 和 iBGP 的作用。图中画出了四个自治系统 AS,每一个 AS 都必须运行本 AS 选择的内部网关协议 IGP,例如 OSPF 或 RIP。而协议 BGP 是在 iBGP 连接和 eBGP 连接之上运行的。

e05a96c90bcf536e41c2e153ea4efc44c3e6eb740d2de654dcb97ad0be757e00.jpg

后面我们经常要讲到 BGP 路由,因此下面介绍一下 BGP 路由的一般格式。前面例子中的 BGP 路由正是按照这种格式书写的。

BGP 路由 = “前缀,BGP 属性” = “前缀,AS-PATH, NEXT-HOP”

前缀的意思很明确,就是通告的 BGP 路由终点(子网前缀)。

BGP 属性有好几种类型,但最重要两个就是这里列出的 AS-PATH 和 NEXT-HOP。

AS-PATH(自治系统路径)是通告的 BGP 路由所经过的自治系统。BGP 路由每经过一个 AS,就将其自治系统号 ASN 加入到 AS-PATH 中(本节在举例中没有使用具体的 ASN 数字号码,而是用 \(AS_{1}, AS_{2}\) 等符号来表示不同的 AS)。从这里可以清楚地看出,“BGP 路由” 必须指出通过哪些自治系统 AS,但不指出路由中途要通过哪些路由器。

NEXT-HOP(下一跳)是通告的 BGP 路由起点。

细心的读者会发现,路由问题并未都解决完。例如,在图 4-48 中 AS₂ 内的路由器 R₄ 在收到 BGP 路由 “X, AS₁, R₁” 后,知道了 “从 R₁ 出发就能到达 AS₁ 中的前缀 X”。但路由器

\(R_{4}\) 应当怎样构造自己的转发表呢?这需要经过两次递归查找。

6379e4308b4bb592f3677507e00199810f6d82d0181321c6da2fbd507c71ea8d.jpg

首先, \(R_{4}\) 要把这条 BGP 路由的起点进行转换。原来的 BGP 路由是 “\(R_{1}\rightarrow X\)”,路由的起点 \(R_{1}\) 并不在 \(AS_{2}\) 中。 \(AS_{2}\) 中的路由器都不能识别 \(R_{1}\) 。因此现在 \(R_{4}\) 要把 BGP 路由的起点改为 \(R_{1}\) 的对等端 \(R_{2}\) ,把 BGP 路由变为 “\(R_{2}\rightarrow R_{1}\rightarrow X\)”。由于 \(R_{2}\) 位于 \(AS_{2}\) 中,因此 \(AS_{2}\) 里面的所有路由器都能把分组转发到 \(R_{2}\) ,然后就能再经过 \(R_{1}\) ,最后到达前缀 X。

其次, \(R_{4}\) 要利用内部网关协议,找到从 \(R_{4}\)\(R_{2}\) 的最佳路由中的下一跳。在本例中,查出下一跳是 \(R_{3}\) 。于是 \(R_{4}\) 在转发表中增加了到达前缀 X 的下一跳是 \(R_{3}\) 这一项目。

前缀匹配下一跳注释
XR3转发表中有下一跳 R3 表示前缀 X 可达。

用类似的方法,路由器 \(R_{3}\) 也在自己的转发表中增加了到达前缀 X 的项目。

前缀匹配下一跳注释
X $R_{2}$ 转发表中有下一跳 $R_{2}$ 表示前缀 X 可达。

这样,路由器 \(R_{4}\) 只要收到要到达前缀 X 的分组,都按照 \(R_{4} \rightarrow R_{3} \rightarrow R_{2} \rightarrow R_{1} \rightarrow X\) 的路径,最后到达前缀 X。

总之,每一个路由器收到一条新的 BGP 路由通告后,必须经过上述步骤,才能在自己的转发表中,增加到达终点的 “下一跳” 的相应项目。

在实际的转发表中,“前缀匹配” 项目都用 CIDR 记法表示。由于路由器有两个以上的接口,因此 “下一跳” 项目用进入该路由器的接口的 IP 地址来表示。在讲解协议 BGP 的原理时,我们就用更简洁的符号来表示。

3. 三种不同的自治系统 AS

在互联网中自治系统 AS 的数量非常之多,其连接图也是相当复杂的。但归纳起来,可以把 AS 划分为图 4-49 中所示的三大类,即末梢 AS (stub AS)、穿越 AS (transit AS) 和对等 AS (peering AS)。

9db7c9d5aaeeaf51ba03b3f5f43bf64e5f06f0c22f8a0e4c40b7b7c62634ec82.jpg

末梢 AS 是比较小的 AS(如图中的 \(AS_{4}\)\(AS_{5}\)\(AS_{6}\) ),其特点是这些 AS 或者把分组发送给其直接连接的 AS,或者从其直接连接的 AS 接收分组,但不会把来自其他 AS 的分组再转发到另一个 AS。末梢 AS 必须向所连接的 AS 付费才能发送或接收分组。图中链路旁边的人民币符号 ¥ 表示需要对转发分组付费。

末梢 AS 也可以同时连接到两个或两个以上的 AS(如图 4-49 中的 AS \(_{5}\) )。这种末梢 AS 就称为多归属 AS (multihomed AS)。多归属 AS 可以增加连接的可靠性,因为若有一条连接出现故障,那么还有另一条连接可用。作为末梢 AS 的 AS \(_{5}\) 不能把 AS \(_{3}\) 发送过来的分组转发到 AS \(_{2}\) 。同理,AS \(_{5}\) 也不能把 AS \(_{2}\) 发送过来的分组转发到 AS \(_{3}\) 。这就是说,末梢 AS 不是穿越 AS,它不允许分组穿越自己的自治系统。末梢 AS \(_{5}\) 也不能把(AS \(_{5}\) →AS \(_{2}\) →AS \(_{4}\) )这样的 BGP 路由信息通告给 AS \(_{3}\) 。如果 AS \(_{3}\) 有分组要转发给 AS \(_{4}\) ,可以通过对等 AS \(_{2}\) 转发,但不能通过末梢 AS \(_{5}\)

如图 4-49 所示的穿越 AS \(_{1}\) 往往是拥有很好的高速通信干线的主干 AS,其任务就是为其他的 AS 有偿转发分组。通常都会有很多的 AS 连接到穿越 AS 上。

对等 AS(如图 4-49 中的 \(AS_{2}\)\(AS_{3}\) )是经过事先协商的两个 AS,彼此之间的发送或接收分组都不收费,这样大家转发分组都比较方便。

这里我们要强调一下,BGP 路由必须避免兜圈子的出现。现观看图 4-49 所示的几个自治系统 AS。AS₃ 向 AS₁ 通告可到达 AS₆ 的 BGP 路由中的属性 AS-PATH 是 [AS₃ AS₆],AS₁ 在收到的 BGP 路由的属性 AS-PATH 中的最前面,添加上自己的 AS,通报给 AS₂:[AS₁ AS₃ AS₆]。AS₂ 收到 BGP 路由后,向 AS₃ 通报 BGP 路由属性 AS-PATH 是 [AS₂ AS₁ AS₃ AS₆]。当 AS₃ 收到 BGP 路由后,检查属性 AS-PATH 序列中已经有了自己的 AS₃,如果 AS₃ 接受这个路由,并添加上本 AS 号,则将在属性 AS-PATH 中出现两个 AS₃(见有灰色底纹的两个 AS₃):[AS₃ AS₂ AS₁ AS₃ AS₆]。这就构成了一个兜圈子的 BGP 路由,因此 AS₃ 应立即删除此 BGP 路由,因而避免了兜圈子路由的出现。请记住,在属性 AS-PATH 中不允许出现相同的 AS。

\(AS_{3}\) 还可向 \(AS_{2}\) 通报可到达 \(AS_{6}\) 的另一条 BGP 路由,其 AS-PATH 是 \([AS_{3} AS_{6}]\) 。因此 \(AS_{2}\) 知道有两条 BGP 路由可到达 \(AS_{6}\) ,其 AS-PATH 是 \([AS_{2} AS_{1} AS_{3} AS_{6}]\)\([AS_{2} AS_{3} AS_{6}]\)

4. BGP 的路由选择

假如从一个 AS 到另外一个 AS 中的前缀 X 只有一条 BGP 路由,那么就不存在选择 BGP 路由的问题,因为这时 BGP 路由是唯一的。

但如果到前缀 X 有两条或更多的 BGP 路由可供选择,那么就应当根据以下的原则,按照这里给出的先后顺序,选择一条较好的 BGP 路由。

- 本地偏好 LOCAL-PREF (LOCAL PREFERENCE) 值最高的路由要首先选择。

在 BGP 路由中的属性里面有一个选项叫作本地偏好,在属性中记为 LOCAL-PREF。本地偏好也就是本地优先,“本地” 的意思是指,从本 AS 开始的、到同一个前缀的不同 BGP 路由中,挑选一个较好的(即偏好值最高的)路由。这可由路由器管理员或网络管理员根据政治上或经济上的策略来设置。

例如在图 4-50 中, \(AS_{1}\) 分别用高速和低速链路连接到 \(AS_{2}\)\(AS_{3}\) ,并从这两个 AS 获悉,可通过 \(AS_{2}\)\(AS_{3}\) 到达 \(AS_{4}\) 。但 \(AS_{1}\) 认为,若有分组要从 \(AS_{1}\) 转发到 \(AS_{4}\) ,应优先选择路由器 \(R_{1}\) 离开 \(AS_{1}\) 。于是就把从 \(R_{1}\) 离开 \(AS_{1}\) 的 BGP 路由的属性 LOCAL-PREF 值设为 300,而把从 \(R_{2}\) 离开 \(AS_{1}\) 的 BGP 路由的 LOCAL-PREF 值设为 200。这一信息通过 iBGP 通告 \(AS_{1}\) 内部的所有路由器。这样,凡是有分组要转发到 \(AS_{4}\) ,都优先选择从 \(R_{1}\) 离开 \(AS_{1}\)

bf02b310e62a2ea7a96ab22e3fda4af23d738766ca0cd6dd451556c4aca11932.jpg

但是,即使所有的通信量都通过这条高速链路,使得链路负荷过重,协议 BGP 也无法把一些负载调整到负载较轻的那条低速链路上。

如果从几条 BGP 路由中找不出本地偏好值最高的路由,则执行下一条。

- 选择具有 AS 跳数最少的路由。

现观察图 4-51 的例子。从 AS \(_{1}\) 到 AS \(_{5}\) 共有两条 BGP 路由,即 AS \(_{1}\) →AS \(_{2}\) →AS \(_{3}\) →AS \(_{5}\) 和 AS \(_{1}\) →AS \(_{4}\) →AS \(_{5}\) 。根据选择具有 AS 跳数最少的原则,我们应选择只通过 1 个 AS 的 BGP 路由,即 AS \(_{1}\) →AS \(_{4}\) →AS \(_{5}\) 。但是没有想到,分组在 AS \(_{4}\) 中反而要经过更多次数的转发(或许 AS \(_{4}\) 是个很大的 AS),可能要花费更长的时间。可见选择经过 AS 数量最少的路由 AS \(_{1}\) →AS \(_{4}\) →AS \(_{5}\) 未必更好。这个例子再次说明了协议 BGP 无法选择出最佳路由。

1d8aa9628764550aab545c83106cc219695572935b39221687505c71fa9540b9.jpg

- 使用热土豆路由选择算法。

如果按前两种方法都无法选择最好的路由,那么就在要进入 BGP 路由的 AS,执行热土豆路由选择算法。例如在图 4-52 中,从 AS \(_{1}\) 出发,共有两条 BGP 路由可到达 AS \(_{3}\)

BGP 路由 1: 从 \(R_{3}\) 离开 \(AS_{1}\) ,然后进入 \(AS_{2}\) ,再到 \(AS_{3}\)

BGP 路由 2:从 \(R_{4}\) 离开 \(AS_{1}\) ,然后进入 \(AS_{2}\) ,再到 \(AS_{3}\)

77469cf7a8f0f38bd905ed16f88882bfbd44804aa685332efc7e8bff3aa53f90.jpg

假定这两条 BGP 路由的本地偏好相同,同时所经过的 AS 个数也相同。在这种情况下,

AS \(_{1}\) 中的每一个路由器,就应采用热土豆路由选择算法。这种算法把分组比喻为烫手的热土豆,要尽快地转发出去。对于图 4-52 的例子,就是要使分组尽快离开 AS \(_{1}\) ,而不考虑从哪个路由器离开 AS \(_{1}\) 。或者说,要让分组经过最少的转发次数离开本 AS。这时要使用内部网关协议(如协议 OSPF 或 RIP)。对于不同的路由器,得出的选择结果是不同的。

例如,对于 \(AS_{1}\) 中的路由器 \(R_{1}\) ,若要使转发的分组尽快离开 \(AS_{1}\) ,应选择 \(R_{4}\) 作为其下一跳,因此应选择 BGP 路由 2。这样, \(R_{1}\) 的转发路径应当是: \(R_{1} \rightarrow R_{4} \rightarrow BGP\) 路由 2。

同理,对于 \(R_{2}\) ,若要使转发的分组尽快离开 \(AS_{1}\) ,应选择 \(R_{3}\) 作为其下一跳,因此应选择 BGP 路由 1。这样, \(R_{2}\) 的转发路径应当是: \(R_{2} \rightarrow R_{3} \rightarrow BGP\) 路由 1。

- 选择路由器 BGP 标识符的数值最小的路由。

当以上几种方法都无法找出最好的 BGP 路由时,就可使用 BGP 标识符来选择路由。在 BGP 进行交互的报文中,其首部有一 4 字节的字段,叫作 BGP 标识符,记为 BGP ID。这个字段被赋予一个无符号整数作为运行 BGP 的路由器的唯一标识符。具有多个接口的路由器有多个 IP 地址。BGP ID 就使用该路由器的 IP 地址中数值最大的一个。

5. BGP 的四种报文

在协议 BGP 刚运行时,BGP 连接的对等端要相互交换整个的 BGP 路由表。但以后只需要在 BGP 路由发生变化时,才更新有变化的部分。这样做对节省网络带宽和减少路由器的处理开销方面都有好处。

在 RFC 4271 中规定了 BGP-4 的四种报文:

OPEN 报文是两个路由器之间建立了 TCP 连接后接着就必须发送的报文。OPEN 报文的作用是相互识别对方,协商一些协议参数(如计时器的时间)。收到 OPEN 报文的路由器,就发回 KEEPALIVE 报文表示接受建立 BGP 连接。

UPDATE 报文是 BGP 协议的核心,用来撤销它以前曾经通知过的路由,或宣布增加新的路由。撤销路由可以一次撤销许多条,但增加新路由时,每个更新报文只能增加一条。

虽然 BGP 连接的两端建立了 TCP 连接,传输报文是可靠的,但 TCP 上层的 BGP 是否始终正常工作还无法确知。在对等端之间定期传送 BGP 路由表是不可取的,因为 BGP 路由表往往过于庞大,这样做会使网络的通信量过大。因此协议 BGP 采用的方法是让 BGP 连接的两个对等端之间,周期性地交换 KEEPALIVE 报文,以表示协议工作正常。KEEPALIVE 报文只包含 BGP 报文的通用首部(19 字节长),因此不会在网络上产生多少开销。

每个路由器都有一个保持时间计时器 (Hold Timer)。路由器每收到一个 BGP 报文,这个计时器就重置一次,继续从 0 开始计时。如果在商定的保持时间内没有收到对等端发来的任何一种 BGP 报文,就认为对方已经不能工作了。发送 KEEPALIVE 报文的时间间隔取为双方事先商定的保持时间 (Hold Time) 的 1/3。例如,在 BGP 连接建立阶段,双方商定保持时间为 180 秒,那么 KEEPALIVE 报文就每隔 60 秒发送一次。如果两个对等端选择的保持时间不一致,就选择数值较小的一个作为彼此使用的保持时间。保持时间也可选择为 0。在这种情况下就永远不发送 KEEPALIVE 报文,表明这条 BGP 连接总是正常工作的。

BGP 可以很容易地解决距离向量路由选择算法中的 “坏消息传播得慢” 这一问题。当某

个路由器或链路出故障时,可以从不止一个邻站获得路由信息,因此很容易选择出新的路由。

在 ASN 升级到 4 字节后,号码 ASN 的范围从 0~65535 扩大到了 0~4294967295。这样就在互联网中存在两种不同的 BGP 报文。旧 BGP 报文使用 2 字节 ASN,而新 BGP 报文使用 4 字节的 ASN,这时 BGP 路由中的路径属性记为 AS4-PATH。使用新的和旧的 BGP 报文的路由器若要进行通信,必须解决如何正确识别其 ASN 的问题 [RFC 6793]。

BGP 报文是作为 TCP 报文的数据部分来传送的(如图 4-53 所示)。四种类型的 BGP 报文具有同样的首部。

74be1b9dc478d4805578856bbdac851ec74f45e3b97975ebb937d1b62bbe63d4.jpg

在讨论完路由选择之后,我们再来介绍路由器的构成。

4.6.5 路由器的构成

1. 路由器的结构

路由器是一种具有多个输入端口和多个输出端口的专用计算机,其任务是转发分组。从路由器某个输入端口收到的分组,按照分组要去的目的

地(即目的网络),把该分组从路由器的某个合适的输出端口转发给下一跳路由器。下一跳路由器也按照这种方法处理分组,直到该分组到达终点为止。路由器的转发分组正是网络层的主要工作。图 4-54 给出了一种典型的路由器的构成框图。

aab09fcdd744839282c8500a15c0ae8464ee4c2fa798494c0f236b279b9a9d91.jpg

从图 4-54 可以看出,整个的路由器结构可划分为两大部分:路由选择部分和分组转发部分。

路由选择部分也叫作控制部分,或控制层面,其核心构件是路由选择处理机。路由选择处理机的任务是根据所选定的路由选择协议构造出路由表,同时经常或定期地和相邻路由

器交换路由信息而不断地更新和维护路由表。

分组转发部分是本节所要讨论的问题,也就是数据层面,它由三部分组成:交换结构、一组输入端口和一组输出端口(请注意:这里的端口就是硬件接口)。小型路由器的端口只有几个。但某些 ISP 使用的边缘路由器的高速 10 Gbit/s 端口,则可以有多达几百个之多。下面分别讨论每一部分的组成。例如,Juniper(瞻博网络)公司的边缘路由器 MX2020 的 10 Gbit/s 端口就有 960 个。路由器整个的系统容量为 80 Tbit/s。

交换结构 (switching fabric) 又称为交换组织,它的作用就是根据转发表 (forwarding table) 对分组进行处理,将某个输入端口进入的分组从一个合适的输出端口转发出去。交换结构本身就是一种网络,但这种网络完全包含在路由器之中,因此交换结构可看成是 “在路由器中的网络”。

请注意 “转发” 和 “路由选择” 是有区别的。在互联网中,“转发” 就是路由器根据转发表把收到的 IP 数据报从路由器合适的端口转发出去。“转发” 仅仅涉及一个路由器。但 “路由选择” 则涉及很多路由器,路由表则是许多路由器协同工作的结果。这些路由器按照复杂的路由算法,得出整个网络的拓扑变化情况,因而能够动态地改变所选择的路由,并由此构造出整个的路由表。路由表一般仅包含从目的网络到下一跳(用 IP 地址表示)的映射,而转发表是从路由表得出的。转发表必须包含完成转发功能所必需的信息。这就是说,在转发表的每一行必须包含从要到达的目的网络到输出端口和某些 MAC 地址信息(如下一跳的以太网地址)的映射。将转发表和路由表用不同的数据结构实现会带来一些好处,这是因为在转发分组时,转发表的结构应当使查找过程最优化,但路由表则需要对网络拓扑变化的计算最优化。路由表总是用软件实现的,但转发表则可用特殊的硬件来实现。请读者注意,在讨论路由选择的原理时,往往不去区分转发表和路由表的区别,而可以笼统地都使用路由表这一名词。

在图 4-54 中,路由器的输入和输出端口里面都各有三个方框,用方框中的 1, 2 和 3 分别代表物理层、数据链路层和网络层的处理模块。物理层进行比特的接收。数据链路层则按照链路层协议接收传送分组的帧。在把帧的首部和尾部剥去后,分组就被送入网络层的处理模块。若接收到的分组是路由器之间交换路由信息的分组(如 RIP 或 OSPF 分组等),则把这种分组送交路由器的路由选择部分中的路由选择处理机。若接收到的是数据分组,则按照分组首部中的目的地址查找转发表,根据得出的结果,分组就经过交换结构到达合适的输出端口。一个路由器的输入端口和输出端口就做在路由器的线路接口卡上。

输入端口中的查找和转发功能在路由器的交换功能中是最重要的。为了使交换功能分散化,往往把复制的转发表放在每一个输入端口中(如图 4-54 中的虚线箭头所示)。路由选择处理机负责对各转发表的副本进行更新。这些副本常称为 “影子副本”(shadow copy)。分散化交换可以避免在路由器中的某一点上出现瓶颈。

以上介绍的查找转发表和转发分组的概念虽然并不复杂,但在具体的实现中还会遇到不少困难。问题就在于路由器必须以很高的速率转发分组。最理想的情况是输入端口的处理速率能够跟上线路把分组传送到路由器的速率。这种速率称为线速(line speed 或 wire speed)。可以粗略地估算一下。设线路是 OC-48 链路,即 2.5 Gbit/s。若分组长度为 256 字节,那么线速就应当达到每秒能够处理 100 万以上的分组。现在常用 Mpps(百万分组每秒)为单位来说明一个路由器对收到的分组的处理速率有多高。在路由器的设计中,怎样提高查找转发表的速率是一个十分重要的研究课题。

当一个分组正在查找转发表时,后面又紧跟着从这个输入端口收到另一个分组。这个后到的分组就必须在队列中排队等待,因而产生了一定的时延。图 4-55 给出了在输入端口的队列中排队的分组的示意图。

f1852f91e46f162b3e7751c1ec1252954aef4a60319ea8d09970c3723b7a43b6.jpg

我们再来观察在输出端口上的情况(如图 4-56 所示)。输出端口从交换结构接收分组,然后把它们发送到路由器外面的线路上。在网络层的处理模块中设有一个缓存区,实际上它就是一个队列。当交换结构传送过来的分组的速率超过输出链路的发送速率时,来不及发送的分组就必须暂时存放在这个队列中。数据链路层处理模块把分组加上链路层的首部和尾部,交给物理层后发送到外部线路。

a715e79c6919c33c7034d8e790e6871397ca0ca75be264e6700b4a1960c8a4c5.jpg

从以上的讨论可以看出,分组在路由器的输入端口和输出端口都可能会在队列中排队等候处理。若分组处理的速率赶不上分组进入队列的速率,则队列的存储空间最终必定减少到零,这就使后面再进入队列的分组由于没有存储空间而只能被丢弃。以前我们提到过的分组丢失就是发生在路由器中的输入或输出队列产生溢出的时候。当然,设备或线路出故障也可能使分组丢失。

2. 交换结构

交换结构是路由器的关键构件 [KURO17]。正是这个交换结构把分组从一个输入端口转移到某个合适的输出端口。实现这样的交换有多种方法,图 4-57 给出了三种常用的交换方法。输入端口是 A,B 和 C,输出端口是 X,Y 和 Z。下面简单介绍它们的特点。

最早使用的路由器就是利用普通的计算机,用计算机的 CPU 作为路由器的路由选择处理机。路由器的输入和输出端口的功能和传统的操作系统中的 I/O 设备一样。当路由器的某个输入端口收到一个分组时,就用中断方式通知路由选择处理机。然后分组就从输入端口复制到存储器中。路由器处理机从分组首部提取目的地址,查找路由表,再将分组复制到合适的输出端口的缓存中。若存储器的带宽(读或写)为每秒 M 个分组,那么路由器的交换速率(即分组从输入端口传送到输出端口的速率)一定小于 M/2。这是因为存储器对分组的读

和写需要花费的时间是同一个数量级。

449078ceb0f1234515b511d4186828cc273333c553c53685b859847cb930d53f.jpg

f9391624cc30ce7853142f4af6c948c1f4137d7a823535378e1f4e04f94c0a8a.jpg

bbdf1c076309b49ba39bbd21cc6e7046cd3057077e2a81a0c826496027e413ae.jpg

许多现代的路由器也通过存储器进行交换,图 4-57 (a) 的示意图表示分组通过存储器进行交换。与早期的路由器的区别就是,目的地址的查找和分组在存储器中的缓存都是在输入端口中进行的。思科 (Cisco) 公司的 Catalyst 8500 系列交换机(有的公司把路由器也称为交换机)就采用了共享存储器的方法。

图 4-57 (b) 是通过总线进行交换的示意图。采用这种方式时,数据报从输入端口通过共享总线直接传送到合适的输出端口,而不需要路由选择处理机的干预。但是,由于总线是共享的,因此在同一时间只能有一个分组在总线上传送。当分组到达输入端口时若发现总线忙(因为总线正在传送另一个分组),则被阻塞而不能通过交换结构,并在输入端口排队等待。因为每一个要转发的分组都要通过这一条总线,因此路由器的转发带宽就受总线速率的限制。现代的技术已经可以将总线的带宽提高到能够满足小型企业网的需求。例如,思科公司的 6500 路由器用来交换分组的背板总线速率已达到 32 Gbit/s。

图 4-57 (c) 画的是通过纵横交换结构 (crossbar switch fabric) 进行交换。这种交换机构常称为互连网络 (interconnection network),它有 2N 条总线,可以使 N 个输入端口和 N 个输出端口相连接,这取决于相应的交叉节点是使水平总线和垂直总线接通还是断开。当输入端口收到一个分组时,就将它发送到与该输入端口相连的水平总线上。若通向所要转发的输出端口的垂直总线是空闲的,则在这个节点将垂直总线与水平总线接通,然后把该分组转发到这个输出端口。例如,一个分组到达输入端口 A,应转发到输出端口 Y。这时交换结构的控制器就把总线 A 和 Y 的交叉节点闭合,因此分组就从输入端口 A 传送到了输出端口 Y。请注意,如果与此同时还有一个分组要从输入端口 B 转发到输出端口 Z,那么也可同时进行,因为 A → Y 和 B → Z 的转发是使用不同的总线的转发。和前两种交换机制不同,这种纵横交换结构是一种无阻塞的交换结构,其特点是分组可以转发到任何一个输出端口,只要这个输出端口没有被别的分组占用。如果这个输出端口(即对应的垂直总线)已被占用(有另一个分组正在转发到同一个输出端口),那么后到达的分组就必须在输入端口排队等待。采用这种交换方式的路由器例子如思科公司的 12000 系列交换路由器,其互连网络的速率达 60 Gbit/s。

4.7 IP 多播

4.7.1 IP 多播的基本概念

1988 年 Steve Deering 首次在其博士学位论文中提出 IP 多播的概念。1992 年 3 月 IETF 在互联网范围首次试验 IETF 会议声音的多播,当时有 20 个网点可同时听到会议的声音。IP 多播是需要在互联网上增加更多的智能才能提供的一种服务。现在 IP 多播(multicast,以前曾译为组播)已成为互联网的一个热门课题。这是由于有许多的应用需要由一个源点发送到许多个终点,即一对多的通信。例如,实时信息的交付(如新闻、股市行情等)、软件更新、交互式会议等。随着互联网的用户数目的急剧增加,以及多媒体通信的开展,有更多的业务需要多播来支持。

与单播相比,在一对多的通信中,多播可大大节约网络资源。图 4-58 (a) 是视频服务器用单播方式向 90 台主机传送同样的视频节目。为此,需要发送 90 个单播,即同一个视频分组要发送 90 个副本。图 4-58 (b) 是视频服务器用多播方式向属于同一个多播组的 90 个成员传送节目。这时,视频服务器只需把视频分组当作多播数据报来发送,并且只需发送一次。路由器 \(R_{1}\) 在转发分组时,需要把收到的分组复制成 3 个副本,分别向 \(R_{2}, R_{3}\)\(R_{4}\) 各转发 1 个副本。当分组到达目的局域网时,由于局域网具有硬件多播功能,因此不需要复制分组,在局域网上的多播组成员都能收到这个视频分组。

9a73de78411f3ea566b184b2bab74a2bcb90eaa0c6ec67720c96cb4fab07f512.jpg

66df145491b3c975565ef423807c2da6ac32eea4f5fc3da091e1c28338f15e4d.jpg

当多播组的主机数很大时(如成千上万个),采用多播方式就可明显地减轻网络中各种资源的消耗。在互联网范围的多播要靠路由器来实现,这些路由器必须增加一些能够识别多播数据报的软件。能够运行多播协议的路由器称为多播路由器 (multicast router)。多播路由器当然也可以转发普通的单播 IP 数据报。

为了适应交互式音频和视频信息的多播,从 1992 年起,在互联网上开始试验虚拟的多播主干网 MBONE (Multicast Backbone On the InterNEt)。MBONE 可把分组传播给地点分散但属于一个组的许多台主机。现在多播主干网已经有了相当大的规模。

在互联网上进行多播就叫作 IP 多播。IP 多播所传送的分组需要使用多播 IP 地址。

我们知道,在互联网中每一台主机必须有一个全球唯一的 IP 地址。如果某台主机现在想接收某个特定多播组的分组,那么怎样才能使这个多播数据报传送到这台主机?

显然,这个多播数据报的目的地址一定不能写入这台主机的 IP 地址。这是因为在同一时间可能有成千上万台主机加入到同一个多播组。多播数据报不可能在其首部写入这样多的主机的 IP 地址。在多播数据报的目的地址写入的是多播组的标识符,然后设法让加入到这个多播组的主机的 IP 地址与多播组的标识符关联起来。

其实多播组的标识符就是 IP 地址中的 D 类地址。D 类 IP 地址的前四位是 1110,因此 D 类地址范围是 224.0.0.0 到 239.255.255.255。我们就用每一个 D 类地址标志一个多播组。这样,D 类地址共可标志 \(2^{28}\) 个多播组,也就是说,在同一时间可以允许有超过 2.6 亿的多播组在互联网上运行。多播数据报也是 “尽最大努力交付”,不保证一定能够交付多播组内的所有成员。因此,多播数据报和一般的 IP 数据报的区别就是它使用 D 类 IP 地址作为目的地址,并且首部中的协议字段值是 2,表明使用网际组管理协议 IGMP。

显然,多播地址只能用于目的地址,而不能用于源地址。此外,对多播数据报不产生 ICMP 差错报文。因此,若在 PING 命令后面键入多播地址,将永远不会收到响应。

IP 多播可以分为两种。一种是只在本局域网上进行硬件多播,另一种则是在互联网的范围进行多播。前一种虽然比较简单,但很重要,因为现在大部分主机都是通过局域网接入到互联网的。在互联网上进行多播的最后阶段,还是要把多播数据报在局域网上用硬件多播交付多播组的所有成员(如图 4-58 (b) 所示)。下面就先讨论这种硬件多播。

4.7.2 在局域网上进行硬件多播

互联网号码指派管理局 IANA 拥有的以太网地址块的高 24 位为 00-00-5E,因此 TCP/IP 协议使用的以太网地址块的范围是从 00-00-5E-00-00-00 到 00-00-5E-FF-FF-FF。在第 3 章 3.3.5 节已讲过,以太网 MAC 地址字段中的第 1 字节的最低位为 1 时即为多播地址,这种多播地址数占 IANA 分配到的地址数的一半。但 IANA 只拿出 \(2^{23}\) 个地址,即 01-00-5E-00-00-00 到 01-00-5E-7F-FF-FF 的地址作为以太网多播地址。或者说,在 48 位的多播地址中,前 25 位都固定不变,只有后 23 位可用作多播。但 D 类 IP 地址可供分配的有 28 位。这 28 位中只有后 23 位才映射以太网多播地址中的后 23 位,因此是多对一的映射关系(如图 4-59 所示),即 28 位中的前 5 位不能用来构成以太网多播地址。例如,IP 多播地址 224.128.64.32(即 E0-80-40-20)和另一个 IP 多播地址 224.0.64.32(即 E0-00-40-20)转换成以太网的多播地址都是 01-00-5E-00-40-20。因此收到多播数据报的主机,还要在 IP 层利用 IP 数据报首部的 IP 地址进行过滤,把不是本主机要接收的数据报丢弃。

b1d565546da842047d52609976406a9f6f4d1bcc201bcb9086b2516e46ee67ed.jpg

下面就讨论进行 IP 多播所需要的协议。

4.7.3 网际组管理协议 IGMP 和多播路由选择协议

1. IP 多播需要两种协议

图 4-60 是在互联网上传送多播数据报的例子。图中标有 IP 地址的四台主机都参加了一个多播组,其组地址是 226.15.37.123。显然,多播数据报

5cd0f223082c65f8a3093353dd5844498d9c5256ec12795c8f276d062e140225.jpg

应当传送到路由器 \(R_{1}, R_{2}\)\(R_{3}\) ,而不应当传送到路由器 \(R_{4}\) ,因为与 \(R_{4}\) 连接的局域网上现在没有这个多播组的成员。但这些路由器又怎样知道多播组的成员信息呢?这就要利用一个协议,叫作网际组管理协议 IGMP (Internet Group Management Protocol)。

40f9ee70d959de60c968d1527097f5ce51ac6d025ca2d778213ca0c178f29879.jpg

图 4-60 强调了 IGMP 的本地使用范围。请注意,IGMP 并非在互联网范围内对所有多播组成员进行管理的协议。IGMP 不知道 IP 多播组包含的成员数,也不知道这些成员都分布在哪些网络上。IGMP 协议是让连接在本地局域网上的多播路由器知道本局域网上是否有主机(严格讲,是主机上的某个进程)参加或退出了某个多播组。

显然,仅有 IGMP 协议是不能完成多播任务的。连接在局域网上的多播路由器还必须和互联网上的其他多播路由器协同工作,以便把多播数据报用最小代价传送给所有的组成员。这就需要使用多播路由选择协议。

然而多播路由选择协议要比单播路由选择协议复杂得多。我们可以通过一个简单的例子来说明。我们假定图 4-61 中有两个多播组。多播组 \(M_{1}\) 的成员有主机 A, B 和 C,而多播组 \(M_{2}\) 的成员有主机 D, E 和 F。这些主机分布在三个网络上 (\(N_{1}, N_{2}\)\(N_{3}\))。

6675d59e70900d491352f1fc08296e683ffeb29cca9f88692845f38f7c5dc3f3.jpg

路由器 R 不应当向网络 \(N_{3}\) 转发多播组 \(M_{1}\) 的分组,因为网络 \(N_{3}\) 上没有多播组 \(M_{1}\) 的成员。但是每一台主机可以随时加入或离开一个多播组。例如,如果主机 G 现在加入了多播组 \(M_{1}\) ,那么从这时起,路由器 R 就必须也向网络 \(N_{3}\) 转发多播组 \(M_{1}\) 的分组。这就是说,多播转发必须动态地适应多播组成员的变化(这时网络拓扑并未发生变化)。请注意,单播路由选择通常在网络拓扑发生变化时才需要更新路由。

再看一种情况。主机 E 和 F 都是多播组 \(M_{2}\) 的成员。当 E 向 F 发送多播数据报时,路由器 R 把这个多播数据报转发到网络 \(N_{3}\) 。但当 F 向 E 发送多播数据报时,路由器 R 则把多播数据报转发到网络 \(N_{2}\) 。如果路由器 R 收到来自主机 A 的多播数据报(A 不是多播组 \(M_{2}\) 的成员,但也可向多播组发送多播数据报),那么路由器 R 就应当把多播数据报转发到 \(N_{2}\)\(N_{3}\) 。由此可见,多播路由器在转发多播数据报时,不能仅仅根据多播数据报中的目的地址,而是还要考虑这个多播数据报从什么地方来和要到什么地方去。

还有一种情况。主机 G 没有参加任何多播组,但 G 却可向任何多播组发送多播数据报。例如,G 可向多播组 \(M_{1}\)\(M_{2}\) 发送多播数据报。主机 G 所在的局域网上可以没有任何多播组的成员。显然,多播数据报所经过的许多网络,也不一定非要有多播组成员。总之,多播数据报可以由没有加入多播组的主机发出,也可以通过没有组成员接入的网络。

正因为如此,IP 多播就成为比较复杂的问题。下面介绍这两种协议的要点。

2. 网际组管理协议 IGMP

IGMP 已有了三个版本。1989 年公布的 RFC 1112(IGMPv1)早已成为了互联网的标准协议(STD 5)。2002 年 10 月公布的建议标准 IGMPv3 是最新的 [RFC 3376]。

和网际控制报文协议 ICMP 相似,IGMP 使用 IP 数据报传递其报文(即 IGMP 报文加上 IP 首部构成 IP 数据报),但它也向 IP 提供服务。因此,我们不把 IGMP 看成是一个单独的协议,而是属于整个网际协议 IP 的一个组成部分。

从概念上讲,IGMP 的工作可分为两个阶段。

第一阶段:当某台主机加入新的多播组时,该主机应向多播组的多播地址发送一个 IGMP 报文,声明自己要成为该组的成员。本地的多播路由器收到 IGMP 报文后,还要利用多播路由选择协议把这种组成员关系转发给互联网上的其他多播路由器。

第二阶段:组成员关系是动态的。本地多播路由器要周期性地探询本地局域网上的主机,以便知道这些主机是否还继续是组的成员。只要有一台主机对某个组响应,那么多播路由器就认为这个组是活跃的。但一个组在经过几次的探询后仍然没有一台主机响应,多播路由器就认为本网络上的主机已经都离开了这个组,因此也就不再把这个组的成员关系转发给其他的多播路由器。

IGMP 设计得很仔细,避免了多播控制信息给网络增加大量的开销。IGMP 采用的一些具体措施如下:

(4) 在 IGMP 的询问报文中有一个数值 \(N\) ,它指明一个最长响应时间(默认值为 10 秒)。当收到询问时,主机在 0 到 \(N\) 之间随机选择发送响应所需经过的时延。因此,若一台主机同时参加了几个多播组,则主机对每一个多播组选择不同的随机数。对应于最小时延的响应最先发送。

(5) 同一个组内的每一台主机都要监听响应,只要有本组的其他主机先发送了响应,自己就可以不再发送响应了。这样就抑制了不必要的通信量。

多播路由器并不需要保留组成员关系的准确记录,因为向局域网上的组成员转发数据报是使用硬件多播。多播路由器只需要知道网络上是否至少还有一台主机是本组成员即可。实际上,对询问报文每一个组只需有一台主机发送响应。

如果一台主机上有多个进程都加入了某个多播组,那么这台主机对发给这个多播组的每个多播数据报只接收一个副本,然后给主机中的每一个进程发送一个本地复制的副本。

最后我们还要强调指出,多播数据报的发送者和接收者都不知道(也无法找出)一个多播组的成员有多少,以及这些成员是哪些主机。互联网中的路由器和主机都不知道哪个应用进程将要向哪个多播组发送多播数据报,因为任何应用进程都可以在任何时候向任何一个多播组发送多播数据报,而这个应用进程并不需要加入这个多播组。

IGMP 的报文格式可参阅有关文档 [RFC 3376],这里从略。

3. 多播路由选择协议

虽然在 TCP/IP 中 IP 多播协议已成为建议标准,但多播路由选择协议(用来在多播路由器之间传播路由信息)则尚未标准化。

在多播过程中一个多播组中的成员是动态变化的。例如在收听网上某个广播节目时,随时会有主机加入或离开这个多播组。多播路由选择实际上就是要找出以源主机为根节点的多播转发树。在多播转发树上,每一个多播路由器向树的叶节点方向转发收到的多播数据报,但在多播转发树上的路由器不会收到重复的多播数据报(即多播数据报不应在互联网中兜圈子)。不难看出,对不同的多播组对应于不同的多播转发树。同一个多播组,对不同的源点也会有不同的多播转发树。

已有了多种实用的多播路由选择协议,它们在转发多播数据报时使用了以下的三种方法:

(1) 洪泛与剪除。这种方法适合于较小的多播组,而所有的组成员接入的局域网也是相邻接的。一开始,路由器转发多播数据报使用洪泛的方法(这就是广播)。为了避免兜圈子,采用了叫作反向路径广播 RPB (Reverse Path Broadcasting) 的策略。RPB 的要点是:每一个路由器在收到一个多播数据报时,先检查数据报是否是从源点经最短路径传送来的。进行这种检查很容易,只要从本路由器寻找到源点的最短路径上(之所以叫作反向路径,因为在计算最短路径时是把源点当作终点的)的第一个路由器是否就是刚才把多播数据报送来的路由器。若是,就向所有其他方向转发刚才收到的多播数据报(但进入的方向除外),否则就丢弃而不转发。如果本路由器有好几个相邻路由器都处在到源点的最短路径上(也就是说,存在几条同样长度的最短路径),那么只能选择一条最短路径,选择的准则就是看这几条最短路径中的相邻路由器谁的 IP 地址最小。图 4-62 的例子说明了这一概念。

aa28b70b023564ecbfebb138ccc61d4dda58de7c9b06d39df9a4fe75f679739d.jpg

为简单起见,在图 4-62 中的网络用路由器之间的链路来表示。我们假定各路由器之间的距离都是 1。路由器 \(R_{1}\) 收到源点发来的多播数据报后,向 \(R_{2}\)\(R_{3}\) 转发。 \(R_{2}\) 发现 \(R_{1}\) 就在自己到源点的最短路径上,因此向 \(R_{3}\)\(R_{4}\) 转发收到的数据报。 \(R_{3}\) 发现 \(R_{2}\) 不在自己到源点的最短路径上,因此丢弃 \(R_{2}\) 发来的数据报。其他路由器也这样转发。 \(R_{7}\) 到源点有两条最短路径: \(R_{7} \rightarrow R_{4} \rightarrow R_{2} \rightarrow R_{1} \rightarrow\) 源点; \(R_{7} \rightarrow R_{5} \rightarrow R_{3} \rightarrow R_{1} \rightarrow\) 源点。我们再假定 \(R_{4}\) 的 IP 地址比 \(R_{5}\) 的 IP 地址小,所以我们只使用前一条最短路径。因此 \(R_{7}\) 只转发 \(R_{4}\) 传过来的数据报,而丢弃 \(R_{5}\) 传过来的数据报。最后就得出了用来转发多播数据报的多播转发树(图中用粗线表示),以后就按这个多播转发树来转发多播数据报。这样就避免了多播数据报兜圈子,同时每一个路由器也不会接收重复的多播数据报。

如果在多播转发树上的某个路由器发现它的下游树枝(即叶节点方向)已没有该多播组的成员,就应把它和下游的树枝一起剪除。例如,在图 4-62 中虚线椭圆表示剪除的部分。当某个树枝有新增加的组成员时,可以再接入到多播转发树上。

(2) 隧道技术 (tunneling)。隧道技术适用于多播组的位置在地理上很分散的情况。例如在图 4-63 中,网 \(N_{1}\) 和网 \(N_{2}\) 都支持多播。现在 \(N_{1}\) 中的主机向 \(N_{2}\) 中的一些主机进行多播。但路由器 \(R_{1}\)\(R_{2}\) 之间的网络并不支持多播,因而 \(R_{1}\)\(R_{2}\) 不能按多播地址转发数据报。为此,路由器 \(R_{1}\) 就对多播数据报进行再次封装,即再加上普通数据报首部,使之成为向单一目的站发送的单播 (unicast) 数据报,然后通过 “隧道”(tunnel) 从 \(R_{1}\) 发送到 \(R_{2}\)

cbb2c51bec18be82b7a10f03d80b73c316a9f3d7475ca23bf8d0fa5ff70a19e0.jpg

单播数据报到达路由器 \(R_{2}\) 后,再由路由器 \(R_{2}\) 剥去其首部,使它又恢复成原来的多播数据报,继续向多个目的站转发。这一点和英吉利海峡隧道运送汽车的情况相似。英吉利海峡隧道不允许汽车在隧道中行驶。但是,可以把汽车放置在隧道中行驶的电气火车上来通过隧道。过了隧道后,汽车又可以继续在公路上行驶。这种使用隧道技术传送数据报又叫作 IP

中的 IP (IP-in-IP)。

(3) 基于核心的发现技术。这种方法对于多播组的大小在较大范围内变化时都适合。这种方法是对每一个多播组 G 指定一个核心 (core) 路由器,给出它的 IP 单播地址。核心路由器按照前面讲过的方法创建出对应于多播组 G 的转发树。如果有一个路由器 \(R_{1}\) 向这个核心路由器发送数据报,那么它在途中经过的每一个路由器都要检查其内容。当数据报到达参加了多播组 G 的路由器 \(R_{2}\) 时, \(R_{2}\) 就处理这个数据报。如果 \(R_{1}\) 发出的是一个多播数据报,其目的地址是 G 的组地址, \(R_{2}\) 就向多播组 G 的成员转发这个多播数据报。如果 \(R_{1}\) 发出的数据报是一个请求加入多播组 G 的数据报, \(R_{2}\) 就把这个信息加到它的路由中,并用隧道技术向 \(R_{1}\) 转发每一个多播数据报的一个副本。这样,参加到多播组 G 的路由器就从核心向外增多了,扩大了多播转发树的覆盖范围。

目前还没有在整个互联网范围使用的多播路由选择协议。下面是一些建议使用的多播路由选择协议。

距离向量多播路由选择协议 DVMRP (Distance Vector Multicast Routing Protocol) 是在互联网上使用的第一个多播路由选择协议 [RFC 1075]。由于在 UNIX 系统中实现 RIP 的程序叫作 routed,所以在 routed 的前面加表示多播的字母 m,叫作 mrouted,它使用 DVMRP 在路由器之间传播路由信息。

基于核心的转发树 CBT (Core Based Tree) [RFC 2189, 2201]。这个协议使用核心路由器作为转发树的根节点。一个大的自治系统 AS 可划分为几个区域,每一个区域选择一个核心路由器(也叫作中心路由器 center router,或汇聚点路由器 rendezvous router)。

开放最短通路优先的多播扩展 MOSPF (Multicast extensions to OSPF) [RFC 1585]。这个协议是单播路由选择协议 OSPF 的扩充,使用于一个机构内。MOSPF 使用多播链路状态路由选择创建出基于源点的多播转发树。

协议无关多播 - 稀疏方式 PIM-SM (Protocol Independent Multicast-Sparse Mode) [RFC 7761, STD83]。这是唯一成为互联网标准的一个协议,它使用和 CBT 同样的方法构成多播转发树。采用 “协议无关” 这个名词是强调:虽然在建立多播转发树时是使用单播数据报来和远程路由器联系的,但这并不要求使用特定的单播路由选择协议。这个协议适用于组成员的分布非常分散的情况。

协议无关多播 - 密集方式 PIM-DM (Protocol Independent Multicast-Dense Mode) [RFC 3973]。这个协议适用于组成员的分布非常集中的情况,例如组成员都在一个机构之内。PIM-DM 不使用核心路由器,而是使用洪泛方式转发数据报。

4.8 虚拟专用网 VPN 和网络地址转换 NAT

4.8.1 虚拟专用网 VPN

由于 IP 地址的紧缺,一个机构能够申请到的 IP 地址数往往远小于本机构所拥有的主机数。考虑到互联网并不很安全,一个机构内也并不需要把所有的主机接入到外部的互联网。实际上,在许多情况下,很多主机主要还是和本机构内的其他主机进行通信(例如,在大型商场或宾馆中,有很多用于营业和管理的计算机。显然这些计算机并不都需要和互联网相连)。假定在一个机构内部的计算机通信也是采用 TCP/IP 协议,那么从原则上讲,对于这些仅在机构内部使用的计算机就可以由本机构自行分配其 IP 地址。这就是说,让这些计算机使用仅在本机构有效的 IP 地址(这种地址称为本地地址),而不需要向互联网的管理机构申请全球唯一的 IP 地址(这种地址称为全球地址)。这样就可以大大节约宝贵的全球 IP 地址资源。

但是,如果任意选择一些 IP 地址作为本机构内部使用的本地地址,那么在某种情况下可能会引起一些麻烦。例如,有时机构内部的某台主机需要和互联网连接,那么这种仅在内部使用的本地地址就有可能和互联网中某个 IP 地址重合,这样就会出现地址的二义性问题。

为了解决这一问题,RFC 1918 指明了一些专用地址 (private address)。这些地址只能用于一个机构的内部通信,而不能用于和互联网上的主机通信。换言之,专用地址只能用作本地地址而不能用作全球地址。在互联网中的所有路由器,对目的地址是专用地址的数据报一律不进行转发。2013 年 4 月,RFC 6890 全面地给出了所有特殊用途的 IPv4 和 IPv6 地址,但三个 IPv4 专用地址块的指派并无变化,即

上面的三个地址块分别相当于原来的一个 A 类网络、16 个连续的 B 类网络和 256 个连续的 C 类网络。A 类地址本来早已用完了,而上面的地址 10.0.0.0 本来是分配给 ARPANET 的。由于 ARPANET 已经关闭停止运行了,因此这个地址就用作专用地址。

采用这样的专用 IP 地址的互连网络称为专用互联网或本地互联网,或更简单些,就叫作专用网。显然,全世界可能有很多的专用互连网络具有相同的 IP 地址,但这并不会引起麻烦,因为这些专用地址仅在本机构内部使用。专用 IP 地址也叫作可重用地址 (reusable address)。

有时一个很大的机构的许多部门分布的范围很广(例如,在世界各地),这些部门经常要互相交换信息。这可以有两种方法。(1) 租用电信公司的通信线路为本机构专用。这种方法虽然简单方便,但线路的租金太高,一般难于承受。(2) 利用公用的互联网作为本机构各专用网之间的通信载体,这样的专用网又称为虚拟专用网 VPN (Virtual Private Network)。

这里之所以称为 “专用网” 是因为这种网络是为本机构的主机用于机构内部的通信,而不是用于和网络外非本机构的主机通信。如果专用网不同网点之间的通信必须经过公用的互联网,但又有保密的要求,那么所有通过互联网传送的数据都必须加密。加密需要采用的协议将在 7.6.1 节讨论。“虚拟” 表示 “好像是”,但实际上并不是,因为现在并没有真正使用通信专线,而 VPN 只是在效果上和真正的专用网一样。一个机构要构建自己的 VPN 就必须为它的每一个场所购买专门的硬件和软件,并进行配置,使每一个场所的 VPN 系统都知道其他场所的地址。

图 4-64 以两个场所为例说明如何使用 IP 隧道技术实现虚拟专用网。

假定某个机构在两个相隔较远的场所建立了专用网 A 和 B,其网络地址分别为专用地址 10.1.0.0 和 10.2.0.0。现在这两个场所需要通过公用的互联网构成一个 VPN。

显然,每一个场所至少要有一个路由器具有合法的全球 IP 地址,如图 4-64 (a) 中的路由器 \(R_{1}\)\(R_{2}\) 。这两个路由器和互联网的接口地址必须是合法的全球 IP 地址。路由器 \(R_{1}\)\(R_{2}\) 在专用网内部网络的接口地址则是专用网的本地地址。

cd474b7148f2f342e417aabdc575ebb49971ea0bc3b68b029822a0e4858f37e5.jpg

2f0d205b512c0509cb1066553e570bf258bc3278c0ed8620d0df4a46813da642.jpg

在每一个场所 A 或 B 内部的通信量都不经过互联网。但如果场所 A 的主机 X 要和另一个场所 B 的主机 Y 通信,那么就必须经过路由器 \(R_{1}\)\(R_{2}\) 。主机 X 向主机 Y 发送的 IP 数据报的源地址是 10.1.0.1,而目的地址是 10.2.0.3。这个数据报先作为本机构的内部数据报从 X 发送到与互联网连接的路由器 \(R_{1}\) 。路由器 \(R_{1}\) 收到内部数据报后,发现其目的网络必须通过互联网才能到达,就把整个的内部数据报进行加密(这样就保证了内部数据报的安全),然后重新加上数据报的首部,封装成为在互联网上发送的外部数据报,其源地址是路由器 \(R_{1}\) 的全球地址 125.1.2.3,而目的地址是路由器 \(R_{2}\) 的全球地址 194.4.5.6。路由器 \(R_{2}\) 收到数据报后将其数据部分取出进行解密,恢复出原来的内部数据报(目的地址是 10.2.0.3),交付主机 Y。可见,虽然 X 向 Y 发送的数据报通过了公用的互联网,但在效果上就好像是在本部门的专用网上传送一样。如果主机 Y 要向 X 发送数据报,那么所进行的步骤也是类似的。

请注意,数据报从 \(R_{1}\) 传送到 \(R_{2}\) 可能要经过互联网中的很多个网络和路由器。但从逻辑上看,在 \(R_{1}\)\(R_{2}\) 之间好像是一条直通的点对点链路,图 4-64 (a) 中的 “隧道” 就是这个意思。

如图 4-64 (b) 所示的、由场所 A 和 B 的内部网络所构成的虚拟专用网 VPN 又称为内联网(intranet 或 intranet VPN,即内联网 VPN),表示场所 A 和 B 都属于同一个机构。

有时一个机构的 VPN 需要有某些外部机构(通常就是合作伙伴)参加进来。这样的 VPN 就称为外联网(extranet 或 extranet VPN,即外联网 VPN)。

请注意,内联网和外联网都采用了互联网技术,即都是基于 TCP/IP 协议的。

还有一种类型的 VPN,就是远程接入 VPN (remote access VPN)。我们知道,有的公司可能并没有分布在不同场所的部门,但却有很多流动员工在外地工作。公司需要和他们保持联系,有时还可能一起开电话会议或视频会议。远程接入 VPN 可以满足这种需求。在外地工作的员工通过拨号接入互联网,而驻留在员工个人电脑中的 VPN 软件可以在员工的个人电脑和公司的主机之间建立 VPN 隧道,因而外地员工与公司通信的内容也是保密的,员工

们感到好像就是使用公司内部的本地网络。

关于 VPN 隧道的保密问题,在后面的 7.5.1 节还有进一步的论述。

4.8.2 网络地址转换

下面讨论另一种情况,就是在专用网内部的一些主机本来已经分配到了本地 IP 地址(即仅在本专用网内使用的专用地址),但现在又想和互联网上的主机通信(并不需要加密),那么应当采取什么措施呢?

最简单的办法就是设法再申请一些全球 IP 地址。但这在很多情况下是不容易做到的。目前使用得最多的方法是采用网络地址转换。

网络地址转换 NAT (Network Address Translation) 方法是在 1994 年提出的。这种方法需要在专用网连接到互联网的路由器上安装 NAT 软件。装有 NAT 软件的路由器叫作 NAT 路由器,它至少有一个有效的外部全球 IP 地址。这样,所有使用本地地址的主机在和外界通信时,都要在 NAT 路由器上将其本地地址转换成全球 IP 地址,才能和互联网连接。

图 4-65 给出了 NAT 路由器的工作原理。在图中,专用网 192.168.0.0 内所有主机的 IP 地址都是本地 IP 地址 192.168.x.x。NAT 路由器至少要有一个全球 IP 地址,才能和互联网相连。在本例中,NAT 路由器的全球 IP 地址是 172.38.1.5(当然,NAT 路由器可以有多个全球 IP 地址)。

9a1a65b2e9a5c922c93bc9f80d73b59186d645570f4be38770970b5d7e0402fb.jpg

NAT 路由器收到从专用网内部的主机 A 发往互联网上主机 B 的 IP 数据报①:源地址 S = 192.168.0.3,而目的地址 D = 213.18.2.4。NAT 路由器通过内部的 NAT 转换表,把专用网的 IP 地址 192.168.0.3,转换为全球 IP 地址 172.38.1.5 后,改写到数据报的首部中作为新的源地址,然后把新的数据报②转发出去。主机 B 收到 IP 数据报②后,发回应答③,B 发送的 IP 数据报的源地址就是自己的地址:S = 213.18.2.4,目的地址就是刚才收到的数据报的源地址,因此现在 D = 172.38.1.5。请注意,B 并不知道 A 的专用地址 192.168.0.3。实际上,即使知道了,也不能使用,因为互联网上的路由器不能转发目的地址是任何专用地址的 IP 数据报。当 NAT 路由器收到 B 发来的 IP 数据报③时,还要进行一次 IP 地址的转换。通过 NAT 转换表,把收到的 IP 数据报使用的目的地址 D = 172.38.1.5 转换为专用网内部的目的地址 D = 192.168.0.3(即主机 A 真正的本地 IP 地址),变成了数据报④,然后发送到 A。

由此可见,当 NAT 路由器具有 n 个全球 IP 地址时,专用网内最多可以同时有 n 台主机接入到互联网。这样就可以使专用网内较多数量的主机,轮流使用 NAT 路由器有限数量的

全球 IP 地址。

显然,通过 NAT 路由器的通信必须由专用网内的主机发起。设想如果有专用网上外面的主机要发起通信,当 IP 数据报到达 NAT 路由器时,NAT 路由器就不知道应当把目的 IP 地址转换成专用网内的哪一个本地 IP 地址。这就表明,专用网内部的主机不能直接充当服务器用。

为了更加有效地利用 NAT 路由器上的全球 IP 地址,现在常用的 NAT 转换表把运输层的端口号也利用上。这样,就可以使多个拥有本地地址的主机,共用 NAT 路由器上的一个全球 IP 地址,因而可以同时和互联网上的不同主机进行通信 [COME06]。

由于运输层的端口号将在下一章 5.1.3 节讨论,因此,建议在学完运输层的有关内容后,再学习下面的内容。但从系统性方面考虑,把下面的这部分内容放在本章中介绍较为合适。

使用端口号的 NAT 也叫作网络地址与端口号转换 NAPT (Network Address and Port Translation),而不使用端口号的 NAT 就叫作传统的 NAT (traditional NAT)。但在许多文献中并没有这样区分,而是不加区分地都使用 NAT 这个更加简洁的缩写词。表 4-9 说明了 NAPT 的地址转换机制。

表 4-9 NAPT 地址转换表举例

方向字段原先的IP地址和端口号转换后的IP地址和端口号
从专用网发往互联网源IP地址:TCP源端口192.168.0.3:30000172.38.1.5:40001
从专用网发往互联网源IP地址:TCP源端口192.168.0.4:30000172.38.1.5:40002
从互联网发往专用网目的IP地址:TCP目的端口172.38.1.5:40001192.168.0.3:30000
从互联网发往专用网目的IP地址:TCP目的端口172.38.1.5:40002192.168.0.4:30000

从表 4-9 可以看出,在专用网内主机 192.168.0.3 向互联网发送 IP 数据报,其 TCP 端口号选择为 30000。NAPT 把源 IP 地址和 TCP 端口号都进行转换(如果使用 UDP,则对 UDP 的端口号进行转换。原理是一样的)。另一台主机 192.168.0.4 也选择了同样的 TCP 端口号 30000。这纯属巧合(端口号仅在本主机中才有意义)。现在 NAPT 把专用网内不同的源 IP 地址都转换为同样的全球 IP 地址。但对源主机所采用的 TCP 端口号(不管相同或不同),则转换为不同的新的端口号。因此,当 NAPT 路由器收到从互联网发来的应答时,就可以从 IP 数据报的数据部分找出运输层的端口号,然后根据不同的目的端口号,从 NAPT 转换表中找到正确的目的主机。

应当指出,从层次的角度看,NAPT 的机制有些特殊。普通路由器在转发 IP 数据报时,对于源 IP 地址或目的 IP 地址都是不改变的。但 NAT 路由器在转发 IP 数据报时,一定要更换其 IP 地址(转换源 IP 地址或目的 IP 地址)。其次,普通路由器在转发分组时是工作在网络层的。但 NAPT 路由器还要查看和转换运输层的端口号,而这本来应当属于运输层的范畴。也正因为这样,NAPT 曾遭受了一些人的批评,认为 NAPT 的操作没有严格按照层次的关系。但不管怎样,NAT(包括 NAPT)已成为互联网的一个重要构件 [RFC 3022]。

4.9 多协议标签交换 MPLS

IETF 于 1997 年成立了 MPLS 工作组,为的是开发出一种新的协议。这种新的协议就是多协议标签交换 MPLS (MultiProtocol Label Switching)。“多协议” 表示在 MPLS 的上层可以