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