suricata 3.1 源码分析22 (数据包处理2)

对数据包进行进一步处理的TmThreadsSlotVarRun函数原型如下:
TmEcode TmThreadsSlotVarRun(ThreadVars *tv, Packet *p,TmSlot *slot)
按照函数头的注释说明,这个函数被从母函数中拉出来独立存在的原因是,为了能够对其进行递归调用。函数主流程是一个遍历所有slot的for循环,

/**
 * \brief Separate run function so we can call it recursively.
 *
 * \todo Deal with post_pq for slots beyond the first.
 */
TmEcode TmThreadsSlotVarRun(ThreadVars *tv, Packet *p,
                                          TmSlot *slot)
{
    TmEcode r;
    TmSlot *s;
    Packet *extra_p;

    for (s = slot; s != NULL; s = s->slot_next) {
        TmSlotFunc SlotFunc = SC_ATOMIC_GET(s->SlotFunc);
/*获取 SlotFunc函数(类似于DecodePcap这种,注册时挂在全局变量
tmm_modules[TMM_DECODEPCAP].Func上)*/
        PACKET_PROFILING_TMM_START(p, s->tm_id);

        if (unlikely(s->id == 0)) {
            r = SlotFunc(tv, p, SC_ATOMIC_GET(s->slot_data), &s->slot_pre_pq, &s->slot_post_pq);
        } else {
            r = SlotFunc(tv, p, SC_ATOMIC_GET(s->slot_data), &s->slot_pre_pq, NULL);
        }
//调用slot的处理函数SlotFunc
        PACKET_PROFILING_TMM_END(p, s->tm_id);

        /* handle error */
        if (unlikely(r == TM_ECODE_FAILED)) {
            /* Encountered error.  Return packets to packetpool and return */
            TmqhReleasePacketsToPacketPool(&s->slot_pre_pq);

            SCMutexLock(&s->slot_post_pq.mutex_q);
            TmqhReleasePacketsToPacketPool(&s->slot_post_pq);
            SCMutexUnlock(&s->slot_post_pq.mutex_q);

            TmThreadsSetFlag(tv, THV_FAILED);
            return TM_ECODE_FAILED;
/*若调用SlotFunc返回失败,则调用TmqhOutputPacketpool将数据包(以及各个slot的
slot_post_pq中的数据包)进行回收或释放。然后设置线程标志为THV_FAILED,等待主线程处理*/
        }

        /* handle new packets */
        while (s->slot_pre_pq.top != NULL) {
            extra_p = PacketDequeue(&s->slot_pre_pq);
            if (unlikely(extra_p == NULL))
                continue;

            /* see if we need to process the packet */
            if (s->slot_next != NULL) {
                r = TmThreadsSlotVarRun(tv, extra_p, s->slot_next);
                if (unlikely(r == TM_ECODE_FAILED)) {
                    TmqhReleasePacketsToPacketPool(&s->slot_pre_pq);

                    SCMutexLock(&s->slot_post_pq.mutex_q);
                    TmqhReleasePacketsToPacketPool(&s->slot_post_pq);
                    SCMutexUnlock(&s->slot_post_pq.mutex_q);

                    TmqhOutputPacketpool(tv, extra_p);
                    TmThreadsSetFlag(tv, THV_FAILED);
                    return TM_ECODE_FAILED;
                }
            }
/*若调用SlotFunc返回成功,则继续处理slot_pre_pq:对其中每个数据包,都递归调用
TmThreadsSlotVarRun,将其送入下一个slot进行处理。
注: slot_pre_pq vs. slot_post_pq: 某个slot在处理某个母数据包时新产生的子数据包,若放入
slot_pre_pq中,则这个数据包将在本个slot处理完母数据包后,在后续slot处理母数据包之前,
先将这些子数据包放到后续的slot去处理;而如果是放如slot_post_pq,则需要等到母数据包被所有
slot都处理完后,在下一个数据包处理之前,再去集中处理*/
            tv->tmqh_out(tv, extra_p);
/*则调用tmqh_out将数据包extra_p送到后续队列中去。在这里会通过队列交给
FlowWorker线程来处理*/

        }
    }

    return TM_ECODE_OK;
}

你可能感兴趣的:(suricata,suricata源码分析)