当你在手机上打开一个网页,应用层会产生请求,传输层会把请求装进报文段,而网络层要解决一个更基础也更宏大的问题:怎样把数据报从源主机一跳一跳送到目的主机。沿途的每台路由器都必须在极短时间内判断“该从哪个出口发走”,还要处理突发流量、地址变化、协议演进和各种网络功能。
这一部分我们把视角放进数据平面内部。我们会从转发与路由的分工出发,拆开一台路由器,观察输入端口、交换结构、输出队列与调度器怎样协作;随后读懂 IPv4 数据报、子网与 CIDR、DHCP、NAT 和 IPv6;最后把“查目的地址”推广为“匹配多个字段并执行动作”,理解软件定义网络和中间盒为什么改变了网络核心。

网络层位于传输层和链路层之间。发送主机把 TCP 报文段或 UDP 数据报作为载荷,封装进 IP 数据报;每经过一段链路,数据报会被装入适合该链路的帧;到达路由器后,链路层封装被拆开,路由器检查网络层首部、选择输出接口,再用下一段链路的帧重新封装。目的主机最终取出 IP 载荷,依据协议字段交给相应传输协议。
因此,网络层提供的是主机到主机的逻辑通信。它与传输层的边界可以这样理解:IP 地址指出目标主机或接口,端口号指出主机中的目标进程;路由器通常关心前者,端系统的传输层负责后者。
这两个词常被混用,但时间尺度和职责完全不同。
传统路由器既运行控制平面协议,又执行数据平面转发。各路由器交换拓扑或可达性信息,独立计算转发表,再把适合高速查询的副本放在线卡上。软件定义网络则把控制逻辑放到逻辑集中的控制器中,由控制器计算规则并下发给交换设备。无论采用哪种组织方式,数据平面都必须在包到达时立即执行已经安装好的规则,而不是为每个包重新计算全网路径。
网络层可以设想提供很多服务,例如保证交付、保证最大时延、保证有序、为一条流预留最低带宽,或者限制相邻数据报的时间间隔。互联网的 IP 层选择了更简单的尽力而为服务:网络会尝试交付,但不保证数据报一定到达、不保证到达顺序、不保证带宽,也不给出端到端时延上界。
“没有保证”并不等于“随便处理”。路由器仍会高速转发,控制平面仍会寻找可达路径,链路层与传输层也可以补充差错检测、重传和拥塞控制。尽力而为的关键是:这些结果不是 IP 层对单个数据报作出的硬承诺。
一条连接看起来端到端连续,实际上每一跳都可能使用不同链路技术。IP 提供统一的数据报格式和地址语义,把异构链路拼成一个可互联的网络。
一台通用路由器可以分为四部分:输入端口、交换结构、输出端口和路由处理器。前三者位于高速转发路径上,通常由硬件完成关键操作;路由处理器运行控制协议、管理表项和设备状态,处理速度要求相对没那么极端。

输入端口首先完成物理层和链路层处理,从收到的信号中恢复帧,检查链路层信息并取出 IP 数据报。随后,它依据数据报首部查询转发表。为避免每个包都跨设备访问中央处理器,线卡通常保存一份可快速查询的转发表副本。
目的地址转发采用最长前缀匹配。设转发表有以下规则:
目的地址 10.12.7.9 同时匹配前三条,但 /24 固定的前导位最多、范围最具体,所以走接口 3。默认路由 /0 能匹配任何地址,却只在没有更具体表项时使用。高速设备常借助三态内容寻址存储器或专用树结构并行比较前缀,让一次查找尽量接近固定时间。
输入端口的动作并不限于查目的地址。设备还可能检查版本号和首部长度、递减 TTL、更新 IPv4 首部校验和、执行访问控制、统计计数,或为数据报标记服务类别。不过复杂处理必须受硬件流水线和时延预算约束。
交换结构负责把包从输入端口搬到目标输出端口。它的性能通常用交换速率衡量。若有 N 个输入端口,每个线速为 R,理想交换结构至少应接近 N × R,这样所有输入同时满速到达时也不会因为内部搬运能力不足而排队。
互连结构也会发生竞争:若多个输入同一时刻都要去同一个输出,最终仍只能按输出链路能力发送。现代设备可能把大包切成内部固定长度单元,经过多级互连后再重组,以减少某个大包长期占用内部资源。
“最长前缀”比较的是匹配前导位的数量,不是地址数值大小,也不是表项出现顺序。更具体的前缀应覆盖更宽泛的聚合前缀。
交换结构和链路都不是无限快的。只要短时间内到达某处的总速率超过它的服务速率,包就会排队;缓存满后,新到包或已排队包会被丢弃。排队并非异常,而是统计复用网络吸收突发流量的正常机制,真正的问题是队列应该多大、先服务谁、拥塞时丢谁。

