]> git.ipfire.org Git - people/ms/suricata.git/blame - src/runmode-af-packet.c
code cleanup
[people/ms/suricata.git] / src / runmode-af-packet.c
CommitLineData
c45d8985
EL
1/* Copyright (C) 2011 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
e80b30c0
EL
18/**
19 * \file
20 *
21 * \author Eric Leblond <eric@regit.org>
22 *
23 * AF_PACKET socket runmode
24 *
25 */
26
27
c45d8985 28#include "suricata-common.h"
e80b30c0 29#include "config.h"
c45d8985
EL
30#include "tm-threads.h"
31#include "conf.h"
32#include "runmodes.h"
33#include "runmode-af-packet.h"
34#include "log-httplog.h"
35#include "output.h"
36#include "cuda-packet-batcher.h"
c45d8985
EL
37#include "detect-engine-mpm.h"
38
39#include "alert-fastlog.h"
40#include "alert-prelude.h"
c45d8985
EL
41#include "alert-unified2-alert.h"
42#include "alert-debuglog.h"
43
44#include "util-debug.h"
45#include "util-time.h"
46#include "util-cpu.h"
47#include "util-affinity.h"
871b2189 48#include "util-device.h"
75c875b1 49#include "util-runmodes.h"
c45d8985 50
e80b30c0
EL
51#include "source-af-packet.h"
52
53static const char *default_mode_auto = NULL;
54static const char *default_mode_autofp = NULL;
c45d8985
EL
55
56const char *RunModeAFPGetDefaultMode(void)
57{
fbca1a4e 58 return default_mode_autofp;
c45d8985
EL
59}
60
61void RunModeIdsAFPRegister(void)
62{
e80b30c0 63 default_mode_auto = "auto";
c45d8985
EL
64 RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "auto",
65 "Multi threaded af-packet mode",
66 RunModeIdsAFPAuto);
e80b30c0
EL
67 RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "single",
68 "Single threaded af-packet mode",
69 RunModeIdsAFPSingle);
beaa909e
EL
70 RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "workers",
71 "Workers af-packet mode, each thread does all"
72 " tasks from acquisition to logging",
73 RunModeIdsAFPWorkers);
e80b30c0
EL
74 default_mode_autofp = "autofp";
75 RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "autofp",
76 "Multi socket AF_PACKET mode. Packets from "
77 "each flow are assigned to a single detect "
78 "thread.",
79 RunModeIdsAFPAutoFp);
c45d8985
EL
80 return;
81}
82
45d5c3ca
EL
83void AFPDerefConfig(void *conf)
84{
85 AFPIfaceConfig *pfp = (AFPIfaceConfig *)conf;
86 /* Pcap config is used only once but cost of this low. */
87 if (SC_ATOMIC_SUB(pfp->ref, 1) == 0) {
88 SCFree(pfp);
89 }
90}
91
fbca1a4e
EL
92/**
93 * \brief extract information from config file
94 *
95 * The returned structure will be freed by the thread init function.
96 * This is thus necessary to or copy the structure before giving it
97 * to thread or to reparse the file for each thread (and thus have
98 * new structure.
99 *
100 * \return a AFPIfaceConfig corresponding to the interface name
101 */
75c875b1 102void *ParseAFPConfig(const char *iface)
fbca1a4e
EL
103{
104 char *threadsstr = NULL;
105 ConfNode *if_root;
106 ConfNode *af_packet_node;
107 AFPIfaceConfig *aconf = SCMalloc(sizeof(*aconf));
108 char *tmpclusterid;
109 char *tmpctype;
110 intmax_t value;
67f791e8 111 int boolval;
fbca1a4e 112
75c875b1
EL
113 if (iface == NULL) {
114 return NULL;
115 }
116
fbca1a4e
EL
117 if (aconf == NULL) {
118 return NULL;
119 }
120 strlcpy(aconf->iface, iface, sizeof(aconf->iface));
121 aconf->threads = 1;
45d5c3ca
EL
122 SC_ATOMIC_INIT(aconf->ref);
123 SC_ATOMIC_ADD(aconf->ref, 1);
fbca1a4e
EL
124 aconf->buffer_size = 0;
125 aconf->cluster_id = 1;
126 aconf->cluster_type = PACKET_FANOUT_HASH;
df7dbe36 127 aconf->promisc = 1;
6062e00c 128 aconf->checksum_mode = CHECKSUM_VALIDATION_KERNEL;
45d5c3ca 129 aconf->DerefFunc = AFPDerefConfig;
49b7b00f 130 aconf->flags = 0;
fbca1a4e
EL
131
132 /* Find initial node */
133 af_packet_node = ConfGetNode("af-packet");
134 if (af_packet_node == NULL) {
135 SCLogInfo("Unable to find af-packet config using default value");
136 return aconf;
137 }
138
139 if_root = ConfNodeLookupKeyValue(af_packet_node, "interface", iface);
140 if (if_root == NULL) {
141 SCLogInfo("Unable to find af-packet config for "
142 "interface %s, using default value",
143 iface);
144 return aconf;
145 }
146
147 if (ConfGetChildValue(if_root, "threads", &threadsstr) != 1) {
148 aconf->threads = 1;
149 } else {
150 if (threadsstr != NULL) {
151 aconf->threads = (uint8_t)atoi(threadsstr);
152 }
153 }
154 if (aconf->threads == 0) {
155 aconf->threads = 1;
156 }
45d5c3ca
EL
157
158 SC_ATOMIC_RESET(aconf->ref);
159 SC_ATOMIC_ADD(aconf->ref, aconf->threads);
160
fbca1a4e
EL
161 if (ConfGetChildValue(if_root, "cluster-id", &tmpclusterid) != 1) {
162 SCLogError(SC_ERR_INVALID_ARGUMENT,"Could not get cluster-id from config");
163 } else {
164 aconf->cluster_id = (uint16_t)atoi(tmpclusterid);
165 SCLogDebug("Going to use cluster-id %" PRId32, aconf->cluster_id);
166 }
167
168 if (ConfGetChildValue(if_root, "cluster-type", &tmpctype) != 1) {
623bb38d 169 SCLogError(SC_ERR_GET_CLUSTER_TYPE_FAILED,"Could not get cluster-type from config");
fbca1a4e
EL
170 } else if (strcmp(tmpctype, "cluster_round_robin") == 0) {
171 SCLogInfo("Using round-robin cluster mode for AF_PACKET (iface %s)",
172 aconf->iface);
173 aconf->cluster_type = PACKET_FANOUT_LB;
174 } else if (strcmp(tmpctype, "cluster_flow") == 0) {
175 /* In hash mode, we also ask for defragmentation needed to
176 * compute the hash */
177 uint16_t defrag = 0;
178 SCLogInfo("Using flow cluster mode for AF_PACKET (iface %s)",
179 aconf->iface);
180 ConfGetChildValueBool(if_root, "defrag", (int *)&defrag);
181 if (defrag) {
182 SCLogInfo("Using defrag kernel functionnality for AF_PACKET (iface %s)",
183 aconf->iface);
184 defrag = PACKET_FANOUT_FLAG_DEFRAG;
185 }
186 aconf->cluster_type = PACKET_FANOUT_HASH | defrag;
187 } else if (strcmp(tmpctype, "cluster_cpu") == 0) {
188 SCLogInfo("Using cpu cluster mode for AF_PACKET (iface %s)",
189 aconf->iface);
190 aconf->cluster_type = PACKET_FANOUT_CPU;
191 } else {
192 SCLogError(SC_ERR_INVALID_CLUSTER_TYPE,"invalid cluster-type %s",tmpctype);
193 return NULL;
194 }
195
196 if ((ConfGetChildValueInt(if_root, "buffer-size", &value)) == 1) {
197 aconf->buffer_size = value;
198 } else {
199 aconf->buffer_size = 0;
200 }
201
67f791e8
EL
202 ConfGetChildValueBool(if_root, "disable-promisc", (int *)&boolval);
203 if (boolval) {
df7dbe36
EL
204 SCLogInfo("Disabling promiscuous mode on iface %s",
205 aconf->iface);
206 aconf->promisc = 0;
207 }
49b7b00f
EL
208 ConfGetChildValueBool(if_root, "use-mmap", (int *)&boolval);
209 if (boolval) {
210 SCLogInfo("Enabling mmaped capture on iface %s",
211 aconf->iface);
212 aconf->flags |= AFP_RING_MODE;
213 }
214
67f791e8 215
d24b3a0e 216 if (ConfGetChildValue(if_root, "checksum-checks", &tmpctype) == 1) {
6062e00c 217 if (strcmp(tmpctype, "auto") == 0) {
6062e00c 218 aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO;
6062e00c
EL
219 } else if (strcmp(tmpctype, "yes") == 0) {
220 aconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
221 } else if (strcmp(tmpctype, "no") == 0) {
222 aconf->checksum_mode = CHECKSUM_VALIDATION_DISABLE;
223 } else if (strcmp(tmpctype, "kernel") == 0) {
224 aconf->checksum_mode = CHECKSUM_VALIDATION_KERNEL;
225 } else {
226 SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", aconf->iface);
227 }
228 }
df7dbe36 229
fbca1a4e
EL
230 return aconf;
231}
232
75c875b1
EL
233int AFPConfigGeThreadsCount(void *conf)
234{
235 AFPIfaceConfig *afp = (AFPIfaceConfig *)conf;
236 return afp->threads;
237}
fbca1a4e 238
c45d8985
EL
239/**
240 * \brief RunModeIdsAFPAuto set up the following thread packet handlers:
e80b30c0 241 * - Receive thread (from live iface)
c45d8985
EL
242 * - Decode thread
243 * - Stream thread
244 * - Detect: If we have only 1 cpu, it will setup one Detect thread
245 * If we have more than one, it will setup num_cpus - 1
246 * starting from the second cpu available.
247 * - Respond/Reject thread
248 * - Outputs thread
249 * By default the threads will use the first cpu available
250 * except the Detection threads if we have more than one cpu.
251 *
252 * \param de_ctx Pointer to the Detection Engine.
253 *
254 * \retval 0 If all goes well. (If any problem is detected the engine will
255 * exit()).
256 */
257int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
258{
259 SCEnter();
e80b30c0
EL
260
261#ifdef HAVE_AF_PACKET
75c875b1
EL
262 int ret;
263 char *live_dev = NULL;
c45d8985
EL
264
265 RunModeInitialize();
c45d8985 266
75c875b1 267 TimeModeSetLive();
c45d8985 268
75c875b1 269 ConfGet("af-packet.live-interface", &live_dev);
c45d8985 270
75c875b1 271 ret = RunModeSetLiveCaptureAuto(de_ctx,
6c55af84
EL
272 ParseAFPConfig,
273 AFPConfigGeThreadsCount,
274 "ReceiveAFP",
75c875b1
EL
275 "DecodeAFP", "RecvAFP",
276 live_dev);
277 if (ret != 0) {
625a1e07 278 SCLogError(SC_ERR_RUNMODE, "Unable to start runmode");
c45d8985
EL
279 exit(EXIT_FAILURE);
280 }
281
75c875b1 282 SCLogInfo("RunModeIdsAFPAuto initialised");
e80b30c0
EL
283#endif
284 SCReturnInt(0);
285}
286
287int RunModeIdsAFPAutoFp(DetectEngineCtx *de_ctx)
288{
289 SCEnter();
290
291/* We include only if AF_PACKET is enabled */
292#ifdef HAVE_AF_PACKET
75c875b1 293 int ret;
e80b30c0 294 char *live_dev = NULL;
e80b30c0 295
fbca1a4e
EL
296 RunModeInitialize();
297
298 TimeModeSetLive();
299
75c875b1 300 ConfGet("af-packet.live-interface", &live_dev);
fbca1a4e 301
75c875b1 302 SCLogDebug("live_dev %s", live_dev);
e80b30c0 303
75c875b1
EL
304 ret = RunModeSetLiveCaptureAutoFp(de_ctx,
305 ParseAFPConfig,
306 AFPConfigGeThreadsCount,
307 "ReceiveAFP",
308 "DecodeAFP", "RxAFP",
309 live_dev);
310 if (ret != 0) {
625a1e07 311 SCLogError(SC_ERR_RUNMODE, "Unable to start runmode");
75c875b1 312 exit(EXIT_FAILURE);
e80b30c0
EL
313 }
314
75c875b1 315 SCLogInfo("RunModeIdsAFPAutoFp initialised");
e80b30c0
EL
316
317#endif /* HAVE_AF_PACKET */
318
319 SCReturnInt(0);
320}
321
322/**
323 * \brief Single thread version of the AF_PACKET processing.
324 */
325int RunModeIdsAFPSingle(DetectEngineCtx *de_ctx)
326{
1aab2470
EL
327#ifdef HAVE_AF_PACKET
328 int ret;
329 char *live_dev = NULL;
330#endif
3801e004
AS
331 SCEnter();
332#ifdef HAVE_AF_PACKET
e80b30c0
EL
333
334 RunModeInitialize();
335 TimeModeSetLive();
336
1aab2470 337 ConfGet("af-packet.live-interface", &live_dev);
e80b30c0 338
1aab2470 339 ret = RunModeSetLiveCaptureSingle(de_ctx,
77869a2d
EL
340 ParseAFPConfig,
341 AFPConfigGeThreadsCount,
342 "ReceiveAFP",
1aab2470
EL
343 "DecodeAFP", "AFPacket",
344 live_dev);
345 if (ret != 0) {
625a1e07 346 SCLogError(SC_ERR_RUNMODE, "Unable to start runmode");
e80b30c0
EL
347 exit(EXIT_FAILURE);
348 }
e80b30c0 349
1aab2470 350 SCLogInfo("RunModeIdsAFPSingle initialised");
e80b30c0
EL
351
352#endif /* HAVE_AF_PACKET */
353 SCReturnInt(0);
c45d8985 354}
beaa909e
EL
355
356/**
357 * \brief Workers version of the AF_PACKET processing.
358 *
359 * Start N threads with each thread doing all the work.
360 *
361 */
362int RunModeIdsAFPWorkers(DetectEngineCtx *de_ctx)
363{
364#ifdef HAVE_AF_PACKET
365 int ret;
366 char *live_dev = NULL;
367#endif
368 SCEnter();
369#ifdef HAVE_AF_PACKET
370
371 RunModeInitialize();
372 TimeModeSetLive();
373
374 ConfGet("af-packet.live-interface", &live_dev);
375
376 ret = RunModeSetLiveCaptureWorkers(de_ctx,
377 ParseAFPConfig,
378 AFPConfigGeThreadsCount,
379 "ReceiveAFP",
380 "DecodeAFP", "AFPacket",
381 live_dev);
382 if (ret != 0) {
625a1e07 383 SCLogError(SC_ERR_RUNMODE, "Unable to start runmode");
beaa909e
EL
384 exit(EXIT_FAILURE);
385 }
386
387 SCLogInfo("RunModeIdsAFPSingle initialised");
388
389#endif /* HAVE_AF_PACKET */
390 SCReturnInt(0);
391}