/**
 * \brief Process a chunk of records read from a DAG interface.
 *
 * This function takes a pointer to buffer read from the DAG interface
 * and processes it individual records.
 */
static inline TmEcode ProcessErfDagRecords(ErfDagThreadVars *ewtn, uint8_t *top,
        uint32_t *pkts_read)
{
    SCEnter();

    int err = 0;
    dag_record_t *dr = NULL;
    char *prec = NULL;
    int rlen;
    char hdr_type = 0;
    int processed = 0;
    int packet_q_len = 0;

    *pkts_read = 0;

    while (((top - ewtn->btm) >= dag_record_size) &&
            ((processed + dag_record_size) < 4*1024*1024)) {

        /* Make sure we have at least one packet in the packet pool,
         * to prevent us from alloc'ing packets at line rate. */
        do {
            packet_q_len = PacketPoolSize();
            if (unlikely(packet_q_len == 0)) {
                PacketPoolWait();
            }
        } while (packet_q_len == 0);

        prec = (char *)ewtn->btm;
        dr = (dag_record_t*)prec;
        rlen = ntohs(dr->rlen);
        hdr_type = dr->type;

        /* If we don't have enough data to finsih processing this ERF record
         * return and maybe next time we will.
         */
        if ((top - ewtn->btm) < rlen)
            SCReturnInt(TM_ECODE_OK);

        ewtn->btm += rlen;
        processed += rlen;

        /* Only support ethernet at this time. */
        switch (hdr_type & 0x7f) {
        case TYPE_PAD:
            /* Skip. */
            continue;
        case TYPE_DSM_COLOR_ETH:
        case TYPE_COLOR_ETH:
        case TYPE_COLOR_HASH_ETH:
            /* In these types the color value overwrites the lctr
             * (drop count). */
            break;
        case TYPE_ETH:
            if (dr->lctr) {
                SCPerfCounterIncr(ewtn->drops, ewtn->tv->sc_perf_pca);
            }
            break;
        default:
            SCLogError(SC_ERR_UNIMPLEMENTED,
                       "Processing of DAG record type: %d not implemented.", dr->type);
            SCReturnInt(TM_ECODE_FAILED);
        }

        err = ProcessErfDagRecord(ewtn, prec);
        if (err != TM_ECODE_OK) {
            SCReturnInt(TM_ECODE_FAILED);
        }

        (*pkts_read)++;
    }

    SCReturnInt(TM_ECODE_OK);
}
Exemple #2
0
TmEcode ProcessErfDagRecords(ErfDagThreadVars *ewtn,
                             Packet *p,
                             uint8_t* top,
                             PacketQueue *postpq,
                             uint32_t *pkts_read)
{
    SCEnter();

    int     err = 0;
    dag_record_t* dr = NULL;
    char    *prec = NULL;
    int     rlen;

    *pkts_read = 0;

    while(((top-(ewtn->btm))>=dag_record_size) &&
          ((*pkts_read)<(ewtn->dag_max_read_packets)))
    {
        prec = (char*)ewtn->btm;
        dr = (dag_record_t*)prec;

        rlen = ntohs(dr->rlen);

        if (rlen == 20) {
            rlen = 28;
            SCLogWarning(SC_WARN_ERF_DAG_REC_LEN_CHANGED,
                "Warning, adjusted the length of ERF from 20 to 28 on stream: %d, DAG: %s",
                ewtn->dagstream, ewtn->dagname);
        }

        /* If we don't have enough data to finsih processing this ERF record
         * return and maybe next time we will.
         */
        if ((top-(ewtn->btm)) < rlen)
            SCReturnInt(TM_ECODE_OK);

        p = p ? p : PacketGetFromQueueOrAlloc();

        if (p == NULL) {
            SCLogError(SC_ERR_MEM_ALLOC,
                       "Failed to allocate a Packet on stream: %d, DAG: %s",
                       ewtn->dagstream, ewtn->dagname);
            SCReturnInt(TM_ECODE_FAILED);
        }

        err = ProcessErfDagRecord(ewtn, prec, p);

        if (err != TM_ECODE_OK)
            SCReturnInt(err);

        ewtn->btm += rlen;

        /* XXX/JNM: Hack to get around the fact that the first Packet from
         * Suricata is added explicitly by the Slot code and shouldn't go
         * onto the post queue -- else it is added twice to the next queue.
         */
        if (*pkts_read) {
            PacketEnqueue(postpq, p);
        }

        (*pkts_read)++;

        p = NULL;
    }

    SCReturnInt(TM_ECODE_OK);
}