当交换结构速度低于输入总到达速率,输入端口会积压。即使交换结构本身足够快,也可能出现队头阻塞:某输入队列最前面的包正等待一个繁忙输出,它身后的包虽然要去空闲输出,却不能越过队头,于是也被迫等待。
例如输入 A 的队列依次是“去输出 1、去输出 2”,输入 B 的队头也去输出 1。一次只能有一个包进入输出 1;A 若暂时没获准发送,它后面的输出 2 数据报也无法利用本轮交换机会。虚拟输出队列会按目标输出拆分输入缓存,可缓解这种阻塞,但调度逻辑更复杂。
当多个输入同时把包送到同一个输出,而输出链路每个时隙只能发送一个包,输出端就会排队。设输出链路速率为 R,若一个短突发中有 N 个输入各送来一个包,瞬时到达速率可接近 N × R。即使长期平均流量没有超过链路,突发也会形成队列。
缓存太小会频繁丢包,太大却可能产生缓冲膨胀:队列长期很深,吞吐量看似不错,但交互流量要等待大量旧包,时延和抖动显著上升。更合理的设备会结合链路速率、往返时延和并发流数量估算缓存,并使用主动队列管理,在队列彻底塞满前通过随机丢弃或显式拥塞通知向端系统发出拥塞信号。
常见丢弃策略包括:
输出链路每次只能发送有限数量的数据,因此调度器决定下一个包来自哪个队列。
若三个持续有包的队列权重为 1:2:3,理想情况下它们长期获得的服务份额分别约为 1/6、2/6、3/6。权重表达的是长期份额;某个队列为空时,闲置份额通常可被其他队列利用。
IPv4 数据报由首部和载荷组成。没有选项时,首部通常为 20 字节;TCP 首部也常为 20 字节,因此一个普通 TCP 数据段在装入链路层之前,往往已经有至少 40 字节的网络与传输层开销。

TTL 的初衷是限制数据报寿命,实际按跳数递减。若路由暂时形成环路,TTL 会逐跳耗尽,避免包永久循环。丢弃方通常返回 ICMP “超时”消息;traceroute 正是逐步增大 TTL,利用不同路由器返回的超时消息观察路径。
ICMP 是网络层的诊断与差错报告协议。常见消息有回显请求/应答、目的不可达、TTL 超时和首部参数问题。它不会把 IP 变成可靠服务:ICMP 消息本身也可能丢失,而且并非每次丢包都一定返回通知。
不同链路允许承载的最大网络层数据报大小不同,这个上限叫 MTU。若 IPv4 数据报大于下一跳 MTU,且未设置“不分片”标志,路由器可以把它拆成多个片。各片都拥有自己的 IPv4 首部,共享同一标识值;“更多分片”标志说明后面还有片,片偏移以 8 字节为单位指出该片数据在原数据报中的位置。

假设一个总长 4000 字节、首部 20 字节的数据报要经过 MTU 为 1500 字节的链路。每片最多承载 1480 字节且 1480 可被 8 整除:
重组只在最终目的主机进行,路由器不沿途重组。只要一个分片丢失,原始数据报就无法完整恢复,传输层往往要重传更大范围的数据。因此现代网络倾向于路径 MTU 发现,让源主机一开始就发送不会在途中被分片的包;IPv6 更进一步,不允许中间路由器执行这类分片。
IPv4 地址不是抽象地“贴在一台设备上”,而是分配给设备与链路相连的接口。普通主机常有无线、以太网等多个接口,路由器更是至少连接两条链路,因此一台设备可以拥有多个 IP 地址。

