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