目录

  • 网卡的工作原理
    • 网卡初始化
    • 网卡的打开与关闭
    • 从网卡到内存
  • DMA与缓冲区
    • 地址转换
    • 缓冲区的使用方式
      • 一致性DMA映射
      • 流式DMA映射
    • 应用程序调用驱动程序分配缓冲区
    • 驱动分配缓冲区的方式
    • DMA shadow buffer两篇论文
  • 扩展到VM

网卡的工作原理

网卡工作原理
https://www.cnblogs.com/menghuanbiao/p/5212244.html

分析网卡的工作原理其实是分析网卡的驱动程序

网络是独立的一个模块。为了屏蔽网络环境中物理网络设备的多样性,Linux对所有的设备进行抽象并定义了一个统一的概念,称之为接口。所有对网络硬件的访问都是通过接口进行的,接口提供了一个对所有类型的硬件一致化的操作集合来处理基本数据发送和接收。一个网络接口被看作是一个发送和接收数据包的实体。对于每个网络接口,都用一个net_device的数据结构来表示。net_device中有很多提供系统访问和协议层调用的设备方法,包括提供设备初始化和往系统注册用的init函数,打开和关闭网络设备的open和stop函数,处理数据包发送的函数hard_start_xmit,以及中断处理函数。

所有被发送和接收的包都用数据结构sk_buff表示。要发送数据时,网络系统将分局系统路由表选择相应的网络接口进行数据传输;当接收数据包时,通过驱动程序登记的中断服务程序进行数据的接口处理。

网卡初始化

网络设备初始化主要工作时检测设备的存在、初始化描述设备的net_device结构及在系统中登记该设备。

初始化过程首先检测网络物理设备是否存在,这是通过检测物理设备的硬件特征来完成;然后对设备进行资源配置,这些完成之后就要构造设备的net_device数据结构,用检测到值对net_device中的变量初始化;最后Linux内核中注册该设备并申请内存空间

网卡的打开与关闭

为了使用网络设备,需要打开网卡,打开和关闭的一个接口是由shell命令ifconfig调用的,而ifconfig则要调用一个通用的设备打开函数dev_open(net/core/dev.c),相应的还有一个dev_close函数,这两个函数提供独立于设备的操作接口的打开和关闭功能。

一般打开函数执行的操作包括注册中断函数,分配并初始化网卡所需要的接收与发送缓冲区,启动硬件检查网络连接线状态等。

从网卡到内存

数据包的发送和接收是实现Linux网络驱动程序中两个最关键的过程。

中断与轮询

在轮询方式中,系统每隔一定的时间间隔就去检查一次物理设备,若设备有数据到达,就调用读取数据的程序。Linux中通过定时器实现,但是此法有一个明显的缺点:不管设备是否有数据,系统总是要固定的消耗CPU资源去查看设备,并且可能对一些紧急数据处理予以延迟。从资源的利用率以及工作的效率上看不是最优。

中断方式利用硬件体系结构的中断机制实现设备和系统的应答对话,即当物理设备需要CPU处理数据时,就向CPU发送一个终端信号,系统则在收到信号后调用相应的中断服务程序响应对设备中断的处理。**因此,基本在所有的网络设备驱动程序中都是用中断方式的。**网卡发送/接收数据,都必须以中断的方式告诉系统,系统处理中断后做出相应操作。

每一个网卡上都有一块FIFO存储器,对于NIC(Network Interface Controller),FIFO存储器是用来通过系统总线传送数据到系统存储器之前,缓存从LAN上接收到的数据。对与快速以太网还有一个直接内存存取(DMA:Directly Memory Access)控制器,用于提供对系统存储器的可靠访问。

驱动为网卡分配一个环形缓冲区,在一段连续的物理内存中实现。

  1. 数据接收
    (1) 接收的数据包,先暂存于片内FIFO接收队列;
    (2) 当接收器达到早期接收上限时就移至环形缓冲区
    (3) 待整个数据包全部从片上存储移至 环形缓冲区 后,将接收状态寄存器和包长度写入接收的数据包头部,并更新CBA(Current Buffer Address)寄存器的值;网卡将数据包通过DMA的方式写入到指定的内存地址,该地址由网卡驱动分配并初始化。
    (4) CMD(Command)寄存器中的BufferEmpty位和ISR(中断状态寄存器)寄存器的ROK位置1,并发出ROK的中断;
    (5) ISR中断调用完成后,清除ISR(ROK)并更新CAPR(Current Address of Packet Read,指向接收缓存的已读取包的地址),完成本次接收。
    以上是硬中断,网卡的数据传输部分完成,然后交由Linux软中断进行协议处理等。