子网是一组无需经过路由器就能相互到达的接口。识别拓扑中的子网时,可以先把路由器接口之间的连接“剪开”,每个剩余的独立网络区域就是一个子网。点到点路由器链路同样构成子网,并不只有挂着许多主机的局域网才算。
CIDR 使用 a.b.c.d/x 表示一个前缀,x 是网络前缀长度,剩余 32-x 位用于区分该范围内的接口。例如 192.0.2.0/24 固定前 24 位,包含从 192.0.2.0 到 192.0.2.255 的 256 个地址。实际可直接分配给主机的数量还要考虑网络用途、广播地址和运营策略。
子网掩码是前缀长度的另一种写法,/24 对应 255.255.255.0。判断地址是否在子网中,本质上是把地址与掩码按位与,再与网络地址比较。
CIDR 允许服务提供商把一批连续网络聚合成一个较短前缀对外通告。假设多个客户前缀都位于 200.23.16.0/20 内,上游只需发布这一条聚合路由,远端路由表便不必保存每个客户的小前缀。
若其中 200.23.18.0/23 迁移到另一家提供商,新提供商可以单独发布这个更具体前缀。互联网其他路由器同时看到 /20 聚合和 /23 例外时,会依据最长前缀匹配把该范围流量交给新提供商,其余地址仍走原聚合路径。由此可见,层次化地址减少表项,而最长前缀匹配为例外情况保留灵活性。
固定服务器和路由器接口可以由管理员手工配置,但终端设备通常使用 DHCP 自动获得地址。一次典型过程可记为 DORA:
初始阶段客户端不知道服务器地址,也不确定自己所在子网,因此广播很重要。若服务器不在同一广播域,路由器上的 DHCP 中继可以接收本地广播并把请求转交远端服务器。
DHCP 分配的是有期限的租约。客户端通常在租期尚未过半时尝试续租;移动到另一个网络后,旧地址通常不能继续使用。DHCP 不仅分配 IP,也可下发第一跳路由器、DNS、网络掩码等关键参数。
地址分配还存在另一个尺度:DHCP 解决“组织内部某台主机用哪个地址”,组织本身的公网前缀则通常来自上游服务提供商。服务提供商持有一段较大的连续地址块,再把较长前缀切给客户;区域互联网注册管理机构负责在更大范围内协调地址资源。这样的层级分配不仅避免重复,也使地址与拓扑尽量对应,从而支持路由聚合。
DHCP 报文使用 UDP。客户端初次接入时尚无可用 IP,发现与请求阶段常以 0.0.0.0 为源、受限广播地址为目的,并使用约定的客户端/服务器端口。服务器在 Offer 中会携带事务标识,客户端用它把回复对应到自己的请求。客户端选择一个 Offer 后仍广播 Request,是为了让同一网络中的所有候选服务器都知道:哪台服务器的方案被接受,其他预留可以回收。
CIDR 同时服务两个目标:在子网内部划分地址范围,在路由系统中聚合可达性。前缀规划越连续,越容易减少全网路由表规模。
许多家庭和企业内网使用私有 IPv4 地址,例如 10.0.0.0/8、172.16.0.0/12 与 192.168.0.0/16。这些地址可在不同组织中重复使用,公网路由器不会把它们当作全球可达前缀传播。位于网络边界的 NAT 设备把内部地址和端口改写为公网地址和外部端口,使多台主机共享少量公网地址。
假设内网主机 10.0.0.2:51514 访问外部服务器。NAT 可能建立如下映射:
内网侧:10.0.0.2:51514
公网侧:198.51.100.10:40001出站时,NAT 把源地址和源端口改为 198.51.100.10:40001,并重新计算 IP 与传输层校验信息。服务器回包到这个公网地址和端口后,NAT 查询转换表,把目的端点还原为 10.0.0.2:51514。另一台内网主机可以共享同一公网 IP,只要分配不同外部端口。
NAT 表是有状态的。映射通常包含协议、内外地址与端口,并设置超时;TCP 映射还可以依据连接状态回收。若外部主动向一个没有表项的端口发包,NAT 不知道应交给哪台内网主机,通常会丢弃。端口转发、打洞、中继或应用层网关等机制都是在弥补这种入站可达性问题。
NAT 延缓了 IPv4 公网地址消耗,让内网更换上游时无需重编号所有主机,也在一定程度上隐藏了内部地址结构。但它打破了“网络核心只看网络层首部”和“任意端点可直接寻址另一个端点”的理想模型:
NAT 不等于防火墙。NAT 的核心职责是地址和端口转换;是否允许某类流量,应由明确的访问控制与安全策略决定。不要把“暂时没有入站映射”当成完整安全边界。
IPv6 把地址从 32 位扩展到 128 位。扩大地址空间是最直观的变化,但协议也重新整理了基本首部,让路由器高频处理的字段保持固定位置,把少见功能移入扩展首部。

