예제 #1
0
static int SCAtomicTest01(void)
{
    int result = 0;
    int a = 10;
    int b = 20;
    int *temp_int = NULL;

    SC_ATOMIC_DECL_AND_INIT(void *, temp);

    temp_int = SC_ATOMIC_GET(temp);
    if (temp_int != NULL)
        goto end;

    (void)SC_ATOMIC_SET(temp, &a);
    temp_int = SC_ATOMIC_GET(temp);
    if (temp_int == NULL)
        goto end;
    if (*temp_int != a)
        goto end;

    (void)SC_ATOMIC_SET(temp, &b);
    temp_int = SC_ATOMIC_GET(temp);
    if (temp_int == NULL)
        goto end;
    if (*temp_int != b)
        goto end;

    result = 1;

 end:
    return result;
}
예제 #2
0
파일: flow-worker.c 프로젝트: norg/suricata
static TmEcode FlowWorkerThreadDeinit(ThreadVars *tv, void *data)
{
    FlowWorkerThreadData *fw = data;

    DecodeThreadVarsFree(tv, fw->dtv);

    /* free TCP */
    StreamTcpThreadDeinit(tv, (void *)fw->stream_thread);

    /* free DETECT */
    void *detect_thread = SC_ATOMIC_GET(fw->detect_thread);
    if (detect_thread != NULL) {
        DetectEngineThreadCtxDeinit(tv, detect_thread);
        SC_ATOMIC_SET(fw->detect_thread, NULL);
    }

    /* Free output. */
    OutputLoggerThreadDeinit(tv, fw->output_thread);

    /* free pq */
    BUG_ON(fw->pq.len);
    SCMutexDestroy(&fw->pq.mutex_q);

    SC_ATOMIC_DESTROY(fw->detect_thread);
    SCFree(fw);
    return TM_ECODE_OK;
}
예제 #3
0
/**
 * \brief select the queue to output in a round robin fashion.
 *
 * \param tv thread vars
 * \param p packet
 */
void TmqhOutputFlowRoundRobin(ThreadVars *tv, Packet *p)
{
    int32_t qid = 0;

    TmqhFlowCtx *ctx = (TmqhFlowCtx *)tv->outctx;

    /* if no flow we use the first queue,
     * should be rare */
    if (p->flow != NULL) {
        qid = SC_ATOMIC_GET(p->flow->autofp_tmqh_flow_qid);
        if (qid == -1) {
            qid = SC_ATOMIC_ADD(ctx->round_robin_idx, 1);
            if (qid >= ctx->size) {
                SC_ATOMIC_RESET(ctx->round_robin_idx);
                qid = 0;
            }
            (void) SC_ATOMIC_ADD(ctx->queues[qid].total_flows, 1);
            (void) SC_ATOMIC_SET(p->flow->autofp_tmqh_flow_qid, qid);
        }
    } else {
        qid = ctx->last++;

        if (ctx->last == ctx->size)
            ctx->last = 0;
    }
    (void) SC_ATOMIC_ADD(ctx->queues[qid].total_packets, 1);

    PacketQueue *q = ctx->queues[qid].q;
    SCMutexLock(&q->mutex_q);
    PacketEnqueue(q, p);
    SCCondSignal(&q->cond_q);
    SCMutexUnlock(&q->mutex_q);

    return;
}
예제 #4
0
파일: flow-worker.c 프로젝트: norg/suricata
static TmEcode FlowWorkerThreadInit(ThreadVars *tv, const void *initdata, void **data)
{
    FlowWorkerThreadData *fw = SCCalloc(1, sizeof(*fw));
    if (fw == NULL)
        return TM_ECODE_FAILED;

    SC_ATOMIC_INIT(fw->detect_thread);
    SC_ATOMIC_SET(fw->detect_thread, NULL);

    fw->dtv = DecodeThreadVarsAlloc(tv);
    if (fw->dtv == NULL) {
        FlowWorkerThreadDeinit(tv, fw);
        return TM_ECODE_FAILED;
    }

    /* setup TCP */
    if (StreamTcpThreadInit(tv, NULL, &fw->stream_thread_ptr) != TM_ECODE_OK) {
        FlowWorkerThreadDeinit(tv, fw);
        return TM_ECODE_FAILED;
    }

    if (DetectEngineEnabled()) {
        /* setup DETECT */
        void *detect_thread = NULL;
        if (DetectEngineThreadCtxInit(tv, NULL, &detect_thread) != TM_ECODE_OK) {
            FlowWorkerThreadDeinit(tv, fw);
            return TM_ECODE_FAILED;
        }
        SC_ATOMIC_SET(fw->detect_thread, detect_thread);
    }

    /* Setup outputs for this thread. */
    if (OutputLoggerThreadInit(tv, initdata, &fw->output_thread) != TM_ECODE_OK) {
        FlowWorkerThreadDeinit(tv, fw);
        return TM_ECODE_FAILED;
    }

    DecodeRegisterPerfCounters(fw->dtv, tv);
    AppLayerRegisterThreadCounters(tv);

    /* setup pq for stream end pkts */
    memset(&fw->pq, 0, sizeof(PacketQueue));
    SCMutexInit(&fw->pq.mutex_q, NULL);

    *data = fw;
    return TM_ECODE_OK;
}
예제 #5
0
/**
 * \brief Print some stats to the log at program exit.
 *
 * \param tv Pointer to ThreadVars.
 * \param data Pointer to data, ErfFileThreadVars.
 */
