网络层简介
网络层的主要作用为实现网络互联,即将分组从一台主机发送到另一台主机上。为此需要实现两种功能:
- 转发(forwarding):网络层将输入链路到达的分组移动到适当的一条或多条输出链路中,或者可能阻挡异常分组转发
- 路由选择(routing):网络层决定发送方向接收方发送分组所采用的路由或路径,因此网络层需要提供合适的路由选择算法
转发一般在几纳秒内完成,通常由硬件实现。路由选择一般需要几秒完成,通常采用软件实现。
为了实现主机互联,网络层需要庞大的遍布世界的分组交换机连接形成网络拓扑结构。分组交换机指能根据首部字段将分组从输入链路接口转移到输出接口的通用分组交换设备。某些分组交换机基于链路层帧的字段转发,称为链路层交换机(link-layer switch),其它基于网络层数据报做转发决定的分组交换机称为路由器(router)。
为了使分组发送到正确的位置,路由器需要选择合适的路径。每台路由器中都有转发表(forwarding table)。路由器根据到达分组首部的一个或多个字段值在其转发表中索引,确定该分组将被转发的路由器的输出链路接口:
网络层能够被分解为两个相互作用的部分:数据平面和控制平面。数据平面主要是每台路由器的功能,决定到达路由器输入链路之一的数据报转发到哪条输出链路。控制平面控制数据报沿着从源主机到目的主机的端到端路径中路由器之间的路由方式。
网络服务模型(network service model)定义了分组在发送与接收端系统之间的端到端运输特性,包括:
- 分组到达目的地
- 时延不超过某一上界
- 分组有序交付
- 一定带宽
- 安全性
- ...
网络层仅提供尽力而为服务,不能保证这些服务的质量。
路由器工作原理
路由器是网络层设备,它们最高只涉及处理网络层的服务,几乎不参与处理运输层与应用层。
下图展示了路由器的基本结构:
路由器包含 4 个主要组件:
- 输入端口:处理输入分组的物理层和链路层功能,并执行查找决定路由器输出端口
- 交换结构:将路由器的输入接口与输出接口相连
- 路由选择处理器:执行控制平面功能
- 输出端口:存储从交换结构接收的分组,执行必要的链路层和物理层功能后发送到输出链路上
输入端口处理
下图展示了输入端口更详细的结构:
在输入端口中,路由器使用转发表查找输出端口。路由器用分组目的地址的前缀匹配该表项,并向匹配项相关联的链路转发分组。当有多个匹配时,路由器使用最长前缀匹配规则,寻找最长的匹配项并转发。
由于在高速链路中查找需要在纳秒时间内完成,因此需要通过硬件使用快速查找算法执行。
一旦通过查找确定了分组的输出端口,则该分组就准备进入交换结构。如果其它输入端口正使用交换结构,那么该分组将被阻塞并排队,等待稍后调度通过交换结构。
除此之外,输入端口还会处理一些别的事务,将在后续介绍。
交换
交换结构是路由器的核心部位,可以通过三种方式完成交换:
- 经内存交换
最简单、最早的路由器由计算机充当,到达的分组通过中断的形式通知 CPU ,使其从首部提取目的地址并通过内存复制到输出端口的缓存中。
使用该方式需要各读写一次内存,因此吞吐量只有内存读写速率的一半,且不能同时转发两个分组。
现代经由内存交换的路由器由输入线路卡来将分组写入适当输出端口的内存中。
- 经总线交换
输入端口可以使用一根共享总线将分组直接传送到输出端口。通常在输入端口处使分组附加一个额外的临时首部标签,经由总线可以被所有输出端口接收,但只有标签对应的输出端口才能保留并发送该分组:
一次只有一个分组能够跨越总线,因此多个分组同时到达路由器时,只有一个分组能通行,其余必须等待。路由器的交换带宽受总线速率的限制。
- 经互联网络交换
使用复杂的互联网络可以克服单一总线的带宽限制。纵横式交换机通过互联网络总线连接多个输入与输出端口,交叉点通过交换结构控制器控制分组通行:
通过闭合合适的交叉点,就可以产生合适的通行路径,并可以转发给多个输出端口。这种交换机是可并行的,且只要不发生总线冲突,转发分组将不会被阻塞。
- 输出端口处理
输出端口处理存放在其缓存中的分组,并将其发送到输出链路上,执行所需的链路层和物理层传输功能:
分组排队与调度
在输入端口和输出端口处都可能存在分组队列:如果交换结构处理速度比输入分组到达速度慢,在输入端口处将出现分组排队等待通过;同样如果向输出链路发送分组比到达速度慢,输出端口也可能发生排队。
交换结构一次只允许一个分组到达指定输出端口,因此如果两个输入队列待发送分组目的一致,则其中的一个分组将被阻塞,必须在输入队列等候。并且该等候分组的排在后面的所有分组也需要等待,称为线路前部(Head-Of-the-Line, HOL)阻塞:
当队列缓存耗尽时,可能产生分组丢失。路由器可以丢弃到达的分组,不过有时在队列满之前也可能主动丢弃一个分组,用于向发送方提供拥塞信号。
多个分组可能同时准备发往同一个输出端口,并且其后的分组也可能发往该输出端口,这就需要输出端口的分组调度(packet schedular)在其中选择一个分组来传输。分组调度可以使用以下方法处理:
- 先进先出
先进先出(First-In-First-Out, FIFO)队列的抽象模型如下:
FIFO 调度规则按照分组到达队列的次序来选择处理分组:先到达的分组先被传输,如果链路正在传输前面的分组,则后续到达的分组要排队等待。
- 优先权排队
优先权排队(priority queuing)规则使到达的分组被分类放入不同的优先权类,通常位于各自的队列中:
多个分组准备传输时,将传输有等待分组的最高优先权类中的分组。同一优先权类的分组之间通常以 FIFO 方式完成传输。非抢占式优先权排队规则可以使低优先级分组在传输时,不会被到达的高优先级分组打断,高优先级分组只能先等待。
- 循环和加权公平排队
循环排队(round robin queuing)规则下分组同样被分类,但类之间不存在严格的服务优先权,循环调度器在这些类之间轮流传输。保持工作排队(work-conserving queuing)规则在有分组排队等候时不允许链路空闲,某个类没有分组时将立即处理下一个类。
下图表示常用的加权公平排队(Weighted Fair Queuing, WFQ)规则,可以根据权重分配服务时间占比:
这样可以保证所有类都获得一定的吞吐量。
网际协议
网际协议简介与IPv4数据报
网际协议(Internet Protocol, IP)是网络层一个非常重要的协议,IP 协议组织了互联网上的主机,对网络层运作至关重要。
IP 协议有两个最重要的版本,目前最常用的版本是 IPv4 。
首先研究 IPv4 数据报,其格式为:
其包含的一些关键字段如下:
- 版本:通过版本号可以确认数据报剩余部分的格式,IP 版本 6 的数据报格式与上图并不一样,将在后文研究
- 首部长度:由于选项长度可变,因此需要该字段指示首部长度。如果不包含选项,典型的 IP 数据报首部长度为 20 字节
- 服务类型:使不同类型的 IP 数据报区分。不同类型的 IP 数据报在路由器中往往调度方式也不同
- 数据报长度:数据报包括数据的完整长度
- 标识、标志、片偏移:与 IP 分片有关,将在后文介绍
- 生命周期(Time-To-Live, TTL):确保数据报在路由环路等情况下不会永远存在。每一台路由器处理数据报时,该值便减一,减至零便被丢弃
- 协议:指示 IP 数据报的数据部分需要被交付给哪个运输层协议。在 UDP 协议的检验和计算实验中介绍过计算检验和时需要添加伪首部,伪首部的协议类型就是该字段
- 源和目的 IP 地址:IP 地址用于指示主机,在前面几篇文章中都提到了该地址的作用,将在接下来详细介绍它
- 选项:一些额外的信息
- 数据:有效载荷(例如运输层报文段)
IPv4数据报分片
IPv4 支持的最大报文长度为 65535 字节,但是链路层未必能承载这么多字节。一个链路层帧能承载的最大数据量称为最大传送单元(Maximum Transmission Unit, MTU)。MTU 限制着数据报的长度,并且在不同的链路上该长度可能会变化。
为此,需要将 IP 数据报分片,用单独的链路层帧封装这些较小的 IP 数据报并发送。这些较小的数据报称为片(fragment)。
片在其到达目的地运输层以前需要重新组装。首部的标识字段区分不同的原始数据报;原始数据报的最后一个片的标志位被置为 0 ,其它片的标志位被置 1 以提示分片接收完毕可以组装;偏移字段表示这些片位于原始数据报中的哪个位置,以避免片丢失或乱序到达。
IPv4编址
主机或路由器与物理链路之间的边界称为接口,它们为了能发送或接收数据报,要求每个接口都需要拥有一个独立的 IP 地址。IP 地址是互联网上每一台主机每一个接口 32 比特的标识符,可用的 IP 地址约有 40 亿个。
IP 地址通常按所谓点分十进制记法(dotted-decimal notation)书写,即地址中的每个字节用十进制形式书写,各字节间以点号隔开。例如,如果一个 IP 地址为
01111011 00111000 01001110 10011010
那么它通常书写为:
123.56.78.154
全球互联网中的每台主机和路由器上的每个接口,都必须有唯一的 IP 地址。但这些地址不能随意地选择,需要由其连接的子网来确定。
考虑以下连接,路由器的两个接口连接两组主机。路由器的一个接口和主机的多个接口之间通过一个无路由器的网络相连,称为子网(subnet)。IP 编址为这个子网提供了一个子网掩码(network mask),指示接入该子网的任何主机最左侧的若干比特都要相同。
以下示例共有 3 个子网,注意两个路由器接口间也存在一个子网:
最左侧的子网掩码可以表示为 172.217.2.0/24
,斜杠表示 IP 地址最左侧的 24 比特相同。互联网的地址分配策略称为无类别域间路由选择(Classless Interdomain Routing, CIDR),它将地址分为前缀和剩余部分,一个区域通常被分配一块前缀相同的连续地址,这样路由器转发时只需匹配该前缀就可以发往正确的方向,大大减少了转发表长度。前缀越长,对应的地址块越小,地址越详细。
还有一个特殊的 IP 地址 255.255.255.255
,称为广播地址。当一台主机发出的数据报具有目的地址为广播地址时,该报文会交付给同一个网络中的所有主机。
IP 地址由互联网名字和编号分配机构(Internet Corporation for Assigned Names and Numbers, ICANN)管理,并且该组织还管理 DNS 根服务器。ICANN 向区域性互联网注册机构分配地址,从而为每一台主机提供 IP 。
动态主机配置协议
一个组织一旦获得了一块地址,它就可为本组织内的主机与路由器接口逐个分配。路由器地址一般远程手工配置,然而主机地址一般使用动态主机配置协议(Dynamic Host Configuration, DHCP)完成。DHCP 使主机每次连接到网络时,都可以自动分配一个合适的 IP 地址,并通知主机子网掩码、本地 DNS 服务器地址等信息。
DHCP 是一个客户-服务器应用层协议,基于 UDP 提供的服务。每个子网需要有一台 DHCP 服务器或使用路由器充当网络中继代理,服务器使用端口号 67 ,客户使用端口号 68 。
DHCP 为一台新到达的主机分配 IP 需要经历以下 4 个步骤:
- DHCP 服务器发现:一台新到达的主机可以通过使用 DHCP 发现报文发现 DHCP 服务器,该报文通过目的地址
255.255.255.255
向子网所有节点中广播,并使用源 IP 地址0.0.0.0
代表本主机 - DHCP 服务器提供:DHCP 服务器收到一个 DHCP 发现报文后,使用 DHCP 提供报文作响应,向客户提供推荐的 IP 地址、网络掩码、第一跳路由器地址(默认网关)以及 DHCP 租用期等。提供报文仍然使用广播地址回应
- DHCP 请求:子网中可能有不止一个 DHCP 服务器,新到达的客户从中选择一个合适的服务,并向选中的服务器提供用 DHCP 请求报文,确认配置参数
- DHCP 响应:服务器使用 DHCP ACK 报文对此作出响应,证实所要求的参数
在广播期间,由于非新接入主机和 DHCP 服务器不提供 67 、68 端口的服务,因此不会参与 DHCP 的工作。
一旦客户收到 DHCP ACK 后,交互便完成了,并且该客户能够在租用期内使用 DHCP 分配的 IP 地址。主机可以随时通过 DHCP 释放报文终止租用期。
当租用期过半时,主机会重新发送 DHCP 请求,若 DHCP 服务器拒绝请求,主机必须重新执行 DHCP 服务器发现等一系列步骤;当租用期快到时,主机也会重新发送 DHCP 请求,若 DHCP 服务器未响应,则当租用期到达后,主机必须立即停止使用其租用的 IP 地址。
网络地址转换
子网中的主机数可能会增加,网络地址转换(Network Address Translation, NAT)提供了一种管理 IP 地址的典型方法。
NAT 路由器对外界的行为就如同一个具有单一 IP 地址的单一设备,所有离开子网路由器流向互联网的报文都拥有相同的 IP 地址。NAT 使路由器对外界隐藏了专用网络(private network)的细节。
在专用网络中,所有接口都具有相同的地址空间 10.0.0.0/8
,该地址是一个保留地址空间,保留地址空间仅可用于当前的专用网络,不可用于互联网中。每一个专用网络各自维护一个保留地址空间,从而管理专用网络中的主机 IP 地址。
当专用网络中的主机要和互联网通信时,需要通过 NAT 路由器转发。NAT 路由器具有一张 NAT 转换表(NAT translation table),在表项中包含需要转发给的 IP 地址及端口号。
例如,专用网络主机 10.0.0.1
如果要向互联网上的某台服务器发送请求,它通过端口号 12000 发送给 NAT 路由器,NAT 路由器使用互联网一侧接口的 IP 地址 138.76.29.7
和空闲端口号 3435 替换源数据报的信息,将转换后的数据报发送到互联网上,并在 NAT 转换表中新建一个表项。当接收到服务器的响应后,根据表项的转换规则将 138.76.29.7:2425
换回 10.0.0.1:12000
。
NAT 充当计算机网络的中间盒组件,连接了互联网的同时也易于管理内网。现今绝大多数家庭网络都使用 NAT 管理,因此平时上网时的主机无法被广域网发现,也就无法充当互联网服务器。为了突破 NAT 的限制,可以使用 NAT 穿透(NAT traversal)工具(或称内网穿透)。不过内网穿透得到的服务器不够稳定,且可能被屏蔽。
IPv6
IPv4 仅提供约 40 亿个 IP 地址,哪怕有专用网络使特定范围的 IP 可以被重复使用,也无法满足日益增长的 IP 地址的需求。为此一个新的 IP 版本 IPv6 被提出。
IPv6 的数据报格式如下:
IPv6 将地址长度从 32 比特增加到 128 比特,甚至地球上每个沙粒都可以分配一个 IP 地址。除了普通地址和广播地址以外,IPv6 还引入了任播地址(anycast address),这种地址可以使数据报交付给一组主机中的任意一个。
IPv6 使用简化高效的 40 宇节首部,许多必要字段被舍弃,从而使路由器可以更快处理。
IPv6 提供了一个流(flow)的支持,不过其定义还没有完全明确。
除此之外,IPv6 还包含以下字段:
- 版本:通过将该字段置为 6 ,可以提醒按 IPv6 报文格式处理后续数据
- 流量类型:与 IPv4 报文中服务类型字段含义相同
- 有效载荷长度:给出 IPv6 数据报在定长 40 字节首部后面的字节数量
- 下一个首部:与 IPv4 报文中协议类型字段含义相同
- 跳限制:与 IPv4 报文中生命周期字段含义相同
IPv6 不再支持分片,因为其耗时太大。如果数据报太大,则路由器将其丢弃并返回一个特殊的差错报文。
IPv6 不再提供检验和,必要的检验已经由运输层完成了。
IPv6 不再显式支持选项,不过其首部的“下一个首部”字段可以指向额外的选项字段位置。去除选项使 IPv6 首部成为定长的 40 字节,无需再拥有长度字段。
由于目前公共互联网只支持 IPv4 ,要使其完全迁移到 IPv6 几乎不可能。目前可行的方式只是先迁移一部分节点,在通过 IPv4 节点时新建一个 IPv4 数据报并作为载荷通过。