您的位置:首页 > 其它

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),以调用后续的数据包处理流程。

/**
*  \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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数 源码