发明名称 Linux系统上以太网卡快速捕包的方法
摘要 本发明公开一种Linux系统上使用以太网卡快速捕包的方法,该方法是将以太网卡DMA接收缓存区映射到用户区,通过减少数据包到达用户区以及用户程序的拷贝次数和每个网卡启动一个线程捕包来实现同时对多网卡进行捕包,还通过关闭中断主动查询接收,减少中断处理调度开销,定义重复使用的缓存及其管理,减少缓存申请和释放的开销并减少捕包线程、包处理线程之间访问缓存的冲突,实现对以太网数据包包括在其上传输的ip包的快速的捕获。
申请公布号 CN101227341A 申请公布日期 2008.07.23
申请号 CN200710115379.0 申请日期 2007.12.18
申请人 浪潮电子信息产业股份有限公司 发明人 黄景昌;张会健;吴庆民;施培任
分类号 H04L12/26(2006.01);H04L12/56(2006.01);H04L12/02(2006.01) 主分类号 H04L12/26(2006.01)
代理机构 济南信达专利事务所有限公司 代理人 姜明
主权项 1.Linux系统上以太网卡快速捕包的方法,其特征在于,是将以太网卡DMA接收缓存区映射到用户区,通过减少数据包到达用户区以及用户程序的拷贝次数和每个网卡启动一个线程捕包来实现同时对多网卡进行捕包,还通过关闭中断主动查询接收,减少中断处理调度开销,定义重复使用的缓存及其管理,减少缓存申请和释放的开销并减少捕包线程和包处理线程之间访问缓存的冲突,实现对以太网数据包包括在其上传输的ip包的快速的捕获,方法步骤如下:(1)在以太网卡驱动中,在模块加载时注册一个混杂设备miscellaneous device,记为misc_dev,定义该设备的open,release,mmap,ioctl操作函数,其中mmap函数将用于将指定网卡的环形接收描述符缓存区和数据包接收缓存区映射给用户区的程序,ioctl函数用于为用户区程序提供移动指定网卡的环形接收描述符缓存区接收尾指针以使网卡能够持续收包的功能,相应的,在模块卸载时要注销该混杂设备;(2)在以太网卡驱动中,在模块加载时定义一个全局结构变量,记为g_map_dev,用于保存该系列的所有网卡设备的环形接收描述符个数及其缓存区虚拟地址、数据包接收缓存区的虚拟地址,在混杂设备misc_dev的mmap函数中使用该全局变量g_map_dev获取缓存区虚拟地址转换为物理地址并向用户区映射,相应的,在模块卸载时要释放该全局结构变量;(3)在以太网卡驱动中,使用pci_alloc_consistent函数分配接收描述符缓存区和数据包接收缓存区,这种方式使缓存区同时从网卡和CPU两个方向访问;这两个缓存区对于网卡直接内存访问Direct Memory Access方式传输的,同时把缓存区的虚拟地址保存到步骤(2)中说明的全局结构变量g_map_dev中,相应的,释放缓存区的时候,停止网卡或重置网卡使用pci_free_consistent函数;(4)在用户区,定义一系列链表结构的缓存区,以实现数据包缓存的重复使用和减少包处理线程之间取包时的锁冲突;缓存区分为两种组别:包接收缓存组和包处理缓存组,对于有N个网卡设备捕包和M个包处理缓存组的配置,将定义((2+M)×N+(4×M))个缓存区,即N个接收缓存组和M个包处理缓存组,每个接收缓存组包含2+M个缓存区,每个包处理缓存组包含4个缓存区,其中的每个缓存区是以链表结构组织,每个链表元素为一个固定大小的数据包缓存及其实际接收的数据包长度;每个接收缓存组由2个空闲缓存区组成的两级空闲缓存区和M个接收缓存区组成,空闲缓存区用于收集存放已处理过的释放的包缓存准备重复使用,接收缓存区用于存放接收的数据包,每个网卡接收的数据包按照均分方式或者按照数据包内容分为M类,投放到M个接收缓存区中;每个包处理缓存组由2个待处理缓存区组成的两级待处理缓存区、1个处理中缓存区、1个已处理缓存区组成;(5)在用户区,对每个捕包网卡启动一个线程捕包,称为捕包线程;(6)捕包及包缓存流通流程为:捕包程序向外提供pktcap_open,pktcap_close,pktcap_get_onepkt_block,pktcap_get_onepkt_noblock,pktcap_free_onepkt接口函数,对于N个捕包网卡、M个包处理缓存组和K个包缓存的配置,在pktcap_open函数中,首先申请K个包缓存,每个包缓存大于以太网包最大值,一般为1500,将K个包缓存平均分布在N个一级空闲缓存区中,然后启动N个捕包线程,每个线程将使用一个网卡和一个包接收缓存组,在每个捕包线程运行开始时,关闭所使用的网卡的中断,调用混杂设备misc_dev的mmap函数将对应网卡的DMA接收描述符缓存区和DMA包接收缓存区的物理地址映射到用户区,调用混杂设备的ioctl函数获取和设置网卡的接收状态,然后进入数据包查询接收循环;对于intel pro100和pro1000系列网卡,是获取DMA接收描述符首指针位置、设置DMA接收描述符尾指针位置;(7)首先查询当前DMA接收描述符的状态字,判断该包是否接收完成,1)若当前包没有接收完成,则睡眠一段时间,睡眠时间长短根据DMA接收描述符个数和网卡带宽而定,对于1000Mb带宽,4096个接收描述符的情况,为保证睡眠期间不会因为DMA接收缓存区满而丢包,睡眠时间t_sleep应小于以满带宽接收4096/2个最小包的时间,即t_sleep=(64x8x4096/2)/(10^9)=1048ms,其中64为以太网包的最小长度,单位字节;2)若当前包已接收完成,则将数据包复制接收到接收缓存区;首先判断一级空闲缓存区有无缓存,如果有则将网卡DMA接收缓存中数据包内容复制到一级空闲缓存区的第一个缓存,然后根据均分原则或者按照数据包内容对该包进行分类,均分原则是对于本网卡,每次将数据包到M个接收缓存区的1个,循环投放从第1个到第M个,而根据数据包内容分类的方法,对ip包的源地址、目的地址、源端口和目的端口进行hash运算再取M的模,得到序号index,0≤index≤M-1,再投放到第index+1个接收缓存区中,然后判断该接收缓存区的缓存个数,大于NUM_RECVED个则将该缓存区的数据包转移到第index+1个二级待处理缓存区,转移前后需要锁定和解锁二级待处理缓存区;若一级空闲缓存区无缓存,则将二级空闲缓存区锁定并将其缓存迁移到一级空闲缓存区再解锁;若从二级空闲缓存区获取的缓存个数小于等于NUM_FREEBUF_L2个则为了防止空闲缓存区迅速消耗完又继续查询二级缓存区形成频繁锁定二级缓存区的恶性循环,睡眠一段时间,时间的数量级要小于前述的t_sleep的,大概为1us-10us;睡眠结束后若一级空闲缓存区的缓存不为空,则复制、分类和投放数据包,否则不进行复制,即丢弃该包,但设置该包状态为已接收,重新循环收包;若从二级空闲缓存区获取的缓存个数大于NUM_FREEBUF_L2,则复制、分类和投放数据包,设置该包状态为已接收,重新循环收包。
地址 250014山东省济南市历下区山大路224号