ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Suricata6.0流管理源码注释一:流管理简介

2022-01-07 16:30:23  阅读:214  来源: 互联网

标签:Suricata6.0 函数 管理 队列 flow 源码 spare 100 pool


Suricata6.0流管理代码梳理

目录

1. 流管理内容简介... 1

2. 流管理基本思想... 1

3. 流建立入口函数... 1

4. 流结构体flow的分配... 1

5. 流存储关键数据结构... 2

6. 流管理主要函数... 2

  1. 流管理内容简介

包括新建流和老化流两大部分,一个流用一个flow结构体表示,具体工作又包括为packet获取一个flow,更新流的状态,流的老化回收,空闲flow个数维护即flow空闲数量少于预分配数量的90%时则进行补充,如果flow空闲数量多于预分配的flow数量的110%时则进行释放。

释放逻辑:多出来的flow数量x是flow队列(固定100个)数量的10倍及以上则释放x/10个flow,就是多出来的flow数量必须小于单个flow队列flow数量的10倍,比如单个flow队列固定flow数量为100,则由于从内存分配而多出来的flow数量必须小于1000(100*10),如果为1000则释放的数量为1000/10=100,如果为1100,则需要释放1100/10=110。

多出来的flow是因为预分配的flow使用完了,而且当前flow占用的总内存没有超过配置的内存字节数,于是flowalloc分配新flow,这样flow数量就会增多。

  1. 流管理基本思想

(1)根据流的状态设置流的超时时间,时间到了则老化之,回收flow到全局的flow_spare_pool中,哪个flow队列不够100,就放入哪个flow队列。

         (2)如果预先分配的flow结构体不够用了,配置的flow内存也用完了,则设置进入紧急模式状态,一个是把流的超时时间设置为紧急超时时间,这个时间远远短于正常老化时间,二是流老化处理线程轮询间隔时间也会缩短,轮询间隔时间正常时667毫秒检查一次老化,紧急模式为250毫秒检查一次;另外,每个线程只老化自己负责的flowbucket上的flow,这个flowbucket的范围在FlowInitConfig初始化时设置,就是按照flowbucket的数量平均分配给每个老化线程即运行FlowManager函数的线程。

(3)进入紧急模式后,会不断检查可用flow的数量,如果这个数量达到预分配flow数量的一定的百分比,则退出紧急模式。

  1. 流建立入口函数

当一个网络数据包到达时,经过收包,解码产生了packet结构体指针p,这时进入下一个模块第一个工作就是为这个p查找其所属流flow,这个工作从函数FlowHandlePacket开始,不同的suricata版本对这个函数的调用位置不一样,但都是在解码后进行调用,从4.0开始在FlowWorker函数中调用,3.0及以前的版本都在解码模块的解码函数中调用比如在DecodeUDP,DecodeTCP等函数中调用。

FlowHandlePacket函数做了大部分流查找分配及状态设置更新的工作,有一部分更新状态的工作放在另外一个函数FlowUpdate,在如果没有找到则分配一个flow,如果找到则更新流状态。

  1. 流结构体flow的分配

流的flow存放在全局flow哈希数组中:FlowBucket *flow_hash,所以操作bucket时需要对其上锁,每个bucket存放若干哈希值相同的flow结构体,哈希值就是五元组哈希后与数组大小的模,解码后为一个包获取flow时,先从全局变量flow_hash[hash%hash_size]数组里进行查找,存在则进行状态更新操作,不存在则需要从空闲的flow池子里分配一个flow结构体。

分配flow两个方式,一个是从预先分配的全局flow池子里获取,如果没有可用的flow,则在配置的内存空间范围内直接从内存上分配flow,这个池子就称为空闲flow池子,它是个根据配置文件预先分配一定数量flow的内存池,需要的时候从里边取,不需要了则归还进去,取到flow后,设置相关成员数据,然后放入全局变量flow_hash中,该flow后续的packet都可以匹配到该flow结构体。

不同版本的全局flow池子有所区别,比如4.0和之前的版本都是FlowQueue flow_spare_q(带锁的flow链表)这样的全局变量(5.0左右版本没看过),直接用锁子从这个全局变量获取可用的flow结构体。

