suricata
source-erf-dag.c
Go to the documentation of this file.
1 /* Copyright (C) 2010-2014 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Endace Technology Limited.
22  * \author Jason MacLulich <jason.maclulich@endace.com>
23  *
24  * Support for reading ERF records from a DAG card.
25  *
26  * Only ethernet supported at this time.
27  */
28 
29 #include "suricata-common.h"
30 #include "suricata.h"
31 #include "tm-threads.h"
32 
33 #include "util-privs.h"
34 #include "util-device.h"
35 #include "tmqh-packetpool.h"
36 #include "source-erf-dag.h"
37 
38 #ifndef HAVE_DAG
39 
40 TmEcode NoErfDagSupportExit(ThreadVars *, const void *, void **);
41 
42 void
44 {
45  tmm_modules[TMM_RECEIVEERFDAG].name = "ReceiveErfDag";
46  tmm_modules[TMM_RECEIVEERFDAG].ThreadInit = NoErfDagSupportExit;
53 }
54 
55 void
57 {
58  tmm_modules[TMM_DECODEERFDAG].name = "DecodeErfDag";
59  tmm_modules[TMM_DECODEERFDAG].ThreadInit = NoErfDagSupportExit;
66 }
67 
68 TmEcode
69 NoErfDagSupportExit(ThreadVars *tv, const void *initdata, void **data)
70 {
72  "Error creating thread %s: you do not have support for DAG cards "
73  "enabled please recompile with --enable-dag", tv->name);
74  exit(EXIT_FAILURE);
75 }
76 
77 #else /* Implied we do have DAG support */
78 
79 #include <dagapi.h>
80 
81 /* Minimum amount of data to read from the DAG at a time. */
82 #define MINDATA 32768
83 
84 /* Maximum time (us) to wait for MINDATA to be read. */
85 #define MAXWAIT 20000
86 
87 /* Poll interval in microseconds. */
88 #define POLL_INTERVAL 1000;
89 
90 /* Number of bytes per loop to process before fetching more data. */
91 #define BYTES_PER_LOOP (4 * 1024 * 1024) /* 4 MB */
92 
93 extern int max_pending_packets;
94 
95 typedef struct ErfDagThreadVars_ {
98 
99  int dagfd;
101  char dagname[DAGNAME_BUFSIZE];
102 
103  struct timeval maxwait, poll; /* Could possibly be made static */
104 
106 
107  uint64_t bytes;
108  uint16_t packets;
109  uint16_t drops;
110 
111  /* Current location in the DAG stream input buffer.
112  */
113  uint8_t *top;
114  uint8_t *btm;
115 
117 
118 static inline TmEcode ProcessErfDagRecords(ErfDagThreadVars *ewtn, uint8_t *top,
119  uint32_t *pkts_read);
120 static inline TmEcode ProcessErfDagRecord(ErfDagThreadVars *ewtn, char *prec);
121 TmEcode ReceiveErfDagLoop(ThreadVars *, void *data, void *slot);
122 TmEcode ReceiveErfDagThreadInit(ThreadVars *, void *, void **);
125 TmEcode DecodeErfDagThreadInit(ThreadVars *, void *, void **);
128  PacketQueue *);
129 void ReceiveErfDagCloseStream(int dagfd, int stream);
130 
131 /**
132  * \brief Register the ERF file receiver (reader) module.
133  */
134 void
136 {
137  tmm_modules[TMM_RECEIVEERFDAG].name = "ReceiveErfDag";
148 }
149 
150 /**
151  * \brief Register the ERF file decoder module.
152  */
153 void
155 {
156  tmm_modules[TMM_DECODEERFDAG].name = "DecodeErfDag";
164 }
165 
166 /**
167  * \brief Initialize the ERF receiver thread, generate a single
168  * ErfDagThreadVar structure for each thread, this will
169  * contain a DAG file descriptor which is read when the
170  * thread executes.
171  *
172  * \param tv Thread variable to ThreadVars
173  * \param initdata Initial data to the interface passed from the user,
174  * this is processed by the user.
175  *
176  * We assume that we have only a single name for the DAG
177  * interface.
178  *
179  * \param data data pointer gets populated with
180  *
181  */
182 TmEcode
183 ReceiveErfDagThreadInit(ThreadVars *tv, void *initdata, void **data)
184 {
185  SCEnter();
186  int stream_count = 0;
187 
188  if (initdata == NULL) {
190  "Error: No DAG interface provided.");
192  }
193 
194  ErfDagThreadVars *ewtn = SCMalloc(sizeof(ErfDagThreadVars));
195  if (unlikely(ewtn == NULL)) {
197  "Failed to allocate memory for ERF DAG thread vars.");
198  exit(EXIT_FAILURE);
199  }
200 
201  memset(ewtn, 0, sizeof(*ewtn));
202 
203  /* dag_parse_name will return a DAG device name and stream number
204  * to open for this thread.
205  */
206  if (dag_parse_name(initdata, ewtn->dagname, DAGNAME_BUFSIZE,
207  &ewtn->dagstream) < 0) {
209  "Failed to parse DAG interface: %s",
210  (char*)initdata);
211  SCFree(ewtn);
212  exit(EXIT_FAILURE);
213  }
214 
215  ewtn->livedev = LiveGetDevice(initdata);
216  if (ewtn->livedev == NULL) {
217  SCLogError(SC_ERR_INVALID_VALUE, "Unable to get %s live device",
218  (char *)initdata);
219  SCFree(ewtn);
221  }
222 
223  SCLogInfo("Opening DAG: %s on stream: %d for processing",
224  ewtn->dagname, ewtn->dagstream);
225 
226  if ((ewtn->dagfd = dag_open(ewtn->dagname)) < 0) {
227  SCLogError(SC_ERR_ERF_DAG_OPEN_FAILED, "Failed to open DAG: %s",
228  ewtn->dagname);
229  SCFree(ewtn);
231  }
232 
233  /* Check to make sure the card has enough available streams to
234  * support reading from the one specified.
235  */
236  if ((stream_count = dag_rx_get_stream_count(ewtn->dagfd)) < 0) {
238  "Failed to open stream: %d, DAG: %s, could not query stream count",
239  ewtn->dagstream, ewtn->dagname);
240  SCFree(ewtn);
242  }
243 
244  /* Check to make sure we have enough rx streams to open the stream
245  * the user is asking for.
246  */
247  if (ewtn->dagstream > stream_count * 2) {
249  "Failed to open stream: %d, DAG: %s, insufficient streams: %d",
250  ewtn->dagstream, ewtn->dagname, stream_count);
251  SCFree(ewtn);
253  }
254 
255  /* If we are transmitting into a soft DAG card then set the stream
256  * to act in reverse mode.
257  */
258  if (0 != (ewtn->dagstream & 0x01)) {
259  /* Setting reverse mode for using with soft dag from daemon side */
260  if (dag_set_mode(ewtn->dagfd, ewtn->dagstream, DAG_REVERSE_MODE)) {
262  "Failed to set mode to DAG_REVERSE_MODE on stream: %d, DAG: %s",
263  ewtn->dagstream, ewtn->dagname);
264  SCFree(ewtn);
266  }
267  }
268 
269  if (dag_attach_stream(ewtn->dagfd, ewtn->dagstream, 0, 0) < 0) {
271  "Failed to open DAG stream: %d, DAG: %s",
272  ewtn->dagstream, ewtn->dagname);
273  SCFree(ewtn);
275  }
276 
277  if (dag_start_stream(ewtn->dagfd, ewtn->dagstream) < 0) {
279  "Failed to start DAG stream: %d, DAG: %s",
280  ewtn->dagstream, ewtn->dagname);
281  SCFree(ewtn);
283  }
284 
285  SCLogInfo("Attached and started stream: %d on DAG: %s",
286  ewtn->dagstream, ewtn->dagname);
287 
288  /*
289  * Initialise DAG Polling parameters.
290  */
291  timerclear(&ewtn->maxwait);
292  ewtn->maxwait.tv_usec = MAXWAIT;
293  timerclear(&ewtn->poll);
294  ewtn->poll.tv_usec = POLL_INTERVAL;
295 
296  /* 32kB minimum data to return -- we still restrict the number of
297  * pkts that are processed to a maximum of dag_max_read_packets.
298  */
299  if (dag_set_stream_poll(ewtn->dagfd, ewtn->dagstream, MINDATA,
300  &(ewtn->maxwait), &(ewtn->poll)) < 0) {
302  "Failed to set poll parameters for stream: %d, DAG: %s",
303  ewtn->dagstream, ewtn->dagname);
304  SCFree(ewtn);
306  }
307 
308  ewtn->packets = StatsRegisterCounter("capture.dag_packets", tv);
309  ewtn->drops = StatsRegisterCounter("capture.dag_drops", tv);
310 
311  ewtn->tv = tv;
312  *data = (void *)ewtn;
313 
314  SCLogInfo("Starting processing packets from stream: %d on DAG: %s",
315  ewtn->dagstream, ewtn->dagname);
316 
318 }
319 
320 /**
321  * \brief Receives packets from a DAG interface.
322  *
323  * \param tv pointer to ThreadVars
324  * \param data pointer to ErfDagThreadVars
325  * \param slot slot containing task information
326  *
327  * \retval TM_ECODE_OK on success
328  * \retval TM_ECODE_FAILED on failure
329  */
330 TmEcode
331 ReceiveErfDagLoop(ThreadVars *tv, void *data, void *slot)
332 {
333  SCEnter();
334 
335  ErfDagThreadVars *dtv = (ErfDagThreadVars *)data;
336  uint32_t diff = 0;
337  int err;
338  uint8_t *top = NULL;
339  uint32_t pkts_read = 0;
340  TmSlot *s = (TmSlot *)slot;
341 
342  dtv->slot = s->slot_next;
343 
344  while (1) {
347  }
348 
349  top = dag_advance_stream(dtv->dagfd, dtv->dagstream, &(dtv->btm));
350  if (top == NULL) {
351  if (errno == EAGAIN) {
352  if (dtv->dagstream & 0x1) {
353  usleep(10 * 1000);
354  dtv->btm = dtv->top;
355  }
356  continue;
357  } else {
359  "Failed to read from stream: %d, DAG: %s when "
360  "using dag_advance_stream",
361  dtv->dagstream, dtv->dagname);
363  }
364  }
365 
366  diff = top - dtv->btm;
367  if (diff == 0) {
368  continue;
369  }
370 
371  assert(diff >= dag_record_size);
372 
373  err = ProcessErfDagRecords(dtv, top, &pkts_read);
374 
375  if (err == TM_ECODE_FAILED) {
377  "Failed to read from stream: %d, DAG: %s",
378  dtv->dagstream, dtv->dagname);
381  }
382 
384 
385  SCLogDebug("Read %d records from stream: %d, DAG: %s",
386  pkts_read, dtv->dagstream, dtv->dagname);
387  }
388 
390 }
391 
392 /**
393  * \brief Process a chunk of records read from a DAG interface.
394  *
395  * This function takes a pointer to buffer read from the DAG interface
396  * and processes it individual records.
397  */
398 static inline TmEcode
399 ProcessErfDagRecords(ErfDagThreadVars *ewtn, uint8_t *top, uint32_t *pkts_read)
400 {
401  SCEnter();
402 
403  int err = 0;
404  dag_record_t *dr = NULL;
405  char *prec = NULL;
406  int rlen;
407  char hdr_type = 0;
408  int processed = 0;
409 
410  *pkts_read = 0;
411 
412  while (((top - ewtn->btm) >= dag_record_size) &&
413  ((processed + dag_record_size) < BYTES_PER_LOOP)) {
414 
415  /* Make sure we have at least one packet in the packet pool,
416  * to prevent us from alloc'ing packets at line rate. */
417  PacketPoolWait();
418 
419  prec = (char *)ewtn->btm;
420  dr = (dag_record_t*)prec;
421  rlen = SCNtohs(dr->rlen);
422  hdr_type = dr->type;
423 
424  /* If we don't have enough data to finish processing this ERF
425  * record return and maybe next time we will.
426  */
427  if ((top - ewtn->btm) < rlen)
429 
430  ewtn->btm += rlen;
431  processed += rlen;
432 
433  /* Only support ethernet at this time. */
434  switch (hdr_type & 0x7f) {
435  case TYPE_PAD:
436  /* Skip. */
437  continue;
438  case TYPE_DSM_COLOR_ETH:
439  case TYPE_COLOR_ETH:
440  case TYPE_COLOR_HASH_ETH:
441  /* In these types the color value overwrites the lctr
442  * (drop count). */
443  break;
444  case TYPE_ETH:
445  if (dr->lctr) {
446  StatsAddUI64(ewtn->tv, ewtn->drops, SCNtohs(dr->lctr));
447  }
448  break;
449  default:
451  "Processing of DAG record type: %d not implemented.", dr->type);
453  }
454 
455  err = ProcessErfDagRecord(ewtn, prec);
456  if (err != TM_ECODE_OK) {
458  }
459 
460  (*pkts_read)++;
461  }
462 
464 }
465 
466 /**
467  * \brief Process a DAG record into a TM packet buffer.
468  * \param prec pointer to a DAG record.
469  * \param
470  */
471 static inline TmEcode
472 ProcessErfDagRecord(ErfDagThreadVars *ewtn, char *prec)
473 {
474  SCEnter();
475 
476  int wlen = 0;
477  int rlen = 0;
478  int hdr_num = 0;
479  char hdr_type = 0;
480  dag_record_t *dr = (dag_record_t*)prec;
481  erf_payload_t *pload;
482  Packet *p;
483 
484  hdr_type = dr->type;
485  wlen = SCNtohs(dr->wlen);
486  rlen = SCNtohs(dr->rlen);
487 
488  /* count extension headers */
489  while (hdr_type & 0x80) {
490  if (rlen < (dag_record_size + (hdr_num * 8))) {
492  "Insufficient captured packet length.");
494  }
495  hdr_type = prec[(dag_record_size + (hdr_num * 8))];
496  hdr_num++;
497  }
498 
499  /* Check that the whole frame was captured */
500  if (rlen < (dag_record_size + (8 * hdr_num) + 2 + wlen)) {
501  SCLogInfo("Incomplete frame captured.");
503  }
504 
505  /* skip over extension headers */
506  pload = (erf_payload_t *)(prec + dag_record_size + (8 * hdr_num));
507 
509  if (p == NULL) {
511  "Failed to allocate a Packet on stream: %d, DAG: %s",
512  ewtn->dagstream, ewtn->dagname);
514  }
516 
517  SET_PKT_LEN(p, wlen);
519 
520  /* Take into account for link type Ethernet ETH frame starts
521  * after ther ERF header + pad.
522  */
523  if (unlikely(PacketCopyData(p, pload->eth.dst, GET_PKT_LEN(p)))) {
524  TmqhOutputPacketpool(ewtn->tv, p);
526  }
527 
528  /* Convert ERF time to timeval - from libpcap. */
529  uint64_t ts = dr->ts;
530  p->ts.tv_sec = ts >> 32;
531  ts = (ts & 0xffffffffULL) * 1000000;
532  ts += 0x80000000; /* rounding */
533  p->ts.tv_usec = ts >> 32;
534  if (p->ts.tv_usec >= 1000000) {
535  p->ts.tv_usec -= 1000000;
536  p->ts.tv_sec++;
537  }
538 
539  StatsIncr(ewtn->tv, ewtn->packets);
540  ewtn->bytes += wlen;
541 
542  if (TmThreadsSlotProcessPkt(ewtn->tv, ewtn->slot, p) != TM_ECODE_OK) {
543  TmqhOutputPacketpool(ewtn->tv, p);
545  }
546 
548 }
549 
550 /**
551  * \brief Print some stats to the log at program exit.
552  *
553  * \param tv Pointer to ThreadVars.
554  * \param data Pointer to data, ErfFileThreadVars.
555  */
556 void
558 {
559  ErfDagThreadVars *ewtn = (ErfDagThreadVars *)data;
560 
561  (void)SC_ATOMIC_SET(ewtn->livedev->pkts,
563  (void)SC_ATOMIC_SET(ewtn->livedev->drop,
564  StatsGetLocalCounterValue(tv, ewtn->drops));
565 
566  SCLogInfo("Stream: %d; Bytes: %"PRIu64"; Packets: %"PRIu64
567  "; Drops: %"PRIu64,
568  ewtn->dagstream,
569  ewtn->bytes,
571  StatsGetLocalCounterValue(tv, ewtn->drops));
572 }
573 
574 /**
575  * \brief Deinitializes the DAG card.
576  * \param tv pointer to ThreadVars
577  * \param data pointer that gets cast into PcapThreadVars for ptv
578  */
579 TmEcode
581 {
582  SCEnter();
583 
584  ErfDagThreadVars *ewtn = (ErfDagThreadVars *)data;
585 
587 
589 }
590 
591 void
593 {
594  dag_stop_stream(dagfd, stream);
595  dag_detach_stream(dagfd, stream);
596  dag_close(dagfd);
597 }
598 
599 /** Decode ErfDag */
600 
601 /**
602  * \brief This function passes off to link type decoders.
603  *
604  * DecodeErfDag reads packets from the PacketQueue and passes
605  * them off to the proper link type decoder.
606  *
607  * \param t pointer to ThreadVars
608  * \param p pointer to the current packet
609  * \param data pointer that gets cast into PcapThreadVars for ptv
610  * \param pq pointer to the current PacketQueue
611  */
612 TmEcode
614  PacketQueue *postpq)
615 {
616  SCEnter();
617  DecodeThreadVars *dtv = (DecodeThreadVars *)data;
618 
619  /* XXX HACK: flow timeout can call us for injected pseudo packets
620  * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */
621  if (p->flags & PKT_PSEUDO_STREAM_END)
622  return TM_ECODE_OK;
623 
624  /* update counters */
625  DecodeUpdatePacketCounters(tv, dtv, p);
626 
627  /* call the decoder */
628  switch(p->datalink) {
629  case LINKTYPE_ETHERNET:
630  DecodeEthernet(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
631  break;
632  default:
634  "Error: datalink type %" PRId32
635  " not yet supported in module DecodeErfDag",
636  p->datalink);
637  break;
638  }
639 
640  PacketDecodeFinalize(tv, dtv, p);
641 
643 }
644 
645 TmEcode
646 DecodeErfDagThreadInit(ThreadVars *tv, void *initdata, void **data)
647 {
648  SCEnter();
649  DecodeThreadVars *dtv = NULL;
650 
651  dtv = DecodeThreadVarsAlloc(tv);
652 
653  if (dtv == NULL)
655 
657 
658  *data = (void *)dtv;
659 
661 }
662 
663 TmEcode
665 {
666  if (data != NULL)
667  DecodeThreadVarsFree(tv, data);
669 }
670 
671 #endif /* HAVE_DAG */
#define TM_FLAG_DECODE_TM
Definition: tm-modules.h:32
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition: decode.c:605
LiveDevice * livedev
#define SCLogDebug(...)
Definition: util-debug.h:335
uint8_t cap_flags
Definition: tm-modules.h:67
uint8_t flags
Definition: tm-modules.h:70
#define SET_PKT_LEN(p, len)
Definition: decode.h:229
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition: decode.c:115
#define unlikely(expr)
Definition: util-optimize.h:35
uint8_t type
Definition: decode.h:418
TmEcode(* Func)(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *)
Definition: tm-modules.h:52
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition: decode.c:465
Address dst
Definition: decode.h:413
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:201
#define SC_CAP_NET_ADMIN
Definition: util-privs.h:31
Packet * PacketGetFromQueueOrAlloc(void)
Get a packet. We try to get a packet from the packetpool first, but if that is empty we alloc a packe...
Definition: decode.c:177
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-modules.h:54
uint16_t rlen
ThreadVars * tv
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1132
#define POLL_INTERVAL
#define TM_FLAG_RECEIVE_TM
Definition: tm-modules.h:31
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition: tm-modules.h:57
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition: counters.c:931
char dagname[DAGNAME_BUFSIZE]
#define SURICATA_STOP
Definition: suricata.h:95
TmEcode DecodeErfDag(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *)
This function passes off to link type decoders.
#define MINDATA
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
int max_pending_packets
Definition: suricata.c:215
#define MAXWAIT
int datalink
Definition: decode.h:574
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
Structure to hold thread specific data for all decode modules.
Definition: decode.h:632
void(* RegisterTests)(void)
Definition: tm-modules.h:65
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:49
#define SCEnter(...)
Definition: util-debug.h:337
void TmModuleReceiveErfDagRegister(void)
Register the ERF file receiver (reader) module.
struct TmSlot_ * slot_next
Definition: tm-threads.h:87
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:163
void ReceiveErfDagThreadExitStats(ThreadVars *, void *)
Print some stats to the log at program exit.
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1091
void ReceiveErfDagCloseStream(int dagfd, int stream)
TmEcode DecodeErfDagThreadInit(ThreadVars *, void *, void **)
#define SCReturnInt(x)
Definition: util-debug.h:341
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
Definition: util-device.c:236
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-modules.h:48
struct timeval maxwait poll
void PacketPoolWait(void)
const char * name
Definition: tm-modules.h:44
void TmModuleDecodeErfDagRegister(void)
Register the ERF file decoder module.
#define SCMalloc(a)
Definition: util-mem.h:222
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:207
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
#define SCFree(a)
Definition: util-mem.h:322
#define SCNtohs(x)
#define BYTES_PER_LOOP
TmEcode ReceiveErfDagThreadInit(ThreadVars *, void *, void **)
Initialize the ERF receiver thread, generate a single ErfDagThreadVar structure for each thread...
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.h:73
uint16_t wlen
uint64_t ts
TmEcode DecodeErfDagThreadDeinit(ThreadVars *tv, void *data)
#define StatsSyncCountersIfSignalled(tv)
Definition: counters.h:136
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:47
#define GET_PKT_DATA(p)
Definition: decode.h:225
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition: decode.c:571
char name[16]
Definition: threadvars.h:59
#define LINKTYPE_ETHERNET
Definition: decode.h:1070
Per thread variable structure.
Definition: threadvars.h:57
struct timeval ts
Definition: decode.h:451
#define GET_PKT_LEN(p)
Definition: decode.h:224
uint32_t flags
Definition: decode.h:443
void StatsAddUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Adds a value of type uint64_t to the local counter.
Definition: counters.c:142
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition: decode.c:624
TmEcode ReceiveErfDagLoop(ThreadVars *, void *data, void *slot)
Receives packets from a DAG interface.
struct ErfDagThreadVars_ ErfDagThreadVars
TmEcode ReceiveErfDagThreadDeinit(ThreadVars *, void *)
Deinitializes the DAG card.
int PacketCopyData(Packet *p, uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:259
uint64_t StatsGetLocalCounterValue(ThreadVars *tv, uint16_t id)
Get the value of the local copy of the counter that hold this id.
Definition: counters.c:1232