EE1608-Computer-Networks-Topic3-Network-Layer
引入
网络层简介
数据链路层工作在一个广播域内,负责局域网内的传输。而网络层负责穿透多个广播域,联通不同的局域网。
网络层的DPU被称为数据包(Datagram)或者IP 包(IP Packet)。网络层使用的地址是IP地址。
网络层的主要作用是:
- 转发(Forwarding):将包从一个路由器的输入口转发到对应的输出口
- 路由(Routing):确定数据包去往目的地的路径是怎么样的,由路由算法驱动
网络层跨接这门课的P1与P2,P1负责网络层A部分,这部分主要包括IP子网划分,如何使用IP等等。网络层B专注于路由算法。
网络层的两种服务类型
网络层有两种服务模型:
- 数据报网络(Datagram Network):提供无连接服务。网络层不需要提前建立 “端到端的连接”,直接转发数据包。
- 虚电路网络(Virtual-Circuit Network):提供面向连接服务。需要先建立 “虚电路”,再传输数据,最后拆除电路。
虚电路(Virtual Circuit)
电路交换(circuit switching)是指使用专用物理通信路径连接通信终端的交换技术。连接建立开始时,通信系统分配给它的资源(通道、带宽、时隙、码字等等),通信活动的整个过程中,这个连接将始终占用着。电路交换总体可以分为这三步:
- 建立连接:分配通信资源。即在使用电路交换打电话前,必须先拨号请求建立连接。当被叫用户听到电话交换机送来的拨号音并摘机后,从主叫端建立连接,即一条专用的物理通路。线路一旦被分配,在未释放之前,其他站点将无法使用,即使某一时刻线路上并没有数据传输。
- 通话:一直占用通信资源。
- 释放连接:归还通信资源
一旦建立虚电路,数据传输的路径固定,延迟等性能指标可预测。在要求数据按先后顺序且以恒定速率快速传输的情况下,使用电路交换是较为理想的选择。因此,当传输实时数据时,诸如音频和视频;或当服务质量(QOS)要求较高时,通常使用电路交换网络。
电路交换最常见的例子是电话网络,但时至今日,电话通信背后的交换技术已经更新了。
虽然传统的电路交换现在已经不再使用,但是它的思想可以被现在的IP网络学习,来保证QoS。虚电路使用VC号识别设备,链路上的每个设备
数据报(Datagrame)
数据报核心是 “无连接、基于目的地址转发”,数据被切分成多个分组传输。数据包携带目的主机的完整地址(IP 地址),路由器根据这个地址决定转发路径。
数据报没有网络层面连接的概念,每一次转发都是独立计算的,换言之,数据包到达目的地的延迟和顺序都可能不一样。
IP数据报与IPv4
IPv4 Header
IP头默认有20Bytes(最短),最长可达60bytes。其内容由下图所示:

版本 Ver(Version):使用4bit来表达IP协议的版本,对于IPv4,其为0100(4)
网络头长度 HLEN(Internet Header Length):使用4bit来表达当前头的长度。HLEN的数值乘4是网络头的Byte数,即,最短为20Bytes使用数字5表示;最长为60Bytes使用数字15表示。
服务类型 TOS (Type of Service):这个字段根据延迟、吞吐量、可靠性和成本要求,指定数据包的优先级。这个字段由8bit组成:
- 0-2bit用于指定优先级(0-7 共8个优先级)。
- bit3 D 用于指定延迟(0=正常延迟,1=低延迟)。
- bit4 T 用于指定吞吐量(0=正常吞吐量,1=高吞吐量)。
- bit5 R 用于指定可靠性(0=正常可靠性,1=高可靠性)。
- bit6 C用于指定成本(0=正常成本,1=最低成本)。bit7保留。

