suricata
source-napatech.c
Go to the documentation of this file.
1 /* Copyright (C) 2012-2017 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 nPulse Technologies, LLC.
22  - * \author Matt Keeler <mk@npulsetech.com>
23  * *
24  * Support for NAPATECH adapter with the 3GD Driver/API.
25  * Requires libntapi from Napatech A/S.
26  *
27  */
28 #include "suricata-common.h"
29 #include "suricata.h"
30 #include "threadvars.h"
31 #include "util-optimize.h"
32 #include "tm-queuehandlers.h"
33 #include "tm-threads.h"
34 #include "tm-modules.h"
35 #include "util-privs.h"
36 #include "tmqh-packetpool.h"
37 #include "util-napatech.h"
38 #include "source-napatech.h"
39 
40 #ifndef HAVE_NAPATECH
41 
42 TmEcode NoNapatechSupportExit(ThreadVars*, const void*, void**);
43 
45 {
46  tmm_modules[TMM_RECEIVENAPATECH].name = "NapatechStream";
47  tmm_modules[TMM_RECEIVENAPATECH].ThreadInit = NoNapatechSupportExit;
53 }
54 
56 {
57  tmm_modules[TMM_DECODENAPATECH].name = "NapatechDecode";
58  tmm_modules[TMM_DECODENAPATECH].ThreadInit = NoNapatechSupportExit;
65 }
66 
67 TmEcode NoNapatechSupportExit(ThreadVars *tv, const void *initdata, void **data)
68 {
70  "Error creating thread %s: you do not have support for Napatech adapter "
71  "enabled please recompile with --enable-napatech",
72  tv->name);
73  exit(EXIT_FAILURE);
74 }
75 
76 #else /* Implied we do have NAPATECH support */
77 
78 
79 #include <numa.h>
80 #include <nt.h>
81 
82 extern int max_pending_packets;
83 
84 typedef struct NapatechThreadVars_
85 {
87  NtNetStreamRx_t rx_stream;
88  uint16_t stream_id;
89  int hba;
92 
93 #ifdef NAPATECH_ENABLE_BYPASS
94 static int NapatechBypassCallback(Packet *p);
95 #endif
96 
97 TmEcode NapatechStreamThreadInit(ThreadVars *, const void *, void **);
99 TmEcode NapatechPacketLoop(ThreadVars *tv, void *data, void *slot);
100 
101 TmEcode NapatechDecodeThreadInit(ThreadVars *, const void *, void **);
104 
105 /* These are used as the threads are exiting to get a comprehensive count of
106  * all the packets received and dropped.
107  */
108 SC_ATOMIC_DECLARE(uint64_t, total_packets);
109 SC_ATOMIC_DECLARE(uint64_t, total_drops);
110 SC_ATOMIC_DECLARE(uint16_t, total_tallied);
111 
112 /* Streams are counted as they are instantiated in order to know when all threads
113  * are running*/
114 SC_ATOMIC_DECLARE(uint16_t, stream_count);
115 
116 SC_ATOMIC_DECLARE(uint16_t, numa0_count);
117 SC_ATOMIC_DECLARE(uint16_t, numa1_count);
118 SC_ATOMIC_DECLARE(uint16_t, numa2_count);
119 SC_ATOMIC_DECLARE(uint16_t, numa3_count);
120 
121 SC_ATOMIC_DECLARE(uint64_t, flow_callback_cnt);
122 SC_ATOMIC_DECLARE(uint64_t, flow_callback_handled_pkts);
123 SC_ATOMIC_DECLARE(uint64_t, flow_callback_udp_pkts);
124 SC_ATOMIC_DECLARE(uint64_t, flow_callback_tcp_pkts);
125 SC_ATOMIC_DECLARE(uint64_t, flow_callback_unhandled_pkts);
126 
127 /**
128  * \brief Register the Napatech receiver (reader) module.
129  */
131 {
132  tmm_modules[TMM_RECEIVENAPATECH].name = "NapatechStream";
142 
143  SC_ATOMIC_INIT(total_packets);
144  SC_ATOMIC_INIT(total_drops);
145  SC_ATOMIC_INIT(total_tallied);
146  SC_ATOMIC_INIT(stream_count);
147 
148  SC_ATOMIC_INIT(numa0_count);
149  SC_ATOMIC_INIT(numa1_count);
150  SC_ATOMIC_INIT(numa2_count);
151  SC_ATOMIC_INIT(numa3_count);
152 
153  SC_ATOMIC_INIT(flow_callback_cnt);
154  SC_ATOMIC_INIT(flow_callback_handled_pkts);
155  SC_ATOMIC_INIT(flow_callback_udp_pkts);
156  SC_ATOMIC_INIT(flow_callback_tcp_pkts);
157  SC_ATOMIC_INIT(flow_callback_unhandled_pkts);
158 }
159 
160 /**
161  * \brief Register the Napatech decoder module.
162  */
164 {
165  tmm_modules[TMM_DECODENAPATECH].name = "NapatechDecode";
173 }
174 
175 #ifdef NAPATECH_ENABLE_BYPASS
176 /**
177  * \brief template of IPv4 header
178  */
179 struct ipv4_hdr
180 {
181  uint8_t version_ihl; /**< version and header length */
182  uint8_t type_of_service; /**< type of service */
183  uint16_t total_length; /**< length of packet */
184  uint16_t packet_id; /**< packet ID */
185  uint16_t fragment_offset; /**< fragmentation offset */
186  uint8_t time_to_live; /**< time to live */
187  uint8_t next_proto_id; /**< protocol ID */
188  uint16_t hdr_checksum; /**< header checksum */
189  uint32_t src_addr; /**< source address */
190  uint32_t dst_addr; /**< destination address */
191 } __attribute__ ((__packed__));
192 
193 /**
194  * \brief template of IPv6 header
195  */
196 struct ipv6_hdr
197 {
198  uint32_t vtc_flow; /**< IP version, traffic class & flow label. */
199  uint16_t payload_len; /**< IP packet length - includes sizeof(ip_header). */
200  uint8_t proto; /**< Protocol, next header. */
201  uint8_t hop_limits; /**< Hop limits. */
202  uint8_t src_addr[16]; /**< IP address of source host. */
203  uint8_t dst_addr[16]; /**< IP address of destination host(s). */
204 } __attribute__ ((__packed__));
205 
206 /**
207  * \brief template of UDP header
208  */
209 struct udp_hdr
210 {
211  uint16_t src_port; /**< UDP source port. */
212  uint16_t dst_port; /**< UDP destination port. */
213  uint16_t dgram_len; /**< UDP datagram length */
214  uint16_t dgram_cksum; /**< UDP datagram checksum */
215 } __attribute__ ((__packed__));
216 
217 /**
218  * \brief template of TCP header
219  */
220 struct tcp_hdr
221 {
222  uint16_t src_port; /**< TCP source port. */
223  uint16_t dst_port; /**< TCP destination port. */
224  uint32_t sent_seq; /**< TX data sequence number. */
225  uint32_t recv_ack; /**< RX data acknowledgement sequence number. */
226  uint8_t data_off; /**< Data offset. */
227  uint8_t tcp_flags; /**< TCP flags */
228  uint16_t rx_win; /**< RX flow control window. */
229  uint16_t cksum; /**< TCP checksum. */
230  uint16_t tcp_urp; /**< TCP urgent pointer, if any. */
231 } __attribute__ ((__packed__));
232 
233 
234 /* The hardware will assign a "color" value indicating what filters are matched
235  * by a given packet. These constants indicate what bits are set in the color
236  * field for different protocols
237  *
238  */
239 #define RTE_PTYPE_L2_ETHER 0x10000000
240 #define RTE_PTYPE_L3_IPV4 0x01000000
241 #define RTE_PTYPE_L3_IPV6 0x04000000
242 #define RTE_PTYPE_L4_TCP 0x00100000
243 #define RTE_PTYPE_L4_UDP 0x00200000
244 
245 /* These masks are used to extract layer 3 and layer 4 protocol
246  * values from the color field in the packet descriptor.
247  */
248 #define RTE_PTYPE_L3_MASK 0x0f000000
249 #define RTE_PTYPE_L4_MASK 0x00f00000
250 
251 #define COLOR_IS_SPAN 0x00001000
252 
253 static int inline_port_map[MAX_PORTS] = { -1 };
254 
255 /**
256  * \brief Binds two ports together for inline operation.
257  *
258  * Get the ID of an adapter on which a given port resides.
259  *
260  * \param port one of the ports in a pairing.
261  * \param peer the other port in a pairing.
262  * \return ID of the adapter.
263  *
264  */
265 int NapatechSetPortmap(int port, int peer)
266 {
267  if ((inline_port_map[port] == -1) && (inline_port_map[peer] == -1)) {
268  inline_port_map[port] = peer;
269  inline_port_map[peer] = port;
270  } else {
272  "Port pairing is already configured.");
273  return 0;
274  }
275  return 1;
276 }
277 
278 /**
279  * \brief Returns the ID of the adapter
280  *
281  * Get the ID of an adapter on which a given port resides.
282  *
283  * \param port for which adapter ID is requested.
284  * \return ID of the adapter.
285  *
286  */
287 int NapatechGetAdapter(uint8_t port)
288 {
289  static int port_adapter_map[MAX_PORTS] = { -1 };
290  int status;
291  NtInfo_t h_info; /* Info handle */
292  NtInfoStream_t h_info_stream; /* Info stream handle */
293 
294  if (unlikely(port_adapter_map[port] == -1)) {
295  if ((status = NT_InfoOpen(&h_info_stream, "ExampleInfo")) != NT_SUCCESS) {
297  return -1;
298  }
299  /* Read the system info */
300  h_info.cmd = NT_INFO_CMD_READ_PORT_V9;
301  h_info.u.port_v9.portNo = (uint8_t) port;
302  if ((status = NT_InfoRead(h_info_stream, &h_info)) != NT_SUCCESS) {
303  /* Get the status code as text */
305  NT_InfoClose(h_info_stream);
306  return -1;
307  }
308  port_adapter_map[port] = h_info.u.port_v9.data.adapterNo;
309  }
310  return port_adapter_map[port];
311 }
312 
313 /**
314  * \brief IPv4 4-tuple convenience structure
315  */
316 struct IPv4Tuple4
317 {
318  uint32_t sa; /*!< Source address */
319  uint32_t da; /*!< Destination address */
320  uint16_t sp; /*!< Source port */
321  uint16_t dp; /*!< Destination port */
322 };
323 
324 /**
325  * \brief IPv6 4-tuple convenience structure
326  */
327 struct IPv6Tuple4
328 {
329  uint8_t sa[16]; /*!< Source address */
330  uint8_t da[16]; /*!< Destination address */
331  uint16_t sp; /*!< Source port */
332  uint16_t dp; /*!< Destination port */
333 };
334 
335 
336 /**
337  * \brief Compares the byte order value of two IPv6 addresses.
338  *
339  *
340  * \param addr_a The first address to compare
341  * \param addr_b The second adress to compare
342  *
343  * \return -1 if addr_a < addr_b
344  * 1 if addr_a > addr_b
345  * 0 if addr_a == addr_b
346  */
347 static int CompareIPv6Addr(uint8_t addr_a[16], uint8_t addr_b[16]) {
348  uint16_t pos;
349  for (pos = 0; pos < 16; ++pos) {
350  if (addr_a[pos] < addr_b[pos]) {
351  return -1;
352  } else if (addr_a[pos] > addr_b[pos]) {
353  return 1;
354  } /* else they are equal - check next position*/
355  }
356 
357  /* if we get here the addresses are equal */
358  return 0;
359 }
360 
361 /**
362  * \brief Callback function to process Bypass events on Napatech Adapter.
363  *
364  * Callback function that sets up the Flow tables on the Napatech card
365  * so that subsequent packets from this flow are bypassed on the hardware.
366  *
367  * \param p packet containing information about the flow to be bypassed
368  * \param is_inline indicates if Suricata is being run in inline mode.
369  *
370  * \return Error code indicating success (1) or failure (0).
371  *
372  */
373 static int ProgramFlow(Packet *p, int is_inline)
374 {
375  int status;
376  NtFlow_t flow_match;
377  memset(&flow_match, 0, sizeof(flow_match));
378 
379  NapatechPacketVars *ntpv = &(p->ntpv);
380 
381  int adapter = NapatechGetAdapter(ntpv->dyn3->rxPort);
382 
383  NtFlowStream_t *phFlowStream = NapatechGetFlowStreamPtr(adapter);
384 
385 
386  /*
387  * The hardware decoder will "color" the packets according to the protocols
388  * in the packet and the port the packet arrived on. packet_type gets
389  * these bits and we mask out layer3, layer4, and is_span to determine
390  * the protocols and if the packet is coming in from a SPAN port.
391  */
392  uint32_t packet_type = ((ntpv->dyn3->color_hi << 14) & 0xFFFFC000) | ntpv->dyn3->color_lo;
393  uint8_t *packet = (uint8_t *) ntpv->dyn3 + ntpv->dyn3->descrLength;
394 
395  uint32_t layer3 = packet_type & RTE_PTYPE_L3_MASK;
396  uint32_t layer4 = packet_type & RTE_PTYPE_L4_MASK;
397  uint32_t is_span = packet_type & COLOR_IS_SPAN;
398 
399  /*
400  * When we're programming the flows to arrive on a span port,
401  * where upstream and downstream packets arrive on the same port,
402  * the hardware is configured to swap the source and dest
403  * fields if the src addr > dest addr. We need to program the
404  * flow tables to match. We'll compare addresses and set
405  * do_swap accordingly.
406  */
407 
408  uint32_t do_swap = 0;
409 
410  SC_ATOMIC_ADD(flow_callback_cnt, 1);
411 
412  /* Only bypass TCP and UDP */
413  if (PKT_IS_TCP(p)) {
414  SC_ATOMIC_ADD(flow_callback_tcp_pkts, 1);
415  } else if PKT_IS_UDP(p) {
416  SC_ATOMIC_ADD(flow_callback_udp_pkts, 1);
417  } else {
418  SC_ATOMIC_ADD(flow_callback_unhandled_pkts, 1);
419  }
420 
421  struct IPv4Tuple4 v4Tuple;
422  struct IPv6Tuple4 v6Tuple;
423  struct ipv4_hdr *pIPv4_hdr = NULL;
424  struct ipv6_hdr *pIPv6_hdr = NULL;
425 
426  switch (layer3) {
427  case RTE_PTYPE_L3_IPV4:
428  {
429  pIPv4_hdr = (struct ipv4_hdr *) (packet + ntpv->dyn3->offset0);
430 
431  if (!is_span) {
432  v4Tuple.sa = pIPv4_hdr->src_addr;
433  v4Tuple.da = pIPv4_hdr->dst_addr;
434  } else {
435  do_swap = (pIPv4_hdr->src_addr > pIPv4_hdr->dst_addr);
436  if (!do_swap) {
437  /* already in order */
438  v4Tuple.sa = pIPv4_hdr->src_addr;
439  v4Tuple.da = pIPv4_hdr->dst_addr;
440  } else { /* swap */
441  v4Tuple.sa = pIPv4_hdr->dst_addr;
442  v4Tuple.da = pIPv4_hdr->src_addr;
443  }
444  }
445  break;
446  }
447  case RTE_PTYPE_L3_IPV6:
448  {
449  pIPv6_hdr = (struct ipv6_hdr *) (packet + ntpv->dyn3->offset0);
450  do_swap = (CompareIPv6Addr(pIPv6_hdr->src_addr, pIPv6_hdr->dst_addr) > 0);
451 
452  if (!is_span) {
453  memcpy(&(v6Tuple.sa), pIPv6_hdr->src_addr, 16);
454  memcpy(&(v6Tuple.da), pIPv6_hdr->dst_addr, 16);
455  } else {
456  /* sort src/dest address before programming */
457  if (!do_swap) {
458  /* already in order */
459  memcpy(&(v6Tuple.sa), pIPv6_hdr->src_addr, 16);
460  memcpy(&(v6Tuple.da), pIPv6_hdr->dst_addr, 16);
461  } else { /* swap the addresses */
462  memcpy(&(v6Tuple.sa), pIPv6_hdr->dst_addr, 16);
463  memcpy(&(v6Tuple.da), pIPv6_hdr->src_addr, 16);
464  }
465  }
466  break;
467  }
468  default:
469  {
470  return 0;
471  }
472  }
473 
474  switch (layer4) {
475  case RTE_PTYPE_L4_TCP:
476  {
477  struct tcp_hdr *tcp_hdr = (struct tcp_hdr *) (packet + ntpv->dyn3->offset1);
478  if (layer3 == RTE_PTYPE_L3_IPV4) {
479  if (!is_span) {
480  v4Tuple.dp = tcp_hdr->dst_port;
481  v4Tuple.sp = tcp_hdr->src_port;
482  flow_match.keyId = NAPATECH_KEYTYPE_IPV4;
483  } else {
484  if (!do_swap) {
485  v4Tuple.sp = tcp_hdr->src_port;
486  v4Tuple.dp = tcp_hdr->dst_port;
487  } else {
488  v4Tuple.sp = tcp_hdr->dst_port;
489  v4Tuple.dp = tcp_hdr->src_port;
490  }
491  flow_match.keyId = NAPATECH_KEYTYPE_IPV4_SPAN;
492  }
493  memcpy(&(flow_match.keyData), &v4Tuple, sizeof(v4Tuple));
494  } else {
495  if (!is_span) {
496  v6Tuple.dp = tcp_hdr->dst_port;
497  v6Tuple.sp = tcp_hdr->src_port;
498  flow_match.keyId = NAPATECH_KEYTYPE_IPV6;
499  } else {
500  if (!do_swap) {
501  v6Tuple.sp = tcp_hdr->src_port;
502  v6Tuple.dp = tcp_hdr->dst_port;
503  } else {
504  v6Tuple.dp = tcp_hdr->src_port;
505  v6Tuple.sp = tcp_hdr->dst_port;
506  }
507  flow_match.keyId = NAPATECH_KEYTYPE_IPV6_SPAN;
508  }
509  memcpy(&(flow_match.keyData), &v6Tuple, sizeof(v6Tuple));
510  }
511  flow_match.ipProtocolField = 6;
512  break;
513  }
514  case RTE_PTYPE_L4_UDP:
515  {
516  struct udp_hdr *udp_hdr = (struct udp_hdr *) (packet + ntpv->dyn3->offset1);
517  if (layer3 == RTE_PTYPE_L3_IPV4) {
518  if (!is_span) {
519  v4Tuple.dp = udp_hdr->dst_port;
520  v4Tuple.sp = udp_hdr->src_port;
521  flow_match.keyId = NAPATECH_KEYTYPE_IPV4;
522  } else {
523  if (!do_swap) {
524  v4Tuple.sp = udp_hdr->src_port;
525  v4Tuple.dp = udp_hdr->dst_port;
526  } else {
527  v4Tuple.dp = udp_hdr->src_port;
528  v4Tuple.sp = udp_hdr->dst_port;
529  }
530  flow_match.keyId = NAPATECH_KEYTYPE_IPV4_SPAN;
531  }
532  memcpy(&(flow_match.keyData), &v4Tuple, sizeof(v4Tuple));
533  } else { /* layer3 is IPV6 */
534  if (!is_span) {
535  v6Tuple.dp = udp_hdr->dst_port;
536  v6Tuple.sp = udp_hdr->src_port;
537  flow_match.keyId = NAPATECH_KEYTYPE_IPV6;
538  } else {
539  if (!do_swap) {
540  v6Tuple.sp = udp_hdr->src_port;
541  v6Tuple.dp = udp_hdr->dst_port;
542  } else {
543  v6Tuple.dp = udp_hdr->src_port;
544  v6Tuple.sp = udp_hdr->dst_port;
545  }
546  flow_match.keyId = NAPATECH_KEYTYPE_IPV6_SPAN;
547  }
548  memcpy(&(flow_match.keyData), &v6Tuple, sizeof(v6Tuple));
549  }
550  flow_match.ipProtocolField = 17;
551  break;
552  }
553  default:
554  {
555  return 0;
556  }
557  }
558 
559  flow_match.op = 1; /* program flow */
560  flow_match.gfi = 1; /* Generate FlowInfo records */
561  flow_match.tau = 1; /* tcp automatic unlearn */
562 
564  flow_match.keySetId = NAPATECH_FLOWTYPE_DROP;
565  } else {
566  if (is_inline) {
567  flow_match.keySetId = NAPATECH_FLOWTYPE_PASS;
568  } else {
569  flow_match.keySetId = NAPATECH_FLOWTYPE_DROP;
570  }
571  }
572 
573  status = NT_FlowWrite(*phFlowStream, &flow_match, -1);
574  if (status == NT_STATUS_TIMEOUT) {
575  SCLogInfo("NT_FlowWrite returned NT_STATUS_TIMEOUT");
576  } else if (status != NT_SUCCESS) {
577  SCLogError(SC_ERR_NAPATECH_OPEN_FAILED,"NT_FlowWrite failed!.");
578  exit(EXIT_FAILURE);
579  }
580 
581  return 1;
582 }
583 
584 /**
585  * \brief Callback from Suricata when a flow that should be bypassed
586  * is identified.
587  */
588 
589 static int NapatechBypassCallback(Packet *p)
590 {
591  NapatechPacketVars *ntpv = &(p->ntpv);
592 
593  /*
594  * Since, at this point, we don't know what action to take,
595  * simply mark this packet as one that should be
596  * bypassed when the packet is returned by suricata with a
597  * pass/drop verdict.
598  */
599  ntpv->bypass = 1;
600 
601  return 1;
602 }
603 
604 #endif
605 
606 /**
607  * \brief Initialize the Napatech receiver thread, generate a single
608  * NapatechThreadVar structure for each thread, this will
609  * contain a NtNetStreamRx_t stream handle which is used when the
610  * thread executes to acquire the packets.
611  *
612  * \param tv Thread variable to ThreadVars
613  * \param initdata Initial data to the adapter passed from the user,
614  * this is processed by the user.
615  *
616  * For now, we assume that we have only a single name for the NAPATECH
617  * adapter.
618  *
619  * \param data data pointer gets populated with
620  *
621  */
622 TmEcode NapatechStreamThreadInit(ThreadVars *tv, const void *initdata, void **data)
623 {
624  SCEnter();
625  struct NapatechStreamDevConf *conf = (struct NapatechStreamDevConf *) initdata;
626  uint16_t stream_id = conf->stream_id;
627  *data = NULL;
628 
629  NapatechThreadVars *ntv = SCCalloc(1, sizeof (NapatechThreadVars));
630  if (unlikely(ntv == NULL)) {
631  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for NAPATECH thread vars.");
632  exit(EXIT_FAILURE);
633  }
634 
635  memset(ntv, 0, sizeof (NapatechThreadVars));
636  ntv->stream_id = stream_id;
637  ntv->tv = tv;
638  ntv->hba = conf->hba;
639  SCLogDebug("Started processing packets from NAPATECH Stream: %lu", ntv->stream_id);
640 
641  *data = (void *) ntv;
643 }
644 
645 static PacketQueue packets_to_release[MAX_STREAMS];
646 
647 /**
648  * \brief Callback to indicate that the packet buffer can be returned to the hardware.
649  *
650  * Called when Suricata is done processing the packet. The packet is placed into
651  * a queue so that it can be retrieved and released by the packet processing thread.
652  *
653  * \param p Packet to return to the system.
654  *
655  */
656 static void NapatechReleasePacket(struct Packet_ *p)
657 {
659  PacketEnqueue(&packets_to_release[p->ntpv.stream_id], p);
660 }
661 
662 /**
663  * \brief Returns the NUMA node associated with the currently running thread.
664  *
665  * \return ID of the NUMA node.
666  *
667  */
668 static int GetNumaNode(void)
669 {
670  int cpu = 0;
671  int node = 0;
672 
673 #if defined(__linux__)
674  cpu = sched_getcpu();
675  node = numa_node_of_cpu(cpu);
676 #else
678  "Auto configuration of NUMA node is not supported on this OS.");
679 #endif
680 
681  return node;
682 }
683 
684 /**
685  * \brief Outputs hints on the optimal host-buffer configuration to aid tuning.
686  *
687  * \param log_level of the currently running instance.
688  *
689  */
690 static void RecommendNUMAConfig(SCLogLevel log_level)
691 {
692  char string0[16];
693  char string1[16];
694  char string2[16];
695  char string3[16];
696  int set_cpu_affinity = 0;
697 
698  if (ConfGetBool("threading.set-cpu-affinity", &set_cpu_affinity) != 1) {
699  set_cpu_affinity = 0;
700  }
701 
702  if (set_cpu_affinity) {
703  SCLog(log_level, __FILE__, __FUNCTION__, __LINE__,
704  "Minimum host buffers that should be defined in ntservice.ini:");
705 
706  SCLog(log_level, __FILE__, __FUNCTION__, __LINE__, " NUMA Node 0: %d",
707  (SC_ATOMIC_GET(numa0_count)));
708 
709  if (numa_max_node() >= 1)
710  SCLog(log_level, __FILE__, __FUNCTION__, __LINE__,
711  " NUMA Node 1: %d ", (SC_ATOMIC_GET(numa1_count)));
712 
713  if (numa_max_node() >= 2)
714  SCLog(log_level, __FILE__, __FUNCTION__, __LINE__,
715  " NUMA Node 2: %d ", (SC_ATOMIC_GET(numa2_count)));
716 
717  if (numa_max_node() >= 3)
718  SCLog(log_level, __FILE__, __FUNCTION__, __LINE__,
719  " NUMA Node 3: %d ", (SC_ATOMIC_GET(numa3_count)));
720 
721  snprintf(string0, 16, "[%d, 16, 0]", SC_ATOMIC_GET(numa0_count));
722  snprintf(string1, 16, (numa_max_node() >= 1 ? ",[%d, 16, 1]" : ""),
723  SC_ATOMIC_GET(numa1_count));
724  snprintf(string2, 16, (numa_max_node() >= 2 ? ",[%d, 16, 2]" : ""),
725  SC_ATOMIC_GET(numa2_count));
726  snprintf(string3, 16, (numa_max_node() >= 3 ? ",[%d, 16, 3]" : ""),
727  SC_ATOMIC_GET(numa3_count));
728 
729  SCLog(log_level, __FILE__, __FUNCTION__, __LINE__,
730  "E.g.: HostBuffersRx=%s%s%s%s", string0, string1, string2,
731  string3);
732  } else if (log_level == SC_LOG_ERROR) {
734  "Or, try running /opt/napatech3/bin/ntpl -e \"delete=all\" to clean-up stream NUMA config.");
735  }
736 }
737 
738 /**
739  * \brief Main Napatechpacket processing loop
740  *
741  * \param tv Thread variable to ThreadVars
742  * \param data Pointer to NapatechThreadVars with data specific to Napatech
743  * \param slot TMSlot where this instance is running.
744  *
745  */
746 TmEcode NapatechPacketLoop(ThreadVars *tv, void *data, void *slot)
747 {
748  int32_t status;
749  char error_buffer[100];
750  uint64_t pkt_ts;
751  NtNetBuf_t packet_buffer;
752  NapatechThreadVars *ntv = (NapatechThreadVars *) data;
753  uint64_t hba_pkt_drops = 0;
754  uint64_t hba_byte_drops = 0;
755  uint16_t hba_pkt = 0;
756  int numa_node = -1;
757  int set_cpu_affinity = 0;
758  int closer = 0;
759  int is_inline = 0;
760  int is_autoconfig = 0;
761 
762  /* This just keeps the startup output more orderly. */
763  usleep(200000 * ntv->stream_id);
764 
765  if (ConfGetBool("napatech.inline", &is_inline) == 0) {
766  is_inline = 0;
767  }
768  if (ConfGetBool("napatech.auto-config", &is_autoconfig) == 0) {
769  is_autoconfig = 0;
770  }
771 
772  if (is_autoconfig) {
773  numa_node = GetNumaNode();
774  switch (numa_node) {
775  case 0:
776  SC_ATOMIC_ADD(numa0_count, 1);
777  break;
778  case 1:
779  SC_ATOMIC_ADD(numa1_count, 1);
780  break;
781  case 2:
782  SC_ATOMIC_ADD(numa2_count, 1);
783  break;
784  case 3:
785  SC_ATOMIC_ADD(numa3_count, 1);
786  break;
787  default:
788  break;
789  }
790 
791  if (ConfGetBool("threading.set-cpu-affinity", &set_cpu_affinity) != 1) {
792  set_cpu_affinity = 0;
793  }
794 
795  if (set_cpu_affinity) {
796  NapatechSetupNuma(ntv->stream_id, numa_node);
797  }
798 
799  numa_node = GetNumaNode();
800  SC_ATOMIC_ADD(stream_count, 1);
801  if (SC_ATOMIC_GET(stream_count) == NapatechGetNumConfiguredStreams()) {
802 
803 #ifdef NAPATECH_ENABLE_BYPASS
804  /* Initialize the port map before we setup traffic filters */
805  for (int i = 0; i < MAX_PORTS; ++i) {
806  inline_port_map[i] = -1;
807  }
808 #endif
809  /* The last thread to run sets up and deletes the streams */
812 
813  closer = 1;
814 
815  if (status == 0x20002061) {
817  "Check host buffer configuration in ntservice.ini.");
818  RecommendNUMAConfig(SC_LOG_ERROR);
819  exit(EXIT_FAILURE);
820 
821  } else if (status == 0x20000008) {
823  "Check napatech.ports in the suricata config file.");
824  exit(EXIT_FAILURE);
825  }
826  RecommendNUMAConfig(SC_LOG_PERF);
827  SCLogNotice("Napatech packet input engine started.");
828  }
829  } // is_autoconfig
830 
831  SCLogInfo(
832  "Napatech Packet Loop Started - cpu: %3d, cpu_numa: %3d stream: %3u ",
833  sched_getcpu(), numa_node, ntv->stream_id);
834 
835  if (ntv->hba > 0) {
836  char *s_hbad_pkt = SCCalloc(1, 32);
837  if (unlikely(s_hbad_pkt == NULL)) {
839  "Failed to allocate memory for NAPATECH stream counter.");
840  exit(EXIT_FAILURE);
841  }
842  snprintf(s_hbad_pkt, 32, "nt%d.hba_drop", ntv->stream_id);
843  hba_pkt = StatsRegisterCounter(s_hbad_pkt, tv);
845  StatsSetUI64(tv, hba_pkt, 0);
846  }
847  SCLogDebug("Opening NAPATECH Stream: %lu for processing", ntv->stream_id);
848 
849  if ((status = NT_NetRxOpen(&(ntv->rx_stream), "SuricataStream",
850  NT_NET_INTERFACE_PACKET, ntv->stream_id, ntv->hba)) != NT_SUCCESS) {
851 
853  SCFree(ntv);
855  }
856  TmSlot *s = (TmSlot *) slot;
857  ntv->slot = s->slot_next;
858 
859  while (!(suricata_ctl_flags & SURICATA_STOP)) {
860  /* make sure we have at least one packet in the packet pool, to prevent
861  * us from alloc'ing packets at line rate */
862  PacketPoolWait();
863 
864  /* Napatech returns packets 1 at a time */
865  status = NT_NetRxGet(ntv->rx_stream, &packet_buffer, 1000);
866  if (unlikely(
867  status == NT_STATUS_TIMEOUT || status == NT_STATUS_TRYAGAIN)) {
868  continue;
869  } else if (unlikely(status != NT_SUCCESS)) {
871  SCLogInfo("Failed to read from Napatech Stream %d: %s",
872  ntv->stream_id, error_buffer);
873  break;
874  }
875 
877 #ifdef NAPATECH_ENABLE_BYPASS
878  p->ntpv.bypass = 0;
879 #endif
880 
881  if (unlikely(p == NULL)) {
882  NT_NetRxRelease(ntv->rx_stream, packet_buffer);
884  }
885 
886  pkt_ts = NT_NET_GET_PKT_TIMESTAMP(packet_buffer);
887 
888  /*
889  * Handle the different timestamp forms that the napatech cards could use
890  * - NT_TIMESTAMP_TYPE_NATIVE is not supported due to having an base
891  * of 0 as opposed to NATIVE_UNIX which has a base of 1/1/1970
892  */
893  switch (NT_NET_GET_PKT_TIMESTAMP_TYPE(packet_buffer)) {
894  case NT_TIMESTAMP_TYPE_NATIVE_UNIX:
895  p->ts.tv_sec = pkt_ts / 100000000;
896  p->ts.tv_usec = ((pkt_ts % 100000000) / 100) + (pkt_ts % 100) > 50 ? 1 : 0;
897  break;
898  case NT_TIMESTAMP_TYPE_PCAP:
899  p->ts.tv_sec = pkt_ts >> 32;
900  p->ts.tv_usec = pkt_ts & 0xFFFFFFFF;
901  break;
902  case NT_TIMESTAMP_TYPE_PCAP_NANOTIME:
903  p->ts.tv_sec = pkt_ts >> 32;
904  p->ts.tv_usec = ((pkt_ts & 0xFFFFFFFF) / 1000) + (pkt_ts % 1000) > 500 ? 1 : 0;
905  break;
906  case NT_TIMESTAMP_TYPE_NATIVE_NDIS:
907  /* number of seconds between 1/1/1601 and 1/1/1970 */
908  p->ts.tv_sec = (pkt_ts / 100000000) - 11644473600;
909  p->ts.tv_usec = ((pkt_ts % 100000000) / 100) + (pkt_ts % 100) > 50 ? 1 : 0;
910  break;
911  default:
913  "Packet from Napatech Stream: %u does not have a supported timestamp format",
914  ntv->stream_id);
915  NT_NetRxRelease(ntv->rx_stream, packet_buffer);
917  }
918 
919  if (unlikely(ntv->hba > 0)) {
920  NtNetRx_t stat_cmd;
921  stat_cmd.cmd = NT_NETRX_READ_CMD_STREAM_DROP;
922  /* Update drop counter */
923  if (unlikely((status = NT_NetRxRead(ntv->rx_stream, &stat_cmd)) != NT_SUCCESS)) {
925  SCLogInfo("Couldn't retrieve drop statistics from the RX stream: %u",
926  ntv->stream_id);
927  } else {
928  hba_pkt_drops = stat_cmd.u.streamDrop.pktsDropped;
929 
930  StatsSetUI64(tv, hba_pkt, hba_pkt_drops);
931  }
933  }
934 
935 #ifdef NAPATECH_ENABLE_BYPASS
936  p->ntpv.dyn3 = _NT_NET_GET_PKT_DESCR_PTR_DYN3(packet_buffer);
937  p->BypassPacketsFlow = (NapatechIsBypassSupported() ? NapatechBypassCallback : NULL);
938  NT_NET_SET_PKT_TXPORT(packet_buffer, inline_port_map[p->ntpv.dyn3->rxPort]);
939 #endif
940  p->ReleasePacket = NapatechReleasePacket;
941  p->ntpv.nt_packet_buf = packet_buffer;
942  p->ntpv.stream_id = ntv->stream_id;
944 
945  if (unlikely(PacketSetData(p, (uint8_t *)NT_NET_GET_PKT_L2_PTR(packet_buffer), NT_NET_GET_PKT_WIRE_LENGTH(packet_buffer)))) {
946  TmqhOutputPacketpool(ntv->tv, p);
947  NT_NetRxRelease(ntv->rx_stream, packet_buffer);
949  }
950 
951  if (unlikely(TmThreadsSlotProcessPkt(ntv->tv, ntv->slot, p) != TM_ECODE_OK)) {
952  NT_NetRxRelease(ntv->rx_stream, packet_buffer);
954  }
955 
956  /* Release any packets that were returned by the callback function */
957  Packet *rel_pkt = PacketDequeue(&packets_to_release[ntv->stream_id]);
958  while (rel_pkt != NULL) {
959 #ifdef NAPATECH_ENABLE_BYPASS
960  if (rel_pkt->ntpv.bypass == 1) {
962  if (is_inline) {
963  rel_pkt->ntpv.dyn3->wireLength = 0;
964  }
965  }
966  ProgramFlow(rel_pkt, is_inline);
967  }
968 #endif
969  NT_NetRxRelease(ntv->rx_stream, rel_pkt->ntpv.nt_packet_buf);
970  rel_pkt = PacketDequeue(&packets_to_release[ntv->stream_id]);
971  }
973  } // while
974 
975  if (closer) {
976 #ifdef NAPATECH_ENABLE_BYPASS
977  NapatechCloseFlowStreams();
978 #endif
980  }
981 
982  if (unlikely(ntv->hba > 0)) {
983  SCLogInfo("Host Buffer Allowance Drops - pkts: %ld, bytes: %ld", hba_pkt_drops, hba_byte_drops);
984  }
985 
987 }
988 
989 /**
990  * \brief Print some stats to the log at program exit.
991  *
992  * \param tv Pointer to ThreadVars.
993  * \param data Pointer to data, ErfFileThreadVars.
994  */
996 {
997  NapatechThreadVars *ntv = (NapatechThreadVars *) data;
999 
1000  double percent = 0;
1001  if (stat.current_drop_packets > 0)
1002  percent = (((double) stat.current_drop_packets)
1003  / (stat.current_packets + stat.current_drop_packets)) * 100;
1004 
1005  SCLogInfo("nt%lu - pkts: %lu; drop: %lu (%5.2f%%); bytes: %lu",
1006  (uint64_t) ntv->stream_id, stat.current_packets,
1007  stat.current_drop_packets, percent, stat.current_bytes);
1008 
1009  SC_ATOMIC_ADD(total_packets, stat.current_packets);
1010  SC_ATOMIC_ADD(total_drops, stat.current_drop_packets);
1011  SC_ATOMIC_ADD(total_tallied, 1);
1012 
1013  if (SC_ATOMIC_GET(total_tallied) == NapatechGetNumConfiguredStreams()) {
1014  if (SC_ATOMIC_GET(total_drops) > 0)
1015  percent = (((double) SC_ATOMIC_GET(total_drops)) / (SC_ATOMIC_GET(total_packets)
1016  + SC_ATOMIC_GET(total_drops))) * 100;
1017 
1018  SCLogInfo(" ");
1019  SCLogInfo("--- Total Packets: %ld Total Dropped: %ld (%5.2f%%)",
1020  SC_ATOMIC_GET(total_packets), SC_ATOMIC_GET(total_drops), percent);
1021 
1022 #ifdef NAPATECH_ENABLE_BYPASS
1023  SCLogInfo("--- BypassCB - Total: %ld, UDP: %ld, TCP: %ld, Unhandled: %ld",
1024  SC_ATOMIC_GET(flow_callback_cnt),
1025  SC_ATOMIC_GET(flow_callback_udp_pkts),
1026  SC_ATOMIC_GET(flow_callback_tcp_pkts),
1027  SC_ATOMIC_GET(flow_callback_unhandled_pkts));
1028 #endif
1029  }
1030 }
1031 
1032 /**
1033  * \brief Deinitializes the NAPATECH card.
1034  * \param tv pointer to ThreadVars
1035  * \param data pointer that gets cast into PcapThreadVars for ptv
1036  */
1038 {
1039  SCEnter();
1040  NapatechThreadVars *ntv = (NapatechThreadVars *) data;
1041 
1042  SCLogDebug("Closing Napatech Stream: %d", ntv->stream_id);
1043  NT_NetRxClose(ntv->rx_stream);
1044 
1046 }
1047 
1048 /**
1049  * \brief This function passes off to link type decoders.
1050  *
1051  * NapatechDecode decodes packets from Napatech and passes
1052  * them off to the proper link type decoder.
1053  *
1054  * \param t pointer to ThreadVars
1055  * \param p pointer to the current packet
1056  * \param data pointer that gets cast into PcapThreadVars for ptv
1057  */
1059 {
1060  SCEnter();
1061 
1063 
1065 
1066  // update counters
1068 
1069  switch (p->datalink) {
1070  case LINKTYPE_ETHERNET:
1072  break;
1073  default:
1075  "Datalink type %" PRId32 " not yet supported in module NapatechDecode",
1076  p->datalink);
1077  break;
1078  }
1079 
1082 }
1083 
1084 /**
1085  * \brief Initialization of Napatech Thread.
1086  *
1087  * \param t pointer to ThreadVars
1088  * \param initdata - unused.
1089  * \param data pointer that gets cast into DecoderThreadVars
1090  */
1091 TmEcode NapatechDecodeThreadInit(ThreadVars *tv, const void *initdata, void **data)
1092 {
1093  SCEnter();
1094  DecodeThreadVars *dtv = NULL;
1096  if (dtv == NULL) {
1098  }
1099 
1101  *data = (void *) dtv;
1103 }
1104 
1105 /**
1106  * \brief Deinitialization of Napatech Thread.
1107  *
1108  * \param tv pointer to ThreadVars
1109  * \param data pointer that gets cast into DecoderThreadVars
1110  */
1112 {
1113  if (data != NULL) {
1114  DecodeThreadVarsFree(tv, data);
1115  }
1117 }
1118 
1119 #endif /* HAVE_NAPATECH */
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:67
TMM_RECEIVENAPATECH
@ TMM_RECEIVENAPATECH
Definition: tm-threads-common.h:57
PKT_IS_UDP
#define PKT_IS_UDP(p)
Definition: decode.h:255
NapatechPacketVars_::stream_id
uint64_t stream_id
Definition: util-napatech.h:31
tm-threads.h
NapatechStreamThreadInit
TmEcode NapatechStreamThreadInit(ThreadVars *, const void *, void **)
Initialize the Napatech receiver thread, generate a single NapatechThreadVar structure for each threa...
Definition: source-napatech.c:622
NapatechGetCurrentStats
NapatechCurrentStats NapatechGetCurrentStats(uint16_t id)
Definition: util-napatech.c:223
max_pending_packets
int max_pending_packets
Definition: suricata.c:212
NapatechPacketVars_
Definition: util-napatech.h:29
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:165
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it's lock.
Definition: util-atomic.h:81
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1115
ConfGetBool
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as an boolen.
Definition: conf.c:517
NapatechSetPortmap
int NapatechSetPortmap(int port, int peer)
SCFree
#define SCFree(a)
Definition: util-mem.h:322
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
NapatechThreadVars_::rx_stream
NtNetStreamRx_t rx_stream
Definition: source-napatech.c:87
NapatechStreamDevConf
Definition: source-napatech.h:34
SC_ERR_NAPATECH_NOSUPPORT
@ SC_ERR_NAPATECH_NOSUPPORT
Definition: util-error.h:248
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:335
PacketEnqueue
void PacketEnqueue(PacketQueue *q, Packet *p)
Definition: packet-queue.c:173
TMM_DECODENAPATECH
@ TMM_DECODENAPATECH
Definition: tm-threads-common.h:58
PacketQueue_
simple fifo queue for packets with mutex and cond Calling the mutex or triggering the cond is respons...
Definition: packet-queue.h:47
NapatechDecode
TmEcode NapatechDecode(ThreadVars *, Packet *, void *)
This function passes off to link type decoders.
Definition: source-napatech.c:1058
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:107
StatsSetUI64
void StatsSetUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Sets a value of type double to the local counter.
Definition: counters.c:190
NapatechStreamDevConf::stream_id
uint16_t stream_id
Definition: source-napatech.h:36
NapatechDeleteFilters
uint32_t NapatechDeleteFilters(void)
Definition: util-napatech.c:1364
SC_ERR_NAPATECH_TIMESTAMP_TYPE_NOT_SUPPORTED
@ SC_ERR_NAPATECH_TIMESTAMP_TYPE_NOT_SUPPORTED
Definition: util-error.h:250
SURICATA_STOP
#define SURICATA_STOP
Definition: suricata.h:95
StatsSetupPrivate
int StatsSetupPrivate(ThreadVars *tv)
Definition: counters.c:1194
tm-modules.h
util-privs.h
NapatechThreadVars_::hba
int hba
Definition: source-napatech.c:89
StatsSyncCountersIfSignalled
#define StatsSyncCountersIfSignalled(tv)
Definition: counters.h:137
PacketDecodeFinalize
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition: decode.c:118
proto
uint8_t proto
Definition: decode-template.h:2
NapatechStreamDevConf::hba
intmax_t hba
Definition: source-napatech.h:37
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:449
Packet_::BypassPacketsFlow
int(* BypassPacketsFlow)(struct Packet_ *)
Definition: decode.h:488
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:79
tmqh-packetpool.h
TmModule_::PktAcqLoop
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-modules.h:54
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:78
SC_ERR_NAPATECH_OPEN_FAILED
@ SC_ERR_NAPATECH_OPEN_FAILED
Definition: util-error.h:246
NapatechThreadVars_
Definition: source-napatech.c:84
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:49
Packet_::datalink
int datalink
Definition: decode.h:575
NapatechStreamThreadDeinit
TmEcode NapatechStreamThreadDeinit(ThreadVars *tv, void *data)
Deinitializes the NAPATECH card.
Definition: source-napatech.c:1037
__attribute__
enum @34 __attribute__
DNP3 application header.
Definition: detect-engine-analyzer.c:583
PKT_IS_TCP
#define PKT_IS_TCP(p)
Definition: decode.h:254
DecodeRegisterPerfCounters
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition: decode.c:477
SC_LOG_ERROR
@ SC_LOG_ERROR
Definition: util-debug.h:57
NapatechCurrentStats_::current_packets
uint64_t current_packets
Definition: util-napatech.h:49
TmModule_::PktAcqBreakLoop
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition: tm-modules.h:57
source-napatech.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:337
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:226
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
TmModule_::Func
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition: tm-modules.h:52
SC_CAP_NET_ADMIN
#define SC_CAP_NET_ADMIN
Definition: util-privs.h:31
NapatechThreadVars_::slot
TmSlot * slot
Definition: source-napatech.c:90
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:265
NapatechGetAdapter
int NapatechGetAdapter(uint8_t port)
PacketPoolWait
void PacketPoolWait(void)
Definition: tmqh-packetpool.c:148
NAPATECH_ERROR
#define NAPATECH_ERROR(err_type, status)
Definition: util-napatech.h:63
util-napatech.h
Packet_
Definition: decode.h:408
TM_FLAG_DECODE_TM
#define TM_FLAG_DECODE_TM
Definition: tm-modules.h:32
SCCalloc
#define SCCalloc(nm, a)
Definition: util-mem.h:253
TmModuleNapatechDecodeRegister
void TmModuleNapatechDecodeRegister(void)
Register the Napatech decoder module.
Definition: source-napatech.c:163
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:33
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:225
SC_ERR_NAPATECH_PARSE_CONFIG
@ SC_ERR_NAPATECH_PARSE_CONFIG
Definition: util-error.h:255
NapatechGetNumConfiguredStreams
uint16_t NapatechGetNumConfiguredStreams(void)
Definition: runmode-napatech.c:54
TmModule_::RegisterTests
void(* RegisterTests)(void)
Definition: tm-modules.h:65
TmSlot_
Definition: tm-threads.h:52
NapatechCurrentStats_::current_bytes
uint64_t current_bytes
Definition: util-napatech.h:50
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(uint64_t, total_packets)
TmEcode
TmEcode
Definition: tm-threads-common.h:77
NapatechDecodeThreadInit
TmEcode NapatechDecodeThreadInit(ThreadVars *, const void *, void **)
Initialization of Napatech Thread.
Definition: source-napatech.c:1091
TmModule_::name
const char * name
Definition: tm-modules.h:44
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
SCLogLevel
SCLogLevel
The various log levels NOTE: when adding new level, don't forget to update SCLogMapLogLevelToSyslogLe...
Definition: util-debug.h:51
TM_FLAG_RECEIVE_TM
#define TM_FLAG_RECEIVE_TM
Definition: tm-modules.h:31
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
Packet_::ntpv
NapatechPacketVars ntpv
Definition: decode.h:606
tm-queuehandlers.h
Packet_::ReleasePacket
void(* ReleasePacket)(struct Packet_ *)
Definition: decode.h:485
NapatechThreadVars
struct NapatechThreadVars_ NapatechThreadVars
DecodeThreadVarsFree
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition: decode.c:636
Packet_::ts
struct timeval ts
Definition: decode.h:452
suricata-common.h
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
SC_LOG_PERF
@ SC_LOG_PERF
Definition: util-debug.h:61
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:47
NapatechGetNumFirstStream
uint16_t NapatechGetNumFirstStream(void)
Definition: runmode-napatech.c:59
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
util-optimize.h
TmModule_::ThreadExitPrintStats
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-modules.h:48
PacketDequeue
Packet * PacketDequeue(PacketQueue *q)
Definition: packet-queue.c:212
threadvars.h
SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED
@ SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED
Definition: util-error.h:253
NapatechGetNumLastStream
uint16_t NapatechGetNumLastStream(void)
Definition: runmode-napatech.c:64
NapatechPacketVars_::nt_packet_buf
NtNetBuf_t nt_packet_buf
Definition: util-napatech.h:32
SCLogWarning
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
MAX_PORTS
#define MAX_PORTS
Definition: util-napatech.h:57
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:622
NapatechThreadVars_::tv
ThreadVars * tv
Definition: source-napatech.c:86
NapatechDecodeThreadDeinit
TmEcode NapatechDecodeThreadDeinit(ThreadVars *tv, void *data)
Deinitialization of Napatech Thread.
Definition: source-napatech.c:1111
payload_len
uint16_t payload_len
Definition: stream-tcp-private.h:61
DecodeThreadVarsAlloc
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition: decode.c:617
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:656
SC_ERR_DATALINK_UNIMPLEMENTED
@ SC_ERR_DATALINK_UNIMPLEMENTED
Definition: util-error.h:68
NapatechStreamThreadExitStats
void NapatechStreamThreadExitStats(ThreadVars *, void *)
Print some stats to the log at program exit.
Definition: source-napatech.c:995
NapatechCurrentStats_::current_drop_packets
uint64_t current_drop_packets
Definition: util-napatech.h:51
SC_ERR_MEM_ALLOC
@ SC_ERR_MEM_ALLOC
Definition: util-error.h:31
TmModuleNapatechStreamRegister
void TmModuleNapatechStreamRegister(void)
Register the Napatech receiver (reader) module.
Definition: source-napatech.c:130
suricata.h
NapatechSetupTraffic
uint32_t NapatechSetupTraffic(uint32_t first_stream, uint32_t last_stream)
Definition: util-napatech.c:1391
NapatechThreadVars_::stream_id
uint16_t stream_id
Definition: source-napatech.c:88
NapatechCurrentStats_
Definition: util-napatech.h:47
TmSlot_::slot_next
struct TmSlot_ * slot_next
Definition: tm-threads.h:61
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:192
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:269
StatsRegisterCounter
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition: counters.c:939
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:341
PacketGetFromQueueOrAlloc
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:180
SC_CAP_NET_RAW
#define SC_CAP_NET_RAW
Definition: util-privs.h:32
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:70
DecodeUpdatePacketCounters
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition: decode.c:583
MAX_STREAMS
#define MAX_STREAMS
Definition: runmode-napatech.c:47
LINKTYPE_ETHERNET
#define LINKTYPE_ETHERNET
Definition: decode.h:1057
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:198
NapatechSetupNuma
bool NapatechSetupNuma(uint32_t stream, uint32_t numa)
Definition: util-napatech.c:1253
NapatechPacketLoop
TmEcode NapatechPacketLoop(ThreadVars *tv, void *data, void *slot)
Main Napatechpacket processing loop.
Definition: source-napatech.c:746
PACKET_TEST_ACTION
#define PACKET_TEST_ACTION(p, a)
Definition: decode.h:847
SCLog
#define SCLog(x, file, func, line,...)
Definition: util-debug.h:211