Linux系统上以太网卡快速捕包的方法

文档序号:7655029阅读:238来源:国知局
专利名称:Linux系统上以太网卡快速捕包的方法
技术领域
本发明涉及计算机通信领域,具体涉及一种Linux系统上以太网卡快速捕包的方法。2、 技术背景目前局域网应用十分广泛,以太网是局域网的一种,也是局域网的主流方式。在以太网上 可传输ip包实现和tcp/ip互联网的连接。而在网络管理、网络检测中,需要对传输的网络数 据包进行捕获,进而分析网络流量、对指定源地址和目的地址的通信进行监控和入侵检测等。 为了提高监控速度等性能,需要对数据包完全或者尽可能完全的捕获。在Linux系统上,传统的以太网卡驱动和内核的网络处理栈受到以太网卡中断调度、数据 包在内核中和由内核向用户区复制次数过多的影响,收包速度还不十分理想。目前Linux系统 上的链路包通用的捕获方式是通过PK一SOCKET类型的套接字(socket)进行数据包接收的,它 是在Linux协议栈的底层的netif—receive—skb函数中将刚收自网卡的链路包复制一份,而使 用该类型的套接字接收数据到用户区时还需要复制一次。此外目前Linux系统内核的网络协议 栈兼顾速度和普遍通用性,它接收网卡设备数据包的一些方式,影响了对网卡设备进行捕包速 度,具体表现在(1) 非NAPI方式是完全由网卡中断触发对数据包的接收,在高频率来包时网卡中断处理 调度需要较大的cpu资源消耗。(2) NAPI方式结合网卡中断触发和主动查询接收,虽然大大减少了中断调度次数,但是每 次轮询有固定时间(1个系统时钟周期腿丝)限制,超出该时间值将结束接收,这样难以保证 轮询结束后不丢包。(3) 无论是非NAPI方式还是NAPI方式,对于每一个接收到DMA接收缓存区的数据包,都 需要申请缓存空间,不能重复使用,而申请和释放缓存空间虽然由系统高效的内存管理模块完 成,但其计算量也不可忽视。(4) 无论是非NAPI方式还是NAPI方式,接收到的数据包缓存队列长度十分有限,当数据 包处理速度不均匀时很容易缓存区满而丢包,而如果在用户区增加扩大缓存,还需要做一次拷 贝。由于Linux系统的传统捕包方式在速度、性能上的局限性,需要一种更快更优的捕包方法。 3、发明内容为了提高使用以太网卡捕包的收包率和性能,本发明提供了一种应用在Linux系统上的以太网卡快速捕包的方法。本发明提供的以太网卡快速捕包方法的步骤为-(1) 在以太网卡驱动中,在模块加载时注册一个混杂设备(m/'sce//aA7eous ofev/'ce),记为misc—dev,定义该设备的open, release,腿ap, ioctl操作函数,其中醒ap函数将用于将指定 网卡的环形接收描述符缓存区和数据包接收缓存区映射给用户区的程序,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)xN + (4 x 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个包缓存的配置,在pkt cap—open函数中,首先申请K 个包缓存,每个包缓存大于以太网包最大值(一般为1500)即可,将K个包缓存平均分布在N 个一级空闲缓存区中。然后启动N个捕包线程,每个线程将使用一个网卡和一个包接收缓存组。 在每个捕包线程运行开始时,关闭所使用的网卡的中断,调用混杂设备misc—dev的mmap函数 将对应网卡的DMA接收描述符缓存区和DMA包接收缓存区的物理地址映射到用户区,调用混杂 设备的ioctl函数获取和设置网卡的接收状态(对于intel prol00和prol000系列网卡,是获 取DMA接收描述符首指针位置、设置DMA接收描述符尾指针位置),然后进入数据包査询接收 循环(7)首先査询当前DMA接收描述符的状态字,判断该包是否接收完成,[l]若否则睡眠一 段时间,睡眠时间长短根据DMA接收描述符个数和网卡带宽而定,对于1000Mb带宽,4096个接 收描述符的情况,为保证睡眠期间不会因为DMA接收缓存区满而丢包,睡眠时间t—slc印应小 于以满带宽接收4096/2个最小包的时间,即t—sle印:(64x8x4096/2)/ (10,1048ins,其中 64为以太网包的最小长度,单位字节。[2]若当前包己接收完成,则将数据包复制接收到接收缓 存区。首先判断一级空闲缓存区有无缓存,[2. l]有则将网卡DMA接收缓存中数据包内容复制到 一级空闲缓存区的第一个缓存,然后根据均分原则或者按照数据包内容对该包进行分类,均分 原则是对于本网卡,每次将数据包到M个接收缓存区的1个,循环投放从第1个到第M个,而 根据数据包内容分类的方法,可以对ip包的源地址、目的地址、源端口和目的端口等进行hash 运算再取M的模,得到序号index, 0《index《M-1,再投放到第index+l个接收缓存区中。然 后判断该接收缓存区的缓存个数,大于MM—RECVED个则将该缓存区的数据包转移到第index+l 个二级待处理缓存区,转移前后需要锁定和解锁二级待处理缓存区。[2.2]若一级空闲缓存区无 缓存,则将二级空闲缓存区锁定并将其缓存迁移到一级空闲缓存区再解锁,[2.2.1]若从二级空 闲.缓存区获取的缓存个数小于等于NUM一FREEBUF—L2 (NUM—FREEBUF—L2为(T数十)个则为了防止 空闲缓存区迅速消耗完又继续査询二级缓存区形成频繁锁定二级缓存区的恶性循环,睡眠一段 时间,时间的数量级要小于前述的t—sle印的,大概为lufl0us。睡眠结束后若一级空闲缓存 区的缓存不为空,则复制、分类和投放数据包,否则不进行复制,即丢弃该包,但设置该包状 态为己接收,重新循环收包。[2. 2. 2]若从二级空闲缓存区获取的缓存个数大于NUM—FREEBUF一L2, 则复制、分类和投放数据包,设置该包状态为已接收,重新循环收包。上述为捕包线程的收包流程,所使用的用户区数据包缓存的输入为二级空闲缓存区,输出 为一级待处理缓存区。而数据包从二级待处理缓存区流通到二级空闲缓存区的流程是每个包处理线程调用pktcap—get—onepkt_block或者pktcap—get—onepkt_noblock接.口函 数获取一个数据包,调用pktcap—free—on印kt释放数据包。其中pktcap—get—onepkt一block函数为阻塞式获取,当有数据包可用时将立即返回,否则将利用Linux线程的条件变量 pthread—cond—wait等待,直到有捕包线程将已接收数据包从接收缓存区转移到二级待处理缓存 区并设置条件变量环形处理线程。pktcap_get—on印kt一noblock接口函数为非阻塞式获取,有数 据包则返回数据包指针,否则立即返回空指针。每个包处理缓存组虽然可以给多个包处理线程 使用,但是为了减少线程并发锁定缓存区而提高效率,最好只由一个包处理线程使用。pktcap—get—onepkt—block或者pktcap—get一o卿kt—noblock接口函数将使数据包缓存将 从一级待处理缓存区转移到处理中缓存区。首先判断一级待处理缓存区是否为空,若不为空, 则将一个数据包从一级待处理缓存区转移到处理中缓存区,然后将该数据包地址以指针方式返 回。若一级待处理缓存区为空,则锁定二级待处理缓存区并将其数据包转移到一级缓存区再解 锁,然后从一级待处理缓存区取一个数据包转移到处理中缓存区并返回该数据包指针。包处理线程处理完某个数据包后将使用pktcap—free—on印kt接口函数释放数据包,在函数 参数中传递该数据包的指针。pktcap—free—on印kt接口函数将使数据包缓存从处理中缓存区转 移到—级空闲缓存区。首先锁定处理中缓存区,将数据包从处理中缓存区中脱离,然后解锁处 理中缓存区,锁定已处理缓存区,将数据包转移到已处理缓存区,然后判断已处理缓存区中数 据包缓存个数是否大于NUM—MIN—FREE,大于则锁定二级空闲缓存区,将己处理缓存区中所有数据 包缓存转移到二级空闲缓存区再解锁这两个缓存区并返回,否则解锁已处理缓存区并返回。本发明的有益效果是,将以太网卡DMA接收缓存区映射到用户区,减少数据包到达用户区 以及用户程序的拷贝次数;每个网卡启动一个线程捕包可实现同时对多网卡进行捕包;关闭中 断主动查询接收,减少中断处理调度开销;定义重复使用的缓存及其管理,减少缓存申请和释 放的开销,减少捕包线程、包处理线程之间使用缓存的锁冲突频率及其造成的系统资源消耗和 效率下降,实现对以太网数据包包括在其上传输的ip包的快速的捕获。4

图1为本发明的快速捕包程序结构示意图; 图2为本发明的包接收缓存组部分的缓存转移流图; 图3为本发明的包处理缓存组部分的缓存转移流图; 图4为本发明的捕包线程流程图。
具体实施方式
本发明提供的一种以太网卡快速捕包的方法,具体步骤为1) 将以太网卡DMA接收缓存区映射到用户区,减少数据包在内核区、内核到用户区的拷贝 次数。2) 注册一个混杂设备用于将以太网卡DMA接收缓存区映射到用户区和提供对网卡的接收状态的设置和控制。3) 关闭中断使用主动査询方式接收数据包,减少中断处理的调度带来的系统开销。4) 对每个网卡启动一个线程进行捕包,从而同时对多个网卡进行快速捕包。5) 在程序启动时分配好指定数量的数据包缓存,实现对数据包的缓存,降低包处理速度不 均匀造成的丢包率。6) 在捕包程序运行中重复使用数据包缓存,不再每次对每个数据包重新申请缓存空间,减 少使用系统分配缓存空间和释放缓存空间带来的消耗。7) 对数据包缓存区做了分组,提供对数据包的分类,降低线程之间对缓存区锁定访问的冲 突频率,具体缓存分组和流通方式为-8) 缓存区分为两种组别包接收缓存组和包处理缓存组,对于有N个网卡设备捕包和M 个包处理缓存组的配置,将定义((2 + M)xN + (4 x M))个缓存区,即N个接收缓存组和M个 包处理缓存组,每个接收缓存组包含2+M个缓存区,每个包处理缓存组包含4个缓存区,其中 的每个缓存区是以链表结构组织,每个链表元素为一个固定大小的数据包缓存及其实际接收的 数据包长度。9) 每个捕包线程使用一个包接收缓存组,由2个缓存区组成的两级空闲缓存区和M个接收 缓存区组成,收包时从一个包接收缓存组的2级空闲缓存区取得空闲数据包缓存,首先从二级 缓存转移全部的缓存到一级缓存上,之后每次只从一级缓存获取空闲数据包缓存直到用完再从 二级空闲缓存转移到一级缓存,对于映射到用户区的网卡DMA数据接收缓存区中接收完毕的数 据包,拷贝到一个空闲数据包缓存上之后,对其按M个类划分,分类的方法是均分为M组或按 数据包内容分类,分类完成后投放到一个接收缓存区上,每个接收缓存区对应一个类,当接收 缓存区中的数据包个数达到一定量时,转移到对应包处理缓存组的第二级待处理缓存区上。9、根据权利要求7所述的Linux系统上以太网卡快速捕包的方法,其特征在于每个包处理缓存 组由2个缓存区组成的两级待处理缓存区、1个处理中缓存区和1个己处理缓存区组成,供一个 或多个包处理线程使用, 一个包处理缓存组对应一个或多个包处理线程,包处理线程获取包的 过程是首先从第二级待处理包缓存区将所有数据包转移到第一级待处理包缓存区,之后每次 从第一级待处理包缓存区取包,每次取一个,且将该数据包从第一级待处理包缓存转移到处理 中缓存区,包处理线程处理完一个包后需要把该数据包从处理中缓存区转移到已处理缓存区, 再判断已处理缓存区中数据包缓存数目是否达到一定量,达到则将已处理缓存区中所有数据包 缓存转移到一个包接收缓存组的第二级空闲缓存区上,对于有多个包接收组的情况,循环投递 实现平均供给,这样实现了数据包缓存的循环使用。
权利要求
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,则复制、分类和投放数据包,设置该包状态为已接收,重新循环收包。
2、根据权利要求1所述的方法,其特征在于,所使用的用户区数据包缓存的输入为二级空闲缓存区,输出为二级待处理缓存区,而数据包从二级待处理缓存区流通到二级空闲缓存区的 流程是每个包处理线程调用pktcap_get_or^pkt—block或者pktcap_get—on印kt—noblock接 口函数获取一个数据包,调用pktcap—free—on印kt释放数据包,其中pktcap—get—on印kt一block 函数为阻塞式获取,当有数据包用时将立即返回,否则将利用Linux线程的条件变量 pthread一cond—wait等待,直到有捕包线程将己接收数据包从接收缓存区转移到二级待处理缓存 区并设置条件变量环形处理线程;pktcap—get—on印kt一noblock接口函数为非阻塞式获取,有数 据包则返回数据包指针,否则立即返回空指针;每个包处理缓存组虽然给多个包处理线程使用, 但是为了减少线程并发锁定缓存区而提高效率,由一个包处理线程使用。
3、 根据权利要求2所述的方法,其特征在于,pktcap—get—on印kt—block或者 pktcap—get—on印kt—noblock接口函数将使数据包缓存将从二级待处理缓存区转移到处理中缓 存区;首先判断一级待处理缓存区是否为空,若不为空,则将一个数据包从一级待处理缓存区 转移到处理中缓存区,然后将该数据包地址以指针方式返回;若一级待处理缓存区为空,则锁 定二级待处理缓存区并将其数据包转移到一级缓存区再解锁,然后从一级待处理缓存区取 -个 数据包转移到处理中缓存区并返回该数据包指针。
4、 根据权利要求2所述的方法,其特征在于,包处理线程处理完某个数据包后将使用 pktcap—free—on印kt接口函数释放数据包,在函数参数中传递该数据包的指针; pktcap_free_0ru3pkt接口函数将使数据包缓存从处理中缓存区转移到二级空闲缓存区;首先锁 定处理中缓存区,将数据包从处理中缓存区中脱离,然后解锁处理中缓存区,锁定已处理缓存 区,将数据包转移到己处理缓存区,然后判断已处理缓存区中数据包缓存个数是否大于 NUM—MIN一FREE,大于则锁定二级空闲缓存区,将已处理缓存区中所有数据包缓存转移到二级空闲 缓存区再解锁这两个缓存区并返回,否则解锁已处理缓存区并返回。
全文摘要
本发明公开一种Linux系统上使用以太网卡快速捕包的方法,该方法是将以太网卡DMA接收缓存区映射到用户区,通过减少数据包到达用户区以及用户程序的拷贝次数和每个网卡启动一个线程捕包来实现同时对多网卡进行捕包,还通过关闭中断主动查询接收,减少中断处理调度开销,定义重复使用的缓存及其管理,减少缓存申请和释放的开销并减少捕包线程、包处理线程之间访问缓存的冲突,实现对以太网数据包包括在其上传输的ip包的快速的捕获。
文档编号H04L12/26GK101227341SQ200710115379
公开日2008年7月23日 申请日期2007年12月18日 优先权日2007年12月18日
发明者吴庆民, 张会健, 施培任, 黄景昌 申请人:浪潮电子信息产业股份有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1