#计算机网络学习笔记4
网络层概述
网络层的功能:将分组从发送主机传输到接收主机
网络层的两个关键功能:
- 转发(forwarding):将分组从路由器的输入链路移动到适当的输出链路(数据平面,局部功能)
- 路由选择(routing):确定分组从源到目的地所经过的路径(控制平面,全局功能)
数据平面与控制平面
数据平面:
- 局部的、每个路由器的功能
- 确定到达路由器输入端口的数据报如何转发到输出端口
- 转发功能:通过查找转发表实现
控制平面:
- 网络范围的逻辑
- 确定数据报在端到端路径上如何在路由器之间路由
两种控制平面方法:
- 传统路由选择算法:在路由器中实现,路由器之间交换路由信息
- 软件定义网络(SDN):在远程服务器中实现,集中式控制器计算并下发转发表
网络层服务模型
网络层的服务模型回答一个问题:从发送主机到接收主机,网络层能够向传输层提供什么保证。
可能的逐数据报服务:
- 保证交付:数据报一定到达目的主机
- 有时限的保证交付:数据报不仅到达,而且在某个最大时延内到达
可能的逐流服务:
- 按序交付:同一流中的数据报按发送顺序到达
- 保证最小带宽:为一条流保留或保证一定速率
- 保证最大抖动:限制相邻分组到达时间间隔的变化
因特网的网络层采用尽力而为服务(best-effort service):不保证带宽、不保证时延、不保证丢包率、不保证按序到达。它看起来很弱,但成功的原因是机制足够简单,便于大规模扩展;链路带宽不断提升,使很多实时应用在统计意义上可以工作;CDN 和复制服务把内容放到离用户更近的位置;端系统的拥塞控制也让弹性业务能够适应网络状态。
路由器工作原理
路由器体系结构
1 | +------------------------------------------------------------------+ |
- 输入端口:物理层功能(线路端接)→ 链路层功能(解封装)→ 查找转发表确定输出端口
- 交换结构:将分组从输入端口转移到输出端口
- 输出端口:缓存 → 链路层封装 → 物理层传输
- 路由选择处理器:执行路由选择协议,维护路由表和转发表(控制平面功能)
路由器内部也体现数据平面和控制平面的时间尺度差异:数据平面在硬件中逐分组处理,通常要求纳秒级完成查找和转发;控制平面负责路由计算、管理和状态维护,通常是毫秒级或更慢的软件过程。
输入端口处理与基于目的地的转发
使用最长前缀匹配(longest prefix matching)规则:在转发表中寻找与目的地址匹配的最长前缀
e.g.: 转发表
前缀 链路接口 11001000 00010111 00010 0 11001000 00010111 00011000 1 11001000 00010111 00011 2 其他 3 目的地址 11001000 00010111 00011000 10101010 匹配接口 1(最长匹配 24 位)
最长前缀匹配通常使用 TCAM(三态内容寻址存储器)在硬件中以纳秒级速度执行
输入端口通常采用分散式交换:每个输入端口自己完成物理层比特接收、链路层解封装、转发表查找、排队和提交给交换结构,而不是把每个分组都交给中央 CPU。TCAM 的特点是可以存储 0、1、通配符三种状态,能在一个时钟周期内并行比较所有表项,查找时间基本不随表项数增长;商用交换设备的 TCAM 可以支持约百万级转发表项。
交换结构
三种交换方式:
- 经内存交换:最早的路由器,由 CPU 直接控制,分组从输入端口复制到内存再从内存复制到输出端口,受限于内存带宽,一次只能转发一个分组
- 经总线交换:输入端口通过共享总线直接将分组传送到输出端口,不需要 CPU 干预,但总线一次只能传输一个分组(总线竞争),受限于总线带宽
- 经互联网络交换(crossbar):\(N\) 个输入端口和 \(N\) 个输出端口的 \(2N\) 条总线构成纵横式交换结构,可以并行转发多个分组(只要不同时到同一输出端口)
理想情况下,若路由器有 \(N\) 个输入端口,交换结构的交换速率应达到输入线路速率的 \(N\) 倍,这样所有端口同时到达的分组都能被及时搬运到输出侧。经内存交换需要把分组写入内存再读出内存,相当于每个分组经过内存两次;经总线交换减少了 CPU 干预,但仍会受到共享总线竞争限制;经互联网络交换可用 crossbar 或 Clos 网络扩展,常把可变长数据报切成固定长度 cell 通过多平面并行交换,再在输出侧重组。
输出端口排队
当交换结构的交付速率超过输出链路速率时,输出端口需要缓存
缓存溢出时必须丢弃分组:
- 弃尾(drop tail):丢弃新到达的分组
- 主动队列管理(AQM):在缓存满之前就开始丢弃/标记分组
- 随机早期检测(Random Early Detection, RED):根据平均队列长度以一定概率丢弃分组
缓存大小的经验法则:
\[B = RTT \cdot C / \sqrt{N}\]
其中 \(C\) 为链路容量,\(N\) 为 TCP 流数量
更早的经验法则来自 RFC 3439:\(B = RTT \cdot C\)。例如 RTT 为 250 ms、链路容量为 10 Gbps 时,缓存约为 2.5 Gbit。这个规则在高速链路上会导致非常大的队列,队列过大会增加排队时延,形成 bufferbloat,对实时应用和 TCP 的快速响应都不利。因此后来的经验法则把同时存在的 TCP 流数量 \(N\) 纳入考虑,用 \(RTT \cdot C / \sqrt{N}\) 估计所需缓存。
缓存管理策略不仅有弃尾,还可以按优先级丢弃低优先级分组,或者在真正丢弃前先通过 ECN/RED 对拥塞进行标记,让端系统提前降低发送速率。
输入端口排队
队头阻塞(Head-of-Line blocking, HOL blocking):输入队列前部的分组阻塞了同一队列中后面的分组(后面的分组要去的输出端口可能是空闲的)
分组调度
FIFO(先到先服务):最简单
优先权排队(priority queuing):分组被分为优先级类别,高优先级先发送,同优先级内 FIFO
加权公平排队(Weighted Fair Queuing, WFQ):每个类别有自己的队列,循环服务,但每个类别按权重获得不同比例的带宽
\[\text{类别 } i \text{ 的带宽份额} = \frac{w_i}{\sum_j w_j} \cdot R\]
轮询调度(Round Robin, RR):把分组按类别放入多个队列,调度器按固定顺序循环检查各队列,若当前类别队列非空就发送一个分组。WFQ 可以看作带权重的公平调度,不同类别按权重获得不同带宽份额。
分组调度和缓存管理也是网络中立性(network neutrality)争论的技术基础。技术上,ISP 必须决定不同业务、不同用户、不同应用在共享链路上如何排队、限速、丢弃或优先转发;社会和经济层面,这关系到言论、竞争和创新。美国 FCC 2015 年的开放互联网规则强调不阻塞、不降速、不付费优先,同时也把 ISP 作为 Title II 电信服务还是 Title I 信息服务来监管视为关键问题。
通用转发与匹配-动作
传统转发:仅基于目的 IP 地址查表转发(基于目的地的转发)
通用转发(generalized forwarding):基于多个首部字段的匹配,执行更丰富的动作
匹配-动作(match+action)范式:
- 匹配:可以匹配链路层(MAC 地址)、网络层(IP 地址、协议号)、传输层(端口号)等多个字段
- 动作:不仅限于转发,还可以丢弃、修改字段、发送到控制器、复制等
这是 SDN 和 OpenFlow 的核心思想,也是从传统路由器到可编程交换机的关键概念转变
通用转发使得单个设备可以同时实现路由器、交换机、防火墙、NAT 等多种功能
在 OpenFlow 一类模型中,流表项通常包含匹配字段、动作、计数器,还包含优先级和超时等控制信息。优先级用于处理多个规则同时匹配的情况,计数器记录命中的分组数和字节数,便于监控和控制器决策。
匹配-动作把多种设备功能统一成同一种抽象:
- 路由器:匹配目的 IP 最长前缀,转发到相应端口
- 交换机:匹配目的 MAC 地址,转发或泛洪
- 防火墙:匹配 IP 地址、协议号、TCP/UDP 端口,允许或丢弃
- NAT:匹配 IP 地址和端口号,重写地址和端口
这种抽象体现了网络可编程性:设备可以匹配不同层次首部中的比特,然后执行丢弃、转发、修改首部、复制、发送给控制器等本地动作。早期的主动网络已经提出过类似思想,现代数据平面可编程语言如 P4 则进一步把“匹配哪些字段、执行哪些动作”开放给程序员定义。
网际协议:IPv4
网络层功能存在于主机和路由器中。主机生成和接收 IP 数据报,路由器检查经过自己的每个 IP 数据报首部,并根据转发表把数据报从输入端口移动到输出端口。
IPv4 数据报格式
1 | 0 1 2 3 |
关键字段:
- 版本(4 bit):IPv4 = 4
- 首部长度(4 bit):以 4 字节为单位,无选项时为 5(即 20 字节)
- 服务类型 ToS(8 bit):包含 ECN(显式拥塞通知)的 2 位
- 总长度(16 bit):数据报总字节数(首部 + 数据),最大 65535 字节
- 标识、标志、片偏移:用于 IP 分片与重组
- 生存时间 TTL(8 bit):每经过一个路由器减 1,到 0 则丢弃(防止无限循环)
- 协议(8 bit):上层协议(TCP=6, UDP=17)
- 首部校验和(16 bit):仅对首部进行校验,每个路由器重新计算(因为 TTL 会变)
- 源/目的 IP 地址(各 32 bit)
IP 分片与重组
不同链路层协议有不同的最大传输单元(Maximum Transmission Unit, MTU)
当 IP 数据报大于输出链路的 MTU 时,路由器将数据报分片(fragmentation)
分片后的片在目的主机重组(而非中间路由器)
分片使用 IP 首部字段:
- 标识:同一数据报的所有片具有相同的标识
- 标志:MF(More Fragments)= 1 表示后面还有更多片
- 片偏移:该片在原始数据报中的位置,以 8 字节为单位
e.g.: 4000 字节数据报(20 字节首部 + 3980 字节数据),MTU = 1500 字节
片 总长度 标识 标志(MF) 片偏移 1 1500 x 1 0 2 1500 x 1 185 (\(=1480/8\)) 3 1040 x 0 370 (\(=2960/8\)) 每片数据 = MTU - 首部 = 1500 - 20 = 1480 字节(前两片)
第三片数据 = 3980 - 1480 - 1480 = 1020 字节
IPv4 编址
IP 地址:32 位标识符,用于标识主机/路由器接口
接口(interface):主机/路由器与物理链路之间的边界
IP 地址与接口关联(不是与主机/路由器关联)
IPv4 地址通常写成点分十进制形式,例如 223.1.1.1。需要注意的是,地址分配给接口:一台有多个网络接口的路由器会有多个 IP 地址,一台多宿主主机也可能有多个 IP 地址。
子网
子网(subnet):IP 地址具有相同前缀的接口集合,无需路由器介入即可互相通信
判断子网的一种直观方法:把主机和路由器上的接口“拔下来”,剩下的每个互连的网络孤岛就是一个子网。一个子网内部的接口拥有相同网络前缀,彼此通信不需要再经过其他路由器。
子网掩码:标识网络部分和主机部分的边界
CIDR(Classless Inter-Domain Routing,无类别域间路由选择):
地址格式 a.b.c.d/x,其中 \(x\) 为前缀长度(网络部分的位数)
e.g.:
200.23.16.0/23表示前 23 位为网络前缀
分类编址(已过时)
| 类别 | 前缀 | 网络位数 | 主机位数 | 地址范围 |
|---|---|---|---|---|
| A | 0 | 8 | 24 | 0.0.0.0 ~ 127.255.255.255 |
| B | 10 | 16 | 16 | 128.0.0.0 ~ 191.255.255.255 |
| C | 110 | 24 | 8 | 192.0.0.0 ~ 223.255.255.255 |
| D | 1110 | — | — | 224.0.0.0 ~ 239.255.255.255(多播) |
CIDR 取代了分类编址,实现更灵活的地址分配
e.g.: 子网划分与 CIDR
某组织获得地址块
200.23.16.0/20(共 \(2^{12} = 4096\) 个地址)将其分配给 8 个子网,每个子网需要 \(4096/8 = 512\) 个地址,需要 \(\lceil\log_2 512\rceil = 9\) 位主机号
子网前缀长度 = \(32 - 9 = 23\)
子网 地址块 地址范围 1 200.23.16.0/23 200.23.16.0 ~ 200.23.17.255 2 200.23.18.0/23 200.23.18.0 ~ 200.23.19.255 3 200.23.20.0/23 200.23.20.0 ~ 200.23.21.255 4 200.23.22.0/23 200.23.22.0 ~ 200.23.23.255 … … … 路由聚合(route aggregation):ISP 对外只通告一条
200.23.16.0/20,而不是 8 条 /23 的路由,减少路由表大小
层次化地址分配使路由聚合成为可能。一个 ISP 可以获得较大的前缀,再把其中更小的前缀分给下游组织。例如 ISP 对外通告 200.23.16.0/20,内部再分出多个 /23。如果组织 1 从原 ISP 迁移到另一个 ISP,新 ISP 可以额外通告更具体的 200.23.18.0/23,由于最长前缀匹配优先,这个组织的流量会被引向新 ISP。
e.g.: 判断两个 IP 是否在同一子网
地址 A =
192.168.1.100,地址 B =192.168.1.200,子网掩码255.255.255.192(即 /26)A 的网络地址:\(192.168.1.100\ \text{AND}\ 255.255.255.192 = 192.168.1.64\)
B 的网络地址:\(192.168.1.200\ \text{AND}\ 255.255.255.192 = 192.168.1.192\)
\(64 \ne 192\),所以 A 和 B 不在同一子网
特殊 IP 地址
255.255.255.255:广播地址127.0.0.0/8:回环地址(loopback)10.0.0.0/8、172.16.0.0/12、192.168.0.0/16:私有地址
如何获得 IP 地址
主机获得 IP 地址:通过 DHCP(动态主机配置协议)
组织获得 IP 地址块:从 ISP 获取
ISP 获得地址块:从 ICANN(互联网名称与数字地址分配机构)获取
实际分配是分层进行的:终端从本地网络的 DHCP 服务器获得地址,组织从接入 ISP 获得地址块,ISP 再从 ICANN 及区域互联网注册机构获得更大的地址块。ICANN 在 2011 年把最后一批 IPv4 地址块分配给区域注册机构,之后 IPv4 地址耗尽压力主要靠 NAT、地址回收和 IPv6 部署缓解。
DHCP
动态主机配置协议(Dynamic Host Configuration Protocol)
允许主机从 DHCP 服务器动态获取 IP 地址
“即插即用”:主机加入网络时自动获取 IP 地址
DHCP 服务器通常由接入路由器或本地网络中的专门服务器承担,为其连接的一个或多个子网分配地址。若客户端记得之前租用过的地址并希望继续使用,发现和提供阶段在某些场景下可以被省略或简化,但完整过程仍以 DORA 四步描述最清楚。
DHCP 还可以提供:
- 子网掩码
- 默认网关(第一跳路由器地址)
- DNS 服务器地址
- 网络前缀长度
DHCP 工作过程(DORA)
- DHCP 发现(DHCP Discover):客户广播
255.255.255.255,源0.0.0.0,端口 67 - DHCP 提供(DHCP Offer):DHCP 服务器广播响应,提供可用 IP 地址
- DHCP 请求(DHCP Request):客户广播请求使用某个提供的地址
- DHCP 确认(DHCP ACK):服务器确认
DHCP 运行在 UDP 之上(客户端口 68,服务器端口 67)
DHCP 报文逐层封装:DHCP 报文放在 UDP 中,UDP 放在 IP 数据报中,IP 数据报再放入链路层帧。新接入主机尚不知道自己的 IP 地址和 DHCP 服务器地址,因此最初常使用 IP 广播目的地址 255.255.255.255,以太网目的地址为 FF:FF:FF:FF:FF:FF。
e.g.: DHCP 完整交互过程
新主机加入子网
223.1.2.0/24,DHCP 服务器地址223.1.2.5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 客户 (MAC: 00:16:D3:23:68:8A) DHCP 服务器 (223.1.2.5)
| |
|--- DHCP Discover (广播) ------------------->|
| src: 0.0.0.0:68 |
| dst: 255.255.255.255:67 |
| Transaction ID: 654 |
| |
|<--- DHCP Offer (广播) ----------------------|
| yiaddr: 223.1.2.4 (提供的IP) |
| 租期: 3600 秒 |
| DNS: 223.1.2.2 |
| 默认网关: 223.1.2.1 |
| 子网掩码: 255.255.255.0 |
| Transaction ID: 654 |
| |
|--- DHCP Request (广播) -------------------->|
| 请求使用 223.1.2.4 |
| Transaction ID: 655 |
| |
|<--- DHCP ACK (广播) -----------------------|
| 确认 223.1.2.4 |
| Transaction ID: 655 |客户获得:IP 地址
223.1.2.4,子网掩码/24,默认网关223.1.2.1,DNS 服务器223.1.2.2
在抓包中,DHCP ACK 通常能看到消息类型 ACK、server identifier、subnet mask、router、DNS server、domain name 等字段。也就是说,DHCP 不只是“给一个 IP 地址”,还把主机接入网络所需的第一跳路由器、DNS、掩码等配置一起下发。
IP 地址有租期(lease time),到期需续约或释放
NAT
网络地址转换(Network Address Translation)
本地网络使用私有 IP 地址(如 10.0.0.0/8),对外共享一个(或少量)公有 IP 地址
NAT 路由器的行为:
- 外出数据报:将(源 IP, 源端口)替换为(NAT IP, 新端口),在 NAT 转换表中记录映射
- 进入数据报:根据 NAT 转换表,将(NAT IP, NAT 端口)替换为对应的(内部 IP, 内部端口)
16 位端口号字段可以支持同时约 60000 个连接
NAT 的实际好处:
- 内网大量设备对外只需要一个或少量 ISP 分配的公有 IP 地址
- 内部主机地址可以调整,而不需要通知外部网络
- 更换 ISP 时可以只改变 NAT 路由器的外部地址,内部地址规划不必整体修改
- 外部主机不能直接寻址内部设备,这在某些场景下也形成了额外的隔离效果
e.g.: NAT 转换表工作过程
内网主机 A(10.0.0.1)访问外网服务器 128.119.40.186:80
步骤 源 IP:端口 目的 IP:端口 说明 1 10.0.0.1:3345 128.119.40.186:80 A 发送请求(内网侧) 2 138.76.29.7:5001 128.119.40.186:80 NAT 替换源地址和端口(外网侧) 3 128.119.40.186:80 138.76.29.7:5001 服务器回复(外网侧) 4 128.119.40.186:80 10.0.0.1:3345 NAT 恢复目的地址和端口(内网侧) NAT 转换表:
NAT 侧 内网侧 138.76.29.7:5001 10.0.0.1:3345 138.76.29.7:5002 10.0.0.2:3345 即使两台内网主机使用相同的源端口 3345,NAT 也能通过分配不同的外部端口(5001、5002)来区分
NAT 的争议:
- 路由器只应处理到网络层(第三层),不应该修改端口号(第四层)
- 违反了端到端原则:外部主机无法直接发起到 NAT 内部主机的连接
- 地址短缺问题应该由 IPv6 解决
尽管存在争议,NAT 仍然广泛存在于家庭网络、校园/企业网络以及 4G/5G 移动网络中。它已经从临时缓解 IPv4 地址短缺的技术,变成了现实互联网路径上非常常见的中间盒功能。
NAT 穿越(NAT traversal)解决方案:
- 静态配置:手动配置 NAT 转发规则
- UPnP(Universal Plug and Play):自动配置端口映射
- 中继(relay):内外部主机都连接到一个中间的中继服务器
IPv6
动机
32 位 IPv4 地址空间即将耗尽
IPv6 的目标不只是扩大地址空间。固定 40 字节首部减少了路由器处理可变首部的复杂度;去掉首部校验和、把分片从路由器移到端系统,也有利于更快转发;流标签字段则为同一流的差异化处理预留了空间。
IPv6 数据报格式
1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
IPv6 与 IPv4 的主要区别:
| 特性 | IPv4 | IPv6 |
|---|---|---|
| 地址长度 | 32 bit | 128 bit |
| 首部长度 | 可变(20~60字节) | 固定 40 字节 |
| 分片 | 任何路由器 | 仅源主机 |
| 校验和 | 有 | 无(由上层处理) |
| 选项 | 在首部中 | 通过扩展首部实现 |
| ICMPv6 | — | 新增 “Packet Too Big” 报文 |
去掉首部校验和的原因:每一跳都要重新计算(因为 TTL/跳限制变化),处理开销大
不允许中间路由器分片:如果分组太大,路由器丢弃并发送 ICMPv6 “Packet Too Big” 报文
因此,IPv6 基本首部中没有 IPv4 的首部校验和、没有路由器分片与重组字段,也没有可变长选项字段。可选功能通过扩展首部表达,并由“下一个首部”字段把多个首部串起来。
中间盒
中间盒(middlebox):位于源和目的之间路径上的、执行非标准路由器/交换机功能的网络设备
RFC 3234 对中间盒的定义更严格:它是数据路径上的任何中间设备,并且执行了不同于普通 IP 路由器标准功能的处理。换言之,普通路由器只按 IP 转发表转发;只要设备还做了过滤、改写、缓存、检测、负载均衡等额外动作,就属于中间盒范畴。
常见中间盒:
- NAT 盒:地址转换(已讨论)
- 防火墙(firewall):基于规则过滤分组(匹配首部字段,决定允许或丢弃)
- 入侵检测系统(IDS)/入侵防御系统(IPS):深度分组检测,检测恶意流量
- 负载均衡器(load balancer):将请求分发到多个服务器
- 缓存/代理:缓存内容以减少延迟和带宽使用
中间盒几乎无处不在:NAT 出现在家庭、移动和机构网络中;防火墙和 IDS/IPS 出现在企业、校园、运营商和 ISP 网络中;负载均衡器出现在企业、云、数据中心和移动核心网中;缓存存在于运营商、移动网络和 CDN 中;还有许多按特定应用设计的中间盒。
中间盒引发的问题:
- 违反了因特网原来的端到端设计原则
- 使网络更难管理和调试
- 不同厂商的中间盒使用专有软件,难以创新
SDN 的方法:通过通用转发的匹配-动作在交换机上实现部分中间盒功能,减少专有设备
中间盒的实现也在演化:早期多是封闭、专有的硬件设备;后来出现基于白盒硬件和开放 API 的实现;再后来,NFV(Network Function Virtualization,网络功能虚拟化)把防火墙、负载均衡、NAT 等功能做成运行在通用计算、存储和网络资源上的可编程服务。
IPv4 到 IPv6 的过渡
隧道(tunneling):IPv6 数据报作为 IPv4 数据报的有效载荷被封装和传输
隧道本质上是“包中包”:IPv6 数据报被放进 IPv4 数据报的数据字段中,使只支持 IPv4 的网络也能转发这段路径上的流量。这类封装思想也常见于移动网络和运营商网络。
当 IPv6 数据报要经过 IPv4 路由器时:
- 隧道入口的 IPv6/IPv4 路由器将 IPv6 数据报封装在 IPv4 数据报中
- IPv4 路由器正常转发该 IPv4 数据报
- 隧道出口的 IPv6/IPv4 路由器解封装,提取出 IPv6 数据报继续转发
IPv6 部署不能通过某一天全网同时切换完成,因此长期处于 IPv4/IPv6 共存状态。PPT 中给出的统计例子显示,约 30% 的客户端通过 IPv6 访问 Google,约三分之一美国政府域名支持 IPv6;从 IPv6 标准化到较大规模部署已经超过 25 年,这与应用层协议和服务的快速迭代形成鲜明对比。
ICMP
因特网控制报文协议(Internet Control Message Protocol)
用于主机和路由器之间交换网络层信息:差错报告、回显请求/回答
ICMP 报文承载在 IP 数据报中(协议号 = 1),但被认为是网络层的一部分
常见 ICMP 报文类型:
| 类型 | 编码 | 描述 |
|---|---|---|
| 0 | 0 | 回显回答(ping reply) |
| 3 | 0 | 目的网络不可达 |
| 3 | 1 | 目的主机不可达 |
| 3 | 3 | 目的端口不可达 |
| 3 | 6 | 目的网络未知 |
| 3 | 7 | 目的主机未知 |
| 4 | 0 | 源抑制(拥塞控制,已弃用) |
| 8 | 0 | 回显请求(ping) |
| 11 | 0 | TTL 过期 |
Traceroute 的工作原理:
- 源发送一系列 UDP 数据报给目的地,第 \(n\) 组的 TTL = \(n\)
- 第 \(n\) 个路由器将 TTL 减到 0 时丢弃该数据报,返回 ICMP 报文(类型 11, 编码 0),携带路由器名字和 IP 地址
- 源记录从发送到收到 ICMP 回复的时间
- 当数据报到达目的主机时,目的端口号不匹配任何进程,目的主机返回 ICMP “端口不可达”(类型 3, 编码 3),源停止发送
路由选择算法
分类
- 全局式路由选择算法(链路状态算法,LS):所有路由器拥有完整的网络拓扑和链路代价信息
- 分散式路由选择算法(距离向量算法,DV):每个路由器只知道自己与邻居之间的链路代价,通过迭代与邻居交换信息
另一种分类:
- 静态路由选择:路由随时间变化缓慢,通常人工调整
- 动态路由选择:路由随网络流量负载或拓扑变化而变化
链路状态算法(LS)—— Dijkstra 算法
每个路由器通过链路状态广播(Link State Broadcast)获取整个网络的拓扑信息
然后运行 Dijkstra 算法计算从自己到所有其他节点的最短路径
1 | 初始化: |
时间复杂度:\(O(n^2)\)(朴素),\(O(n\log n + m)\)(优先队列)
e.g.:
步骤 \(N'\) \(D(v),p(v)\) \(D(w),p(w)\) \(D(x),p(x)\) \(D(y),p(y)\) \(D(z),p(z)\) 0 u 2,u 5,u 1,u \(\infty\) \(\infty\) 1 ux 2,u 4,x — 2,x \(\infty\) 2 uxy 2,u 3,y — — 4,y 3 uxyv — 3,y — — 4,y 4 uxyvw — — — — 4,y 5 uxyvwz — — — — —
LS 算法的问题:当链路代价等于流量负载时,可能出现路由振荡
距离向量算法(DV)—— Bellman-Ford 方程
核心思想(Bellman-Ford 方程):
\[d_x(y) = \min_v\{c(x,v) + d_v(y)\}\]
其中 \(v\) 遍历 \(x\) 的所有邻居
每个节点维护自己的距离向量 \(D_x = [D_x(y): y \in N]\)
算法过程:
- 每个节点将自己的距离向量发送给所有邻居
- 收到邻居的距离向量后,用 Bellman-Ford 方程更新自己的距离向量
- 如果距离向量发生变化,通知邻居
- 重复直到收敛
DV 算法的特点:
- 迭代:每次本地链路代价变化或收到邻居更新时触发
- 异步:不要求所有节点同步操作
- 分布式:每个节点只与直接邻居通信
无穷计数问题(Count-to-Infinity)
当链路代价增大时,DV 算法可能产生路由环路,代价逐步增加到无穷
e.g.: 三个节点 X-Y-Z,X-Y 的链路代价从 4 变为 60
Y 认为可以经 Z 到 X(代价 5+4=9),Z 又认为可以经 Y 到 X(代价 9+1=10)
两者不断互相更新,直到代价增长到超过 60 才收敛
解决方案:毒性逆转(poisoned reverse)
如果 Z 通过 Y 到达 X,则 Z 告诉 Y 自己到 X 的距离为 \(\infty\)(而不是实际值)
毒性逆转可以解决两个节点之间的环路,但无法解决涉及三个及以上节点的环路
e.g.: DV 算法的收敛过程
三个节点 X, Y, Z,链路代价:\(c(X,Y)=2\),\(c(Y,Z)=1\),\(c(X,Z)=7\)
初始(每个节点只知道直连链路代价):
节点 \(D(\cdot)\) 到 X \(D(\cdot)\) 到 Y \(D(\cdot)\) 到 Z X 0 2 7 Y 2 0 1 Z 7 1 0 第 1 轮(交换距离向量后更新):
X 收到 Y 和 Z 的距离向量: - \(D_X(Z) = \min\{c(X,Z), c(X,Y)+D_Y(Z)\} = \min\{7, 2+1\} = 3\)(经 Y)
Y 收到 X 和 Z 的距离向量: - \(D_Y(X) = \min\{c(Y,X), c(Y,Z)+D_Z(X)\} = \min\{2, 1+7\} = 2\)(直连,不变)
Z 收到 X 和 Y 的距离向量: - \(D_Z(X) = \min\{c(Z,X), c(Z,Y)+D_Y(X)\} = \min\{7, 1+2\} = 3\)(经 Y)
更新后:
节点 \(D(\cdot)\) 到 X \(D(\cdot)\) 到 Y \(D(\cdot)\) 到 Z X 0 2 3 Y 2 0 1 Z 3 1 0 第 2 轮:无变化,算法收敛
e.g.: 无穷计数问题的详细过程
沿用上面的拓扑,假设 \(c(X,Y)\) 从 2 变为 60
Y 检测到链路变化,重新计算: - \(D_Y(X) = \min\{c(Y,X), c(Y,Z)+D_Z(X)\} = \min\{60, 1+3\} = 4\)(经 Z)
但 Z 到 X 的路径是经 Y 的!Z 并不知道 Y 的路径已经变了
轮次 \(D_Y(X)\) \(D_Z(X)\) Y 的下一跳 Z 的下一跳 1 4 3 Z Y 2 4 5 Z Y 3 6 5 Z Y 4 6 7 Z Y … … … Z Y n 60 60 X(直连) Y 代价每轮增加 2,需要约 30 轮才能收敛到正确值——这就是”无穷计数”
LS 与 DV 比较
| LS | DV | |
|---|---|---|
| 信息复杂度 | 每个节点需要知道全局拓扑 | 只需知道邻居的距离向量 |
| 报文开销 | \(O(nE)\) 个报文 | 只在邻居间交换 |
| 收敛速度 | \(O(n^2)\),不振荡 | 可能慢(无穷计数问题) |
| 健壮性 | 节点只计算自己的表 | 一个节点的错误可能扩散 |
因特网中的路由选择
因特网过于庞大,不可能所有路由器运行同一种路由选择算法
自治系统(AS)
自治系统(Autonomous System):由同一组织管理的路由器集合
路由选择分为两层:
- 自治系统内部路由选择(intra-AS routing):AS 内部路由器之间
- 自治系统间路由选择(inter-AS routing):不同 AS 之间
OSPF
开放最短路径优先(Open Shortest Path First)
- 使用链路状态算法(Dijkstra)
- 每个路由器向 AS 内所有路由器广播链路状态信息(洪泛)
- 路由器构建完整的 AS 拓扑图
- OSPF 报文直接承载在 IP 数据报中(协议号 89)
OSPF 报文类型:
| 类型 | 名称 | 功能 |
|---|---|---|
| 1 | Hello | 发现和维护邻居关系 |
| 2 | Database Description | 向邻居描述自己的链路状态数据库 |
| 3 | Link-State Request | 请求特定的链路状态信息 |
| 4 | Link-State Update | 向邻居发送链路状态更新(核心报文) |
| 5 | Link-State Acknowledgment | 确认收到链路状态更新 |
OSPF 的高级特性:
- 安全:所有 OSPF 报文可以被鉴别(防止恶意入侵)
- 多条相同代价路径:允许使用多条路径(负载均衡)
- 支持单播和多播路由选择
- 支持层次结构:大型 AS 可以划分为多个区域(area),区域内部路由和区域间路由分开
OSPF 的层次结构:
- 骨干区域(area 0, backbone):所有区域边界路由器必须连接到骨干区域
- 区域边界路由器:汇总区域内路由信息并通告到其他区域
- AS 边界路由器:连接到其他 AS
RIP
路由信息协议(Routing Information Protocol)
- 使用距离向量算法
- 距离度量:跳数(hop count),每条链路代价为 1
- 最大跳数 15(16 表示不可达),适用于小型网络
- 每 30 秒交换一次路由信息(通过 UDP 端口 520 发送 RIP 通告)
- 如果 180 秒未收到邻居的通告,认为该邻居不可达
RIP 实现简单但扩展性差,适用于小型 AS;OSPF 适用于大型 AS
BGP
边界网关协议(Border Gateway Protocol)
BGP 是因特网的自治系统间路由选择协议,也是将因特网中数千个 ISP 粘合在一起的”胶水”
BGP 为每个 AS 提供:
- eBGP(external BGP):从邻居 AS 获取子网可达性信息
- iBGP(internal BGP):将可达性信息传播到 AS 内部所有路由器
- 基于可达性信息和策略确定到达其他网络的”好”路由
BGP 基本原理
- BGP 会话(BGP session):两个 BGP 路由器通过 TCP 连接(端口 179)交换路由信息
- 通告前缀的可达性:当 AS3 向 AS1 通告前缀 \(x\) 时,AS3 承诺自己可以将数据报转发到 \(x\)
BGP 报文类型:
| 报文 | 功能 |
|---|---|
| OPEN | 建立 BGP 对等关系,协商参数(AS 号、保持时间等) |
| UPDATE | 通告新路由或撤销之前的路由(包含路径属性和前缀) |
| KEEPALIVE | 保持连接活跃(周期性发送,通常每 30 秒) |
| NOTIFICATION | 报告差错或关闭连接 |
BGP 路由属性
BGP 通告的路由包含前缀 + 属性:
- AS-PATH:到达该前缀经过的 AS 序列(如 AS3 AS2 AS1)
- NEXT-HOP:到达下一个 AS 的具体路由器接口 IP 地址
BGP 路由选择
当有多条路由到达同一前缀时,按以下优先级选择:
- 本地偏好值(local preference,策略决定)
- 最短 AS-PATH
- 最近的 NEXT-HOP(热土豆路由选择)
- BGP 标识符
热土豆路由选择(hot potato routing):选择使得到达 NEXT-HOP 代价最小的路由,即尽快将分组送出本 AS
BGP 路由策略
- 客户-提供商关系:客户向提供商付费获取转接服务
- 对等关系:两个 AS 互相免费交换流量
策略规则:
- 来自客户的流量:转发到所有(提供商、对等方、其他客户)
- 来自提供商或对等方的流量:只转发给客户,不转发给其他提供商或对等方
e.g.: BGP 路由选择
AS1 中的路由器 1c 收到两条到达前缀
138.16.64.0/22的路由:
路由 AS-PATH NEXT-HOP 本地偏好 路由1 AS3 AS4 192.168.1.1(通往AS3) 80 路由2 AS2 AS4 10.0.0.1(通往AS2) 80 按 BGP 路由选择规则依次判断:
- 本地偏好:两者都是 80 → 平局
- 最短 AS-PATH:两者都经过 2 个 AS → 平局
- 最近的 NEXT-HOP(热土豆路由选择):假设路由器 1c 到 192.168.1.1 的 OSPF 代价为 5,到 10.0.0.1 的 OSPF 代价为 3 → 选择路由2(代价更小,尽快送出本 AS)
热土豆路由选择体现了”自私”的原则:每个 AS 都希望尽快将分组送出自己的网络,减少自身的转发负担
软件定义网络(SDN)
传统网络的控制平面分布在每个路由器中,难以管理和创新
SDN 的思想:将控制平面与数据平面分离
课堂上强调,SDN 的核心价值不只是“集中式控制”,而是网络可编程性。集中控制便于统一观察拓扑、计算路径和下发策略,但它不是所有场景下都天然优于分布式路由。因特网本身长期依赖去中心化协议扩展到全球规模;SDN 更适合数据中心、校园网、运营商骨干中的局部管理域,用来实现流量工程、访问控制和复杂策略。
从设计取向看,SDN 有点违背传统因特网“网络内部尽量简单”的直觉,但在有限域内很实用。它可以表达单纯目的地址转发难以表达的策略,例如让某类流量绕开拥塞链路、必须经过防火墙、或者按业务类型走不同路径。
SDN 架构
1 | +-----------------------------+ |
- SDN 控制器:维护网络状态信息,通过北向接口向应用提供 API,通过南向接口(如 OpenFlow)控制交换机
- SDN 交换机:根据控制器下发的流表(flow table)执行转发
SDN 控制器是逻辑集中,而不一定是一台物理机器。实际系统常由多个控制器实例组成集群,对外提供一个逻辑上的网络操作系统视图,以提高可靠性和扩展性。
SDN 控制器的三层架构:
- 通信层(南向接口):与交换机通信(OpenFlow、SNMP 等)
- 网络范围状态管理层:维护网络拓扑、主机信息、交换机流表等全局状态
- 网络控制应用接口(北向接口):向上层应用提供 API(如 REST API)
代表性 SDN 控制器:ONOS、OpenDaylight、Floodlight
OpenFlow
OpenFlow 是 SDN 中控制器与交换机之间的通信协议
控制器通过 OpenFlow 对交换机进行配置和编程:读取交换机能力和状态,添加、删除、修改流表项,处理未匹配分组和端口状态变化。随着版本演进,OpenFlow 支持的匹配字段和动作越来越多,协议本身也变得更复杂。
流表表项包含:
- 匹配字段:匹配 IP 地址、端口号、MAC 地址、VLAN 等
- 动作:转发到指定端口、丢弃、修改字段、发送到控制器等
- 计数器:匹配的分组数和字节数
流表项还会包含优先级、超时和统计信息。优先级决定多条规则同时匹配时使用哪条规则;统计信息帮助控制器了解流量规模;超时机制用于清理不再活跃的流。
OpenFlow 报文类型:
- 控制器到交换机:
features-request/reply:控制器查询交换机能力configuration:设置/查询交换机参数modify-state(flow-mod):添加/删除/修改流表表项packet-out:控制器让交换机从指定端口发送分组
- 交换机到控制器:
packet-in:交换机将无法匹配的分组发送给控制器flow-removed:通知控制器某条流表项被删除port-status:通知端口状态变化
OpenFlow 可以实现:
- 路由器功能:匹配最长前缀 IP 地址,转发到对应端口
- 交换机功能:匹配 MAC 地址,转发到对应端口
- 防火墙功能:匹配 IP 地址或端口号,丢弃
- NAT 功能:重写 IP 地址和端口号
e.g.: OpenFlow 流表实现不同功能
路由器(基于目的 IP 转发):
匹配 动作 IP dst = 51.6.0.8 转发到端口 6 IP dst = 51.6.0.0/16 转发到端口 2 交换机(基于 MAC 转发):
匹配 动作 MAC dst = 22:A7:23:11:E1:02 转发到端口 3 防火墙(过滤规则):
匹配 动作 IP src = 128.119.1.1, TCP dst port = 22 丢弃 IP dst = 10.0.0.0/8 丢弃 * 转发到端口 2 同一个 OpenFlow 交换机通过不同流表项同时充当路由器、交换机和防火墙
e.g.: SDN 中的链路故障处理
- 交换机检测到某端口或链路故障,通过 OpenFlow
port-status等事件通知控制器- 控制器更新网络拓扑图和链路状态数据库
- 路由或流量工程应用在新的网络图上重新计算路径
- 控制器向受影响交换机下发新的流表项,例如更新
s1、s2、s4上的转发规则- 后续分组按新路径转发,数据平面不需要每台交换机独立运行完整路由协议
这个过程体现了 SDN 的“网络操作系统”类比:控制器掌握全局状态,上层应用负责策略和路径计算,底层交换机执行匹配-动作规则。
IP 沙漏与端到端论证
因特网体系结构常用 IP 沙漏描述:上层有很多应用和传输协议,下层有很多链路层和物理层技术,但中间收束到统一的 IP。IP 是“细腰”,它让不同应用可以运行在不同底层网络之上,也让不同底层网络只要承载 IP 就能接入因特网。
后来沙漏中间逐渐变“胖”:NAT、防火墙、缓存、负载均衡、组播、各种中间盒和可编程网络设备把更多功能放回网络内部,所以也有人称之为 middle-aged hourglass。
RFC 1958 表达的设计原则可以概括为:目标是连通性,工具是因特网协议,智能应尽可能放在端系统,而不是隐藏在网络内部。对应三条核心信念:
- 简单连通性:网络层主要提供把分组送到目的地的基本能力
- IP 作为细腰:用统一、简单的网络层协议连接多样化上层和下层
- 复杂性在边缘:可靠传输、拥塞控制、应用语义等主要由端系统实现
端到端论证(end-to-end argument)认为,某些功能只有通信端点最了解需求,也只有端点才能完整正确地实现。例如可靠传输可以得到链路层或网络内部的帮助,但最终是否收到正确数据,仍必须由端系统确认;网络内部的机制可以提升性能,却不能完全替代端到端机制。
网络智能的位置也在变化:传统电话网把智能放在网络内部,终端很简单;早期因特网把网络做得简单,把智能放到端系统;2005 年后,数据中心、CDN、中间盒和可编程交换机又把一部分智能带回网络内部,但总体上仍要在可扩展性、可管理性和端到端语义之间取舍。
小结
网络层核心知识:
- 数据平面(转发)vs 控制平面(路由选择),通用转发的匹配-动作范式
- 路由器:输入端口(最长前缀匹配)、交换结构、输出端口(排队、调度)
- IPv4:数据报格式、分片与重组、CIDR 编址
- DHCP:动态获取 IP 地址(DORA 四步过程)
- NAT:私有地址到公有地址的转换;中间盒的概念
- IPv6:128 位地址、固定 40 字节首部、隧道过渡
- ICMP:差错报告和诊断(Traceroute 原理)
- 路由选择算法:LS(Dijkstra,全局)vs DV(Bellman-Ford,分布式)
- AS 内路由:RIP(距离向量,跳数)、OSPF(链路状态,层次结构)
- AS 间路由:BGP(路径向量,OPEN/UPDATE/KEEPALIVE/NOTIFICATION,策略驱动)
- SDN:控制平面集中化,OpenFlow 流表与报文类型,控制器三层架构