《TCP/IP 详解 卷一:协议》第五章:Internet 协议

5.1 引言

IP是 TCP/IP 协议族中的核心协议。所有 TCP、 UDP、 ICMP 和 IGMP 数据都通过 IP 数据报传输。 IP 提供了一种尽力而为、无连接的数据报交付服务。 “尽力而为”的含义是不保证 IP 数据报能成功到达目的地。虽然 IP 不是简单丢弃所有不必要流量,但它也不对自己尝试交付的数据报提供保证。当某些错误发生时,例如一台路由器临时用尽缓冲区, IP 提供一个简单的错误处理方法: 丢弃一些数据(通常是最后到达的数据报)。任何可靠性必须由上层(例如 TCP)提供。 IPv4 和 IPv6 都使用这种尽力而为的基本交付模式。

无连接”意味着 IP 不维护网络单元(即路由器)中数据报相关的任何链接状态信息,每个数据报独立于其他数据报来处理。这也意味着 IP 数据报可不按顺序交付。如果一个源主机向同一目的地发送两个连续的数据报(第一个为 A,第二个为 B),每个数据报可以独立路由,通过不同路径,并且 B 可能在 A 之前到达。 IP 数据报也可能发生其他问题:它们可能在传输过程中被复制,可能改变内容从而导致错误。此外, IP 之上的一些协议(通常是 TCP)需要处理这些潜在问题,以便为应用提供无差错的交付。

本章我们首先看一下 IPv4 (见图 5-1)和 IPv6 (见图 5-2)头部中的字段,然后描述 IP 如何转发。[RFC0791] 是针对 IPv4 的正式规范。描述 IPv6 的一系列 RFC 从 [RFC2460] 开始。

图 5-1

图 5-1 IPv4 数据报。头部大小可变, 4 位的 IHL 字段被限制为 15 个 32 位字(60字节)。一个典型的 IPv4 头部包含 20 字节(没有选项)。源地址和目的地址的长度为 32 位。第二个 32 位字的大部分用于 IPv4 分片功能。头部校验和有助于确保头部字段被正确发送到目的地,但不保护数据内容

图 5-2

图 5-2 IPv6 头部大小固定(40 字节),并包含 128 位源地址和目的地址。下一个头部字段用于说明 IPv6 头部之后其他扩展头部的存在和类型,它们形成一条包括特殊扩展或处理指令的头部链。应用数据跟在这条头部链之后,通常紧跟着是一个传输层头部


5.2 IPv4 头部和 IPv6 头部

图 5-1 显示了 IPv4 数据报格式。正常的 IPv4 头部大小为 20 字节,除非存在选项(这种情况很少见)。 IPv6 头部长度是它的两倍,但没有任何选项。它可以有扩展头部,可提供类似的功能,我们将在后面看到。在关于 IP 头部和数据报的印象中,最高有效位在左侧且编号为 0,一个 32 位值的最低有效位在右侧且编号为 31。

一个 32 位值的 4 字节按以下顺序传输:首先是 0 ~ 7 位,然后是 8 ~ 15 位,接着是 16 ~ 23 位,最后是 24 ~ 31 位。这就是所谓的高位优先字节序,它是 TCP/IP 头部中所有二进制整数在网络中传输时所需的字节顺序。它也被称为网络字节序。计算机的 CPU 使用其他格式存储二进制整数,例如大多数 PC 使用低位优先字节序,在传输时必须将头部值转换为网络字节序,并在接收时再转换回来。

5.2.1 IP 头部字段

第一个字段(只有 4 位或半个字节)是版本字段。它包含 IP 数据报的版本号:IPv4 为 4, IPv6 为 6。IPv4 头部和 IPv6 头部除版本字段位置相同外再无其他是一样的。因此,这两个协议不能直接互操作,主机或路由器必须分别处理 IPv4 或 IPv6 (或两者,称为双栈)。虽然也提出并发展了其他 IP 版本,但只有版本 4 和 6 经常使用。 IANA 负责保存这些版本号的正式注册信息 [IV]。

**Internet 头部长度(IHL)**字段保存 IPv4 头部中 32 位字的数量,包括任何选项。由于它是一个 4 位的字段,所以 IPv4 头部被限制为最多 15 个 32 位字,即 60 字节。后面,我们将看到,这种限制使一些选项(例如“记录路由”选项)当前几乎无法使用。这个字段的正常值(当没有选项时)是 5。 IPv6 中不存在这个字段,其头部长度固定为 40 字节。

在头部长度之后, IPv4 [RFC0791] 的最初规范指定了一个服务类型(ToS)字段,IPv6 [RFC2460] 指定了一个等效的通信类型字段。由于它们从来没被广泛使用,因此最终这个 8 位长的字段被分为两个部分,并由一组 RFC( [RFC3260] [RFC3168] [RFC2474] 和其他 RFC)重新定义。目前,前 6 位被称为区分服务字段(DS字段),后 2 位是**显式拥塞通知(ECN)**字段或指示位。现在,这些 RFC 适用于 IPv4 和 IPv6。这些字段被用于数据报转发时的特殊处理。我们将在 5.2.3 节中详细讨论它们。