2. 数据发送
(1) 将待传送的数据写入主存中一段连续的缓存空间,由OS配合驱动程序完成;
(2) 找到一个可用的描述符,并写入内容,包括该数据包的开始物理地址和传输状态字(包的大小、可传送下限、OWN位);
(3) OWN位有效,将数据从缓存移至片内FIFO队列;
(4) 当FIFO队列中的数据达到早期传送下限,NIC的传送单元就会启动,将数据顺序输出至线路;
(5) 当整个数据包都已经传至FIFO,OWN位置1;
(6) 当整个数据包都已经传至线路上, TOK寄存器置1;
(7) 当TOK(IMR)和TOK(ISR)都置为1,就发出TOK中断;
(8) TOK中断调用完成以后,清除TSD状态字,完成本次传送。

网卡上存在一定大小的FIFO存储器,DMA缓冲区是由系统/驱动程序分配的一段连续的物理内存。

Linux网络 - 数据包的接收过程
https://segmentfault.com/a/1190000008836467
网卡到内存(硬中断+DMA),软中断会触发内核网络模块中的软中断处理函数,一顿操作后将数据包交给协议栈处理,最终通过socket唤醒应用程序。

DMA与缓冲区

驱动程序调用dma_map函数分配DMA缓冲区

地址转换


在PCI设备枚举(初始化)过程中,内核了解了所有的IO device及其对应的MMIO地址空间(MMIO是物理地址空间的子集),也了解了是PCI主桥设备将这些PCI device和系统连接在一起。

PCI设备会有BAR(base address register),表示自己在PCI总线上的地址范围,CPU并不能通过总线地址A(位于BAR范围内)直接访问总线上的PCI设备,PCI host bridge会在MMIO(即物理地址)和总线地址之间进行mapping。
因此,对于CPU,它实际上是可以通过B地址(位于MMIO地址空间)访问PCI设备(反正PCI host bridge会进行翻译)。地址B的信息保存在struct resource变量中,并可以通过/proc/iomem开放给用户空间。

对于驱动程序,它往往是通过ioremap()把物理地址B映射成虚拟地址C,这时候,驱动程序就可以通过ioread32©来访问PCI总线上的地址A了。

如果PCI设备支持DMA,那么在驱动中可以通过kmalloc或者其他类似接口分配一个DMA buffer,并且返回了虚拟地址X,MMU将X地址映射成了物理地址Y,从而定位了DMA buffer在系统内存中的位置。因此,驱动可以通过访问地址X来操作DMA buffer,但是PCI 设备并不能通过X地址来访问DMA buffer,因为MMU对设备不可见,而且系统内存所在的系统总线和PCI总线属于不同的地址空间。

在一些简单的系统中(没有IOMMU),设备可以通过DMA直接访问物理地址Y,但是在大多数的系统中,使用IOMMU硬件block将DMA可访问的总线地址翻译成物理地址,也就是把上图中的地址Z翻译成Y。

驱动程序在调用dma_map_single这样的接口函数的时候会传递一个虚拟地址X,在这个函数中会设定IOMMU的页表,将地址X映射到Z,并且将返回z这个总线地址。驱动可以把Z这个总线地址设定到设备上的DMA相关的寄存器中。这样,当设备发起对地址Z开始的DMA操作的时候,IOMMU可以进行地址映射,并将DMA操作定位到Y地址开始的DMA buffer。

缓冲区的使用方式

分为 一致性DMA映射 与 流式DMA映射

一致性DMA映射

Consistent / coherent DMA mapping:持续使用该DMA buffer(不是一次性的),因此Consistent DMA总是在初始化的时候进行map,在shutdown的时候unmap。

网卡驱动和网卡DMA控制器往往是通过一些内存中的描述符(形成环或者链)进行交互,这些保存描述符的memory一般采用Consistent DMA mapping。

流式DMA映射

streaming DMA mapping:流式DMA映射是一次性的,一般是需要进行DMA传输的时候才进行mapping,一旦DMA传输完成,就立刻ummap(除非使用dma_sync_*的接口,下面会描述)。并且硬件可以为顺序化访问进行优化。
一般使用streaming DMA mapping的场景包括:
(1)网卡进行数据传输使用的DMA buffer
(2)文件系统中的各种数据buffer

