suricata 3.1 源码分析13 (流初始化)
2016-09-13 14:08
609 查看
简介
Suricata中用于管理和维护流的模块称为Flow Engine,主要由两部分实现,第一部分的入口点是FlowHandlePacket函数,用于为新数据包进行流查找/分配,另一部分是FlowManagerThread线程,用于对超时的流进行删除。初始化
初始化在FlowInitConfig中完成,与之相关的配置结构体为FlowConfig,其字段含义如下:
字段含义hash_rand用于随机化hash table的分布,后面会介绍hash_size流表所使用的hash table的大小(桶数量),默认为65536,memcapflow engine所允许使用的最大内存数量,默认为32MB,prealloc初始时预分配的流的数量,默认为10000,emergency_recovery退出紧急状态前需要删除的流的百分比,默认为30
/** \brief initialize the configuration * \warning Not thread safe */ void FlowInitConfig(char quiet) { SCLogDebug("initializing flow engine..."); memset(&flow_config, 0, sizeof(flow_config)); //初始化FlowConfig类型的变量low_config。 SC_ATOMIC_INIT(flow_flags); SC_ATOMIC_INIT(flow_memuse); SC_ATOMIC_INIT(flow_prune_idx); FlowQueueInit(&flow_spare_q); FlowQueueInit(&flow_recycle_q); 使用FlowQueueInit初始化一个用于存放空闲流(预分配的/回收后的)的flow_spare_q和flow_recycle_q。这里专门使用了一个FlowQueue结构体来实现队列,内部是一个标准的链式队列(首指针、尾指针、元素个数),与Ring Buffer那种基于数组实现的循环队列相比,更适合存储容量未知的数据。 #ifndef AFLFUZZ_NO_RANDOM unsigned int seed = RandomTimePreseed(); /* set defaults */ flow_config.hash_rand = (int)( FLOW_DEFAULT_HASHSIZE * (rand_r(&seed) / RAND_MAX + 1.0)); #endif flow_config.hash_size = FLOW_DEFAULT_HASHSIZE; 设置默认值hash_size:65536 flow_config.memcap = FLOW_DEFAULT_MEMCAP; 设置默认值memcap:32*1024*1024 (32M) flow_config.prealloc = FLOW_DEFAULT_PREALLOC; 设置默认值prealloc:10000 /* If we have specific config, overwrite the defaults with them, * otherwise, leave the default values */ intmax_t val = 0; if (ConfGetInt("flow.emergency-recovery", &val) == 1) { if (val <= 100 && val >= 1) { flow_config.emergency_recovery = (uint8_t)val; } else { SCLogError(SC_ERR_INVALID_VALUE, "flow.emergency-recovery must be in the range of 1 and 100 (as percentage)"); flow_config.emergency_recovery = FLOW_DEFAULT_EMERGENCY_RECOVERY; } } else { SCLogDebug("flow.emergency-recovery, using default value"); flow_config.emergency_recovery = FLOW_DEFAULT_EMERGENCY_RECOVERY; } 从配置中读取emergency-recovery /* Check if we have memcap and hash_size defined at config */ char *conf_val; uint32_t configval = 0; /** set config values for memcap, prealloc and hash_size */ if ((ConfGet("flow.memcap", &conf_val)) == 1) { if (ParseSizeStringU64(conf_val, &flow_config.memcap) < 0) { SCLogError(SC_ERR_SIZE_PARSE, "Error parsing flow.memcap " "from conf file - %s. Killing engine", conf_val); exit(EXIT_FAILURE); } } 从配置中读取memcap if ((ConfGet("flow.hash-size", &conf_val)) == 1) { if (ByteExtractStringUint32(&configval, 10, strlen(conf_val), conf_val) > 0) { flow_config.hash_size = configval; } } 从配置中读取hash_size if ((ConfGet("flow.prealloc", &conf_val)) == 1) { if (ByteExtractStringUint32(&configval, 10, strlen(conf_val), conf_val) > 0) { flow_config.prealloc = configval; } } 从配置中读取prealloc SCLogDebug("Flow config from suricata.yaml: memcap: %"PRIu64", hash-size: " "%"PRIu32", prealloc: %"PRIu32, flow_config.memcap, flow_config.hash_size, flow_config.prealloc); /* alloc hash memory */ uint64_t hash_size = flow_config.hash_size * sizeof(FlowBucket); if (!(FLOW_CHECK_MEMCAP(hash_size))) { SCLogError(SC_ERR_FLOW_INIT, "allocating flow hash failed: " "max flow memcap is smaller than projected hash size. " "Memcap: %"PRIu64", Hash table size %"PRIu64". Calculate " "total hash size by multiplying \"flow.hash-size\" with %"PRIuMAX", " "which is the hash bucket size.", flow_config.memcap, hash_size, (uintmax_t)sizeof(FlowBucket)); exit(EXIT_FAILURE); } flow_hash = SCMallocAligned(flow_config.hash_size * sizeof(FlowBucket), CLS); if (unlikely(flow_hash == NULL)) { SCLogError(SC_ERR_FATAL, "Fatal error encountered in FlowInitConfig. Exiting..."); exit(EXIT_FAILURE); } memset(flow_hash, 0, flow_config.hash_size * sizeof(FlowBucket)); 按照hash_size为流表flow_hash分配内存,并全部初始化为0 uint32_t i = 0; for (i = 0; i < flow_config.hash_size; i++) { FBLOCK_INIT(&flow_hash[i]); } 初始化各个bucket的锁 (void) SC_ATOMIC_ADD(flow_memuse, (flow_config.hash_size * sizeof(FlowBucket))); 将hash表大小记录到当前flow engine占用的内存flow_memuse中 if (quiet == FALSE) { SCLogConfig("allocated %llu bytes of memory for the flow hash... " "%" PRIu32 " buckets of size %" PRIuMAX "", SC_ATOMIC_GET(flow_memuse), flow_config.hash_size, (uintmax_t)sizeof(FlowBucket)); } /* pre allocate flows */ for (i = 0; i < flow_config.prealloc; i++) { if (!(FLOW_CHECK_MEMCAP(sizeof(Flow) + FlowStorageSize()))) { SCLogError(SC_ERR_FLOW_INIT, "preallocating flows failed: " "max flow memcap reached. Memcap %"PRIu64", " "Memuse %"PRIu64".", flow_config.memcap, ((uint64_t)SC_ATOMIC_GET(flow_memuse) + (uint64_t)sizeof(Flow))); exit(EXIT_FAILURE); } Flow *f = FlowAlloc(); 调用FlowAlloc新建prealloc个Flow if (f == NULL) { SCLogError(SC_ERR_FLOW_INIT, "preallocating flow failed: %s", strerror(errno)); exit(EXIT_FAILURE); } FlowEnqueue(&flow_spare_q,f); 使用FlowEnqueue将f放入flow_spare_q中 } if (quiet == FALSE) { SCLogConfig("preallocated %" PRIu32 " flows of size %" PRIuMAX "", flow_spare_q.len, (uintmax_t)(sizeof(Flow) + + FlowStorageSize())); SCLogConfig("flow memory usage: %llu bytes, maximum: %"PRIu64, SC_ATOMIC_GET(flow_memuse), flow_config.memcap); } FlowInitFlowProto(); 调用FlowInitFlowProto,初始化各种协议相关的timeout和清理/状态函数,此处可在配置文件flow-timeouts里设置 return; }
相关文章推荐
- suricata 3.1 源码分析18 (模块注册及初始化)
- suricata 3.1 源码分析23 (数据包解码模块注册及初始化)
- suricata 3.1 源码分析4
- suricata 3.1 源码分析9
- suricata 3.1 源码分析24 (数据包解码模块执行)
- suricata 3.1 源码分析31 (RespondReject)
- suricata 3.1 源码分析22 (数据包处理2)
- suricata 3.1 源码分析1
- suricata 3.1 源码分析28 (数据包TCP解码)
- suricata 3.1 源码分析20 (数据包封装)
- suricata 3.1 源码分析7
- suricata 3.1 源码分析16 (流管理1)
- suricata 3.1 源码分析11
- suricata 3.1 源码分析25 (数据包以太层解码)
- suricata 3.1 源码分析2
- suricata 3.1 源码分析8
- suricata 3.1 源码分析14 (流查找分配)
- suricata 3.1 源码分析15 (流更新)
- suricata 3.1 源码分析30 (packet_pool处理流程)
- suricata 3.1 源码分析27 (数据包IPv4解码)