void
ReceiveErfDagThreadExitStats(ThreadVars *tv, void *data)
{
    ErfDagThreadVars *ewtn = (ErfDagThreadVars *)data;

    (void)SC_ATOMIC_SET(ewtn->livedev->pkts,
        (uint64_t)SCPerfGetLocalCounterValue(ewtn->packets, tv->sc_perf_pca));
    (void)SC_ATOMIC_SET(ewtn->livedev->drop,
        (uint64_t)SCPerfGetLocalCounterValue(ewtn->drops, tv->sc_perf_pca));

    SCLogInfo("Stream: %d; Bytes: %"PRIu64"; Packets: %"PRIu64
        "; Drops: %"PRIu64,
        ewtn->dagstream,
        ewtn->bytes,
        (uint64_t)SCPerfGetLocalCounterValue(ewtn->packets, tv->sc_perf_pca),
        (uint64_t)SCPerfGetLocalCounterValue(ewtn->drops, tv->sc_perf_pca));
}
예제 #6
0
/**
 * \brief Print some stats to the log at program exit.
 *
 * \param tv Pointer to ThreadVars.
 * \param data Pointer to data, ErfFileThreadVars.
 */
void
ReceiveErfDagThreadExitStats(ThreadVars *tv, void *data)
{
    ErfDagThreadVars *ewtn = (ErfDagThreadVars *)data;

    (void)SC_ATOMIC_SET(ewtn->livedev->pkts,
        StatsGetLocalCounterValue(tv, ewtn->packets));
    (void)SC_ATOMIC_SET(ewtn->livedev->drop,
        StatsGetLocalCounterValue(tv, ewtn->drops));

    SCLogInfo("Stream: %d; Bytes: %"PRIu64"; Packets: %"PRIu64
        "; Drops: %"PRIu64,
        ewtn->dagstream,
        ewtn->bytes,
        StatsGetLocalCounterValue(tv, ewtn->packets),
        StatsGetLocalCounterValue(tv, ewtn->drops));
}
예제 #7
0
파일: ippair.c 프로젝트: bmeeks8/suricata
/**
 *  \brief Update memcap value
 *
 *  \param size new memcap value
 */
int IPPairSetMemcap(uint64_t size)
{
    if ((uint64_t)SC_ATOMIC_GET(ippair_memuse) < size) {
        SC_ATOMIC_SET(ippair_config.memcap, size);
        return 1;
    }

    return 0;
}
예제 #8
0
파일: source-pcap.c 프로젝트: norg/suricata
static inline void PcapDumpCounters(PcapThreadVars *ptv)
{
    struct pcap_stat pcap_s;
    if (likely((pcap_stats(ptv->pcap_handle, &pcap_s) >= 0))) {
        StatsSetUI64(ptv->tv, ptv->capture_kernel_packets, pcap_s.ps_recv);
        StatsSetUI64(ptv->tv, ptv->capture_kernel_drops, pcap_s.ps_drop);
        (void) SC_ATOMIC_SET(ptv->livedev->drop, pcap_s.ps_drop);
        StatsSetUI64(ptv->tv, ptv->capture_kernel_ifdrops, pcap_s.ps_ifdrop);
    }
}
예제 #9
0
void LogFilestoreRegister (void)
{
    OutputRegisterFiledataModule(LOGGER_FILE_STORE, MODULE_NAME, "file",
        LogFilestoreLogInitCtx, LogFilestoreLogger, LogFilestoreLogThreadInit,
        LogFilestoreLogThreadDeinit, LogFilestoreLogExitPrintStats);
    OutputRegisterFiledataModule(LOGGER_FILE_STORE, MODULE_NAME, "file-store",
        LogFilestoreLogInitCtx, LogFilestoreLogger, LogFilestoreLogThreadInit,
        LogFilestoreLogThreadDeinit, LogFilestoreLogExitPrintStats);

    SC_ATOMIC_INIT(filestore_open_file_cnt);
    SC_ATOMIC_SET(filestore_open_file_cnt, 0);
    SCLogDebug("registered");
}
예제 #10
0
/**
 * \brief select the queue to output to based on queue lengths.
 *
 * \param tv thread vars
 * \param p packet
 */