总长度字段是 IPv4 数据报的总长度(以字节为单位)。通过这个字段和 IHL 字段,我们知道数据报的数据部分从哪里开始,以及它的长度。由于它是一个 16 位的字段,所以 IPv4 数据报的最大长度(包括头部)为 65535 字节。由于一些携带 IPv4 数据报的低层协议不能(精确)表达自己封装的数据报大小,所以需要在头部中给出总长度字段。例如,以太网会将短帧填充到最小长度(64 字节)。虽然以太网最小有效载荷为 46 字节(见第 3 章),但一个 IPv4 数据报也可能会更小(20 字节)。如果没有提供总长度字段, IPv4 实现将无法知道一个 46 字节的以太网帧是一个 IP 数据报,还是经过填充的 IP 数据报,这样可能会导致混淆。

尽管可发送一个 65535 字节的IP数据报,但大多数链路层(例如以太网)不能携带这么大的数据,除非将它分(拆)成更小的片。另外,主机不需要接收大于 576 字节的 IPv4 数据报。 (在 IPv6 中,主机需要能处理所连接链路 MTU 大小的数据报,而最小链路 MTU 为 1280 字节。)很多使用 UDP 协议(见第 10 章)传输数据(例如 DNS、DHCP 等)的应用程序,限制为使用 512 字节大小的数据,以避免 576 字节的 IPv4 限制。 TCP 根据额外信息(见第 15 章)选择自己的数据报大小。

当一个 IPv4 数据报被分为多个更小的分片时,每个分片自身仍是一个独立的 IP 数据报,总长度字段反映具体的分片长度。第 10 章中将详细介绍分片和 UDP。IPv6 头部不支持分片,其长度可由负载长度字段获得。这个字段提供 IPv6 数据报长度,不包括头部长度,但扩展头部包括在负载长度中。对于 IPv4,这个 16 位的字段限制其最大值为 65535。对于 IPv6,负载长度被限制为 64KB,而不是整个数据报。另外, IPv6 还支持一个超长数据报选项(见 5.3.1.2 节),它至少在理论上提供了可能性,即单个分组的有效载荷可达到 4GB (4294967295 字节)!

标识字段帮助标识由 IPv4 主机发送的数据报。为了避免将一个数据报分片和其他数据报分片混淆,发送主机通常在每次(从它的一个 IP 地址)发送数据报时都将一个内部计数器加 1,并将该计数器值复制到 IPv4 标识 字段。这个字段对实现分片很重要,因此我们将在第 10 章中进一步讨论,另外还会讨论标志和分片偏移字段。在 IPv6 中,这个字段显示在分片扩展头部中,我们将在 5.3.3 节中讨论。

**生存期(TTL)**字段用于设置一个数据报可经过的路由器数量的上限。发送方将它初始化为某个值([RFC1122] 建议为 64,但 128 或 255 也不少见),每台路由器在转发数据报时将该值减 1。当这个字段值达到 0 时,该数据报被丢弃,并使用一个 ICMP 消息通知发送方(见第 8 章)。.这可以防止由于出现不希望的路由环路而导致数据报在网络中永远循环。

注意    TTL 字段最初指定 IP 数据报的最大生存期在几秒钟内,但路由器总需要将
这个值至少减 1。 实际上,当前路由器在正常操作下通常不会持有数据报超过 1 秒
钟,因此较早的规则现在已被忽略或遗忘,这个字段在 IPv6 中根据实际用途已被
重新命名为跳数限制。

IPv4 头部中的协议字段包含一个数字,表示数据报有效载荷部分的数据类型。最常用的值为 17 (UDP)和 6 (TCP)。这提供了多路分解的功能,以便 IP 协议可用于携带多种协议类型的有效载荷。虽然该字段最初仅用于指定数据报封装的传输层协议,但它现在用于识别其中封装的协议是否为一种传输层协议。其他封装也是可能的,例如 IPv4-in-IPv4 (值为 4)。数字分配页面 [AN] 给出了可能的协议字段值的正式列表。 IPv6 头部中的下一个头部字段给出了 IPv4 中的协议字段。它用于指出 IPv6 头部之后的头部类型。这个字段可能包含由 IPv4 协议字段定义的任何值,或 5.3 节中描述的 IPv6 扩展头部的相关值。

头部校验和字段仅计算 IPv4 头部。理解这一点很重要,因为这意味着 IP 协议不检查 IPv4 数据报有效载荷(例如 TCP 或 UDP 数据)的正确性。为了确保 IP 数据报的有效载荷部分已正确传输,其他协议必须通过自己的数据完整性检验机制来检查重要数据。我们看到,封装在 IP 中的几乎所有协议(ICMP、 IGMP、 UDP 和 TCP)在自己头部中都有一个涵盖其头部和数据的校验和,也涵盖它们认为重要的 IP 头部的某些部分(一种“违反分层”的形式)。令人惊讶的是, IPv6 头部没有任何校验和字段。

注意    IPv6 头部省略校验和字段是一个有争议的决定。这个行动背后的理由大致
如下:在 IP 头部中,更高层协议为确定正确性,必须计算它们自己的校验和,这
需要涵盖它们认为重要的数据。 IP 头部中的错误带来的后果是:数据被投递到错误
的目的地、指示数据来源错误,或在交付过程中错位。由于位错误比较少见(受益
于 Internet 流量的光纤传输),而且其他字段提供了更有力的确保正确性的机制(更
高层次的校验和或其他检查),因此决定从 IPv6 头部中删除这个字段。

大多数使用校验和的其他 Internet 相关协议也使用该校验和计算算法,因此有时称之为 Internet 校验和。注意,当一个 IPv4 数据报经过一台路由器时, TTL 字段减 1 带来的结果是其头部校验和必须改变。找们将在 5.2.2 节详细讨论校验和计算方法。

