3.2 Linux 系统收包流程

本节,我们了解数据包进入网卡(eth0)后,Linux 内核中各个模块是如何相互协作的,对 Linux 系统下网络包的接收过程有个全局性的认识。

Linux 系统收包流程,如图 3-1 所示。


图 3-1 Linux 系统收包流程

  1. 外部数据包到达主机时,首先由网卡 eth0 接收。
  2. 网卡通过 DMA(Direct Memory Access,直接内存访问)技术,将数据包拷贝到内核中的 RingBuffer(环形缓冲区)等待 CPU 处理。RingBuffer 是一种首尾相接的环形数据结构,它作为缓冲区,缓解网卡接收数据的速度快于 CPU 处理数据的速度问题。
  3. 接着,网卡产生 IRQ(Interrupt Request,硬件中断),通知内核有新的数据包到达。
  4. 内核调用中断处理函数,标记新数据到达。接着,唤醒 ksoftirqd 内核线程,执行软中断(SoftIRQ)处理。
  5. 软中断处理中,内核调用网卡驱动的 NAPI(New API)poll 接口,从 RingBuffer 中提取数据包,并转换为 skb(Socket Buffer)格式。skb 网络子系统中用于描述网络数据包的核心数据结构。数据包的发送、接收还是转发,内核都会通过 skb 来处理。
  6. skb 被传递到内核协议栈,在多个网络层次间处理:
    • 网络层(L3 Network layer):根据主机中的路由表,判断数据包路由到哪一个网络接口(Network Interface)。这里的网络接口可能是稍后介绍的虚拟设备,也可能是物理网卡 eth0 接口。
    • 传输层(L4 Transport layer):处理网络地址转换(NAT)、连接跟踪(conntrack)等。
  7. 内核协议栈处理完成后,数据包被传递到 socket 接收缓冲区。应用程序利用系统调用(如 Socket API)从缓冲区读取数据。至此,整个收包过程结束。

分析 Linux 系统处理网络数据包的过程,我们注意到潜在问题:数据包的处理流程过于冗长。处理流程涉及到多个网络层协议栈(如数据链路层、网络层、传输层和应用层),网络层协议栈之间需要封包/解包,还有频繁的上下文切换(Context Switch),都让 Linux 内核的瓶颈不可忽视。对于设计网络密集型系统,优化内核参数是不可或缺的一环。

除了想办法优化内核参数,业界提出了“绕过内核”的技术思路,如图 3-1 所示的 XDP 和 DPDK 技术,笔者将在 3.4 节中详细介绍它们的原理与区别。

接下来,我们将继续深入 Linux 内核网络模块,研究 Linux 内核是如何过滤、修改和转发数据的。

总字数:714
Last Updated:
Contributors: isno