void TmqhOutputFlowActivePackets(ThreadVars *tv, Packet *p)
{
    int32_t qid = 0;

    TmqhFlowCtx *ctx = (TmqhFlowCtx *)tv->outctx;

    /* if no flow we use the first queue,
     * should be rare */
    if (p->flow != NULL) {
        qid = SC_ATOMIC_GET(p->flow->autofp_tmqh_flow_qid);
        if (qid == -1) {
            uint16_t i = 0;
            int lowest_id = 0;
            TmqhFlowMode *queues = ctx->queues;
            uint32_t lowest = queues[i].q->len;
            for (i = 1; i < ctx->size; i++) {
                if (queues[i].q->len < lowest) {
                    lowest = queues[i].q->len;
                    lowest_id = i;
                }
            }
            qid = lowest_id;
            (void) SC_ATOMIC_SET(p->flow->autofp_tmqh_flow_qid, lowest_id);
            (void) SC_ATOMIC_ADD(ctx->queues[qid].total_flows, 1);
        }
    } else {
        qid = ctx->last++;

        if (ctx->last == ctx->size)
            ctx->last = 0;
    }
    (void) SC_ATOMIC_ADD(ctx->queues[qid].total_packets, 1);

    PacketQueue *q = ctx->queues[qid].q;
    SCMutexLock(&q->mutex_q);
    PacketEnqueue(q, p);
#ifdef __tile__
    q->cond_q = 1;
#else
    SCCondSignal(&q->cond_q);
#endif
    SCMutexUnlock(&q->mutex_q);

    return;
}
예제 #11
0
/**
 * \brief select the queue to output based on address hash.
 *
 * \param tv thread vars.
 * \param p packet.
 */