每个 IP 数据报包含发送者的源 IP 地址和接收者的目的 IP 地址。这些针对 IPv4 的 32 位地址和针对 IPv6 的 128 位地址,通常标识一台计算机的一个接口,但组播地址和广播地址(见第 2 章)不符合本规则。虽然一个 32 位地址可容纳看似很多 Internet 实体(232 个),但一个广泛的共识是这个数字仍不够,这是向 IPv6 迁移的一个主要动机。 IPv6 的 128 位地址可容纳数量庞大的 Internet 实体。 [H05] 进行了重新统计, IPv6 拥有 3.4 × 1038 个地址。引用 [H05] 和其他人的话:“乐观估计将使地球上每平方米表面拥有 3 911 873 538 269 506 102 个地址。”这确实看起来可持续很长一段时间。

5.2.2 Internet 校验和

Internet 校验和是一个 16 位的数字和,它能以相当高的概率确定接收的消息或其中的部分内容是否与发送的相匹配。注意,Internet 校验和算法与常见的循环冗余校验(CRC)[PB61] 不同,后者提供了更强的保护功能。

为了给输出的数据报计算 IPv4 头部校验和,首先将数据报的校验和字段值设置为 0。然后,对头部(整个头部被认为是一个 16 位字的序列)计算 16 位二进制反码和。这个 16 位二进制反码和被存储在校验和字段中。二进制反码加法可通过“循环进位(end-round-carry)加法”实现:当使用传统(二进制补码)加法产生一个进位时,这个进位以二进制值 1 加在高位。图 5-3 显示了这个例子,消息内容使用十六进制表示。

图 5-3 Internet 校验和是一个被校验数据(如果被计算的字节数为奇数,用 0 填充)的 16 位反码和的反码。如果被计算数据包括一个校验和字段,该字段在计算校验和运算之前被设置为 0,然后将计算出的校验和填充到该字段。为了检查一个包含校验和字段(头部、有效载荷等)的数据输入是否有效,需要对整个数据块(包含校验和字段)同样计算校验和。由于校验和字段本质上是其余数据校验和的反码,对正确接收的数据计算校验和应产生一个值 0

当一个 IPv4 数据报被接收时,对整个头部计算出一个校验和,包括校验和字段自身的值。假设这里没有错误,计算出的校验和值为 0 (值 FFFF 的反码)。注意,对于任何不正常的分组或头部,分组中的校验和字段值不为 FFFF。如果是这样,这个和(在发送方的最后一次反码运算之前)将为 0。通过反码加法得到的和不能永远为 0,除非所有字节都是 0,这在任何合法 IPv4 头部中都不可能出现。当发现一个头部出错(计算的校验和不为 0)时, IPv4 实现将丢弃接收到的数据报。但是,不会生成差错信息。更高层以某种方式检测丢失的数据报,并在必要时重新传输。

5.2.2.1 Internet 校验和数学性质

在数学上, 16 位的十六进制值集合 V = {0001, …, FFFF} 与其反码和运算“+”共同形成一个阿贝尔群。将一个集合和一个运算符组合到一组时,必须符合以下性质:闭包、结合性、存在一个恒等元素,以及存在可逆。要形成一个阿贝尔(可交换的)群,还必须满足交换性。如果我们仔细观察,可看到所有特性实际上都服从:

  • 对于 V 中的任何 X、Y、(X + Y) 在 V 中 [闭包]
  • 对于 V 中的任何 X、Y、Z,X +(Y + Z) = (X + Y) + Z [结合性]
  • 对于 V 中的任何 X,e + X = X + e = X,其中 e = FFFF [恒等]
  • 对于 V 中的任何 X,有一个 X' 在 V 中,使得 X + X' = e [可逆]
  • 对于 V 中的任何 X、Y,(X + Y)=(Y +X) [交换性]

关于集合 V 和组 <V, +>,有趣的是我们已删除 0000。如果我们将数字 0000 放入集合 V,这时 <V, +> 不再是一个组。为了看清这点,我们首先观察 0000 和 FFFF 作为 0 (加性恒等)出现在使用“+”的运算中的情况。例如,AB12 + 0000= AB1 2= AB12+FFFF。但是,在一个组中只能有一个恒等元素。如果我们包含元素 12AB,并假设恒等元素为 0000,那么我们就需要某个可逆数 X′ 使得 (12AB + X′)= 0000,但我们发现,在 V 中没有满足此条件的 X' 存在。因此,我们需要排除 0000 作为<V, +> 中的恒等元素,通过将它从集合 V 中删除,使得这种结构成为一个满足要求的组。这里仅对抽象代数做一个简单介绍,读者若希望详细阅读这方面内容,可参考 Pinter [P90] 的畅销书。

5.2.3 DS 字段和 ECN (以前称为 ToS 字节或 IPv6 流量类别)

IPv4 头部的第 3 和第 4 字段(IPv6 头部的第 2 和第 3 字段)分别是区分服务(称为 DS 字段)ECN 字段。区分服务(称为 DiffServ)是一个框架和一组标准,用于支持 Internet [RFC2474] [RFC2475] [RFC3260] 上不同类型的服务(即不只是尽力而为服务)。 IP 数据报以某种方式(通过预定义模式设置某些位)被标记,使它们的转发不同于(例如以更高的优先级)其他数据报。这样做可能导致网络中排队延时的增加或减少,以及出现其他特殊效果(可能与 ISP 收取的特殊费用相关)。 DS 字段中的数字称为区分服务代码点(DSCP)。 “代码点”指的是预定义的具有特定含义的位。在通常情况下,如果数据报拥有一个分配的 DSCP,它在通过网络基础设施交付过程中会保持不变。但是,某些策略(例如在一段时间内可发送多少个高优先级的分组)可能导致一个数据报中的 DSCP 在交付过程中改变。

