第四章 网络层:数据平面
第四章 网络层:数据平面
我们在前一章中了解到,传输层通过依赖于网络层的主机到主机(host-to-host)通信服务来提供各种形式的进程到进程通信。我们还了解到,传输层这样做时并不知道网络层实际上是如何实现这个服务的。因此,您现在可能想知道,主机到主机通信服务的底层原理是什么?是什么让它发挥作用?
在本章和下一章中,我们将准确地了解网络层如何提供它的主机到主机通信服务。我们将看到,与传输层和应用层不同, 在网络中的每台主机和路由器中都有一个网络层。 因此,网络层协议是协议栈中最具挑战性(因此也是最有趣的!)的协议之一。
由于网络层可以说是协议栈中最复杂的一层,因此我们将在这里讨论很多内容。实际上,有很多内容要讲,所以我们用两章来讨论网络层。我们将看到网络层可以分解为两个相互作用的部分, 数据平面 (data plane)和 控制平面 (control plane)。在第四章,我们首先会介绍网络层的数据平面功能——网络层的 逐路由器(per-router) 功能决定一个到达路由器输入链路的数据报如何转发到该路由器的输出链路之一。我们将讨论传统的IP转发(转发基于数据报的目标地址)和广义转发(转发和其他功能可以使用数据报头中几个不同字段中的值来执行)。我们将详细研究IPv4和IPv6协议和地址。在第5章中,我们将介绍网络层的控制平面功能—— network-wide 逻辑控制数据报如何沿着从源主机到目标主机的端到端路径在路由器之间路由。我们将介绍目前在因特网上广泛使用的OSPF、BGP等路由协议和路由算法。传统上,这些控制平面路由协议和数据平面转发功能是在一个路由器中一起实现的。软件定义网络(software defined networking, SDN)将数据平面和控制平面作为一个独立的服务实现,通常在远程控制器中实现。我们还将在第5章中介绍SDN控制器。
网络层中数据平面和控制平面功能之间的区别是一个重要的概念,在您学习网络层时,它将帮助您构建对网络层的思考,并反映出网络层在计算机网络中的作用的现代观点。
网络层概述
图4.1展示了一个简单的网络,其中有两台主机H1和H2,在H1和H2之间的路径上有几台路由器。假设H1向H2发送信息,考虑网络层在这些主机和中间路由器中的作用。H1中的网络层从H1中的传输层获取段,将每个段封装成一个数据报,然后将数据报发送到它附近的路由器R1。在接收主机H2上,网络层接收来自其附近路由器R2的数据报,提取传输层段,并将这些段交付给H2传输层。每个路由器数据平面的主要作用是将数据报从输入链路转发到输出链路;网络控制平面的主要作用是协调这些本地的、逐路由器(per-router)的转发操作,从而使数据报最终沿着源主机和目标主机之间的路由器路径端到端地传输。请注意,图4.1中的路由器显示了一个截取的协议栈,也就是说,在网络层之上没有更高的层,因为路由器不运行应用程序和传输层协议,比如我们在第2章和第3章中探讨的那些协议。
4.1.1转发和路由:数据和控制平面
网络层的主要作用看似简单——只是将数据包从发送主机移动到接收主机。为此,可以确定两个重要的网络层功能:
- 转发 当数据包到达路由器的输入链路时,路由器必须将数据包移动到相应的输出链路。例如,在图4.1中,一个从主机H1到达路由器R1的数据包必须被转发到下一个通往H2的路由器。正如我们将看到的,转发只是在数据平面中实现的一个功能(尽管是最重要的一个!)。在更一般的情况下,我们会在4.4节讨论,一个数据包也可能被阻止离开路由器(例如,如果数据包是在已知的恶意发送主机上,或者数据包是注定要被禁止的目标主机),或可能被复制和发送到多个传出链路。
- 路由 网络层必须确定数据包从发送方流向接收方时所采用的路由或路径。计算这些路径的算法称为 路由算法 (routing algorithms)。例如,路由算法会确定图4.1中数据包从H1流向H2的路径。路由在网络层的控制平面实现。
在讨论网络层时,转发(Forwarding)和路由(Routing)这两个术语经常可以互换使用。我们将在本书中更精确地使用这些术语。转发是指将数据包从输入链路接口转移到恰当的输出链路接口。转发发生在非常短的时间尺度(通常是几纳秒),因此通常是在硬件中实现的。路由是指network-wide的过程,它决定数据包从源到目的地的端到端路径。路由发生在更长的时间尺度上(通常是秒),正如我们将看到的,通常是在软件中实现的。使用我们的驾驶类比,考虑我们的旅行者在第1.3.1节中从宾夕法尼亚到佛罗里达的旅行。在这趟旅行中,我们的司机在去佛罗里达的路上要经过许多换乘站。我们可以把转发想象成通过一个换乘站的过程:一辆汽车从一条路进入换乘站,并决定从哪条路离开换乘站。我们可以把路线设计看作是规划从宾夕法尼亚到佛罗里达旅程的过程:在开始旅程之前,司机会参考地图,从许多可能的路径中选择一条,每条路径都由一系列在换乘站连接的路段组成。
每个网络路由器的一个关键元素是它的 转发表 (forwarding table)。路由器通过检查到达的数据包头中的一个或多个字段的值来转发数据包,然后使用这些头值在转发表中建立索引。这些值存储在转发表项中,表示该数据包将被转发到该路由器的传出链路接口。例如,在图4.2中,一个头字段值为0110的数据包到达了路由器。路由器索引到其转发表,并确定该数据包的输出链路接口为接口2。路由器然后在内部将数据包转发到接口2。在第4.2节中,我们将深入了解路由器并更详细地探讨转发功能。转发是网络层的数据平面功能所执行的关键功能。
控制平面:传统方法
但是,现在你肯定想知道路由器的转发表最初是如何配置的。这个问题很关键,暴露了转发(在数据平面)和路由(在控制平面)之间相互影响的重要性。如图4.2所示,路由算法决定了路由器转发表的内容。本例中,路由算法运行在每台路由器上,同时包含转发和路由功能。正如我们将在5.3和5.4节中看到的,一台路由器的路由算法功能与其他路由器的路由算法功能通信,计算出它的转发表的值。这种通信是如何执行的?通过根据路由协议交换包含路由信息的路由消息!我们将在章节5.2到5.4中讨论路由算法和协议。
假设网络中的所有转发表都由物理存在于路由器上的网络操作员直接配置,这种假设(虽然不现实,但在技术上是可行的)可以进一步说明转发和路由功能的不同用途。在这种情况下,不需要任何路由协议!当然,人工操作人员需要彼此交互,以确保转发表的配置方式使数据包到达它们的预期目的地。与路由协议相比,人工配置可能更容易出错,对网络拓扑变化的响应也会更慢。幸运的是,所有的网络都有转发和路由功能。
控制平面:SDN方法
如图4.2所示,每个路由器都有一个路由组件来与其他路由器的路由组件通信,这种实现路由功能的方法一直是路由供应商在其产品中采用的传统方法,至少直到最近才有所改变。我们观察到,人类可以手动配置转发表,然而,控制平面功能可能有其他方法来确定数据平面转发表的内容。
图4.3显示了另一种方法,在这种方法中,一个物理上独立的远程控制器计算并分配每个路由器使用的转发表。请注意,图4.2和4.3中的数据平面组件是相同的。在图4.3中,然而,控制平面的路由功能与物理路由器是分离的——路由设备只执行转发,远程控制器计算和分配路由表。远程控制器可以在高可靠性和冗余性的远程数据中心中实现,由ISP或其他第三方管理。路由器和远程控制器如何通信?通过交换包含转发表和其他路由信息的消息。图4.3所示的控制平面方法是软件定义网络(SDN,software-defined networking)的核心,其中网络是软件定义的,因为计算转发表和与路由器交互的控制器是在软件中实现的。更甚者,这些软件实现也是开放的,也就是说,类似于Linux操作系统的代码,这些代码是公开的,允许ISP(以及网络研究人员和学生!)对控制网络层功能的软件进行创新和建议更改。我们将在5.5节中介绍SDN控制平面。
4.1.2网络服务模型
在深入研究网络层的数据平面之前,让我们以更广泛的视角来结束我们的介绍,并考虑网络层可能提供的不同类型的服务。当发送主机的传输层将数据包传输到网络中时(即,将其从发送主机向下传递到网络层),传输层能否依靠网络层将数据包交付到目的地?当发送多个数据包时,它们会按照发送的顺序被发送到接收主机的传输层吗?两个连续数据包传输之间的时间是否与它们接收之间的时间相同?网络会提供任何关于网络拥塞的反馈吗?这些问题和其他问题的答案由网络层提供的服务模型确定。 网络服务模型 (network service model)定义了发送主机和接收主机之间端到端交付数据包的特征。
现在让我们考虑网络层可以提供的一些可能的服务。这些服务可以包括:
- 保证交付 。该服务保证由源主机发送的数据包最终会到达目标主机。
- 以有限的延迟交付 该服务不仅保证数据包的交付,而且保证在指定的主机到主机延迟内的交付(例如,在100毫秒内)。
- 有序数据包交付 这个服务保证数据包按照发送的顺序到达目的地。
- 保证最小的带宽 这个网络层服务模拟传输链路的发送主机和接收主机之间指定比特率(例如,1mbps)的行为。只要发送主机以低于指定比特率的速率发送比特(作为数据包的一部分),那么所有的数据包最终都会发送到目标主机。
- 安全 网络层可以在源端加密所有数据报,在目标端解密它们,从而为所有传输层段提供机密性。
这只是网络层可以提供的服务的一部分——有无数变化的可能。
因特网的网络层提供单一的服务,被称为尽力而为服务(best-effort service)。使用这个服务,既不能保证数据包按照发送的顺序被接收,也不能保证最终交付。没有端到端延迟保证,也没有最小的带宽保证。尽力而为服务似乎是完全没有服务的一种委婉说法——没有向目的地发送数据包的网络将满足尽力而为服务的定义!其他网络体系结构已经定义和实现了超越Internet的尽力而为服务的服务模型。例如,ATM网络架构[Black 1995]提供了有保证的有序延迟、有限的延迟和有保证的最小带宽。也有人建议将服务模型扩展到互联网架构;例如,Intserv架构[RFC 1633]旨在提供端到端延迟保证和无拥塞通信。有趣的是,尽管有这些发达的替代品,Internet的基本尽力服务模型,加上足够的带宽供应和带宽自适应的应用层协议(如我们在第2.6.2节中遇到的DASH协议),已经被证明足够好,可以实现一系列惊人的应用程序,包括Netflix等流媒体视频服务,以及Skype和Facetime等实时会议应用。
第四章概述
在概述了网络层之后,我们将在本章接下来的章节中介绍网络层的数据平面组件。在第4.2节中,我们将深入研究路由器的内部硬件操作,包括输入和输出数据包处理,路由器的内部交换机制,以及数据包排队和调度。在4.3节中,我们将介绍传统的IP转发,即根据目标IP地址将数据包转发到输出端口。我们将遇到IP地址,著名的IPv4和IPv6协议等。在4.4节中,我们将讨论广义转发,其中数据包可能会根据大量的头值(即,不仅仅是根据目标IP地址)被转发到输出端口。数据包可能在路由器上被阻塞或复制,或者某些头字段值可能在软件控制下被重写。这种更普遍的数据包转发形式是现代网络数据平面的关键组成部分,包括软件定义网络(SDN)中的数据平面。在第4.5节中,我们将了解除了转发之外还可以执行其他功能的中间件。
我们在这里顺便提到,术语转发和交换经常被计算机网络研究人员和从业人员互换使用;在本教科书中,这两个术语也可以互换使用。当我们讨论术语这个话题时,还需要提到另外两个经常可以互换使用的术语,但我们将更加小心地使用它们。我们将保留术语数据包交换机(packet switch)是指一般的数据包交换设备,根据数据包的头字段的值,把数据包从输入链路接口传输到输出链路接口。有些数据包交换机称为 链路层交换机 (link-layer switches,在第6章中讨论),它们的转发决策基于链路层帧字段中的值;因此,交换机被称为链路层(第2层)设备。其他数据包交换机(称为路由器)根据网络层数据报中头字段值做出转发决策。因此,路由器是网络层(第三层)设备。(要充分理解这个重要的区别,您可能需要回顾一下1.5.2节,在该节中我们讨论了网络层数据报和链路层帧及其关系。)由于本章的重点是网络层,我们将主要使用术语路由器来代替数据包交换机。
4.2路由器内部是什么?
既然我们已经概述了网络层的数据和控制平面,了解了转发和路由之间的重要区别,以及网络层的服务和功能,让我们把注意力转向它的转发功能,即数据包从路由器的传入链路到该路由器适当的传出链路的实际传输。
通用路由器架构的高级视图如图4.4所示。可以识别出四个路由器组件:
- 输入端口 输入端口执行几个关键功能。其在路由器上执行结束进来的物理链路的物理层功能;在图4.4中,输入端口的最左边的框和输出端口的最右边的框显示了这一点。输入端口还执行与传入链路另一端的链路层互操作所需的链路层功能;这由输入和输出端口中中间的框表示。也许最重要的是,查找功能也在输入端口执行;这将发生在输入端口的最右边的框中。在这里,转发表被用来确定路由器的输出端口,到达的数据包将通过交换结构(switching fabric)转发到哪个端口。控制数据包(例如,携带路由协议信息的数据包)从输入端口转发到路由处理器。请注意,这里的术语端口指的是路由器物理输入和输出接口,它与第2章和第3章中讨论的与网络应用程序和套接字相关的软件端口明显不同。在实践中,路由器支持的端口数量有少有多,企业路由器较少,ISP边缘路由器支持数百个10Gbps端口(输入线路的数量往往是最大的)。例如,边缘路由器JunIPer MX2020支持800个100Gbps以太网端口,整体路由器系统容量为800Tbps [JunIPer MX2020 2020]。
- 交换结构 交换结构将路由器的输入端口连接到它的输出端口。这种交换结构完全包含在路由器中——一个网络路由器中的网络!
- 输出端口 输出端口存储从交换结构接收到的数据包,并通过执行必要的链路层和物理层功能将这些数据包发送到传出链路上。当链路是双向的(即在两个方向承载流量)时,输出端口通常会与同一线卡(line card)上该链路的输入端口配对。
- 路由处理器(Routing processor) 路由处理器执行控制平面功能。在传统路由器中,它执行路由协议(我们将在章节5.3和5.4中学习),维护路由表和附加的链路状态信息,并为路由器计算转发表。在SDN路由器中,路由处理器负责与远程控制器通信,以便接收远程控制器计算的转发表项,并将这些转发表项安装在路由器的输入端口上。路由处理器还执行我们将在第5.7节中研究的网络管理功能。
路由器的输入端口、输出端口和交换结构几乎都是在硬件中实现的,如图4.4所示。要理解为什么需要硬件实现,请考虑使用100 Gbps的输入链接和64字节的IP数据报,在另一个数据报到达之前,输入端口只有5.12 ns来处理该数据报。如果在一个线卡上合并N个端口(在实践中经常这样做),那么数据报处理管道的运行速度将快N倍——对于软件实现来说太快了。转发硬件既可以使用路由器供应商自己的硬件设计来实现,也可以使用购买的商用硅芯片(例如,由英特尔和博通等公司销售)来构建。
当数据平面以纳秒级的时间尺度运行时,路由器的控制功能以毫秒级或秒级运行,执行路由协议、响应连接的链路上行或下行、与远程控制器通信(在SDN的情况下)、执行管理功能。因此,这些控制平面的功能通常在软件中实现,并在路由处理器(通常是传统的CPU)上执行。
在深入研究路由器内部的细节之前,让我们回到本章开始时的类比,将数据包转发比作进出换乘站的汽车。假设换乘站是一个环岛(roundabout),当一辆汽车进入环岛时,需要进行一些处理。让我们考虑一下这个处理需要什么信息:
- 基于目的地的转发 假设汽车停在一个入口站,并指示其最终目的地(其旅程的最终目的地)。入口站的工作人员查找最终目的地,确定通往最终目的地的环岛出口,并告诉司机该走哪个出口。
- 广义转发(Generalized forwarding) 除了目的地之外,乘务员还可以根据很多其他因素来确定车辆的出口匝道。例如,选择的出口匝道可能取决于汽车的起源,例如颁发汽车牌照的州。来自特定一组州的汽车可能被引导使用一个出口匝道(通过一条慢车道通向目的地),而来自其他州的汽车可能被引导使用一个不同的出口匝道(通过高速公路通往目的地)。同样的决定也可能是基于汽车的型号、品牌和年份。或者,一辆被认为不适合上路的汽车可能会被阻塞,不允许通过该环岛。在广义转发的情况下,任何一种因素都可能影响乘务员对给定车辆出口匝道的选择。
一旦车辆进入环岛(可能会有其他车辆从其他输入道路进入并驶往其他出口),车辆最终会在指定的出口匝道离开,并可能在该出口遇到其他车辆。
在这个类比中,我们可以很容易地识别图4.4中的主要路由器组件,入口道路和入口站对应于输入端口(通过一个查找功能来确定本地输出端口);所述环岛对应于交换结构;所述环岛出口道路对应输出端口。通过这个类比,考虑瓶颈可能出现的地方是很有指导意义的。如果车开得非常快(比如,环岛在德国或意大利!)而车站工作人员却很慢,那该怎么办?服务员必须以多快的速度工作,以确保在入口道路上没有候补?即使有一个快得惊人的乘务员,如果车辆缓慢地通过环岛会发生什么——还会发生候补吗?如果在环岛所有入口匝道上进入的大部分车辆都想在同一个出口匝道上离开环岛——那么在出口匝道或其他地方会发生候补吗?如果我们想给不同的车辆分配优先级,或者在一开始就阻止某些车辆进入环岛,环岛应该如何运行?这些都类似于路由器和交换机设计者所面临的关键问题。
在下面的小节中,我们将更详细地查看路由器功能。[Turner 1988; McKeown 1997a; Partridge 1998; Iyer 2008; Serpanos 2011; Zilberman 2019]提供了关于特定路由器架构的讨论。为了具体和简单,在本节中,我们首先假定转发决策仅基于数据包的目标地址,而不是基于一组通用的数据包头字段。我们将在第4.4节中讨论更广义的数据包转发的情况。
输入端口处理和基于目标的转发
图4.5显示了输入处理的更详细视图。正如刚才讨论的,输入端口的线路中止(line-termination)功能和链路层处理为独立的输入链路实现了物理层和链路层。在输入端口执行的查找是路由器最重要的操作——在这里,路由器使用转发表查找输出端口,到达的数据包将通过交换结构转发到这个端口。转发表由路由处理器(使用路由协议与其他网络路由器中的路由处理器交互)计算和更新,或者从远程SDN控制器接收。转发表通过一个单独的总线(bus,例如PCI bus)从路由处理器复制到线卡,如图4.4中从路由处理器到输入线卡的虚线所示。在每个线卡上都有这样一个卷影复制(shadow copy),转发决策可以在本地、在每个输入端口上做出,而无需在每个数据包的基础上调用集中式路由处理器,从而避免了集中式处理瓶颈。
现在让我们考虑一个最简单的情况,传入数据包要交换到的输出端口基于数据包的目标地址。在32位IP地址的情况下,对转发表的蛮力实现对每个可能的目标地址都有一个表项。因为有超过40亿个可能的地址,这个选择是完全不可能的。
作为如何处理这种规模问题的一个例子,让我们假设我们的路由器有4条链路,编号为0到3,并且数据包将被转发到如下的链路接口:
显然,在本例中,路由器的转发表中没有必要有40亿项。例如,我们可以有一个只有4个表项的转发表:
在这种转发表中,路由器将数据包目标地址的 前缀 与表项进行匹配;如果有匹配项,路由器将数据包转发到与该匹配项相关的链路上。例如,假设数据包的目标地址为11001000 00010111 00010110 10100001;由于该地址的21位前缀与该表的第一个表项匹配,因此将数据包转发到链路接口0。如果前缀没有匹配前三个表项,则将数据包转发到默认接口3。虽然这听起来很简单,但这里有一个非常重要的微妙之处。您可能已经注意到,一个目标地址可以匹配多个表项。例如:地址11001000 00010111 00011000 10101010的前24位匹配表中的第二项,地址的前21位匹配表中的第三项。当有多个匹配时,路由器使用 最长前缀匹配规则 (longest prefix matching rule);即查找表中最长的匹配项,将数据包转发到最长前缀匹配项对应的链路接口。当我们在4.3节更详细地学习Internet寻址时,我们将看到为什么使用最长前缀匹配规则。
考虑到转发表的存在,查找在概念上是简单的硬件逻辑,只是通过转发表查找最长的前缀匹配。但是在千兆比特传输速率下,这个查找必须以纳秒为单位执行(回想一下我们前面的例子,10 Gbps链路和64字节IP数据报)。因此,不仅必须在硬件上进行查找,而且还需要在一个大表中进行简单的线性搜索以外的技术;快速查找算法的调查可以在[Gupta 2001, Ruiz-Sanchez 2001]中找到。还必须特别注意内存访问次数,这导致设计采用嵌入式的芯片内(on-chip)的DRAM和更快的SRAM(用作DRAM缓存)存储器。在实践中,三元内容寻址存储器(TCAM)也经常用于查找[Yu 2004]。使用TCAM,一个32位的IP地址被引入到内存中,它在基本固定的时间内返回该地址的转发表项的内容。思科Catalyst 6500和7600系列路由器和交换机可以容纳多达100万个TCAM转发表项(Cisco TCAM 2014)。
一旦通过查找确定了数据包的输出端口,就可以将数据包发送到交换结构中。在某些设计中,如果来自其他输入端口的数据包目前正在使用该结构,则该数据包可能会被暂时阻止进入交换结构。阻塞的数据包将在输入端口排队,然后计划在稍后的时间点通过结构。我们稍后将进一步研究(在输入端口和输出端口)数据包的阻塞、排队和调度。尽管查找可能是输入端口处理中最重要的操作,但必须采取许多其他操作:(1)必须进行物理层和链路层处理,如前所述;(2)数据包的版本号,校验和和time-to-live字段——所有这些我们将在4.3节学习——必须检查和重写后两个字段;(3)用于网络管理的计数器(如接收到的IP数据报的数量)必须更新。
让我们以通过关注输入端口步骤的目标IP地址查询(match)和随后的发送数据包到交换结构再到指定的输出端口(action)的输入端口处理来结束我们的讨论,这是执行在许多网络设备上的“match plus action”抽象的一个具体案列,而不仅是路由器。在链路层交换机中(见第6章),除了将帧发送到交换结构的输出端口外,还需要查找链路层的目标地址并采取一些操作。在防火墙中(在第8章中涉及到)——过滤掉选中的输入数据包的设备——即数据包头匹配给定条件(例如,源/目标IP地址和传输层端口号的组合)的输入数据包可能会被丢弃(action)。在网络地址转换器(NAT,在4.3节中介绍)中,传输层端口号与给定值匹配的传入数据包将在转发(action)之前重写其端口号。事实上,匹配加操作抽象[Bosshart 2013]在当今网络设备中既强大又流行,是我们将在第4.4节中研究的广义转发概念的核心。
4.22 交换
交换结构是路由器的核心,因为数据包实际上是通过这个结构从输入端口交换(即转发)到输出端口的。交换可以通过多种方式完成,如图4.6所示:
- 通过内存交换 最简单、最早的路由器是传统计算机,在CPU(路由处理器)的直接控制下进行输入和输出端口的交换。在传统的操作系统中,输入和输出端口作为传统的I/O设备。带有输入数据包的输入端口首先通过一个中断(interrupt)向路由处理器发出信号。然后将数据包从输入端口复制到处理器内存中。然后,路由处理器从头中提取出目标地址,在转发表中查找适当的输出端口,并将数据包复制到输出端口的缓冲区。在此场景下,如果内存带宽达到每秒最多可写入或读取B个数据包,则总转发吞吐量(输入端口向输出端口传输数据包的总速率)必须小于B/2。还要注意,两个数据包不能同时转发,即使它们有不同的目标端口,因为在共享系统总线上,一次只能进行一个内存读/写操作。
一些现代路由器通过内存进行交换。然而,与早期路由器的主要区别是,目标地址的查找和数据包存储到适当的内存位置是通过在输入线卡上进行处理来完成的。在某些方面,通过内存进行交换的路由器看起来非常像多处理器共享内存,在线卡上进行处理,将数据包交换(写入)到相应的输出端口的内存中。思科的Catalyst 8500系列交换机[Cisco 8500 2020]内部通过共享内存交换数据包。
- 通过总线交换 在这种方法中,输入端口通过共享总线直接将数据包传输到输出端口,而不需要路由处理器的干预。这通常是通过让输入端口预挂一个switch-internal标签(头)到数据包,该数据包是在总线上传递到输出端口的数据包。所有输出端口都接收数据包,但只有匹配标签的端口将保留数据包。之后标签在输出端口被移除,因为这个标签只在交换机中被用来跨越总线。如果多个数据包同时到达路由器,每个都在不同的输入端口,所有的数据包都必须等待,因为在同一时间只有一个数据包可以通过总线。由于每一个数据包都必须经过单个总线,路由器的交换速度受到总线速度的限制;在我们的环岛类比中,这就好像环岛一次只能容纳一辆车。尽管如此,对于在小型局域网和企业网络中运行的路由器来说,通过总线进行交换通常已经足够了。思科6500路由器(Cisco 6500 2020)内部通过32-Gbps-backplane总线进行数据包交换。
- 通过互连网络交换 克服单一共享总线带宽限制的一种方法是使用更复杂的互连网络,例如过去在多处理器计算机体系结构中用来互连处理器的互连网络。交叉交换(crossbar switch)是由2N个总线组成的互连网络,N个输入端口连接到N个输出端口,如图4.6所示。每个垂直总线与每个水平总线在一个交叉点上相交,这个交叉点可以在任何时候由交换机结构控制器(其逻辑是交换结构本身的一部分)打开或关闭。当一个数据包到达端口A并需要转发到端口Y,交换机控制器关闭在总线A和Y交界处的交点,端口A随后发送数据包到其总线,(仅)由总线Y捡起。请注意,来自端口B的数据包可以同时转发到端口X,因为A-to-Y和B-to-X数据包使用不同的输入和输出总线。因此,与前两种交换方法不同,交叉交换能够并行转发多个数据包。交叉交换是非阻塞的——只要当前没有其他数据包被转发到输出端口,转发到输出端口的数据包就不会被阻止到达该输出端口。但是,如果来自两个不同输入端口的两个数据包要发送到同一个输出端口,那么其中一个必须在输入端等待,因为在任何给定的总线上,一次只能发送一个数据包。Cisco 12000系列交换机[Cisco 12000 2020]采用交叉交换网络;思科7600系列可以配置为使用总线或交叉交换[思科7600 2020]。
更复杂的互连网络使用多阶段交换元件(switching elements),允许来自不同输入端口的数据包通过多阶段交换结构,在同一时间向相同的输出端口前进。请参阅[Tobagi 1990]来了解交换机架构的概况。思科CRS采用三阶段非阻塞交换策略。路由器的交换容量也可以通过并行运行多个交换网络来扩展。在这种方法中,输入端口和输出端口连接到并行工作的N个交换结构。输入端口将一个数据包分成K个小块,然后通过这N个交换结构中的K个将这些小块发送到选定的输出端口,输出端口将这K个小块重新组装回原始数据包中。
4.2.3 输出端口处理
输出端口处理(如图4.7所示)获取存储在输出端口内存中的数据包并通过输出链路传输。这包括为传输选择(即调度)和出队数据包,以及执行所需的链路层和物理层传输功能。
4.2.4 哪里出现排队现象?
如果我们探讨如图4.7所示的输入和输出端口的功能和配置,很明显数据包队列可能出现在输入端口和输出端口,就像我们发现的案例一样,汽车可以在我们类比的环岛的输入和输出等交通路口。队列的位置和范围(无论是在输入端口队列还是在输出端口队列)将取决于流量负载、交换结构的相对速度和线路速度。现在让我们更详细地探讨这些队列,因为随着这些队列的增长,路由器的内存最终会耗尽,当没有内存可用来存储到达的数据包时,就会出现丢包的情况。回想一下,在我们之前的讨论中,我们说过“数据包在网络中丢失”或“在路由器上丢弃”。在路由器的这些队列中,这样的数据包实际上被丢弃和丢失了。
假设输入和输出的线路速度(传输速率)都为Rline数据包/每秒,并且有N个输入端口和N个输出端口。为了进一步简化讨论,我们假设所有的数据包都具有相同的固定长度,并且数据包以同步的方式到达输入端口。也就是说,在任何链路上发送数据包的时间等于在任何链路上接收数据包的时间,在这个时间间隔内,输入链路上可以有0个或1个数据包到达。定义交换结构的传输速率Rswitch作为数据包从输入端口移动到输出端口的速率。如果Rswitch比Rline快N倍,那么在输入端口上只会出现微不足道的排队。这是因为即使在最坏的情况下,即所有N个输入线路都在接收数据包,并且所有的数据包都被转发到同一个输出端口,每一批N个数据包(每个输入端口一个数据包)可以在下一批到达之前通过交换机结构清除掉。
输入队列
但是,如果交换机结构不够快(相对于输入线路的速度而言),无法没有延迟地通过该结构传输所有到达的数据包,会发生什么呢?在这种情况下,数据包排队也可以发生在输入端口,因为数据包必须加入输入端口队列,等待它们通过交换结构以被传输到输出端口。为了说明这个排队结果的重要性,考虑一个交叉交换结构和假设(1)所有链路的速度是相同的,(2)一个数据包可以从任何一个输入端口传输到一个给定的输出端口,所用的时间与在输入链路上接收一个数据包所需的时间相同,(3)数据包以FCFS(First Come First Served)的方式从给定的输入队列移动到预期的输出队列。多个数据包可以并行传输,只要它们的输出端口不同。但是,如果两个输入队列前面的两个数据包都去往同一个输出队列,那么其中一个数据包将被阻塞,必须在输入队列上等待,交换结构一次只能将一个数据包传输到给定的输出端口。
图4.8显示了一个示例,其中两个位于输入队列前面的数据包(用深色阴影表示)将发送到右上方同一个输出端口。假设交换机结构选择传输左上方队列前面的数据包。在这种情况下,左下角队列中深色阴影的数据包必须等待。但是,不仅这个深色阴影数据包必须等待,在左下方队列中,排在该数据包后面的浅色阴影数据包也必须等待,即使右侧中间的输出端口(浅色阴影数据包的目的地)可用。这种现象在输入队列的交换机中被称为HOL阻塞(head-of-the-line)——输入队列中的排队的数据包必须等待传输通过结构(即使它的输出端口是空闲的),因为它被队列头的另一个数据包阻塞。[Karol 1987]表明,由于HOL阻塞,在一定的假设下,一旦输入链路上的数据包到达率达到其容量的58%,输入队列将增长到无限长(非正式地,这相当于说,将发生重大的丢包)。在[McKeown 1997]中讨论了HOL阻塞的一些解决方案。
输出队列
接下来,让我们考虑在交换机的输出端口是否会发生排队。假设Rswitch比Rline快N倍,到达每个输入端口的数据包都去往同一个输出端口。在这种情况下,在发送一个数据包到传出链路上的时间内,将有N个新的数据包到达这个输出端口(N个输入端口各一个)。由于输出端口在一个单位时间内只能传输一个数据包(数据包传输时间),因此N个到达的数据包将不得不排队(等待),以便在传出链路上传输。那么在传输完刚排队的N个数据包中的一个的时间内又有N个数据包到达。因此,即使交换结构比端口线路速度快N倍,数据包队列也能在输出端口出现。最终,排队的数据包的数量会增长到足以耗尽输出端口的可用内存。
当没有足够的内存来缓冲传入的数据包时,必须做出决定,要么丢弃到达的数据包(称为drop-tail策略),要么删除一个或多个已经排队的数据包,为新到达的数据包腾出空间。在某些情况下,为了向发送方提供一个拥塞信号,在缓冲区满之前丢弃(或标记数据包的头)可能是有利的。这个标记可以使用我们在3.7.2节中学习的显式拥塞通知比特来完成。许多主动丢包和标记策略(统称为主动队列管理(AQM,active queue management)算法)已经被提出和分析[Labrador 1999, Hollot 2002]。最广泛的研究和实现的AQM算法之一是 随机早期检测 (RED,Random Early Detection)算法[Christiansen 2001]。最近的AQM策略包括PIE(the Proportional Integral controller Enhanced[RFC 8033])和CoDel [Nichols 2012]。
输出端口队列如图4.9所示。在t时刻,每个输入端口已经到了一个数据包,每个端口的目的地都是最上面的输出端口。假设线路速度相同,且交换机的运行速度是线路速度的三倍,一个时间单位后(即,在接收或发送数据包所需的时间内),所有三个原始数据包都被传输到传出端口,并排队等待传输。在下一个单位时间中,这三个数据包中的一个将通过传出链路传输。在我们的例子中,两个新的数据包已经到达交换机的传入端;这些数据包中的一个将发送到这个最上面的输出端口。这样排队的一个结果是,输出端口的数据包调度程序必须从排队的数据包中选择一个进行传输——我们将在下一节中讨论这个主题。
多少缓冲区才算“足够”?
我们上面的研究已经表明,当大量数据包到达路由器的输入端口或(更可能的)输出端口时,并且数据包到达速率临时超过了数据包转发的速率时,数据包队列是如何形成的。不匹配持续的时间越长,队列就越长,直到充满端口缓冲区,数据包被丢弃。一个自然的问题是,应该在一个端口提供多少缓冲。事实证明,这个问题的答案比人们想象的要复杂得多,并且可以教会我们很多关于网络边缘和网络核心中感知拥塞的发送者之间的微妙交互的知识。
多年来,对于缓冲区大小的经验法则[RFC 3439]是缓冲区的大小(B)应该等于平均往返时间(RTT,比如250msec)乘以链路容量(C)。因此,一个10-Gbps的链路RTT为250msec需要的缓冲区大小为:B = RTT * C = 2.5 Gbits。这个结果是基于对相对较少的TCP流的队列动态分析[Villamizar 1994]。然而,最近的理论和实验研究[Appenzeller 2004]表明,当大量独立的TCP流(N)通过一条链路时,需要的缓冲区大小为:B = RTT * C/√N。在核心网络中,大量TCP流通常通过大型骨干路由器链路,N的值可以很大,这种情况下所需缓冲区大小的明显要小的多。[Appenzeller 2004;Wischik 2005;Beheshti 2008]从理论、实现和操作的角度对缓冲区大小问题进行了非常可读的讨论。
人们不禁会想,缓冲越多越好——更大的缓冲区将允许路由器吸收数据包到达速率的较大波动,从而降低路由器的丢包率。但更大的缓冲区也意味着潜在的更长的排队延迟。对于游戏玩家和交互式电话会议用户来说,能接受的延迟也就几十毫秒。将每跳缓冲区的大小增加10倍以减少丢包可能会使端到端延迟也增加10倍!增加的RTT也使TCP发送方对初始的拥塞和/或丢包的响应变慢。这些基于延迟的考虑表明,缓冲是一把双刃剑——缓冲可以用来吸收流量中的短期统计波动,但也可能导致延迟和相关问题的增加。缓冲有点像盐——适量的盐能让食物更好吃,但过多的盐就不能吃了。
在上面的讨论中,我们隐式地假设许多独立的发送方在拥塞的链路上竞争带宽和缓冲区。虽然对于网络核心中的路由器来说,这可能是一个很好的假设,但在网络边缘,这可能不成立。图4.10(a)显示了一个家用路由器向远程游戏服务器发送TCP段。根据[Nichols 2012],假设发送一个数据包(包含玩家的一个TCP段)需要10毫秒,并且在通往游戏服务器的路径上有可以忽略不计的排队延迟,并且 RTT是200毫秒 。如图4.10(b)所示,假设t = 0时刻有25个突发数据包到达队列。这些排队的数据包每10毫秒发送一个,所以当t = 200毫秒时,第一个ACK到达,导致TCP发送方发送另一个数据包,这个数据包在主路由器的传出链路上排队。当t = 220时,下一个ACK到达,另一个TCP段由玩家释放并进入队列,第22个数据包正在传输,以此类推。您应该说服自己,在这种情况下,每次发送排队的数据包时,ACK计时(clocking)都会导致一个新的数据包到达队列,从而导致主路由器的出站链路的队列大小总是5个数据包!也就是说,端-端管道已满(以每10 ms一个数据包的路径瓶颈速率向目的地发送数据包),但排队延迟是恒定和持久的。因此,玩家对延迟感到不满,家长(甚至知道wireshark!)也会感到困惑,因为他或她不明白为什么延迟会持续存在,而且时间过长,即使在家庭网络上没有其他流量的情况下。
由于持久的缓冲而导致上面这个场景的长延迟叫做bufferbloat,这说明不仅吞吐量重要,而且小延迟也重要[Kleinrock 2018],边缘网络中发送者之间的交互和在网络中的队列是复杂和微妙的。我们将在第6章中研究的有线网络DOCSIS 3.1标准,最近添加了一个特定的AQM机制[RFC 8033, RFC 8034]来对抗缓冲区膨胀,同时保持大吞吐量性能。
4.2.5 数据包调度
现在让我们回到确定队列数据包在传出链路上传输的顺序的问题。毫无疑问,您自己在很多情况下都不得不排着长队等待,并观察到等待的客户是如何得到服务的,因此您肯定熟悉路由器中常见的排队规则。有先到先得(FCFS,也称为先进先出,FIFO)。英国人以在公共汽车站和市场上耐心有序地排队而闻名(“Oh, are you queueing?”)。 其他国家则实行优先服务原则,对一类等待服务的顾客给予优先服务,而不是其他等待服务的顾客。还有轮询排队,在这种情况下,客户再次被划分为不同的类别(与优先级排队一样),但每个类别的客户将依次获得服务。
先进先出(FIFO)
图4.11显示了FIFO链路调度规则的队列模型抽象。如果链路当前正忙着传输另一个数据包,到达链路输出队列的数据包将等待传输。如果没有足够的缓冲空间来容纳到达的数据包,那么队列的数据包丢弃策略就会决定数据包是否会被丢弃(丢失),或者是否会从队列中删除其他的数据包来为到达的数据包腾出空间,就像上面讨论的那样。在下面的讨论中,我们将忽略丢包。当数据包完全通过传出链路传输(即接收到服务)时,它将从队列中删除。
FIFO(也称为first-come-first-served,FCFS)调度原则以到达输出链路队列的相同顺序选择数据包进行链路传输。我们都很熟悉服务中心的先进先出排队,到达的顾客会排在单队的后面,保持秩序,然后当他们到达队伍的前面时,他们会得到服务。图4.12显示了运行中的FIFO队列。数据包到达由上面时间线之上的编号箭头表示,编号表示数据包到达的顺序。单个数据包的离开显示在下面的时间线之下。数据包在服务(正在传输)中花费的时间由两个时间线之间的阴影矩形表示。在我们的例子中,假设每个数据包需要三个单位的时间来传输。在FIFO规则下,数据包按照到达的顺序离开。注意,在数据包4离开后,链路保持空闲(因为数据包1到4已经被传输并从队列中移除),直到数据包5到达。
优先队列
在优先级队列模式下,数据包到达输出链路时,会根据优先级分类,如图4.13所示。在实践中,网络运营商可以配置一个队列,使携带网络管理信息的数据包(例如,由源或目标TCP/UDP端口号指示)接收优先于用户流量;此外,voice-over-IP数据包可能比非实时通信(如电子邮件数据包)获得优先级。每个优先级通常都有自己的队列。在选择要传输的数据包时,优先级队列规则将从具有最高优先级的非空队列(即有等待传输的数据包)发送数据包。在相同优先级中的数据包之间的选择通常以FIFO的方式完成。
图4.14演示了一个具有两个优先级的优先队列的操作。数据包1、3、4属于高优先级,数据包2、5属于低优先级。数据包1到达后,发现链路空闲,就开始传输。数据包1在传输过程中,数据包2和数据包3到达,分别进入低优先级队列和高优先级队列。数据包1传输后,数据包3 (一个高优先级数据包)被选择在数据包2之前传输(即使它更早到达,但它是一个低优先级数据包)。在数据包3的传输结束时,数据包2开始传输。数据包4(高优先级数据包)在数据包2(低优先级数据包)的传输过程中到达。在一个 非抢占优先权排队 (non-preemptive priority queuing)规则下,数据包的传输一旦开始就不会中断。此时数据包4排队等待数据包2传输完成,才开始传输。
网路中立
我们已经看到数据包调度机制(例如,优先流量调度规则如严格优先,和WFQ)可以用来为不同级别的流量提供不同级别的服务。确切地构成一类流量的定义由ISP决定,但可能基于IP数据报报头中的任何字段集。例如,IP数据报报头中的port字段可用于根据与该端口相关联的“知名服务”对数据报进行分类:SNMP网络管理数据报(端口161)可能被分配到比IMAP电子邮件协议(端口143或993)数据报更高的优先级,因此得到更好的服务。ISP还可能使用数据报的源IP地址,为某些公司(可能已经为该特权付费)发送的数据报提供优先级,而不是来自其他公司(未付费)发送的数据报。ISP甚至可以阻断某个特定公司或国家的源IP地址流量。有许多机制可以允许ISP为不同类型的流量提供不同级别的服务。真正的问题是什么政策和法律决定了ISP实际上可以做什么。当然,这些法律因国家而异;查看[Smithsonian 2017]的简短调查。在这里,我们将简要地考虑一下美国关于网络中立性的政策。
“网络中立”一词没有明确的决定,但美国联邦通信委员会在2015年3月发布的《关于保护和促进开放互联网的命令》(FCC 2015)提供了三条明确、明确的规则,这些规则现在经常与网络中立联系在一起:
- 没有阻塞 一个从事宽带互联网接入服务的人,在合理的网络管理下,不得屏蔽合法的内容、应用程序、服务或无害的设备。
- 没有节流 一个从事宽带互联网接入服务的人,在合理的网络管理下,不得因互联网内容、应用、服务或使用无害设备而损害或降低合法的互联网流量。
- 没有付费优先 一个从事宽带互联网接入服务的人,不得参与付费优先排序。付费优先化是指宽带提供商的网络管理直接或间接地偏爱某些流量而不是其他流量,包括通过使用诸如流量整形、优先化、资源预留或其他形式的优先流量管理等技术。
非常有趣的是,在该命令之前,ISP违反前两条规则的行为已经被观察到[Faulhaber 2012]。2005年,北卡罗来纳州的一家ISP同意停止阻止其客户使用Vonage的做法,Vonage是一种IP语音服务,与它自己的电话服务竞争。在2007年,康卡斯特被判定通过内部创建和发送TCP RST数据包到BitTorrent发送者和接收者,干扰BitTorrent P2P流量,这导致他们关闭他们的BitTorrent连接[FCC 2008]。
关于网络中立性的争论双方一直争论不休,主要集中在网络中立性在多大程度上为客户提供利益,同时促进创新。参见[Peha 2006, Faulhaber 2012, Economides 2017, Madhyastha 2017]。
2015年FCC关于保护和促进开放互联网的命令,禁止ISP封锁、限制或提供付费优先级,被2017年FCC恢复互联网自由秩序(FCC 2017)取代,该命令撤销了这些禁令,转而关注ISP透明度。有了这么多的兴趣和这么多的变化,可以说我们还没有看到在美国或其他地方关于网络中立性的最后一章。
轮询与加权公平排队(WFQ)
在轮循队列规则下,数据包被按优先队列分类。然而,在类之间没有严格的服务优先级,而是轮询调度程序在类之间替换服务。在最简单的轮询调度形式中,发送类1数据包,然后是类2数据包,接着是类1数据包,再接着是类2数据包,以此类推。所谓的 work-conserving queuing 原则,在有(任何类的)数据包排队等待传输时,永远不允许链路保持空闲。work-conserving轮询规则寻找给定类的数据包并在没有找到时将立即检查轮询序列中的下一个类。
图4.15演示了一个两类轮询队列的操作。本例中,数据包1、2、4属于第1类,数据包3、5属于第2类。数据包1在到达输出队列后立即开始传输。数据包2和3在数据包1传输期间到达,因此等待传输。在发送数据包1之后,链路调度程序寻找第2类数据包,从而发送数据包3。数据包3传输后,调度程序寻找第1类数据包,从而发送数据包2。数据包2传输后,数据包4是唯一排队的数据包;因此,它将在数据包2之后立即传输。
一种广泛应用于路由器的轮询队列的广义形式是所谓的加权公平队列(WFQ,weighted fair queuing)规则[Demers 1990;Parekh 1993]。WFQ如图4.16所示。在这里,到达的数据包被分类,并在相应的每类等待区排队。和轮询调度一样,WFQ调度程序将以循环的方式服务类——首先服务类1,然后服务类2,然后服务类3,然后(假设有三个类)重复服务模式。WFQ也是一种work-conserving的排队规则,因此当它发现一个空的类队列时,它将立即转移到服务序列中的下一个类。
WFQ与轮询的不同之处在于,每个类在任何时间间隔内都可能收到不同数量的服务。具体来说,每个类i被分配了一个权重wi。在WFQ模式下,在有第i类数据包需要发送的任何时间间隔内,第i类将被保证接收到一个等于wi/(Σwj)的服务分数,其中分母为所有队列中也有数据包等待传输的类。在最坏的情况下,即使所有类都有队列数据包,类i仍然保证接收到带宽的wi /(Σwj),在这种最坏的情况下,分母的和是所有类的总和。因此,对于传输速率为R的链路,i类总能达到至少R * wi / (Σwh)的吞吐量。我们对WFQ的描述是理想化的,因为我们没有考虑到数据包是离散的,并且一个数据包的传输不会被中断而开始另一个数据包的传输;[Demers 1990]讨论这个分组问题。
4.3 IP (Internet Protocol): IPv4、寻址、IPv6等
到目前为止,我们在第4章中研究了网络层的数据和控制平面的概念,网络层的组成部分,转发和路由的区别,各种网络服务模型的识别,我们对路由器内部的了解通常没有涉及任何特定的计算机网络结构或协议。在这一节中,我们将重点介绍当今互联网和著名的互联网协议(IP)的网络层的关键方面。
目前使用的IP有两个版本。我们将首先研究广泛部署的IP协议版本4,它通常在章节4.3.1中被简单地称为IPv4 [RFC791]。我们将探讨IPv6 [RFC 2460;RFC 4291],在章节4.3.4中被提议取代IPv4。在此期间,我们将主要讨论Internet,解决一个似乎相当枯燥和注重细节的主题,但我们将看到这对理解Internet的网络层如何工作至关重要。掌握IP地址就是掌握因特网网络层本身。
4.3.1 IPv4数据报格式
回想一下,Internet的网络层数据包被称为数据报。我们从IPv4数据报的语法和语义的概述开始我们对IP的研究。您可能认为没有什么比数据包的语法和语义更枯燥的了。然而,数据报在互联网中扮演主要角色——每个网络专业的学生都需要看到它,吸收它,并掌握它。(为了了解协议报头确实很有趣,请查看[Pomeranz 2010])。IPv4数据报格式如图4.17所示。IPv4数据报中的关键字段如下:
- 版本号 这4比特指定数据报的IP协议版本。通过查看版本号,路由器可以决定如何解释IP数据报的其余部分。不同版本的IP使用不同的数据报格式。IPv4的数据报格式如图4.17所示。新版本的IP (IPv6)的数据报格式将在章节4.3.4中讨论。
- 报头长度 因为IPv4数据报可以包含可变数量的选项(包含在IPv4数据报报头中),所以需要这4比特来确定负载(例如,封装在该数据报中的传输层段)在IP数据报中的实际开始位置。大多数IP数据报不包含选项,因此典型的IP数据报有一个20字节的报头。
- 服务类型 IPv4报头中包含服务类型(TOS,type of service)比特,以区分不同类型的IP数据报。例如,区分实时数据报(如IP电话应用程序使用的数据报)和非实时流量(如FTP)可能很有用。要提供的特定服务级别是由网络管理员为该路由器确定和配置的策略问题。我们还在3.7.2节中了解到,两个TOS比特用于显式拥塞通知。
- 数据报长度 这是IP数据报(报头加数据)的总长度,以字节为单位。因为这个字段是16比特长,所以IP数据报的理论最大大小是65,535字节。然而,数据报很少大于1500字节,这允许IP数据报适合最大尺寸的以太网帧的负载字段。
- Identifier, flags, fragmentation offset 这三个字段与所谓的IP分段 (fragmentation)有关,当一个大型IP数据报被分解为几个较小的独立IP数据报,然后单独地转发到目的地,在负载数据(见下文)传递到目标主机的传输层之前重组。有趣的是,新版本的IP——IPv6,不允许分段。这里我们不讨论分段;但读者可以在网上找到这本书早期版本的“退役”材料中的详细讨论。
- Time-to-live time-to-live(TTL)字段确保数据报不会永远在网络中循环(例如,由于一个长期存在的路由循环)。路由器每次处理数据报时,此字段减1。如果TTL字段达到0,路由器必须丢弃该数据报。
- 协议 此字段通常仅在IP数据报到达其最终目的地时使用。该字段的值表示该IP数据报的数据部分应该传递到的特定传输层协议。例如,值6表示将数据部分传递给TCP,值17表示将数据部分传递给UDP。所有可能值的列表请参见[IANA协议号2016]。请注意,IP数据报中的协议号类似于传输层段中的端口号字段。协议号是将网络层和传输层绑定在一起的粘合剂,而端口号则是将传输层和应用层绑定在一起的粘合剂。我们将在第6章中看到,链路层帧还有一个特殊的字段将链路层绑定到网络层。
- 报头校验和 报头校验和帮助路由器检测接收到的IP数据报中的比特错误。报头校验和是通过将报头中每2个字节(16 bit)作为一个数字并将这些数字使用1补和算法相加计算出的。正如在第3.3节中讨论的,这个1补和,即Internet校验和,存储在校验和字段中。路由器为每个接收到的IP数据报计算报头校验和,如果数据报报头中携带的校验和不等于计算出来的校验和,路由器就会检测到错误情况。路由器通常会丢弃检测到错误的数据报。注意,校验和必须在每台路由器上重新计算和存储,因为TTL字段,可能还有选项字段,会变。一个关于计算Internet校验和的快速算法的有趣讨论是[RFC 1071]。在这一点上经常被问到的一个问题是,为什么TCP/IP在传输层和网络层都执行错误检查?这种重复有几个原因。首先,注意只有IP报头在IP层进行校验和,而TCP/UDP校验和是在整个TCP/UDP段上计算的。第二,TCP/ UDP和IP不一定都属于同一个协议栈。TCP,在原则上,可以运行在不同的网络层协议上(例如,ATM) [Black 1995]),IP可以携带不会被传递到TCP/UDP的数据。
- 源和目标IP地址 当源创建数据报时,它将自己的IP地址插入到源IP地址字段中,并将最终目标地址插入到目标IP地址字段中。通常源主机通过DNS查找确定目标地址,如第2章所述。我们将在4.3.2节详细讨论IP地址。
- 选项 选项字段允许扩展IP报头。报头选项很少被使用,因此为了节省开销,决定在每个数据报报头中不包含选项字段中的信息。然而,仅仅是选项的存在就使问题复杂化了,因为数据报头的长度是可变的,不能预先确定数据字段将从哪里开始。此外,由于一些数据报可能需要处理选项,而另一些可能不需要,在路由器上处理IP数据报所需的时间可能会有很大的差异。这些考虑对于高性能路由器和主机的IP处理特别重要。由于这些原因和其他原因,IP选项不包括在IPv6头中,如章节4.3.4所讨论的。
- 数据(负载) 最后,我们来看最后一个也是最重要的字段——数据报存在的理由!在大多数情况下,IP数据报的数据字段包含要交付到目的地的传输层段(TCP或UDP)。但是,数据字段可以携带其他类型的数据,例如ICMP消息(在第5.6节中讨论)。
注意,一个IP数据报共有20个字节的报头(假设没有选项)。如果数据报携带一个TCP段,那么每个数据报连同应用层消息共携带40字节的报头(20字节的IP报头加上20字节的TCP报头)。
4.3.2 IPv4寻址
现在我们将注意力转向IPv4寻址。虽然您可能认为寻址必须是一个简单的主题,但希望在本节结束时,您将确信Internet寻址不仅是一个有趣、微妙的主题,而且是一个对Internet至关重要的主题。在[Stewart 1999]的第一章中可以找到一个很好的IPv4寻址方法。
然而,在讨论IP地址之前,我们需要简单介绍一下主机和路由器是如何连接到Internet上的。一个主机通常只有一个到网络的链路;当主机中的IP想要发送一个数据报时,它通过这个链路来完成。主机和物理链路之间的边界称为 接口 。现在考虑一个路由器及其接口。因为路由器的工作是接收一个链路上的数据报,然后在其他链路上转发这个数据报,所以路由器必须要连接两个或更多的链路。路由器和它的任何一条链路之间的边界也称为接口。因此,路由器有多个接口,每个接口对应它的每条链路。因为每台主机和路由器都能够发送和接收IP数据报,IP要求每台主机和路由器接口都有自己的IP地址。因此,从技术上讲,IP地址与接口相关联,而不是与包含该接口的主机或路由器相关联。
每个IP地址是32位长(相当于4个字节),因此总共有232个(或大约40亿个)可能的IP地址。这些地址通常用所谓的点分十进制记数法(dotted-decimal notation)来写,地址的每个字节都以十进制形式来写,并且用句号(点)与地址中的其他字节分开。例如,考虑IP地址193.32.216.9。193与地址的前8位的十进制数相等;32与地址的第二个8位的十进制数相等,以此类推。因此,地址193.32.216.9在二进制记数法中是: 11000001 00100000 11011000 00001001
在全局Internet中,每台主机和路由器上的每个接口都必须有一个全局唯一的IP地址(NAT的接口除外,如章节4.3.3所述)。然而,这些地址不能随意选择。一个接口的IP地址的一部分将由它所连接的子网决定。
图4.18提供了一个IP地址和接口的示例。在图中,一个路由器(有三个接口)用来连接七台主机。仔细查看分配给主机和路由器接口的IP地址,因为有几件事需要注意。图4.18左上角的三个主机,以及它们所连接的路由器接口,都有一个形式为223.1.1.xxx的IP地址。也就是说,它们的IP地址左边24位都是相同的。这四个接口可通过一个 不含路由器 的网络相互连接。这个网络可以通过以太网局域网互联。在这种情况下,各个接口将由一个以太网交换机互联(如第六章中我们会讨论),或者通过无线接入点互联(如在第7章中我们会讨论)。我们现在将这些连接主机的无路由器网络表示为云,并在第6章和第7章深入了解这种网络的内部结构。
在IP术语中,这个网络连接三个主机接口和一个路由器接口组成了一个 子网 [RFC 950]。(子网在互联网文献中也被称为IP网络或简称网络,network)。IP地址分配一个地址给这个子网:223.1.1.0/24,其中”/24“表示法,有时称为 子网掩码 ,表示32位数中最左边的24位定义子网地址。因此,223.1.1.0/24子网由三个主机接口(223.1.1.1、223.1.1.2和223.1.1.3)和一个路由器接口(223.1.1.4)组成。任何附加到223.1.1.0/24子网的附加主机都需要具有223.1.1.xxx形式的地址。如图4.18所示,还有两个额外的子网:223.1.2.0/24网络和223.1.3.0/24子网。图4.19展示了图4.18中出现的三个IP子网。
子网的IP定义并不局限于连接多个主机到路由器接口的以太网段。为了更好地理解这里的内容,请参考图4.20,其中显示了通过点对点链路相互连接的三个路由器。每个路由器有三个接口,一个用于点对点链路,另一个用于直接将路由器连接到一对主机的广播链路。这里有哪些子网?223.1.1.0/24、223.1.2.0/24和223.1.3.0/24三个子网与图4.18中遇到的子网类似。但是请注意,在这个例子中还有三个额外的子网:一个子网,223.1.9.0/24,用于连接路由器R1和R2的接口;另一个子网为223.1.8.0/24,用于连接路由器R2和R3的接口;第三个子网为223.1.7.0/24,用于连接路由器R3和R1的接口。对于由路由器和主机组成的通用互联系统,我们可以使用下面的方法来定义系统中的子网:
要确定子网,可以将每个接口从它的主机或路由器中分离出来,创建隔离网络的孤岛,用接口结束隔离网络的终点(end point)。这些隔离的网络被称为子网。
从上面的讨论可以清楚地看出,具有多个以太网段和点对点链路的组织(如公司或学术机构)将具有多个子网,给定子网上的所有设备具有相同的子网地址。原则上,不同的子网可能有完全不同的子网地址。然而,事实上它们的子网地址往往有很多共同之处。为了理解其中的原因,让我们接下来关注全球互联网中如何处理寻址。
互联网的地址分配策略被称为 Classless Interdomain Routing (CIDR,发音为cider) [RFC 4632]。CIDR概括了子网寻址的概念。与子网寻址一样,32位的IP地址被分成两部分,同样采用十进制点分形式a.b.c.d/x,其中x表示地址第一部分的位数。
a.b.c.d/x形式的地址的x个最高有效位构成了IP地址的网络部分,通常被称为地址的 前缀 (或网络前缀)。一个组织通常被分配一个连续的地址块,即一个带有公共前缀的地址范围。在这种情况下,组织内各设备的IP地址将使用同一个前缀。当我们在5.4节中讨论Internet的BGP路由协议时,我们将看到只有前x位被组织网络外的路由器考虑。也就是说,当组织外部的路由器转发数据报的目标地址在组织内部时,只需要考虑地址的前x位。这大大减少了这些路由器中的转发表的大小,因为一个a.b.c.d/x形式的单表项就足以将数据包转发到组织中的任何目的地。
地址的其余32-x位可以被认为是组织内设备之间的区别,所有这些设备都有相同的网络前缀。这些位在组织内部的路由器上转发数据包时将被考虑。这些低阶位可能(也可能不)有一个额外的子网结构,就像上面讨论的那样。例如,假设CIDRized地址a.b.c.d/21的前21位指定了该组织的网络前缀,并且与该组织中所有设备的IP地址共用。剩下的11位标识组织中的特定主机。组织的内部结构可能是这样的:这11个最右边的位用于组织内部的子网,如上所述。例如,a.b.c.d/24可能指的是组织中的一个特定子网。
在采用CIDR之前,IP地址的网络部分被限制为8位、16位或24位,这种寻址方案被称为 有类寻址 (classful addressing),因为8位、16位和24位子网地址分别被称为A类、B类和C类网络。要求IP地址的子网部分恰好为1、2或3字节长,这对于支持快速增长的中小型子网组织来说是有问题的。一个C类(/24)子网最多只能容纳28 - 2 = 254个主机(256个地址中有两个预留给特殊用途),对于许多组织来说太小了。然而,一个B类(/16)子网太大,最大支持65634台主机。在有类寻址下,一个拥有2000台主机的组织通常被分配一个B类(/16)子网地址。这导致了B类地址空间的快速耗尽和分配的地址空间的不良利用。例如,使用B类地址的组织为它的2000个主机分配了足够的地址空间,可以容纳多达65,534个接口,留下超过63,000个不能被其他组织使用的地址。
如果我们没有提到另一种类型的IP地址,IP广播地址255.255.255.255,那就太不负责任了。当主机发送目标地址为255.255.255.255的数据报时,该消息将被发送到同一子网内的所有主机。路由器也可以选择将消息转发到邻近的子网(尽管它们通常不会)。
现在详细研究了IP地址,我们首先需要知道主机和子网是如何获得它们的地址的。让我们先看看一个组织如何获取其设备的地址块,然后看看一个设备(如主机)如何从该组织的地址块中分配一个地址。
实践
这个连接8个组织到Internet的ISP的例子很好地说明了如何小心地分配CIDRized地址来使路由更容易。假设,如图4.21所示,ISP(我们称之为Fly-By-Night-ISP)向外界宣布,它应该发送前20个地址位匹配200.23.16.0/20的任何数据报。其他人不需要知道,在地址块200.23.16.0/20中实际上还有8个其他组织,每个组织都有自己的子网。这种使用单个前缀发布多个网络的能力通常被称为 地址聚合 (address aggregation,也称route aggregation 或 route summarization)。
当地址以块的形式分配给ISP,然后从ISP分配给客户端组织时,地址聚合工作得非常好。但是,如果地址不是以这种分层的方式分配的,会发生什么情况呢?例如,如果Fly-By-Night-ISP收购了ISPs-R-Us,然后让组织1通过其子公司ISPs-R-Us连接到互联网,会发生什么?如图4.21所示,子公司ISPs-R-Us拥有地址段199.31.0.0/16,但不幸的是,组织1的IP地址不在这个地址块之内。这里应该做什么?当然,组织1可以重新编号它所有的路由器和主机,使其在ISPs-R-Us地址块内拥有地址。但这是一个代价高昂的解决方案,而且组织1很可能在未来被重新分配到另一个子公司。通常采用的解决方案是组织1将其IP地址保持在200.23.18.0/23。在这种情况下,如图4.22所示,Fly-By-Night-ISP继续发布地址块200.23.16.0/20,而ISPs-R-Us继续发布地址块199.31.0.0/16。然而,ISPs-R-Us现在也为组织1,200.23.18.0 /23发布地址块。当其他路由器在更大的互联网看到的地址块200.23.16.0/20 (Fly-By-Night-ISP)和200.23.18.0/23(从ISPs-R-Us)和200.23.18.0/23且想要路由到块200.23.18.0/23中的一个地址时,他们将使用最长前缀匹配(见部分4.2.1),路由到ISPs-R-Us,因为它发布与目标地址匹配的最长地址前缀。
获取地址块
为了获得一个组织子网内使用的IP地址块,网络管理员可以首先联系它的ISP,后者将提供已经分配给该ISP的更大的IP地址块中的地址。例如,ISP本身可能已经被分配了地址块200.23.16.0/20。ISP,反过来,可以把它的地址块分成8个大小相等的连续地址块,并把这些地址块分给8个组织,如下所示。
ISP’s block: 200.23.16.0/20 11001000 00010111 00010000 00000000
Organization 0 200.23.16.0/23 11001000 00010111 00010000 00000000
Organization 1 200.23.18.0/23 11001000 00010111 00010010 00000000
Organization 2 200.23.20.0/23 11001000 00010111 00010100 00000000
…
Organization 7 200.23.30.0/23 11001000 00010111 00011110 00000000
虽然从ISP获得一组地址是获得一组地址的一种方法,但它不是唯一的方法。显然,ISP本身也必须有一种方法来获取地址块。是否有一个全球权威机构对管理IP地址空间和分配地址块给ISP和其他组织负有最终责任?确实有!IP地址由ICANN[ICANN 2020,Internet Corporation for Assigned Names and Numbers]根据[RFC 7020]规定的指导方针管理。非营利的ICANN组织的角色不仅是分配IP地址,而且还管理DNS根服务器。它也有非常有争议的工作,分配域名和解决域名争端。ICANN为区域性的Internet注册机构(如ARIN、RIPE、APNIC、LACNIC)分配地址,并负责区域内地址的分配和管理。这些机构共同组成ICANN的地址支持组织(Address support Organization of ICANN [ASO-ICANN 2020])。
获取主机地址:动态主机配置协议
一旦一个组织获得了一个地址块,它就可以为其组织中的主机和路由器接口分配单独的IP地址。系统管理员通常会手动将IP地址配置到路由器中(通常是远程的,使用网络管理工具)。主机地址也可以手动配置,但通常使用动态主机配置协议(DHCP,Dynamic Host Configuration Protocol) [RFC 2131]来完成。DHCP是主机自动获取(分配)IP地址的方式。网络管理员可以配置DHCP,使给定的主机在每次连接到网络时接收到相同的IP地址,或者给主机分配一个临时的IP地址,该IP地址在每次主机连接到网络时将不同。除了主机IP地址分配外,DHCP还允许主机了解其他信息,如子网掩码、第一跳路由器的地址(通常称为默认网关)和本地DNS服务器的地址。
由于DHCP具有将主机连接到网络的网络相关方面自动化的能力,因此它通常被称为 即插即用 (plug-and-play)协议或 零配置 (zeroconf)协议。这个功能对网络管理员非常有吸引力,否则他们将不得不手动执行这些任务!DHCP在住宅Internet接入网、企业网和无线局域网中也得到了广泛的应用,在无线局域网中,主机频繁地加入和离开网络。例如,考虑一个学生,他带着笔记本电脑从宿舍到图书馆再到教室。很可能在每个位置,学生将连接到一个新的子网,因此在每个位置将需要一个新的IP地址。DHCP非常适合这种情况,因为有很多用户来来去去,只需要地址有限的时间。DHCP的即插即用功能的价值是显而易见的,因为很难想象系统管理员能够在每个位置重新配置笔记本电脑,而且很少有学生(除了参加计算机网络课程的学生!)有手动配置笔记本电脑的专业知识。
DHCP是一种客户端-服务器协议。客户端通常是一个新到达的主机,它希望获得网络配置信息,包括它自己的IP地址。在最简单的情况下,每个子网(图4.20)将有一个DHCP服务器。如果子网中没有服务器,则需要一个DHCP中继代理(通常是路由器),它知道该网络中的DHCP服务器的地址。图4.23所示为223.1.2/24子网下的DHCP服务器,路由器作为新到达客户端的中继代理,连接到子网223.1.1/24和223.1.3/24。在下面的讨论中,我们假设子网上有一个DHCP服务器。
对于新到达的主机,DHCP协议的配置过程分为四个步骤,如图4.24所示。在这个图中,yiaddr(your Internet address)表示分配给新到达的客户端的地址。这四个步骤是:
DHCP server discovery 新到达的主机的第一个任务是找到一个DHCP服务器,并与之交互。这是通过DHCP discover消息完成的,客户端发送一个UDP数据包到端口67。UDP数据包封装在一个IP数据报中。但是这个数据报应该发送给谁呢?主机甚至不知道它所连接的网络的IP地址,更不用说这个网络的DHCP服务器的地址。因此,DHCP客户端创建一个IP数据报,其中包含其DHCP discover数据包,广播目标IP地址为255.255.255.255,此主机源IP地址为0.0.0.0。DHCP客户端将IP数据报传递给链路层,链路层然后将此帧广播给附加到子网的所有节点(我们将在第6.4节讨论链路层广播的细节)。
DHCP server offer(s) DHCP server收到DHCP discover数据包后,会向client发送DHCP offer数据包,并广播给子网内的所有节点,同样使用IP广播地址255.255.255.255。(您可能想知道为什么这个服务器应答也必须被广播)。由于子网中可能存在多个DHCP服务器,客户端可能会发现自己处于一个令人羡慕的位置,能够从多个offer中进行选择。每个服务器提供的消息包含收到的discover消息的交易ID,客户端提议的IP地址,网络掩码,和IP地址租用时间(IP address lease time)——IP地址的有效时间。服务器通常将租用时间设置为几个小时或几天[Droms 2002]。
DHCP的请求 新到达的客户端将从一个或多个服务器的offer中做出选择,并以一个DHCP请求消息回应它所选择的offer,并返回配置参数。
DHCP ACK 服务器发送DHCP ACK消息响应DHCP请求消息,确认DHCP请求的参数。
客户端收到DHCP ACK后,即完成交互,在租期内可以使用DHCP分配的IP地址。由于客户端可能希望在租期届满后使用其地址,DHCP还提供了一种机制,允许客户端更新其IP地址的租期。
从移动性的角度来看,DHCP确实有一个非常明显的缺点。由于每次节点连接到新的子网时,都会从DHCP获得一个新的IP地址,因此当移动节点在子网之间移动时,无法维护到远程应用程序的TCP连接。在第七章中,我们将学习移动蜂窝网络如何允许主机保留其IP地址和TCP连接,因为它在供应商的蜂窝网络的基站之间移动。有关DHCP的其他详细信息可以在[Droms 2002]和[dhc 2020]中找到。DHCP的开源参考实现可从Internet系统联盟[ISC 2020]获得。
4.3.3网络地址转换(NAT)
考虑到我们对Internet地址和IPv4数据报格式的讨论,我们现在很清楚地认识到,每个支持IP的设备都需要一个IP地址。随着小办公室,家庭办公室(SOHO)子网,这似乎意味着每当SOHO想安装一个局域网连接多台机器,需要通过ISP分配一系列的地址来涵盖所有SOHO的IP设备(包括手机、平板电脑、游戏设备、IP电视、打印机等)。如果子网变大,就必须分配更大的地址块。但是,如果ISP已经分配了SOHO网络当前地址范围的连续部分呢?房主如何管理IP地址?幸运的是,有一种更简单的方法来分配地址,并且在这些场景中得到了越来越广泛的应用: 网络地址转换(NAT,network address translation) [RFC 2663; RFC 3022;Huston 2004, Zhang 2007; Huston 2017]。
启用NAT功能的路由器的操作如图4.25所示。启用NAT的路由器位于家中,在图4.25右侧有一个属于家庭网络的接口。家庭网络中的寻址就像我们上面看到的——家庭网络中的所有四个接口都有相同的子网地址10.0.0.0/24。地址空间10.0.0.0/8是IP地址空间的三个部分之一,在[RFC 1918]中为私有网络或具有私有地址领域(realm with private addresses)保留,如图4.25中的家庭网络。具有私有地址领域指的是一个网络,其地址仅对该网络中的设备有意义。要了解为什么这很重要,请考虑这样一个事实:有数十万个家庭网络,其中许多使用相同的地址空间10.0.0.0/24。给定家庭网络内的设备可以使用10.0.0.0/24地址互相发送数据包。然而,从家庭网络转发到更大的全球互联网的数据包显然不能使用这些地址(作为源地址或目标地址),因为有成千上万的网络使用这个地址块。也就是说,10.0.0.0/24地址只能在给定的家庭网络中有意义。但是,如果私有地址只在给定的网络中有意义,那么当数据包发送到或从全球Internet接收时,地址必须是唯一的,该如何处理寻址呢?答案在于理解NAT。
在外界看来,启用NAT的路由器并不像路由器。相反,NAT路由器对外界的行为就像一台拥有单一IP地址的设备。在图4.25中,所有离开主路由器前往更大的Internet的流量的源IP地址都是138.76.29.7,所有进入主路由器的流量的目标地址都必须是138.76.29.7。本质上,启用NAT的路由器对外界隐藏了家庭网络的细节。(顺便说一句,你可能想知道家庭网络计算机从哪里得到它们的地址,路由器从哪里得到它的单一IP地址。通常,答案是同一个——DHCP!路由器从ISP的DHCP服务器获取地址,并运行DHCP服务器向NAT-DHCP-router-controlled的家庭网络地址空间内的计算机提供地址。)
如果所有从WAN(Wide Area Network)到达NAT路由器的数据报都有相同的目标IP地址(具体地说,NAT路由器的WAN端接口的目标IP地址),那么路由器如何知道它应该将给定的数据报转发给哪个内部主机?诀窍是在NAT路由器上使用NAT转换表,并在表项中包含端口号和IP地址。
考虑图4.25中的例子。假设一个用户在10.0.0.1主机后面的家庭网络中请求一个IP地址为128.119.40.186的Web服务器(端口80)上的Web页面。主机10.0.0.1分配(任意)源端口号3345,并将数据报发送到局域网。NAT路由器接收到该数据报后,为该数据报生成新的源端口号5001,并将源IP地址替换为其WAN端IP地址138.76.29.7,将原源端口号3345替换为新的源端口号5001。在生成新的源端口号时,NAT路由器可以选择当前NAT转换表中没有的任何源端口号。(请注意,因为端口号字段是16位长,NAT协议可以支持超过60000个与路由器的一个WAN端IP地址的同时连接!)路由器中的NAT也会在它的NAT转换表中增加一个表项。Web服务器很幸运,不知道包含HTTP请求的到达数据报已经被NAT路由器操作过,因此用一个数据报进行响应,该数据报的目标地址是NAT路由器的IP地址,目标端口号是5001。当这个数据报到达NAT路由器时,路由器使用目标IP地址和目标端口号索引NAT转换表,以获得家庭网络中浏览器的适当的IP地址(10.0.0.1)和目标端口号(3345)。然后路由器重写数据报的目标地址和目目标端口号,并将数据报转发到家庭网络。
NAT近年来得到了广泛的应用。但是NAT也不是没有批评者。首先,有人可能会说,端口号是用来寻址进程的,而不是用来寻址主机的。这种冲突确实会给家庭网络上运行的服务器带来问题,因为,正如我们在第二章中看到的,服务器进程在已知的端口号上等待传入的请求,而P2P协议中的对等体在充当服务器时需要接受传入的连接。一个对等体如何连接到另一个NAT server后面的对等体,并且有DHCP提供的NAT地址?这些问题的技术解决方案包括 NAT穿越 工具[RFC 5389] [RFC 5389, RFC 5128, Ford 2005]。
建筑纯粹主义者也对NAT提出了更多的哲学观点。在这里,需要考虑的是路由器应该是第三层(即网络层)设备,应该只处理到网络层的数据包。NAT违背了主机之间应该直接通信的原则,不干涉节点修改IP地址,更不用说端口了。我们将在第4.5节稍后讨论中间件(middleboxes)时回到这个争论。
聚焦安全之数据报检视:防火墙和入侵检测系统
假设您被分配管理家庭、部门、大学或公司网络的任务。攻击者知道您的网络的IP地址范围,可以很容易地将IP数据报发送到您的范围内的地址。这些数据报可以做各种各样的不正当的事情,包括用ping扫描和端口扫描映射您的网络,用畸形的数据包破坏脆弱的主机,在您的网络服务器上扫描开放的TCP/UDP端口,并通过在数据包中包含恶意软件感染主机。作为网络管理员,您将如何处理那些可能向您的网络发送恶意数据包的坏人呢?防火墙和入侵检测系统(IDS)是两种常用的恶意数据包攻击防御机制。
作为一名网络管理员,您可以首先尝试在您的网络和Internet之间安装防火墙。(现在大多数接入路由器都有防火墙功能。)防火墙检查数据报和段头字段,拒绝可疑的数据报进入内部网络。例如,可以将防火墙配置为阻止所有ICMP echo request数据包(参见5.6节),从而防止攻击者在您的IP地址范围内进行传统的端口扫描。防火墙也可以根据源、目标IP地址和端口号屏蔽数据包。此外,可以将防火墙配置为跟踪TCP连接,只将入口授予属于已批准连接的数据报。
IDS可以提供额外的保护。IDS通常位于网络边界,执行深度数据包检查,不仅检查头字段,还检查数据报中的有效负载(包括应用层数据)。IDS拥有一个数据包签名数据库,这些数据包签名已知是攻击的一部分。当发现新的攻击时,该数据库会自动更新。当数据包经过IDS时,IDS会尝试将头字段和负载与特征库中的特征进行匹配。如果找到这样的匹配,则创建警报。入侵防御系统(IPS,intrusion prevention system)与IDS类似,不同的是,它除了创建警报之外,实际上还阻断了数据包。我们将在第4.5节和第8章中更详细地探讨防火墙和IDS。
防火墙和IDS能完全保护您的网络免受所有攻击吗?答案显然是否定的,因为攻击者不断地发现新的攻击,而这些攻击的签名还不可用。但是防火墙和传统的基于签名的IDS在保护您的网络免受已知攻击方面很有用。
4.3.4 IPv6
在20世纪90年代早期,IETF(Internet Engineering Task Force)开始努力开发IPv4协议的继承者。这一努力的主要动机是意识到32位IPv4地址空间终将被用完,新的子网和IP节点正以惊人的速度连接到Internet(并被分配唯一的IP地址)。为了响应这种对大IP地址空间的需求,开发了一种新的IP协议,IPv6。IPv6的设计者也利用这个机会,基于IPv4积累的运营经验,对IPv4的其他方面进行了调整和增强。
在什么时候IPv4地址将被完全分配(因此没有新的网络可以连接到互联网上),这是一个相当有争议的话题。IETF的地址寿命预期工作组的两位领导人估计地址将分别在2008年和2018年耗尽[Solensky 1996]。2011年2月,IANA将最后一个未分配的IPv4地址池分配给了一个区域注册商。虽然这些注册商的地址池中仍然有可用的IPv4地址,但一旦这些地址耗尽,就没有更多的地址块可以从中心地址池中分配[houston 2011a]。最近一项关于IPv4地址空间耗尽的调查,以及采取的延长地址空间寿命的措施是[Richter 2015];最近的IPv4地址使用分析是[Huston 2019]。
尽管20世纪90年代中期对IPv4地址耗尽的估计表明,在IPv4地址空间耗尽之前可能还有相当长的一段时间,但人们意识到,在如此广泛的规模上部署一项新技术将需要相当长的时间,因此,开发IPv6[RFC 2460]的过程开始了[RFC 1752]。(一个经常被问到的问题是IPv5发生了什么?最初的设想是ST-2协议将成为IPv5,但ST-2协议后来被放弃。)关于IPv6的一个很好的信息来源是[Huitema 1998]。
IPv6数据报格式
IPv6数据报的格式如图4.26所示。IPv6中引入的最重要的变化明显地体现在数据报格式上:
- 扩大了寻址能力 IPv6将IP地址的长度从32位增加到128位。这确保了世界不会耗尽IP地址。现在,地球上的每一粒沙子都可以被IP地址覆盖。除了单播(unicast)和组播(multicast)地址,IPv6还引入了一种新的地址类型,称为 任播地址 (anycast address),允许数据报被发送到一组主机中的任何一个。(例如,可以使用该特性向包含给定文档的镜像站点中最近的站点发送HTTP GET。)
- 改进的40字节报头 正如下面所讨论的,许多IPv4字段已经被删除或变成可选的。由此产生的40字节固定长度报头允许路由器更快地处理IP数据报。一种新的选项编码允许更灵活的选项处理。
- 流标(Flow labeling) IPv6对流有一个难以捉摸的定义。RFC 2460规定允许“标记属于发送方请求特殊处理的特定流的数据包,例如非默认服务质量或实时服务。”例如,音频和视频传输可能被视为一个流。另一方面,更传统的应用程序,如文件传输和电子邮件,可能不会被视为流。高优先级用户(例如,有人为他们的流量支付了更好的服务)携带的流量也可能被视为流。然而,明确的是,IPv6的设计者预见到最终需要能够区分流,即使流的确切含义尚未确定。
如上所述,图4.26和图4.17的比较揭示了更简单、更精简的IPv6数据报结构。以下字段在IPv6中定义:
- Version 这个4位字段标识IP版本号。不足为奇的是,IPv6的这个字段值为6。注意,在这个字段中输入4并不能创建有效的IPv4数据报。(如果是这样,生活就会简单得多——参见下面关于从IPv4过渡到IPv6的讨论。)
- Traffic class 8位的流量类型字段,如IPv4中的TOS字段,可以用来给流中的某些数据报优先级,也可以用来给来自某些应用程序(例如,IP语音)的数据报优先于来自其他应用程序(例如,SMTP电子邮件)的数据报优先级。
- Flow label 如上所述,这个20位字段用于标识数据报的流。
- Payload length 这个16位的值被视为一个无符号整数,给出IPv6数据报中固定长度的40字节数据报报头后面的字节数。
- Next header 这个字段标识这个数据报的内容(数据字段)将被交付到的协议(例如,TCP或UDP)。该字段与IPv4报头中的协议字段使用相同的值。
- Hop limit 每个转发该数据报的路由器将该字段的内容减1。如果跳数限制达到零,路由器必须丢弃该数据报。
- Source and destination addresses :IPv6 128位地址的各种格式在RFC 4291中有描述。
- Data 这是IPv6数据报的负载部分。当数据报到达目的地时,有效负载将从IP数据报中删除,并传递到next header字段中指定的协议。
上面的讨论确定了包含在IPv6数据报中的字段的用途。比较图4.26中的IPv6数据报格式和我们在图4.17中看到的IPv4数据报格式,我们注意到IPv4数据报中出现的几个字段不再出现在IPv6数据报中:
- Fragmentation/reassembly IPv6不允许中间路由器分段和重组;这些操作只能由源端和目标端执行。如果路由器接收到的IPv6数据报太大而不能通过发送链路转发,路由器就会丢弃该数据报,并向发送方发送一个“数据包太大”ICMP错误消息(见章节5.6)。然后,发送方可以使用较小的IP数据报大小重新发送数据。分段和重组是一项耗时的工作;将这种功能从路由器中移除,直接放到终端系统中,可以大大加快网络中的IP转发速度。
- Header checksum 由于Internet层中的传输层(例如TCP和UDP)和链路层(例如以太网)协议执行校验和,IP的设计者可能认为这种功能在网络层中是多余的,可以删除。再一次,快速处理IP数据包是一个核心问题。回想一下我们在第4.3.1节中对IPv4的讨论,因为IPv4报头包含一个TTL字段(类似于IPv6中的跳数限制字段),所以IPv4报头的校验和需要在每台路由器上重新计算。与分段和重组一样,这在IPv4中也是一项代价高昂的操作。
- Options 选项字段不再是标准IP报头的一部分。然而,它并没有消失。相反,options字段可能是指向IPv6 header中的next header之一。也就是说,就像TCP或UDP协议头可以是IP数据包中的next header一样,选项字段也可以。删除options字段会产生一个固定长度、40字节的IP报头。
IPv4向IPv6过渡
现在我们已经看到了IPv6的技术细节,让我们考虑一个非常实际的问题:基于IPv4的公共互联网将如何过渡到IPv6?问题是,虽然新的支持IPv6的系统可以向后兼容,也就是说,可以发送、路由和接收IPv4数据报,但已经部署的支持IPv4的系统无法处理IPv6数据报。有几种可能的选择[Huston 2011b, RFC 4213]。
一种选择是宣布flag日,在给定的时间和日期,所有互联网机器将被关闭并从IPv4升级到IPv6。上一次重大的技术转变(从使用NCP到使用TCP提供可靠的传输服务)发生在近40年前。甚至在那时[RFC 801],当互联网很小,仍然由少数向导管理时,人们意识到这样的flag日是不可能的。在今天,一个涉及数十亿个设备的flag日更是难以想象。
IPv4到IPv6过渡的方法已经在实践中被广泛采用,其中包括 隧道 (tunneling)[RFC 4213]。隧道背后的基本思想——这是一个关键的概念,除了IPv4到IPv6的过渡之外,还有许多其他场景的应用,包括all-IP蜂窝网络的广泛应用,我们将在第7章中介绍。假设两个IPv6节点(在本例中,图4.27中的B和E)希望使用IPv6数据报进行互操作,但通过中间的IPv4路由器连接。我们将两个IPv6路由器之间的一组IPv4路由器称为隧道,如图4.27所示。使用隧道,隧道发送端的IPv6节点(在本例中为B)获取整个IPv6数据报,并将其放入IPv4数据报的数据(负载)字段中。然后,这个IPv4数据报随后交给隧道接收端的IPv6节点(在这个例子中,E)。其间的IPv4路由器在隧道中路由这些IPv4数据报,就像路由任何其他的数据报一样,根本意识不到IPv4数据报本身包含一个完整的IPv6数据报。IPv6节点的接收端隧道最终接收IPv4数据报(IPv4数据报的目的地!),确定IPv4数据报包含一个IPv6数据报(通过观察IPv4数据报协议号字段是41 (RFC 4213),表明IPv4负载是IPv6数据报),提取IPv6数据报,然后路由IPv6数据报,就像它从直接连接的IPv6邻居接收IPv6数据报一样。
在结束本节时,我们注意到,虽然IPv6的采用最初起步缓慢[Lawton 2001; Huston 2008b],势头已经形成。NIST [NIST IPv6 2020]报告称,超过三分之一的美国政府二级域名已启用IPv6。在客户端,谷歌报告约25%的客户端通过IPv6访问谷歌服务[谷歌IPv6 2020]。其他最近的测量[Czyz 2014]表明IPv6的采用正在加速。设备的激增,如支持IP的电话和其他便携式设备提供了一个额外的推动更广泛的IPv6部署。欧洲第三代合作伙伴计划[3GPP 2020]已经指定IPv6作为移动多媒体的标准寻址方案。
我们可以从IPv6的经验中学到的一个重要教训是,改变网络层协议是非常困难的。自20世纪90年代初以来,许多新的网络层协议被鼓吹为互联网的下一个重大革命,但迄今为止,这些协议的渗透程度有限。这些协议包括IPv6、组播协议和资源预留协议(resource reservation protocols);关于后两类协议的讨论可以在本文的在线补冲中找到。实际上,在网络层引入新的协议,就像更换房屋的地基一样,如果不拆除整个房屋,或至少暂时搬迁住户,很难做到这一点。另一方面,互联网的应用层新协议迅速部署。当然,经典的例子是Web、即时消息、流媒体、分布式游戏和各种形式的社交媒体。引入新的应用层协议就像给房子上一层新漆,这是相对容易做到的,如果你选择了一个吸引人的颜色,邻居们会模仿你。
总之,在未来,我们肯定会看到Internet的网络层发生变化,但这些变化发生的时间尺度很可能比应用层发生的变化慢得多。
4.4 广义转发和SDN
回想一下章节4.2.1将基于目的地的转发描述为两个步骤:查找目标IP地址(match),然后将数据包发送到交换结构中指定的输出端口(action)。现在让我们考虑一个更通用的match-plus-action范例,在这个范例中,匹配可以在协议栈的不同层中与不同协议相关联的多个头字段上进行。操作可以包括将数据包转发给一个或多个输出端口(如基于目的地的转发),负载均衡数据包到多个传出接口,导致服务(如负载均衡),重写头值(如NAT),故意屏蔽/丢弃一个数据包(如防火墙),发送一个数据包到一个特殊的服务器进行进一步的处理和操作(如DPI,Deep Packet Inspection),等等。
在广义转发中,match-plus-action表概括了我们在章节4.2.1中遇到的基于目标的转发表的概念。由于转发决策可能使用网络层和/或链路层的源地址和目标地址,因此图4.28所示的转发设备更准确地描述为数据包交换机,而不是三层路由器或二层交换机。因此,在本节的其余部分和5.5节中,我们将这些设备称为数据包交换机,采用了SDN文献中广泛采用的术语。
图4.28显示了每个数据包交换机中的match-plus-action表,该表由远程控制器计算、安装和更新。我们注意到,虽然各个数据包交换机上的控制组件可以相互交互(例如,在某种程度上类似于图4.2),在实践中,广义的match-plus-action功能是通过一个远程控制器计算,安装和更新这些表实现的。您可能需要花一些时间来比较图4.2、4.3和4.28——你注意到图4.2和4.3中所示的基于目的地的转发和图4.28中所示的广义转发之间有什么异同吗?
我们接下来对广义转发的讨论将基于Open-Flow[McKeown 2008, ONF 2020, Casado 2014, Tourrilhes 2014]——一个高度可见的标准,开创了匹配加操作转发抽象和控制器的概念,以及更普遍的SDN革命[Feamster 2013]。我们将主要考虑OpenFlow 1.0,它以一种特别清晰和简洁的方式引入了关键的SDN抽象和功能。OpenFlow的后续版本引入了额外的功能,这是通过实现和使用获得的经验的结果;OpenFlow标准的当前和早期版本可以在[ONF 2020]中找到。
匹配加操作转发表(OpenFlow中称为流表,flow table)中的每个表项包括:
- 一组头字段值 ,传入的数据包将与之匹配。与基于目的地的转发一样,基于硬件的匹配在TCAM内存中执行得最快,可能有超过100万个目标地址项[Bosshart 2013]。没有匹配流表表项的数据包可以被删除或发送到远程控制器以进行更多的处理。在实践中,由于性能或成本的原因,一个流表可能由多个流表实现[Bosshart 2013],但我们将在这里关注单个流表的抽象。
- 一组计数器 ,当数据包与流表项匹配时更新。这些计数器可能包括与该表项匹配的数据包的数量,以及该表项上次更新以来的时间。
- 当数据包与流表项匹配时 要采取的一组操作 。这些操作可能是将数据包转发到给定的输出端口,丢弃数据包,复制数据包并将其发送到多个输出端口,和/或重写选定的头字段。
我们将分别在4.4.1节和4.4.2节更详细地探讨匹配和操作。然后,我们将在章节4.4.3中研究如何使用逐-数据包交换机匹配规则的全网络集合来实现广泛的功能,包括路由、二层交换、防火墙、负载均衡、虚拟网络等。在结束的时候,我们注意到流表本质上是一个API,通过这个抽象,一个单独的数据包交换的行为可以被编程;我们将在章节4.4.3中看到,通过在网络数据包交换机集合中适当地编程/配置这些表,可以类似地编程网络范围(network-wide)的行为[Casado 2014]。
4.1.1 匹配
图4.29显示了在OpenFlow 1.0 match-plus-action规则中可以匹配的11个头字段和传入端口ID。回想一下第1.5.2节,到达数据包交换机的链路层(第2层)帧将包含一个网络层(第3层)数据报作为其有效载荷,而这个数据报通常又包含一个传输层(第4层)段。我们观察到的第一个现象是OpenFlow的匹配抽象允许从三层协议头中选择字段进行匹配(因此公然违背了我们在第1.5节中研究的分层原则)。因为我们还没有讨论链路层,一言以蔽之,图4.29中所示的源MAC地址和目标MAC地址是与帧的发送和接收接口相关的链路层地址;通过基于以太网地址而不是IP地址转发,我们可以看到,启用openflow的设备可以像路由器(第三层设备)一样转发数据报,也可以像交换机(第二层设备)一样转发帧。以太网类型字段对应于上层协议(例如,IP),帧的负载将被解复用,VLAN字段与所谓的虚拟局域网有关,我们将在第6章中学习。在OpenFlow 1.0规范中可以匹配的12个值集合在最近的OpenFlow规范中已经增长到41个[Bosshart 2014]。
入口(ingress)端口是指接收数据包的数据包交换机上的输入端口。数据包的IP源地址、IP目标地址、IP协议字段和IP TOS字段在前面的章节4.3.1中已经讨论过。传输层源端口号和目标端口号字段也可以匹配。
流表表项也可以使用通配符。例如,在一个流表中的IP地址128.119.*.*将匹配以128.119作为其地址的前16位的任何数据报的对应地址字段。每个流表表项也有一个关联的优先级。当数据包匹配多个流表表项时,所选择的匹配项和对应的操作将是数据包所匹配的优先级最高的表项。
最后,我们发现并非IP头中的所有字段都能匹配。例如,OpenFlow不允许基于TTL字段或数据报长度字段进行匹配。为什么有些字段允许匹配,而有些则不允许?毫无疑问,答案与功能和复杂性之间的权衡有关。选择抽象的艺术是提供足够的功能来完成一项任务(在这种情况下是实现、配置和管理广泛的网络层功能,这些功能以前通过各种各样的网络层设备实现),不要给抽象增加太多的细节和概括性,以免它变得臃肿和不可用。Butler Lampson有一句名言[Lampson 1983]:
一次只做一件事,做到最好!接口应该捕获抽象的最基本要素。不笼统;笼统化一般是错误的。
考虑到OpenFlow的成功,我们可以推测它的设计者确实很好地选择了抽象。OpenFlow匹配的更多细节可以在[ONF 2020]中找到。
操作
如图4.28所示,每个流表表项都有一个由零个或多个操作组成的列表,这些操作决定了要应用于匹配流表表项的数据包的处理。如果有多个操作,则按列表中指定的顺序执行。
最重要的操作可能包括:
- 转发 一个传入的数据包可以被转发到一个特定的物理输出端口,在所有端口上广播(除了它到达的端口)或在一个选定的端口组播。该数据包可能被封装并发送到该设备的远程控制器。然后,控制器可能(也可能不)对数据包采取一些操作,包括安装新的流表项,并可能将数据包返回给设备,以便在更新后的流表规则集下转发。
- 丢弃 没有操作的流表项表示匹配的数据包应该被丢弃。
- 修改字段 在数据包被转发到选择的输出端口之前,10个头字段(图4.29中除IP Protocol字段外的所有第二、三和四层字段)中的值可能会被重写。
4.4.3 OpenFlow Action中的Match-plus-action示例
现在探讨了广义转发的匹配和操作组件,让我们把这些想法放在图4.30所示的示例网络的坏境中。该网络有6台主机(h1, h2, h3, h4, h5和类推)和三个数据包交换机(s1, s2和s3),每一个有四个本地接口(编号1到4)。我们会探讨很多我们想实现全网行为,和流表表项在s1, s2和s3需要实现这种行为。
第一个例子:简单转发
举一个非常简单的例子,假设期望的转发行为是,从h5或h6发往h3或h4的数据包从s3转发到s1,再从s1转发到s2(从而完全避免使用s3和s2之间的链路)。s1中的流表表项是:
Match | Action |
---|---|
Ingress Port = 1 ; IP Src = 10.3.*.* ; IP Dst = 10.2.*.* | Forward(4) |
... | ... |
当然,我们还需要在s3中有一个流表表项,以便从h5或h6发送的数据报通过传出接口3转发到s1:
Match | Action |
---|---|
IP Src = 10.3.*.* ; IP Dst = 10.2.*.* | Forward(3) |
... | ... |
最后,我们还需要s2中的一个流表表项来完成第一个示例,以便从s1到达的数据报被转发到它们的目的地,即主机h3或h4:
Match | Action |
---|---|
Ingress port = 2 ; IP Dst = 10.2.0.3 | Forward(3) |
Ingress port = 2 ; IP Dst = 10.2.0.4 | Forward(4) |
... | ... |
第二个例子:负载均衡
作为第二个例子,让我们考虑一个负载均衡场景,其中h3发送的数据报通过s2和s1之间的直连链路转发到10.1.*.*,h4发送的数据报将通过s2和s3(然后从s3转发到s1)之间的链路转发到10.1.*.*。请注意,这种行为不能通过IP的基于目的地的转发实现。在本例中,s2中的流表将是:
Match | Action |
---|---|
Ingress port = 3; IP Dst = 10.1.*.* | Forward(2) |
Ingress port = 4; IP Dst = 10.1.*.* | Forward(1) |
... | ... |
在s1也需要流表表项来将从s2接收到的数据报转发到h1或h2;s3需要流表表项,将接口4从s2接口1接收到的数据报通过接口3转发给s1。看看你能否找出s1和s3的这些流表表项。
第三个例子:防火墙
作为第三个例子,让我们考虑一个防火墙场景,在这个场景中,s2只希望接收(在它的任何接口上)从连接到s3的主机发送的流量,s2流表如下:
Match | Action |
---|---|
IP Src = 10.3.*.* IP Dst = 10.2.0.3 | Forward(3) |
IP Src = 10.3.*.* IP Dst = 10.2.0.4 | Forward(4) |
... | ... |
如果s2的流表中没有其他表项,那么只有来自10.3.*.*的流量被转发到附加到s2的主机。
尽管我们在这里只考虑了几个基本场景,但广义转发的多功能性和优势是很明显的。在作业问题中,我们将探讨如何使用流表来创建许多不同的逻辑行为,包括虚拟网络——两个或更多逻辑上独立的网络(每个网络都有自己独立和不同的转发行为)——它们使用相同的物理数据包交换机和链路。在5.5节中,当我们研究计算和分配流表的SDN控制器时,我们将回到流表,以及用于数据包交换机和它的控制器之间通信的协议。
我们在本节中看到的匹配加操作流表实际上是可编程性的一种有限形式:指定路由器应该如何转发和操作(例如,更改头字段)一个数据报,是基于数据报头值与匹配条件之间的匹配。人们可以想象更丰富的可编程形式——可编程性:一种具有高级结构的编程语言,例如变量、通用算术和布尔操作、变量、函数和条件语句,以及专门为以线路速度处理数据报而设计的结构。P4(Programming Protocol-independent Packet Processors)[P4 2020]就是这样一种语言,自从五年前引入以来,已经获得了相当大的兴趣和关注[Bosshart 2014]。
4.5 中间件
路由器是网络层的驮马,在本章中,我们已经了解了它们是如何完成它们的基本工作,即把IP数据报转发到它们的目的地。但是在本章和前面几章中,我们还遇到了网络中的其他网络设备(“boxes”),它们位于数据路径上,执行转发以外的功能。我们在2.2.5节中遇到了Web缓存;3.7节中的TCP连接分离器;以及4.3.4节中的NAT (network address translation)、防火墙和入侵检测系统。我们在4.4节中了解到,广义转发允许现代路由器通过广义的“match plus action”操作轻松自然地执行防火墙和负载均衡。
在过去的20年里,我们已经看到了这种中间件的巨大增长,RFC 3234将其定义为:
在源主机和目标主机之间的数据路径上,执行IP路由器正常、标准功能以外的任何中间件。
我们可以大致识别出由中间件执行的三种服务类型:
- NAT 正如我们在章节4.3.4中看到的,NAT中间件实现了私有网络寻址,重写了数据报头IP地址和端口号。
- 安全服务 防火墙会根据头字段的值来阻断流量,或者重定向数据包进行其他处理,如DPI (deep packet inspection)。入侵检测系统(IDS)能够检测预定的模式并相应地过滤数据包。应用程序级电子邮件过滤器会拦截被认为是垃圾邮件、网络钓鱼或其他对安全构成威胁的电子邮件。
- 性能增强 这些中间件执行的服务包括压缩、内容缓存、将服务请求(如HTTP请求或搜索引擎查询)负载均衡到能够提供所需服务的一组服务器中的一个等。
许多其他的中间件[RFC 3234]提供了属于这三种类型服务的功能,如在有线和无线蜂窝网络中[Wang 2011]。
随着中间件的增多,随之而来的是对这些设备的操作、管理和升级的需要。单独的专用硬件盒、单独的软件栈和单独的管理/操作技能会转化为重大的运营和资本成本。因此,研究人员正在探索将商用硬件(网络、计算和存储)与构建在公共软件栈之上的专用软件结合使用,这也许并不令人惊讶,而十年前SDN实现这些服务时采用的正是这种方法。这种方法被称为 网络功能虚拟化 (NFV,network function virtualization) [Mijumbi 2016]。另一种已经被探索过的方法是将中间件功能外包给云[Sherry 2012]。
多年来,Internet体系结构在网络层和传输/应用程序层之间有明显的分离。在过去的好时光里,网络层由在网络核心内操作的路由器组成,它们只使用IP数据报头中的字段将数据报转发到目的地。传输层和应用层是在网络边缘运行的主机上实现的。主机之间以传输层段和应用层消息交换数据包。今天的中间件显然违反了这种分离:位于路由器和主机之间的NAT重写了网络层IP地址和传输层端口号;网络内防火墙使用应用层(如HTTP)、传输层和网络层头字段阻止可疑的数据报;邮件安全网关在邮件发送者(无论是否恶意)和邮件接收者之间注入,根据白/黑名单IP地址和邮件内容对应用层邮件进行过滤。虽然有些人认为这很可憎[Garfinkel 2003年],其他人则采用了这样的哲学——中间件“exist for important and permanent reasons”——他们满足了一种重要的需求——未来我们会有更多,而不是更少的中间件[Walfish 2004]。关于在网络中何处放置服务功能的问题,请参阅下面的端到端争论部分。
互联网的架构原则
考虑到互联网的巨大成功,人们可能会很自然地想知道,是什么架构原则指导了人类迄今为止所构建的最大、最复杂的工程系统的开发。RFC 1958,题为“互联网架构原则”,认为如果这些原则确实存在,那么它们确实是简朴的:
Internet社区的许多成员会说,没有体系结构,只有一个传统,在最初的25年里(或者至少没有被IAB写下来)。然而,一般来说,社区认为目标是连接,工具是互联网协议,智能是端到端,而不是隐藏在网络中。[RFC 1958]
这就是结果!其目标是提供连通性,只有一个网络层协议(我们在本章中研究过的著名的IP协议),而智能(也可以说是复杂性)将被置于网络边缘,而不是网络核心。让我们更详细地看看最后两个注意事项。
IP沙漏
到目前为止,我们已经很熟悉了在图1.23中首次遇到的五层Internet协议栈。这个栈的另一个可视化显示,如图4.31所示,有时被称为 IP沙漏 (IP hourglass),说明了分层Internet架构的 杨柳腰 (narrow waist)。虽然Internet在物理层、链路层、传输层和应用层有许多协议,但只有一个网络层协议,即IP协议。这是一个必须由数以十亿计的互联网连接设备实现的协议。这种“杨柳腰”在互联网的飞速发展中发挥了关键作用。IP协议的相对简单性,以及它是互联网连接的唯一普遍要求,使得各种具有非常不同的底层链路层技术的网络(从以太网到WiFi到蜂窝网络到光纤网络)成为互联网的一部分。[Clark 1997]指出,“杨柳腰”的作用,也就是他所说的“跨层”(spanning layer),是隐藏这些不同[底层]技术之间的细节差异,并向上面的应用程序提供一个统一的服务接口。特别是对于IP层:IP跨层是如何实现其目的的?它定义了一组基本的服务,这些服务经过精心设计,因此它们可以由广泛的底层网络技术构建。软件,作为Internet[即网络]层的一部分,将这些底层技术提供的内容转换为Internet层的公共服务。
关于杨柳腰的讨论,包括互联网以外的例子,见[Beck 2019;Akhshabi 2011]。我们在这里注意到,随着互联网架构进入中年(当然,互联网的40到50岁的年龄使它成为中年!),人们可能会注意到,通过中间件的崛起,它的“杨柳腰”可能确实会扩大一点(这在中年经常发生!)。
端到端争论
RFC 1958中的第三个原则是——智能是端到端的,而不是隐藏在网络中,这说明了网络中的功能布局。在这里,我们已经看到,直到最近出现的中间件,大多数Internet功能确实是放在网络的边缘。值得注意的是,与20世纪电话网络——是“哑的”(非可编程)端点和智能交换机——互联网一直都有智能终端(可编程计算机),能够在这些终端上放置复杂的功能。但在一篇极具影响力的论文[Saltzer]中提出了一个更有原则的论点,即在端点上实际放置功能[1984年]阐明了“端到端争论”。说的是:
这里有一系列功能,每个功能都可以通过以下几种方式中的任何一种来实现:通过通信子系统实现,通过其客户端实现,作为一个合资企业实现,或者冗余地实现,每个功能都有自己的版本。在对这一选择进行推理时,应用程序的要求为一类参数提供了基础,如下所示:
只有在通信系统端点的应用程序的知晓和帮助下,该功能才能完整而正确地实现。因此,提供被质疑的功能作为通信系统本身的一个特征是不可能的。(有时,通信系统提供的功能的不完整版本可能有助于提高性能。)
我们将这种针对低级功能实现的推理称为“端到端争论”。
一个说明端到端争论的例子是可靠数据传输。因为数据包可能会丢失在网络中(例如,即使没有缓冲区溢出,路由器队列分组可能崩溃,或者由于链路故障,网络中排队的数据包的一部分被分离),端点通过TCP协议(在本例中)必须执行错误控制。正如我们将在第6章中看到的,一些链路层协议确实执行了本地错误控制,但这种本地错误控制本身是不完整的,不足以提供端到端可靠的数据传输。因此,可靠的数据传输必须端到端实现。
RFC 1958故意只包含了两篇参考文献,它们都是关于Internet架构的基础论文。其中之一就是端到端论文本身(Saltzer 1984);第二篇论文[Clark 1988]讨论了DARPA互联网协议的设计理念。对于任何对Internet架构感兴趣的人来说,这两篇都是必读的。继[Clark 1988]之后,[Blumenthal 2001; Clark 2005]根据当今互联网必须在更加复杂的环境中运行的情况,重新考虑互联网架构。
4.6 总结
在本章中,我们介绍了网络层的数据平面功能——per-router的作用是决定到达路由器的一个输入链路的数据包如何被转发到该路由器的一个输出链路。我们首先详细地研究了路由器的内部操作,研究了输入和输出端口的功能和基于目的地的转发,路由器的内部交换机制,数据包队列管理等。我们讨论了传统的IP转发(转发基于数据报的目标地址)和广义转发(转发和其他功能可以使用数据报头中几个不同字段中的值来执行),并看到了后一种方法的通用性。我们还详细研究了IPv4和IPv6协议,以及Internet寻址,我们发现它比我们预期的更深入、更微妙、更有趣。通过对中间件的研究和对Internet体系结构的广泛讨论,我们完成了对网络层数据平面的研究。
随着我们对网络层的数据平面有了新的了解,现在我们准备在第5章中深入研究网络层的控制平面!