suricata
util-napatech.c
Go to the documentation of this file.
1 /* Copyright (C) 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 Napatech Inc.
22  * \author Phil Young <py@napatech.com>
23  *
24  *
25  */
26 
27 
28 #include "suricata-common.h"
29 #ifdef HAVE_NAPATECH
30 #include "suricata.h"
31 #include "threadvars.h"
32 #include "tm-threads.h"
33 
34 
35 uint16_t NapatechGetNumaNode(uint16_t stream_id)
36 {
37  int status;
38  char buffer[80]; // Error buffer
39  NtInfoStream_t info_stream;
40  NtInfo_t info;
41  uint16_t numa_node;
42 
43  if ((status = NT_InfoOpen(&info_stream, "SuricataStreamInfo")) != NT_SUCCESS) {
44  NT_ExplainError(status, buffer, sizeof (buffer) - 1);
45  SCLogError(SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED, "NT_InfoOpen failed: %s", buffer);
46  exit(EXIT_FAILURE);
47  }
48 
49  // Read the info on this specific stream
50  info.cmd = NT_INFO_CMD_READ_STREAMID;
51  info.u.streamID.streamId = stream_id;
52  if ((status = NT_InfoRead(info_stream, &info)) != NT_SUCCESS) {
53  NT_ExplainError(status, buffer, sizeof (buffer) - 1);
54  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_InfoRead() failed: %s\n", buffer);
55  exit(EXIT_FAILURE);
56  }
57 
58  numa_node = info.u.streamID.data.numaNode;
59 
60  if ((status = NT_InfoClose(info_stream)) != NT_SUCCESS) {
61  NT_ExplainError(status, buffer, sizeof (buffer) - 1);
62  SCLogError(SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED, "NT_InfoClose failed: %s", buffer);
63  exit(EXIT_FAILURE);
64  }
65  return numa_node;
66 }
67 
68 
69 /*-----------------------------------------------------------------------------
70  *-----------------------------------------------------------------------------
71  * Statistics code
72  *-----------------------------------------------------------------------------
73 */
74 
75 typedef struct StreamCounters_ {
76  uint16_t pkts;
77  uint16_t byte;
78  uint16_t drop;
80 
81 
83 
85 {
86 
87  return current_stats[id];
88 }
89 
90 
91 static uint16_t TestStreamConfig(
92  NtInfoStream_t hInfo,
93  NtStatStream_t hStatStream,
95  uint16_t num_inst)
96 {
97 
98  uint16_t num_active = 0;
99 
100  for (uint16_t inst = 0; inst < num_inst; ++inst) {
101  int status;
102  char buffer[80]; // Error buffer
103  NtStatistics_t stat; // Stat handle.
104 
105  /* Check to see if it is an active stream */
106  memset(&stat, 0, sizeof (NtStatistics_t));
107 
108  /* Read usage data for the chosen stream ID */
109  stat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
110  stat.u.usageData_v0.streamid = (uint8_t) stream_config[inst].stream_id;
111 
112  if ((status = NT_StatRead(hStatStream, &stat)) != NT_SUCCESS) {
113  /* Get the status code as text */
114  NT_ExplainError(status, buffer, sizeof (buffer));
115  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_StatRead():2 failed: %s\n", buffer);
116  return 0;
117  }
118 
119  if (stat.u.usageData_v0.data.numHostBufferUsed > 0) {
120  stream_config[inst].is_active = true;
121  num_active++;
122  } else {
123  stream_config[inst].is_active = false;
124  }
125  }
126 
127  return num_active;
128 }
129 
130 static uint32_t UpdateStreamStats(ThreadVars *tv,
131  NtInfoStream_t hInfo,
132  NtStatStream_t hStatStream,
133  uint16_t num_streams,
134  NapatechStreamConfig stream_config[],
135  StreamCounters streamCounters[]
136  )
137 {
138  static uint64_t rxPktsStart[MAX_STREAMS] = {0};
139  static uint64_t rxByteStart[MAX_STREAMS] = {0};
140  static uint64_t dropStart[MAX_STREAMS] = {0};
141 
142  int status;
143  char error_buffer[80]; // Error buffer
144  NtInfo_t hStreamInfo;
145  NtStatistics_t hStat; // Stat handle.
146 
147  /* Query the system to get the number of streams currently instantiated */
148  hStreamInfo.cmd = NT_INFO_CMD_READ_STREAM;
149  if ((status = NT_InfoRead(hInfo, &hStreamInfo)) != NT_SUCCESS) {
150  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
151  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_InfoRead() failed: %s\n", error_buffer);
152  exit(EXIT_FAILURE);
153  }
154 
155  uint16_t num_active;
156  if ((num_active = TestStreamConfig(hInfo, hStatStream, stream_config, num_streams)) == 0) {
157  /* None of the configured streams are active */
158  return 0;
159  }
160 
161  /* At least one stream is active so proceed with the stats. */
162  uint16_t inst_id = 0;
163  uint32_t stream_cnt = 0;
164  for (stream_cnt = 0; stream_cnt < num_streams; ++stream_cnt) {
165 
166 
167  while(inst_id < num_streams) {
168  if (stream_config[inst_id].is_active) {
169  break;
170  } else {
171  ++inst_id;
172  }
173  }
174  if (inst_id == num_streams)
175  break;
176 
177  /* Read usage data for the chosen stream ID */
178  memset(&hStat, 0, sizeof (NtStatistics_t));
179  hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
180  hStat.u.usageData_v0.streamid = (uint8_t) stream_config[inst_id].stream_id;
181 
182  if ((status = NT_StatRead(hStatStream, &hStat)) != NT_SUCCESS) {
183  /* Get the status code as text */
184  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
185  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_StatRead() failed: %s\n", error_buffer);
186  return 0;
187  }
188 
189  uint16_t stream_id = stream_config[inst_id].stream_id;
190  if (stream_config[inst_id].is_active) {
191  uint64_t rxPktsTotal = 0;
192  uint64_t rxByteTotal = 0;
193  uint64_t dropTotal = 0;
194 
195  for (uint32_t hbCount = 0; hbCount < hStat.u.usageData_v0.data.numHostBufferUsed; hbCount++) {
196  if (unlikely(stream_config[inst_id].initialized == false)) {
197  rxPktsStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.frames;
198  rxByteStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.bytes;
199  dropStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.frames;
200  stream_config[inst_id].initialized = true;
201  } else {
202  rxPktsTotal += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.frames;
203  rxByteTotal += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.bytes;
204  dropTotal += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.frames;
205  }
206  }
207 
208  current_stats[stream_id].current_packets = rxPktsTotal - rxPktsStart[stream_id];
209  current_stats[stream_id].current_bytes = rxByteTotal - rxByteStart[stream_id];
210  current_stats[stream_id].current_drops = dropTotal - dropStart[stream_id];
211  }
212 
213  StatsSetUI64(tv, streamCounters[inst_id].pkts, current_stats[stream_id].current_packets);
214  StatsSetUI64(tv, streamCounters[inst_id].byte, current_stats[stream_id].current_bytes);
215  StatsSetUI64(tv, streamCounters[inst_id].drop, current_stats[stream_id].current_drops);
216 
217  ++inst_id;
218  }
219  return num_active;
220 }
221 
222 static void *NapatechStatsLoop(void *arg)
223 {
224  ThreadVars *tv = (ThreadVars *) arg;
225 
226  int status;
227  char error_buffer[80]; // Error buffer
228  NtInfoStream_t hInfo;
229  NtStatStream_t hStatStream;
230 
231  NapatechStreamConfig stream_config[MAX_STREAMS];
232  uint16_t stream_cnt = NapatechGetStreamConfig(stream_config);
233 
234  /* Open the info and Statistics */
235  if ((status = NT_InfoOpen(&hInfo, "StatsLoopInfoStream")) != NT_SUCCESS) {
236  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
237  SCLogError(SC_ERR_RUNMODE, "NT_InfoOpen() failed: %s\n", error_buffer);
238  return NULL;
239  }
240 
241  if ((status = NT_StatOpen(&hStatStream, "StatsLoopStatsStream")) != NT_SUCCESS) {
242  /* Get the status code as text */
243  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
244  SCLogError(SC_ERR_RUNMODE, "NT_StatOpen() failed: %s\n", error_buffer);
245  return NULL;
246  }
247 
248  StreamCounters streamCounters[MAX_STREAMS];
249  for (int i = 0; i < stream_cnt; ++i) {
250  char *pkts_buf = SCCalloc(1, 32);
251  if (unlikely(pkts_buf == NULL)) {
252  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for NAPATECH stream counter.");
253  exit(EXIT_FAILURE);
254  }
255 
256  snprintf(pkts_buf, 32, "nt%d.pkts", stream_config[i].stream_id);
257  streamCounters[i].pkts = StatsRegisterCounter(pkts_buf, tv);
258 
259  char *byte_buf = SCCalloc(1, 32);
260  if (unlikely(byte_buf == NULL)) {
261  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for NAPATECH stream counter.");
262  exit(EXIT_FAILURE);
263  }
264  snprintf(byte_buf, 32, "nt%d.bytes", stream_config[i].stream_id);
265  streamCounters[i].byte = StatsRegisterCounter(byte_buf, tv);
266 
267  char *drop_buf = SCCalloc(1, 32);
268  if (unlikely(drop_buf == NULL)) {
269  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for NAPATECH stream counter.");
270  exit(EXIT_FAILURE);
271  }
272  snprintf(drop_buf, 32, "nt%d.drop", stream_config[i].stream_id);
273  streamCounters[i].drop = StatsRegisterCounter(drop_buf, tv);
274  }
275 
276  StatsSetupPrivate(tv);
277 
278  for (int i = 0; i < stream_cnt; ++i) {
279  StatsSetUI64(tv, streamCounters[i].pkts, 0);
280  StatsSetUI64(tv, streamCounters[i].byte, 0);
281  StatsSetUI64(tv, streamCounters[i].drop, 0);
282  }
283 
284  uint32_t num_active = UpdateStreamStats(tv, hInfo, hStatStream,
285  stream_cnt, stream_config, streamCounters);
286 
287  if (num_active < stream_cnt) {
288  SCLogInfo("num_active: %d, stream_cnt: %d", num_active, stream_cnt);
290  "Some or all of the configured streams are not created. Proceeding with active streams.");
291  }
292 
294  while (1) {
295  if (TmThreadsCheckFlag(tv, THV_KILL)) {
296  SCLogDebug("NapatechStatsLoop THV_KILL detected");
297  break;
298  }
299 
300  UpdateStreamStats(tv, hInfo, hStatStream,
301  stream_cnt, stream_config, streamCounters);
302 
304  usleep(1000000);
305  }
306 
307  /* CLEAN UP NT Resources and Close the info stream */
308  if ((status = NT_InfoClose(hInfo)) != NT_SUCCESS) {
309  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
310  SCLogError(SC_ERR_RUNMODE, "NT_InfoClose() failed: %s\n", error_buffer);
311  return NULL;
312  }
313 
314  /* Close the statistics stream */
315  if ((status = NT_StatClose(hStatStream)) != NT_SUCCESS) {
316  /* Get the status code as text */
317  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
318  SCLogError(SC_ERR_RUNMODE, "NT_StatClose() failed: %s\n", error_buffer);
319  return NULL;
320  }
321 
322 
323  SCLogDebug("Exiting NapatechStatsLoop");
327 
328  return NULL;
329 }
330 
331 #define MAX_HOSTBUFFER 4
332 #define MAX_STREAMS 256
333 #define HB_HIGHWATER 2048 //1982
334 
335 static bool RegisteredStream(uint16_t stream_id, uint16_t num_registered,
336  NapatechStreamConfig registered_streams[])
337 {
338  for (uint16_t reg_id = 0; reg_id < num_registered; ++reg_id) {
339  if (stream_id == registered_streams[reg_id].stream_id) {
340  return true;
341  }
342  }
343  return false;
344 }
345 
347 {
348  int status;
349  char error_buffer[80]; // Error buffer
350  NtStatStream_t hStatStream;
351  NtStatistics_t hStat; // Stat handle.
352  NtInfoStream_t info_stream;
353  NtInfo_t info;
354  uint16_t instance_cnt = 0;
355  int use_all_streams;
356  ConfNode *ntstreams;
357 
358  for (uint16_t i = 0; i < MAX_STREAMS; ++i) {
359  stream_config[i].stream_id = 0;
360  stream_config[i].is_active = false;
361  stream_config[i].initialized = false;
362  }
363 
364  if (ConfGetBool("napatech.use-all-streams", &use_all_streams) == 0) {
365  SCLogError(SC_ERR_RUNMODE, "Failed retrieving napatech.use-all-streams from Conf");
366  exit(EXIT_FAILURE);
367  }
368 
369  if ((status = NT_InfoOpen(&info_stream, "SuricataStreamInfo")) != NT_SUCCESS) {
370  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
371  SCLogError(SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED, "NT_InfoOpen failed: %s", error_buffer);
372  exit(EXIT_FAILURE);
373  }
374 
375  if ((status = NT_StatOpen(&hStatStream, "StatsStream")) != NT_SUCCESS) {
376  /* Get the status code as text */
377  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
378  SCLogError(SC_ERR_RUNMODE, "NT_StatOpen() failed: %s\n", error_buffer);
379  exit(EXIT_FAILURE);
380  }
381 
382  if (use_all_streams) {
383  info.cmd = NT_INFO_CMD_READ_STREAM;
384  if ((status = NT_InfoRead(info_stream, &info)) != NT_SUCCESS) {
385  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
386  SCLogError(SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED, "NT_InfoRead failed: %s", error_buffer);
387  exit(EXIT_FAILURE);
388  }
389 
390  uint16_t stream_id = 0;
391  while (instance_cnt < info.u.stream.data.count) {
392 
393  /*
394  * For each stream ID query the number of host-buffers used by
395  * the stream. If zero, then that streamID is not used; skip
396  * over it and continue until we get a streamID with a non-zero
397  * count of the host-buffers.
398  */
399  memset(&hStat, 0, sizeof (NtStatistics_t));
400 
401  /* Read usage data for the chosen stream ID */
402  hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
403  hStat.u.usageData_v0.streamid = (uint8_t) stream_id;
404 
405  if ((status = NT_StatRead(hStatStream, &hStat)) != NT_SUCCESS) {
406  /* Get the status code as text */
407  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
408  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_StatRead() failed: %s\n", error_buffer);
409  return 0;
410  }
411 
412  if (hStat.u.usageData_v0.data.numHostBufferUsed == 0) {
413  ++stream_id;
414  continue;
415  }
416 
417  /* if we get here it is an active stream */
418  stream_config[instance_cnt].stream_id = stream_id++;
419  stream_config[instance_cnt].is_active = true;
420  instance_cnt++;
421  }
422 
423  } else {
424  /* When not using the default streams we need to parse the array of streams from the conf */
425  if ((ntstreams = ConfGetNode("napatech.streams")) == NULL) {
426  SCLogError(SC_ERR_RUNMODE, "Failed retrieving napatech.streams from Conf");
427  exit(EXIT_FAILURE);
428  }
429 
430  /* Loop through all stream numbers in the array and register the devices */
431  ConfNode *stream;
432  instance_cnt = 0;
433 
434  TAILQ_FOREACH(stream, &ntstreams->head, next) {
435  uint16_t stream_id = 0;
436 
437  if (stream == NULL) {
438  SCLogError(SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED, "Couldn't Parse Stream Configuration");
439  exit(EXIT_FAILURE);
440  }
441 
442  uint16_t start, end;
443  if (strchr(stream->val, '-')) {
444  char copystr[16];
445  strlcpy(copystr, stream->val, 16);
446 
447  start = atoi(copystr);
448  end = atoi(strchr(copystr, '-')+1);
449  } else {
450  stream_config[instance_cnt].stream_id = atoi(stream->val);
451  start = stream_config[instance_cnt].stream_id;
452  end = stream_config[instance_cnt].stream_id;
453  }
454  SCLogInfo("%s start: %d end: %d", stream->val, start, end);
455 
456  for (stream_id = start; stream_id <= end; ++stream_id) {
457  /* if we get here it is configured in the .yaml file */
458  stream_config[instance_cnt].stream_id = stream_id;
459 
460  /* Check to see if it is an active stream */
461  memset(&hStat, 0, sizeof (NtStatistics_t));
462 
463  /* Read usage data for the chosen stream ID */
464  hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
465  hStat.u.usageData_v0.streamid = (uint8_t) stream_config[instance_cnt].stream_id;
466 
467  if ((status = NT_StatRead(hStatStream, &hStat)) != NT_SUCCESS) {
468  /* Get the status code as text */
469  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
470  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_StatRead() failed: %s\n", error_buffer);
471  return 0;
472  }
473 
474  if (hStat.u.usageData_v0.data.numHostBufferUsed > 0) {
475  stream_config[instance_cnt].is_active = true;
476  }
477  instance_cnt++;
478  }
479  }
480  }
481 
482  /* Close the statistics stream */
483  if ((status = NT_StatClose(hStatStream)) != NT_SUCCESS) {
484  /* Get the status code as text */
485  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
486  SCLogError(SC_ERR_RUNMODE, "NT_StatClose() failed: %s\n", error_buffer);
487  exit(EXIT_FAILURE);
488  }
489 
490  if ((status = NT_InfoClose(info_stream)) != NT_SUCCESS) {
491  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
493  "NT_InfoClose failed: %s", error_buffer);
494  exit(EXIT_FAILURE);
495  }
496 
497  return instance_cnt;
498 }
499 
500 
501 static void *NapatechBufMonitorLoop(void *arg)
502 {
503  ThreadVars *tv = (ThreadVars *) arg;
504 
505  NtInfo_t hStreamInfo;
506  NtStatistics_t hStat; // Stat handle.
507  NtInfoStream_t hInfo;
508  NtStatStream_t hStatStream;
509 
510  char error_buffer[NT_ERRBUF_SIZE]; // Error buffer
511  int status; // Status variable
512 
513  const uint32_t alertInterval = 25;
514 
515  uint32_t OB_fill_level[MAX_STREAMS] = {0};
516  uint32_t OB_alert_level[MAX_STREAMS] = {0};
517  uint32_t ave_OB_fill_level[MAX_STREAMS] = {0};
518 
519  uint32_t HB_fill_level[MAX_STREAMS] = {0};
520  uint32_t HB_alert_level[MAX_STREAMS] = {0};
521  uint32_t ave_HB_fill_level[MAX_STREAMS] = {0};
522 
523  /* Open the info and Statistics */
524  if ((status = NT_InfoOpen(&hInfo, "InfoStream")) != NT_SUCCESS) {
525  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
526  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_InfoOpen() failed: %s\n", error_buffer);
527  exit(1);
528  }
529 
530  if ((status = NT_StatOpen(&hStatStream, "StatsStream")) != NT_SUCCESS) {
531  /* Get the status code as text */
532  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
533  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_StatOpen() failed: %s\n", error_buffer);
534  exit(1);
535  }
536 
537  /* Read the info on all streams instantiated in the system */
538  hStreamInfo.cmd = NT_INFO_CMD_READ_STREAM;
539  if ((status = NT_InfoRead(hInfo, &hStreamInfo)) != NT_SUCCESS) {
540  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
541  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_InfoRead() failed: %s\n", error_buffer);
542  exit(EXIT_FAILURE);
543  }
544 
545  NapatechStreamConfig registered_streams[MAX_STREAMS];
546  uint16_t num_registered = NapatechGetStreamConfig(registered_streams);
547 
549  while (1) {
550  if (TmThreadsCheckFlag(tv, THV_KILL)) {
551  SCLogDebug("NapatechBufMonitorLoop THV_KILL detected");
552  break;
553  }
554 
555  usleep(200000);
556 
557  /* Read the info on all streams instantiated in the system */
558  hStreamInfo.cmd = NT_INFO_CMD_READ_STREAM;
559  if ((status = NT_InfoRead(hInfo, &hStreamInfo)) != NT_SUCCESS) {
560  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
561  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_InfoRead() failed: %s\n", error_buffer);
562  exit(EXIT_FAILURE);
563  }
564 
565  char pktCntStr[4096];
566  memset(pktCntStr, 0, sizeof (pktCntStr));
567 
568  uint32_t stream_id = 0;
569  uint32_t stream_cnt = 0;
570  uint32_t num_streams = hStreamInfo.u.stream.data.count;
571 
572  for (stream_cnt = 0; stream_cnt < num_streams; ++stream_cnt) {
573 
574  do {
575 
576  /* Read usage data for the chosen stream ID */
577  hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
578  hStat.u.usageData_v0.streamid = (uint8_t) stream_id;
579 
580  if ((status = NT_StatRead(hStatStream, &hStat)) != NT_SUCCESS) {
581  /* Get the status code as text */
582  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
583  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_StatRead() failed: %s\n", error_buffer);
584  exit(1);
585  }
586 
587  if (hStat.u.usageData_v0.data.numHostBufferUsed == 0) {
588  ++stream_id;
589  continue;
590  }
591  } while (hStat.u.usageData_v0.data.numHostBufferUsed == 0);
592 
593  if (RegisteredStream(stream_id, num_registered, registered_streams)) {
594  ave_OB_fill_level[stream_id] = 0;
595  ave_HB_fill_level[stream_id] = 0;
596 
597  for (uint32_t hb_count = 0; hb_count < hStat.u.usageData_v0.data.numHostBufferUsed; hb_count++) {
598 
599  OB_fill_level[hb_count] =
600  ((100 * hStat.u.usageData_v0.data.hb[hb_count].onboardBuffering.used) /
601  hStat.u.usageData_v0.data.hb[hb_count].onboardBuffering.size);
602 
603  if (OB_fill_level[hb_count] > 100) {
604  OB_fill_level[hb_count] = 100;
605  }
606 
607  uint32_t bufSize = hStat.u.usageData_v0.data.hb[hb_count].enQueuedAdapter / 1024
608  + hStat.u.usageData_v0.data.hb[hb_count].deQueued / 1024
609  + hStat.u.usageData_v0.data.hb[hb_count].enQueued / 1024
610  - HB_HIGHWATER;
611 
612  HB_fill_level[hb_count] = (uint32_t)
613  ((100 * hStat.u.usageData_v0.data.hb[hb_count].deQueued / 1024) /
614  bufSize);
615 
616  ave_OB_fill_level[stream_id] += OB_fill_level[hb_count];
617  ave_HB_fill_level[stream_id] += HB_fill_level[hb_count];
618  }
619 
620  ave_OB_fill_level[stream_id] /= hStat.u.usageData_v0.data.numHostBufferUsed;
621  ave_HB_fill_level[stream_id] /= hStat.u.usageData_v0.data.numHostBufferUsed;
622 
623  /* Host Buffer Fill Level warnings... */
624  if (ave_HB_fill_level[stream_id] >= (HB_alert_level[stream_id] + alertInterval)) {
625 
626  while (ave_HB_fill_level[stream_id] >= HB_alert_level[stream_id] + alertInterval) {
627  HB_alert_level[stream_id] += alertInterval;
628  }
629  SCLogInfo("nt%d - Increasing Host Buffer Fill Level : %4d%%",
630  stream_id, ave_HB_fill_level[stream_id]);
631  }
632 
633  if (HB_alert_level[stream_id] > 0) {
634  if ((ave_HB_fill_level[stream_id] <= (HB_alert_level[stream_id] - alertInterval))) {
635  SCLogInfo("nt%d - Decreasing Host Buffer Fill Level: %4d%%",
636  stream_id, ave_HB_fill_level[stream_id]);
637 
638  while (ave_HB_fill_level[stream_id] <= (HB_alert_level[stream_id] - alertInterval)) {
639  if ((HB_alert_level[stream_id]) > 0) {
640  HB_alert_level[stream_id] -= alertInterval;
641  } else break;
642  }
643  }
644  }
645 
646  /* On Board SDRAM Fill Level warnings... */
647  if (ave_OB_fill_level[stream_id] >= (OB_alert_level[stream_id] + alertInterval)) {
648  while (ave_OB_fill_level[stream_id] >= OB_alert_level[stream_id] + alertInterval) {
649  OB_alert_level[stream_id] += alertInterval;
650 
651  }
652  SCLogInfo("nt%d - Increasing Adapter SDRAM Fill Level: %4d%%",
653  stream_id, ave_OB_fill_level[stream_id]);
654  }
655 
656  if (OB_alert_level[stream_id] > 0) {
657  if ((ave_OB_fill_level[stream_id] <= (OB_alert_level[stream_id] - alertInterval))) {
658  SCLogInfo("nt%d - Decreasing Adapter SDRAM Fill Level : %4d%%",
659  stream_id, ave_OB_fill_level[stream_id]);
660 
661  while (ave_OB_fill_level[stream_id] <= (OB_alert_level[stream_id] - alertInterval)) {
662  if ((OB_alert_level[stream_id]) > 0) {
663  OB_alert_level[stream_id] -= alertInterval;
664  } else break;
665  }
666  }
667  }
668  }
669  ++stream_id;
670  }
671  }
672 
673  if ((status = NT_InfoClose(hInfo)) != NT_SUCCESS) {
674  NT_ExplainError(status, error_buffer, sizeof (error_buffer) - 1);
675  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_InfoClose() failed: %s\n", error_buffer);
676  exit(1);
677  }
678 
679  /* Close the statistics stream */
680  if ((status = NT_StatClose(hStatStream)) != NT_SUCCESS) {
681  /* Get the status code as text */
682  NT_ExplainError(status, error_buffer, sizeof (error_buffer));
683  SCLogError(SC_ERR_NAPATECH_INIT_FAILED, "NT_StatClose() failed: %s\n", error_buffer);
684  exit(1);
685  }
686 
687  SCLogDebug("Exiting NapatechStatsLoop");
691 
692  return NULL;
693 }
694 
696 {
697  /* Creates the Statistic threads */
698  ThreadVars *stats_tv = TmThreadCreate("NapatechStats",
699  NULL, NULL,
700  NULL, NULL,
701  "custom", NapatechStatsLoop, 0);
702 
703  if (stats_tv == NULL) {
705  "Error creating a thread for NapatechStats - Killing engine.");
706  exit(EXIT_FAILURE);
707  }
708 
709  if (TmThreadSpawn(stats_tv) != 0) {
711  "Failed to spawn thread for NapatechStats - Killing engine.");
712  exit(EXIT_FAILURE);
713  }
714 
715  ThreadVars *buf_monitor_tv = TmThreadCreate("NapatechBufMonitor",
716  NULL, NULL,
717  NULL, NULL,
718  "custom", NapatechBufMonitorLoop, 0);
719 
720  if (buf_monitor_tv == NULL) {
722  "Error creating a thread for NapatechBufMonitor - Killing engine.");
723  exit(EXIT_FAILURE);
724  }
725 
726  if (TmThreadSpawn(buf_monitor_tv) != 0) {
728  "Failed to spawn thread for NapatechBufMonitor - Killing engine.");
729  exit(EXIT_FAILURE);
730  }
731 
732 
733  return;
734 }
735 
736 #endif // HAVE_NAPATECH
uint16_t NapatechGetStreamConfig(NapatechStreamConfig stream_config[])
struct StreamCounters_ StreamCounters
#define SCLogDebug(...)
Definition: util-debug.h:335
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
struct HtpBodyChunk_ * next
NapatechCurrentStats NapatechGetCurrentStats(uint16_t id)
Definition: util-napatech.c:84
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
TcpStreamCnf stream_config
Definition: stream-tcp.h:106
#define THV_RUNNING_DONE
Definition: threadvars.h:45
#define unlikely(expr)
Definition: util-optimize.h:35
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as an boolen.
Definition: conf.c:517
NapatechCurrentStats current_stats[MAX_STREAMS]
Definition: util-napatech.c:82
char * val
Definition: conf.h:34
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition: counters.c:939
void TmThreadsSetFlag(ThreadVars *tv, uint16_t flag)
Set a thread flag.
Definition: tm-threads.c:113
#define SCCalloc(nm, a)
Definition: util-mem.h:205
void TmThreadWaitForFlag(ThreadVars *tv, uint16_t flags)
Waits till the specified flag(s) is(are) set. We don&#39;t bother if the kill flag has been set or not on...
Definition: tm-threads.c:1998
void StatsSetUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Sets a value of type double to the local counter.
Definition: counters.c:185
#define THV_INIT_DONE
Definition: threadvars.h:36
#define THV_CLOSED
Definition: threadvars.h:41
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define HB_HIGHWATER
uint16_t NapatechGetNumaNode(uint16_t stream_id)
Definition: util-napatech.c:35
#define THV_KILL
Definition: threadvars.h:39
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
Definition: conf.h:32
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
void NapatechStartStats(void)
#define StatsSyncCountersIfSignalled(tv)
Definition: counters.h:136
int StatsSetupPrivate(ThreadVars *tv)
Definition: counters.c:1201
int TmThreadsCheckFlag(ThreadVars *tv, uint16_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:105
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
#define MAX_STREAMS
#define THV_DEINIT
Definition: threadvars.h:44
Per thread variable structure.
Definition: threadvars.h:57
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
Definition: tm-threads.c:1882
ThreadVars * TmThreadCreate(const char *name, const char *inq_name, const char *inqh_name, const char *outq_name, const char *outqh_name, const char *slots, void *(*fn_p)(void *), int mucond)
Creates and returns the TV instance for a new thread.
Definition: tm-threads.c:1131