当通过一台具有内部排队流量的路由器时,头部中的 2 位 ECN 位用于为数据报标记拥塞标识符。一台持续拥塞的具有 ECN 感知能力的路由器在转发分组时会设置这两位。这种功能的设计思路是,当一个被标记的分组被目的节点接收时,有些协议(例如 TCP)会发现分组被标记并将这种情况通知发送方,发送方随后会降低发送速度,这样可在路由器因过载而被迫丢弃流量之前缓解拥塞。这种机制是避免或处理网络拥塞的方法之一,我们将在第 16 章中详细探讨。虽然 DS 字段ECN 字段并不密切相关,但它们被用作代替以前定义的** IPv4 服务类型 IPv6 流量类别**字段。因此,它们经常被放在一起讨论,术语“ToS 字节”和“流量类别字节”仍在广泛使用。

尽管原来的 ToS 和流量类别字节没得到广泛支持,但 DS 字段结构仍提供了一些对它们的兼容能力。为了对其如何工作有更清楚的了解,我们首先回顾服务类型字段 [RFC0791] 的原始结构,如图 5-4 所示。

图 5-4

图 5-4 原来的 IPv4 服务类型IPv6 流量类别 字段结构。优先级子字段用于表示哪些分组具有更高优先级(较大的值意味着更高的优先级)。D、T 和 R 子字段分别用于表示延时、吞吐量和可靠性。如果这些字段值为 1,分别对应于低延时、高吞吐量和高可靠性

D、 T 和 R 子字段表示数据报在延时、吞吐量和可靠性方面得到良好的处理。相应值为 1 表示更好的处理(分别为低延时、高吞吐量和高可靠性)。优先级取值范围是从 000 (常规)到 111 (网络控制),表示优先级依次递增(见表 5-1)。它们都基于一个称为**多级优先与抢占(MLPP)**的方案,该方案可追溯到美国国防部的 AUTOVON 电话系统 [A92],其中较低优先级的呼叫可被更高优先级的呼叫抢占。这些术语仍在使用,并被纳入 VoIP 系统中。

表 5-1 原来的 IPv4 服务类型和 IPv6 流量类别 的优先级子字段值
优先级名称
000 常规
001 优先级
010 立即
011 瞬间
100 瞬间覆盖
101 严重
110 网间控制
111 网络控制

在定义 DS 字段时,优先级的值已定义在 [RFC2474] 中,以提供有限的兼容性。在图 5-5 中, 6 位 DS 字段用于保存 DSCP,提供对 64 个代码点的支持。特定 DSCP 值可通知路由器对接收的数据报进行转发或特殊处理。不同类型的转发处理表示为每跳行为(PHB),因此 DSCP 值可有效通知路由器哪种 PHB 被应用于数据报。 DSCP 的默认值通常为 0,对应于常规的尽力而为的 Internet 流量。 64 个可能的 DSCP 值分为不同用途,它们可从 [DSCPREG] 中获得,如表 5-2 所示。

图 5-5

图 5-5 DS 字段包含 6 位(其中 5 位当前是标准的,表示当前接收的数据报应转发时,可由一台兼容的路由器转发)。后面 2 位用作 ECN,当数据报通过持续拥塞的路由器时设置。当这些数据报到达目的地时,稍后发送一个包含拥塞指示的数据报给发送方,通知该数据报经过一台或多台拥塞的路由器

表 5-2 DSCP 值被分成 3 个池:标准的、实验/本地用途的(EXP/LU)和最终打算标准化的实验/本地用途的(*)
代码店前缀 策略
1 xxxxx0 标准的
2 xxxx11 EXP/LU
3 xxxx01 EXP/LU(*)

这个方案供研究人员和操作人员用于实验或本地用途。以 0 作为结尾的 DSCP 用于标准用途,以 1 作为结尾的 DSCP 用于实验或本地用途。以 01 作为结尾的 DSCP 最初打算用于实验或本地用途,但最终会走向标准化。

在图 5-5 中, DS 字段中的类别部分包含前 3 位,并基于较早定义的服务类型的优先级子字段。路由器通常先将流量分为不同类别。常见类别的流量可能有不同的丢弃概率,如果路由器被迫丢弃流量,允许路由器确定首先丢弃哪些流量。 3 位的类别选择器提供了 8 个定义的代码点(称为类别选择代码点),它们对应于一个指定最小功能集的 PHB,提供与早期的 IP 优先级相似的功能。它们称为类别选择兼容的 PHB,目的是支持部分兼容的最初定义的 IP 优先级子字段 [RFC0791] 。 xxx000 形式的代码点总被映射为这种 PHB,但是其他值也可映射到相同 PHB。

表 5-3 给出了类别选择器的 DSCP 值,以及 [RFC0791] 定义的 IP 优先级字段的相应术语。保证转发(AF)组对固定数量的独立 AF 类别的 IP 分组提供转发,它有效地概括了优先级的概念。某个类别的流量与其他类别的流量分别转发。在一个流量类别中,数据报被分配一个丢弃优先级。在一个类别中,较高丢弃优先级的数据报优先于那些较低丢弃优先级的数据报处理(即以较高优先级转发)。结合流量类别和丢弃优先级,名称 AFij 对应于保证转发类别 i 的丢弃优先级 j。例如,一个标记为 AF32 的数据报的流量类别为 3,丢弃优先级为 2。

