suricata
source-netmap.c
Go to the documentation of this file.
1 /* Copyright (C) 2011-2022 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 * \defgroup netmap Netmap running mode
20 *
21 * @{
22 */
23 
24 /**
25  * \file
26  *
27  * \author Aleksey Katargin <gureedo@gmail.com>
28  * \author Victor Julien <victor@inliniac.net>
29  * \author Bill Meeks <billmeeks8@gmail.com>
30  *
31  * Netmap socket acquisition support
32  *
33  * Many thanks to Luigi Rizzo for guidance and support.
34  *
35  */
36 
37 #include "suricata.h"
38 #include "suricata-common.h"
39 #include "tm-threads.h"
40 #include "packet.h"
41 #include "util-bpf.h"
42 #include "util-privs.h"
43 #include "util-validate.h"
44 #include "util-datalink.h"
45 #include "util-device-private.h"
46 
47 #include "source-netmap.h"
48 
49 #ifdef HAVE_NETMAP
50 
51 #define NETMAP_WITH_LIBS
52 #ifdef DEBUG
53 #define DEBUG_NETMAP_USER
54 #endif
55 
56 #include <net/netmap_user.h>
57 #include <libnetmap.h>
58 
59 #endif /* HAVE_NETMAP */
60 
61 #include "util-ioctl.h"
62 
63 #ifndef HAVE_NETMAP
64 
65 /**
66 * \brief this function prints an error message and exits.
67 */
68 static TmEcode NoNetmapSupportExit(ThreadVars *tv, const void *initdata, void **data)
69 {
70  FatalError("Error creating thread %s: Netmap is not enabled. "
71  "Make sure to pass --enable-netmap to configure when building.",
72  tv->name);
73 }
74 
76 {
77  tmm_modules[TMM_RECEIVENETMAP].name = "ReceiveNetmap";
78  tmm_modules[TMM_RECEIVENETMAP].ThreadInit = NoNetmapSupportExit;
80 }
81 
82 /**
83 * \brief Registration Function for DecodeNetmap.
84 */
86 {
87  tmm_modules[TMM_DECODENETMAP].name = "DecodeNetmap";
88  tmm_modules[TMM_DECODENETMAP].ThreadInit = NoNetmapSupportExit;
90 }
91 
92 #else /* We have NETMAP support */
93 
94 #include "action-globals.h"
95 
96 #define POLL_TIMEOUT 100
97 
98 #if defined(__linux__)
99 #define POLL_EVENTS (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL)
100 
101 #ifndef IFF_PPROMISC
102 #define IFF_PPROMISC IFF_PROMISC
103 #endif
104 
105 #else
106 #define POLL_EVENTS (POLLHUP|POLLERR|POLLNVAL)
107 #endif
108 
109 enum { NETMAP_FLAG_ZERO_COPY = 1, NETMAP_FLAG_EXCL_RING_ACCESS = 2 };
110 
111 /**
112  * \brief Netmap device instance. Each ring for each device gets its own
113  * device.
114  */
115 typedef struct NetmapDevice_
116 {
117  struct nmport_d *nmd;
118  unsigned int ref;
119  SC_ATOMIC_DECLARE(unsigned int, threads_run);
120  TAILQ_ENTRY(NetmapDevice_) next;
121  // actual ifname can only be 16, but we store a bit more,
122  // like the options string and a 'netmap:' prefix.
123  char ifname[32];
124  int ring;
125  int direction; // 0 rx, 1 tx
126 
127  // autofp: Used to lock a destination ring while we are sending data.
128  SCMutex netmap_dev_lock;
129 } NetmapDevice;
130 
131 /**
132  * \brief Module thread local variables.
133  */
134 typedef struct NetmapThreadVars_
135 {
136  /* receive interface */
137  NetmapDevice *ifsrc;
138  /* dst interface for IPS mode */
139  NetmapDevice *ifdst;
140 
141  int flags;
142  struct bpf_program bpf_prog;
143 
144  /* suricata internals */
145  TmSlot *slot;
146  ThreadVars *tv;
147  LiveDevice *livedev;
148 
149  /* copy from config */
150  int copy_mode;
151  ChecksumValidationMode checksum_mode;
152 
153  /* buffer used to join a packet that is split across several netmap slots */
154  uint8_t *coalesce_buf;
155  uint32_t coalesce_size;
156 
157  /* counters */
158  uint64_t pkts;
159  uint64_t bytes;
160  uint64_t drops;
161  StatsCounterId capture_kernel_packets;
162  StatsCounterId capture_kernel_drops;
163 } NetmapThreadVars;
164 
165 typedef TAILQ_HEAD(NetmapDeviceList_, NetmapDevice_) NetmapDeviceList;
166 
167 static NetmapDeviceList netmap_devlist = TAILQ_HEAD_INITIALIZER(netmap_devlist);
168 static SCMutex netmap_devlist_lock = SCMUTEX_INITIALIZER;
169 
170 /** \brief get RSS RX-queue count
171  * \retval rx_rings RSS RX queue count or 0 on error
172  */
173 int NetmapGetRSSCount(const char *ifname)
174 {
175  struct nmreq_port_info_get req;
176  struct nmreq_header hdr;
177  int rx_rings = 0;
178 
179  /* we need the base interface name to query queues */
180  char base_name[IFNAMSIZ];
181  strlcpy(base_name, ifname, sizeof(base_name));
182  if (strlen(base_name) > 0 &&
183  (base_name[strlen(base_name) - 1] == '^' || base_name[strlen(base_name) - 1] == '*')) {
184  base_name[strlen(base_name) - 1] = '\0';
185  }
186 
187  SCMutexLock(&netmap_devlist_lock);
188 
189  /* open netmap device */
190  int fd = open("/dev/netmap", O_RDWR);
191  if (fd == -1) {
192  SCLogError("%s: open netmap device failed: %s", ifname, strerror(errno));
193  goto error_open;
194  }
195 
196  /* query netmap interface info for ring count */
197  memset(&req, 0, sizeof(req));
198  memset(&hdr, 0, sizeof(hdr));
199  hdr.nr_version = NETMAP_API;
200  hdr.nr_reqtype = NETMAP_REQ_PORT_INFO_GET;
201  hdr.nr_body = (uintptr_t)&req;
202  strlcpy(hdr.nr_name, base_name, sizeof(hdr.nr_name));
203 
204  if (ioctl(fd, NIOCCTRL, &hdr) != 0) {
205  SCLogError(
206  "Query of netmap HW rings count on %s failed; error: %s", ifname, strerror(errno));
207  goto error_fd;
208  };
209 
210  /* return RX rings count if it equals TX rings count */
211  if (req.nr_rx_rings == req.nr_tx_rings) {
212  rx_rings = req.nr_rx_rings;
213  }
214 
215 error_fd:
216  close(fd);
217 error_open:
218  SCMutexUnlock(&netmap_devlist_lock);
219  return rx_rings;
220 }
221 
222 static void NetmapDestroyDevice(NetmapDevice *pdev)
223 {
224  nmport_close(pdev->nmd);
225  SCMutexDestroy(&pdev->netmap_dev_lock);
226  SCFree(pdev);
227 }
228 
229 /**
230  * \brief Close or dereference netmap device instance.
231  * \param dev Netmap device instance.
232  * \return Zero on success.
233  */
234 static int NetmapClose(NetmapDevice *dev)
235 {
236  NetmapDevice *pdev, *tmp;
237 
238  SCMutexLock(&netmap_devlist_lock);
239 
240  TAILQ_FOREACH_SAFE (pdev, &netmap_devlist, next, tmp) {
241  if (pdev == dev) {
242  pdev->ref--;
243  if (!pdev->ref) {
244  NetmapDestroyDevice(pdev);
245  }
246  SCMutexUnlock(&netmap_devlist_lock);
247  return 0;
248  }
249  }
250 
251  SCMutexUnlock(&netmap_devlist_lock);
252  return -1;
253 }
254 
255 /**
256  * \brief Close all open netmap device instances.
257  */
258 static void NetmapCloseAll(void)
259 {
260  NetmapDevice *pdev, *tmp;
261 
262  SCMutexLock(&netmap_devlist_lock);
263 
264  TAILQ_FOREACH_SAFE (pdev, &netmap_devlist, next, tmp) {
265  NetmapDestroyDevice(pdev);
266  }
267 
268  SCMutexUnlock(&netmap_devlist_lock);
269 }
270 
271 /**
272  * \brief Open interface in netmap mode.
273  * \param ifname Interface name.
274  * \param promisc Enable promiscuous mode.
275  * \param dev Pointer to requested netmap device instance.
276  * \param verbose Verbose error logging.
277  * \param read Indicates direction: RX or TX
278  * \param zerocopy 1 if zerocopy access requested
279  * \param soft Use Host stack (software) interface
280  * \return Zero on success.
281  */
282 static int NetmapOpen(NetmapIfaceSettings *ns, NetmapDevice **pdevice, int verbose, int read,
283  bool zerocopy, bool soft)
284 {
285  SCEnter();
286  SCLogDebug("ifname %s", ns->iface);
287 
288  char base_name[IFNAMSIZ];
289  strlcpy(base_name, ns->iface, sizeof(base_name));
290  if (strlen(base_name) > 0 &&
291  (base_name[strlen(base_name)-1] == '^' ||
292  base_name[strlen(base_name)-1] == '*'))
293  {
294  base_name[strlen(base_name)-1] = '\0';
295  }
296 
297  if (ns->real) {
298  /* check interface is up */
299  int if_flags = GetIfaceFlags(base_name);
300  if (if_flags == -1) {
301  if (verbose) {
302  SCLogError("%s: cannot access network interface: %s", base_name, ns->iface);
303  }
304  goto error;
305  }
306 
307  /* bring iface up if it is down */
308  if ((if_flags & IFF_UP) == 0) {
309  SCLogError("%s: interface is down", base_name);
310  goto error;
311  }
312  /* if needed, try to set iface in promisc mode */
313  if (ns->promisc && (if_flags & (IFF_PROMISC|IFF_PPROMISC)) == 0) {
314  if_flags |= IFF_PPROMISC;
315  SetIfaceFlags(base_name, if_flags); // TODO reset at exit
316  // TODO move to parse config?
317  }
318  }
319  NetmapDevice *pdev = NULL, *spdev = NULL;
320  pdev = SCCalloc(1, sizeof(*pdev));
321  if (unlikely(pdev == NULL)) {
322  SCLogError("%s: memory allocation failed", base_name);
323  goto error;
324  }
325  SC_ATOMIC_INIT(pdev->threads_run);
326 
327  SCMutexLock(&netmap_devlist_lock);
328 
329  const int direction = (read != 1);
330  int ring = 0;
331  /* Search for interface in our already opened list. */
332  /* We will find it when opening multiple rings on */
333  /* the device when it exposes multiple RSS queues. */
334  TAILQ_FOREACH(spdev, &netmap_devlist, next) {
335  SCLogDebug("spdev %s", spdev->ifname);
336  if (direction == spdev->direction && strcmp(ns->iface, spdev->ifname) == 0) {
337  ring = spdev->ring + 1;
338  }
339  }
340  SCLogDebug("netmap/%s: using ring %d", ns->iface, ring);
341 
342  const char *opt_R = "R";
343  const char *opt_T = "T";
344  const char *opt_x = "x"; // not for IPS
345  const char *opt_z = "z"; // zero copy, not for IPS
346 
347  /* assemble options string */
348  char optstr[16];
349  if (ns->ips)
350  opt_x = "";
351  // z seems to not play well with multiple opens of a real dev on linux
352  opt_z = "";
353 
354  /*
355  * How netmap endpoint names are selected:
356  *
357  * The following logic within the "retry" loop builds endpoint names.
358  *
359  * IPS Mode:
360  * There are two endpoints: one hardware NIC and either a hardware NIC or host stack "NIC".
361  *
362  * IDS Mode:
363  * One endpoint -- usually a hardware NIC.
364  *
365  * IPS mode -- with one endpoint a host stack "NIC":
366  * When using multiple rings/threads, then the open of the initial Ring 0 MUST
367  * instruct netmap to open multiple Host Stack rings (as the default is to open only a single
368  * pair). This is also critical for the HW NIC endpoint. This is done by adding
369  * “@conf:host-rings=x” suffix option (where “x” is the number of host rings desired)
370  * to BOTH endpoint nmport_open_desc() calls for ring 0 (hardware and host stack).
371  * For subsequent additional ring open calls, omit the suffix option specifying host ring count.
372  *
373  * IPS mode -- both endpoints are hardware NICs:
374  * Do NOT pass any suffix option (even for Ring 0). You do not need to tell netmap how many
375  * rings, because it already knows the correct value from the NIC driver itself. Specifying a
376  * desired ring count when both ends are Hardware NICs confuses netmap, and it seems to default
377  * to using only a single hardware ring. In this scenario, specify only the specific ring number
378  * being opened.
379  */
380 
381  // loop to retry opening if unsupported options are used
382 retry:
383  snprintf(optstr, sizeof(optstr), "%s%s%s", opt_z, opt_x, direction == 0 ? opt_R : opt_T);
384 
385  char devname[128];
386  if (strncmp(ns->iface, "netmap:", 7) == 0) {
387  snprintf(devname, sizeof(devname), "%s}%d%s%s",
388  ns->iface, ring, strlen(optstr) ? "/" : "", optstr);
389  } else if (strlen(ns->iface) > 5 && strncmp(ns->iface, "vale", 4) == 0 && isdigit(ns->iface[4])) {
390  snprintf(devname, sizeof(devname), "%s", ns->iface);
391  } else if (ring == 0 && ns->threads == 1) {
392  /* just a single thread and ring, so don't use ring param */
393  snprintf(devname, sizeof(devname), "netmap:%s%s%s",
394  ns->iface, strlen(optstr) ? "/" : "", optstr);
395  SCLogDebug("device with %s-ring enabled (devname): %s", soft ? "SW" : "HW", devname);
396  } else {
397  /* Going to be using multiple threads and rings */
398  if (ns->sw_ring) {
399  /* Opening a host stack interface */
400  if (ring == 0) {
401  /* Ring 0, so tell netmap how many host rings we want created */
402  snprintf(devname, sizeof(devname), "netmap:%s%d%s%s@conf:host-rings=%d", ns->iface,
403  ring, strlen(optstr) ? "/" : "", optstr, ns->threads);
404  } else {
405  /* Software (host) ring, but not initial open of ring 0 */
406  snprintf(devname, sizeof(devname), "netmap:%s%d%s%s", ns->iface, ring,
407  strlen(optstr) ? "/" : "", optstr);
408  }
409  SCLogDebug("device with SW-ring enabled (devname): %s", devname);
410  } else if (ring == 0 && soft) {
411  /* Ring 0 of HW endpoint, and other endpoint is SW stack,
412  * so request SW host stack rings to match HW rings count.
413  */
414  snprintf(devname, sizeof(devname), "netmap:%s-%d%s%s@conf:host-rings=%d", ns->iface,
415  ring, strlen(optstr) ? "/" : "", optstr, ns->threads);
416  SCLogDebug("device with HW-ring enabled (devname): %s", devname);
417  } else {
418  /* Hardware ring other than ring 0, or both endpoints are HW
419  * and there is no host stack (SW) endpoint */
420  snprintf(devname, sizeof(devname), "netmap:%s-%d%s%s", ns->iface, ring,
421  strlen(optstr) ? "/" : "", optstr);
422  SCLogDebug("device with HW-ring enabled (devname): %s", devname);
423  }
424  }
425 
426  strlcpy(pdev->ifname, ns->iface, sizeof(pdev->ifname));
427 
428  /* have the netmap API parse device name and prepare the port descriptor for us */
429  pdev->nmd = nmport_prepare(devname);
430 
431  if (pdev->nmd != NULL) {
432  /* For RX devices, set the nr_mode flag we need on the netmap port TX rings prior to opening
433  */
434  if (read) {
435  pdev->nmd->reg.nr_flags |= NR_NO_TX_POLL;
436  }
437 
438  /* Now attempt to actually open the netmap port descriptor */
439  if (nmport_open_desc(pdev->nmd) < 0) {
440  /* the open failed, so clean-up the descriptor and fall through to error handler */
441  nmport_close(pdev->nmd);
442  pdev->nmd = NULL;
443  }
444  }
445 
446  if (pdev->nmd == NULL) {
447  if (errno == EINVAL) {
448  if (opt_z[0] == 'z') {
449  SCLogNotice(
450  "%s: dev '%s' got EINVAL: going to retry without 'z'", base_name, devname);
451  opt_z = "";
452  goto retry;
453  } else if (opt_x[0] == 'x') {
454  SCLogNotice(
455  "%s: dev '%s' got EINVAL: going to retry without 'x'", base_name, devname);
456  opt_x = "";
457  goto retry;
458  }
459  }
460 
461  SCMutexUnlock(&netmap_devlist_lock);
462  NetmapCloseAll();
463  FatalError("opening devname %s failed: %s", devname, strerror(errno));
464  }
465 
466  /* Work around bug in libnetmap library where "cur_{r,t}x_ring" values not initialized */
467  SCLogDebug("%s -- cur rings: [%d, %d] first rings: [%d, %d]", devname, pdev->nmd->cur_rx_ring,
468  pdev->nmd->cur_tx_ring, pdev->nmd->first_rx_ring, pdev->nmd->first_tx_ring);
469  pdev->nmd->cur_rx_ring = pdev->nmd->first_rx_ring;
470  pdev->nmd->cur_tx_ring = pdev->nmd->first_tx_ring;
471 
472  SCLogInfo("%s: %s opened [fd: %d]", devname, ns->iface, pdev->nmd->fd);
473 
474  pdev->direction = direction;
475  pdev->ring = ring;
476  SCMutexInit(&pdev->netmap_dev_lock, NULL);
477  TAILQ_INSERT_TAIL(&netmap_devlist, pdev, next);
478 
479  SCMutexUnlock(&netmap_devlist_lock);
480  *pdevice = pdev;
481 
482  return 0;
483 error:
484  return -1;
485 }
486 
487 /**
488  * \brief PcapDumpCounters
489  * \param ntv
490  */
491 static inline void NetmapDumpCounters(NetmapThreadVars *ntv)
492 {
493  StatsCounterAddI64(&ntv->tv->stats, ntv->capture_kernel_packets, ntv->pkts);
494  StatsCounterAddI64(&ntv->tv->stats, ntv->capture_kernel_drops, ntv->drops);
495  (void) SC_ATOMIC_ADD(ntv->livedev->drop, ntv->drops);
496  (void) SC_ATOMIC_ADD(ntv->livedev->pkts, ntv->pkts);
497  ntv->drops = 0;
498  ntv->pkts = 0;
499 }
500 
501 /**
502  * \brief Init function for ReceiveNetmap.
503  * \param tv pointer to ThreadVars
504  * \param initdata pointer to the interface passed from the user
505  * \param data pointer gets populated with NetmapThreadVars
506  */
507 static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, const void *initdata, void **data)
508 {
509  SCEnter();
510 
511  NetmapIfaceConfig *aconf = (NetmapIfaceConfig *)initdata;
512  if (initdata == NULL) {
513  SCLogError("initdata == NULL");
515  }
516 
517  NetmapThreadVars *ntv = SCCalloc(1, sizeof(*ntv));
518  if (unlikely(ntv == NULL)) {
519  SCLogError("Memory allocation failed");
520  goto error;
521  }
522 
523  ntv->livedev = LiveGetDevice(aconf->iface_name);
524  if (ntv->livedev == NULL) {
525  SCLogError("Unable to find Live device");
526  goto error_ntv;
527  }
528 
529  ntv->tv = tv;
530  ntv->checksum_mode = aconf->in.checksum_mode;
531  ntv->copy_mode = aconf->in.copy_mode;
532 
533  /* room for the biggest packet we can handle, used to join split packets */
534  ntv->coalesce_size = MAX_PAYLOAD_SIZE;
535  ntv->coalesce_buf = SCMalloc(ntv->coalesce_size);
536  if (unlikely(ntv->coalesce_buf == NULL)) {
537  SCLogError("Memory allocation failed");
538  goto error_ntv;
539  }
540 
541  /* enable zero-copy mode for workers runmode */
542  char const *active_runmode = RunmodeGetActive();
543  if (strcmp("workers", active_runmode) == 0) {
544  ntv->flags |= NETMAP_FLAG_ZERO_COPY;
545  SCLogDebug("Enabling zero copy mode for %s", aconf->in.iface);
546  } else if (strcmp("autofp", active_runmode) == 0) {
547  ntv->flags |= NETMAP_FLAG_EXCL_RING_ACCESS;
548  }
549 
550  /* Need to insure open of ring 0 conveys requested ring count for open */
551  bool soft = aconf->in.sw_ring || aconf->out.sw_ring;
552  if (NetmapOpen(&aconf->in, &ntv->ifsrc, 1, 1, (ntv->flags & NETMAP_FLAG_ZERO_COPY) != 0,
553  soft) != 0) {
554  goto error_ntv;
555  }
556 
557  if (aconf->in.copy_mode != NETMAP_COPY_MODE_NONE) {
558  if (NetmapOpen(&aconf->out, &ntv->ifdst, 1, 0, (ntv->flags & NETMAP_FLAG_ZERO_COPY) != 0,
559  soft) != 0) {
560  goto error_src;
561  }
562  }
563 
564  /* basic counters */
565  ntv->capture_kernel_packets = StatsRegisterCounter("capture.kernel_packets", &ntv->tv->stats);
566  ntv->capture_kernel_drops = StatsRegisterCounter("capture.kernel_drops", &ntv->tv->stats);
567 
568  if (aconf->in.bpf_filter) {
569  SCLogConfig("%s: using BPF '%s'", ntv->ifsrc->ifname, aconf->in.bpf_filter);
570  char errbuf[PCAP_ERRBUF_SIZE];
571  if (SCBPFCompile(default_packet_size, /* snaplen_arg */
572  LINKTYPE_ETHERNET, /* linktype_arg */
573  &ntv->bpf_prog, /* program */
574  aconf->in.bpf_filter, /* const char *buf */
575  1, /* optimize */
576  PCAP_NETMASK_UNKNOWN, /* mask */
577  errbuf,
578  sizeof(errbuf)) == -1)
579  {
580  SCLogError("%s: failed to compile BPF \"%s\": %s", ntv->ifsrc->ifname,
581  aconf->in.bpf_filter, errbuf);
582  goto error_dst;
583  }
584  }
585 
586  SCLogDebug("thread: %s polling on fd: %d", tv->name, ntv->ifsrc->nmd->fd);
587 
589 
590  *data = (void *)ntv;
591  aconf->DerefFunc(aconf);
593 
594 error_dst:
595  if (aconf->in.copy_mode != NETMAP_COPY_MODE_NONE) {
596  NetmapClose(ntv->ifdst);
597  }
598 
599 error_src:
600  NetmapClose(ntv->ifsrc);
601 
602 error_ntv:
603  SCFree(ntv->coalesce_buf);
604  SCFree(ntv);
605 
606 error:
607  aconf->DerefFunc(aconf);
609 }
610 
611 /**
612  * \brief Output packet to destination interface or drop.
613  * \param ntv Thread local variables.
614  * \param p Source packet.
615  */
616 static TmEcode NetmapWritePacket(NetmapThreadVars *ntv, Packet *p)
617 {
618  if (ntv->copy_mode == NETMAP_COPY_MODE_IPS) {
620  return TM_ECODE_OK;
621  }
622  }
623  DEBUG_VALIDATE_BUG_ON(ntv->ifdst == NULL);
624 
625  /* Lock the destination netmap ring while writing to it */
626  if (ntv->flags & NETMAP_FLAG_EXCL_RING_ACCESS) {
627  SCMutexLock(&ntv->ifdst->netmap_dev_lock);
628  }
629 
630  int write_tries = 0;
631 try_write:
632  /* attempt to write the packet into the netmap ring buffer(s) */
633  if (nmport_inject(ntv->ifdst->nmd, GET_PKT_DATA(p), GET_PKT_LEN(p)) == 0) {
634 
635  /* writing the packet failed, but ask kernel to sync TX rings
636  * for us as the ring buffers may simply be full */
637  (void)ioctl(ntv->ifdst->nmd->fd, NIOCTXSYNC, 0);
638 
639  /* Try write up to 2 more times before giving up */
640  if (write_tries < 3) {
641  write_tries++;
642  goto try_write;
643  }
644 
645  if (ntv->flags & NETMAP_FLAG_EXCL_RING_ACCESS) {
646  SCMutexUnlock(&ntv->ifdst->netmap_dev_lock);
647  }
648  SCLogDebug("failed to send %s -> %s", ntv->ifsrc->ifname, ntv->ifdst->ifname);
649  ntv->drops++;
650  return TM_ECODE_FAILED;
651  }
652 
653  SCLogDebug("sent successfully: %s(%d)->%s(%d) (%u)", ntv->ifsrc->ifname, ntv->ifsrc->ring,
654  ntv->ifdst->ifname, ntv->ifdst->ring, GET_PKT_LEN(p));
655 
656  /* Instruct netmap to push the data on the TX ring on the destination port */
657  (void)ioctl(ntv->ifdst->nmd->fd, NIOCTXSYNC, 0);
658  if (ntv->flags & NETMAP_FLAG_EXCL_RING_ACCESS) {
659  SCMutexUnlock(&ntv->ifdst->netmap_dev_lock);
660  }
661  return TM_ECODE_OK;
662 }
663 
664 /**
665  * \brief Packet release routine.
666  * \param p Packet.
667  */
668 static void NetmapReleasePacket(Packet *p)
669 {
670  NetmapThreadVars *ntv = (NetmapThreadVars *)p->netmap_v.ntv;
671 
672  if ((ntv->copy_mode != NETMAP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
673  NetmapWritePacket(ntv, p);
674  }
675 
677 }
678 
679 /* force_copy is set for packets joined in ntv->coalesce_buf. that buffer is
680  * reused for the next packet, so it cannot be handed out zero-copy. */
681 static void NetmapProcessPacket(NetmapThreadVars *ntv, const struct nm_pkthdr *ph, bool force_copy)
682 {
683  if (ntv->bpf_prog.bf_len) {
684  struct pcap_pkthdr pkthdr = { {0, 0}, ph->len, ph->len };
685  if (pcap_offline_filter(&ntv->bpf_prog, &pkthdr, ph->buf) == 0) {
686  return;
687  }
688  }
689 
691  if (unlikely(p == NULL)) {
692  return;
693  }
694 
696  p->livedev_id = ntv->livedev->id;
698  p->ts = SCTIME_FROM_TIMEVAL(&ph->ts);
699  ntv->pkts++;
700  ntv->bytes += ph->len;
701 
702  if ((ntv->flags & NETMAP_FLAG_ZERO_COPY) && !force_copy) {
703  if (PacketSetData(p, (uint8_t *)ph->buf, ph->len) == -1) {
704  TmqhOutputPacketpool(ntv->tv, p);
705  return;
706  }
707  } else {
708  if (PacketCopyData(p, (uint8_t *)ph->buf, ph->len) == -1) {
709  TmqhOutputPacketpool(ntv->tv, p);
710  return;
711  }
712  }
713 
714  p->ReleasePacket = NetmapReleasePacket;
715  p->netmap_v.ntv = ntv;
716 
717  SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
719 
720  (void)TmThreadsSlotProcessPkt(ntv->tv, ntv->slot, p);
721 }
722 
723 /* read the packet at ring->cur into hdr and move the ring past the slots it
724  * used. slot buffers are not always next to each other, so a packet spread
725  * over more than one slot is copied into ntv->coalesce_buf and hdr points
726  * there. returns false when the chain is broken or does not fit, the packet
727  * is dropped then. */
728 static bool NetmapReadOnePacket(
729  struct netmap_ring *ring, NetmapThreadVars *ntv, struct nm_pkthdr *hdr, bool *force_copy)
730 {
731  u_int i = ring->cur;
732  struct netmap_slot *slot = &ring->slot[i];
733 
734  memset(hdr, 0, sizeof(*hdr));
735  hdr->ts = ring->ts;
736  hdr->slot = slot;
737  hdr->buf = (u_char *)NETMAP_BUF(ring, slot->buf_idx);
738  hdr->len = hdr->caplen = slot->len;
739  *force_copy = false;
740 
741  bool dropped = false;
742 
743  if (slot->flags & NS_MOREFRAG) {
744  /* a packet cannot use more slots than we currently own */
745  uint32_t avail = nm_ring_space(ring);
746  uint32_t total = 0;
747  uint32_t nfrags = 0;
748  bool malformed = false;
749 
750  /* copy the slots into one buffer. keep walking after a problem so the
751  * whole frame is consumed at once and the ring keeps moving. */
752  for (;;) {
753  uint32_t slen = slot->len;
754  if (!malformed) {
755  if (slen > ntv->coalesce_size - total) {
756  /* frame is bigger than we can hold */
757  malformed = true;
758  } else {
759  memcpy(ntv->coalesce_buf + total, (u_char *)NETMAP_BUF(ring, slot->buf_idx),
760  slen);
761  total += slen;
762  }
763  }
764  nfrags++;
765 
766  if (!(slot->flags & NS_MOREFRAG))
767  break;
768  if (nfrags >= avail) {
769  /* the chain never ended inside the slots we own */
770  malformed = true;
771  break;
772  }
773  i = nm_ring_next(ring, i);
774  slot = &ring->slot[i];
775  }
776 
777  if (malformed) {
778  ntv->drops++;
779  dropped = true;
780  } else {
781  hdr->buf = ntv->coalesce_buf;
782  hdr->len = hdr->caplen = total;
783  *force_copy = true;
784  }
785  }
786 
787  /* release the slots we walked back to the kernel */
788  ring->head = ring->cur = nm_ring_next(ring, i);
789  return !dropped;
790 }
791 
792 /**
793  * \brief Copy netmap rings data into Packet structures.
794  * \param *d nmport_d (or nm_desc) netmap if structure.
795  * \param cnt int count of packets to read (-1 = all).
796  * \param *ntv NetmapThreadVars.
797  */
798 static TmEcode NetmapReadPackets(struct nmport_d *d, int cnt, NetmapThreadVars *ntv)
799 {
800  int last_ring = d->last_rx_ring - d->first_rx_ring + 1;
801  int cur_ring, got = 0, cur_rx_ring = d->cur_rx_ring;
802 
803  if (cnt == 0)
804  cnt = -1;
805 
806  for (cur_ring = 0; cur_ring < last_ring && cnt != got; cur_ring++, cur_rx_ring++) {
807  struct netmap_ring *ring;
808 
809  if (cur_rx_ring > d->last_rx_ring)
810  cur_rx_ring = d->first_rx_ring;
811 
812  ring = NETMAP_RXRING(d->nifp, cur_rx_ring);
813 
814  /* cycle through the non-empty ring slots to fetch their data */
815  for (; !nm_ring_empty(ring) && cnt != got; got++) {
816  struct nm_pkthdr hdr;
817  bool force_copy;
818 
819  d->cur_rx_ring = cur_rx_ring;
820  if (NetmapReadOnePacket(ring, ntv, &hdr, &force_copy)) {
821  NetmapProcessPacket(ntv, &hdr, force_copy);
822  }
823  }
824  }
825 
826  return got;
827 }
828 
829 /**
830  * \brief Main netmap reading loop function
831  */
832 static TmEcode ReceiveNetmapLoop(ThreadVars *tv, void *data, void *slot)
833 {
834  SCEnter();
835 
836  TmSlot *s = (TmSlot *)slot;
837  NetmapThreadVars *ntv = (NetmapThreadVars *)data;
838  struct pollfd fds;
839 
840  ntv->slot = s->slot_next;
841  fds.fd = ntv->ifsrc->nmd->fd;
842  fds.events = POLLIN;
843 
844  SCLogDebug("thread %s polling on %d", tv->name, fds.fd);
845 
846  // Indicate that the thread is actually running its application level code (i.e., it can poll
847  // packets)
849 
850  for(;;) {
851  if (unlikely(suricata_ctl_flags != 0)) {
852  break;
853  }
854 
855  /* make sure we have at least one packet in the packet pool,
856  * to prevent us from alloc'ing packets at line rate */
857  PacketPoolWait();
858 
859  int r = poll(&fds, 1, POLL_TIMEOUT);
860  if (r < 0) {
861  /* error */
862  if (errno != EINTR)
863  SCLogError("%s: error polling netmap: %s", ntv->ifsrc->ifname, strerror(errno));
864  continue;
865 
866  } else if (r == 0) {
867  /* no events, timeout */
868  /* sync counters */
869  NetmapDumpCounters(ntv);
871 
872  /* poll timed out, lets handle the timeout */
873  TmThreadsCaptureHandleTimeout(tv, NULL);
874  continue;
875  }
876 
877  if (unlikely(fds.revents & POLL_EVENTS)) {
878  if (fds.revents & POLLERR) {
879  SCLogError("%s: error reading netmap data via polling: %s", ntv->ifsrc->ifname,
880  strerror(errno));
881  } else if (fds.revents & POLLNVAL) {
882  SCLogError("%s: invalid polling request", ntv->ifsrc->ifname);
883  }
884  continue;
885  }
886 
887  if (likely(fds.revents & POLLIN)) {
888  /* have data on RX ring, so copy to Packet for processing */
889  NetmapReadPackets(ntv->ifsrc->nmd, -1, ntv);
890  }
891 
892  NetmapDumpCounters(ntv);
894  }
895 
896  NetmapDumpCounters(ntv);
899 }
900 
901 /**
902  * \brief This function prints stats to the screen at exit.
903  * \param tv pointer to ThreadVars
904  * \param data pointer that gets cast into NetmapThreadVars for ntv
905  */
906 static void ReceiveNetmapThreadExitStats(ThreadVars *tv, void *data)
907 {
908  SCEnter();
909  NetmapThreadVars *ntv = (NetmapThreadVars *)data;
910 
911  NetmapDumpCounters(ntv);
912  SCLogPerf("%s: (%s) packets %" PRIi64 ", dropped %" PRIi64 ", bytes %" PRIu64 "",
913  ntv->ifsrc->ifname, tv->name,
914  StatsCounterGetLocalValue(&tv->stats, ntv->capture_kernel_packets),
915  StatsCounterGetLocalValue(&tv->stats, ntv->capture_kernel_drops), ntv->bytes);
916 }
917 
918 /**
919  * \brief
920  * \param tv
921  * \param data Pointer to NetmapThreadVars.
922  */
923 static TmEcode ReceiveNetmapThreadDeinit(ThreadVars *tv, void *data)
924 {
925  SCEnter();
926 
927  NetmapThreadVars *ntv = (NetmapThreadVars *)data;
928 
929  if (ntv->ifsrc) {
930  NetmapClose(ntv->ifsrc);
931  ntv->ifsrc = NULL;
932  }
933  if (ntv->ifdst) {
934  NetmapClose(ntv->ifdst);
935  ntv->ifdst = NULL;
936  }
937  if (ntv->bpf_prog.bf_insns) {
938  SCBPFFree(&ntv->bpf_prog);
939  }
940 
941  SCFree(ntv->coalesce_buf);
942  SCFree(ntv);
943 
945 }
946 
947 /**
948  * \brief Prepare netmap decode thread.
949  * \param tv Thread local variables.
950  * \param initdata Thread config.
951  * \param data Pointer to DecodeThreadVars placed here.
952  */
953 static TmEcode DecodeNetmapThreadInit(ThreadVars *tv, const void *initdata, void **data)
954 {
955  SCEnter();
956 
958  if (dtv == NULL)
960 
962 
963  *data = (void *)dtv;
964 
966 }
967 
968 /**
969  * \brief This function passes off to link type decoders.
970  *
971  * \param t pointer to ThreadVars
972  * \param p pointer to the current packet
973  * \param data pointer that gets cast into NetmapThreadVars for ntv
974  */
975 static TmEcode DecodeNetmap(ThreadVars *tv, Packet *p, void *data)
976 {
977  SCEnter();
978 
980 
982 
983  /* update counters */
985 
987 
989 
991 }
992 
993 /**
994  * \brief
995  * \param tv
996  * \param data Pointer to DecodeThreadVars.
997  */
998 static TmEcode DecodeNetmapThreadDeinit(ThreadVars *tv, void *data)
999 {
1000  SCEnter();
1001 
1002  if (data != NULL)
1003  DecodeThreadVarsFree(tv, data);
1004 
1006 }
1007 
1008 #ifdef UNITTESTS
1009 #include "tests/source-netmap.c"
1010 #endif
1011 
1012 /**
1013  * \brief Registration Function for ReceiveNetmap.
1014  */
1016 {
1017  tmm_modules[TMM_RECEIVENETMAP].name = "ReceiveNetmap";
1018  tmm_modules[TMM_RECEIVENETMAP].ThreadInit = ReceiveNetmapThreadInit;
1019  tmm_modules[TMM_RECEIVENETMAP].PktAcqLoop = ReceiveNetmapLoop;
1020  tmm_modules[TMM_RECEIVENETMAP].ThreadExitPrintStats = ReceiveNetmapThreadExitStats;
1021  tmm_modules[TMM_RECEIVENETMAP].ThreadDeinit = ReceiveNetmapThreadDeinit;
1024 #ifdef UNITTESTS
1025  tmm_modules[TMM_RECEIVENETMAP].RegisterTests = NetmapRegisterTests;
1026 #endif
1027 }
1028 
1029 /**
1030  * \brief Registration Function for DecodeNetmap.
1031  */
1033 {
1034  tmm_modules[TMM_DECODENETMAP].name = "DecodeNetmap";
1035  tmm_modules[TMM_DECODENETMAP].ThreadInit = DecodeNetmapThreadInit;
1036  tmm_modules[TMM_DECODENETMAP].Func = DecodeNetmap;
1037  tmm_modules[TMM_DECODENETMAP].ThreadDeinit = DecodeNetmapThreadDeinit;
1040 }
1041 
1042 #endif /* HAVE_NETMAP */
1043 
1044 /**
1045 * @}
1046 */
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:77
PacketCheckAction
bool PacketCheckAction(const Packet *p, const uint8_t a)
Definition: packet.c:50
util-device-private.h
tm-threads.h
NETMAP_COPY_MODE_IPS
@ NETMAP_COPY_MODE_IPS
Definition: source-netmap.h:32
ThreadVars_::name
char name[16]
Definition: threadvars.h:64
PacketFreeOrRelease
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
Definition: decode.c:291
StatsSyncCountersIfSignalled
void StatsSyncCountersIfSignalled(StatsThreadContext *stats)
Definition: counters.c:481
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:314
PacketCopyData
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:396
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1366
util-bpf.h
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
NetmapIfaceSettings_::checksum_mode
ChecksumValidationMode checksum_mode
Definition: source-netmap.h:51
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
StatsRegisterCounter
StatsCounterId StatsRegisterCounter(const char *name, StatsThreadContext *stats)
Registers a normal, unqualified counter.
Definition: counters.c:1038
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:102
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
action-globals.h
LiveDevice_
Definition: util-device-private.h:32
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:332
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:54
source-netmap.c
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
NetmapIfaceConfig_::out
NetmapIfaceSettings out
Definition: source-netmap.h:64
util-privs.h
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:122
p
Packet * p
Definition: fuzz_dataset.c:30
TAILQ_INSERT_TAIL
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:294
StatsCounterId
Definition: counters.h:30
PacketDecodeFinalize
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition: decode.c:244
RunmodeGetActive
char * RunmodeGetActive(void)
Definition: runmodes.c:198
TmModuleReceiveNetmapRegister
void TmModuleReceiveNetmapRegister(void)
Definition: source-netmap.c:75
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:305
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
NetmapIfaceSettings_::iface
char iface[NETMAP_IFACE_NAME_LENGTH]
Definition: source-netmap.h:40
NetmapIfaceSettings_::ips
bool ips
Definition: source-netmap.h:46
TmModule_::PktAcqLoop
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-modules.h:58
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:53
TAILQ_ENTRY
#define TAILQ_ENTRY(type)
Definition: queue.h:239
Packet_::datalink
int datalink
Definition: decode.h:654
NetmapGetRSSCount
int NetmapGetRSSCount(const char *ifname)
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1368
DecodeRegisterPerfCounters
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition: decode.c:657
TAILQ_HEAD_INITIALIZER
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:236
TmModuleDecodeNetmapRegister
void TmModuleDecodeNetmapRegister(void)
Registration Function for DecodeNetmap.
Definition: source-netmap.c:85
NetmapIfaceConfig_::DerefFunc
void(* DerefFunc)(void *)
Definition: source-netmap.h:67
PKT_SRC_WIRE
@ PKT_SRC_WIRE
Definition: decode.h:52
NetmapIfaceSettings_::real
bool real
Definition: source-netmap.h:45
PCAP_NETMASK_UNKNOWN
#define PCAP_NETMASK_UNKNOWN
Definition: log-pcap.c:90
Packet_::ts
SCTime_t ts
Definition: decode.h:572
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
NetmapIfaceSettings_::sw_ring
bool sw_ring
Definition: source-netmap.h:43
LiveGetDevice
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
Definition: util-device.c:269
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:210
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
SCTIME_FROM_TIMEVAL
#define SCTIME_FROM_TIMEVAL(tv)
Definition: util-time.h:79
TmModule_::Func
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition: tm-modules.h:56
NetmapIfaceSettings_
Definition: source-netmap.h:38
TMM_DECODENETMAP
@ TMM_DECODENETMAP
Definition: tm-threads-common.h:59
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:322
NetmapIfaceSettings_::threads
uint16_t threads
Definition: source-netmap.h:49
SC_ATOMIC_DECLARE
#define SC_ATOMIC_DECLARE(type, name)
wrapper for declaring atomic variables.
Definition: util-atomic.h:280
PacketPoolWait
void PacketPoolWait(void)
Definition: tmqh-packetpool.c:71
Packet_
Definition: decode.h:518
TM_FLAG_DECODE_TM
#define TM_FLAG_DECODE_TM
Definition: tm-modules.h:33
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:29
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:209
source-netmap.h
TmModule_::RegisterTests
void(* RegisterTests)(void)
Definition: tm-modules.h:75
TmSlot_
Definition: tm-threads.h:53
TmEcode
TmEcode
Definition: tm-threads-common.h:80
NetmapIfaceSettings_::promisc
bool promisc
Definition: source-netmap.h:44
TmModule_::name
const char * name
Definition: tm-modules.h:48
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:232
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:329
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
TM_FLAG_RECEIVE_TM
#define TM_FLAG_RECEIVE_TM
Definition: tm-modules.h:32
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:35
default_packet_size
uint32_t default_packet_size
Definition: decode.c:77
NETMAP_COPY_MODE_NONE
@ NETMAP_COPY_MODE_NONE
Definition: source-netmap.h:30
Packet_::ReleasePacket
void(* ReleasePacket)(struct Packet_ *)
Definition: decode.h:608
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
NetmapIfaceSettings_::bpf_filter
const char * bpf_filter
Definition: source-netmap.h:52
flags
uint8_t flags
Definition: decode-gre.h:0
DecodeThreadVarsFree
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition: decode.c:871
NetmapIfaceConfig_
Definition: source-netmap.h:56
ChecksumValidationMode
ChecksumValidationMode
Definition: decode.h:42
suricata-common.h
packet.h
Packet_::livedev_id
uint16_t livedev_id
Definition: decode.h:635
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:241
StatsCounterGetLocalValue
int64_t StatsCounterGetLocalValue(StatsThreadContext *stats, StatsCounterId id)
Get the value of the local copy of the counter that hold this id.
Definition: counters.c:1375
SCBPFFree
void SCBPFFree(struct bpf_program *program)
Definition: util-bpf.c:56
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:51
FatalError
#define FatalError(...)
Definition: util-debug.h:517
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
TmModule_::ThreadExitPrintStats
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-modules.h:52
util-validate.h
TMM_RECEIVENETMAP
@ TMM_RECEIVENETMAP
Definition: tm-threads-common.h:58
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
POLL_TIMEOUT
#define POLL_TIMEOUT
Definition: source-af-packet.c:172
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SCFree
#define SCFree(p)
Definition: util-mem.h:61
NetmapIfaceConfig_::iface_name
char iface_name[NETMAP_IFACE_NAME_LENGTH]
Definition: source-netmap.h:58
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:997
MAX_PAYLOAD_SIZE
#define MAX_PAYLOAD_SIZE
Definition: decode.h:716
NetmapIfaceSettings_::copy_mode
int copy_mode
Definition: source-netmap.h:50
util-ioctl.h
DecodeThreadVarsAlloc
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition: decode.c:853
TAILQ_HEAD
#define TAILQ_HEAD(name, type)
Definition: queue.h:230
PacketSetData
int PacketSetData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Set data for Packet and set length when zero copy is used.
Definition: decode.c:891
PacketPoolGetPacket
Packet * PacketPoolGetPacket(void)
Get a new packet from the packet pool.
Definition: tmqh-packetpool.c:118
SCBPFCompile
int SCBPFCompile(int snaplen_arg, int linktype_arg, struct bpf_program *program, const char *buf, int optimize, uint32_t mask, char *errbuf, size_t errbuf_len)
Definition: util-bpf.c:62
NetmapIfaceConfig_::in
NetmapIfaceSettings in
Definition: source-netmap.h:61
suricata.h
likely
#define likely(expr)
Definition: util-optimize.h:32
TmSlot_::slot_next
struct TmSlot_ * slot_next
Definition: tm-threads.h:62
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:250
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:120
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
SCMutexDestroy
#define SCMutexDestroy
Definition: threads-debug.h:121
StatsCounterAddI64
void StatsCounterAddI64(StatsThreadContext *stats, StatsCounterId id, int64_t x)
Adds a value of type uint64_t to the local counter.
Definition: counters.c:144
SCMutex
#define SCMutex
Definition: threads-debug.h:114
SC_CAP_NET_RAW
#define SC_CAP_NET_RAW
Definition: util-privs.h:32
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
DecodeEthernet
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ethernet.c:41
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:80
DecodeUpdatePacketCounters
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition: decode.c:821
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:177