Linux 网络--TCP协议收包流程(NAPI机制)

Linux 网络--TCP协议收包流程(NAPI机制)

平台环境简介
宿主机: ubuntu18.04
Linux内核源码版本: Linux-4.15
网卡驱动: Intel e1000 (ubuntu 虚拟机默认网卡驱动)
协议:TCP协议,本文分析收包过程

本文以 Linux4.15 内核版本对TCP协议的网络数据包接收处理过程进行分析。

NAPI机制引入
New API(NAPI)是 Linux 上采用的一种提高网络处理效率的技术,它的核心概念就是不采用中断的方式读取数据,而代之以首先采用中断唤醒数据接收的服务程序,然后 POLL 的方法来轮询数据。随着网络的接收速度的增加,NIC 触发的中断能做到不断减少,目前 NAPI 技术已经在网卡驱动层和网络层得到了广泛的应用,驱动层次上已经有 E1000 系列网卡,RTL8139 系列网卡,3c50X 系列等主流的网络适配器都采用了这个技术,而在网络层次上,NAPI 技术已经完全被应用到了著名的netif_rx 函数中间,并且提供了专门的 POLL 方法--process_backlog 来处理轮询的方法;根据实验数据表明采用NAPI技术可以大大改善短长度数据包接收的效率,减少中断触发的时间。

OSI七层模式和TCP/IP四层模型
进入正题前,我们先重温一下TCP/IP模型以及对应Linux系统的各部分功能。

数据包流转

函数调用流程 您粘贴的区域不支持图片插入。

1.系统调用

应用程序调用read()阻塞等待读取网络数据,通过sk_wait_data()进行阻塞,当有数据到来时,触发等待队列,调用skb_copy_datagram_msg()进行数据拷贝。具体函数调用流程如下所示:

=>read() 系统调用
=>vfs_read()
=>new_sync_read()
=>call_read_iter()
=>sock_recvmsg() 进入sock接收
=>sock_recvmsg_nosec()
=>inet_recvmsg()
=>tcp_recvmsg() 阻塞,进入tcp协议栈
 =>sk_wait_data() 等待数据到来
 =>skb_copy_datagram_msg() 数据来了拷贝

2.网卡中断处理函数

当网卡收到数据时,通过e1000网卡驱动绑定的 e1000_intr() 中断函数进行处理,因为e1000网卡支持NAPI机制,所以进入__napi_schedule()进行触发,将当前节点加入napi_poll链表并触发软中断进入 NAPI处理 。中断函数的调用流程如下所示:

=> irqreturn_t e1000_intr(int irq, void *data) 中断处理函数
=> __napi_schedule(&adapter->napi) 调度NAPI
=> ____napi_schedule() NAPI调度
  =>list_add_tail(&napi->poll_list,&sd->poll_list);添加到poll链表
  =>__raise_softirq_irqoff(NET_RX_SOFTIRQ); 触发软中断

3.NAPI处理

=> invoke_softirq() 软中断
=> __do_softirq()
=> net_rx_action()
=> napi_poll() 执行NAPI机制
=> e1000_clean()
=> e1000_clean_rx_irq()
=> e1000_copybreak() 拷贝数据
 =>e1000_alloc_rx_skb() 申请skb内存
 =>dma_sync_single_for_cpu() 同步DMA数据
 =>skb_put_data() 拷贝DMA数据到SKB
=> e1000_receive_skb()
=> napi_gro_receive()
=> napi_skb_finish()
=> netif_receive_skb_internal()
=> __netif_receive_skb()
=> __netif_receive_skb_core()

=> ip_rcv() 进入网络层
=> ip_rcv_finish()
=> dst_input()
=> ip_local_deliver()
=> ip_local_deliver_finish()
=> tcp_v4_rcv()
=> tcp_v4_do_rcv()
 => tcp_rcv_established()
 => sk_data_ready() 唤醒等待队列
=> tcp_add_backlog()
=> release_sock()唤醒

总结

注: 不同的Linux内核版本,可能函数名不太一样,但是总体流程是一样的,可参考进行分析。

通过对网络收包过程的梳理,让我们对Linux网络数据包的流转有一定的概念,在需要分析源码的时候能找到对应位置进行分析。

我是小C,欢迎大家一起交流学习,请关注、点赞、在看吧,不定期分享技术干活哦。

相关推荐

  1. 计算机网络 TCP协议流量控制

    2024-07-10 02:20:02       40 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 02:20:02       49 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 02:20:02       53 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 02:20:02       42 阅读
  4. Python语言-面向对象

    2024-07-10 02:20:02       53 阅读

热门阅读

  1. 特征的精粹:SKlearn中自动特征选择技术

    2024-07-10 02:20:02       21 阅读
  2. ADOQuery 查询MSSQL存储过程一个莫名其妙的错误;

    2024-07-10 02:20:02       19 阅读
  3. 「隐藏的宝藏」你不知道的各种API接口分类

    2024-07-10 02:20:02       18 阅读
  4. 数据结构第09节:二叉树

    2024-07-10 02:20:02       17 阅读
  5. 深入探讨数据结构:基础理论与应用实践

    2024-07-10 02:20:02       20 阅读
  6. liunx离线安装Firefox

    2024-07-10 02:20:02       22 阅读
  7. 百日筑基第九天-单元测试Junit、Log4j 、Log4j 2

    2024-07-10 02:20:02       19 阅读
  8. Bugly并非无所不能

    2024-07-10 02:20:02       21 阅读
  9. Linux 安装pdfjam (PDF文件尺寸调整)

    2024-07-10 02:20:02       17 阅读
  10. OpenStack是一个开源的云计算平台

    2024-07-10 02:20:02       15 阅读
  11. Vue 使用Audio或AudioContext播放本地音频

    2024-07-10 02:20:02       18 阅读
  12. Oracle PL/SQL Delete删除数据

    2024-07-10 02:20:02       19 阅读