表 5-3 DS 字段值设计为兼容服务类型和 IPv6 流量类别字段中指定的 IP 优先级字段。 AF 和 EF 提供比简单的“尽力而为”更好的服务
名称 参考文献 描述
CS0 000000 [RFC2474] 类别选择(尽力而为/常规)
CS1 001000 [RFC2474] 类别选择(优先)
CS2 010000 [RFC2474] 类别选择(立即)
CS3 011000 [RFC2474] 类别选择(瞬间)
CS4 100000 [RFC2474] 类别选择(瞬间覆盖)
CS5 101000 [RFC2474] 类别选择(CRITIC/ECP)
CS6 110000 [RFC2474] 类别选择(网间控制)
CS7 111000 [RFC2474] 类别选择(控制)
AF11 001010 [RFC2597] 保证转发(1,1)
AF12 001100 [RFC2597] 保证转发(1,2)
AF13 001110 [RFC2597] 保证转发(1,3)
AF21 010010 [RFC2597] 保证转发(2,1)
AF22 010100 [RFC2597] 保证转发(2,2)
AF23 010110 [RFC2597] 保证转发(2,3)
AF31 011010 [RFC2597] 保证转发(3,1)
AF32 011100 [RFC2597] 保证转发(3,2)
AF33 011110 [RFC2597] 保证转发(3,3)
AF41 100010 [RFC2597] 保证转发(4,1)
AF42 100100 [RFC2597] 保证转发(4,2)
AF43 100110 [RFC2597] 保证转发(4,3)
EF PHB 101110 [RFC3246] 加速转发
VOICE-ADMIT 101100 [RFC5865] 容量许可的流量

**加速转发(EF)**提供了非拥塞的网络服务,也就是说, EF 流量应享受较低的延时、抖动和丢包率。直观地说, EF 流量要求路由器的输出速率至少比输入速率大。因此,在一台路由器的队列中, EF 流量仅排在其他 EF 流量之后。

为了在 Internet 中提供差异化服务,目前已持续进行十多年的努力。虽然大部分机制的标准化开始于 20 世纪 90 年代末,但其中有些功能直到 21 世纪才被实现。 [RFC4594] 给出了一些关于如何配置系统以利用该功能的指导。差异化服务的复杂性在于:差异化服务和假设的差异化定价结构之间的联系,以及由此产生的公平问题。这种经济关系是复杂的,并且不在我们讨论的范围内。关于这个问题和相关主题的更多信息,详见 [MB97] 和 [W03] 。

5.2.4 IP 选项

IP 支持一些可供数据报选择的选项。 [RFC0791] 介绍了大多数的选项,当时处于 IPv4 设计阶段, Internet 的规模相当小,对来自恶意用户的威胁关注较少。由于 IPv4 头部大小的限制以及相关的安全问题,因此很多选项不再是实用或可取的。在 IPv6 中,大部分选项已被删除或改变,不再是 IPv6 基本头部的一部分,而被放在 IPv6 头部之后的一个或多个扩展头部中。 IP 路由器接收到一个包含选项的数据报,通常需要对该数据报进行特殊处理。在某些情况下,尽管 IPv6 路由器可以处理扩展头部,但很多头部被设计为仅由终端主机处理。在有些路由器中,带选项或扩展的数据报不会像普通数据报那样被快速转发。作为相关的背景知识,我们简要讨论 IPv4 选项,以及 IPv6 如何实现扩展头部和选项。表 5-4 显示了经过多年标准化的 IPv4 选项。

表 5-4 给出了保留的 IPv4 选项,它们可在描述性的 RFC 中找到。这个完整的列表会定期更新,并可在 [IPPARAM] 中在线查看。选项的范围总是以 32 位为界。如果有必要,数值 0 作为填充字节被添加。这确保 IPv4 头部始终是 32 位的倍数(IHL 字段的要求)。表 5-4 中的“编号”列是选项编号。 “值”列给出了放在类型字段中的编号,以表示该选项的存在。由于类型字段有另外的结构,所以这两列中的相应值不必相同。特别指出的是,第 1 (高序)位表示如果相关数据报被分片,该选项是否被复制到分片中。后面 2 位表示该选项的类别。目前,除了“时间戳”和“跟踪”使用类别 2 (调试和测量)外,表 5-4 中的所有选项使用类别 0 (控制)。类别 1 和 3 被保留。