总长度 Total length:用16bits表示包括头在内的数据包总长度,单位为1字节。最高位16位,因此IP包最大大小为65535字节。(但实际中,IP包的大小收到路径 Maximum Transmit Unit, MTU的影响)
标识(Identification):用16bits标识一个数据包的分片属于哪个原始数据包。当 IP 数据包被分片时,所有分片会携带相同的标识值,以便目的主机将这些分片重组为原始数据包。
标志(Flags):
- 位 0(保留位):必须设为 0。
- 位 1(DF,Don’t Fragment):表示 “不分片”。若该位为 1,数据包不允许被分片;若为 0,则允许分片。
- 位 2(MF,More Fragments):表示 “还有分片”。若该位为 1,说明该分片不是最后一个分片;若为 0,说明是最后一个分片。
分片偏移(Fragmentation offset):表示该分片在原始数据包中的相对位置,单位为 8 字节。目的主机通过分片偏移和标识字段,将所有分片按正确顺序重组为原始数据包。
生存时间(Time-to-live,TTL):限制数据包在网络中的存活时间,防止数据包在网络中无限循环。每经过一个路由器,TTL 值减 1,当 TTL 值为 0 时,数据包被丢弃。通常用于诊断网络故障(如
ping命令)。协议(Protocol):标识上层协议,即该 IP 数据包携带的数据是由哪种传输层协议处理的。例如,值为 6 表示 TCP,值为 17 表示 UDP,值为 1 表示 ICMP 等。
头部校验和(Header checksum):CRC校验
选项(Options)+ 填充(Padding):选项用于实现一些特殊功能,如记录路由(RR)、时间戳(TS)、源路由(SR)等。由于 IP 头部长度必须是 4 字节的整数倍,当选项部分长度不足时,通过填充 0 来满足这一要求。
例:一个 IPv4 数据包到达,其前 8 位为 (01000010)₂。接收方丢弃了该数据包。为什么?
前4位中,0100表示IPv4版本,后4位表示IP头长度,IP头最小长度位20byte,而这里只有2byte。因此IP头肯定发生了损坏。
例:在一个 IPv4 数据包中,HLEN 的值是 5,总长度字段的值是 40(十进制)。这个数据包携带了多少字节的数据?
头部长度是$5\times 4= 20 Bytes$,总长度是$40Bytes$,则携带了20Bytes数据。
IP分段(Fragmentation)
MTU(Maximum Transmission Unit,最大传输单元):MTU指在网络层一次传输中,能够发送的最大 PDU(协议数据单元,即数据报)的大小。例如以太网帧最大长度为 1518 字节,因此其 MTU 为 1500 字节。
由于数据报在互联网中传输时,可能经过不同类型的网络。不同数据链路层的网络对帧大小的要求不同,因此 MTU 也不同。如果数据报大小超过某网络的 MTU,就必须进行 分片。
当数据报大小 超过路径上的 MTU 时,必须进行分片:
- 每个分片的数据部分(除最后一个)必须是 8 字节的整数倍。
- 分片可以在:
- 源主机完成(通常由 IP 层处理)
- 中间路由器完成(若路径 MTU 更小)
- 分片可以被再次分片,形成多层分片结构。
分片与重组依赖于 IP 报文头中的三个字段:
- Identification(标识符):唯一标识某个数据报的所有分片。
- Flags(标志位):指示是否允许分片、是否还有后续分片。
- 位 0(保留位):必须设为 0。
- 位 1(DF,Don’t Fragment):表示 “不分片”。若该位为 1,数据包不允许被分片;若为 0,则允许分片。
- 位 2(MF,More Fragments):表示 “还有分片”。若该位为 1,说明该分片不是最后一个分片;若为 0,说明是最后一个分片。
- Fragment Offset(分片偏移量):指示该分片在原始数据报中的位置(以 8 字节为单位)。
例题:一个数据包到达时,M 位的值为 0。这是第一个片段、最后一个片段,还是中间片段?(1)我们知道这个数据包是否被分片了吗?(2)若Mbit 为1呢?(2)若Mbit为1,且Offset为0呢》
(1)Flag的M位是0,表示没有更多分片了。因此这是最后一个包。但是我们不知道DF位的值,所以无法确定这个片段是否经过分片。
(2)若M bit为1,则表示后面还有分片,那这个包肯定经过了分片。但是它可能是第一个片段,也可能是中间片段。
(3)这一次,由于偏移量是0,所以这肯定是第一个分段。
例题:一个数据包到达,其offset为100。这个包内第一个字节的编号是多少?(1)我们知道最后一个字节的编号吗?(2)如果再补充HLEN的值为5,Total Length的值为100呢?
(1)包内第一个字节的编号就是$100\times8=800$(偏移以8byte为单位)。然而由于不知道这个包的长度,所以无法知道最后一个字节的编号。
(2)有了补充之后,我们知道IP头占了$5\times4=20bytes$,总长度100bytes,数据有80bytes。因此最后一个字节的编号是879。
例题:一个IP数据报将被转发到MTU为576字节的网络。该数据报有20字节的IP头和1484字节的负载,应该如何分片?
由于MTU是576,那么每个数据报的数据部分只能占$576-20=556byts$。
由于IP分段要求除了最后一段,数据部分都要是8的倍数,因此一段最多有552Bytes数据。
那么,将1484字节的数据拆分,可以拆分出两个552Bytes+1个380Bytes。因此最终拆分出三个包,如下图所示(下图从左到右的字段分别表示:Identification(63),Flags,Fragment Offset,以及Data(编号)):

