suricata
runmode-dpdk.c
Go to the documentation of this file.
1/* Copyright (C) 2021-2025 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 * \ingroup dpdk
20 *
21 * @{
22 */
23
24/**
25 * \file
26 *
27 * \author Lukas Sismis <lukas.sismis@gmail.com>
28 *
29 * DPDK runmode
30 *
31 */
32
33#include "suricata-common.h"
34#include "runmodes.h"
35#include "runmode-dpdk.h"
36#include "decode.h"
37#include "source-dpdk.h"
38#include "util-runmodes.h"
39#include "util-byte.h"
40#include "util-cpu.h"
41#include "util-debug.h"
42#include "util-device-private.h"
43#include "util-dpdk.h"
44#include "util-dpdk-bonding.h"
45#include "util-dpdk-common.h"
46#include "util-dpdk-i40e.h"
47#include "util-dpdk-ice.h"
48#include "util-dpdk-ixgbe.h"
49#include "util-dpdk-rss.h"
50#include "util-time.h"
51#include "util-conf.h"
52#include "suricata.h"
53#include "util-affinity.h"
54
55#ifdef HAVE_DPDK
56
57// Calculates the closest multiple of y from x
58#define ROUNDUP(x, y) ((((x) + ((y)-1)) / (y)) * (y))
59
60/* Maximum DPDK EAL parameters count. */
61#define EAL_ARGS 48
62
63struct Arguments {
64 uint16_t capacity;
65 char **argv;
66 uint16_t argc;
67};
68
69static char *AllocArgument(size_t arg_len);
70static char *AllocAndSetArgument(const char *arg);
71static char *AllocAndSetOption(const char *arg);
72
73static void ArgumentsInit(struct Arguments *args, uint16_t capacity);
74static void ArgumentsCleanup(struct Arguments *args);
75static void ArgumentsAdd(struct Arguments *args, char *value);
76static void ArgumentsAddOptionAndArgument(struct Arguments *args, const char *opt, const char *arg);
77static void InitEal(void);
78
79static void ConfigSetIface(DPDKIfaceConfig *iconf, const char *entry_str);
80static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str);
81static int ConfigSetRxQueues(DPDKIfaceConfig *iconf, uint16_t nb_queues, uint16_t max_queues);
82static int ConfigSetTxQueues(
83 DPDKIfaceConfig *iconf, uint16_t nb_queues, uint16_t max_queues, bool iface_sends_pkts);
84static int ConfigSetMempoolSize(DPDKIfaceConfig *iconf, const char *entry_str);
85static int ConfigSetMempoolCacheSize(DPDKIfaceConfig *iconf, const char *entry_str);
86static int ConfigSetRxDescriptors(DPDKIfaceConfig *iconf, const char *entry_str, uint16_t max_desc);
87static int ConfigSetTxDescriptors(
88 DPDKIfaceConfig *iconf, const char *entry_str, uint16_t max_desc, bool iface_sends_pkts);
89static int ConfigSetMtu(DPDKIfaceConfig *iconf, intmax_t entry_int);
90static bool ConfigSetPromiscuousMode(DPDKIfaceConfig *iconf, int entry_bool);
91static bool ConfigSetMulticast(DPDKIfaceConfig *iconf, int entry_bool);
92static int ConfigSetChecksumChecks(DPDKIfaceConfig *iconf, int entry_bool);
93static int ConfigSetChecksumOffload(DPDKIfaceConfig *iconf, int entry_bool);
94static int ConfigSetCopyIface(DPDKIfaceConfig *iconf, const char *entry_str);
95static int ConfigSetCopyMode(DPDKIfaceConfig *iconf, const char *entry_str);
96static int ConfigSetCopyIfaceSettings(DPDKIfaceConfig *iconf, const char *iface, const char *mode);
97static void ConfigInit(DPDKIfaceConfig **iconf);
98static int ConfigLoad(DPDKIfaceConfig *iconf, const char *iface);
99static DPDKIfaceConfig *ConfigParse(const char *iface);
100
101static void DeviceInitPortConf(const DPDKIfaceConfig *iconf,
102 const struct rte_eth_dev_info *dev_info, struct rte_eth_conf *port_conf);
103static int DeviceConfigureQueues(DPDKIfaceConfig *iconf, const struct rte_eth_dev_info *dev_info,
104 const struct rte_eth_conf *port_conf);
105static int DeviceValidateOutIfaceConfig(DPDKIfaceConfig *iconf);
106static int DeviceConfigureIPS(DPDKIfaceConfig *iconf);
107static int DeviceConfigure(DPDKIfaceConfig *iconf);
108static void *ParseDpdkConfigAndConfigureDevice(const char *iface);
109static void DPDKDerefConfig(void *conf);
110
111#define DPDK_CONFIG_DEFAULT_THREADS "auto"
112#define DPDK_CONFIG_DEFAULT_INTERRUPT_MODE false
113#define DPDK_CONFIG_DEFAULT_MEMPOOL_SIZE "auto"
114#define DPDK_CONFIG_DEFAULT_MEMPOOL_CACHE_SIZE "auto"
115#define DPDK_CONFIG_DEFAULT_RX_DESCRIPTORS "auto"
116#define DPDK_CONFIG_DEFAULT_TX_DESCRIPTORS "auto"
117#define DPDK_CONFIG_DEFAULT_RSS_HASH_FUNCTIONS RTE_ETH_RSS_IP
118#define DPDK_CONFIG_DEFAULT_MTU 1500
119#define DPDK_CONFIG_DEFAULT_PROMISCUOUS_MODE 1
120#define DPDK_CONFIG_DEFAULT_MULTICAST_MODE 1
121#define DPDK_CONFIG_DEFAULT_CHECKSUM_VALIDATION 1
122#define DPDK_CONFIG_DEFAULT_CHECKSUM_VALIDATION_OFFLOAD 1
123#define DPDK_CONFIG_DEFAULT_VLAN_STRIP 0
124#define DPDK_CONFIG_DEFAULT_LINKUP_TIMEOUT 0
125#define DPDK_CONFIG_DEFAULT_COPY_MODE "none"
126#define DPDK_CONFIG_DEFAULT_COPY_INTERFACE "none"
127
128DPDKIfaceConfigAttributes dpdk_yaml = {
129 .threads = "threads",
130 .irq_mode = "interrupt-mode",
131 .promisc = "promisc",
132 .multicast = "multicast",
133 .checksum_checks = "checksum-checks",
134 .checksum_checks_offload = "checksum-checks-offload",
135 .mtu = "mtu",
136 .vlan_strip_offload = "vlan-strip-offload",
137 .rss_hf = "rss-hash-functions",
138 .linkup_timeout = "linkup-timeout",
139 .mempool_size = "mempool-size",
140 .mempool_cache_size = "mempool-cache-size",
141 .rx_descriptors = "rx-descriptors",
142 .tx_descriptors = "tx-descriptors",
143 .copy_mode = "copy-mode",
144 .copy_iface = "copy-iface",
145};
146
147/**
148 * \brief Input is a number of which we want to find the greatest divisor up to max_num (inclusive).
149 * The divisor is returned.
150 */
151static uint32_t GreatestDivisorUpTo(uint32_t num, uint32_t max_num)
152{
153 for (uint32_t i = max_num; i >= 2; i--) {
154 if (num % i == 0) {
155 return i;
156 }
157 }
158 return 1;
159}
160
161/**
162 * \brief Input is a number of which we want to find the greatest power of 2 up to num. The power of
163 * 2 is returned or 0 if no valid power of 2 is found.
164 */
165static uint64_t GreatestPowOf2UpTo(uint64_t num)
166{
167 if (num == 0) {
168 return 0; // No power of 2 exists for 0
169 }
170
171 // Bit manipulation to isolate the highest set bit
172 num |= (num >> 1);
173 num |= (num >> 2);
174 num |= (num >> 4);
175 num |= (num >> 8);
176 num |= (num >> 16);
177 num |= (num >> 32);
178 num = num - (num >> 1);
179
180 return num;
181}
182
183static char *AllocArgument(size_t arg_len)
184{
185 SCEnter();
186 char *ptr;
187
188 arg_len += 1; // null character
189 ptr = (char *)SCCalloc(arg_len, sizeof(char));
190 if (ptr == NULL)
191 FatalError("Could not allocate memory for an argument");
192
193 SCReturnPtr(ptr, "char *");
194}
195
196/**
197 * Allocates space for length of the given string and then copies contents
198 * @param arg String to set to the newly allocated space
199 * @return memory address if no error otherwise NULL (with errno set)
200 */
201static char *AllocAndSetArgument(const char *arg)
202{
203 SCEnter();
204 if (arg == NULL)
205 FatalError("Passed argument is NULL in DPDK config initialization");
206
207 char *ptr;
208 size_t arg_len = strlen(arg);
209
210 ptr = AllocArgument(arg_len);
211 strlcpy(ptr, arg, arg_len + 1);
212 SCReturnPtr(ptr, "char *");
213}
214
215static char *AllocAndSetOption(const char *arg)
216{
217 SCEnter();
218 if (arg == NULL)
219 FatalError("Passed option is NULL in DPDK config initialization");
220
221 char *ptr = NULL;
222 size_t arg_len = strlen(arg);
223 uint8_t is_long_arg = arg_len > 1;
224 const char *dash_prefix = is_long_arg ? "--" : "-";
225 size_t full_len = arg_len + strlen(dash_prefix);
226
227 ptr = AllocArgument(full_len);
228 strlcpy(ptr, dash_prefix, full_len);
229 strlcat(ptr, arg, full_len);
230 SCReturnPtr(ptr, "char *");
231}
232
233static void ArgumentsInit(struct Arguments *args, uint16_t capacity)
234{
235 SCEnter();
236 args->argv = SCCalloc(capacity, sizeof(*args->argv)); // alloc array of pointers
237 if (args->argv == NULL)
238 FatalError("Could not allocate memory for Arguments structure");
239
240 args->capacity = capacity;
241 args->argc = 0;
242 SCReturn;
243}
244
245static void ArgumentsCleanup(struct Arguments *args)
246{
247 SCEnter();
248 for (int i = 0; i < args->argc; i++) {
249 if (args->argv[i] != NULL) {
250 SCFree(args->argv[i]);
251 args->argv[i] = NULL;
252 }
253 }
254
255 SCFree(args->argv);
256 args->argv = NULL;
257 args->argc = 0;
258 args->capacity = 0;
259}
260
261static void ArgumentsAdd(struct Arguments *args, char *value)
262{
263 SCEnter();
264 if (args->argc + 1 > args->capacity)
265 FatalError("No capacity for more arguments (Max: %" PRIu32 ")", EAL_ARGS);
266
267 args->argv[args->argc++] = value;
268 SCReturn;
269}
270
271static void ArgumentsAddOptionAndArgument(struct Arguments *args, const char *opt, const char *arg)
272{
273 SCEnter();
274 char *option;
275 char *argument;
276
277 option = AllocAndSetOption(opt);
278 ArgumentsAdd(args, option);
279
280 // Empty argument could mean option only (e.g. --no-huge)
281 if (arg == NULL || arg[0] == '\0')
282 SCReturn;
283
284 argument = AllocAndSetArgument(arg);
285 ArgumentsAdd(args, argument);
286 SCReturn;
287}
288
289static void InitEal(void)
290{
291 SCEnter();
292 int retval;
293 SCConfNode *param;
294 const SCConfNode *eal_params = SCConfGetNode("dpdk.eal-params");
295 struct Arguments args;
296 char **eal_argv;
297
298 if (eal_params == NULL) {
299 FatalError("DPDK EAL parameters not found in the config");
300 }
301
302 ArgumentsInit(&args, EAL_ARGS);
303 ArgumentsAdd(&args, AllocAndSetArgument("suricata"));
304
305 TAILQ_FOREACH (param, &eal_params->head, next) {
306 if (SCConfNodeIsSequence(param)) {
307 const char *key = param->name;
308 SCConfNode *val;
309 TAILQ_FOREACH (val, &param->head, next) {
310 ArgumentsAddOptionAndArgument(&args, key, (const char *)val->val);
311 }
312 continue;
313 }
314 ArgumentsAddOptionAndArgument(&args, param->name, param->val);
315 }
316
317 // creating a shallow copy for cleanup because rte_eal_init changes array contents
318 eal_argv = SCCalloc(args.argc, sizeof(*args.argv));
319 if (eal_argv == NULL) {
320 FatalError("Failed to allocate memory for the array of DPDK EAL arguments");
321 }
322 memcpy(eal_argv, args.argv, args.argc * sizeof(*args.argv));
323
324 rte_log_set_global_level(RTE_LOG_WARNING);
325 retval = rte_eal_init(args.argc, eal_argv);
326
327 ArgumentsCleanup(&args);
328 SCFree(eal_argv);
329
330 if (retval < 0) { // retval bound to the result of rte_eal_init
331 FatalError("DPDK EAL initialization error: %s", rte_strerror(-retval));
332 }
333}
334
335static void DPDKDerefConfig(void *conf)
336{
337 SCEnter();
338 DPDKIfaceConfig *iconf = (DPDKIfaceConfig *)conf;
339
340 if (SC_ATOMIC_SUB(iconf->ref, 1) == 1) {
341 DPDKDeviceResourcesDeinit(&iconf->pkt_mempools);
342 SCFree(iconf);
343 }
344 SCReturn;
345}
346
347static void ConfigInit(DPDKIfaceConfig **iconf)
348{
349 SCEnter();
350 DPDKIfaceConfig *ptr = NULL;
351 ptr = SCCalloc(1, sizeof(DPDKIfaceConfig));
352 if (ptr == NULL)
353 FatalError("Could not allocate memory for DPDKIfaceConfig");
354
355 ptr->out_port_id = UINT16_MAX; // make sure no port is set
356 SC_ATOMIC_INIT(ptr->ref);
357 (void)SC_ATOMIC_ADD(ptr->ref, 1);
358 ptr->DerefFunc = DPDKDerefConfig;
359 ptr->flags = 0;
360
361 *iconf = ptr;
362 SCReturn;
363}
364
365static void ConfigSetIface(DPDKIfaceConfig *iconf, const char *entry_str)
366{
367 SCEnter();
368 int retval;
369
370 if (entry_str == NULL || entry_str[0] == '\0')
371 FatalError("Interface name in DPDK config is NULL or empty");
372
373 retval = rte_eth_dev_get_port_by_name(entry_str, &iconf->port_id);
374 if (retval < 0)
375 FatalError("%s: interface not found: %s", entry_str, rte_strerror(-retval));
376
377 strlcpy(iconf->iface, entry_str, sizeof(iconf->iface));
378 SCReturn;
379}
380
381static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str)
382{
383 SCEnter();
384 static uint16_t remaining_auto_cpus = UINT16_MAX; // uninitialized
386 SCLogError("DPDK runmode requires configured thread affinity");
387 SCReturnInt(-EINVAL);
388 }
389
390 bool wtaf_periface = true;
391 ThreadsAffinityType *wtaf = GetAffinityTypeForNameAndIface("worker-cpu-set", iconf->iface);
392 if (wtaf == NULL) {
393 wtaf_periface = false;
394 wtaf = GetAffinityTypeForNameAndIface("worker-cpu-set", NULL); // mandatory
395 if (wtaf == NULL) {
396 SCLogError("Specify worker-cpu-set list in the threading section");
397 SCReturnInt(-EINVAL);
398 }
399 }
400 ThreadsAffinityType *mtaf = GetAffinityTypeForNameAndIface("management-cpu-set", NULL);
401 if (mtaf == NULL) {
402 SCLogError("Specify management-cpu-set list in the threading section");
403 SCReturnInt(-EINVAL);
404 }
405 uint16_t sched_cpus = UtilAffinityGetAffinedCPUNum(wtaf);
406 if (sched_cpus == UtilCpuGetNumProcessorsOnline()) {
408 "\"all\" specified in worker CPU cores affinity, excluding management threads");
409 UtilAffinityCpusExclude(wtaf, mtaf);
410 sched_cpus = UtilAffinityGetAffinedCPUNum(wtaf);
411 }
412
413 if (sched_cpus == 0) {
414 SCLogError("No worker CPU cores with configured affinity were configured");
415 SCReturnInt(-EINVAL);
416 } else if (UtilAffinityCpusOverlap(wtaf, mtaf) != 0) {
417 SCLogWarning("Worker threads should not overlap with management threads in the CPU core "
418 "affinity configuration");
419 }
420
421 const char *active_runmode = RunmodeGetActive();
422 if (active_runmode && !strcmp("single", active_runmode)) {
423 iconf->threads = 1;
424 SCReturnInt(0);
425 }
426
427 if (entry_str == NULL) {
428 SCLogError("Number of threads for interface \"%s\" not specified", iconf->iface);
429 SCReturnInt(-EINVAL);
430 }
431
432 if (strcmp(entry_str, "auto") == 0) {
433 if (wtaf_periface) {
434 iconf->threads = (uint16_t)sched_cpus;
435 SCLogConfig("%s: auto-assigned %u threads", iconf->iface, iconf->threads);
436 SCReturnInt(0);
437 }
438
439 uint16_t live_dev_count = (uint16_t)LiveGetDeviceCountWithoutAssignedThreading();
440 if (live_dev_count == 0) {
441 SCLogError("No live devices found, cannot auto-assign threads");
442 SCReturnInt(-EINVAL);
443 }
444 iconf->threads = sched_cpus / live_dev_count;
445 if (iconf->threads == 0) {
446 SCLogError("Not enough worker CPU cores with affinity were configured");
447 SCReturnInt(-ERANGE);
448 }
449
450 if (remaining_auto_cpus == UINT16_MAX) {
451 // first time auto-assignment
452 remaining_auto_cpus = sched_cpus % live_dev_count;
453 if (remaining_auto_cpus > 0) {
454 iconf->threads++;
455 remaining_auto_cpus--;
456 }
457 } else if (remaining_auto_cpus > 0) {
458 iconf->threads++;
459 remaining_auto_cpus--;
460 }
461 SCLogConfig("%s: auto-assigned %u threads", iconf->iface, iconf->threads);
462 SCReturnInt(0);
463 }
464
465 if (StringParseUint16(&iconf->threads, 10, 0, entry_str) < 0) {
466 SCLogError("Threads entry for interface %s contain non-numerical characters - \"%s\"",
467 iconf->iface, entry_str);
468 SCReturnInt(-EINVAL);
469 }
470
471 if (iconf->threads <= 0) {
472 SCLogError("%s: positive number of threads required", iconf->iface);
473 SCReturnInt(-ERANGE);
474 }
475
476 SCReturnInt(0);
477}
478
479static bool ConfigSetInterruptMode(DPDKIfaceConfig *iconf, bool enable)
480{
481 SCEnter();
482 if (enable)
483 iconf->flags |= DPDK_IRQ_MODE;
484
485 SCReturnBool(true);
486}
487
488static int ConfigSetRxQueues(DPDKIfaceConfig *iconf, uint16_t nb_queues, uint16_t max_queues)
489{
490 SCEnter();
491 if (nb_queues == 0) {
492 SCLogInfo("%s: positive number of RX queues is required", iconf->iface);
493 SCReturnInt(-ERANGE);
494 }
495
496 if (nb_queues > max_queues) {
497 SCLogInfo("%s: number of RX queues cannot exceed %" PRIu16, iconf->iface, max_queues);
498 SCReturnInt(-ERANGE);
499 }
500
501 iconf->nb_rx_queues = nb_queues;
502 SCReturnInt(0);
503}
504
505static bool ConfigIfaceSendsPkts(const char *mode)
506{
507 SCEnter();
508 if (strcmp(mode, "ips") == 0 || strcmp(mode, "tap") == 0) {
509 SCReturnBool(true);
510 }
511 SCReturnBool(false);
512}
513
514static int ConfigSetTxQueues(
515 DPDKIfaceConfig *iconf, uint16_t nb_queues, uint16_t max_queues, bool iface_sends_pkts)
516{
517 SCEnter();
518 if (nb_queues == 0 && iface_sends_pkts) {
519 SCLogInfo("%s: positive number of TX queues is required", iconf->iface);
520 SCReturnInt(-ERANGE);
521 }
522
523 if (nb_queues > max_queues) {
524 SCLogInfo("%s: number of TX queues cannot exceed %" PRIu16, iconf->iface, max_queues);
525 SCReturnInt(-ERANGE);
526 }
527
528 iconf->nb_tx_queues = nb_queues;
529 SCReturnInt(0);
530}
531
532static uint32_t MempoolSizeCalculate(
533 uint32_t rx_queues, uint32_t rx_desc, uint32_t tx_queues, uint32_t tx_desc)
534{
535 uint32_t sz = rx_queues * rx_desc + tx_queues * tx_desc;
536 if (!tx_queues || !tx_desc)
537 sz *= 2; // double to have enough space for RX descriptors
538
539 return sz;
540}
541
542static int ConfigSetMempoolSize(DPDKIfaceConfig *iconf, const char *entry_str)
543{
544 SCEnter();
545 if (entry_str == NULL || entry_str[0] == '\0' || strcmp(entry_str, "auto") == 0) {
546 // calculate the mempool size based on the number of:
547 // - RX / TX queues
548 // - RX / TX descriptors
549 bool err = false;
550 if (iconf->nb_rx_queues == 0) {
551 // in IDS mode, we don't need TX queues
552 SCLogError("%s: cannot autocalculate mempool size without RX queues", iconf->iface);
553 err = true;
554 }
555
556 if (iconf->nb_rx_desc == 0) {
558 "%s: cannot autocalculate mempool size without RX descriptors", iconf->iface);
559 err = true;
560 }
561
562 if (err) {
563 SCReturnInt(-EINVAL);
564 }
565
566 iconf->mempool_size = MempoolSizeCalculate(
567 iconf->nb_rx_queues, iconf->nb_rx_desc, iconf->nb_tx_queues, iconf->nb_tx_desc);
568 SCReturnInt(0);
569 }
570
571 if (StringParseUint32(&iconf->mempool_size, 10, 0, entry_str) < 0) {
572 SCLogError("%s: mempool size entry contain non-numerical characters - \"%s\"", iconf->iface,
573 entry_str);
574 SCReturnInt(-EINVAL);
575 }
576
577 if (MempoolSizeCalculate(
578 iconf->nb_rx_queues, iconf->nb_rx_desc, iconf->nb_tx_queues, iconf->nb_tx_desc) >
579 iconf->mempool_size + 1) { // +1 to mask mempool size advice given in Suricata 7.0.x -
580 // mp_size should be n = (2^q - 1)
581 SCLogError("%s: mempool size is likely too small for the number of descriptors and queues, "
582 "set to \"auto\" or adjust to the value of \"%" PRIu32 "\"",
583 iconf->iface,
584 MempoolSizeCalculate(iconf->nb_rx_queues, iconf->nb_rx_desc, iconf->nb_tx_queues,
585 iconf->nb_tx_desc));
586 SCReturnInt(-ERANGE);
587 }
588
589 if (iconf->mempool_size == 0) {
590 SCLogError("%s: mempool size requires a positive integer", iconf->iface);
591 SCReturnInt(-ERANGE);
592 }
593
594 SCReturnInt(0);
595}
596
597static uint32_t MempoolCacheSizeCalculate(uint32_t mp_sz)
598{
599 // It is advised to have mempool cache size lower or equal to:
600 // RTE_MEMPOOL_CACHE_MAX_SIZE (by default 512) and "mempool-size / 1.5"
601 // and at the same time "mempool-size modulo cache_size == 0".
602 uint32_t max_cache_size = MIN(RTE_MEMPOOL_CACHE_MAX_SIZE, (uint32_t)(mp_sz / 1.5));
603 return GreatestDivisorUpTo(mp_sz, max_cache_size);
604}
605
606static int ConfigSetMempoolCacheSize(DPDKIfaceConfig *iconf, const char *entry_str)
607{
608 SCEnter();
609 if (entry_str == NULL || entry_str[0] == '\0' || strcmp(entry_str, "auto") == 0) {
610 // calculate the mempool size based on the mempool size (it needs to be already filled in)
611 if (iconf->mempool_size == 0) {
612 SCLogError("%s: cannot calculate mempool cache size of a mempool with size %d",
613 iconf->iface, iconf->mempool_size);
614 SCReturnInt(-EINVAL);
615 }
616
617 iconf->mempool_cache_size = MempoolCacheSizeCalculate(iconf->mempool_size);
618 SCReturnInt(0);
619 }
620
621 if (StringParseUint32(&iconf->mempool_cache_size, 10, 0, entry_str) < 0) {
622 SCLogError("%s: mempool cache size entry contain non-numerical characters - \"%s\"",
623 iconf->iface, entry_str);
624 SCReturnInt(-EINVAL);
625 }
626
627 if (iconf->mempool_cache_size <= 0 || iconf->mempool_cache_size > RTE_MEMPOOL_CACHE_MAX_SIZE) {
628 SCLogError("%s: mempool cache size requires a positive number smaller than %" PRIu32,
629 iconf->iface, RTE_MEMPOOL_CACHE_MAX_SIZE);
630 SCReturnInt(-ERANGE);
631 }
632
633 SCReturnInt(0);
634}
635
636static int ConfigSetRxDescriptors(DPDKIfaceConfig *iconf, const char *entry_str, uint16_t max_desc)
637{
638 SCEnter();
639 if (entry_str == NULL || entry_str[0] == '\0') {
640 SCLogInfo("%s: number of RX descriptors not found, going with: %s", iconf->iface,
641 DPDK_CONFIG_DEFAULT_RX_DESCRIPTORS);
642 entry_str = DPDK_CONFIG_DEFAULT_RX_DESCRIPTORS;
643 }
644
645 if (strcmp(entry_str, "auto") == 0) {
646 iconf->nb_rx_desc = (uint16_t)GreatestPowOf2UpTo(max_desc);
647 SCReturnInt(0);
648 }
649
650 if (StringParseUint16(&iconf->nb_rx_desc, 10, 0, entry_str) < 0) {
651 SCLogError("%s: RX descriptors entry contains non-numerical characters - \"%s\"",
652 iconf->iface, entry_str);
653 SCReturnInt(-EINVAL);
654 }
655
656 if (iconf->nb_rx_desc == 0) {
657 SCLogError("%s: positive number of RX descriptors is required", iconf->iface);
658 SCReturnInt(-ERANGE);
659 } else if (iconf->nb_rx_desc > max_desc) {
660 SCLogError("%s: number of RX descriptors cannot exceed %" PRIu16, iconf->iface, max_desc);
661 SCReturnInt(-ERANGE);
662 }
663
664 SCReturnInt(0);
665}
666
667static int ConfigSetTxDescriptors(
668 DPDKIfaceConfig *iconf, const char *entry_str, uint16_t max_desc, bool iface_sends_pkts)
669{
670 SCEnter();
671 if (entry_str == NULL || entry_str[0] == '\0') {
672 SCLogInfo("%s: number of TX descriptors not found, going with: %s", iconf->iface,
673 DPDK_CONFIG_DEFAULT_TX_DESCRIPTORS);
674 entry_str = DPDK_CONFIG_DEFAULT_TX_DESCRIPTORS;
675 }
676
677 if (strcmp(entry_str, "auto") == 0) {
678 if (iface_sends_pkts) {
679 iconf->nb_tx_desc = (uint16_t)GreatestPowOf2UpTo(max_desc);
680 } else {
681 iconf->nb_tx_desc = 0;
682 }
683 SCReturnInt(0);
684 }
685
686 if (StringParseUint16(&iconf->nb_tx_desc, 10, 0, entry_str) < 0) {
687 SCLogError("%s: TX descriptors entry contains non-numerical characters - \"%s\"",
688 iconf->iface, entry_str);
689 SCReturnInt(-EINVAL);
690 }
691
692 if (iconf->nb_tx_desc == 0 && iface_sends_pkts) {
693 SCLogError("%s: positive number of TX descriptors is required", iconf->iface);
694 SCReturnInt(-ERANGE);
695 } else if (iconf->nb_tx_desc > max_desc) {
696 SCLogError("%s: number of TX descriptors cannot exceed %" PRIu16, iconf->iface, max_desc);
697 SCReturnInt(-ERANGE);
698 }
699
700 SCReturnInt(0);
701}
702
703static int ConfigSetRSSHashFunctions(DPDKIfaceConfig *iconf, const char *entry_str)
704{
705 SCEnter();
706 if (entry_str == NULL || entry_str[0] == '\0' || strcmp(entry_str, "auto") == 0) {
707 iconf->rss_hf = DPDK_CONFIG_DEFAULT_RSS_HASH_FUNCTIONS;
708 SCReturnInt(0);
709 }
710
711 if (StringParseUint64(&iconf->rss_hf, 0, 0, entry_str) < 0) {
712 SCLogError("%s: RSS hash functions entry contain non-numerical characters - \"%s\"",
713 iconf->iface, entry_str);
714 SCReturnInt(-EINVAL);
715 }
716
717 SCReturnInt(0);
718}
719
720static int ConfigSetMtu(DPDKIfaceConfig *iconf, intmax_t entry_int)
721{
722 SCEnter();
723 if (entry_int < RTE_ETHER_MIN_MTU || entry_int > RTE_ETHER_MAX_JUMBO_FRAME_LEN) {
724 SCLogError("%s: MTU size can only be between %" PRIu32 " and %" PRIu32, iconf->iface,
725 RTE_ETHER_MIN_MTU, RTE_ETHER_MAX_JUMBO_FRAME_LEN);
726 SCReturnInt(-ERANGE);
727 }
728
729 iconf->mtu = (uint16_t)entry_int;
730 SCReturnInt(0);
731}
732
733static int ConfigSetLinkupTimeout(DPDKIfaceConfig *iconf, intmax_t entry_int)
734{
735 SCEnter();
736 if (entry_int < 0 || entry_int > UINT16_MAX) {
737 SCLogError("%s: Link-up waiting timeout needs to be a positive number (up to %u) or 0 to "
738 "disable",
739 iconf->iface, UINT16_MAX);
740 SCReturnInt(-ERANGE);
741 }
742
743 iconf->linkup_timeout = (uint16_t)entry_int;
744 SCReturnInt(0);
745}
746
747static bool ConfigSetPromiscuousMode(DPDKIfaceConfig *iconf, int entry_bool)
748{
749 SCEnter();
750 if (entry_bool)
751 iconf->flags |= DPDK_PROMISC;
752
753 SCReturnBool(true);
754}
755
756static bool ConfigSetMulticast(DPDKIfaceConfig *iconf, int entry_bool)
757{
758 SCEnter();
759 if (entry_bool)
760 iconf->flags |= DPDK_MULTICAST; // enable
761
762 SCReturnBool(true);
763}
764
765static int ConfigSetChecksumChecks(DPDKIfaceConfig *iconf, int entry_bool)
766{
767 SCEnter();
768 if (entry_bool)
769 iconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
770
771 SCReturnInt(0);
772}
773
774static int ConfigSetChecksumOffload(DPDKIfaceConfig *iconf, int entry_bool)
775{
776 SCEnter();
777 if (entry_bool)
778 iconf->flags |= DPDK_RX_CHECKSUM_OFFLOAD;
779
780 SCReturnInt(0);
781}
782
783static void ConfigSetVlanStrip(DPDKIfaceConfig *iconf, int entry_bool)
784{
785 SCEnter();
786 iconf->vlan_strip_enabled = entry_bool;
787 SCReturn;
788}
789
790static int ConfigSetCopyIface(DPDKIfaceConfig *iconf, const char *entry_str)
791{
792 SCEnter();
793 int retval;
794
795 if (entry_str == NULL || entry_str[0] == '\0' || strcmp(entry_str, "none") == 0) {
796 iconf->out_iface = NULL;
797 SCReturnInt(0);
798 }
799
800 retval = rte_eth_dev_get_port_by_name(entry_str, &iconf->out_port_id);
801 if (retval < 0) {
802 SCLogError("%s: copy interface (%s) not found: %s", iconf->iface, entry_str,
803 rte_strerror(-retval));
804 SCReturnInt(retval);
805 }
806
807 iconf->out_iface = entry_str;
808 SCReturnInt(0);
809}
810
811static int ConfigSetCopyMode(DPDKIfaceConfig *iconf, const char *entry_str)
812{
813 SCEnter();
814 if (entry_str == NULL) {
815 SCLogWarning("%s: no copy mode specified, changing to %s ", iconf->iface,
816 DPDK_CONFIG_DEFAULT_COPY_MODE);
817 entry_str = DPDK_CONFIG_DEFAULT_COPY_MODE;
818 }
819
820 if (strcmp(entry_str, "none") != 0 && strcmp(entry_str, "tap") != 0 &&
821 strcmp(entry_str, "ips") != 0) {
822 SCLogWarning("%s: copy mode \"%s\" is not one of the possible values (none|tap|ips). "
823 "Changing to %s",
824 entry_str, iconf->iface, DPDK_CONFIG_DEFAULT_COPY_MODE);
825 entry_str = DPDK_CONFIG_DEFAULT_COPY_MODE;
826 }
827
828 if (strcmp(entry_str, "none") == 0) {
829 iconf->copy_mode = DPDK_COPY_MODE_NONE;
830 } else if (strcmp(entry_str, "tap") == 0) {
831 iconf->copy_mode = DPDK_COPY_MODE_TAP;
832 } else if (strcmp(entry_str, "ips") == 0) {
833 iconf->copy_mode = DPDK_COPY_MODE_IPS;
834 }
835
836 SCReturnInt(0);
837}
838
839static int ConfigSetCopyIfaceSettings(DPDKIfaceConfig *iconf, const char *iface, const char *mode)
840{
841 SCEnter();
842 int retval;
843
844 retval = ConfigSetCopyIface(iconf, iface);
845 if (retval < 0)
846 SCReturnInt(retval);
847
848 retval = ConfigSetCopyMode(iconf, mode);
849 if (retval < 0)
850 SCReturnInt(retval);
851
852 if (iconf->copy_mode == DPDK_COPY_MODE_NONE) {
853 if (iconf->out_iface != NULL)
854 iconf->out_iface = NULL;
855 SCReturnInt(0);
856 }
857
858 if (iconf->out_iface == NULL || strlen(iconf->out_iface) <= 0) {
859 SCLogError("%s: copy mode enabled but interface not set", iconf->iface);
860 SCReturnInt(-EINVAL);
861 }
862
863 SCReturnInt(0);
864}
865
866static int ConfigLoad(DPDKIfaceConfig *iconf, const char *iface)
867{
868 SCEnter();
869 int retval;
870 SCConfNode *if_root;
871 SCConfNode *if_default;
872 const char *entry_str = NULL;
873 intmax_t entry_int = 0;
874 int entry_bool = 0;
875 const char *copy_iface_str = NULL;
876 const char *copy_mode_str = NULL;
877
878 ConfigSetIface(iconf, iface);
879 struct rte_eth_dev_info dev_info = { 0 };
880 retval = rte_eth_dev_info_get(iconf->port_id, &dev_info);
881 if (retval < 0) {
882 SCLogError("%s: getting device info failed: %s", iconf->iface, rte_strerror(-retval));
883 SCReturnInt(retval);
884 }
885
886 retval = SCConfSetRootAndDefaultNodes("dpdk.interfaces", iconf->iface, &if_root, &if_default);
887 if (retval < 0) {
888 FatalError("failed to find DPDK configuration for the interface %s", iconf->iface);
889 }
890
891 retval = SCConfGetChildValueWithDefault(if_root, if_default, dpdk_yaml.threads, &entry_str) != 1
892 ? ConfigSetThreads(iconf, DPDK_CONFIG_DEFAULT_THREADS)
893 : ConfigSetThreads(iconf, entry_str);
894 if (retval < 0)
895 SCReturnInt(retval);
896
897 bool irq_enable;
899 if_root, if_default, dpdk_yaml.irq_mode, &entry_bool);
900 if (retval != 1) {
901 irq_enable = DPDK_CONFIG_DEFAULT_INTERRUPT_MODE;
902 } else {
903 irq_enable = entry_bool ? true : false;
904 }
905 retval = ConfigSetInterruptMode(iconf, irq_enable);
906 if (retval != true)
907 SCReturnInt(-EINVAL);
908
910 if_root, if_default, dpdk_yaml.copy_mode, &copy_mode_str);
911 if (retval != 1) {
912 copy_mode_str = DPDK_CONFIG_DEFAULT_COPY_MODE;
913 }
914
916 if_root, if_default, dpdk_yaml.rx_descriptors, &entry_str) != 1
917 ? ConfigSetRxDescriptors(iconf, DPDK_CONFIG_DEFAULT_RX_DESCRIPTORS,
918 dev_info.rx_desc_lim.nb_max)
919 : ConfigSetRxDescriptors(iconf, entry_str, dev_info.rx_desc_lim.nb_max);
920 if (retval < 0)
921 SCReturnInt(retval);
922
923 bool iface_sends_pkts = ConfigIfaceSendsPkts(copy_mode_str);
925 if_root, if_default, dpdk_yaml.tx_descriptors, &entry_str) != 1
926 ? ConfigSetTxDescriptors(iconf, DPDK_CONFIG_DEFAULT_TX_DESCRIPTORS,
927 dev_info.tx_desc_lim.nb_max, iface_sends_pkts)
928 : ConfigSetTxDescriptors(
929 iconf, entry_str, dev_info.tx_desc_lim.nb_max, iface_sends_pkts);
930 if (retval < 0)
931 SCReturnInt(retval);
932
933 // currently only mapping "1 thread == 1 RX (and 1 TX queue in IPS mode)" is supported
934 retval = ConfigSetRxQueues(iconf, iconf->threads, dev_info.max_rx_queues);
935 if (retval < 0) {
936 SCLogError("%s: too many threads configured - reduce thread count to: %" PRIu16,
937 iconf->iface, dev_info.max_rx_queues);
938 SCReturnInt(retval);
939 }
940
941 // currently only mapping "1 thread == 1 RX (and 1 TX queue in IPS mode)" is supported
942 uint16_t tx_queues = iconf->nb_tx_desc > 0 ? iconf->threads : 0;
943 retval = ConfigSetTxQueues(iconf, tx_queues, dev_info.max_tx_queues, iface_sends_pkts);
944 if (retval < 0) {
945 SCLogError("%s: too many threads configured - reduce thread count to: %" PRIu16,
946 iconf->iface, dev_info.max_tx_queues);
947 SCReturnInt(retval);
948 }
949
951 if_root, if_default, dpdk_yaml.mempool_size, &entry_str) != 1
952 ? ConfigSetMempoolSize(iconf, DPDK_CONFIG_DEFAULT_MEMPOOL_SIZE)
953 : ConfigSetMempoolSize(iconf, entry_str);
954 if (retval < 0)
955 SCReturnInt(retval);
956
958 if_root, if_default, dpdk_yaml.mempool_cache_size, &entry_str) != 1
959 ? ConfigSetMempoolCacheSize(iconf, DPDK_CONFIG_DEFAULT_MEMPOOL_CACHE_SIZE)
960 : ConfigSetMempoolCacheSize(iconf, entry_str);
961 if (retval < 0)
962 SCReturnInt(retval);
963
964 retval = SCConfGetChildValueIntWithDefault(if_root, if_default, dpdk_yaml.mtu, &entry_int) != 1
965 ? ConfigSetMtu(iconf, DPDK_CONFIG_DEFAULT_MTU)
966 : ConfigSetMtu(iconf, entry_int);
967 if (retval < 0)
968 SCReturnInt(retval);
969
970 retval = SCConfGetChildValueWithDefault(if_root, if_default, dpdk_yaml.rss_hf, &entry_str) != 1
971 ? ConfigSetRSSHashFunctions(iconf, NULL)
972 : ConfigSetRSSHashFunctions(iconf, entry_str);
973 if (retval < 0)
974 SCReturnInt(retval);
975
977 if_root, if_default, dpdk_yaml.promisc, &entry_bool) != 1
978 ? ConfigSetPromiscuousMode(iconf, DPDK_CONFIG_DEFAULT_PROMISCUOUS_MODE)
979 : ConfigSetPromiscuousMode(iconf, entry_bool);
980 if (retval != true)
981 SCReturnInt(-EINVAL);
982
984 if_root, if_default, dpdk_yaml.multicast, &entry_bool) != 1
985 ? ConfigSetMulticast(iconf, DPDK_CONFIG_DEFAULT_MULTICAST_MODE)
986 : ConfigSetMulticast(iconf, entry_bool);
987 if (retval != true)
988 SCReturnInt(-EINVAL);
989
991 if_root, if_default, dpdk_yaml.checksum_checks, &entry_bool) != 1
992 ? ConfigSetChecksumChecks(iconf, DPDK_CONFIG_DEFAULT_CHECKSUM_VALIDATION)
993 : ConfigSetChecksumChecks(iconf, entry_bool);
994 if (retval < 0)
995 SCReturnInt(retval);
996
998 if_root, if_default, dpdk_yaml.checksum_checks_offload, &entry_bool) != 1
999 ? ConfigSetChecksumOffload(
1000 iconf, DPDK_CONFIG_DEFAULT_CHECKSUM_VALIDATION_OFFLOAD)
1001 : ConfigSetChecksumOffload(iconf, entry_bool);
1002 if (retval < 0)
1003 SCReturnInt(retval);
1004
1006 if_root, if_default, dpdk_yaml.vlan_strip_offload, &entry_bool);
1007 if (retval != 1) {
1008 ConfigSetVlanStrip(iconf, DPDK_CONFIG_DEFAULT_VLAN_STRIP);
1009 } else {
1010 ConfigSetVlanStrip(iconf, entry_bool);
1011 }
1012
1014 if_root, if_default, dpdk_yaml.linkup_timeout, &entry_int) != 1
1015 ? ConfigSetLinkupTimeout(iconf, DPDK_CONFIG_DEFAULT_LINKUP_TIMEOUT)
1016 : ConfigSetLinkupTimeout(iconf, entry_int);
1017 if (retval < 0)
1018 SCReturnInt(retval);
1019
1021 if_root, if_default, dpdk_yaml.copy_iface, &copy_iface_str);
1022 if (retval != 1) {
1023 copy_iface_str = DPDK_CONFIG_DEFAULT_COPY_INTERFACE;
1024 }
1025
1026 retval = ConfigSetCopyIfaceSettings(iconf, copy_iface_str, copy_mode_str);
1027 if (retval < 0)
1028 SCReturnInt(retval);
1029
1030 SCReturnInt(0);
1031}
1032
1033static bool ConfigThreadsGenericIsValid(uint16_t iface_threads, ThreadsAffinityType *wtaf)
1034{
1035 static uint32_t total_cpus = 0;
1036 total_cpus += iface_threads;
1037 if (wtaf == NULL) {
1038 SCLogError("Specify worker-cpu-set list in the threading section");
1039 return false;
1040 }
1041 if (total_cpus > UtilAffinityGetAffinedCPUNum(wtaf)) {
1042 SCLogError("Interfaces requested more cores than configured in the worker-cpu-set "
1043 "threading section (requested %d configured %d",
1044 total_cpus, UtilAffinityGetAffinedCPUNum(wtaf));
1045 return false;
1046 }
1047
1048 return true;
1049}
1050
1051static bool ConfigThreadsInterfaceIsValid(uint16_t iface_threads, ThreadsAffinityType *itaf)
1052{
1053 if (iface_threads > UtilAffinityGetAffinedCPUNum(itaf)) {
1054 SCLogError("Interface requested more cores than configured in the interface-specific "
1055 "threading section (requested %d configured %d",
1056 iface_threads, UtilAffinityGetAffinedCPUNum(itaf));
1057 return false;
1058 }
1059
1060 return true;
1061}
1062
1063static bool ConfigIsThreadingValid(uint16_t iface_threads, const char *iface)
1064{
1065 ThreadsAffinityType *itaf = GetAffinityTypeForNameAndIface("worker-cpu-set", iface);
1066 ThreadsAffinityType *wtaf = GetAffinityTypeForNameAndIface("worker-cpu-set", NULL);
1067 if (itaf && !ConfigThreadsInterfaceIsValid(iface_threads, itaf)) {
1068 return false;
1069 } else if (itaf == NULL && !ConfigThreadsGenericIsValid(iface_threads, wtaf)) {
1070 return false;
1071 }
1072 return true;
1073}
1074
1075static DPDKIfaceConfig *ConfigParse(const char *iface)
1076{
1077 SCEnter();
1078 int retval;
1079 DPDKIfaceConfig *iconf = NULL;
1080 if (iface == NULL)
1081 FatalError("DPDK interface is NULL");
1082
1083 ConfigInit(&iconf);
1084 retval = ConfigLoad(iconf, iface);
1085 if (retval < 0 || !ConfigIsThreadingValid(iconf->threads, iface)) {
1086 iconf->DerefFunc(iconf);
1087 SCReturnPtr(NULL, "void *");
1088 }
1089
1090 SCReturnPtr(iconf, "DPDKIfaceConfig *");
1091}
1092
1093static void DeviceSetPMDSpecificRSS(struct rte_eth_rss_conf *rss_conf, const char *driver_name)
1094{
1095 if (strcmp(driver_name, "net_i40e") == 0)
1096 i40eDeviceSetRSSConf(rss_conf);
1097 if (strcmp(driver_name, "net_ice") == 0)
1098 iceDeviceSetRSSConf(rss_conf);
1099 if (strcmp(driver_name, "net_ixgbe") == 0)
1100 ixgbeDeviceSetRSSHashFunction(&rss_conf->rss_hf);
1101 if (strcmp(driver_name, "net_e1000_igb") == 0)
1102 rss_conf->rss_hf = (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_IPV6_EX);
1103}
1104
1105// Returns -1 if no bit is set
1106static int32_t GetFirstSetBitPosition(uint64_t bits)
1107{
1108 for (int32_t i = 0; i < 64; i++) {
1109 if (bits & BIT_U64(i))
1110 return i;
1111 }
1112 return -1;
1113}
1114
1115static void DumpRSSFlags(const uint64_t requested, const uint64_t actual)
1116{
1117 SCLogConfig("REQUESTED (groups):");
1118
1120 "RTE_ETH_RSS_IP %sset", ((requested & RTE_ETH_RSS_IP) == RTE_ETH_RSS_IP) ? "" : "NOT ");
1121 SCLogConfig("RTE_ETH_RSS_TCP %sset",
1122 ((requested & RTE_ETH_RSS_TCP) == RTE_ETH_RSS_TCP) ? "" : "NOT ");
1123 SCLogConfig("RTE_ETH_RSS_UDP %sset",
1124 ((requested & RTE_ETH_RSS_UDP) == RTE_ETH_RSS_UDP) ? "" : "NOT ");
1125 SCLogConfig("RTE_ETH_RSS_SCTP %sset",
1126 ((requested & RTE_ETH_RSS_SCTP) == RTE_ETH_RSS_SCTP) ? "" : "NOT ");
1127 SCLogConfig("RTE_ETH_RSS_TUNNEL %sset",
1128 ((requested & RTE_ETH_RSS_TUNNEL) == RTE_ETH_RSS_TUNNEL) ? "" : "NOT ");
1129
1130 SCLogConfig("REQUESTED (individual):");
1131 SCLogConfig("RTE_ETH_RSS_IPV4 (Bit position: %d) %sset",
1132 GetFirstSetBitPosition(RTE_ETH_RSS_IPV4), (requested & RTE_ETH_RSS_IPV4) ? "" : "NOT ");
1133 SCLogConfig("RTE_ETH_RSS_FRAG_IPV4 (Bit position: %d) %sset",
1134 GetFirstSetBitPosition(RTE_ETH_RSS_FRAG_IPV4),
1135 (requested & RTE_ETH_RSS_FRAG_IPV4) ? "" : "NOT ");
1136 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_TCP (Bit position: %d) %sset",
1137 GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV4_TCP),
1138 (requested & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? "" : "NOT ");
1139 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_UDP (Bit position: %d) %sset",
1140 GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV4_UDP),
1141 (requested & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? "" : "NOT ");
1142 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_SCTP (Bit position: %d) %sset",
1143 GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV4_SCTP),
1144 (requested & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) ? "" : "NOT ");
1145 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_OTHER (Bit position: %d) %sset",
1146 GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV4_OTHER),
1147 (requested & RTE_ETH_RSS_NONFRAG_IPV4_OTHER) ? "" : "NOT ");
1148 SCLogConfig("RTE_ETH_RSS_IPV6 (Bit position: %d) %sset",
1149 GetFirstSetBitPosition(RTE_ETH_RSS_IPV6), (requested & RTE_ETH_RSS_IPV6) ? "" : "NOT ");
1150 SCLogConfig("RTE_ETH_RSS_FRAG_IPV6 (Bit position: %d) %sset",
1151 GetFirstSetBitPosition(RTE_ETH_RSS_FRAG_IPV6),
1152 (requested & RTE_ETH_RSS_FRAG_IPV6) ? "" : "NOT ");
1153 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_TCP (Bit position: %d) %sset",
1154 GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV6_TCP),
1155 (requested & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? "" : "NOT ");
1156 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_UDP (Bit position: %d) %sset",
1157 GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV6_UDP),
1158 (requested & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? "" : "NOT ");
1159 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_SCTP (Bit position: %d) %sset",
1160 GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV6_SCTP),
1161 (requested & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) ? "" : "NOT ");
1162 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_OTHER (Bit position: %d) %sset",
1163 GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV6_OTHER),
1164 (requested & RTE_ETH_RSS_NONFRAG_IPV6_OTHER) ? "" : "NOT ");
1165
1166 SCLogConfig("RTE_ETH_RSS_L2_PAYLOAD (Bit position: %d) %sset",
1167 GetFirstSetBitPosition(RTE_ETH_RSS_L2_PAYLOAD),
1168 (requested & RTE_ETH_RSS_L2_PAYLOAD) ? "" : "NOT ");
1169 SCLogConfig("RTE_ETH_RSS_IPV6_EX (Bit position: %d) %sset",
1170 GetFirstSetBitPosition(RTE_ETH_RSS_IPV6_EX),
1171 (requested & RTE_ETH_RSS_IPV6_EX) ? "" : "NOT ");
1172 SCLogConfig("RTE_ETH_RSS_IPV6_TCP_EX (Bit position: %d) %sset",
1173 GetFirstSetBitPosition(RTE_ETH_RSS_IPV6_TCP_EX),
1174 (requested & RTE_ETH_RSS_IPV6_TCP_EX) ? "" : "NOT ");
1175 SCLogConfig("RTE_ETH_RSS_IPV6_UDP_EX (Bit position: %d) %sset",
1176 GetFirstSetBitPosition(RTE_ETH_RSS_IPV6_UDP_EX),
1177 (requested & RTE_ETH_RSS_IPV6_UDP_EX) ? "" : "NOT ");
1178
1179 SCLogConfig("RTE_ETH_RSS_PORT (Bit position: %d) %sset",
1180 GetFirstSetBitPosition(RTE_ETH_RSS_PORT), (requested & RTE_ETH_RSS_PORT) ? "" : "NOT ");
1181 SCLogConfig("RTE_ETH_RSS_VXLAN (Bit position: %d) %sset",
1182 GetFirstSetBitPosition(RTE_ETH_RSS_VXLAN),
1183 (requested & RTE_ETH_RSS_VXLAN) ? "" : "NOT ");
1184 SCLogConfig("RTE_ETH_RSS_NVGRE (Bit position: %d) %sset",
1185 GetFirstSetBitPosition(RTE_ETH_RSS_NVGRE),
1186 (requested & RTE_ETH_RSS_NVGRE) ? "" : "NOT ");
1187 SCLogConfig("RTE_ETH_RSS_GTPU (Bit position: %d) %sset",
1188 GetFirstSetBitPosition(RTE_ETH_RSS_GTPU), (requested & RTE_ETH_RSS_GTPU) ? "" : "NOT ");
1189
1190 SCLogConfig("RTE_ETH_RSS_L3_SRC_ONLY (Bit position: %d) %sset",
1191 GetFirstSetBitPosition(RTE_ETH_RSS_L3_SRC_ONLY),
1192 (requested & RTE_ETH_RSS_L3_SRC_ONLY) ? "" : "NOT ");
1193 SCLogConfig("RTE_ETH_RSS_L3_DST_ONLY (Bit position: %d) %sset",
1194 GetFirstSetBitPosition(RTE_ETH_RSS_L3_DST_ONLY),
1195 (requested & RTE_ETH_RSS_L3_DST_ONLY) ? "" : "NOT ");
1196 SCLogConfig("RTE_ETH_RSS_L4_SRC_ONLY (Bit position: %d) %sset",
1197 GetFirstSetBitPosition(RTE_ETH_RSS_L4_SRC_ONLY),
1198 (requested & RTE_ETH_RSS_L4_SRC_ONLY) ? "" : "NOT ");
1199 SCLogConfig("RTE_ETH_RSS_L4_DST_ONLY (Bit position: %d) %sset",
1200 GetFirstSetBitPosition(RTE_ETH_RSS_L4_DST_ONLY),
1201 (requested & RTE_ETH_RSS_L4_DST_ONLY) ? "" : "NOT ");
1202 SCLogConfig("ACTUAL (group):");
1204 "RTE_ETH_RSS_IP %sset", ((actual & RTE_ETH_RSS_IP) == RTE_ETH_RSS_IP) ? "" : "NOT ");
1206 "RTE_ETH_RSS_TCP %sset", ((actual & RTE_ETH_RSS_TCP) == RTE_ETH_RSS_TCP) ? "" : "NOT ");
1208 "RTE_ETH_RSS_UDP %sset", ((actual & RTE_ETH_RSS_UDP) == RTE_ETH_RSS_UDP) ? "" : "NOT ");
1209 SCLogConfig("RTE_ETH_RSS_SCTP %sset",
1210 ((actual & RTE_ETH_RSS_SCTP) == RTE_ETH_RSS_SCTP) ? "" : "NOT ");
1211 SCLogConfig("RTE_ETH_RSS_TUNNEL %sset",
1212 ((actual & RTE_ETH_RSS_TUNNEL) == RTE_ETH_RSS_TUNNEL) ? "" : "NOT ");
1213
1214 SCLogConfig("ACTUAL (individual flags):");
1215 SCLogConfig("RTE_ETH_RSS_IPV4 %sset", (actual & RTE_ETH_RSS_IPV4) ? "" : "NOT ");
1216 SCLogConfig("RTE_ETH_RSS_FRAG_IPV4 %sset", (actual & RTE_ETH_RSS_FRAG_IPV4) ? "" : "NOT ");
1217 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_TCP %sset",
1218 (actual & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? "" : "NOT ");
1219 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_UDP %sset",
1220 (actual & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? "" : "NOT ");
1221 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_SCTP %sset",
1222 (actual & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) ? "" : "NOT ");
1223 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_OTHER %sset",
1224 (actual & RTE_ETH_RSS_NONFRAG_IPV4_OTHER) ? "" : "NOT ");
1225 SCLogConfig("RTE_ETH_RSS_IPV6 %sset", (actual & RTE_ETH_RSS_IPV6) ? "" : "NOT ");
1226 SCLogConfig("RTE_ETH_RSS_FRAG_IPV6 %sset", (actual & RTE_ETH_RSS_FRAG_IPV6) ? "" : "NOT ");
1227 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_TCP %sset",
1228 (actual & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? "" : "NOT ");
1229 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_UDP %sset",
1230 (actual & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? "" : "NOT ");
1231 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_SCTP %sset",
1232 (actual & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) ? "" : "NOT ");
1233 SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_OTHER %sset",
1234 (actual & RTE_ETH_RSS_NONFRAG_IPV6_OTHER) ? "" : "NOT ");
1235
1236 SCLogConfig("RTE_ETH_RSS_L2_PAYLOAD %sset", (actual & RTE_ETH_RSS_L2_PAYLOAD) ? "" : "NOT ");
1237 SCLogConfig("RTE_ETH_RSS_IPV6_EX %sset", (actual & RTE_ETH_RSS_IPV6_EX) ? "" : "NOT ");
1238 SCLogConfig("RTE_ETH_RSS_IPV6_TCP_EX %sset", (actual & RTE_ETH_RSS_IPV6_TCP_EX) ? "" : "NOT ");
1239 SCLogConfig("RTE_ETH_RSS_IPV6_UDP_EX %sset", (actual & RTE_ETH_RSS_IPV6_UDP_EX) ? "" : "NOT ");
1240
1241 SCLogConfig("RTE_ETH_RSS_PORT %sset", (actual & RTE_ETH_RSS_PORT) ? "" : "NOT ");
1242 SCLogConfig("RTE_ETH_RSS_VXLAN %sset", (actual & RTE_ETH_RSS_VXLAN) ? "" : "NOT ");
1243 SCLogConfig("RTE_ETH_RSS_NVGRE %sset", (actual & RTE_ETH_RSS_NVGRE) ? "" : "NOT ");
1244 SCLogConfig("RTE_ETH_RSS_GTPU %sset", (actual & RTE_ETH_RSS_GTPU) ? "" : "NOT ");
1245
1246 SCLogConfig("RTE_ETH_RSS_L3_SRC_ONLY %sset", (actual & RTE_ETH_RSS_L3_SRC_ONLY) ? "" : "NOT ");
1247 SCLogConfig("RTE_ETH_RSS_L3_DST_ONLY %sset", (actual & RTE_ETH_RSS_L3_DST_ONLY) ? "" : "NOT ");
1248 SCLogConfig("RTE_ETH_RSS_L4_SRC_ONLY %sset", (actual & RTE_ETH_RSS_L4_SRC_ONLY) ? "" : "NOT ");
1249 SCLogConfig("RTE_ETH_RSS_L4_DST_ONLY %sset", (actual & RTE_ETH_RSS_L4_DST_ONLY) ? "" : "NOT ");
1250}
1251
1252static void DumpRXOffloadCapabilities(const uint64_t rx_offld_capa)
1253{
1254 SCLogConfig("RTE_ETH_RX_OFFLOAD_VLAN_STRIP - %savailable",
1255 rx_offld_capa & RTE_ETH_RX_OFFLOAD_VLAN_STRIP ? "" : "NOT ");
1256 SCLogConfig("RTE_ETH_RX_OFFLOAD_IPV4_CKSUM - %savailable",
1257 rx_offld_capa & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ? "" : "NOT ");
1258 SCLogConfig("RTE_ETH_RX_OFFLOAD_UDP_CKSUM - %savailable",
1259 rx_offld_capa & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ? "" : "NOT ");
1260 SCLogConfig("RTE_ETH_RX_OFFLOAD_TCP_CKSUM - %savailable",
1261 rx_offld_capa & RTE_ETH_RX_OFFLOAD_TCP_CKSUM ? "" : "NOT ");
1262 SCLogConfig("RTE_ETH_RX_OFFLOAD_TCP_LRO - %savailable",
1263 rx_offld_capa & RTE_ETH_RX_OFFLOAD_TCP_LRO ? "" : "NOT ");
1264 SCLogConfig("RTE_ETH_RX_OFFLOAD_QINQ_STRIP - %savailable",
1265 rx_offld_capa & RTE_ETH_RX_OFFLOAD_QINQ_STRIP ? "" : "NOT ");
1266 SCLogConfig("RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM - %savailable",
1267 rx_offld_capa & RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM ? "" : "NOT ");
1268 SCLogConfig("RTE_ETH_RX_OFFLOAD_MACSEC_STRIP - %savailable",
1269 rx_offld_capa & RTE_ETH_RX_OFFLOAD_MACSEC_STRIP ? "" : "NOT ");
1270#if RTE_VERSION < RTE_VERSION_NUM(22, 11, 0, 0)
1271 SCLogConfig("RTE_ETH_RX_OFFLOAD_HEADER_SPLIT - %savailable",
1272 rx_offld_capa & RTE_ETH_RX_OFFLOAD_HEADER_SPLIT ? "" : "NOT ");
1273#endif
1274 SCLogConfig("RTE_ETH_RX_OFFLOAD_VLAN_FILTER - %savailable",
1275 rx_offld_capa & RTE_ETH_RX_OFFLOAD_VLAN_FILTER ? "" : "NOT ");
1276 SCLogConfig("RTE_ETH_RX_OFFLOAD_VLAN_EXTEND - %savailable",
1277 rx_offld_capa & RTE_ETH_RX_OFFLOAD_VLAN_EXTEND ? "" : "NOT ");
1278 SCLogConfig("RTE_ETH_RX_OFFLOAD_SCATTER - %savailable",
1279 rx_offld_capa & RTE_ETH_RX_OFFLOAD_SCATTER ? "" : "NOT ");
1280 SCLogConfig("RTE_ETH_RX_OFFLOAD_TIMESTAMP - %savailable",
1281 rx_offld_capa & RTE_ETH_RX_OFFLOAD_TIMESTAMP ? "" : "NOT ");
1282 SCLogConfig("RTE_ETH_RX_OFFLOAD_SECURITY - %savailable",
1283 rx_offld_capa & RTE_ETH_RX_OFFLOAD_SECURITY ? "" : "NOT ");
1284 SCLogConfig("RTE_ETH_RX_OFFLOAD_KEEP_CRC - %savailable",
1285 rx_offld_capa & RTE_ETH_RX_OFFLOAD_KEEP_CRC ? "" : "NOT ");
1286 SCLogConfig("RTE_ETH_RX_OFFLOAD_SCTP_CKSUM - %savailable",
1287 rx_offld_capa & RTE_ETH_RX_OFFLOAD_SCTP_CKSUM ? "" : "NOT ");
1288 SCLogConfig("RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM - %savailable",
1289 rx_offld_capa & RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM ? "" : "NOT ");
1290 SCLogConfig("RTE_ETH_RX_OFFLOAD_RSS_HASH - %savailable",
1291 rx_offld_capa & RTE_ETH_RX_OFFLOAD_RSS_HASH ? "" : "NOT ");
1292#if RTE_VERSION >= RTE_VERSION_NUM(20, 11, 0, 0)
1293 SCLogConfig("RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT - %savailable",
1294 rx_offld_capa & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT ? "" : "NOT ");
1295#endif
1296}
1297
1298static int DeviceValidateMTU(const DPDKIfaceConfig *iconf, const struct rte_eth_dev_info *dev_info)
1299{
1300 SCEnter();
1301 if (iconf->mtu > dev_info->max_mtu || iconf->mtu < dev_info->min_mtu) {
1302 SCLogError("%s: MTU out of bounds. "
1303 "Min MTU: %" PRIu16 " Max MTU: %" PRIu16,
1304 iconf->iface, dev_info->min_mtu, dev_info->max_mtu);
1305 SCReturnInt(-ERANGE);
1306 }
1307
1308#if RTE_VERSION < RTE_VERSION_NUM(21, 11, 0, 0)
1309 // check if jumbo frames are set and are available
1310 if (iconf->mtu > RTE_ETHER_MAX_LEN &&
1311 !(dev_info->rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME)) {
1312 SCLogError("%s: jumbo frames not supported, set MTU to 1500", iconf->iface);
1313 SCReturnInt(-EINVAL);
1314 }
1315#endif
1316
1317 SCReturnInt(0);
1318}
1319
1320static void DeviceSetMTU(struct rte_eth_conf *port_conf, uint16_t mtu)
1321{
1322#if RTE_VERSION >= RTE_VERSION_NUM(21, 11, 0, 0)
1323 port_conf->rxmode.mtu = mtu;
1324#else
1325 port_conf->rxmode.max_rx_pkt_len = mtu;
1326 if (mtu > RTE_ETHER_MAX_LEN) {
1327 port_conf->rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
1328 }
1329#endif
1330}
1331
1332static void PortConfSetInterruptMode(const DPDKIfaceConfig *iconf, struct rte_eth_conf *port_conf)
1333{
1334 SCLogConfig("%s: interrupt mode is %s", iconf->iface,
1335 iconf->flags & DPDK_IRQ_MODE ? "enabled" : "disabled");
1336 if (iconf->flags & DPDK_IRQ_MODE)
1337 port_conf->intr_conf.rxq = 1;
1338}
1339
1340static void PortConfSetRSSConf(const DPDKIfaceConfig *iconf,
1341 const struct rte_eth_dev_info *dev_info, struct rte_eth_conf *port_conf)
1342{
1343 if (dev_info->rx_offload_capa & RTE_ETH_RX_OFFLOAD_RSS_HASH) {
1344 if (iconf->nb_rx_queues > 1) {
1345 SCLogConfig("%s: RSS enabled for %d queues", iconf->iface, iconf->nb_rx_queues);
1346 port_conf->rx_adv_conf.rss_conf = (struct rte_eth_rss_conf){
1347 .rss_key = RSS_HKEY,
1348 .rss_key_len = RSS_HKEY_LEN,
1349 .rss_hf = iconf->rss_hf,
1350 };
1351
1352 const char *dev_driver = dev_info->driver_name;
1353 if (strcmp(dev_info->driver_name, "net_bonding") == 0) {
1354 dev_driver = BondingDeviceDriverGet(iconf->port_id);
1355 }
1356
1357 DeviceSetPMDSpecificRSS(&port_conf->rx_adv_conf.rss_conf, dev_driver);
1358
1359 uint64_t rss_hf_tmp =
1360 port_conf->rx_adv_conf.rss_conf.rss_hf & dev_info->flow_type_rss_offloads;
1361 if (port_conf->rx_adv_conf.rss_conf.rss_hf != rss_hf_tmp) {
1362 DumpRSSFlags(port_conf->rx_adv_conf.rss_conf.rss_hf, rss_hf_tmp);
1363
1364 SCLogWarning("%s: modified RSS hash function based on hardware support: "
1365 "requested:%#" PRIx64 ", configured:%#" PRIx64,
1366 iconf->iface, port_conf->rx_adv_conf.rss_conf.rss_hf, rss_hf_tmp);
1367 port_conf->rx_adv_conf.rss_conf.rss_hf = rss_hf_tmp;
1368 }
1369 port_conf->rxmode.mq_mode = RTE_ETH_MQ_RX_RSS;
1370 } else {
1371 SCLogConfig("%s: RSS not enabled", iconf->iface);
1372 port_conf->rx_adv_conf.rss_conf.rss_key = NULL;
1373 port_conf->rx_adv_conf.rss_conf.rss_hf = 0;
1374 }
1375 } else {
1376 SCLogConfig("%s: RSS not supported", iconf->iface);
1377 }
1378}
1379
1380static void PortConfSetChsumOffload(const DPDKIfaceConfig *iconf,
1381 const struct rte_eth_dev_info *dev_info, struct rte_eth_conf *port_conf)
1382{
1383 if (iconf->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
1384 SCLogConfig("%s: checksum validation disabled", iconf->iface);
1385 } else if ((dev_info->rx_offload_capa & RTE_ETH_RX_OFFLOAD_CHECKSUM) ==
1386 RTE_ETH_RX_OFFLOAD_CHECKSUM) { // multibit comparison to make sure all bits are set
1387 if (iconf->checksum_mode == CHECKSUM_VALIDATION_ENABLE &&
1388 iconf->flags & DPDK_RX_CHECKSUM_OFFLOAD) {
1389 SCLogConfig("%s: IP, TCP and UDP checksum validation offloaded", iconf->iface);
1390 port_conf->rxmode.offloads |= RTE_ETH_RX_OFFLOAD_CHECKSUM;
1391 } else if (iconf->checksum_mode == CHECKSUM_VALIDATION_ENABLE &&
1392 !(iconf->flags & DPDK_RX_CHECKSUM_OFFLOAD)) {
1393 SCLogConfig("%s: checksum validation enabled (but can be offloaded)", iconf->iface);
1394 }
1395 }
1396}
1397
1398static void PortConfSetVlanOffload(const DPDKIfaceConfig *iconf,
1399 const struct rte_eth_dev_info *dev_info, struct rte_eth_conf *port_conf)
1400{
1401 if (iconf->vlan_strip_enabled) {
1402 if (dev_info->rx_offload_capa & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) {
1403 port_conf->rxmode.offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
1404 SCLogConfig("%s: hardware VLAN stripping enabled", iconf->iface);
1405 } else {
1406 SCLogWarning("%s: hardware VLAN stripping enabled but not supported, disabling",
1407 iconf->iface);
1408 }
1409 }
1410}
1411
1412static void DeviceInitPortConf(const DPDKIfaceConfig *iconf,
1413 const struct rte_eth_dev_info *dev_info, struct rte_eth_conf *port_conf)
1414{
1415 DumpRXOffloadCapabilities(dev_info->rx_offload_capa);
1416 *port_conf = (struct rte_eth_conf){
1417 .rxmode = {
1418 .mq_mode = RTE_ETH_MQ_RX_NONE,
1419 .offloads = 0, // turn every offload off to prevent any packet modification
1420 },
1421 .txmode = {
1422 .mq_mode = RTE_ETH_MQ_TX_NONE,
1423 .offloads = 0,
1424 },
1425 };
1426
1427 PortConfSetInterruptMode(iconf, port_conf);
1428
1429 // configure RX offloads
1430 PortConfSetRSSConf(iconf, dev_info, port_conf);
1431 PortConfSetChsumOffload(iconf, dev_info, port_conf);
1432 DeviceSetMTU(port_conf, iconf->mtu);
1433 PortConfSetVlanOffload(iconf, dev_info, port_conf);
1434
1435 if (dev_info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) {
1436 port_conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
1437 }
1438}
1439
1440static int DeviceConfigureQueues(DPDKIfaceConfig *iconf, const struct rte_eth_dev_info *dev_info,
1441 const struct rte_eth_conf *port_conf)
1442{
1443 SCEnter();
1444 int retval;
1445 struct rte_eth_rxconf rxq_conf;
1446 struct rte_eth_txconf txq_conf;
1447
1448 retval = DPDKDeviceResourcesInit(&(iconf->pkt_mempools), iconf->nb_rx_queues);
1449 if (retval < 0) {
1450 goto cleanup;
1451 }
1452
1453 // +4 for VLAN header
1454 uint16_t mtu_size = iconf->mtu + RTE_ETHER_CRC_LEN + RTE_ETHER_HDR_LEN + 4;
1455 uint16_t mbuf_size = ROUNDUP(mtu_size, 1024) + RTE_PKTMBUF_HEADROOM;
1456 // ceil the div so e.g. mp_size of 262144 and 262143 both lead to 65535 on 4 rx queues
1457 uint32_t q_mp_sz = (iconf->mempool_size + iconf->nb_rx_queues - 1) / iconf->nb_rx_queues - 1;
1458 uint32_t q_mp_cache_sz = MempoolCacheSizeCalculate(q_mp_sz);
1459 SCLogInfo("%s: creating %u packet mempools of size %u, cache size %u, mbuf size %u",
1460 iconf->iface, iconf->nb_rx_queues, q_mp_sz, q_mp_cache_sz, mbuf_size);
1461 for (int i = 0; i < iconf->nb_rx_queues; i++) {
1462 char mempool_name[64];
1463 snprintf(mempool_name, sizeof(mempool_name), "mp_%d_%.20s", i, iconf->iface);
1464 iconf->pkt_mempools->pkt_mp[i] = rte_pktmbuf_pool_create(
1465 mempool_name, q_mp_sz, q_mp_cache_sz, 0, mbuf_size, (int)iconf->socket_id);
1466 if (iconf->pkt_mempools->pkt_mp[i] == NULL) {
1467 retval = -rte_errno;
1468 SCLogError("%s: rte_pktmbuf_pool_create failed with code %d (mempool: %s) - %s",
1469 iconf->iface, rte_errno, mempool_name, rte_strerror(rte_errno));
1470 goto cleanup;
1471 }
1472 }
1473
1474 for (uint16_t queue_id = 0; queue_id < iconf->nb_rx_queues; queue_id++) {
1475 rxq_conf = dev_info->default_rxconf;
1476 rxq_conf.offloads = port_conf->rxmode.offloads;
1477 rxq_conf.rx_thresh.hthresh = 0;
1478 rxq_conf.rx_thresh.pthresh = 0;
1479 rxq_conf.rx_thresh.wthresh = 0;
1480 rxq_conf.rx_free_thresh = 0;
1481 rxq_conf.rx_drop_en = 0;
1482 SCLogConfig("%s: setting up RX queue %d: rx_desc: %u offloads: 0x%" PRIx64
1483 " hthresh: %" PRIu8 " pthresh: %" PRIu8 " wthresh: %" PRIu8
1484 " free_thresh: %" PRIu16 " drop_en: %" PRIu8,
1485 iconf->iface, queue_id, iconf->nb_rx_desc, rxq_conf.offloads,
1486 rxq_conf.rx_thresh.hthresh, rxq_conf.rx_thresh.pthresh, rxq_conf.rx_thresh.wthresh,
1487 rxq_conf.rx_free_thresh, rxq_conf.rx_drop_en);
1488
1489 retval = rte_eth_rx_queue_setup(iconf->port_id, queue_id, iconf->nb_rx_desc,
1490 (unsigned int)iconf->socket_id, &rxq_conf, iconf->pkt_mempools->pkt_mp[queue_id]);
1491 if (retval < 0) {
1492 SCLogError("%s: failed to setup RX queue %u: %s", iconf->iface, queue_id,
1493 rte_strerror(-retval));
1494 goto cleanup;
1495 }
1496 }
1497
1498 for (uint16_t queue_id = 0; queue_id < iconf->nb_tx_queues; queue_id++) {
1499 txq_conf = dev_info->default_txconf;
1500 txq_conf.offloads = port_conf->txmode.offloads;
1501 SCLogConfig("%s: setting up TX queue %d: tx_desc: %" PRIu16 " tx: offloads: 0x%" PRIx64
1502 " hthresh: %" PRIu8 " pthresh: %" PRIu8 " wthresh: %" PRIu8
1503 " tx_free_thresh: %" PRIu16 " tx_rs_thresh: %" PRIu16
1504 " txq_deferred_start: %" PRIu8,
1505 iconf->iface, queue_id, iconf->nb_tx_desc, txq_conf.offloads,
1506 txq_conf.tx_thresh.hthresh, txq_conf.tx_thresh.pthresh, txq_conf.tx_thresh.wthresh,
1507 txq_conf.tx_free_thresh, txq_conf.tx_rs_thresh, txq_conf.tx_deferred_start);
1508 retval = rte_eth_tx_queue_setup(iconf->port_id, queue_id, iconf->nb_tx_desc,
1509 (unsigned int)iconf->socket_id, &txq_conf);
1510 if (retval < 0) {
1511 SCLogError("%s: failed to setup TX queue %u: %s", iconf->iface, queue_id,
1512 rte_strerror(-retval));
1513 retval = -1; // the error code explained, informing about failure
1514 goto cleanup;
1515 }
1516 }
1517
1518 SCReturnInt(0);
1519
1520cleanup:
1521 DPDKDeviceResourcesDeinit(&iconf->pkt_mempools);
1522 SCReturnInt(retval);
1523}
1524
1525static int DeviceValidateOutIfaceConfig(DPDKIfaceConfig *iconf)
1526{
1527 SCEnter();
1528 int retval;
1529 DPDKIfaceConfig *out_iconf = NULL;
1530 ConfigInit(&out_iconf);
1531 if (out_iconf == NULL) {
1532 FatalError("Copy interface of the interface \"%s\" is NULL", iconf->iface);
1533 }
1534
1535 retval = ConfigLoad(out_iconf, iconf->out_iface);
1536 if (retval < 0) {
1537 SCLogError("%s: fail to load config of interface", iconf->out_iface);
1538 out_iconf->DerefFunc(out_iconf);
1539 SCReturnInt(-EINVAL);
1540 }
1541
1542 if (iconf->nb_rx_queues != out_iconf->nb_tx_queues) {
1543 // the other direction is validated when the copy interface is configured
1544 SCLogError("%s: configured %d RX queues but copy interface %s has %d TX queues"
1545 " - number of queues must be equal",
1546 iconf->iface, iconf->nb_rx_queues, out_iconf->iface, out_iconf->nb_tx_queues);
1547 out_iconf->DerefFunc(out_iconf);
1548 SCReturnInt(-EINVAL);
1549 } else if (iconf->mtu != out_iconf->mtu) {
1550 SCLogError("%s: configured MTU of %d but copy interface %s has MTU set to %d"
1551 " - MTU must be equal",
1552 iconf->iface, iconf->mtu, out_iconf->iface, out_iconf->mtu);
1553 out_iconf->DerefFunc(out_iconf);
1554 SCReturnInt(-EINVAL);
1555 } else if (iconf->copy_mode != out_iconf->copy_mode) {
1556 SCLogError("%s: copy modes of interfaces %s and %s are not equal", iconf->iface,
1557 iconf->iface, out_iconf->iface);
1558 out_iconf->DerefFunc(out_iconf);
1559 SCReturnInt(-EINVAL);
1560 } else if (strcmp(iconf->iface, out_iconf->out_iface) != 0) {
1561 // check if the other iface has the current iface set as a copy iface
1562 SCLogError("%s: copy interface of %s is not set to %s", iconf->iface, out_iconf->iface,
1563 iconf->iface);
1564 out_iconf->DerefFunc(out_iconf);
1565 SCReturnInt(-EINVAL);
1566 }
1567
1568 out_iconf->DerefFunc(out_iconf);
1569 SCReturnInt(0);
1570}
1571
1572static int DeviceConfigureIPS(DPDKIfaceConfig *iconf)
1573{
1574 SCEnter();
1575 if (iconf->out_iface != NULL) {
1576 if (!rte_eth_dev_is_valid_port(iconf->out_port_id)) {
1577 SCLogError("%s: retrieved copy interface port ID \"%d\" is invalid or the device is "
1578 "not attached ",
1579 iconf->iface, iconf->out_port_id);
1580 SCReturnInt(-ENODEV);
1581 }
1582 int32_t out_port_socket_id;
1583 int retval = DPDKDeviceSetSocketID(iconf->out_port_id, &out_port_socket_id);
1584 if (retval < 0) {
1585 SCLogError("%s: invalid socket id: %s", iconf->out_iface, rte_strerror(-retval));
1586 SCReturnInt(retval);
1587 }
1588
1589 if (iconf->socket_id != out_port_socket_id) {
1591 "%s: out iface %s is not on the same NUMA node (%s - NUMA %d, %s - NUMA %d)",
1592 iconf->iface, iconf->out_iface, iconf->iface, iconf->socket_id,
1593 iconf->out_iface, out_port_socket_id);
1594 }
1595
1596 retval = DeviceValidateOutIfaceConfig(iconf);
1597 if (retval != 0) {
1598 // Error will be written out by the validation function
1599 SCReturnInt(retval);
1600 }
1601
1602 if (iconf->copy_mode == DPDK_COPY_MODE_IPS)
1603 SCLogInfo("%s: DPDK IPS mode activated: %s->%s", iconf->iface, iconf->iface,
1604 iconf->out_iface);
1605 else if (iconf->copy_mode == DPDK_COPY_MODE_TAP)
1606 SCLogInfo("%s: DPDK TAP mode activated: %s->%s", iconf->iface, iconf->iface,
1607 iconf->out_iface);
1608 }
1609 SCReturnInt(0);
1610}
1611
1612/**
1613 * Function verifies changes in e.g. device info after configuration has
1614 * happened. Sometimes (e.g. DPDK Bond PMD with Intel NICs i40e/ixgbe) change
1615 * device info only after the device configuration.
1616 * @param iconf
1617 * @param dev_info
1618 * @return 0 on success, -EAGAIN when reconfiguration is needed, <0 on failure
1619 */
1620static int32_t DeviceVerifyPostConfigure(
1621 const DPDKIfaceConfig *iconf, const struct rte_eth_dev_info *dev_info)
1622{
1623 SCEnter();
1624 struct rte_eth_dev_info post_conf_dev_info = { 0 };
1625 int32_t ret = rte_eth_dev_info_get(iconf->port_id, &post_conf_dev_info);
1626 if (ret < 0) {
1627 SCLogError("%s: getting device info failed: %s", iconf->iface, rte_strerror(-ret));
1628 SCReturnInt(ret);
1629 }
1630
1631 if (dev_info->flow_type_rss_offloads != post_conf_dev_info.flow_type_rss_offloads ||
1632 dev_info->rx_offload_capa != post_conf_dev_info.rx_offload_capa ||
1633 dev_info->tx_offload_capa != post_conf_dev_info.tx_offload_capa ||
1634 dev_info->max_rx_queues != post_conf_dev_info.max_rx_queues ||
1635 dev_info->max_tx_queues != post_conf_dev_info.max_tx_queues ||
1636 dev_info->max_mtu != post_conf_dev_info.max_mtu) {
1637 SCLogWarning("%s: device information severely changed after configuration, reconfiguring",
1638 iconf->iface);
1639 return -EAGAIN;
1640 }
1641
1642 if (strcmp(dev_info->driver_name, "net_bonding") == 0) {
1643 ret = BondingAllDevicesSameDriver(iconf->port_id);
1644 if (ret < 0) {
1645 SCLogError("%s: bond port uses port with different DPDK drivers", iconf->iface);
1646 SCReturnInt(ret);
1647 }
1648 }
1649
1650 return 0;
1651}
1652
1653static int DeviceConfigure(DPDKIfaceConfig *iconf)
1654{
1655 SCEnter();
1656 if (!rte_eth_dev_is_valid_port(iconf->port_id)) {
1657 SCLogError("%s: retrieved port ID \"%d\" is invalid or the device is not attached ",
1658 iconf->iface, iconf->port_id);
1659 SCReturnInt(-ENODEV);
1660 }
1661
1662 int32_t retval = DPDKDeviceSetSocketID(iconf->port_id, &iconf->socket_id);
1663 if (retval < 0) {
1664 SCLogError("%s: invalid socket id: %s", iconf->iface, rte_strerror(-retval));
1665 SCReturnInt(retval);
1666 }
1667
1668 struct rte_eth_dev_info dev_info = { 0 };
1669 retval = rte_eth_dev_info_get(iconf->port_id, &dev_info);
1670 if (retval < 0) {
1671 SCLogError("%s: getting device info failed: %s", iconf->iface, rte_strerror(-retval));
1672 SCReturnInt(retval);
1673 }
1674
1675 if (iconf->nb_rx_queues > dev_info.max_rx_queues) {
1676 SCLogError("%s: configured RX queues %u is higher than device maximum (%" PRIu16 ")",
1677 iconf->iface, iconf->nb_rx_queues, dev_info.max_rx_queues);
1678 SCReturnInt(-ERANGE);
1679 }
1680
1681 if (iconf->nb_tx_queues > dev_info.max_tx_queues) {
1682 SCLogError("%s: configured TX queues %u is higher than device maximum (%" PRIu16 ")",
1683 iconf->iface, iconf->nb_tx_queues, dev_info.max_tx_queues);
1684 SCReturnInt(-ERANGE);
1685 }
1686
1687 retval = DeviceValidateMTU(iconf, &dev_info);
1688 if (retval < 0)
1689 return retval;
1690
1691 struct rte_eth_conf port_conf = { 0 };
1692 DeviceInitPortConf(iconf, &dev_info, &port_conf);
1693 if (port_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM) {
1694 // Suricata does not need recalc checksums now
1695 iconf->checksum_mode = CHECKSUM_VALIDATION_OFFLOAD;
1696 }
1697
1698 retval = rte_eth_dev_configure(
1699 iconf->port_id, iconf->nb_rx_queues, iconf->nb_tx_queues, &port_conf);
1700 if (retval < 0) {
1701 SCLogError("%s: failed to configure the device: %s", iconf->iface, rte_strerror(-retval));
1702 SCReturnInt(retval);
1703 }
1704
1705 retval = DeviceVerifyPostConfigure(iconf, &dev_info);
1706 if (retval < 0)
1707 return retval;
1708
1709 uint16_t tmp_nb_rx_desc = iconf->nb_rx_desc;
1710 uint16_t tmp_nb_tx_desc = iconf->nb_tx_desc;
1711 retval = rte_eth_dev_adjust_nb_rx_tx_desc(
1712 iconf->port_id, &iconf->nb_rx_desc, &iconf->nb_tx_desc);
1713 if (retval != 0) {
1714 SCLogError("%s: failed to adjust device queue descriptors: %s", iconf->iface,
1715 rte_strerror(-retval));
1716 SCReturnInt(retval);
1717 } else if (tmp_nb_rx_desc != iconf->nb_rx_desc || tmp_nb_tx_desc != iconf->nb_tx_desc) {
1718 SCLogWarning("%s: device queue descriptors adjusted (RX: from %u to %u, TX: from %u to %u)",
1719 iconf->iface, tmp_nb_rx_desc, iconf->nb_rx_desc, tmp_nb_tx_desc, iconf->nb_tx_desc);
1720 }
1721
1722 retval = iconf->flags & DPDK_MULTICAST ? rte_eth_allmulticast_enable(iconf->port_id)
1723 : rte_eth_allmulticast_disable(iconf->port_id);
1724 if (retval == -ENOTSUP) {
1725 retval = rte_eth_allmulticast_get(iconf->port_id);
1726 // when multicast is enabled but set to disable or vice versa
1727 if ((retval == 1 && !(iconf->flags & DPDK_MULTICAST)) ||
1728 (retval == 0 && (iconf->flags & DPDK_MULTICAST))) {
1729 SCLogWarning("%s: cannot configure allmulticast, the port is %sin allmulticast mode",
1730 iconf->iface, retval == 1 ? "" : "not ");
1731 } else if (retval < 0) {
1732 SCLogError("%s: failed to get multicast mode: %s", iconf->iface, rte_strerror(-retval));
1733 SCReturnInt(retval);
1734 }
1735 } else if (retval < 0) {
1736 SCLogError("%s: error when changing multicast setting: %s", iconf->iface,
1737 rte_strerror(-retval));
1738 SCReturnInt(retval);
1739 }
1740
1741 retval = iconf->flags & DPDK_PROMISC ? rte_eth_promiscuous_enable(iconf->port_id)
1742 : rte_eth_promiscuous_disable(iconf->port_id);
1743 if (retval == -ENOTSUP) {
1744 retval = rte_eth_promiscuous_get(iconf->port_id);
1745 if ((retval == 1 && !(iconf->flags & DPDK_PROMISC)) ||
1746 (retval == 0 && (iconf->flags & DPDK_PROMISC))) {
1747 SCLogError("%s: cannot configure promiscuous mode, the port is in %spromiscuous mode",
1748 iconf->iface, retval == 1 ? "" : "non-");
1750 } else if (retval < 0) {
1751 SCLogError(
1752 "%s: failed to get promiscuous mode: %s", iconf->iface, rte_strerror(-retval));
1753 SCReturnInt(retval);
1754 }
1755 } else if (retval < 0) {
1756 SCLogError("%s: error when changing promiscuous setting: %s", iconf->iface,
1757 rte_strerror(-retval));
1759 }
1760
1761 // set maximum transmission unit
1762 SCLogConfig("%s: setting MTU to %d", iconf->iface, iconf->mtu);
1763 retval = rte_eth_dev_set_mtu(iconf->port_id, iconf->mtu);
1764 if (retval == -ENOTSUP) {
1765 // if it is not possible to set the MTU, retrieve it
1766 retval = rte_eth_dev_get_mtu(iconf->port_id, &iconf->mtu);
1767 if (retval < 0) {
1768 SCLogError("%s: failed to retrieve MTU: %s", iconf->iface, rte_strerror(-retval));
1769 SCReturnInt(retval);
1770 }
1772 "%s: changing MTU is not supported, current MTU: %u", iconf->iface, iconf->mtu);
1773 } else if (retval < 0) {
1774 SCLogError(
1775 "%s: failed to set MTU to %u: %s", iconf->iface, iconf->mtu, rte_strerror(-retval));
1776 SCReturnInt(retval);
1777 }
1778
1779 retval = DeviceConfigureQueues(iconf, &dev_info, &port_conf);
1780 if (retval < 0) {
1781 SCReturnInt(retval);
1782 }
1783
1784 retval = DeviceConfigureIPS(iconf);
1785 if (retval < 0) {
1786 SCReturnInt(retval);
1787 }
1788
1789 SCReturnInt(0);
1790}
1791
1792static void *ParseDpdkConfigAndConfigureDevice(const char *iface)
1793{
1794 int retval;
1795 DPDKIfaceConfig *iconf = ConfigParse(iface);
1796 if (iconf == NULL) {
1797 FatalError("DPDK configuration could not be parsed");
1798 }
1799
1800 retval = DeviceConfigure(iconf);
1801 if (retval == -EAGAIN) {
1802 // for e.g. bonding PMD it needs to be reconfigured
1803 retval = DeviceConfigure(iconf);
1804 }
1805
1806 if (retval < 0) { // handles both configure attempts
1807 iconf->DerefFunc(iconf);
1808 if (rte_eal_cleanup() != 0)
1809 FatalError("EAL cleanup failed: %s", rte_strerror(-retval));
1810
1811 if (retval == -ENOMEM) {
1812 FatalError("%s: memory allocation failed - consider"
1813 "%s freeing up some memory.",
1814 iface,
1815 rte_eal_has_hugepages() != 0 ? " increasing the number of hugepages or" : "");
1816 } else {
1817 FatalError("%s: failed to configure", iface);
1818 }
1819 }
1820
1821 SC_ATOMIC_RESET(iconf->ref);
1822 (void)SC_ATOMIC_ADD(iconf->ref, iconf->threads);
1823 // This counter is increased by worker threads that individually pick queue IDs.
1824 SC_ATOMIC_RESET(iconf->queue_id);
1825 SC_ATOMIC_RESET(iconf->inconsistent_numa_cnt);
1826 iconf->workers_sync = SCCalloc(1, sizeof(*iconf->workers_sync));
1827 if (iconf->workers_sync == NULL) {
1828 FatalError("Failed to allocate memory for workers_sync");
1829 }
1830 SC_ATOMIC_RESET(iconf->workers_sync->worker_checked_in);
1831 iconf->workers_sync->worker_cnt = iconf->threads;
1832
1833 // initialize LiveDev DPDK values
1834 LiveDevice *ldev_instance = LiveGetDevice(iface);
1835 if (ldev_instance == NULL) {
1836 FatalError("Device %s is not registered as a live device", iface);
1837 }
1838 for (uint16_t i = 0; i < iconf->threads; i++) {
1839 ldev_instance->dpdk_vars = iconf->pkt_mempools;
1840 iconf->pkt_mempools = NULL;
1841 }
1842 return iconf;
1843}
1844
1845/**
1846 * \brief extract information from config file
1847 *
1848 * The returned structure will be freed by the thread init function.
1849 * This is thus necessary to or copy the structure before giving it
1850 * to thread or to reparse the file for each thread (and thus have
1851 * new structure.
1852 *
1853 * After configuration is loaded, DPDK also configures the device according to the settings.
1854 *
1855 * \return a DPDKIfaceConfig corresponding to the interface name
1856 */
1857
1858static int DPDKConfigGetThreadsCount(void *conf)
1859{
1860 if (conf == NULL)
1861 FatalError("Configuration file is NULL");
1862
1863 DPDKIfaceConfig *dpdk_conf = (DPDKIfaceConfig *)conf;
1864 return dpdk_conf->threads;
1865}
1866
1867#endif /* HAVE_DPDK */
1868
1869static int DPDKRunModeIsIPS(void)
1870{
1871 /* Find initial node */
1872 const char dpdk_node_query[] = "dpdk.interfaces";
1873 SCConfNode *dpdk_node = SCConfGetNode(dpdk_node_query);
1874 if (dpdk_node == NULL) {
1875 FatalError("Unable to get %s configuration node", dpdk_node_query);
1876 }
1877
1878 const char default_iface[] = "default";
1879 SCConfNode *if_default = SCConfNodeLookupKeyValue(dpdk_node, "interface", default_iface);
1880 int nlive = LiveGetDeviceCount();
1881 bool has_ips = false;
1882 bool has_ids = false;
1883 for (int ldev = 0; ldev < nlive; ldev++) {
1884 const char *live_dev = LiveGetDeviceName(ldev);
1885 if (live_dev == NULL)
1886 FatalError("Unable to get device id %d from LiveDevice list", ldev);
1887
1888 SCConfNode *if_root = ConfFindDeviceConfig(dpdk_node, live_dev);
1889 if (if_root == NULL) {
1890 if (if_default == NULL)
1891 FatalError("Unable to get %s or %s interface", live_dev, default_iface);
1892
1893 if_root = if_default;
1894 }
1895
1896 const char *copymodestr = NULL;
1897 const char *copyifacestr = NULL;
1898 if (SCConfGetChildValueWithDefault(if_root, if_default, "copy-mode", &copymodestr) == 1 &&
1899 SCConfGetChildValue(if_root, "copy-iface", &copyifacestr) == 1) {
1900 if (strcmp(copymodestr, "ips") == 0) {
1901 has_ips = true;
1902 } else {
1903 has_ids = true;
1904 }
1905 } else {
1906 has_ids = true;
1907 }
1908
1909 if (has_ids && has_ips) {
1910 FatalError("Copy-mode of interface %s mixes with the previously set copy-modes "
1911 "(only IDS/TAP and IPS copy-mode combinations are allowed in DPDK",
1912 live_dev);
1913 }
1914 }
1915
1916 return has_ips;
1917}
1918
1919static int DPDKRunModeEnableIPS(void)
1920{
1921 int r = DPDKRunModeIsIPS();
1922 if (r == 1) {
1923 SCLogInfo("Setting IPS mode");
1925 }
1926 return r;
1927}
1928
1930{
1931 return "workers";
1932}
1933
1935{
1937 "Workers DPDK mode, each thread does all"
1938 " tasks from acquisition to logging",
1939 RunModeIdsDpdkWorkers, DPDKRunModeEnableIPS);
1940}
1941
1942/**
1943 * \brief Workers version of the DPDK processing.
1944 *
1945 * Start N threads with each thread doing all the work.
1946 *
1947 */
1949{
1950 SCEnter();
1951#ifdef HAVE_DPDK
1952 int ret;
1953
1955
1956 InitEal();
1957 ret = RunModeSetLiveCaptureWorkers(ParseDpdkConfigAndConfigureDevice, DPDKConfigGetThreadsCount,
1958 "ReceiveDPDK", "DecodeDPDK", thread_name_workers, NULL);
1959 if (ret != 0) {
1960 FatalError("Unable to start runmode");
1961 }
1962
1963 SCLogDebug("RunModeIdsDpdkWorkers initialised");
1964
1965#endif /* HAVE_DPDK */
1966 SCReturnInt(0);
1967}
1968
1969/**
1970 * @}
1971 */
struct HtpBodyChunk_ * next
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition conf.c:181
int SCConfSetRootAndDefaultNodes(const char *ifaces_node_name, const char *iface, SCConfNode **if_root, SCConfNode **if_default)
Finds and sets root and default node of the interface.
Definition conf.c:962
int SCConfGetChildValueWithDefault(const SCConfNode *base, const SCConfNode *dflt, const char *name, const char **vptr)
Definition conf.c:393
int SCConfNodeIsSequence(const SCConfNode *node)
Check if a node is a sequence or node.
Definition conf.c:925
SCConfNode * SCConfNodeLookupKeyValue(const SCConfNode *base, const char *key, const char *value)
Lookup for a key value under a specific node.
Definition conf.c:841
int SCConfGetChildValueBoolWithDefault(const SCConfNode *base, const SCConfNode *dflt, const char *name, int *val)
Definition conf.c:528
int SCConfGetChildValueIntWithDefault(const SCConfNode *base, const SCConfNode *dflt, const char *name, intmax_t *val)
Definition conf.c:476
int SCConfGetChildValue(const SCConfNode *base, const char *name, const char **vptr)
Definition conf.c:363
@ CHECKSUM_VALIDATION_OFFLOAD
Definition decode.h:48
@ CHECKSUM_VALIDATION_ENABLE
Definition decode.h:44
@ CHECKSUM_VALIDATION_DISABLE
Definition decode.h:43
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:252
int RunModeIdsDpdkWorkers(void)
Workers version of the DPDK processing.
const char * RunModeDpdkGetDefaultMode(void)
void RunModeDpdkRegister(void)
bool threading_set_cpu_affinity
Definition runmodes.c:62
char * RunmodeGetActive(void)
Definition runmodes.c:199
void RunModeRegisterNewRunMode(enum SCRunModes runmode, const char *name, const char *description, int(*RunModeFunc)(void), int(*RunModeIsIPSEnabled)(void))
Registers a new runmode.
Definition runmodes.c:486
const char * thread_name_workers
Definition runmodes.c:68
@ RUNMODE_DPDK
Definition runmodes.h:39
@ DPDK_COPY_MODE_IPS
Definition source-dpdk.h:34
@ DPDK_COPY_MODE_NONE
Definition source-dpdk.h:34
@ DPDK_COPY_MODE_TAP
Definition source-dpdk.h:34
#define DPDK_MULTICAST
Definition source-dpdk.h:41
#define DPDK_PROMISC
Definition source-dpdk.h:40
#define DPDK_IRQ_MODE
Definition source-dpdk.h:42
#define DPDK_RX_CHECKSUM_OFFLOAD
Definition source-dpdk.h:44
const char * mempool_cache_size
const char * checksum_checks_offload
const char * vlan_strip_offload
char * name
Definition conf.h:38
char * val
Definition conf.h:39
#define MIN(x, y)
size_t strlcat(char *, const char *src, size_t siz)
#define BIT_U64(n)
size_t strlcpy(char *dst, const char *src, size_t siz)
void EngineModeSetIPS(void)
Definition suricata.c:259
@ TM_ECODE_FAILED
ThreadsAffinityType * GetAffinityTypeForNameAndIface(const char *name, const char *interface_name)
Find affinity by name (*-cpu-set name) and an interface name.
uint16_t UtilAffinityGetAffinedCPUNum(ThreadsAffinityType *taf)
Return the total number of CPUs in a given affinity.
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define SC_ATOMIC_RESET(name)
wrapper for reinitializing an atomic variable.
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
int StringParseUint16(uint16_t *res, int base, size_t len, const char *str)
Definition util-byte.c:337
int StringParseUint64(uint64_t *res, int base, size_t len, const char *str)
Definition util-byte.c:308
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition util-byte.c:313
SCConfNode * ConfFindDeviceConfig(SCConfNode *node, const char *iface)
Find the configuration node for a specific device.
Definition util-conf.c:121
uint16_t UtilCpuGetNumProcessorsOnline(void)
Get the number of cpus online in the system.
Definition util-cpu.c:108
#define SCReturnBool(x)
Definition util-debug.h:295
#define SCEnter(...)
Definition util-debug.h:277
#define FatalError(...)
Definition util-debug.h:510
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCReturnPtr(x, type)
Definition util-debug.h:293
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCLogConfig(...)
Definition util-debug.h:229
#define SCReturn
Definition util-debug.h:279
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
int LiveGetDeviceCount(void)
Get the number of registered devices.
int LiveGetDeviceCountWithoutAssignedThreading(void)
const char * LiveGetDeviceName(int number)
Get a pointer to the device name at idx.
int32_t DPDKDeviceSetSocketID(uint16_t port_id, int32_t *socket_id)
Definition util-dpdk.c:75
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
int RunModeSetLiveCaptureWorkers(ConfigIfaceParserFunc ConfigParser, ConfigIfaceThreadsCountFunc ModThreadsCount, const char *recv_mod_name, const char *decode_mod_name, const char *thread_name, const char *live_dev)
void TimeModeSetLive(void)
Definition util-time.c:99