void TmqhOutputFlowHash(ThreadVars *tv, Packet *p)
{
    int32_t qid = 0;

    TmqhFlowCtx *ctx = (TmqhFlowCtx *)tv->outctx;

    /* if no flow we use the first queue,
     * should be rare */
    if (p->flow != NULL) {
        qid = SC_ATOMIC_GET(p->flow->autofp_tmqh_flow_qid);
        if (qid == -1) {
#if __WORDSIZE == 64
            uint64_t addr = (uint64_t)p->flow;
#else
            uint32_t addr = (uint32_t)p->flow;
#endif
            addr >>= 7;

            /* we don't have to worry about possible overflow, since
             * ctx->size will be lesser than 2 ** 31 for sure */
            qid = addr % ctx->size;
            (void) SC_ATOMIC_SET(p->flow->autofp_tmqh_flow_qid, qid);
            (void) SC_ATOMIC_ADD(ctx->queues[qid].total_flows, 1);
        }
예제 #12
0
파일: flow-worker.c 프로젝트: norg/suricata
void FlowWorkerReplaceDetectCtx(void *flow_worker, void *detect_ctx)
{
    FlowWorkerThreadData *fw = flow_worker;

    SC_ATOMIC_SET(fw->detect_thread, detect_ctx);
}
예제 #13
0
파일: flow-hash.c 프로젝트: norg/suricata
/** \internal
 *  \brief Get a flow from the hash directly.
 *
 *  Called in conditions where the spare queue is empty and memcap is reached.
 *
 *  Walks the hash until a flow can be freed. Timeouts are disregarded, use_cnt
 *  is adhered to. "flow_prune_idx" atomic int makes sure we don't start at the
 *  top each time since that would clear the top of the hash leading to longer
 *  and longer search times under high pressure (observed).
 *
 *  \param tv thread vars
 *  \param dtv decode thread vars (for flow log api thread data)
 *
 *  \retval f flow or NULL
 */
static Flow *FlowGetUsedFlow(ThreadVars *tv, DecodeThreadVars *dtv)
{
    uint32_t idx = SC_ATOMIC_GET(flow_prune_idx) % flow_config.hash_size;
    uint32_t cnt = flow_config.hash_size;

    while (cnt--) {
        if (++idx >= flow_config.hash_size)
            idx = 0;

        FlowBucket *fb = &flow_hash[idx];

        if (FBLOCK_TRYLOCK(fb) != 0)
            continue;

        Flow *f = fb->tail;
        if (f == NULL) {
            FBLOCK_UNLOCK(fb);
            continue;
        }

        if (FLOWLOCK_TRYWRLOCK(f) != 0) {
            FBLOCK_UNLOCK(fb);
            continue;
        }

        /** never prune a flow that is used by a packet or stream msg
         *  we are currently processing in one of the threads */
        if (SC_ATOMIC_GET(f->use_cnt) > 0) {
            FBLOCK_UNLOCK(fb);
            FLOWLOCK_UNLOCK(f);
            continue;
        }

        /* remove from the hash */
        if (f->hprev != NULL)
            f->hprev->hnext = f->hnext;
        if (f->hnext != NULL)
            f->hnext->hprev = f->hprev;
        if (fb->head == f)
            fb->head = f->hnext;
        if (fb->tail == f)
            fb->tail = f->hprev;

        f->hnext = NULL;
        f->hprev = NULL;
        f->fb = NULL;
        SC_ATOMIC_SET(fb->next_ts, 0);
        FBLOCK_UNLOCK(fb);

        int state = SC_ATOMIC_GET(f->flow_state);
        if (state == FLOW_STATE_NEW)
            f->flow_end_flags |= FLOW_END_FLAG_STATE_NEW;
        else if (state == FLOW_STATE_ESTABLISHED)
            f->flow_end_flags |= FLOW_END_FLAG_STATE_ESTABLISHED;
        else if (state == FLOW_STATE_CLOSED)
            f->flow_end_flags |= FLOW_END_FLAG_STATE_CLOSED;
        else if (state == FLOW_STATE_CAPTURE_BYPASSED)
            f->flow_end_flags |= FLOW_END_FLAG_STATE_BYPASSED;
        else if (state == FLOW_STATE_LOCAL_BYPASSED)
            f->flow_end_flags |= FLOW_END_FLAG_STATE_BYPASSED;

        f->flow_end_flags |= FLOW_END_FLAG_FORCED;

        if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY)
            f->flow_end_flags |= FLOW_END_FLAG_EMERGENCY;

        /* invoke flow log api */
        if (dtv && dtv->output_flow_thread_data)
            (void)OutputFlowLog(tv, dtv->output_flow_thread_data, f);

        FlowClearMemory(f, f->protomap);

        FlowUpdateState(f, FLOW_STATE_NEW);

        FLOWLOCK_UNLOCK(f);

        (void) SC_ATOMIC_ADD(flow_prune_idx, (flow_config.hash_size - cnt));
        return f;
    }

    return NULL;
}
예제 #14
0
파일: ippair.c 프로젝트: bmeeks8/suricata
/** \brief initialize the configuration
 *  \warning Not thread safe */
void IPPairInitConfig(char quiet)
{
    SCLogDebug("initializing ippair engine...");
    if (IPPairStorageSize() > 0)
        g_ippair_size = sizeof(IPPair) + IPPairStorageSize();

    memset(&ippair_config,  0, sizeof(ippair_config));
    //SC_ATOMIC_INIT(flow_flags);
    SC_ATOMIC_INIT(ippair_counter);
    SC_ATOMIC_INIT(ippair_memuse);
    SC_ATOMIC_INIT(ippair_prune_idx);
    SC_ATOMIC_INIT(ippair_config.memcap);
    IPPairQueueInit(&ippair_spare_q);

    /* set defaults */
    ippair_config.hash_rand   = (uint32_t)RandomGet();
    ippair_config.hash_size   = IPPAIR_DEFAULT_HASHSIZE;
    ippair_config.prealloc    = IPPAIR_DEFAULT_PREALLOC;
    SC_ATOMIC_SET(ippair_config.memcap, IPPAIR_DEFAULT_MEMCAP);

    /* Check if we have memcap and hash_size defined at config */
    const char *conf_val;
    uint32_t configval = 0;

    /** set config values for memcap, prealloc and hash_size */
    uint64_t ippair_memcap;
    if ((ConfGet("ippair.memcap", &conf_val)) == 1)
    {
        if (ParseSizeStringU64(conf_val, &ippair_memcap) < 0) {
            SCLogError(SC_ERR_SIZE_PARSE, "Error parsing ippair.memcap "
                       "from conf file - %s.  Killing engine",
                       conf_val);
            exit(EXIT_FAILURE);
        } else {
            SC_ATOMIC_SET(ippair_config.memcap, ippair_memcap);
        }
    }
    if ((ConfGet("ippair.hash-size", &conf_val)) == 1)
    {
        if (ByteExtractStringUint32(&configval, 10, strlen(conf_val),
                                    conf_val) > 0) {
            ippair_config.hash_size = configval;
        }
    }

    if ((ConfGet("ippair.prealloc", &conf_val)) == 1)
    {
        if (ByteExtractStringUint32(&configval, 10, strlen(conf_val),
                                    conf_val) > 0) {
            ippair_config.prealloc = configval;
        } else {
            WarnInvalidConfEntry("ippair.prealloc", "%"PRIu32, ippair_config.prealloc);
        }
    }
    SCLogDebug("IPPair config from suricata.yaml: memcap: %"PRIu64", hash-size: "
               "%"PRIu32", prealloc: %"PRIu32, SC_ATOMIC_GET(ippair_config.memcap),
               ippair_config.hash_size, ippair_config.prealloc);

    /* alloc hash memory */
    uint64_t hash_size = ippair_config.hash_size * sizeof(IPPairHashRow);
    if (!(IPPAIR_CHECK_MEMCAP(hash_size))) {
        SCLogError(SC_ERR_IPPAIR_INIT, "allocating ippair hash failed: "
                "max ippair memcap is smaller than projected hash size. "
                "Memcap: %"PRIu64", Hash table size %"PRIu64". Calculate "
                "total hash size by multiplying \"ippair.hash-size\" with %"PRIuMAX", "
                "which is the hash bucket size.", SC_ATOMIC_GET(ippair_config.memcap), hash_size,
                (uintmax_t)sizeof(IPPairHashRow));
        exit(EXIT_FAILURE);
    }
    ippair_hash = SCMallocAligned(ippair_config.hash_size * sizeof(IPPairHashRow), CLS);
    if (unlikely(ippair_hash == NULL)) {
        SCLogError(SC_ERR_FATAL, "Fatal error encountered in IPPairInitConfig. Exiting...");
        exit(EXIT_FAILURE);
    }
    memset(ippair_hash, 0, ippair_config.hash_size * sizeof(IPPairHashRow));

    uint32_t i = 0;
    for (i = 0; i < ippair_config.hash_size; i++) {
        HRLOCK_INIT(&ippair_hash[i]);
    }
    (void) SC_ATOMIC_ADD(ippair_memuse, (ippair_config.hash_size * sizeof(IPPairHashRow)));

    if (quiet == FALSE) {
        SCLogConfig("allocated %"PRIu64" bytes of memory for the ippair hash... "
                  "%" PRIu32 " buckets of size %" PRIuMAX "",
                  SC_ATOMIC_GET(ippair_memuse), ippair_config.hash_size,
                  (uintmax_t)sizeof(IPPairHashRow));
    }

    /* pre allocate ippairs */
    for (i = 0; i < ippair_config.prealloc; i++) {
        if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
            SCLogError(SC_ERR_IPPAIR_INIT, "preallocating ippairs failed: "
                    "max ippair memcap reached. Memcap %"PRIu64", "
                    "Memuse %"PRIu64".", SC_ATOMIC_GET(ippair_config.memcap),
                    ((uint64_t)SC_ATOMIC_GET(ippair_memuse) + g_ippair_size));
            exit(EXIT_FAILURE);
        }

        IPPair *h = IPPairAlloc();
        if (h == NULL) {
            SCLogError(SC_ERR_IPPAIR_INIT, "preallocating ippair failed: %s", strerror(errno));
            exit(EXIT_FAILURE);
        }
        IPPairEnqueue(&ippair_spare_q,h);
    }

    if (quiet == FALSE) {
        SCLogConfig("preallocated %" PRIu32 " ippairs of size %" PRIu16 "",
                ippair_spare_q.len, g_ippair_size);
        SCLogConfig("ippair memory usage: %"PRIu64" bytes, maximum: %"PRIu64,
                SC_ATOMIC_GET(ippair_memuse), SC_ATOMIC_GET(ippair_config.memcap));
    }

    return;
}