博客
关于我
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/

    你可能感兴趣的文章
    NIFI大数据进阶_内嵌ZK模式集群1_搭建过程说明---大数据之Nifi工作笔记0015
    查看>>
    NIFI大数据进阶_外部ZK模式集群1_实际操作搭建NIFI外部ZK模式集群---大数据之Nifi工作笔记0017
    查看>>
    NIFI大数据进阶_离线同步MySql数据到HDFS_01_实际操作---大数据之Nifi工作笔记0029
    查看>>
    NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
    查看>>
    NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
    查看>>
    NIFI数据库同步_多表_特定表同时同步_实际操作_MySqlToMysql_可推广到其他数据库_Postgresql_Hbase_SqlServer等----大数据之Nifi工作笔记0053
    查看>>
    NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南001---大数据之Nifi工作笔记0068
    查看>>
    NIFI集群_内存溢出_CPU占用100%修复_GC overhead limit exceeded_NIFI: out of memory error ---大数据之Nifi工作笔记0017
    查看>>
    NIFI集群_队列Queue中数据无法清空_清除队列数据报错_无法删除queue_解决_集群中机器交替重启删除---大数据之Nifi工作笔记0061
    查看>>
    NIH发布包含10600张CT图像数据库 为AI算法测试铺路
    查看>>
    Nim教程【十二】
    查看>>
    Nim游戏
    查看>>
    NIO ByteBuffer实现原理
    查看>>
    Nio ByteBuffer组件读写指针切换原理与常用方法
    查看>>
    NIO Selector实现原理
    查看>>
    nio 中channel和buffer的基本使用
    查看>>
    NIO三大组件基础知识
    查看>>
    NIO与零拷贝和AIO
    查看>>
    NIO同步网络编程
    查看>>
    NIO基于UDP协议的网络编程
    查看>>