用最大白的话语,探讨技术的本质
本系列想从这几个方向聊
1. 整套系统它的受众业务,为何要探讨和学习
2. 网络协议栈开发基础知识,各模块角色的定位,为什么要设计这几个模块
3. 如何进行设计框架、工作线程模式、各模块如何高效协作
本章探讨的有
包捕获方案的介绍
不同方案区别的本质
捕获模块的线程模型
内存存储设计
为什么开启本系列文章
探讨本系列文章的目的有:
l 其一是普及网络协议栈产品开发,帮助新手或为入行,并想从事网络产品类研发的同学尽快入行,了解开发需要的基础知识,行业的业务面知识;
l 其二深层次探讨,系统设计,实现方式,算法的优缺点,通用性,专用性的一些技术细节,学习并改进。
本系类文章主要是围绕应用层网络协议栈的开发展开讨论的;它是一套通用的解决网络产品需求的系统,网络产品需求指的是对网络数据的监控、审计、研判、提取、防护、可视等;具体比如现在要对一个公司,整个高校,一个地区互联网出入口流量做一个检查,检查该地区是否有人使用QQ传输非法文件,监测公司是否有人上班摸鱼,高校是否有人考试作弊(基于网络作弊手段),电脑或服务器是否被黑客攻击,被攻击了后的防护措施,这些都在网络协议栈的业务范畴中。
本系统对比交换机和路由器的业务,虽然它们同样处理网络流量,但是交换机和路由器只是处理网络的二、三层,再往上的内容不再做进一步处理了。
应用协议栈-捕获模块:
回顾下
捕获模块主要是针对互联网上传输的流量进行捕获,捕获的目的是将二进制的bit数据,提供给后续的模块进行解析、信息提取、审计、研判等等,以网络产品的业务需求。
应用层程序是利用系统调用/第三方接口的形式,调用网卡驱动来操作网卡,从而获得数据包捕获的功能。
包捕获方案
开发数据包捕获模块的方案有:libpcap、netmap、pfring、afpacket、xdp、dpdk...
对于本系类不对具体的包捕获方案做详细讨论,在这里想讨论的是:不同包捕获方案它有什么区别,区别的底层原理是什么,了解这些,从而能够提升自己的设计思想!其实条条大路通罗马,选对路!
论数据包捕获方案基本原理:
想象一下,网络世界就像一条繁忙的高速路,而数据包就是在这条路上飞驰的车辆。我们的任务是挑选出某些特定的车辆进行检查,这就好比在网络中捕获我们需要的数据包。不同的包捕获方案就像是设置在高速路上的不同类型的检查站,它们各有各的工作方式和效率。
libpcap:这是一位老练的交警,对各种路况都熟悉。它通过操作系统提供的接口,站在路边耐心等待数据包路过,然后记录下来。这种方式比较通用,但因为要等操作系统通知,所以速度上可能不是最快的。
netmap:这个方案像是直接在高速路上建了一个高科技检查站,它可以绕过一些常规的排队流程,直接从车道上“抓取”数据包,大大提升了处理速度。但它需要网卡支持特定的技术才能发挥最佳效果。
pfring:想象它为一个装备了快速识别系统的检查点,专门优化了对于高流量环境的处理能力。它能同时处理多条车道上的车辆(数据包),适合那些需要高速筛选和处理大量数据的场景。
afpacket:这是一个相对简单直接的方法,它直接和内核合作,开辟了一条快速通道,让数据包能更快地从网卡到达应用程序。虽然不如某些高级方案那么灵活,但在很多场景下已经足够高效。
xdp:这是个超级智能的前置检查系统,它直接在数据包进入高速路(网络栈)的入口处就开始工作,能在极短的时间内决定数据包的命运(比如丢弃或转发)。它的反应速度非常快,适合需要实时处理的场景(可以讨论,应用比较广泛,除了处理数据面工具,还可以做解密行业方案)。
dpdk:想象它为一个完全不依赖传统高速公路规则的私人跑道。它绕过了操作系统的一部分,直接与硬件打交道,创建了自己的高速数据传输通道。这样做的结果是极高的数据处理速度,但同时也需要更多的定制和配置工作(会单独专项讲说)。
每个方案的选择,都要根据你的具体需求来定。比如,如果你追求极致的速度和低延迟,可能会考虑xdp或dpdk;如果需要广泛的兼容性和易用性,libpcap可能是更好的选择。理解这些底层原理,就像是掌握不同交通规则和道路建设技术,能帮助你在设计时,更准确地选择合适的工具,构建出既高效又符合需求的网络数据捕获系统。
再梳理下硬件的传输流程:
包捕获方案基本原理都是将网卡硬件中的数据,通过总线,传递到内存中,cpu再从内存中加载到寄存器中运算(中间也涉及到cache),运算结果再次通过内存,通过总线重载入具体硬件网卡上,这样网卡通过网线(或者无线模块)就连接到互联网了。
论各类方案的区别,如何从中偷师学艺:
那么大家写过程序的都知道,除了算法,这个中间核心问题不可避免的就是,内核态切换!拷贝!信号!!,其实各项方案具体的区别就是在于提出了一套自己的解决三个核心的处理方式:
那我们顺着思路分解喽:
拷贝指的是,一拷贝的次数,二拷贝的量
信号指的是,如何通知目的模块,如何捕获中断,如何处理中断?
内核态切换指的是,操作系统上用户程序不可避免的,用户态和内核态空间切换
再深入往下想一层:
一你看拷贝次数很明确,越少越好!
二拷贝的量当然也是越少越好,那么量除了减少次数,是不是需要合理的设计数据结构,减少拷贝体积也是必须要做的!
三处理中断,频繁的中断系统就废掉了,即消耗系统句柄也需要上下文的维护,能够减少中断,或者去掉中断是个好路子!
四内核态的切换,之所以有内核态和用户态的切换,那是因为上章节说的,用户态需要通过系统调用再通过内核模块,调用具体的驱动操作到硬件。主流解决方案是offloading或者uploading,就是将模块功能上载或者卸载掉,这样保证功能实现的方案都在同一个空间态中,那就没有切换了!
五内核是个全能的王,但是绝对不是单项的冠军,不要过分崇拜内核,是否可以做到绕开内核,另辟蹊径呀,条条大路通罗马!
对吧,思想就谈到这里了,思想很重要,战略很重要,架构很重要!先要摆正思想,多了解优秀的项目思想,重中之重!
如何将落地,完成捕获模块的设计
要写代码,那是要做好框架设计,接口设计,数据结构定义,算法就不谈了:
下一章将详细针对以上设计展开,针对线程模型,功能模块的抽象,上下游交互,内存管理设计,详细聊一些...
待续!