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-time.h"
48 #include "util-conf.h"
49 #include "suricata.h"
50 
51 #ifdef HAVE_DPDK
52 
53 #define RSS_HKEY_LEN 40
54 // General purpose RSS key for symmetric bidirectional flow distribution
55 uint8_t rss_hkey[] = { 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D,
56  0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D,
57  0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A };
58 
59 // Calculates the closest multiple of y from x
60 #define ROUNDUP(x, y) ((((x) + ((y)-1)) / (y)) * (y))
61 
62 /* Maximum DPDK EAL parameters count. */
63 #define EAL_ARGS 48
64 
65 struct Arguments {
66  uint16_t capacity;
67  char **argv;
68  uint16_t argc;
69 };
70 
71 static char *AllocArgument(size_t arg_len);
72 static char *AllocAndSetArgument(const char *arg);
73 static char *AllocAndSetOption(const char *arg);
74 
75 static void ArgumentsInit(struct Arguments *args, unsigned capacity);
76 static void ArgumentsCleanup(struct Arguments *args);
77 static void ArgumentsAdd(struct Arguments *args, char *value);
78 static void ArgumentsAddOptionAndArgument(struct Arguments *args, const char *opt, const char *arg);
79 static void InitEal(void);
80 
81 static void ConfigSetIface(DPDKIfaceConfig *iconf, const char *entry_str);
82 static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str);
83 static int ConfigSetRxQueues(DPDKIfaceConfig *iconf, uint16_t nb_queues);
84 static int ConfigSetTxQueues(DPDKIfaceConfig *iconf, uint16_t nb_queues);
85 static int ConfigSetMempoolSize(DPDKIfaceConfig *iconf, intmax_t entry_int);
86 static int ConfigSetMempoolCacheSize(DPDKIfaceConfig *iconf, const char *entry_str);
87 static int ConfigSetRxDescriptors(DPDKIfaceConfig *iconf, intmax_t entry_int);
88 static int ConfigSetTxDescriptors(DPDKIfaceConfig *iconf, intmax_t entry_int);
89 static int ConfigSetMtu(DPDKIfaceConfig *iconf, intmax_t entry_int);
90 static bool ConfigSetPromiscuousMode(DPDKIfaceConfig *iconf, int entry_bool);
91 static bool ConfigSetMulticast(DPDKIfaceConfig *iconf, int entry_bool);
92 static int ConfigSetChecksumChecks(DPDKIfaceConfig *iconf, int entry_bool);
93 static int ConfigSetChecksumOffload(DPDKIfaceConfig *iconf, int entry_bool);
94 static int ConfigSetCopyIface(DPDKIfaceConfig *iconf, const char *entry_str);
95 static int ConfigSetCopyMode(DPDKIfaceConfig *iconf, const char *entry_str);
96 static int ConfigSetCopyIfaceSettings(DPDKIfaceConfig *iconf, const char *iface, const char *mode);
97 static void ConfigInit(DPDKIfaceConfig **iconf);
98 static int ConfigLoad(DPDKIfaceConfig *iconf, const char *iface);
99 static DPDKIfaceConfig *ConfigParse(const char *iface);
100 
101 static void DeviceInitPortConf(const DPDKIfaceConfig *iconf,
102  const struct rte_eth_dev_info *dev_info, struct rte_eth_conf *port_conf);
103 static int DeviceConfigureQueues(DPDKIfaceConfig *iconf, const struct rte_eth_dev_info *dev_info,
104  const struct rte_eth_conf *port_conf);
105 static int DeviceValidateOutIfaceConfig(DPDKIfaceConfig *iconf);
106 static int DeviceConfigureIPS(DPDKIfaceConfig *iconf);
107 static int DeviceConfigure(DPDKIfaceConfig *iconf);
108 static void *ParseDpdkConfigAndConfigureDevice(const char *iface);
109 static void DPDKDerefConfig(void *conf);
110 
111 #define DPDK_CONFIG_DEFAULT_THREADS "auto"
112 #define DPDK_CONFIG_DEFAULT_MEMPOOL_SIZE 65535
113 #define DPDK_CONFIG_DEFAULT_MEMPOOL_CACHE_SIZE "auto"
114 #define DPDK_CONFIG_DEFAULT_RX_DESCRIPTORS 1024
115 #define DPDK_CONFIG_DEFAULT_TX_DESCRIPTORS 1024
116 #define DPDK_CONFIG_DEFAULT_RSS_HASH_FUNCTIONS RTE_ETH_RSS_IP
117 #define DPDK_CONFIG_DEFAULT_MTU 1500
118 #define DPDK_CONFIG_DEFAULT_PROMISCUOUS_MODE 1
119 #define DPDK_CONFIG_DEFAULT_MULTICAST_MODE 1
120 #define DPDK_CONFIG_DEFAULT_CHECKSUM_VALIDATION 1
121 #define DPDK_CONFIG_DEFAULT_CHECKSUM_VALIDATION_OFFLOAD 1
122 #define DPDK_CONFIG_DEFAULT_COPY_MODE "none"
123 #define DPDK_CONFIG_DEFAULT_COPY_INTERFACE "none"
124 
125 DPDKIfaceConfigAttributes dpdk_yaml = {
126  .threads = "threads",
127  .promisc = "promisc",
128  .multicast = "multicast",
129  .checksum_checks = "checksum-checks",
130  .checksum_checks_offload = "checksum-checks-offload",
131  .mtu = "mtu",
132  .rss_hf = "rss-hash-functions",
133  .mempool_size = "mempool-size",
134  .mempool_cache_size = "mempool-cache-size",
135  .rx_descriptors = "rx-descriptors",
136  .tx_descriptors = "tx-descriptors",
137  .copy_mode = "copy-mode",
138  .copy_iface = "copy-iface",
139 };
140 
141 static int GreatestDivisorUpTo(uint32_t num, uint32_t max_num)
142 {
143  for (int i = max_num; i >= 2; i--) {
144  if (num % i == 0) {
145  return i;
146  }
147  }
148  return 1;
149 }
150 
151 static char *AllocArgument(size_t arg_len)
152 {
153  SCEnter();
154  char *ptr;
155 
156  arg_len += 1; // null character
157  ptr = (char *)SCCalloc(arg_len, sizeof(char));
158  if (ptr == NULL)
159  FatalError("Could not allocate memory for an argument");
160 
161  SCReturnPtr(ptr, "char *");
162 }
163 
164 /**
165  * Allocates space for length of the given string and then copies contents
166  * @param arg String to set to the newly allocated space
167  * @return memory address if no error otherwise NULL (with errno set)
168  */
169 static char *AllocAndSetArgument(const char *arg)
170 {
171  SCEnter();
172  if (arg == NULL)
173  FatalError("Passed argument is NULL in DPDK config initialization");
174 
175  char *ptr;
176  size_t arg_len = strlen(arg);
177 
178  ptr = AllocArgument(arg_len);
179  strlcpy(ptr, arg, arg_len + 1);
180  SCReturnPtr(ptr, "char *");
181 }
182 
183 static char *AllocAndSetOption(const char *arg)
184 {
185  SCEnter();
186  if (arg == NULL)
187  FatalError("Passed option is NULL in DPDK config initialization");
188 
189  char *ptr = NULL;
190  size_t arg_len = strlen(arg);
191  uint8_t is_long_arg = arg_len > 1;
192  const char *dash_prefix = is_long_arg ? "--" : "-";
193  size_t full_len = arg_len + strlen(dash_prefix);
194 
195  ptr = AllocArgument(full_len);
196  strlcpy(ptr, dash_prefix, strlen(dash_prefix) + 1);
197  strlcat(ptr, arg, full_len + 1);
198  SCReturnPtr(ptr, "char *");
199 }
200 
201 static void ArgumentsInit(struct Arguments *args, unsigned capacity)
202 {
203  SCEnter();
204  args->argv = SCCalloc(capacity, sizeof(ptrdiff_t)); // alloc array of pointers
205  if (args->argv == NULL)
206  FatalError("Could not allocate memory for Arguments structure");
207 
208  args->capacity = capacity;
209  args->argc = 0;
210  SCReturn;
211 }
212 
213 static void ArgumentsCleanup(struct Arguments *args)
214 {
215  SCEnter();
216  for (int i = 0; i < args->argc; i++) {
217  if (args->argv[i] != NULL) {
218  SCFree(args->argv[i]);
219  args->argv[i] = NULL;
220  }
221  }
222 
223  SCFree(args->argv);
224  args->argv = NULL;
225  args->argc = 0;
226  args->capacity = 0;
227 }
228 
229 static void ArgumentsAdd(struct Arguments *args, char *value)
230 {
231  SCEnter();
232  if (args->argc + 1 > args->capacity)
233  FatalError("No capacity for more arguments (Max: %" PRIu32 ")", EAL_ARGS);
234 
235  args->argv[args->argc++] = value;
236  SCReturn;
237 }
238 
239 static void ArgumentsAddOptionAndArgument(struct Arguments *args, const char *opt, const char *arg)
240 {
241  SCEnter();
242  char *option;
243  char *argument;
244 
245  option = AllocAndSetOption(opt);
246  ArgumentsAdd(args, option);
247 
248  // Empty argument could mean option only (e.g. --no-huge)
249  if (arg == NULL || arg[0] == '\0')
250  SCReturn;
251 
252  argument = AllocAndSetArgument(arg);
253  ArgumentsAdd(args, argument);
254  SCReturn;
255 }
256 
257 static void InitEal(void)
258 {
259  SCEnter();
260  int retval;
261  ConfNode *param;
262  const ConfNode *eal_params = ConfGetNode("dpdk.eal-params");
263  struct Arguments args;
264  char **eal_argv;
265 
266  if (eal_params == NULL) {
267  FatalError("DPDK EAL parameters not found in the config");
268  }
269 
270  ArgumentsInit(&args, EAL_ARGS);
271  ArgumentsAdd(&args, AllocAndSetArgument("suricata"));
272 
273  TAILQ_FOREACH (param, &eal_params->head, next) {
274  ArgumentsAddOptionAndArgument(&args, param->name, param->val);
275  }
276 
277  // creating a shallow copy for cleanup because rte_eal_init changes array contents
278  eal_argv = SCMalloc(args.argc * sizeof(args.argv));
279  if (eal_argv == NULL) {
280  FatalError("Failed to allocate memory for the array of DPDK EAL arguments");
281  }
282  memcpy(eal_argv, args.argv, args.argc * sizeof(*args.argv));
283 
284  rte_log_set_global_level(RTE_LOG_WARNING);
285  retval = rte_eal_init(args.argc, eal_argv);
286 
287  ArgumentsCleanup(&args);
288  SCFree(eal_argv);
289 
290  if (retval < 0) { // retval binded to the result of rte_eal_init
291  FatalError("DPDK EAL initialization error: %s", rte_strerror(-retval));
292  }
294 }
295 
296 static void DPDKDerefConfig(void *conf)
297 {
298  SCEnter();
299  DPDKIfaceConfig *iconf = (DPDKIfaceConfig *)conf;
300 
301  if (SC_ATOMIC_SUB(iconf->ref, 1) == 1) {
302  if (iconf->pkt_mempool != NULL) {
303  rte_mempool_free(iconf->pkt_mempool);
304  }
305 
306  SCFree(iconf);
307  }
308  SCReturn;
309 }
310 
311 static void ConfigInit(DPDKIfaceConfig **iconf)
312 {
313  SCEnter();
314  DPDKIfaceConfig *ptr = NULL;
315  ptr = SCCalloc(1, sizeof(DPDKIfaceConfig));
316  if (ptr == NULL)
317  FatalError("Could not allocate memory for DPDKIfaceConfig");
318 
319  ptr->pkt_mempool = NULL;
320  ptr->out_port_id = -1; // make sure no port is set
321  SC_ATOMIC_INIT(ptr->ref);
322  (void)SC_ATOMIC_ADD(ptr->ref, 1);
323  ptr->DerefFunc = DPDKDerefConfig;
324  ptr->flags = 0;
325 
326  *iconf = ptr;
327  SCReturn;
328 }
329 
330 static void ConfigSetIface(DPDKIfaceConfig *iconf, const char *entry_str)
331 {
332  SCEnter();
333  int retval;
334 
335  if (entry_str == NULL || entry_str[0] == '\0')
336  FatalError("Interface name in DPDK config is NULL or empty");
337 
338  retval = rte_eth_dev_get_port_by_name(entry_str, &iconf->port_id);
339  if (retval < 0)
340  FatalError("Interface \"%s\": %s", entry_str, rte_strerror(-retval));
341 
342  strlcpy(iconf->iface, entry_str, sizeof(iconf->iface));
343  SCReturn;
344 }
345 
346 static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str)
347 {
348  SCEnter();
349  const char *active_runmode = RunmodeGetActive();
350 
351  if (active_runmode && !strcmp("single", active_runmode)) {
352  iconf->threads = 1;
353  SCReturnInt(0);
354  }
355 
356  if (entry_str == NULL) {
357  SCLogError("Number of threads for interface \"%s\" not specified", iconf->iface);
358  SCReturnInt(-EINVAL);
359  }
360 
361  if (strcmp(entry_str, "auto") == 0) {
362  iconf->threads = (int)UtilCpuGetNumProcessorsOnline();
363  SCLogPerf("%u cores, so using %u threads", iconf->threads, iconf->threads);
364  SCReturnInt(0);
365  }
366 
367  if (StringParseInt32(&iconf->threads, 10, 0, entry_str) < 0) {
368  SCLogError("Threads entry for interface %s contain non-numerical characters - \"%s\"",
369  iconf->iface, entry_str);
370  SCReturnInt(-EINVAL);
371  }
372 
373  if (iconf->threads < 0) {
374  SCLogError("Interface %s has a negative number of threads", iconf->iface);
375  SCReturnInt(-ERANGE);
376  }
377 
378  SCReturnInt(0);
379 }
380 
381 static int ConfigSetRxQueues(DPDKIfaceConfig *iconf, uint16_t nb_queues)
382 {
383  SCEnter();
384  iconf->nb_rx_queues = nb_queues;
385  if (iconf->nb_rx_queues < 1) {
386  SCLogError("Interface %s requires to have positive number of RX queues", iconf->iface);
387  SCReturnInt(-ERANGE);
388  }
389 
390  SCReturnInt(0);
391 }
392 
393 static int ConfigSetTxQueues(DPDKIfaceConfig *iconf, uint16_t nb_queues)
394 {
395  SCEnter();
396  iconf->nb_tx_queues = nb_queues;
397  if (iconf->nb_tx_queues < 1) {
398  SCLogError("Interface %s requires to have positive number of TX queues", iconf->iface);
399  SCReturnInt(-ERANGE);
400  }
401 
402  SCReturnInt(0);
403 }
404 
405 static int ConfigSetMempoolSize(DPDKIfaceConfig *iconf, intmax_t entry_int)
406 {
407  SCEnter();
408  if (entry_int <= 0) {
409  SCLogError("Interface %s requires to have positive memory pool size", iconf->iface);
410  SCReturnInt(-ERANGE);
411  }
412 
413  iconf->mempool_size = entry_int;
414  SCReturnInt(0);
415 }
416 
417 static int ConfigSetMempoolCacheSize(DPDKIfaceConfig *iconf, const char *entry_str)
418 {
419  SCEnter();
420  if (entry_str == NULL || entry_str[0] == '\0' || strcmp(entry_str, "auto") == 0) {
421  // calculate the mempool size based on the mempool size (it needs to be already filled in)
422  // It is advised to have mempool cache size lower or equal to:
423  // RTE_MEMPOOL_CACHE_MAX_SIZE (by default 512) and "mempool-size / 1.5"
424  // and at the same time "mempool-size modulo cache_size == 0".
425  if (iconf->mempool_size == 0) {
426  SCLogError("Cannot calculate mempool cache size of a mempool with size %d",
427  iconf->mempool_size);
428  SCReturnInt(-EINVAL);
429  }
430 
431  uint32_t max_cache_size = MAX(RTE_MEMPOOL_CACHE_MAX_SIZE, iconf->mempool_size / 1.5);
432  iconf->mempool_cache_size = GreatestDivisorUpTo(iconf->mempool_size, max_cache_size);
433  SCReturnInt(0);
434  }
435 
436  if (StringParseUint32(&iconf->mempool_cache_size, 10, 0, entry_str) < 0) {
437  SCLogError("Mempool cache size entry for interface %s contain non-numerical "
438  "characters - \"%s\"",
439  iconf->iface, entry_str);
440  SCReturnInt(-EINVAL);
441  }
442 
443  if (iconf->mempool_cache_size <= 0 || iconf->mempool_cache_size > RTE_MEMPOOL_CACHE_MAX_SIZE) {
444  SCLogError(
445  "Interface %s requires to have mempool cache size set to a positive number smaller "
446  "than %" PRIu32,
447  iconf->iface, RTE_MEMPOOL_CACHE_MAX_SIZE);
448  SCReturnInt(-ERANGE);
449  }
450 
451  SCReturnInt(0);
452 }
453 
454 static int ConfigSetRxDescriptors(DPDKIfaceConfig *iconf, intmax_t entry_int)
455 {
456  SCEnter();
457  if (entry_int <= 0) {
458  SCLogError("Interface %s requires to have positive number of RX descriptors", iconf->iface);
459  SCReturnInt(-ERANGE);
460  }
461 
462  iconf->nb_rx_desc = entry_int;
463  SCReturnInt(0);
464 }
465 
466 static int ConfigSetTxDescriptors(DPDKIfaceConfig *iconf, intmax_t entry_int)
467 {
468  SCEnter();
469  if (entry_int <= 0) {
470  SCLogError("Interface %s requires to have positive number of TX descriptors", iconf->iface);
471  SCReturnInt(-ERANGE);
472  }
473 
474  iconf->nb_tx_desc = entry_int;
475  SCReturnInt(0);
476 }
477 
478 static int ConfigSetRSSHashFunctions(DPDKIfaceConfig *iconf, const char *entry_str)
479 {
480  SCEnter();
481  if (entry_str == NULL || entry_str[0] == '\0' || strcmp(entry_str, "auto") == 0) {
482  iconf->rss_hf = DPDK_CONFIG_DEFAULT_RSS_HASH_FUNCTIONS;
483  SCReturnInt(0);
484  }
485 
486  if (StringParseUint64(&iconf->rss_hf, 0, 0, entry_str) < 0) {
487  SCLogError("RSS hash functions entry for interface %s contain non-numerical "
488  "characters - \"%s\"",
489  iconf->iface, entry_str);
490  SCReturnInt(-EINVAL);
491  }
492 
493  SCReturnInt(0);
494 }
495 
496 static int ConfigSetMtu(DPDKIfaceConfig *iconf, intmax_t entry_int)
497 {
498  SCEnter();
499  if (entry_int < RTE_ETHER_MIN_MTU || entry_int > RTE_ETHER_MAX_JUMBO_FRAME_LEN) {
500  SCLogError("Interface %s requires to have size of MTU between %" PRIu32 " and %" PRIu32,
501  iconf->iface, RTE_ETHER_MIN_MTU, RTE_ETHER_MAX_JUMBO_FRAME_LEN);
502  SCReturnInt(-ERANGE);
503  }
504 
505  iconf->mtu = entry_int;
506  SCReturnInt(0);
507 }
508 
509 static bool ConfigSetPromiscuousMode(DPDKIfaceConfig *iconf, int entry_bool)
510 {
511  SCEnter();
512  if (entry_bool)
513  iconf->flags |= DPDK_PROMISC;
514 
515  SCReturnBool(true);
516 }
517 
518 static bool ConfigSetMulticast(DPDKIfaceConfig *iconf, int entry_bool)
519 {
520  SCEnter();
521  if (entry_bool)
522  iconf->flags |= DPDK_MULTICAST; // enable
523 
524  SCReturnBool(true);
525 }
526 
527 static int ConfigSetChecksumChecks(DPDKIfaceConfig *iconf, int entry_bool)
528 {
529  SCEnter();
530  if (entry_bool)
531  iconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
532 
533  SCReturnInt(0);
534 }
535 
536 static int ConfigSetChecksumOffload(DPDKIfaceConfig *iconf, int entry_bool)
537 {
538  SCEnter();
539  if (entry_bool)
540  iconf->flags |= DPDK_RX_CHECKSUM_OFFLOAD;
541 
542  SCReturnInt(0);
543 }
544 
545 static int ConfigSetCopyIface(DPDKIfaceConfig *iconf, const char *entry_str)
546 {
547  SCEnter();
548  int retval;
549 
550  if (entry_str == NULL || entry_str[0] == '\0' || strcmp(entry_str, "none") == 0) {
551  iconf->out_iface = NULL;
552  SCReturnInt(0);
553  }
554 
555  retval = rte_eth_dev_get_port_by_name(entry_str, &iconf->out_port_id);
556  if (retval < 0) {
557  SCLogError("%s: name of the copy interface (%s) is invalid (err %d)", iconf->iface,
558  entry_str, retval);
559  SCReturnInt(retval);
560  }
561 
562  iconf->out_iface = entry_str;
563  SCReturnInt(0);
564 }
565 
566 static int ConfigSetCopyMode(DPDKIfaceConfig *iconf, const char *entry_str)
567 {
568  SCEnter();
569  if (entry_str == NULL) {
570  SCLogWarning("Interface %s has no copy mode specified, changing to %s ", iconf->iface,
571  DPDK_CONFIG_DEFAULT_COPY_MODE);
572  entry_str = DPDK_CONFIG_DEFAULT_COPY_MODE;
573  }
574 
575  if (strcmp(entry_str, "none") != 0 && strcmp(entry_str, "tap") != 0 &&
576  strcmp(entry_str, "ips") != 0) {
577  SCLogWarning(
578  "Copy mode \"%s\" is not one of the possible values (none|tap|ips) for interface "
579  "%s. Changing to %s",
580  entry_str, iconf->iface, DPDK_CONFIG_DEFAULT_COPY_MODE);
581  entry_str = DPDK_CONFIG_DEFAULT_COPY_MODE;
582  }
583 
584  if (strcmp(entry_str, "none") == 0) {
585  iconf->copy_mode = DPDK_COPY_MODE_NONE;
586  } else if (strcmp(entry_str, "tap") == 0) {
587  iconf->copy_mode = DPDK_COPY_MODE_TAP;
588  } else if (strcmp(entry_str, "ips") == 0) {
589  iconf->copy_mode = DPDK_COPY_MODE_IPS;
590  }
591 
592  SCReturnInt(0);
593 }
594 
595 static int ConfigSetCopyIfaceSettings(DPDKIfaceConfig *iconf, const char *iface, const char *mode)
596 {
597  SCEnter();
598  int retval;
599 
600  retval = ConfigSetCopyIface(iconf, iface);
601  if (retval < 0)
602  SCReturnInt(retval);
603 
604  retval = ConfigSetCopyMode(iconf, mode);
605  if (retval < 0)
606  SCReturnInt(retval);
607 
608  if (iconf->copy_mode == DPDK_COPY_MODE_NONE) {
609  if (iconf->out_iface != NULL)
610  iconf->out_iface = NULL;
611  SCReturnInt(0);
612  }
613 
614  if (iconf->out_iface == NULL || strlen(iconf->out_iface) <= 0) {
615  SCLogError("%s: copy mode enabled but interface not set", iconf->iface);
616  SCReturnInt(-EINVAL);
617  }
618 
619  SCReturnInt(0);
620 }
621 
622 static int ConfigLoad(DPDKIfaceConfig *iconf, const char *iface)
623 {
624  SCEnter();
625  int retval;
626  ConfNode *if_root;
627  ConfNode *if_default;
628  const char *entry_str = NULL;
629  intmax_t entry_int = 0;
630  int entry_bool = 0;
631  const char *copy_iface_str = NULL;
632  const char *copy_mode_str = NULL;
633 
634  ConfigSetIface(iconf, iface);
635 
636  retval = ConfSetRootAndDefaultNodes("dpdk.interfaces", iconf->iface, &if_root, &if_default);
637  if (retval < 0) {
638  FatalError("failed to find DPDK configuration for the interface %s", iconf->iface);
639  }
640 
641  retval = ConfGetChildValueWithDefault(if_root, if_default, dpdk_yaml.threads, &entry_str) != 1
642  ? ConfigSetThreads(iconf, DPDK_CONFIG_DEFAULT_THREADS)
643  : ConfigSetThreads(iconf, entry_str);
644  if (retval < 0)
645  SCReturnInt(retval);
646 
647  // currently only mapping "1 thread == 1 RX (and 1 TX queue in IPS mode)" is supported
648  retval = ConfigSetRxQueues(iconf, (uint16_t)iconf->threads);
649  if (retval < 0)
650  SCReturnInt(retval);
651 
652  // currently only mapping "1 thread == 1 RX (and 1 TX queue in IPS mode)" is supported
653  retval = ConfigSetTxQueues(iconf, (uint16_t)iconf->threads);
654  if (retval < 0)
655  SCReturnInt(retval);
656 
658  if_root, if_default, dpdk_yaml.mempool_size, &entry_int) != 1
659  ? ConfigSetMempoolSize(iconf, DPDK_CONFIG_DEFAULT_MEMPOOL_SIZE)
660  : ConfigSetMempoolSize(iconf, entry_int);
661  if (retval < 0)
662  SCReturnInt(retval);
663 
665  if_root, if_default, dpdk_yaml.mempool_cache_size, &entry_str) != 1
666  ? ConfigSetMempoolCacheSize(iconf, DPDK_CONFIG_DEFAULT_MEMPOOL_CACHE_SIZE)
667  : ConfigSetMempoolCacheSize(iconf, entry_str);
668  if (retval < 0)
669  SCReturnInt(retval);
670 
672  if_root, if_default, dpdk_yaml.rx_descriptors, &entry_int) != 1
673  ? ConfigSetRxDescriptors(iconf, DPDK_CONFIG_DEFAULT_RX_DESCRIPTORS)
674  : ConfigSetRxDescriptors(iconf, entry_int);
675  if (retval < 0)
676  SCReturnInt(retval);
677 
679  if_root, if_default, dpdk_yaml.tx_descriptors, &entry_int) != 1
680  ? ConfigSetTxDescriptors(iconf, DPDK_CONFIG_DEFAULT_TX_DESCRIPTORS)
681  : ConfigSetTxDescriptors(iconf, entry_int);
682  if (retval < 0)
683  SCReturnInt(retval);
684 
685  retval = ConfGetChildValueIntWithDefault(if_root, if_default, dpdk_yaml.mtu, &entry_int) != 1
686  ? ConfigSetMtu(iconf, DPDK_CONFIG_DEFAULT_MTU)
687  : ConfigSetMtu(iconf, entry_int);
688  if (retval < 0)
689  SCReturnInt(retval);
690 
691  retval = ConfGetChildValueWithDefault(if_root, if_default, dpdk_yaml.rss_hf, &entry_str) != 1
692  ? ConfigSetRSSHashFunctions(iconf, NULL)
693  : ConfigSetRSSHashFunctions(iconf, entry_str);
694  if (retval < 0)
695  SCReturnInt(retval);
696 
698  if_root, if_default, dpdk_yaml.promisc, &entry_bool) != 1
699  ? ConfigSetPromiscuousMode(iconf, DPDK_CONFIG_DEFAULT_PROMISCUOUS_MODE)
700  : ConfigSetPromiscuousMode(iconf, entry_bool);
701  if (retval != true)
702  SCReturnInt(-EINVAL);
703 
705  if_root, if_default, dpdk_yaml.multicast, &entry_bool) != 1
706  ? ConfigSetMulticast(iconf, DPDK_CONFIG_DEFAULT_MULTICAST_MODE)
707  : ConfigSetMulticast(iconf, entry_bool);
708  if (retval != true)
709  SCReturnInt(-EINVAL);
710 
712  if_root, if_default, dpdk_yaml.checksum_checks, &entry_bool) != 1
713  ? ConfigSetChecksumChecks(iconf, DPDK_CONFIG_DEFAULT_CHECKSUM_VALIDATION)
714  : ConfigSetChecksumChecks(iconf, entry_bool);
715  if (retval < 0)
716  SCReturnInt(retval);
717 
719  if_root, if_default, dpdk_yaml.checksum_checks_offload, &entry_bool) != 1
720  ? ConfigSetChecksumOffload(
721  iconf, DPDK_CONFIG_DEFAULT_CHECKSUM_VALIDATION_OFFLOAD)
722  : ConfigSetChecksumOffload(iconf, entry_bool);
723  if (retval < 0)
724  SCReturnInt(retval);
725 
726  retval = ConfGetChildValueWithDefault(if_root, if_default, dpdk_yaml.copy_mode, &copy_mode_str);
727  if (retval != 1)
728  SCReturnInt(-ENOENT);
729  if (retval < 0)
730  SCReturnInt(retval);
731 
733  if_root, if_default, dpdk_yaml.copy_iface, &copy_iface_str);
734  if (retval != 1)
735  SCReturnInt(-ENOENT);
736  if (retval < 0)
737  SCReturnInt(retval);
738 
739  retval = ConfigSetCopyIfaceSettings(iconf, copy_iface_str, copy_mode_str);
740  if (retval < 0)
741  SCReturnInt(retval);
742 
743  SCReturnInt(0);
744 }
745 
746 static DPDKIfaceConfig *ConfigParse(const char *iface)
747 {
748  SCEnter();
749  int retval;
750  DPDKIfaceConfig *iconf = NULL;
751  if (iface == NULL)
752  FatalError("DPDK interface is NULL");
753 
754  ConfigInit(&iconf);
755  retval = ConfigLoad(iconf, iface);
756  if (retval < 0) {
757  iconf->DerefFunc(iconf);
758  SCReturnPtr(NULL, "void *");
759  }
760 
761  SCReturnPtr(iconf, "DPDKIfaceConfig *");
762 }
763 
764 static void DeviceSetPMDSpecificRSS(struct rte_eth_rss_conf *rss_conf, const char *driver_name)
765 {
766  // RSS is configured in a specific way for a driver i40e and DPDK version <= 19.xx
767  if (strcmp(driver_name, "net_i40e") == 0)
768  i40eDeviceSetRSSHashFunction(&rss_conf->rss_hf);
769  if (strcmp(driver_name, "net_ice") == 0)
770  iceDeviceSetRSSHashFunction(&rss_conf->rss_hf);
771  if (strcmp(driver_name, "net_ixgbe") == 0)
772  ixgbeDeviceSetRSSHashFunction(&rss_conf->rss_hf);
773  if (strcmp(driver_name, "net_e1000_igb") == 0)
774  rss_conf->rss_hf = (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_IPV6_EX);
775 }
776 
777 // Returns -1 if no bit is set
778 static int GetFirstSetBitPosition(uint64_t bits)
779 {
780  for (uint64_t i = 0; i < 64; i++) {
781  if (bits & BIT_U64(i))
782  return i;
783  }
784  return -1;
785 }
786 
787 static void DumpRSSFlags(const uint64_t requested, const uint64_t actual)
788 {
789  SCLogConfig("REQUESTED (groups):");
790 
791  SCLogConfig(
792  "RTE_ETH_RSS_IP %sset", ((requested & RTE_ETH_RSS_IP) == RTE_ETH_RSS_IP) ? "" : "NOT ");
793  SCLogConfig("RTE_ETH_RSS_TCP %sset",
794  ((requested & RTE_ETH_RSS_TCP) == RTE_ETH_RSS_TCP) ? "" : "NOT ");
795  SCLogConfig("RTE_ETH_RSS_UDP %sset",
796  ((requested & RTE_ETH_RSS_UDP) == RTE_ETH_RSS_UDP) ? "" : "NOT ");
797  SCLogConfig("RTE_ETH_RSS_SCTP %sset",
798  ((requested & RTE_ETH_RSS_SCTP) == RTE_ETH_RSS_SCTP) ? "" : "NOT ");
799  SCLogConfig("RTE_ETH_RSS_TUNNEL %sset",
800  ((requested & RTE_ETH_RSS_TUNNEL) == RTE_ETH_RSS_TUNNEL) ? "" : "NOT ");
801 
802  SCLogConfig("REQUESTED (individual):");
803  SCLogConfig("RTE_ETH_RSS_IPV4 (Bit position: %d) %sset",
804  GetFirstSetBitPosition(RTE_ETH_RSS_IPV4), (requested & RTE_ETH_RSS_IPV4) ? "" : "NOT ");
805  SCLogConfig("RTE_ETH_RSS_FRAG_IPV4 (Bit position: %d) %sset",
806  GetFirstSetBitPosition(RTE_ETH_RSS_FRAG_IPV4),
807  (requested & RTE_ETH_RSS_FRAG_IPV4) ? "" : "NOT ");
808  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_TCP (Bit position: %d) %sset",
809  GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV4_TCP),
810  (requested & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? "" : "NOT ");
811  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_UDP (Bit position: %d) %sset",
812  GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV4_UDP),
813  (requested & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? "" : "NOT ");
814  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_SCTP (Bit position: %d) %sset",
815  GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV4_SCTP),
816  (requested & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) ? "" : "NOT ");
817  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_OTHER (Bit position: %d) %sset",
818  GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV4_OTHER),
819  (requested & RTE_ETH_RSS_NONFRAG_IPV4_OTHER) ? "" : "NOT ");
820  SCLogConfig("RTE_ETH_RSS_IPV6 (Bit position: %d) %sset",
821  GetFirstSetBitPosition(RTE_ETH_RSS_IPV6), (requested & RTE_ETH_RSS_IPV6) ? "" : "NOT ");
822  SCLogConfig("RTE_ETH_RSS_FRAG_IPV6 (Bit position: %d) %sset",
823  GetFirstSetBitPosition(RTE_ETH_RSS_FRAG_IPV6),
824  (requested & RTE_ETH_RSS_FRAG_IPV6) ? "" : "NOT ");
825  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_TCP (Bit position: %d) %sset",
826  GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV6_TCP),
827  (requested & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? "" : "NOT ");
828  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_UDP (Bit position: %d) %sset",
829  GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV6_UDP),
830  (requested & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? "" : "NOT ");
831  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_SCTP (Bit position: %d) %sset",
832  GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV6_SCTP),
833  (requested & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) ? "" : "NOT ");
834  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_OTHER (Bit position: %d) %sset",
835  GetFirstSetBitPosition(RTE_ETH_RSS_NONFRAG_IPV6_OTHER),
836  (requested & RTE_ETH_RSS_NONFRAG_IPV6_OTHER) ? "" : "NOT ");
837 
838  SCLogConfig("RTE_ETH_RSS_L2_PAYLOAD (Bit position: %d) %sset",
839  GetFirstSetBitPosition(RTE_ETH_RSS_L2_PAYLOAD),
840  (requested & RTE_ETH_RSS_L2_PAYLOAD) ? "" : "NOT ");
841  SCLogConfig("RTE_ETH_RSS_IPV6_EX (Bit position: %d) %sset",
842  GetFirstSetBitPosition(RTE_ETH_RSS_IPV6_EX),
843  (requested & RTE_ETH_RSS_IPV6_EX) ? "" : "NOT ");
844  SCLogConfig("RTE_ETH_RSS_IPV6_TCP_EX (Bit position: %d) %sset",
845  GetFirstSetBitPosition(RTE_ETH_RSS_IPV6_TCP_EX),
846  (requested & RTE_ETH_RSS_IPV6_TCP_EX) ? "" : "NOT ");
847  SCLogConfig("RTE_ETH_RSS_IPV6_UDP_EX (Bit position: %d) %sset",
848  GetFirstSetBitPosition(RTE_ETH_RSS_IPV6_UDP_EX),
849  (requested & RTE_ETH_RSS_IPV6_UDP_EX) ? "" : "NOT ");
850 
851  SCLogConfig("RTE_ETH_RSS_PORT (Bit position: %d) %sset",
852  GetFirstSetBitPosition(RTE_ETH_RSS_PORT), (requested & RTE_ETH_RSS_PORT) ? "" : "NOT ");
853  SCLogConfig("RTE_ETH_RSS_VXLAN (Bit position: %d) %sset",
854  GetFirstSetBitPosition(RTE_ETH_RSS_VXLAN),
855  (requested & RTE_ETH_RSS_VXLAN) ? "" : "NOT ");
856  SCLogConfig("RTE_ETH_RSS_NVGRE (Bit position: %d) %sset",
857  GetFirstSetBitPosition(RTE_ETH_RSS_NVGRE),
858  (requested & RTE_ETH_RSS_NVGRE) ? "" : "NOT ");
859  SCLogConfig("RTE_ETH_RSS_GTPU (Bit position: %d) %sset",
860  GetFirstSetBitPosition(RTE_ETH_RSS_GTPU), (requested & RTE_ETH_RSS_GTPU) ? "" : "NOT ");
861 
862  SCLogConfig("RTE_ETH_RSS_L3_SRC_ONLY (Bit position: %d) %sset",
863  GetFirstSetBitPosition(RTE_ETH_RSS_L3_SRC_ONLY),
864  (requested & RTE_ETH_RSS_L3_SRC_ONLY) ? "" : "NOT ");
865  SCLogConfig("RTE_ETH_RSS_L3_DST_ONLY (Bit position: %d) %sset",
866  GetFirstSetBitPosition(RTE_ETH_RSS_L3_DST_ONLY),
867  (requested & RTE_ETH_RSS_L3_DST_ONLY) ? "" : "NOT ");
868  SCLogConfig("RTE_ETH_RSS_L4_SRC_ONLY (Bit position: %d) %sset",
869  GetFirstSetBitPosition(RTE_ETH_RSS_L4_SRC_ONLY),
870  (requested & RTE_ETH_RSS_L4_SRC_ONLY) ? "" : "NOT ");
871  SCLogConfig("RTE_ETH_RSS_L4_DST_ONLY (Bit position: %d) %sset",
872  GetFirstSetBitPosition(RTE_ETH_RSS_L4_DST_ONLY),
873  (requested & RTE_ETH_RSS_L4_DST_ONLY) ? "" : "NOT ");
874  SCLogConfig("ACTUAL (group):");
875  SCLogConfig(
876  "RTE_ETH_RSS_IP %sset", ((actual & RTE_ETH_RSS_IP) == RTE_ETH_RSS_IP) ? "" : "NOT ");
877  SCLogConfig(
878  "RTE_ETH_RSS_TCP %sset", ((actual & RTE_ETH_RSS_TCP) == RTE_ETH_RSS_TCP) ? "" : "NOT ");
879  SCLogConfig(
880  "RTE_ETH_RSS_UDP %sset", ((actual & RTE_ETH_RSS_UDP) == RTE_ETH_RSS_UDP) ? "" : "NOT ");
881  SCLogConfig("RTE_ETH_RSS_SCTP %sset",
882  ((actual & RTE_ETH_RSS_SCTP) == RTE_ETH_RSS_SCTP) ? "" : "NOT ");
883  SCLogConfig("RTE_ETH_RSS_TUNNEL %sset",
884  ((actual & RTE_ETH_RSS_TUNNEL) == RTE_ETH_RSS_TUNNEL) ? "" : "NOT ");
885 
886  SCLogConfig("ACTUAL (individual flags):");
887  SCLogConfig("RTE_ETH_RSS_IPV4 %sset", (actual & RTE_ETH_RSS_IPV4) ? "" : "NOT ");
888  SCLogConfig("RTE_ETH_RSS_FRAG_IPV4 %sset", (actual & RTE_ETH_RSS_FRAG_IPV4) ? "" : "NOT ");
889  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_TCP %sset",
890  (actual & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? "" : "NOT ");
891  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_UDP %sset",
892  (actual & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? "" : "NOT ");
893  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_SCTP %sset",
894  (actual & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) ? "" : "NOT ");
895  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV4_OTHER %sset",
896  (actual & RTE_ETH_RSS_NONFRAG_IPV4_OTHER) ? "" : "NOT ");
897  SCLogConfig("RTE_ETH_RSS_IPV6 %sset", (actual & RTE_ETH_RSS_IPV6) ? "" : "NOT ");
898  SCLogConfig("RTE_ETH_RSS_FRAG_IPV6 %sset", (actual & RTE_ETH_RSS_FRAG_IPV6) ? "" : "NOT ");
899  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_TCP %sset",
900  (actual & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? "" : "NOT ");
901  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_UDP %sset",
902  (actual & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? "" : "NOT ");
903  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_SCTP %sset",
904  (actual & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) ? "" : "NOT ");
905  SCLogConfig("RTE_ETH_RSS_NONFRAG_IPV6_OTHER %sset",
906  (actual & RTE_ETH_RSS_NONFRAG_IPV6_OTHER) ? "" : "NOT ");
907 
908  SCLogConfig("RTE_ETH_RSS_L2_PAYLOAD %sset", (actual & RTE_ETH_RSS_L2_PAYLOAD) ? "" : "NOT ");
909  SCLogConfig("RTE_ETH_RSS_IPV6_EX %sset", (actual & RTE_ETH_RSS_IPV6_EX) ? "" : "NOT ");
910  SCLogConfig("RTE_ETH_RSS_IPV6_TCP_EX %sset", (actual & RTE_ETH_RSS_IPV6_TCP_EX) ? "" : "NOT ");
911  SCLogConfig("RTE_ETH_RSS_IPV6_UDP_EX %sset", (actual & RTE_ETH_RSS_IPV6_UDP_EX) ? "" : "NOT ");
912 
913  SCLogConfig("RTE_ETH_RSS_PORT %sset", (actual & RTE_ETH_RSS_PORT) ? "" : "NOT ");
914  SCLogConfig("RTE_ETH_RSS_VXLAN %sset", (actual & RTE_ETH_RSS_VXLAN) ? "" : "NOT ");
915  SCLogConfig("RTE_ETH_RSS_NVGRE %sset", (actual & RTE_ETH_RSS_NVGRE) ? "" : "NOT ");
916  SCLogConfig("RTE_ETH_RSS_GTPU %sset", (actual & RTE_ETH_RSS_GTPU) ? "" : "NOT ");
917 
918  SCLogConfig("RTE_ETH_RSS_L3_SRC_ONLY %sset", (actual & RTE_ETH_RSS_L3_SRC_ONLY) ? "" : "NOT ");
919  SCLogConfig("RTE_ETH_RSS_L3_DST_ONLY %sset", (actual & RTE_ETH_RSS_L3_DST_ONLY) ? "" : "NOT ");
920  SCLogConfig("RTE_ETH_RSS_L4_SRC_ONLY %sset", (actual & RTE_ETH_RSS_L4_SRC_ONLY) ? "" : "NOT ");
921  SCLogConfig("RTE_ETH_RSS_L4_DST_ONLY %sset", (actual & RTE_ETH_RSS_L4_DST_ONLY) ? "" : "NOT ");
922 }
923 
924 static int DeviceValidateMTU(const DPDKIfaceConfig *iconf, const struct rte_eth_dev_info *dev_info)
925 {
926  if (iconf->mtu > dev_info->max_mtu || iconf->mtu < dev_info->min_mtu) {
927  SCLogError("%s: MTU out of bounds. "
928  "Min MTU: %" PRIu16 " Max MTU: %" PRIu16,
929  iconf->iface, dev_info->min_mtu, dev_info->max_mtu);
930  SCReturnInt(-ERANGE);
931  }
932 
933 #if RTE_VER_YEAR < 21 || RTE_VER_YEAR == 21 && RTE_VER_MONTH < 11
934  // check if jumbo frames are set and are available
935  if (iconf->mtu > RTE_ETHER_MAX_LEN &&
936  !(dev_info->rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME)) {
937  SCLogError("%s: jumbo frames not supported, set MTU to 1500", iconf->iface);
938  SCReturnInt(-EINVAL);
939  }
940 #endif
941 
942  SCReturnInt(0);
943 }
944 
945 static void DeviceSetMTU(struct rte_eth_conf *port_conf, uint16_t mtu)
946 {
947 #if RTE_VER_YEAR > 21 || RTE_VER_YEAR == 21 && RTE_VER_MONTH == 11
948  port_conf->rxmode.mtu = mtu;
949 #else
950  port_conf->rxmode.max_rx_pkt_len = mtu;
951  if (mtu > RTE_ETHER_MAX_LEN) {
952  port_conf->rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
953  }
954 #endif
955 }
956 
957 static void DeviceInitPortConf(const DPDKIfaceConfig *iconf,
958  const struct rte_eth_dev_info *dev_info, struct rte_eth_conf *port_conf)
959 {
960  *port_conf = (struct rte_eth_conf){
961  .rxmode = {
962  .mq_mode = RTE_ETH_MQ_RX_NONE,
963  .offloads = 0, // turn every offload off to prevent any packet modification
964  },
965  .txmode = {
966  .mq_mode = RTE_ETH_MQ_TX_NONE,
967  .offloads = 0,
968  },
969  };
970 
971  // configure RX offloads
972  if (dev_info->rx_offload_capa & RTE_ETH_RX_OFFLOAD_RSS_HASH) {
973  if (iconf->nb_rx_queues > 1) {
974  SCLogConfig("%s: RSS enabled for %d queues", iconf->iface, iconf->nb_rx_queues);
975  port_conf->rx_adv_conf.rss_conf = (struct rte_eth_rss_conf){
976  .rss_key = rss_hkey,
977  .rss_key_len = RSS_HKEY_LEN,
978  .rss_hf = iconf->rss_hf,
979  };
980 
981  DeviceSetPMDSpecificRSS(&port_conf->rx_adv_conf.rss_conf, dev_info->driver_name);
982 
983  uint64_t rss_hf_tmp =
984  port_conf->rx_adv_conf.rss_conf.rss_hf & dev_info->flow_type_rss_offloads;
985  if (port_conf->rx_adv_conf.rss_conf.rss_hf != rss_hf_tmp) {
986  DumpRSSFlags(port_conf->rx_adv_conf.rss_conf.rss_hf, rss_hf_tmp);
987 
988  SCLogWarning("%s: modified RSS hash function based on hardware support: "
989  "requested:%#" PRIx64 ", configured:%#" PRIx64,
990  iconf->iface, port_conf->rx_adv_conf.rss_conf.rss_hf, rss_hf_tmp);
991  port_conf->rx_adv_conf.rss_conf.rss_hf = rss_hf_tmp;
992  }
993  port_conf->rxmode.mq_mode = RTE_ETH_MQ_RX_RSS;
994  } else {
995  SCLogConfig("%s: RSS not enabled", iconf->iface);
996  port_conf->rx_adv_conf.rss_conf.rss_key = NULL;
997  port_conf->rx_adv_conf.rss_conf.rss_hf = 0;
998  }
999  } else {
1000  SCLogConfig("%s: RSS not supported", iconf->iface);
1001  }
1002 
1003  if (iconf->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
1004  SCLogConfig("%s: checksum validation disabled", iconf->iface);
1005  } else if (dev_info->rx_offload_capa & RTE_ETH_RX_OFFLOAD_CHECKSUM) {
1006  if (iconf->checksum_mode == CHECKSUM_VALIDATION_ENABLE &&
1007  iconf->flags & DPDK_RX_CHECKSUM_OFFLOAD) {
1008  SCLogConfig("%s: IP, TCP and UDP checksum validation offloaded", iconf->iface);
1009  port_conf->rxmode.offloads |= RTE_ETH_RX_OFFLOAD_CHECKSUM;
1010  } else if (iconf->checksum_mode == CHECKSUM_VALIDATION_ENABLE &&
1011  !(iconf->flags & DPDK_RX_CHECKSUM_OFFLOAD)) {
1012  SCLogConfig("%s: checksum validation enabled (but can be offloaded)", iconf->iface);
1013  }
1014  }
1015 
1016  DeviceSetMTU(port_conf, iconf->mtu);
1017 
1018  if (dev_info->tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) {
1019  port_conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
1020  }
1021 }
1022 
1023 static int DeviceConfigureQueues(DPDKIfaceConfig *iconf, const struct rte_eth_dev_info *dev_info,
1024  const struct rte_eth_conf *port_conf)
1025 {
1026  SCEnter();
1027  int retval;
1028  uint16_t mtu_size;
1029  uint16_t mbuf_size;
1030  struct rte_eth_rxconf rxq_conf;
1031  struct rte_eth_txconf txq_conf;
1032 
1033  char mempool_name[64];
1034  snprintf(mempool_name, 64, "mempool_%.20s", iconf->iface);
1035  // +4 for VLAN header
1036  mtu_size = iconf->mtu + RTE_ETHER_CRC_LEN + RTE_ETHER_HDR_LEN + 4;
1037  mbuf_size = ROUNDUP(mtu_size, 1024) + RTE_PKTMBUF_HEADROOM;
1038  SCLogInfo("%s: creating packet mbuf pool %s of size %d, cache size %d, mbuf size %d",
1039  iconf->iface, mempool_name, iconf->mempool_size, iconf->mempool_cache_size, mbuf_size);
1040 
1041  iconf->pkt_mempool = rte_pktmbuf_pool_create(mempool_name, iconf->mempool_size,
1042  iconf->mempool_cache_size, 0, mbuf_size, (int)iconf->socket_id);
1043  if (iconf->pkt_mempool == NULL) {
1044  retval = -rte_errno;
1045  SCLogError("%s: rte_pktmbuf_pool_create failed with code %d (mempool: %s) - %s",
1046  iconf->iface, rte_errno, mempool_name, rte_strerror(rte_errno));
1047  SCReturnInt(retval);
1048  }
1049 
1050  for (uint16_t queue_id = 0; queue_id < iconf->nb_rx_queues; queue_id++) {
1051  rxq_conf = dev_info->default_rxconf;
1052  rxq_conf.offloads = port_conf->rxmode.offloads;
1053  rxq_conf.rx_thresh.hthresh = 0;
1054  rxq_conf.rx_thresh.pthresh = 0;
1055  rxq_conf.rx_thresh.wthresh = 0;
1056  rxq_conf.rx_free_thresh = 0;
1057  rxq_conf.rx_drop_en = 0;
1058  SCLogPerf("%s: rx queue setup: queue:%d port:%d rx_desc:%d tx_desc:%d rx: htresh: %d "
1059  "pthresh %d wtresh %d free_tresh %d drop_en %d offloads %lu",
1060  iconf->iface, queue_id, iconf->port_id, iconf->nb_rx_desc, iconf->nb_tx_desc,
1061  rxq_conf.rx_thresh.hthresh, rxq_conf.rx_thresh.pthresh, rxq_conf.rx_thresh.wthresh,
1062  rxq_conf.rx_free_thresh, rxq_conf.rx_drop_en, rxq_conf.offloads);
1063 
1064  retval = rte_eth_rx_queue_setup(iconf->port_id, queue_id, iconf->nb_rx_desc,
1065  iconf->socket_id, &rxq_conf, iconf->pkt_mempool);
1066  if (retval < 0) {
1067  rte_mempool_free(iconf->pkt_mempool);
1068  SCLogError(
1069  "%s: rte_eth_rx_queue_setup failed with code %d for device queue %u of port %u",
1070  iconf->iface, retval, queue_id, iconf->port_id);
1071  SCReturnInt(retval);
1072  }
1073  }
1074 
1075  for (uint16_t queue_id = 0; queue_id < iconf->nb_tx_queues; queue_id++) {
1076  txq_conf = dev_info->default_txconf;
1077  txq_conf.offloads = port_conf->txmode.offloads;
1078  SCLogPerf("%s: tx queue setup: queue:%d port:%d", iconf->iface, queue_id, iconf->port_id);
1079  retval = rte_eth_tx_queue_setup(
1080  iconf->port_id, queue_id, iconf->nb_tx_desc, iconf->socket_id, &txq_conf);
1081  if (retval < 0) {
1082  rte_mempool_free(iconf->pkt_mempool);
1083  SCLogError(
1084  "%s: rte_eth_tx_queue_setup failed with code %d for device queue %u of port %u",
1085  iconf->iface, retval, queue_id, iconf->port_id);
1086  SCReturnInt(retval);
1087  }
1088  }
1089 
1090  SCReturnInt(0);
1091 }
1092 
1093 static int DeviceValidateOutIfaceConfig(DPDKIfaceConfig *iconf)
1094 {
1095  SCEnter();
1096  int retval;
1097  DPDKIfaceConfig *out_iconf = NULL;
1098  ConfigInit(&out_iconf);
1099  if (out_iconf == NULL) {
1100  FatalError("Copy interface of the interface \"%s\" is NULL", iconf->iface);
1101  }
1102 
1103  retval = ConfigLoad(out_iconf, iconf->out_iface);
1104  if (retval < 0) {
1105  SCLogError("Fail to load config of interface %s", iconf->out_iface);
1106  out_iconf->DerefFunc(out_iconf);
1107  SCReturnInt(-EINVAL);
1108  }
1109 
1110  if (iconf->nb_rx_queues != out_iconf->nb_tx_queues) {
1111  // the other direction is validated when the copy interface is configured
1112  SCLogError("%s: configured %d RX queues but copy interface %s has %d TX queues"
1113  " - number of queues must be equal",
1114  iconf->iface, iconf->nb_rx_queues, out_iconf->iface, out_iconf->nb_tx_queues);
1115  out_iconf->DerefFunc(out_iconf);
1116  SCReturnInt(-EINVAL);
1117  } else if (iconf->mtu != out_iconf->mtu) {
1118  SCLogError("%s: configured MTU of %d but copy interface %s has MTU set to %d"
1119  " - MTU must be equal",
1120  iconf->iface, iconf->mtu, out_iconf->iface, out_iconf->mtu);
1121  out_iconf->DerefFunc(out_iconf);
1122  SCReturnInt(-EINVAL);
1123  } else if (iconf->copy_mode != out_iconf->copy_mode) {
1124  SCLogError("%s: copy modes of interfaces %s and %s are not equal", iconf->iface,
1125  iconf->iface, out_iconf->iface);
1126  out_iconf->DerefFunc(out_iconf);
1127  SCReturnInt(-EINVAL);
1128  } else if (strcmp(iconf->iface, out_iconf->out_iface) != 0) {
1129  // check if the other iface has the current iface set as a copy iface
1130  SCLogError("%s: copy interface of %s is not set to %s", iconf->iface, out_iconf->iface,
1131  iconf->iface);
1132  out_iconf->DerefFunc(out_iconf);
1133  SCReturnInt(-EINVAL);
1134  }
1135 
1136  out_iconf->DerefFunc(out_iconf);
1137  SCReturnInt(0);
1138 }
1139 
1140 static int DeviceConfigureIPS(DPDKIfaceConfig *iconf)
1141 {
1142  SCEnter();
1143  int retval;
1144 
1145  if (iconf->out_iface != NULL) {
1146  retval = rte_eth_dev_get_port_by_name(iconf->out_iface, &iconf->out_port_id);
1147  if (retval != 0) {
1148  SCLogError("%s: failed to obtain out iface %s port id (err=%d)", iconf->iface,
1149  iconf->out_iface, retval);
1150  SCReturnInt(retval);
1151  }
1152 
1153  if (rte_eth_dev_socket_id(iconf->port_id) != rte_eth_dev_socket_id(iconf->out_port_id)) {
1154  SCLogWarning("%s: out iface %s is not on the same NUMA node", iconf->iface,
1155  iconf->out_iface);
1156  }
1157 
1158  retval = DeviceValidateOutIfaceConfig(iconf);
1159  if (retval != 0) {
1160  // Error will be written out by the validation function
1161  SCReturnInt(retval);
1162  }
1163 
1164  if (iconf->copy_mode == DPDK_COPY_MODE_IPS)
1165  SCLogInfo("%s: DPDK IPS mode activated: %s->%s", iconf->iface, iconf->iface,
1166  iconf->out_iface);
1167  else if (iconf->copy_mode == DPDK_COPY_MODE_TAP)
1168  SCLogInfo("%s: DPDK TAP mode activated: %s->%s", iconf->iface, iconf->iface,
1169  iconf->out_iface);
1170  }
1171  SCReturnInt(0);
1172 }
1173 
1174 static int DeviceConfigure(DPDKIfaceConfig *iconf)
1175 {
1176  SCEnter();
1177  // configure device
1178  int retval;
1179  struct rte_eth_dev_info dev_info;
1180  struct rte_eth_conf port_conf;
1181 
1182  retval = rte_eth_dev_get_port_by_name(iconf->iface, &(iconf->port_id));
1183  if (retval < 0) {
1184  SCLogError("%s: getting port id failed (err=%d). Is device enabled?", iconf->iface, retval);
1185  SCReturnInt(retval);
1186  }
1187 
1188  if (!rte_eth_dev_is_valid_port(iconf->port_id)) {
1189  SCLogError("%s: specified port %d is invalid", iconf->iface, iconf->port_id);
1190  SCReturnInt(retval);
1191  }
1192 
1193  retval = rte_eth_dev_socket_id(iconf->port_id);
1194  if (retval < 0) {
1195  SCLogError("%s: invalid socket id (err=%d)", iconf->iface, retval);
1196  SCReturnInt(retval);
1197  }
1198  iconf->socket_id = retval;
1199 
1200  retval = rte_eth_dev_info_get(iconf->port_id, &dev_info);
1201  if (retval != 0) {
1202  SCLogError("%s: getting device info failed (err=%d)", iconf->iface, retval);
1203  SCReturnInt(retval);
1204  }
1205 
1206  if (iconf->nb_rx_queues > dev_info.max_rx_queues) {
1207  SCLogError("%s: configured RX queues %u is higher than device maximum (%" PRIu16 ")",
1208  iconf->iface, iconf->nb_rx_queues, dev_info.max_rx_queues);
1209  SCReturnInt(-ERANGE);
1210  }
1211 
1212  if (iconf->nb_tx_queues > dev_info.max_tx_queues) {
1213  SCLogError("%s: configured TX queues %u is higher than device maximum (%" PRIu16 ")",
1214  iconf->iface, iconf->nb_tx_queues, dev_info.max_tx_queues);
1215  SCReturnInt(-ERANGE);
1216  }
1217 
1218  retval = DeviceValidateMTU(iconf, &dev_info);
1219  if (retval != 0)
1220  return retval;
1221 
1222  DeviceInitPortConf(iconf, &dev_info, &port_conf);
1223  if (port_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM) {
1224  // Suricata does not need recalc checksums now
1225  iconf->checksum_mode = CHECKSUM_VALIDATION_OFFLOAD;
1226  }
1227 
1228  retval = rte_eth_dev_configure(
1229  iconf->port_id, iconf->nb_rx_queues, iconf->nb_tx_queues, &port_conf);
1230  if (retval != 0) {
1231  SCLogError("%s: failed to configure the device (port %u, err %d)", iconf->iface,
1232  iconf->port_id, retval);
1233  SCReturnInt(retval);
1234  }
1235 
1236  retval = rte_eth_dev_adjust_nb_rx_tx_desc(
1237  iconf->port_id, &iconf->nb_rx_desc, &iconf->nb_tx_desc);
1238  if (retval != 0) {
1239  SCLogError("%s: failed to adjust device queue descriptors (port %u, err %d)", iconf->iface,
1240  iconf->port_id, retval);
1241  SCReturnInt(retval);
1242  }
1243 
1244  retval = iconf->flags & DPDK_MULTICAST ? rte_eth_allmulticast_enable(iconf->port_id)
1245  : rte_eth_allmulticast_disable(iconf->port_id);
1246  if (retval == -ENOTSUP) {
1247  retval = rte_eth_allmulticast_get(iconf->port_id);
1248  // when multicast is enabled but set to disable or vice versa
1249  if ((retval == 1 && !(iconf->flags & DPDK_MULTICAST)) ||
1250  (retval == 0 && (iconf->flags & DPDK_MULTICAST))) {
1251  SCLogError("%s: Allmulticast setting of port (%" PRIu16
1252  ") can not be configured. Set it to %s",
1253  iconf->iface, iconf->port_id, retval == 1 ? "true" : "false");
1254  } else if (retval < 0) {
1255  SCLogError("%s: failed to get multicast mode (port %u, err %d)", iconf->iface,
1256  iconf->port_id, retval);
1257  SCReturnInt(retval);
1258  }
1259  } else if (retval < 0) {
1260  SCLogError("%s: error when changing multicast setting (port %u err %d)", iconf->iface,
1261  iconf->port_id, retval);
1262  SCReturnInt(retval);
1263  }
1264 
1265  retval = iconf->flags & DPDK_PROMISC ? rte_eth_promiscuous_enable(iconf->port_id)
1266  : rte_eth_promiscuous_disable(iconf->port_id);
1267  if (retval == -ENOTSUP) {
1268  retval = rte_eth_promiscuous_get(iconf->port_id);
1269  if ((retval == 1 && !(iconf->flags & DPDK_PROMISC)) ||
1270  (retval == 0 && (iconf->flags & DPDK_PROMISC))) {
1271  SCLogError("%s: promiscuous setting of port (%" PRIu16
1272  ") can not be configured. Set it to %s",
1273  iconf->iface, iconf->port_id, retval == 1 ? "true" : "false");
1275  } else if (retval < 0) {
1276  SCLogError("%s: failed to get promiscuous mode (port %u, err=%d)", iconf->iface,
1277  iconf->port_id, retval);
1278  SCReturnInt(retval);
1279  }
1280  } else if (retval < 0) {
1281  SCLogError("%s: error when changing promiscuous setting (port %u, err %d)", iconf->iface,
1282  iconf->port_id, retval);
1284  }
1285 
1286  // set maximum transmission unit
1287  SCLogConfig("%s: setting MTU to %d", iconf->iface, iconf->mtu);
1288  retval = rte_eth_dev_set_mtu(iconf->port_id, iconf->mtu);
1289  if (retval == -ENOTSUP) {
1290  SCLogWarning("%s: changing MTU on port %u is not supported, ignoring the setting",
1291  iconf->iface, iconf->port_id);
1292  // if it is not possible to set the MTU, retrieve it
1293  retval = rte_eth_dev_get_mtu(iconf->port_id, &iconf->mtu);
1294  if (retval < 0) {
1295  SCLogError("%s: failed to retrieve MTU (port %u, err %d)", iconf->iface, iconf->port_id,
1296  retval);
1297  SCReturnInt(retval);
1298  }
1299  } else if (retval < 0) {
1300  SCLogError("%s: failed to set MTU to %u (port %u, err %d)", iconf->iface, iconf->mtu,
1301  iconf->port_id, retval);
1302  SCReturnInt(retval);
1303  }
1304 
1305  retval = DeviceConfigureQueues(iconf, &dev_info, &port_conf);
1306  if (retval < 0) {
1307  SCReturnInt(retval);
1308  }
1309 
1310  retval = DeviceConfigureIPS(iconf);
1311  if (retval < 0) {
1312  SCReturnInt(retval);
1313  }
1314 
1315  SCReturnInt(0);
1316 }
1317 
1318 static void *ParseDpdkConfigAndConfigureDevice(const char *iface)
1319 {
1320  int retval;
1321  DPDKIfaceConfig *iconf = ConfigParse(iface);
1322  if (iconf == NULL) {
1323  FatalError("DPDK configuration could not be parsed");
1324  }
1325 
1326  if (DeviceConfigure(iconf) != 0) {
1327  iconf->DerefFunc(iconf);
1328  retval = rte_eal_cleanup();
1329  if (retval != 0)
1330  FatalError("EAL cleanup failed: %s", strerror(-retval));
1331 
1332  FatalError("%s: failed to configure", iface);
1333  }
1334 
1335  SC_ATOMIC_RESET(iconf->ref);
1336  (void)SC_ATOMIC_ADD(iconf->ref, iconf->threads);
1337  // This counter is increased by worker threads that individually pick queue IDs.
1338  SC_ATOMIC_RESET(iconf->queue_id);
1339  SC_ATOMIC_RESET(iconf->inconsitent_numa_cnt);
1340  return iconf;
1341 }
1342 
1343 /**
1344  * \brief extract information from config file
1345  *
1346  * The returned structure will be freed by the thread init function.
1347  * This is thus necessary to or copy the structure before giving it
1348  * to thread or to reparse the file for each thread (and thus have
1349  * new structure.
1350  *
1351  * After configuration is loaded, DPDK also configures the device according to the settings.
1352  *
1353  * \return a DPDKIfaceConfig corresponding to the interface name
1354  */
1355 
1356 static int DPDKConfigGetThreadsCount(void *conf)
1357 {
1358  if (conf == NULL)
1359  FatalError("Configuration file is NULL");
1360 
1361  DPDKIfaceConfig *dpdk_conf = (DPDKIfaceConfig *)conf;
1362  return dpdk_conf->threads;
1363 }
1364 
1365 #endif /* HAVE_DPDK */
1366 
1367 static int DPDKRunModeIsIPS(void)
1368 {
1369  /* Find initial node */
1370  const char dpdk_node_query[] = "dpdk.interfaces";
1371  ConfNode *dpdk_node = ConfGetNode(dpdk_node_query);
1372  if (dpdk_node == NULL) {
1373  FatalError("Unable to get %s configuration node", dpdk_node_query);
1374  }
1375 
1376  const char default_iface[] = "default";
1377  ConfNode *if_default = ConfNodeLookupKeyValue(dpdk_node, "interface", default_iface);
1378  int nlive = LiveGetDeviceCount();
1379  bool has_ips = false;
1380  bool has_ids = false;
1381  for (int ldev = 0; ldev < nlive; ldev++) {
1382  const char *live_dev = LiveGetDeviceName(ldev);
1383  if (live_dev == NULL)
1384  FatalError("Unable to get device id %d from LiveDevice list", ldev);
1385 
1386  ConfNode *if_root = ConfFindDeviceConfig(dpdk_node, live_dev);
1387  if (if_root == NULL) {
1388  if (if_default == NULL)
1389  FatalError("Unable to get %s or %s interface", live_dev, default_iface);
1390 
1391  if_root = if_default;
1392  }
1393 
1394  const char *copymodestr = NULL;
1395  if (ConfGetChildValueWithDefault(if_root, if_default, "copy-mode", &copymodestr) == 1) {
1396  if (strcmp(copymodestr, "ips") == 0) {
1397  has_ips = true;
1398  } else {
1399  has_ids = true;
1400  }
1401  } else {
1402  has_ids = true;
1403  }
1404 
1405  if (has_ids && has_ips) {
1406  FatalError("Copy-mode of interface %s mixes with the previously set copy-modes "
1407  "(only IDS/TAP and IPS copy-mode combinations are allowed in DPDK",
1408  live_dev);
1409  }
1410  }
1411 
1412  return has_ips;
1413 }
1414 
1415 static void DPDKRunModeEnableIPS(void)
1416 {
1417  if (DPDKRunModeIsIPS()) {
1418  SCLogInfo("Setting IPS mode");
1419  EngineModeSetIPS();
1420  }
1421 }
1422 
1423 const char *RunModeDpdkGetDefaultMode(void)
1424 {
1425  return "workers";
1426 }
1427 
1429 {
1431  "Workers DPDK mode, each thread does all"
1432  " tasks from acquisition to logging",
1433  RunModeIdsDpdkWorkers, DPDKRunModeEnableIPS);
1434 }
1435 
1436 /**
1437  * \brief Workers version of the DPDK processing.
1438  *
1439  * Start N threads with each thread doing all the work.
1440  *
1441  */
1443 {
1444  SCEnter();
1445 #ifdef HAVE_DPDK
1446  int ret;
1447 
1449  TimeModeSetLive();
1450 
1451  InitEal();
1452  ret = RunModeSetLiveCaptureWorkers(ParseDpdkConfigAndConfigureDevice, DPDKConfigGetThreadsCount,
1453  "ReceiveDPDK", "DecodeDPDK", thread_name_workers, NULL);
1454  if (ret != 0) {
1455  FatalError("Unable to start runmode");
1456  }
1457 
1458  SCLogDebug("RunModeIdsDpdkWorkers initialised");
1459 
1460 #endif /* HAVE_DPDK */
1461  SCReturnInt(0);
1462 }
1463 
1464 /**
1465  * @}
1466  */
thread_name_workers
const char * thread_name_workers
Definition: runmodes.c:81
DPDKIfaceConfigAttributes_::checksum_checks_offload
const char * checksum_checks_offload
Definition: runmode-dpdk.h:31
util-byte.h
DPDKIfaceConfigAttributes_::mempool_size
const char * mempool_size
Definition: runmode-dpdk.h:34
CHECKSUM_VALIDATION_OFFLOAD
@ CHECKSUM_VALIDATION_OFFLOAD
Definition: decode.h:50
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:322
DPDKSetTimevalOfMachineStart
void DPDKSetTimevalOfMachineStart(void)
DPDKIfaceConfigAttributes_::promisc
const char * promisc
Definition: runmode-dpdk.h:28
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:315
ConfNode_::val
char * val
Definition: conf.h:34
RUNMODE_DPDK
@ RUNMODE_DPDK
Definition: runmodes.h:40
DPDKIfaceConfigAttributes_::mempool_cache_size
const char * mempool_cache_size
Definition: runmode-dpdk.h:35
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:508
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
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:333
DPDKIfaceConfigAttributes_::copy_iface
const char * copy_iface
Definition: runmode-dpdk.h:39
RunModeInitialize
void RunModeInitialize(void)
Definition: runmodes.c:985
RunModeIdsDpdkWorkers
int RunModeIdsDpdkWorkers(void)
Workers version of the DPDK processing.
Definition: runmode-dpdk.c:1442
util-runmodes.h
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
RunModeRegisterNewRunMode
void RunModeRegisterNewRunMode(enum RunModes runmode, const char *name, const char *description, int(*RunModeFunc)(void), void(*RunModeIsIPSEnabled)(void))
Registers a new runmode.
Definition: runmodes.c:491
ConfNodeLookupKeyValue
ConfNode * ConfNodeLookupKeyValue(const ConfNode *base, const char *key, const char *value)
Lookup for a key value under a specific node.
Definition: conf.c:825
CHECKSUM_VALIDATION_DISABLE
@ CHECKSUM_VALIDATION_DISABLE
Definition: decode.h:45
RunmodeGetActive
char * RunmodeGetActive(void)
Definition: runmodes.c:217
StringParseInt32
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:622
DPDKIfaceConfig_
Definition: source-dpdk.h:45
util-dpdk-ice.h
ConfGetChildValueIntWithDefault
int ConfGetChildValueIntWithDefault(const ConfNode *base, const ConfNode *dflt, const char *name, intmax_t *val)
Definition: conf.c:460
MAX
#define MAX(x, y)
Definition: suricata-common.h:384
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:85
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:46
RunModeDpdkGetDefaultMode
const char * RunModeDpdkGetDefaultMode(void)
Definition: runmode-dpdk.c:1423
decode.h
util-device.h
util-debug.h
DPDKIfaceConfigAttributes_::rx_descriptors
const char * rx_descriptors
Definition: runmode-dpdk.h:36
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:30
DPDK_RX_CHECKSUM_OFFLOAD
#define DPDK_RX_CHECKSUM_OFFLOAD
Definition: source-dpdk.h:42
ConfFindDeviceConfig
ConfNode * ConfFindDeviceConfig(ConfNode *node, const char *iface)
Find the configuration node for a specific device.
Definition: util-conf.c:130
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
EngineModeSetIPS
void EngineModeSetIPS(void)
Definition: suricata.c:221
ConfGetChildValueWithDefault
int ConfGetChildValueWithDefault(const ConfNode *base, const ConfNode *dflt, const char *name, const char **vptr)
Definition: conf.c:376
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:342
SCReturn
#define SCReturn
Definition: util-debug.h:273
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:287
BIT_U64
#define BIT_U64(n)
Definition: suricata-common.h:390
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
TimeModeSetLive
void TimeModeSetLive(void)
Definition: util-time.c:99
DPDKIfaceConfigAttributes_::tx_descriptors
const char * tx_descriptors
Definition: runmode-dpdk.h:37
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:178
DPDK_PROMISC
#define DPDK_PROMISC
Definition: source-dpdk.h:39
ConfNode_::name
char * name
Definition: conf.h:33
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:230
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:324
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
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
DPDKIfaceConfigAttributes_::multicast
const char * multicast
Definition: runmode-dpdk.h:29
RunModeDpdkRegister
void RunModeDpdkRegister(void)
Definition: runmode-dpdk.c:1428
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:977
util-dpdk-i40e.h
suricata.h
runmode-dpdk.h
DPDKIfaceConfigAttributes_::rss_hf
const char * rss_hf
Definition: runmode-dpdk.h:33
LiveGetDeviceCount
int LiveGetDeviceCount(void)
Get the number of registered devices.
Definition: util-device.c:158
DPDKIfaceConfigAttributes_::mtu
const char * mtu
Definition: runmode-dpdk.h:32
DPDKIfaceConfigAttributes_::copy_mode
const char * copy_mode
Definition: runmode-dpdk.h:38
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