应用程序调用驱动程序分配缓冲区

DMA控制器硬件结构与DMA通道使用的地址

所谓DMA可以使用任意的内存地址是因为:应用层通过malloc 获得的DMA缓冲区内存,无法知道他的物理地址是多少,而且可能不连续。
(但是DMA内存在物理上要连续。)

想知道的问题:这个DMA缓冲区地址区间在哪?是如何划分的?
https://blog.csdn.net/junwua/article/details/80942295

数据传输可以以两种方式触发:一种软件请求数据,另一种由硬件异步传输。

  1. 软件请求数据
    调用的步骤可以概括如下(以read为例):
    (1)在进程调用 read 时,驱动程序分配一个 DMA 缓冲区,随后指示硬件传送它的数据。进程进入睡眠。
    (2)硬件将数据写入 DMA 缓冲区并在完成时产生一个中断。
    (3)中断处理程序获得输入数据,应答中断,最后唤醒进程,该进程现在可以读取数据了。

  2. 由硬件异步传输
    在 DMA 被异步使用时发生的。以数据采集设备为例:
    (1)硬件发出中断来通知新的数据已经到达。
    (2)中断处理程序分配一个DMA缓冲区
    (3)外围设备将数据写入缓冲区,然后在完成时发出另一个中断。
    (4)处理程序利用DMA分发新的数据,唤醒任何相关进程。

网卡传输也是如此,网卡有一个循环缓冲区(通常叫做 DMA 环形缓冲区)建立在与处理器共享的内存中。每一个输入数据包被放置在环形缓冲区中下一个可用缓冲区,并且发出中断。然后驱动程序将网络数据包传给内核的其它部分处理,并在环形缓冲区中放置一个新的 DMA 缓冲区。

驱动分配缓冲区的方式

驱动可以通过系统接口(例如__get_free_page*())或者类似kmalloc() or kmem_cache_alloc()这样的通用内存分配的接口来分配DMA buffer,这些接口函数返回的虚拟地址可以直接用于DMA mapping接口API,并通过DMA操作在外设和dma buffer中交换数据。
不推荐使用kmap()和vmalloc()分配DMA buffer。

DMA shadow buffer两篇论文

重新理解:固定的是虚拟地址 最左边这一列

在IOMMU里固定好了映射
做的事情主要是VA(DMA缓冲区)的管理与分配了

扩展到VM

IOMMU里存的是全部GPA-HPA的映射

对于GuestOS:
在GuestOS内固定一块虚拟内存,专用做DMA缓冲区,防止DMA缓冲区乱窜。在IOMMU中固定好映射关系。

存疑:
1、guestos里面是否有IOMMU机制?
没有的话怎么绕过hypervisor访问物理iommu?
2、VM初始化的时候与IOMMU初始化的时候设置IOMMU页表
3、编程模型GVA-GPA,GuestOS内网络I/O的时候内存虚拟地址VA(DMA缓冲区)如何分配的问题