表 5-4 如果选项存在,它在 IPv4 分组中紧跟在基本 IPv4 头部之后。选项由一个 8 位的类型字段标识。这个字段被细分为 3 个子字段:复制(1 位)、类别(2 位)和编号(5 位)。选项 0 和 1 的长度是 1 字节,多数的其他选项长度可变。可变选项包括 1 字节的类型标识符、1 字节的长度以及选项自身
名称 编号 长度 描述 参考文献 注释
列表结尾 0 0 1 表示没有更多选项 [RFC0791] 如果需要
没有操作 1 1 1 表示没有操作执行(用于填充) [RFC0791] 如果需要
源路由 3
9
131
137
可变 发送方列出分组转发时遍历的路由器“航点”。松散意味着其他路由器可以包含在航点(3,131)中。严格意味着(9,137)中的所有航点都有按顺序遍历 [RFC1108] 很少,经常被过滤
安全和处理标签 2
5
130
133
11 在美国军事环境下如何为 IP 数据包指定安全标签和处理闲置 [RFC0791] 很少
记录路由 7 7 可变 在分组的头部中记录经过的路由器 [RFC0791] 很少
时间戳 4 68 可变 在分组的源和目的地记录日期和时间 [RFC0791] 很少
流 ID 8 136 4 携带 16 位的 SATNET 流标识符 [RFC0791] 历史的
EIP 17 145 可变 扩展 Internet 协议(20 世纪 90 年代早期的一个实验) [RFC1385] 历史的
跟踪 18 82 可变 增加一个路由跟踪选项和 ICMP 报文(20 世纪 90 年代早期的一个实验) [RFC1393] 历史的
路由器警告 20 148 4 表示一个路由器需要解释数据报的内容 [RFC2113] [RFC5350] 偶然
快速启动 25 25 8 表示启动快速传输协议(实验性的) [RFC4782] 很少

目前,多数标准化选项在 Internet 中很少或从未使用。例如,源路由和记录路由选项需要将 IPv4 地址放在 IPv4 头部中。由于头部(总计 60 字节,其中 20 字节是基本 IPv4 头部)空间有限,这些选项在当前基于 IPv4 的 Internet 中用处不大,其中一条 Internet 路径的平均路由器跳步数约为 15 [LFS07]。另外,这些选项主要用于诊断目的,它们为防火墙的构建带来麻烦和风险。因此, IPv4 选项通常在企业网络边界处被防火墙拒绝或剥离(见第 7 章)。

在企业网络内部,路径的平均长度更小,对恶意用户的防护可能考虑得更少,这些选项仍然可以使用。另外,路由器警告选项提示可能由于在 Internet 上使用其他选项而有异常问题。由于它的设计目标主要是优化性能,并不会改变路由器的基本行为,所以该选项通常比其他选项更常用。正如前面所提到的,有些路由器会实现高度优化的内部路径,用于那些不包含选项的 IP 流量转发。路由器警告选项用于通知路由器,一个分组需使用超出常规的转发算法来处理。在表 5-4 的结尾处,实验性的“快速启动”选项适用于 IPv4 和 IPv6 ,我们将在下一节讨论 IPv6 扩展头部和选项时介绍它。


5.3 IPv6 扩展头部

在 IPv6 中,那些由 IPv4 选项提供的特殊功能,通过在 IPv6 头部之后增加扩展头部实现。IPv4 路由和时间戳功能都采用这种方式,其他功能(例如分片和超大分组)很少在 IPv6 中使用(但仍需要),因此没有为它们在 IPv6 头部分配相应的位。基于这种设计, IPv6 头部固定为 40 字节,扩展头部仅在需要时添加。在选择 IPv6 头部为固定大小时,要求扩展头部仅由终端主机(仅有一个例外)处理, IPv6 设计者简化了高性能路由器的设计和实现,这是因为 IPv6 路由器处理分组所需的命令比 IPv4 简单。实际上,分组处理性能受很多因素影响,包括协议复杂性、路由器硬件和软件功能,以及流量负载等。

扩展头部和更高层协议(例如 TCP 或 UDP)头部与 IPv6 头部链接起来构成级联的头部(见图 5-6)。每个头部中的下一个头部字段表示紧跟着的头部的类型,它可能是一个 IPv6 扩展头部或其他类型。值 59 表示这个头部链的结尾。下一个头部字段的可能值定义在 [IP6PARAM] 中,并在表 5-5 中列出了其中的大多数。

图 5-6

图 5-6 IPv6 头部使用下一个头部字段形成一个链。链中的头部可以是 IPv6 扩展头部或传输层头部。 IPv6 头部出现在数据报的开头,并且长度始终为 40 字节

表 5-5 IPv6 下一个头部字段值可能表示扩展头部或其他协议头部。在适当情况下,它与 IPv4 协议字段使用相同值
头部类型 顺序 参考文献
IPv6 头部 1 41 [RFC2460] [RFC2473]
逐跳选项(HOPOPT) 2 0 [RFC2460],紧跟在 IPv6 头部之后
目的地选项 3,8 60 [RFC2460]
路由 4 43 [RFC2460] [RFC5095]
分片 5 44 [RFC2460]
封装安全载荷(ESP) 7 50 (见第 18 章)
认证(AH) 6 51 (见第 18 章)
移动(MIPv6) 9 135 [RFC6275]
(无——没有下一个头部) 最后 59 [RFC2460]
ICMPv6 最后 58 (见第 8 章)
UDP 最后 17 (见第 10 章)
TCP 最后 6 (见第 13 ~ 17 章)
各种其他高层协议 最后 —— 见 [AN] 中的完整列表

我们从表 5-5 中可以看到, IPv6 扩展头部机制将一些功能(例如路由和分片)与选项加以区分。除了“逐跳选项”的位置之外(它是强制性的),扩展头部的顺序是建议性的,因此一个 IPv6 实现必须按接收的顺序处理扩展头部。只有“目的地选项”头部可以使用两次,第一次是指出包含在 IPv6 头部中的目的 IPv6 地址,第二次(位置 8)是关于数据报的最终目的地。在某些情况下(例如使用路由头部),当数据报被转发到最终目的地时, IPv6 头部中的目的 IP 地址字段将会改变。

5.3.1 IPv6 选项

