suricata
runmode-napatech.c
Go to the documentation of this file.
1 /* Copyright (C) 2012-2017 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author nPulse Technologies, LLC.
22  * \author Matt Keeler <mk@npulsetech.com>
23  */
24 
25 #include "suricata-common.h"
26 #include "tm-threads.h"
27 #include "conf.h"
28 #include "runmodes.h"
29 #include "output.h"
30 #include "util-debug.h"
31 #include "util-time.h"
32 #include "util-cpu.h"
33 #include "util-affinity.h"
34 #include "util-runmodes.h"
35 #include "util-device.h"
36 #include "util-napatech.h"
37 #include "runmode-napatech.h"
38 #include "source-napatech.h" // need NapatechStreamDevConf structure
39 
40 #define NT_RUNMODE_AUTOFP 1
41 #define NT_RUNMODE_WORKERS 2
42 
43 #ifdef HAVE_NAPATECH
44 
45 #define MAX_STREAMS 256
46 static uint16_t num_configured_streams = 0;
47 static uint16_t first_stream = 0xffff;
48 static uint16_t last_stream = 0xffff;
49 static int auto_config = 0;
50 
52 {
53  return num_configured_streams;
54 }
55 
57 {
58  return first_stream;
59 }
60 
62 {
63  return last_stream;
64 }
65 
67 {
68  return (auto_config != 0);
69 }
70 
71 #endif
72 
74 {
75  return "workers";
76 }
77 
79 {
80 #ifdef HAVE_NAPATECH
82  "Workers Napatech mode, each thread does all"
83  " tasks from acquisition to logging",
85  return;
86 #endif
87 }
88 
89 
90 #ifdef HAVE_NAPATECH
91 
92 static int NapatechRegisterDeviceStreams(void)
93 {
94  /* Display the configuration mode */
95  int use_all_streams;
96 
97  if (ConfGetBool("napatech.use-all-streams", &use_all_streams) == 0) {
98  SCLogInfo("Could not find napatech.use-all-streams in config file. Defaulting to \"no\".");
99  use_all_streams = 0;
100  }
101 
102  if (ConfGetBool("napatech.auto-config", &auto_config) == 0) {
103  SCLogInfo("napatech.auto-config not found in config file. Defaulting to disabled.");
104  }
105 
106  if (use_all_streams && auto_config) {
107  SCLogError(SC_ERR_RUNMODE, "auto-config cannot be used with use-all-streams.");
108  }
109 
110  /* Get the stream ID's either from the conf or by querying Napatech */
112 
113  uint16_t stream_cnt = NapatechGetStreamConfig(stream_config);
114  num_configured_streams = stream_cnt;
115  SCLogDebug("Configuring %d Napatech Streams...", stream_cnt);
116 
117  for (uint16_t inst = 0; inst < stream_cnt; ++inst) {
118  char *plive_dev_buf = SCCalloc(1, 9);
119  if (unlikely(plive_dev_buf == NULL)) {
121  "Failed to allocate memory for NAPATECH stream counter.");
122  exit(EXIT_FAILURE);
123  }
124  snprintf(plive_dev_buf, 9, "nt%d", stream_config[inst].stream_id);
125 
126  if (auto_config) {
127  if (stream_config[inst].is_active) {
129  "Registering Napatech device: %s - active stream found.",
130  plive_dev_buf);
132  "Delete the stream or disable auto-config before running.");
133  exit(EXIT_FAILURE);
134  }
135  } else {
136  SCLogInfo("Registering Napatech device: %s - active stream%sfound.",
137  plive_dev_buf, stream_config[inst].is_active ? " " : " NOT ");
138  }
139  LiveRegisterDevice(plive_dev_buf);
140 
141  if (first_stream == 0xffff) {
142  first_stream = stream_config[inst].stream_id;
143  }
144  last_stream = stream_config[inst].stream_id;
145  }
146 
147  /* Napatech stats come from a separate thread. This will surpress
148  * the counters when suricata exits.
149  */
151  return 0;
152 }
153 
154 static void *NapatechConfigParser(const char *device)
155 {
156  /* Expect device to be of the form nt%d where %d is the stream id to use */
157  int dev_len = strlen(device);
158  if (dev_len < 3 || dev_len > 5) {
160  "Could not parse config for device: %s - invalid length", device);
161  return NULL;
162  }
163 
164  struct NapatechStreamDevConf *conf = SCCalloc(1, sizeof (struct NapatechStreamDevConf));
165  if (unlikely(conf == NULL)) {
167  "Failed to allocate memory for NAPATECH device name.");
168  return NULL;
169  }
170 
171  /* device+5 is a pointer to the beginning of the stream id after the constant nt portion */
172  conf->stream_id = atoi(device + 2);
173 
174  /* Set the host buffer allowance for this stream
175  * Right now we just look at the global default - there is no per-stream hba configuration
176  */
177  if (ConfGetInt("napatech.hba", &conf->hba) == 0) {
178  conf->hba = -1;
179  }
180  return (void *) conf;
181 }
182 
183 static int NapatechGetThreadsCount(void *conf __attribute__((unused)))
184 {
185  /* No matter which live device it is there is no reason to ever use more than 1 thread
186  2 or more thread would cause packet duplication */
187  return 1;
188 }
189 
190 static int NapatechInit(int runmode)
191 {
192  int status;
193 
195  TimeModeSetLive();
196 
197  /* Initialize the API and check version compatibility */
198  if ((status = NT_Init(NTAPI_VERSION)) != NT_SUCCESS) {
200  exit(EXIT_FAILURE);
201  }
202 
203  status = NapatechRegisterDeviceStreams();
204  if (status < 0 || num_configured_streams <= 0) {
206  "Unable to find existing Napatech Streams");
207  exit(EXIT_FAILURE);
208  }
209 
210  struct NapatechStreamDevConf *conf =
211  SCCalloc(1, sizeof (struct NapatechStreamDevConf));
212  if (unlikely(conf == NULL)) {
213  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for NAPATECH device.");
214  exit(EXIT_FAILURE);
215  }
216 
217  if ((ConfGetInt("napatech.hba", &conf->hba) != 0) && (conf->hba > 0)) {
218  SCLogInfo("Host Buffer Allowance: %d", (int) conf->hba);
219  }
220 
221  /* Start a thread to process the statistics */
223 
224  switch (runmode) {
225  case NT_RUNMODE_WORKERS:
226  status = RunModeSetLiveCaptureWorkers(NapatechConfigParser,
227  NapatechGetThreadsCount,
228  "NapatechStream", "NapatechDecode",
229  thread_name_workers, NULL);
230  break;
231  default:
232  status = -1;
233  }
234 
235  if (status != 0) {
236  SCLogError(SC_ERR_RUNMODE, "Runmode start failed");
237  exit(EXIT_FAILURE);
238  }
239  return 0;
240 }
241 
243 {
244  return NapatechInit(NT_RUNMODE_AUTOFP);
245 }
246 
248 {
249  return NapatechInit(NT_RUNMODE_WORKERS);
250 }
251 
252 #endif
#define SCLogDebug(...)
Definition: util-debug.h:335
int LiveRegisterDevice(const char *dev)
Add a pcap device for monitoring and create structure.
Definition: util-device.c:124
void RunModeInitialize(void)
Definition: runmodes.c:900
TcpStreamCnf stream_config
Definition: stream-tcp.h:106
#define unlikely(expr)
Definition: util-optimize.h:35
uint16_t NapatechGetNumLastStream(void)
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as an boolen.
Definition: conf.c:517
void TimeModeSetLive(void)
Definition: util-time.c:90
int NapatechGetStreamConfig(NapatechStreamConfig stream_config[])
enum @34 __attribute__
DNP3 application header.
const char * RunModeNapatechGetDefaultMode(void)
#define SCCalloc(nm, a)
Definition: util-mem.h:253
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
int RunModeNapatechWorkers(void)
#define NT_RUNMODE_WORKERS
bool NapatechIsAutoConfigEnabled(void)
#define NAPATECH_ERROR(err_type, status)
Definition: util-napatech.h:54
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:437
void RunModeNapatechRegister(void)
void NapatechStartStats(void)
uint16_t NapatechGetNumFirstStream(void)
void RunModeRegisterNewRunMode(enum RunModes runmode, const char *name, const char *description, int(*RunModeFunc)(void))
Registers a new runmode.
Definition: runmodes.c:419
#define MAX_STREAMS
int RunModeSetLiveCaptureWorkers(ConfigIfaceParserFunc ConfigParser, ConfigIfaceThreadsCountFunc ModThreadsCount, const char *recv_mod_name, const char *decode_mod_name, const char *thread_name, const char *live_dev)
uint16_t NapatechGetNumConfiguredStreams(void)
#define NT_RUNMODE_AUTOFP
int RunModeNapatechAutoFp(void)
void LiveDeviceHasNoStats()
Definition: util-device.c:300
const char * thread_name_workers
Definition: runmodes.c:63