1.概述
最近调网卡驱动,调的身心俱疲,这里记录一下在调试过程中学习到的网卡驱动相关知识。这个系列文章只关注在SylixOS系统下要让网卡收发数据,需要做什么,会涉及到网络控制器的一些基本硬件知识、驱动和网络协议栈传递数据的方法等等,不会讲具体的一个网卡驱动代码,写这个系列文章的目的就是给网卡驱动初学者一个指南。如果你看完这个系列文章,明白了网卡在数据流上如何和SylixOS协议栈交互的,那么这篇文章就没有白写。好了,不多BB,让我们一起来揭开网卡的神秘面纱~
2. 网络数据收发
2.1 总览
首先来看下在一个系统中网络数据流大致是如何传递的,如下图:
- 在网络的世界中,数据的接收和发送都是以帧为单位的,也就是一帧数据一帧数据的传输,每帧数据的大小可能为几十个字节,也可能是几百字节。
- 发送的时候,数据经过两次拷贝由应用层复制到协议栈,再由协议栈复制到DMA缓冲区,然后设置网卡从DMA缓冲区中取数据发送。
- 接收的时候,当网卡收到一帧数据后,将数据保存在DMA缓冲区中,然后通知cpu从缓冲区中取数据处理。cpu将DMA缓冲区中的数据经过两次拷贝之后传送到应用程序。
- 上图是SylixOS中网卡驱动不使用零拷贝的数据流图。
2.2 缓冲区描述符
本小节关注网卡硬件上如何使用DMA缓冲区进行数据的收发。
网卡硬件上通过缓冲区描述符来使用DMA缓冲区,这里讲述一种常见的缓冲区描述符,如下图所示:
- 属性标明描述符的一些基本属性,比如描述符指向的缓冲区是否有有效数据,DMA传输完成后是否产生中断等等。
- 缓冲区地址指向用于存放收发数据的DMA缓冲区,一般都会有字节对齐的要求,比如地址要4字节对齐等等。
- 缓冲区大小用于标明DMA缓冲区中有效数据的大小,以字节为单位。
- 下一个描述符地址很好理解,就是下一个描述符的物理地址,一般初始化的时候会事先确定好有多少个缓冲区描述符,比如256个,然后将这些缓冲区描述符组成一个环链。
- 网卡硬件上收发各有一个环链。
3. 网络驱动和协议栈交互
3.1 概述
网络驱动和协议栈通过两个很重要的数据结构进行交互,struct netdev和struct pbuf。
一个网卡就对应着一个struct netdev,也就是说struct netdev是网卡硬件的抽象。netdev中有两个重要的方法,transmit和receive。当需要发送数据时,协议栈调用transmit方法通知驱动来进行数据发送,当网卡接收到数据时,系统通过receive方法接收数据并通知协议栈进行解析。如下图所示:
网络驱动和协议栈之间传递数据是通过struct pbuf来维护的,struct pbuf中有一个成员是保存帧数据所在的DMA缓冲区地址。也就是说一个pbuf就表示网络上的一帧数据,SylixOS网络协议栈初始化的时候会默认创建1024个pbuf。
3.2 网络任务处理线程
在SylixOS中,有两个线程是专门用来处理网络相关的任务的,分别是t_netjob和t_netproto,如下图所示。
在多核系统上,会看到有两个t_netjob线程,用于并发处理网络任务,前提是驱动要做好并发处理。
- 当网络收发数据完成产生中断后,可以将耗时的处理放入t_netjob中进行排队处理
- t_netproto是网络协议栈线程,专门用来处理网络协议相关的东西
评论