IP地址分配
基础:IPv4 地址与“类(classful)”
ip地址由32bit构成,常记为xxx.xxx.xxx.xxx的形式(每个xxx的范围是0-128(8bit))。
有分类IP地址
最开始,将IP地址划分为了ABCDE五类,其中ABC三类为单播地址(一对一通信),是最常用的。

IP地址最开始仅由 地址分类号+网络号+主机号 构成。比如A类地址,它的第一个bit是0,在看到bit1=0时,路由器就知道是A类地址,前8bit是网络号,后24bit都是主机号。
网络号用于区分不同网络,路由器负责将不同网络之间路由通。主机号用于区分不同主机,这些主机都处于一个局域网内(或称一个广播域内,即,使用二层设备相互连接)。
在路由器内,路由表中只需要存储xxx网络(网络号)通过xxx端口路由,即可把数据包转发到对应的局域网内。
对于网络号的位数被称为掩码(mask),掩码也是由32bit构成。例如一个C类地址,它只有最后8位是主机号,它的掩码就是24位1+8位0,即,255.255.255.0。常记作192.168.23.0/24这样的形式。在路由器进行路由时,例如有一个数据包要发给192.168.23.1这个主机,路由器只关心发送给哪个局域网,它就会把IP地址与掩码进行与运算,192.168.23.1&255.255.255.0=192.168.23.0,这样它就拿到了单纯只有网络号的地址,把网络号和自己路由表一比对即可找出往哪个端口路由。
局域网内特殊的IP地址
在一个局域网内,主机号全0的地址作为局域网的标识,不分配给主机。例如C类地址最后8位是主机号,192.168.23.0这个C类地址就不分配给任何一个主机,而是单纯用来标识192.168.23.0这个网络。
在一个局域网内,主机号全1的地址作为广播地址,不分配给主机。例如C类地址最后8位是主机号,192.168.23.255这个C类地址就不分配给任何一个主机,当有IP数据报携带这个地址进入局域网时,会被分发给该网段上的所有计算机。
分类IP地址的局限性
classful 太僵化,会造成地址浪费。例如一个机构只要 300 台主机,但只能拿 Class B 地址,主机号可以支撑$2^16-2=65534$太主机,这会浪费很多地址。
因此在主机号的基础上,还可以再从主机号内借用若干比特来划分一段子网号(subnet-id),来更精细化地分配局域网内的资源(三级编址)。在划分和子网后,路由器先使用网络号进入网络后,再使用子网号进入子网,再在子网内寻找主机。
固定长度子网划分(Fixed-Length Subnet Mask FLSM)
固定长度的子网划分可以将一个较大的网络划分为多个大小相同的子网(每个子网掩码相同)。
例如,对于223.1.1.0/24这个C类地址,它被某一个小公司拿到了。这个小公司有多个部门,每个部门主机量都小于30台。那么就可以把这个C类地址中8位主机号借3位出来,变成子网号,每个子网内最多有$2^{8-3}-2=30$台主机,共有$2^3=7$个不同的子网。每一个子网都可以分配给一个不同的部门。
每个子网的掩码都记作/27,例如223.1.1.0/27。这个网络号内的所有的主机(所有子网内的主机)填写子网掩码时,都要填255.255.255.224。
对于公司内部的路由器,它使用的掩码地址就是255.255.255.224,即,它需要区分每一个子网,为每个子网创建一条路由表。而对于骨干网路由器,它只会看到223.1.1.0是个C类地址,不会为子网创建路由表。
这个过程就像是快递分拨,地址是重庆市江北区xxx,先派送到重庆分拨中心(骨干网路由器转发到223.1.1.0网络内),再由重庆的快递公司自行分拣到江北区派送中心(公司内部路由器根据子网来分拨)。
在早期(Classful 网络时代,1980s),子网号全0和子网号全1不被允许使用,因为怕和“网络标识”及“广播子网”混淆。而在今天(CIDR 时代),它明确允许使用,也确实应该使用。
一个例子:如果一个类 B 地址的源主机是 140.252.1.1,并且子网掩码是 255.255.255.0
- 若目标主机IP地址是140.252.4.5 ,那么源与目标处于一个网络内,但在不同子网
- 若目标主机IP地址是140.252.1.22 ,那么源与目标处于一个网络内,且在同一子网
- 若目标主机IP地址是192.43.235.5,那么源与目标处于不同网络
可变长度子网划分(Variable-Length Subnet Mask VLSM)
固定长度子网掩码使得每一个子网的主机数量都是一致的,然而,就算在一个公司内,各部门主机数量也可能有差异。这就需要VLSM。
VLSM可以根据每个子网的实际需要分配不同大小的子网(掩码可变)。通常采取“先满足最大需求(largest-first)”的分配策略,保证地址对齐与不重叠。
VLSM的划分可以遵循以下步骤:
- 把需要的子网按所需主机数从大到小排序。
- 对每个需求,选择能容纳其主机数的最小子网(最小地址块),即找到满足 $2^h - 2 \ge \text{所需主机数}$ 的最小 h,使得前缀 =
32 - h。 - 将该块从可用地址池中切出(从低地址向高地址依次分配,注意对齐)。
- 重复,直到所有需求分配完或地址耗尽。
举个例子:假设你有 200.10.20.0/24这个网络,需要分配给 4 个子网,需求分别:100、50、10、5 主机
第一&二步:从大到小选择能容纳主机数的最小子网
- 100 主机:找最小 h 使 $2^h -2 \ge 100$。 $h=7 \Rightarrow 2^7-2=126$。前缀 =
32-7=25→/25。 - 50 主机:$h=6 \Rightarrow 62$ 主机 →
/26。 - 10 主机:$h=4 \Rightarrow 14$ 主机 →
/28。 - 5 主机:$h=3 \Rightarrow 6$ 主机 →
/29。
第三步:从 200.10.20.0/24 低地址开始分配(largest-first)
- 第一个子网:
200.10.20.0/25,子网号为0,子网内IP范围是192.168.20.0-192.168.20.127。最大主机容量为126(全0和全1主机号保留)。在这一次分配完之后,剩下的IP都需要从200.10.20.1000 0000(128)开始,以和第一个子网区分开。 - 第二个子网:
200.10.20.128/26,子网号是10,子网内IP范围是192.168.20.128-192.168.20.191,最大容纳主机数为62。在这一次分配完之后,剩下的IP都需要从200.10.20.1100 0000(192)开始,以和现在已经划分的子网区分开。 - 第三个子网:
200.10.20.192/28,子网号是1100,子网内IP范围是192.168.20.192-192.168.20.207,最大容纳主机数为14。在这一次分配完之后,剩下的IP都需要从200.10.20.1101 0000(208)开始,以和现在已经划分的子网区分开。 - 第四个子网:
200.10.20.208/29,子网内IP范围是192.168.20.208-192.168.20.223,最大容纳主机数为6。 - 而
192.168.20.223-192.168.20.255还可以留给未来的子网分配使用。
无类别域间路由(Classless Inter-Domain Routing CIDR)
是什么
B类IP地址在1992年就已经分配了一半,眼看就要快分完了。同时,互联网主干网上路由表的项目数正在急剧增长。为了解决这个问题,IETF研究出了无分类编址,正式名称是无分类域间路由选择(Classless Inter-Domain Routing, CIDR)。
传统的有分类IP地址,纵然使用VLSM进行子网划分,那么对于划不了这么多子网的地方仍是浪费。例如,我的公司就3个部门,每个部门就7 8台计算机,但是我拿到了一个B类地址,就算我使用VLSM,那么也有大量资源被浪费。这归根结底是IP地址分类把网络号给定死了。
CIDR消除了传统的ABC类地址划分和子网的概念。CIDR把32位的IP地址划分为前后两个部分。前面部分是“网络前缀”(network-prefix),用来指明网络,后面部分则用来指明主机。因此CIDR使IP地址从三级编址(使用子网掩码)又回到了两级编址。
在CIDR中,可以使用任意长度前缀(/n),不受 A/B/C 的限制(即无类别)。而且允许 路由聚合(route aggregation / supernetting):把多个连续且对齐的子网合并成一个更短的前缀。
为何说CIDR是一个VLSM的增强版
本质来说,CIDR就是把一段无类别的IP地址切成下图这样:

这和分配VLSM一模一样。唯一的区别是,CIDR对于最大粒度的IP地址块(即,第一个被分割的IP地址)不再有class要求,提高了资源利用率。例如,假设南洋理工大学校园网内有一万台设备。要容纳下这一万台设备,按照传统的有分类IP,NTU必须拿一个B类地址,即,16号主机位。然后再进行子网划分。然而,现在有了CIDR,我们可以不关心分类了,直接把10.16.64.0/18这个地址块拿给NTU。这个地址块理论可以分出$2^{14}=16384$个IP地址。
让我们再回去看看之前VLSM的那个例子,我们划分出了:
| 子网编号 | 子网地址 | 网络号 | |
|---|---|---|---|
| 1 | 200.10.20.0000 0000(0) |
`200.10.20.0 | xxx xxxx` |
| 2 | 200.10.20.1000 0000(128) |
`200.10.20.10 | xx xxxx` |
| 3 | 200.10.20.1100 0000(192) |
`200.10.20.1100 | xxxx` |
| 4 | 200.10.20.1101 0000(208) |
`200.10.20.1101 | xxxx` |
CIDR是如何把多个层级的子网进行聚合的呢?假设现在这个拓补如下图:

那么,路由1的路由表只需要存储200.10.20.x|--- ----来区分是发给子网1,还是发给路由2即可,子网1+路由2我们称为CIDR块1。
路由2的路由表只需要存储200.10.20.xx|-- ----来区分是发给子网2,还是发给路由3即可,子网2+路由3我们称为CIDR块2。
路由3的路由表只需要存储200.10.20.xxxx| ----来区分是发给子网3,还是发给子网4即可,子网3+子网4我们称为CIDR块3。
不难看出,CIDR块1是由可以切出CIDR块2,CIDR块2可以切出CIDR块3,每一层的路由都只需要记住自己负责的CIDR块内如何路由就行。对外,路由器可以把这个局域网合成一条:200.10.20.0/24都发给路由1。这样就大大减少了路由表。
纵然VLSM也可以这样聚合路由,而VLSM还是以有分类IP为基础的,那么就定死了第一次分割的粒度。而CIDR就强在第一次分割的粒度不定,又可以一直分下去,把一个大的CIDR块切成不同的小的,最后每一层级的路由只存储自己这个粒度下的路由。
特殊的CIDR地址:
| 网路前缀长度 | 地址掩码 | 说明 |
|---|---|---|
| /32 | 255.255.255.225 | 就是一个IP地址。用于主机路由 |
| /31 | 255.255.255.254 | 只有两个IP地址,主机号为0和1,用于点对点通信 |
DHCP
DHCP是什么
HDCP(Dynamic Host Configuration Protocol)允许主机在加入网络时,从网络服务器动态获取IP地址。以此来实现网络地址的复用。
DHCP有如下特点:
- 采用租约机制:主机可以续租使用中的地址,若主机离开,到期没有续约到期可以更新(renew)。
- 地址复用:基于租约机制,允许不同设备复用地址(地址仅在连接时保留)
- 更强的移动性:比如笔记本电脑到处连 WiFi,都能自动拿到新网络的地址。
DHCP获取地址的步骤
DHCP消息交互包含4个步骤:
DHCP Discover(发现):首次接入网络的DHCP客户端不知道DHCP服务器的IP,为了学习到DHCP服务器的IP地址,DHCP客户端以广播方式发送DHCP DISCOVER报文。
DHCP Offer(提供):
- DHCP 服务器收到 discover 后,会选择跟接收DHCP DISCOVER报文接口的IP地址处于同一网段的地址池,并且从中选择一个可用的IP地址,然后通过DHCP OFFER报文广播给DHCP客户端。
- DHCP服务器的地址池中会指定IP地址的租期,如果DHCP客户端发送的DHCP DISCOVER报文中携带了期望租期,服务器会将客户端请求的期望租期与其指定的租期进行比较,选择其中时间较短的租期分配给客户端。
DHCP Request(请求):由于网段内可以存在多台DHCP服务器,因此主机需要通过Request来明确,它选取了哪一个DHCP offer。主机会以广播方式发送DHCP REQUEST报文,该报文中包含客户端想选择的DHCP服务器标识符和客户端IP地址。
DHCP ACK(确认):最后服务器对客户端明确使用的offer进行一次确认,完成分配。
下面是一个DHCP分配的例子:

能通过DHCP服务器获取的不仅仅是子网中分配的 IP 地址,还有:
- 客户端的第一跳路由器地址
- DNS 服务器的名称和 IP 地址
- 网络掩码(指示地址的网络部分和主机部分)
NAT
随着IPv4的IP逐渐被分配完,不可能做到一台设备一个IP地址。因此需要对其进行网路地址转换(Network Address Translation, NAT)。在外界看来,一个局域网内的
在NAT模式下,所有离开本地网络的数据都拥有同一单源的IP地址,但具有不同的端口号。如下图所示:

局域网内10.0.0.x的设备,经过设置了NAT转换的路由器之后,都以138.76.29.7这个IP地址对外,但是具有不同的端口号。当数据包发回给这里面的某一个机器时,NAT路由根据端口号恢复原机器的IP地址。
NAT的实现过程:
- 将出站的每一个数据包的
IP+端口映射成为NAT IP + 新端口,去访问对应的目标主机 - NAT路由在NAT转换表(NAT translation table)中记住每一个IP+端口的映射关系。
- 将每一个入站的数据包,通过NAT转换表,把
NAT IP + 新端口重新映射回原来的IP+端口,发回给内网
如下图这个例子

NAT的好处:
- 一个局域网内的设备只需要一个IP地址,无需从运营商(ISP)处获取地址块
- 可以在不改变外部网络路由器路由表(即,不通知外部网络)的情况下改变本地网络的设备地址。
- 可以更换运营商(ISP),而不更改局域网的IP地址构成。
- 局域网内的设备无法直接被外部网络访问,只能从内访问外部。提高了安全性(因为外部设备就算知道机器未经过NAT的IP,也没有路由器知道这个IP如何路由。只能访问网关路由的IP,然而网关路由在NAT关系没有建立前,不知道这个连接发给内网的哪台设备)。
端口号位于传输层,其是一个16bit的地址,因此NAT可以使单个局域网地址支撑超过6万个同时连接。
然而,由于NAT使用了传输层技术,也存在一些争议:路由器是三层设备,应该仅处理三层网络,不应涉足传输层。而且NAT违反了端到端原则,也使得基于点对点(P2P)通信的应用实现更复杂。