网卡-驱动-DMA API-TCP/IP相关推荐

  1. 协议 驱动 接口 服务器,TCP/IP 协议底层驱动原理 (含网卡芯片读写) 说明 [撸 swoole 和 workerman 的同学建议瞧瞧]...

    本文章简要的说明该协议的大概内容,具体请百度哦! 图片来源于德州仪器网卡芯片的 datasheet 修改过的 OSI 模型层图示[来源于德州仪器厂商的资料说明] TCP/IP 协议族[TCP/IP 族 ...

  2. rtems网络移植-实现网卡驱动

    经过两周的调试,终于初步实现网卡的发送功能. 在这里参考了uboot的beaglebone网卡驱动和<tcp/ip详解卷二> 1.在前几篇博文中,讲解了网卡的mdio初始化过程,那么网卡l ...

  3. AM3354 CPSW网卡驱动

    经过两周的调试,终于初步实现网卡的发送功能. 在这里参考了uboot的beaglebone网卡驱动和<tcp/ip详解卷二> 1.在前几篇博文中,讲解了网卡的mdio初始化过程,那么网卡l ...

  4. 走近TCP/IP协议

    转载,来自:[url]http://pfw.sky.net.cn/article/4695.html[/url] 走近TCP/IP协议 1.TCP/IP是什么? TCP/IP协议(Transmissi ...

  5. HTTP 协议 - 简单谈谈 TCP / IP (一)

    原文连接 blog TCP / IP 基本概念 世界上几乎所有的 HTTP 协议都是由 TCP / IP 协议来承载的.它是互联网相关的各类协议族的总称(通常所说的规则,就是协议). 从输入的 URL ...

  6. Linux 网卡驱动学习(六)(应用层、tcp 层、ip 层、设备层和驱动层作用解析)

    本文将介绍网络连接建立的过程.收发包流程,以及其中应用层.tcp层.ip层.设备层和驱动层各层发挥的作用. 1.应用层 对于使用socket进行网络连接的服务器端程序,我们会先调用socket函数创建 ...

  7. 【技术分享篇】从网卡到tcpip协议栈,再到应用程序丨tcp/ip网络编程丨网络api的实现原理丨sk_buff的作用

     从网卡 聊到tcp/ip协议栈,再到应用程序 1. posix tcp/ip网络编程 2. 网络api的实现原理 3. sk_buff的作用 [技术分享篇]面试中从网卡 聊到tcpip协议栈,再到应 ...

  8. server2008网卡驱动包_从网卡发送数据再谈TCP/IP协议—网络传输速度计算-网卡构造...

    在<在深谈TCP/IP三步握手&四步挥手原理及衍生问题-长文解剖IP>里面提到 单个TCP包每次打包1448字节的数据进行发送(以太网Ethernet最大的数据帧是1518字节,以 ...

  9. STM32F103驱动SDIO wifi Marvell8801/Marvell88w8801 介绍(十) ---- 移植TCP/IP协议栈LWIP

    代码工程的GITHUB连接:点进进入GITHUB仓库 https://github.com/sj15712795029/stm32f1_marvell88w8801_marvell8801_wifi ...

  10. Linux内核协议栈分析之网卡初始化——tcp/ip通信并不神秘(1)

    写在代码前: 写技术类文章的一个痛苦之处在于--写简单了,看的人觉得没意思:写难了,又看不懂是什么意思.例如--<redis源代码分析--事件机制>http://blog.csdn.net ...

最新文章

  1. 四百元值不值——论小米2A与2S
  2. LR分析法从理解到运用
  3. IDEA2021全局配置maven
  4. 利用序列化与反序列化对Java对象进行深度复制
  5. python中and和or的惰性求值特点_惰性求值和yield-Python
  6. 在.NetCore中使用Myrmec检测文件真实格式
  7. Codeforces Round #667 (Div. 3)
  8. 什么鬼?弃用JDK动态代理,Spring5 默认使用 CGLIB 了?
  9. 面试题:二叉树中和为某一路径
  10. idea 关闭检查更新_Intellij idea的抑制警告(SuppressWarnings)列表(正在持续更新)
  11. 和大家分享一款使用PHP+MYSQL搭建在线教育系统源码
  12. 3ds max 2012 VRay 2.0-3ds max 效果图设计与制作-HDRI贴图的应用
  13. qqxml图片代码_PCQQ - 发送自定义的XML卡片消息
  14. 集成建行聚合支付踩过的坑,有些槽不吐不快
  15. 服务器被黑客入侵了怎么办?
  16. matlab 获取文件毫秒时间,在Matlab中经过的时间,以毫秒为单位,具有不同的日期...
  17. idea spring boot 修改 html,js 等不用重启即时生效
  18. finalshell连接超时怎么办
  19. [7 kyu] Exes and Ohs
  20. 为何excel中数据无法计算机,Excel中数字无法正常求和怎么办?

热门文章

  1. Oracle项目管理系统P6 EPPM企业级规划方案
  2. 浅谈敏捷思想-05.精益画布电梯演讲
  3. 手机版qq邮箱一直连接服务器失败,手机qq邮箱网页版无法登录 求高手 QQ邮箱登不上去 显示找不到服务器15?请问我咋用不...
  4. 计算机一级怎么发送邮件到别人邮箱,电脑怎样发邮件到指定的邮箱地址(小白必须电脑操作邮件收发)...
  5. 松下机器人找原点步骤_松下机器人操作规程
  6. 360路由器v2刷第三方固件_斐讯K2P MTK版简单几步刷入breed教程,附刷第三方固件方法...
  7. gmssl编程之签发X509证书
  8. 无线网络信号测试软件WirelessMon 免费赠送
  9. 用c语言编程计算水力学习题,Anderson 计算流体力学入门 学习小结-一些感想
  10. 计算机电路与电子学试卷,电路与电子学(第5版)学习指导与习题解答