我们已经看到,相对于 IPv4, IPv6 提供了一种更灵活和可扩展的方式,将扩展和选项相结合。由于 IPv4 头部空间的限制,那些来自 IPv4 的选项已停止使用,而 IPv6 可变长度的扩展头部或编码在特殊扩展头部中的选项可适应当前更大的 Internet。如果选项存在,可放入逐跳选项(与一个数据报传输路径上的每个路由器相关)或目的地选项(仅与接收方相关)。逐跳选项(称为HOPOPT)是唯一由分组经过的每个路由器处理的选项。逐跳选项和目的地选项的编码格式一样。

逐跳选项和目的地选项头部的出现可以超过一次。这些选项均被编码为 类型 - 长度 - 值(TLV) 集合,对应于 图5-7 中所示格式。

图 5-7

图 5-7 逐跳选项和目的地选项编码为 TLV 集合。第一字节给出了选项类型,包括一些子字段,在选项没被识别时指示一个 IPv6 节点如何动作,以及在数据报转发时选项数据是否改变。选项数据长度字段给出了选项数据的字节长度

TLV 结构如图 5-7 所示,它的长度为 2 字节,后面是可变长度的数据字节。第一字节表示选项类型,其中包括 3 个子字段。当 5 位的类型子字段无法由选项识别时,第一个子字段给出了一个 IPv6 节点尝试执行的动作。表 5-6 显示了所有可能的值。

表 5-6 一个 IPv6 的 TLV 选项类型的 2 个高序位,表示如果这个选项没有被识别,一个 IPv6 节点是转发还是丢弃该数据报,以及是否向发送方返回一个消息,提示这个数据报的处理结果
动作
00 跳过选项,继续处理
01 丢弃这个数据报(沉默)
10 丢弃这个数据报,并向原地址发送一个“ICMPv6 参数问题”消息
11 与 10 相同,但仅在分组的目的地不是组播时,发送这个 ICMPv6 消息

如果一个发往组播目的地的数据报中包括一个未知选项,那么大量节点将生成返回源节点的流量。这可通过将动作子字段设置为 11 来避免。动作子字段的灵活性在开发新的选项时是有用的。一个新的选项可携带在一个数据报中,并被那些无法理解它的路由器所忽略,这样有助于促进新选项的增量部署。当选项数据可能在数据报转发过程改变时,改变位字段(图 5-7 中的 Chg)设置为 1。表 5-7 中所示的选项已被 IPv6 定义。

表 5-7 IPv6 选项携带在逐跳(H)选项或目的地(D)选项扩展头部中。选项类型字段包含来自“类型”列以及动作和改变子字段中的二进制值。“长度”列包含来自图 5-7 的选项数据长度字节中的值。填充 1 是唯一没有该字节的选项
选项名 头部 动作 改变 类型 长度 参考文献
填充 1 HD 00 0 0 N/A [RFC2460]
填充 N HD 00 0 1 可变 [RFC2460]
超大有效载荷 H 11 0 194 4 [RFC2675]
隧道封装限制 D 00 0 4 4 [RFC2473]
路由器警告 H 00 0 5 4 [RFC2711]
快速启动 H 00 1 5 8 [RFC4782]
CALIPSO H 00 0 7 8+ [RFC5570]
家乡地址 D 11 0 201 16 [RFC6275]

5.3.1.1 填充 1 和填充 N

由于 IPv6 选项需要与 8 字节的偏移量对齐,因此较小的选项用 0 填充到长度为 8 字节。这里有两个填充选项,分别称为填充 1 和填充 N。填充 1 选项(类型 0)是唯一缺少长度字段和字段的选项。它仅有 1 字节长,取值为 0。填充 N 选项(类型 1)向头部的选项区域填充 2 字节或更多字节,它使用图 5-7 所示格式。对于″个填充字节,选项数据长度字段包含的值为(n - 2)。

5.3.1.2 IPv6 超大有效载荷

在某些 TCP/IP 网络中,例如那些用于互连超级计算机的网络,由于正常的 64KB 的 IP 数据报大小限制,在传输大量数据时会导致不必要的开销。 IPv6 超大有效载荷选项指定了一种有效载荷大于 65535 字节的 IPv6 数据报,称为超大报文。这个选项无法由 MTU 小于 64KB 的链路连接的节点来实现。超大有效载荷选项提供了一个 32 位的字段,用于携带有效载荷在 65535 ~ 4294967295 字节之间的数据报。

当一个用于传输的超大报文形成时,其正常负载长度字段被设置为 0。我们将在后面看到, TCP 协议使用负载长度字段,计算由前面所述的 Internet 校验和算法得到的校验和。当使用超大有效载荷选项时, TCP 必须使用来自选项的长度值,而不是基本头部中的长度字段值。虽然这个过程并不困难,但更大有效载荷使得未检测出错误的可能性增大 [RFC2675]。

5.3.1.3 隧道封装限制

隧道是指将一个协议封装在另一个协议中(见第 1 章和第 3 章)。例如, IP 数据报可能被封装在另一个 IP 数据报的有效载荷部分。隧道可用于形成虚拟的覆盖网络,在覆盖网络中,一个网络(例如 Internet)可作为另一个 IP 的链路层使用 [TWEF03]。隧道可以嵌套,从这个意义上来说,一条隧道中的数据报本身也可采用递归方式封装在另一条隧道中。

