/** * \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); }
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); }