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