IPv6 基本首部固定为 40 字节,关键字段包括:
IPv6 基本首部取消了首部校验和,避免路由器因每跳修改跳数限制而重算;需要完整性检查的工作交给链路层和传输层。选项通过扩展首部串联,不让每个路由器都解析不常见字段。中间路由器不负责分片;若包过大,通常通过 ICMPv6 “包太大”反馈促使源端调整大小。
IPv6 地址常写成 8 组十六进制数,每组 16 位。每组前导 0 可省略,连续的全零组可用一次 :: 压缩。例如 2001:0db8:0000:0000:0000:0000:0000:0021 可写为 2001:db8::21。同一地址中 :: 只能出现一次,否则无法判断省略了多少组。
互联网无法在某个时刻让全部设备同时切换,因此迁移依靠渐进部署:
隧道入口为原始 IPv6 数据报添加 IPv4 首部,IPv4 网络只把它当普通载荷转发;隧道出口移除外层首部,恢复 IPv6 转发。这样能跨越旧网络,但会增加额外首部、MTU 处理和运维复杂度。
IPv6 不是“自动更快”的开关。性能仍取决于路由、链路、拥塞、实现与对端服务。它的长期价值在于充足地址、简化基本首部以及更直接的端到端编址空间。
传统目的地址转发可以概括为“匹配目的 IP 前缀,然后选择输出端口”。现代数据平面把它推广为匹配加动作:在链路层、网络层和传输层的多个字段上匹配,再执行转发、丢弃、改写、复制、计数或送往控制器等动作。这种统一抽象让交换、路由、访问控制和流量工程能够使用相似的规则表达。

一条规则通常包含三部分:匹配字段、动作和统计计数器。可匹配字段可能包括入口端口、MAC 地址、以太网类型、VLAN、IPv4/IPv6 地址、协议号以及 TCP/UDP 端口。字段可以精确匹配,也可以通配或前缀匹配;当多条规则都命中时,由优先级决定采用哪条。
匹配:入口=1,目的前缀=10.8.0.0/16,TCP 目的端口=443
动作:转发到端口 4,同时增加计数器流表通常还包含包计数、字节计数和规则持续时间。这些统计让控制器观察流量、发现热点并调整策略。若没有规则命中,设备可以丢包,也可以把首包或首部摘要送给控制器,由控制器决定是否安装新规则。
常见动作包括:
例如,一组规则可以让来自某端口、发往某服务器的流量绕过故障链路;另一组规则可以把访客网络访问内部数据库的包直接丢弃。负载均衡还可依据源地址或五元组把不同连接分配到不同后端,保证同一连接的包持续落到同一服务器。
广义转发并不意味着每个包都询问控制器。控制器负责计算并下发规则,交换设备在本地以硬件速度匹配。只有未命中、异常或策略指定的包才可能触发控制器参与。
早期开放流表接口主要规定了一组可匹配字段和动作,让控制器能跨厂商配置交换设备。进一步的可编程数据平面允许运营者描述:设备应该解析哪些首部、流水线各阶段保存哪些表、表项可执行哪些动作,以及最终如何封装。P4 一类语言表达的正是这种协议无关处理模型。
不过,数据平面程序与普通服务器程序不同。包处理必须在极短时间内完成,硬件流水线的级数、表容量、每阶段可读写字段和状态内存都有限。实际部署时,控制器会向表中填入具体规则,而数据平面程序定义“有哪些表以及怎样执行”。前者像运行时配置,后者像设备的处理骨架。
中间盒是执行普通 IP 转发之外功能的网络设备或功能实例,包括 NAT、防火墙、入侵检测与防御、负载均衡、WAN 优化、代理和缓存等。它们会检查更多首部甚至应用数据,有些还会修改报文或维护连接状态。
中间盒带来实际价值:安全策略可以在网络边界统一实施,负载均衡可把请求分散到服务集群,NAT 可共享 IPv4 地址,缓存与压缩能减少跨广域链路流量。但代价也很明显:
网络功能虚拟化把防火墙、负载均衡等功能从专用硬件迁移到通用计算平台,以软件实例组成服务链;可编程数据平面则允许在受约束的流水线内定义新的解析和处理逻辑。二者都提高了部署速度,但也要求严格管理性能隔离、状态一致性和规则安全。
一份数据报进入路由器后,可能经历如下过程:输入端口恢复帧并解析首部;转发流水线用最长前缀或多字段规则匹配;TTL 或跳数限制更新;ACL、NAT 或其他中间盒功能执行;交换结构把包搬到目标输出;输出端依据队列策略安排发送;下一条链路重新封装。控制平面则在更慢的时间尺度上维护这些规则。
这条流水线解释了网络层数据平面的核心矛盾:它既要保持足够简单,才能以线速处理海量包;又要足够可编程,才能承载地址演进、安全、测量、流量工程和服务质量。理解每个机制位于哪一层、维护什么状态、在哪个时间尺度工作,就能把看似零散的概念连成一个完整系统。
数据平面可编程不等于没有边界。规则越复杂,越需要验证优先级、环路、黑洞、状态容量和故障切换,否则一条错误的高优先级规则就可能影响大量流量。