6.0版本也是用的全局变量,只不过flow不是组织成一个链表,而是先根据配置文件配置的flow个数进行预分配,把这些flow每100个flow组织成一个空闲的flow队列,再把每个包含100个flow的队列组成pool,就是通过static FlowSparePool *flow_spare_pool链接起来形成pool,它是个全局变量,由static SCMutex flow_spare_pool_m保护。

处理包的每个线程都有自己的空闲flow队列,分配flow时,从线程自己的flow队列(变量名字:spare_queue)里获取,如果没有可用flow,则从上边说的全局pool里取一个flow队列赋值给spare_queue,后续有包到来就从spare_queue里取flow使用,所以从全局pool获取的flow是一个flow队列(100个),一次获取一个队列的flow,只有100个flow用完了才需要锁一次全局pool获取一个flow队列,而不像4.0及之前版本一次获取一个flow每次都要锁,从这点看,减小了锁的粒度,如果流的数量比较多的话,在获取flow时可以提高不少性能。

  1. 流存储关键数据结构

全局flow哈希数组中:FlowBucket *flow_hash,正则使用的流的结构体flow存放到这里

存放空闲Flow队列的pool定义:

typedef struct FlowSparePool {

FlowQueuePrivate queue;        //flow队列,就是个链表,由100个flow组成

     struct FlowSparePool *next; //池子链表,把多个flow队列组织成链表,线程自己的flow队列用完时,从这个pool里获取一个flow队列

 } FlowSparePool;

 static uint32_t flow_spare_pool_flow_cnt = 0;    //空闲flow总个数,包括所有flow队列的flow

 static uint32_t flow_spare_pool_block_size = 100;//每个flow队列里空闲flow的个数

 static FlowSparePool *flow_spare_pool = NULL;  //全局链表头指针,存储可用的flow

 static SCMutex flow_spare_pool_m = SCMUTEX_INITIALIZER;//保护上边那位爷

  1. 流管理主要函数

流初始化函数:

入口函数

被直接调用函数

FlowInitConfig

(flow.c)

FlowQueueInit

FlowSparePoolInit

FlowInitFlowProto

FlowSparePoolInit

(flow-spare-pool.c)

FlowSpareGetPool

FlowSparePoolUpdateBlock

流查询建立主要函数:

入口函数

被直接调用函数

FlowWorker (flow-worker.c)

FlowHandlePacket

FlowHandlePacket (flow.c)

FlowGetFlowFromHash

FlowGetFlowFromHash

(flow-hash.c)

FlowGetNew

MoveToWorkQueue

FlowInit

FlowUpdateState

FlowGetNew

(flow-hash.c)

FlowQueuePrivateGetFromTop

FlowSpareSync

FlowTimeoutsEmergency

FlowGetUsedFlow

FlowAlloc

流老化检查主要函数:

入口函数

被直接调用函数

FlowManage

(flow-manager.c)

FlowSpareGetPoolSize

FlowSparePoolUpdate

FlowTimeoutHash

FlowTimeoutHash

(flow-manager.c)

FlowManagerHashRowTimeout

FlowManagerHashRowClearEvictedList

ProcessAsideQueue

FlowManagerHashRowClearEvictedList

(flow-manager.c)

FlowQueuePrivateAppendFlow

FlowManagerFlowTimeout

(flow-manager.c)

FlowGetFlowTimeoutDirect

ProcessAsideQueue

(flow-manager.c)

FlowForceReassemblyForFlow

FlowQueuePrivateAppendFlow

FlowForceReassemblyForFlow

(flow-timeout.c)

TmThreadsInjectFlowById

TmThreadsInjectFlowById

(tm-threads.c)

FlowEnqueue

SCCondSignal

流回收主要函数:

入口函数

被直接调用函数

FlowRecycler

(flow-manager.c)

FlowQueueExtractPrivate

FlowQueuePrivateGetFromTop

Recycler

Recycler

(flow-manager.c)

OutputFlowLog

FlowClearMemory

FlowSparePoolReturnFlow

标签:Suricata6.0,函数,管理,队列,flow,源码,spare,100,pool
来源: https://blog.csdn.net/ljq32/article/details/122367100

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有