]>
Commit | Line | Data |
---|---|---|
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 | ||
53 | static const char *default_mode_auto = NULL; | |
54 | static const char *default_mode_autofp = NULL; | |
c45d8985 EL |
55 | |
56 | const char *RunModeAFPGetDefaultMode(void) | |
57 | { | |
fbca1a4e | 58 | return default_mode_autofp; |
c45d8985 EL |
59 | } |
60 | ||
61 | void 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 |
83 | void 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 | 102 | void *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 |
233 | int 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 | */ | |
257 | int 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 | ||
287 | int 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 | */ | |
325 | int 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 | */ | |
362 | int 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 | } |