千兆网卡驱动实现机制浅析(4)

  根据接收队列数num_rx_queues建立相应的接收缓冲区结构e1000_rx_ring,在该结构中有描述该区域的指向e1000_rx_desc结构的desc,该缓冲区指向的dma总线地址,用于接收硬件传送来的用e1000_buffer结构描述的缓冲块数组buffer_info[],另外的几个参数则主要用于描述这些缓冲块,其中count表示缓冲块的个数,next_to_use和next_to_clean主要描述缓冲块的使用状态,如已经接收接收了数据的位置及准备接收的位置,当有新的数据包要到来时,则根据这两个参数找到相应的区域存放。对于需要分片接收的数据包则利用了ps_page和ps_page_dma来实现,参数cpu指定了该接收缓冲队列所属的处理器。总线地址与要发送的虚拟地址间的映射方向为PCI_DMA_FROMDEVICE,控制总线会把总线地址的内容映射到虚拟地址空间内。接收数据包的相关结构图及相互关系如图5-2所示。

  当有新的数据包到达时,首先触动中断处理函数e1000_intr(),在函数中会为新来的数据包在缓冲块数组buffer_info中找到一个新的缓冲块位置,并完成e1000_buffer结构的赋值。数据包的接收其实就是将总线地址指向的内容拷贝到skb中,然后根据skb中的协议将其传给相应的上层协议的接收函数。

  6. 网卡驱动程序的设计

  编写网卡驱动程序,需要对以下三类结构体进行相应的操作:

  1.与网络协议栈相关的结构体,如sk_buff结构体。

  2.网卡和协议栈接口相关的结构体,如net_device结构体。

  3.与I/O总线相关的结构体,如利用PCI总线进行数据包传送的DMA缓冲区以及表示网卡的pci_dev结构体。

  设计网卡驱动时,需要针对以上的数据结构实现相应的功能,如对sk_buff结构的操作实现对数据包的有效控制;对net_device结构的操作可以对网卡进行操作(如开启、关闭等),可以发送数据包以及轮询数据包,可以制定网卡的相应的定时操作以及统计数据包,可以为用户提供配置功能(ethtool)等。在设计网卡驱动时,需要考虑如何与上层协议的协调以及对底层总线地址的控制。

  有关网卡驱动程序更详细的设计流程可以参考《Essential Linux Device Driver》及《Linux Device Driver 3rd》。

  7. 总结

  本文的分析重点为网卡驱动中涉及到的重要数据结构,以及发送和接收数据包的实现,对这些实现机制了解后,对于设计和实现驱动程序应该会有帮助,因为该机制本身难度很大,加上作者水平有限,其中的分析结论不能保证完全正确。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzyyzz.html