博客
关于我
The journey of a packet through the linux 2.4network stack
阅读量:120 次
发布时间:2019-02-26

本文共 2175 字,大约阅读时间需要 7 分钟。

数据包在 Linux 2.4 内核中的传递过程

作者:Harald Welte

日期:2000/10/14 20:27:43

翻译:yunyuaner


2. 接收数据包

2.1 接收中断

当网卡接收到一个与自身硬件地址匹配的或链路层广播的以太网帧时,它会触发一个中断。网卡设备驱动程序负责处理这个中断,通过 DMA/PIO 等方式将数据拷贝到内存中。接着,它申请一个 skb 结构并调用与设备无关的函数 net/core/dev.c:netif_rx(skb)

如果驱动程序未标记时间戳,该函数负责标记时间戳。然后,skb 被添加到适当的队列中进行处理。如果队列已满,数据包会被丢弃。当 skb 被加入接收队列后,接收软件中断会被标记,并在未来某个时间被执行,执行的函数为 include/linux/interrupt.h:__cpu_raise_softirq()。中断处理例程结束后,中断会被重新启用。


2.2 网络接收软件中断

从 2.2 版本以来,序列化底半部被性能优越的软件中断系统取代,传递过程也发生了重大变化。软件中断的最大优点是可以同时在多个 CPU 上执行,而底半部则只能在一个 CPU 上运行。

软件中断的注册位于 net/core/dev.c:net_init()kernel/softirq.c:open_softirq(),后者由软件中断子系统提供。进一步处理数据包的工作由网络接收软件中断(NET_RX_SOFTIRQ)执行,调用函数为 kernel/softirq.c:do_softirq()。这个函数有三个调用点:

  • arch/i386/kernel/irq.c:do_IRQ(),这是通用的 IRQ 处理例程。
  • arch/i386/kernel/entry.S,内核从系统调用返回时调用此处。
  • kernel/sched.c:schedule(),在主进程调度函数中调用。
  • do_softirq() 检测到 NET_RX_SOFTIRQ 被标记时,它会调用 net/core/dev.c:net_rx_action()。在 net_rx_action() 函数中,skb 从接收队列中卸载并分发给适当的数据包处理例程。这里讨论的是 IPv4 数据包,它会被分发给 net/ipv4/ip_input.c:ip_rcv()


    3. IP 数据包处理例程

    3.1 数据包注册

    IP 数据包在 net/core/dev.c:dev_add_pack() 中完成注册。该函数被 net/ipv4/ip_output.c:ip_init() 调用以完成任务。

    3.2 数据包处理

    Linux 内核网络协议栈中,负责处理 IPv4 数据包的函数为 net/ipv4/ip_input.c:ip_rcv()。在初始化检验(如数据包是否针对该主机等)后,IP 检验和被计算出来。其余检验(如数据包长度、协议版本号等)也已完成。

    如果数据包通过了有效性检验,它会被丢弃。如果通过检验,数据包的大小被计算,用于传输介质的无效填充字段被截去。


    4. 数据包路由到其他设备

    如果路由程序决定数据包需要路由到另一台设备,函数 net/ipv4/ip_forward.c:ip_forward() 会被调用。该函数的第一步是检查数据包首部的 TTL。如果 TTL 小于等于 1,则直接丢弃数据包并返回一个 ICMP 超时报文给发送者。

    接下来,检查 skb 的尾空间是否有足够的空间存放目标设备的数据链路层首部。如果没有,skb 进行扩充。然后,TTL 被减 1。如果新数据包的大小大于目标设备的 MTU 且 IP 首部的不分片字段被设置,数据包会被丢弃并返回一个 ICMP 错误报文给发送者。

    最后,调用 netfilter 钩子函数,这里使用的是 NF_IP_FORWARD 钩子。假设 netfilter 钩子函数返回 NF_ACCEPT,则会调用 net/ipv4/ip_forward.c:ip_forward_finish()。该函数检测是否设置了 IP 选项,并用专门的 ip_optFIXME 处理。接着,它调用 include/net/ip.h:ip_send()。如果需要分片,则调用 ip_fragment();否则,继续调用 net/ipv4/ip_forward:ip_finish_output()


    5. 数据包路由到其他设备(续)

    ip_finish_output() 中,函数调用 netfilter NF_IP_POST_ROUTING 钩子,并将接下来的工作交给 ip_finish_output2()。该函数将数据链路层首部添加到 skb 中,然后调用 net/ipv4/ip_output.c:ip_output()

    ip_output() 函数负责将数据包发送到目标设备。它会根据需要分片,并调用相应的函数。如果需要分片,调用 ip_fragment();否则,继续调用 ip_finish_output()


    以上描述了 Linux 2.4.x 内核中 IP 数据包的传递过程。由于从 2.2 版本以来,序列化底半部被性能优越的软件中断系统取代,整个传递过程也随之发生了大的变化。

    转载地址:http://yxdf.baihongyu.com/

    你可能感兴趣的文章
    OpenCV与AI深度学习 | 实战 | 使用YoloV8实例分割识别猪的姿态(含数据集)
    查看>>
    OpenCV与AI深度学习 | 实战 | 使用姿态估计算法构建简单的健身训练辅助应用程序
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于OpenCV和K-Means聚类实现颜色分割(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于YoloV5和Mask RCNN实现汽车表面划痕检测(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于YOLOv9+SAM实现动态目标检测和分割(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于YOLOv9和OpenCV实现车辆跟踪计数(步骤 + 源码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 文本图片去水印--同时保持文本原始色彩(附源码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 通过微调SegFormer改进车道检测效果(数据集 + 源码)
    查看>>
    OpenCV与AI深度学习 | 实战—使用YOLOv8图像分割实现路面坑洞检测(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战篇——基于YOLOv8和OpenCV实现车速检测(详细步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战|OpenCV实时弯道检测(详细步骤+源码)
    查看>>
    OpenCV与AI深度学习 | 实用技巧 | 使用OpenCV进行模糊检测
    查看>>
    OpenCV与AI深度学习 | 实践教程|旋转目标检测模型-TensorRT 部署(C++)
    查看>>
    OpenCV与AI深度学习 | 工业缺陷检测中数据标注需要注意的几个事项
    查看>>
    OpenCV与AI深度学习 | 干货 | 深度学习模型训练和部署的基本步骤
    查看>>
    OpenCV与AI深度学习 | 手把手教你用Python和OpenCV搭建一个半自动标注工具(详细步骤 + 源码)
    查看>>
    OpenCV与AI深度学习 | 水下检测+扩散模型:或成明年CVPR最大惊喜!
    查看>>
    OpenCV与AI深度学习 | 深入浅出了解OCR识别票据原理
    查看>>
    OpenCV与AI深度学习 | 深度学习检测小目标常用方法
    查看>>
    OpenCV与AI深度学习 | 超越YOLOv10/11、RT-DETRv2/3!中科大D-FINE重新定义边界框回归任务
    查看>>