suricata 3.1 源码分析19 (数据包获取)
2016-09-22 09:02
661 查看
初始化完成后,TmThreadsSlotPktAcqLoop函数将进入一个while循环,调用slot的PktAcqLoop函数获取并处理数据包。对应的模块函数原型为:
TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot)
其中,data即为初始化阶段生成的PcapThreadVars结构体,而slot就是包含该模块的那个slot,传入进来的目的主要是获取线程中后续的slot(这里对应DecodePcap),以调用后续的数据包处理流程。
TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot)
其中,data即为初始化阶段生成的PcapThreadVars结构体,而slot就是包含该模块的那个slot,传入进来的目的主要是获取线程中后续的slot(这里对应DecodePcap),以调用后续的数据包处理流程。
/** * \brief Main PCAP reading Loop function */ TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot) { SCEnter(); int packet_q_len = 64; PcapThreadVars *ptv = (PcapThreadVars *)data; //获取初始化时生成的PcapThreadVars结构体 int r; TmSlot *s = (TmSlot *)slot; //获取当前slot(此处是与“ReceivePcap”对应的slot) ptv->slot = s->slot_next; //将PcapThreadVars指向下一个slot(此处是与“DecodePcap”对应的slot) ptv->cb_result = TM_ECODE_OK; while (1) { if (suricata_ctl_flags & (SURICATA_STOP | SURICATA_KILL)) { SCReturnInt(TM_ECODE_OK); /*检查suricata_ctl_flags是否包含STOP或KILL标志,即Suricata是否需要退出, 若是的话则立即返回。这里让子线程去检查全局控制标志的处理方式感觉的不是很优雅, 最好是只检查自己的线程标志。*/ } /* make sure we have at least one packet in the packet pool, to prevent * us from alloc'ing packets at line rate */ PacketPoolWait(); //等待packet pool中有空闲数据包结构(通过cond或sleep实现) /* Right now we just support reading packets one at a time. */ r = pcap_dispatch(ptv->pcap_handle, packet_q_len, (pcap_handler)PcapCallbackLoop, (u_char *)ptv); /*调用pcap_dispatch获取并处理数据包。其中,第2个参数表示最多处理的数据包个数, 传入的值packet_q_len为packet pool的当前大小;第3个参数为包处理回调函数 PcapCallbackLoop;最后一个参数为传给前面的回调函数的用户数据,这里传入的是 PcapThreadVars结构体。*/ if (unlikely(r < 0)) { int dbreak = 0; SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 " %s", r, pcap_geterr(ptv->pcap_handle)); #ifdef PCAP_ERROR_BREAK if (r == PCAP_ERROR_BREAK) { SCReturnInt(ptv->cb_result); } #endif do { usleep(PCAP_RECONNECT_TIMEOUT); if (suricata_ctl_flags != 0) { dbreak = 1; break; } r = PcapTryReopen(ptv); } while (r < 0); //检查返回值,若出错则尝试不断调用PcapTryReopen重新开启抓包。 if (dbreak) { break; } } else if (ptv->cb_result == TM_ECODE_FAILED) { SCLogError(SC_ERR_PCAP_DISPATCH, "Pcap callback PcapCallbackLoop failed"); SCReturnInt(TM_ECODE_FAILED); } else if (unlikely(r == 0)) { TmThreadsCaptureInjectPacket(tv, ptv->slot, NULL); } StatsSyncCountersIfSignalled(tv); //同步stats counters } PcapDumpCounters(ptv); StatsSyncCountersIfSignalled(tv); SCReturnInt(TM_ECODE_OK); }
相关文章推荐
- suricata 3.1 源码分析27 (数据包IPv4解码)
- suricata 3.1 源码分析29 (数据包队列)
- suricata 3.1 源码分析26 (数据包VLAN解码)
- suricata 3.1 源码分析21 (数据包处理1)
- suricata 3.1 源码分析23 (数据包解码模块注册及初始化)
- suricata 3.1 源码分析20 (数据包封装)
- suricata 3.1 源码分析28 (数据包TCP解码)
- suricata 3.1 源码分析22 (数据包处理2)
- suricata 3.1 源码分析25 (数据包以太层解码)
- suricata 3.1 源码分析24 (数据包解码模块执行)
- suricata 3.1 源码分析34 (dns解析获取相关内容)
- suricata 3.1 源码分析17 (流管理2)
- suricata 3.1 源码分析10
- suricata 3.1 源码分析34 (FlowWorker处理流程3 - 流重用)
- suricata 3.1 源码分析9
- suricata 3.1 源码分析6
- suricata 3.1 源码分析16 (流管理1)
- suricata 3.1 源码分析1
- suricata 3.1 源码分析18 (模块注册及初始化)
- suricata 3.1 源码分析33 (FlowWorker处理流程2 - FlowHandlePacket)