在发送一个 IP 数据报时,发送者通常无法控制最终用于封装的隧道层次。发送者可使用这个选项设置一个限制。一台路由器打算将一个 IPv6 数据报封装在一条隧道中,它首先检查隧道封装限制选项是否存在并置位。如果这个限制选项的值为 0,该数据报被丢弃,并将一个“ICMPv6 参数间题”消息(见第 8 章)发送到数据报源端(即之前的隧道入口点)。如果这个限制选项的值不为 0,该数据报可进行隧道封装,但新形成(封装)的 IPv6 数据报必须包括一个隧道封装限制选项,其值比封装之前的数据报中的封装限制选项值减 1。实际上,封装限制行动类似于 IPv4 的 TTL 和 IPv6 的跳数限制字段,只不过采用隧道封装层次代替转发跳步。

5.3.1.4 路由器警告

路由器警告选项指出数据报包含需要路由器处理的信息。它与 IPv4 的路由器警告选项的目的相同。 [RAOPTS] 给出了这个选项的当前设置值。

5.3.1.5 快速启动

**快速启动(QS)**选项和 [RFC4782] 定义的 TCP/IP 实验性“快速启动”程序配合使用。它适用于 IPv4 和 IPv6,但目前建议仅用于专用网络,而不是全球性的 Internet。选项包括发送者需要的以比特/秒为单位的传输速率的编码值、 QS TTL 值和一些额外信息。如果沿途的路由器认为可以接受所需的速率,在这种情况下它们将递减 QS TTL,并在转发数据报时保持所需的速率不变。如果路由器不同意(即其支持的速率较低),它将该速率减小到一个可接受的速率。如果路由器不能识别 QS 选项,它将不递减 QS TTL。接收方将向发送方提供反馈,包括接收到的数据报的 IPv4 TTL 或 IPv6 跳数限制字段和自己的 QS TTL 之间的差异,以及获得的速率可能被沿途的路由器所调整。这个信息被发送方用于确定发送速率(否则可能超出 TCP 使用的速率)。对 TTL 值进行比较的目的是确保沿途每台路由器参与 QS 谈判。如果发现任何路由器递减 IPv4 TTL (或 IPv6 跳数限制)字段,但没有修改 QS TTL 值,则说明它没有启用 QS。

5.3.16 CALIPSO

这个选项用于在某些专用网络中支持通用体系结构标签 IPv6 安全选项(CALIPSO) [RFC5570]。它提供了一种为数据报做标记的方法,包括一个安全级别标识符和一些额外的信息。需要注意的是,它用于多级安全网络环境(例如,政府、军队和银行),其中所有数据的安全级别必须以某种形式的标签注明。

5.3.1.7 家乡地址

当使用 IPv6 移动选项时,这个选项保存发送数据报的 IPv6 节点的“家乡”地址。移动 IP (见 5.5 节)规定了 IP 节点的一系列处理过程,这些节点可能改变自已的网络接入点,同时不会断开自已的高层网络连接。这里存在一个节点的“家乡”的概念,它来自其典型位置的地址前缀。当远离家乡漫游时,通常为该节点分配一个不同的 IP 地址。该选项允许这个节点提供自己正常的家乡地址,以及它在漫游时的新地址(通常是临时分配)。当其他 IPv6 节点需要与移动节点通信时,它可以使用该节点的家乡地址。如果家乡地址选项存在,包含它的目的地选项头部必须出现在路由头部之后,并且在分片、认证ESP 头部(见第 18 章)之前(如果这些头部也存在)。我们将在移动 IP 中详细讨论这个选项。

5.3.2 路由头部

IPv6 路由头部为发送方提供了一种 IPv6 数据报控制机制,以控制(至少部分控制)数据报通过网络的路径。目前,路由扩展头部有两个不同版本,分别称为类型 0 (RH0)和类型 2 (RH2)。 RH0 出于安全方面的考虑已被否决 [RFC5095], RH2 被定义为与移动 IP 共同使用。为了更好地理解路由头部,我们首先讨论 RH0,然后研究它为什么被放弃,以及它和 RH2 的不同之处。 RH0 规定了数据报转发时可“访问”的一个或多个 IPv6 节点。图 5-8 显示了这个头部。

图 5-8

图 5-8 目前已废弃的路由头部类型 0(RH0)涵盖了 IPv4 的宽松和严格的源路由记录路由选项。它在数据报转发时由发送方构造,其中包括转发路径上的 IPv6 节点地址。每个地址可指定为一个宽松或严格的地址。一个严格的地址必须经过一个 IPv6 跳步到达,而一个松散的地址可能经过一个或多个其他跳步到达。在 IPv6 基本头部中,目的 IP 地址字段修改为包含数据报转发的下一个转发地址

图 5-8 所示的 IPv6 路由头部涵盖了来自 IPv4 的宽松源路由记录路由选项。它还支持采用 IPv6 地址之外的其他标识符路由的可能性,这个功能是不规范的,这里没有进一步讨论。对于标准化的 IPv6 地址的路由, RH0 允许发送方指定一个指向目的地址的向量。

这个头部包含一个 8 位的路由类型标识符和一个 8 位的剩余部分字段。对于 RH0, IPv6 地址类型标识符为 0 ;对于 RH2,该标识符为 2。剩余部分字段指出还有多少段路由需要处理,也就是说,在到达最终目的地之前仍需访问的中间节点数。它是一个 32 位的从保留字段开始的地址块,由发送方设置为 0,并由接收方忽略。在数据报转发时,这些地址并非可访问的组播 IPv6 地址。