netmap分析(4)-原理分析之驱动介绍

DMA Engine

在分析netmap驱动前,先简要了解一下DMA engine的原理。

下面是DMA Engine的大概示意图:


下面以接收为例,整个流程如下:

  1. 在System memory中为DMA开辟一端连续空间,用来BD数组 (一致性dma内存)BD是给DMA Engine使用的,所以不同的设备,BD结构不同,但是大致都有状态、长度、指针3个成员。

  2. 初始化BD数组,status为E,length为0。在System memory中再开辟一块一块的内存,可以不连续,用来存放以太网包将这些内存块的总线地址赋给buf(dma映射)

  3. 当MAC接收以太网数据流,放在了Rx FIFO中

  4. 当一个以太网包接收完全后,DMA engine依次做以下事情

    • fetch bd:开始一个个的遍历BD数组,直到当前BD状态为Empty为止
    • update bd:更新BD状态为Ready
    • move data:把数据从Rx FIFO中搬移到System Memory中dma映射的部分
    • generate interrupt:数据搬移完了,产生外部中断给cpu core
  5. cpu core处理外部中断,此时以太网数据已经在System memory中dma映射的部分了解除dma映射,更新bd状态为Empty再开辟一端内存,将这块内存的总线地址赋给bd的指针字段.

映射DMA内存

Netmap开辟了一段连续的内存空间,然后通过dma_ map_ single将该段内存映射为DMA内存来使用。通过DMA Engine介绍 可知,当网卡收到数据包后将存储在netmap开辟的内存空间中,当获得一个接收中断后,netmap会将当前这段内存解映射,然后再将缓冲队列中的下一个可用缓冲队列映射为DMA内存,如此循环。

数据接收

在驱动中,首先会映射相应内存池中的buffer 为DMA内存,然后调用selrecord(poll_wait)等待MAC接收数据.

MAC接收到数据后放入RX FIFO中,待接收完整个数据包,DMA engine将数据copy到对应的netmap内存池中,然后发出rx中断。该中断会进入netmap驱动的处理逻辑,此时,netmap会唤醒等待在此队列上的poll_wait.

数据发送

在驱动中, 会检测netmap的发送缓冲队列中是否有要发送的数据,如果有数据要发送,则会将数据报文存储的物理地址赋到DMA engine的BD数组的对应位置,进而通知NIC,发送数据。

内核到用户空间的内存映射

为了避免内核态和用户态之间的内存拷贝,netmap将内存池通过mmap映射到用户空间。同时,为了数据访问时,避免内核地址空间和用户地址空间的转换,netmap在各个数据结构中引用其他数据结构实例时均采用了地址偏移加索引的方式,该技术可以很容易定位各个数据结构实例同时性能也高。

Netmap对缓冲队列的安排

netmap驱动层针对一个网卡接口有n+1对缓存队列(具体几对缓存队列不同的网卡不一样的,比如千兆网卡只有一对缓存,则这里n = 1). 那么,第0到第n-1对缓冲队列用于接收来自网卡的数据及发送数据到网卡,第n对缓冲队列用于接收来自系统协议栈的数据以及发往系统协议栈的数据。

如果我们只关心和协议栈之间的交互,则设置:

req.nr_flags = NR_REG_SW;

如果我们只关心和网卡之间的交互,则设置:

req.nr_flags = NR_REG_ALL_NIC;

如果同时关注协议栈和网卡, 则设置:

req.nr_flags = NR_REG_NIC_SW;

如果要制定关注某个缓冲队列,则设置:

req.nr_flags = NR_REG_ONE_NIC; 

我们通过调用ioctl(fd, NIOCREGIF, &req)后获得了该接口上有多少个netmap ring 对:

req.nr_tx_rings 表示有多少个发送缓冲队列
req
.nr_rx_rings 表示有多少个接收缓冲队列

原创文章,版权归属yynote.com.转载请标明出处.

本文地址: http://yynote.com/blog/detail/networking/netmap-study-4-netmap-driver-introduction

你可能感兴趣的:(linux,kernel,netmap)