suricata
source-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  * \defgroup dpdk DPDK running mode
20  *
21  * @{
22  */
23 
24 /**
25  * \file
26  *
27  * \author Lukas Sismis <lukas.sismis@gmail.com>
28  *
29  * DPDK capture interface
30  *
31  */
32 
33 #include "suricata-common.h"
34 #include "runmodes.h"
35 #include "decode.h"
36 #include "packet.h"
37 #include "source-dpdk.h"
38 #include "suricata.h"
39 #include "threads.h"
40 #include "threadvars.h"
41 #include "tm-threads.h"
42 #include "tmqh-packetpool.h"
43 #include "util-privs.h"
44 #include "action-globals.h"
45 
46 #ifndef HAVE_DPDK
47 
48 TmEcode NoDPDKSupportExit(ThreadVars *, const void *, void **);
49 
51 {
52  tmm_modules[TMM_RECEIVEDPDK].name = "ReceiveDPDK";
59 }
60 
61 /**
62  * \brief Registration Function for DecodeDPDK.
63  */
65 {
66  tmm_modules[TMM_DECODEDPDK].name = "DecodeDPDK";
73 }
74 
75 /**
76  * \brief this function prints an error message and exits.
77  */
78 TmEcode NoDPDKSupportExit(ThreadVars *tv, const void *initdata, void **data)
79 {
80  FatalError("Error creating thread %s: you do not have "
81  "support for DPDK enabled, on Linux host please recompile "
82  "with --enable-dpdk",
83  tv->name);
84 }
85 
86 #else /* We have DPDK support */
87 
88 #include "util-dpdk.h"
89 #include "util-dpdk-i40e.h"
90 #include <numa.h>
91 
92 #define BURST_SIZE 32
93 static struct timeval machine_start_time = { 0, 0 };
94 
95 /**
96  * \brief Structure to hold thread specific variables.
97  */
98 typedef struct DPDKThreadVars_ {
99  /* counters */
100  uint64_t pkts;
101  ThreadVars *tv;
102  TmSlot *slot;
103  LiveDevice *livedev;
104  ChecksumValidationMode checksum_mode;
105  /* references to packet and drop counters */
106  uint16_t capture_dpdk_packets;
107  uint16_t capture_dpdk_rx_errs;
108  uint16_t capture_dpdk_imissed;
109  uint16_t capture_dpdk_rx_no_mbufs;
110  uint16_t capture_dpdk_ierrors;
111  uint16_t capture_dpdk_tx_errs;
112  unsigned int flags;
113  int threads;
114  /* for IPS */
115  DpdkCopyModeEnum copy_mode;
116  uint16_t out_port_id;
117  /* Entry in the peers_list */
118 
119  uint64_t bytes;
120  uint64_t accepted;
121  uint64_t dropped;
122  uint16_t port_id;
123  uint16_t queue_id;
124  struct rte_mempool *pkt_mempool;
125  struct rte_mbuf *received_mbufs[BURST_SIZE];
126 } DPDKThreadVars;
127 
128 static TmEcode ReceiveDPDKThreadInit(ThreadVars *, const void *, void **);
129 static void ReceiveDPDKThreadExitStats(ThreadVars *, void *);
130 static TmEcode ReceiveDPDKThreadDeinit(ThreadVars *, void *);
131 static TmEcode ReceiveDPDKLoop(ThreadVars *tv, void *data, void *slot);
132 
133 static TmEcode DecodeDPDKThreadInit(ThreadVars *, const void *, void **);
134 static TmEcode DecodeDPDKThreadDeinit(ThreadVars *tv, void *data);
135 static TmEcode DecodeDPDK(ThreadVars *, Packet *, void *);
136 
137 static uint64_t CyclesToMicroseconds(uint64_t cycles);
138 static uint64_t CyclesToSeconds(uint64_t cycles);
139 static void DPDKFreeMbufArray(struct rte_mbuf **mbuf_array, uint16_t mbuf_cnt, uint16_t offset);
140 static uint64_t DPDKGetSeconds(void);
141 
142 static void DPDKFreeMbufArray(struct rte_mbuf **mbuf_array, uint16_t mbuf_cnt, uint16_t offset)
143 {
144  for (int i = offset; i < mbuf_cnt; i++) {
145  rte_pktmbuf_free(mbuf_array[i]);
146  }
147 }
148 
149 static uint64_t CyclesToMicroseconds(const uint64_t cycles)
150 {
151  const uint64_t ticks_per_us = rte_get_tsc_hz() / 1000000;
152  return cycles / ticks_per_us;
153 }
154 
155 static uint64_t CyclesToSeconds(const uint64_t cycles)
156 {
157  const uint64_t ticks_per_s = rte_get_tsc_hz();
158  return cycles / ticks_per_s;
159 }
160 
161 static void CyclesAddToTimeval(
162  const uint64_t cycles, struct timeval *orig_tv, struct timeval *new_tv)
163 {
164  uint64_t usec = CyclesToMicroseconds(cycles) + orig_tv->tv_usec;
165  new_tv->tv_sec = orig_tv->tv_sec + usec / 1000000;
166  new_tv->tv_usec = (usec % 1000000);
167 }
168 
170 {
171  gettimeofday(&machine_start_time, NULL);
172  machine_start_time.tv_sec -= DPDKGetSeconds();
173 }
174 
175 /**
176  * Initializes real_tv to the correct real time. Adds TSC counter value to the timeval of
177  * the machine start
178  * @param machine_start_tv - timestamp when the machine was started
179  * @param real_tv
180  */
181 static SCTime_t DPDKSetTimevalReal(struct timeval *machine_start_tv)
182 {
183  struct timeval real_tv;
184  CyclesAddToTimeval(rte_get_tsc_cycles(), machine_start_tv, &real_tv);
185  return SCTIME_FROM_TIMEVAL(&real_tv);
186 }
187 
188 /* get number of seconds from the reset of TSC counter (typically from the machine start) */
189 static uint64_t DPDKGetSeconds(void)
190 {
191  return CyclesToSeconds(rte_get_tsc_cycles());
192 }
193 
194 static void DevicePostStartPMDSpecificActions(DPDKThreadVars *ptv, const char *driver_name)
195 {
196  // The PMD Driver i40e has a special way to set the RSS, it can be set via rte_flow rules
197  // and only after the start of the port
198  if (strcmp(driver_name, "net_i40e") == 0)
199  i40eDeviceSetRSS(ptv->port_id, ptv->threads);
200 }
201 
202 static void DevicePreStopPMDSpecificActions(DPDKThreadVars *ptv, const char *driver_name)
203 {
204  int retval;
205 
206  if (strcmp(driver_name, "net_i40e") == 0) {
207  // Flush the RSS rules that have been inserted in the post start section
208  struct rte_flow_error flush_error = { 0 };
209  retval = rte_flow_flush(ptv->port_id, &flush_error);
210  if (retval != 0) {
211  SCLogError("Unable to flush rte_flow rules: %s Flush error msg: %s",
212  rte_strerror(-retval), flush_error.message);
213  }
214  }
215 }
216 
217 /**
218  * Attempts to retrieve NUMA node id on which the caller runs
219  * @return NUMA id on success, -1 otherwise
220  */
221 static int GetNumaNode(void)
222 {
223  int cpu = 0;
224  int node = -1;
225 
226 #if defined(__linux__)
227  cpu = sched_getcpu();
228  node = numa_node_of_cpu(cpu);
229 #else
230  SCLogWarning("NUMA node retrieval is not supported on this OS.");
231 #endif
232 
233  return node;
234 }
235 
236 /**
237  * \brief Registration Function for ReceiveDPDK.
238  * \todo Unit tests are needed for this module.
239  */
241 {
242  tmm_modules[TMM_RECEIVEDPDK].name = "ReceiveDPDK";
243  tmm_modules[TMM_RECEIVEDPDK].ThreadInit = ReceiveDPDKThreadInit;
245  tmm_modules[TMM_RECEIVEDPDK].PktAcqLoop = ReceiveDPDKLoop;
247  tmm_modules[TMM_RECEIVEDPDK].ThreadExitPrintStats = ReceiveDPDKThreadExitStats;
248  tmm_modules[TMM_RECEIVEDPDK].ThreadDeinit = ReceiveDPDKThreadDeinit;
251 }
252 
253 /**
254  * \brief Registration Function for DecodeDPDK.
255  * \todo Unit tests are needed for this module.
256  */
258 {
259  tmm_modules[TMM_DECODEDPDK].name = "DecodeDPDK";
260  tmm_modules[TMM_DECODEDPDK].ThreadInit = DecodeDPDKThreadInit;
261  tmm_modules[TMM_DECODEDPDK].Func = DecodeDPDK;
263  tmm_modules[TMM_DECODEDPDK].ThreadDeinit = DecodeDPDKThreadDeinit;
266 }
267 
268 static inline void DPDKDumpCounters(DPDKThreadVars *ptv)
269 {
270  struct rte_eth_stats eth_stats;
271  int retval = rte_eth_stats_get(ptv->port_id, &eth_stats);
272  if (unlikely(retval != 0)) {
273  SCLogError("Failed to get stats for port id %d: %s", ptv->port_id, rte_strerror(-retval));
274  return;
275  }
276 
277  /* Some NICs (e.g. Intel) do not support queue statistics and the drops can be fetched only on
278  * the port level. Therefore setting it to the first worker to have at least continuous update
279  * on the dropped packets. */
280  if (ptv->queue_id == 0) {
281  StatsSetUI64(ptv->tv, ptv->capture_dpdk_packets,
282  ptv->pkts + eth_stats.imissed + eth_stats.ierrors + eth_stats.rx_nombuf);
283  SC_ATOMIC_SET(ptv->livedev->pkts,
284  eth_stats.ipackets + eth_stats.imissed + eth_stats.ierrors + eth_stats.rx_nombuf);
285  StatsSetUI64(ptv->tv, ptv->capture_dpdk_rx_errs,
286  eth_stats.imissed + eth_stats.ierrors + eth_stats.rx_nombuf);
287  StatsSetUI64(ptv->tv, ptv->capture_dpdk_imissed, eth_stats.imissed);
288  StatsSetUI64(ptv->tv, ptv->capture_dpdk_rx_no_mbufs, eth_stats.rx_nombuf);
289  StatsSetUI64(ptv->tv, ptv->capture_dpdk_ierrors, eth_stats.ierrors);
290  StatsSetUI64(ptv->tv, ptv->capture_dpdk_tx_errs, eth_stats.oerrors);
292  ptv->livedev->drop, eth_stats.imissed + eth_stats.ierrors + eth_stats.rx_nombuf);
293  } else {
294  StatsSetUI64(ptv->tv, ptv->capture_dpdk_packets, ptv->pkts);
295  }
296 }
297 
298 static void DPDKReleasePacket(Packet *p)
299 {
300  int retval;
301  /* Need to be in copy mode and need to detect early release
302  where Ethernet header could not be set (and pseudo packet)
303  When enabling promiscuous mode on Intel cards, 2 ICMPv6 packets are generated.
304  These get into the infinite cycle between the NIC and the switch in some cases */
305  if ((p->dpdk_v.copy_mode == DPDK_COPY_MODE_TAP ||
306  (p->dpdk_v.copy_mode == DPDK_COPY_MODE_IPS && !PacketCheckAction(p, ACTION_DROP)))
307 #if defined(RTE_LIBRTE_I40E_PMD) || defined(RTE_LIBRTE_IXGBE_PMD) || defined(RTE_LIBRTE_ICE_PMD)
308  && !(PKT_IS_ICMPV6(p) && p->icmpv6h->type == 143)
309 #endif
310  ) {
312  retval =
313  rte_eth_tx_burst(p->dpdk_v.out_port_id, p->dpdk_v.out_queue_id, &p->dpdk_v.mbuf, 1);
314  // rte_eth_tx_burst can return only 0 (failure) or 1 (success) because we are only
315  // transmitting burst of size 1 and the function rte_eth_tx_burst returns number of
316  // successfully sent packets.
317  if (unlikely(retval < 1)) {
318  // sometimes a repeated transmit can help to send out the packet
319  rte_delay_us(DPDK_BURST_TX_WAIT_US);
320  retval = rte_eth_tx_burst(
321  p->dpdk_v.out_port_id, p->dpdk_v.out_queue_id, &p->dpdk_v.mbuf, 1);
322  if (unlikely(retval < 1)) {
323  SCLogDebug("Unable to transmit the packet on port %u queue %u",
324  p->dpdk_v.out_port_id, p->dpdk_v.out_queue_id);
325  rte_pktmbuf_free(p->dpdk_v.mbuf);
326  p->dpdk_v.mbuf = NULL;
327  }
328  }
329  } else {
330  rte_pktmbuf_free(p->dpdk_v.mbuf);
331  p->dpdk_v.mbuf = NULL;
332  }
333 
335 }
336 
337 /**
338  * \brief Main DPDK reading Loop function
339  */
340 static TmEcode ReceiveDPDKLoop(ThreadVars *tv, void *data, void *slot)
341 {
342  SCEnter();
343  Packet *p;
344  uint16_t nb_rx;
345  time_t last_dump = 0;
346  time_t current_time;
347 
348  DPDKThreadVars *ptv = (DPDKThreadVars *)data;
349  TmSlot *s = (TmSlot *)slot;
350 
351  ptv->slot = s->slot_next;
352 
353  // Indicate that the thread is actually running its application level code (i.e., it can poll
354  // packets)
356 
357  PacketPoolWait();
358  while (1) {
359  if (unlikely(suricata_ctl_flags != 0)) {
360  SCLogDebug("Stopping Suricata!");
361  DPDKDumpCounters(ptv);
362  break;
363  }
364 
365  nb_rx = rte_eth_rx_burst(ptv->port_id, ptv->queue_id, ptv->received_mbufs, BURST_SIZE);
366  if (unlikely(nb_rx == 0)) {
367  continue;
368  }
369 
370  ptv->pkts += (uint64_t)nb_rx;
371  for (uint16_t i = 0; i < nb_rx; i++) {
373  if (unlikely(p == NULL)) {
374  continue;
375  }
378  if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
380  }
381 
382  p->ts = DPDKSetTimevalReal(&machine_start_time);
383  p->dpdk_v.mbuf = ptv->received_mbufs[i];
384  p->ReleasePacket = DPDKReleasePacket;
385  p->dpdk_v.copy_mode = ptv->copy_mode;
386  p->dpdk_v.out_port_id = ptv->out_port_id;
387  p->dpdk_v.out_queue_id = ptv->queue_id;
388  p->livedev = ptv->livedev;
389 
390  if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
392  } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_OFFLOAD) {
393  uint64_t ol_flags = ptv->received_mbufs[i]->ol_flags;
394  if ((ol_flags & RTE_MBUF_F_RX_IP_CKSUM_MASK) == RTE_MBUF_F_RX_IP_CKSUM_GOOD &&
395  (ol_flags & RTE_MBUF_F_RX_L4_CKSUM_MASK) == RTE_MBUF_F_RX_L4_CKSUM_GOOD) {
396  SCLogDebug("HW detected GOOD IP and L4 chsum, ignoring validation");
398  } else {
399  if ((ol_flags & RTE_MBUF_F_RX_IP_CKSUM_MASK) == RTE_MBUF_F_RX_IP_CKSUM_BAD) {
400  SCLogDebug("HW detected BAD IP checksum");
401  // chsum recalc will not be triggered but rule keyword check will be
402  p->level3_comp_csum = 0;
403  }
404  if ((ol_flags & RTE_MBUF_F_RX_L4_CKSUM_MASK) == RTE_MBUF_F_RX_L4_CKSUM_BAD) {
405  SCLogDebug("HW detected BAD L4 chsum");
406  p->level4_comp_csum = 0;
407  }
408  }
409  }
410 
411  PacketSetData(p, rte_pktmbuf_mtod(p->dpdk_v.mbuf, uint8_t *),
412  rte_pktmbuf_pkt_len(p->dpdk_v.mbuf));
413  if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
414  TmqhOutputPacketpool(ptv->tv, p);
415  DPDKFreeMbufArray(ptv->received_mbufs, nb_rx - i - 1, i + 1);
416  SCReturnInt(EXIT_FAILURE);
417  }
418  }
419 
420  /* Trigger one dump of stats every second */
421  current_time = DPDKGetSeconds();
422  if (current_time != last_dump) {
423  DPDKDumpCounters(ptv);
424  last_dump = current_time;
425  }
427  }
428 
430 }
431 
432 /**
433  * \brief Init function for ReceiveDPDK.
434  *
435  * \param tv pointer to ThreadVars
436  * \param initdata pointer to the interface passed from the user
437  * \param data pointer gets populated with DPDKThreadVars
438  *
439  */
440 static TmEcode ReceiveDPDKThreadInit(ThreadVars *tv, const void *initdata, void **data)
441 {
442  SCEnter();
443  int retval, thread_numa;
444  DPDKThreadVars *ptv = NULL;
445  DPDKIfaceConfig *dpdk_config = (DPDKIfaceConfig *)initdata;
446 
447  if (initdata == NULL) {
448  SCLogError("DPDK configuration is NULL in thread initialization");
449  goto fail;
450  }
451 
452  ptv = SCCalloc(1, sizeof(DPDKThreadVars));
453  if (unlikely(ptv == NULL)) {
454  SCLogError("Unable to allocate memory");
455  goto fail;
456  }
457 
458  ptv->tv = tv;
459  ptv->pkts = 0;
460  ptv->bytes = 0;
461  ptv->livedev = LiveGetDevice(dpdk_config->iface);
462 
463  ptv->capture_dpdk_packets = StatsRegisterCounter("capture.packets", ptv->tv);
464  ptv->capture_dpdk_rx_errs = StatsRegisterCounter("capture.rx_errors", ptv->tv);
465  ptv->capture_dpdk_tx_errs = StatsRegisterCounter("capture.tx_errors", ptv->tv);
466  ptv->capture_dpdk_imissed = StatsRegisterCounter("capture.dpdk.imissed", ptv->tv);
467  ptv->capture_dpdk_rx_no_mbufs = StatsRegisterCounter("capture.dpdk.no_mbufs", ptv->tv);
468  ptv->capture_dpdk_ierrors = StatsRegisterCounter("capture.dpdk.ierrors", ptv->tv);
469 
470  ptv->copy_mode = dpdk_config->copy_mode;
471  ptv->checksum_mode = dpdk_config->checksum_mode;
472 
473  ptv->threads = dpdk_config->threads;
474  ptv->port_id = dpdk_config->port_id;
475  ptv->out_port_id = dpdk_config->out_port_id;
476  // pass the pointer to the mempool and then forget about it. Mempool is freed in thread deinit.
477  ptv->pkt_mempool = dpdk_config->pkt_mempool;
478  dpdk_config->pkt_mempool = NULL;
479 
480  thread_numa = GetNumaNode();
481  if (thread_numa >= 0 && thread_numa != rte_eth_dev_socket_id(ptv->port_id)) {
482  SC_ATOMIC_ADD(dpdk_config->inconsitent_numa_cnt, 1);
483  SCLogPerf("%s: NIC is on NUMA %d, thread on NUMA %d", dpdk_config->iface,
484  rte_eth_dev_socket_id(ptv->port_id), thread_numa);
485  }
486 
487  uint16_t queue_id = SC_ATOMIC_ADD(dpdk_config->queue_id, 1);
488  ptv->queue_id = queue_id;
489 
490  // the last thread starts the device
491  if (queue_id == dpdk_config->threads - 1) {
492  retval = rte_eth_dev_start(ptv->port_id);
493  if (retval < 0) {
494  SCLogError("Error (%s) during device startup of %s", rte_strerror(-retval),
495  dpdk_config->iface);
496  goto fail;
497  }
498 
499  struct rte_eth_dev_info dev_info;
500  retval = rte_eth_dev_info_get(ptv->port_id, &dev_info);
501  if (retval != 0) {
502  SCLogError("Error (%s) when getting device info of %s", rte_strerror(-retval),
503  dpdk_config->iface);
504  goto fail;
505  }
506 
507  // some PMDs requires additional actions only after the device has started
508  DevicePostStartPMDSpecificActions(ptv, dev_info.driver_name);
509 
510  uint16_t inconsist_numa_cnt = SC_ATOMIC_GET(dpdk_config->inconsitent_numa_cnt);
511  if (inconsist_numa_cnt > 0) {
512  SCLogWarning("%s: NIC is on NUMA %d, %u threads on different NUMA node(s)",
513  dpdk_config->iface, rte_eth_dev_socket_id(ptv->port_id), inconsist_numa_cnt);
514  }
515  }
516 
517  *data = (void *)ptv;
518  dpdk_config->DerefFunc(dpdk_config);
520 
521 fail:
522  if (dpdk_config != NULL)
523  dpdk_config->DerefFunc(dpdk_config);
524  if (ptv != NULL)
525  SCFree(ptv);
527 }
528 
529 static void PrintDPDKPortXstats(uint32_t port_id, const char *port_name)
530 {
531  struct rte_eth_xstat *xstats;
532  struct rte_eth_xstat_name *xstats_names;
533 
534  int32_t len = rte_eth_xstats_get(port_id, NULL, 0);
535  if (len < 0)
536  FatalError("Error (%s) getting count of rte_eth_xstats failed on port %s",
537  rte_strerror(-len), port_name);
538 
539  xstats = SCCalloc(len, sizeof(*xstats));
540  if (xstats == NULL)
541  FatalError("Failed to allocate memory for the rte_eth_xstat structure");
542 
543  int32_t ret = rte_eth_xstats_get(port_id, xstats, len);
544  if (ret < 0 || ret > len) {
545  SCFree(xstats);
546  FatalError("Error (%s) getting rte_eth_xstats failed on port %s", rte_strerror(-ret),
547  port_name);
548  }
549  xstats_names = SCCalloc(len, sizeof(*xstats_names));
550  if (xstats_names == NULL) {
551  SCFree(xstats);
552  FatalError("Failed to allocate memory for the rte_eth_xstat_name array");
553  }
554  ret = rte_eth_xstats_get_names(port_id, xstats_names, len);
555  if (ret < 0 || ret > len) {
556  SCFree(xstats);
557  SCFree(xstats_names);
558  FatalError("Error (%s) getting names of rte_eth_xstats failed on port %s",
559  rte_strerror(-ret), port_name);
560  }
561  for (int32_t i = 0; i < len; i++) {
562  if (xstats[i].value > 0)
563  SCLogPerf("Port %u (%s) - %s: %" PRIu64, port_id, port_name, xstats_names[i].name,
564  xstats[i].value);
565  }
566 
567  SCFree(xstats);
568  SCFree(xstats_names);
569 }
570 
571 /**
572  * \brief This function prints stats to the screen at exit.
573  * \param tv pointer to ThreadVars
574  * \param data pointer that gets cast into DPDKThreadVars for ptv
575  */
576 static void ReceiveDPDKThreadExitStats(ThreadVars *tv, void *data)
577 {
578  SCEnter();
579  int retval;
580  DPDKThreadVars *ptv = (DPDKThreadVars *)data;
581 
582  if (ptv->queue_id == 0) {
583  struct rte_eth_stats eth_stats;
584  char port_name[RTE_ETH_NAME_MAX_LEN];
585 
586  retval = rte_eth_dev_get_name_by_port(ptv->port_id, port_name);
587  if (unlikely(retval != 0)) {
588  SCLogError("Failed to convert port id %d to the interface name: %s", ptv->port_id,
589  strerror(-retval));
590  SCReturn;
591  }
592 
593  PrintDPDKPortXstats(ptv->port_id, port_name);
594 
595  retval = rte_eth_stats_get(ptv->port_id, &eth_stats);
596  if (unlikely(retval != 0)) {
597  SCLogError("Failed to get stats for interface %s: %s", port_name, strerror(-retval));
598  SCReturn;
599  }
600  SCLogPerf("Total RX stats of %s: packets %" PRIu64 " bytes: %" PRIu64 " missed: %" PRIu64
601  " errors: %" PRIu64 " nombufs: %" PRIu64,
602  port_name, eth_stats.ipackets, eth_stats.ibytes, eth_stats.imissed,
603  eth_stats.ierrors, eth_stats.rx_nombuf);
604  if (ptv->copy_mode == DPDK_COPY_MODE_TAP || ptv->copy_mode == DPDK_COPY_MODE_IPS)
605  SCLogPerf("Total TX stats of %s: packets %" PRIu64 " bytes: %" PRIu64
606  " errors: %" PRIu64,
607  port_name, eth_stats.opackets, eth_stats.obytes, eth_stats.oerrors);
608  }
609 
610  DPDKDumpCounters(ptv);
611  SCLogPerf("(%s) received packets %" PRIu64, tv->name, ptv->pkts);
612 }
613 
614 /**
615  * \brief DeInit function closes dpdk at exit.
616  * \param tv pointer to ThreadVars
617  * \param data pointer that gets cast into DPDKThreadVars for ptv
618  */
619 static TmEcode ReceiveDPDKThreadDeinit(ThreadVars *tv, void *data)
620 {
621  SCEnter();
622  DPDKThreadVars *ptv = (DPDKThreadVars *)data;
623 
624  int retval;
625  if (ptv->queue_id == 0) {
626  struct rte_eth_dev_info dev_info;
627  char iface[RTE_ETH_NAME_MAX_LEN];
628  retval = rte_eth_dev_get_name_by_port(ptv->port_id, iface);
629  if (retval != 0) {
630  SCLogError("Error (err=%d) when getting device name (port %d)", retval, ptv->port_id);
632  }
633  retval = rte_eth_dev_info_get(ptv->port_id, &dev_info);
634  if (retval != 0) {
635  SCLogError("Error (err=%d) during getting device info (port %s)", retval, iface);
637  }
638 
639  DevicePreStopPMDSpecificActions(ptv, dev_info.driver_name);
640  }
641 
642  rte_eth_dev_stop(ptv->port_id);
643  if (ptv->copy_mode == DPDK_COPY_MODE_TAP || ptv->copy_mode == DPDK_COPY_MODE_IPS) {
644  rte_eth_dev_stop(ptv->out_port_id);
645  }
646 
647  if (ptv->queue_id == 0 && ptv->pkt_mempool != NULL) {
648  rte_mempool_free(ptv->pkt_mempool);
649  ptv->pkt_mempool = NULL;
650  }
651 
652  SCFree(ptv);
654 }
655 
656 /**
657  * \brief This function passes off to link type decoders.
658  *
659  * DecodeDPDK decodes packets from DPDK and passes
660  * them off to the proper link type decoder.
661  *
662  * \param t pointer to ThreadVars
663  * \param p pointer to the current packet
664  * \param data pointer that gets cast into DPDKThreadVars for ptv
665  */
666 static TmEcode DecodeDPDK(ThreadVars *tv, Packet *p, void *data)
667 {
668  SCEnter();
670 
672 
673  /* update counters */
675 
676  /* If suri has set vlan during reading, we increase vlan counter */
677  if (p->vlan_idx) {
679  }
680 
681  /* call the decoder */
682  DecodeLinkLayer(tv, dtv, p->datalink, p, GET_PKT_DATA(p), GET_PKT_LEN(p));
683 
685 
687 }
688 
689 static TmEcode DecodeDPDKThreadInit(ThreadVars *tv, const void *initdata, void **data)
690 {
691  SCEnter();
692  DecodeThreadVars *dtv = NULL;
693 
695 
696  if (dtv == NULL)
698 
700 
701  *data = (void *)dtv;
702 
704 }
705 
706 static TmEcode DecodeDPDKThreadDeinit(ThreadVars *tv, void *data)
707 {
708  SCEnter();
709  if (data != NULL)
710  DecodeThreadVarsFree(tv, data);
712 }
713 
714 #endif /* HAVE_DPDK */
715 /* eof */
716 /**
717  * @}
718  */
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:67
PacketCheckAction
bool PacketCheckAction(const Packet *p, const uint8_t a)
Definition: packet.c:48
tm-threads.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
TMM_RECEIVEDPDK
@ TMM_RECEIVEDPDK
Definition: tm-threads-common.h:58
ICMPV6Hdr_::type
uint8_t type
Definition: decode-icmpv6.h:145
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:167
CHECKSUM_VALIDATION_OFFLOAD
@ CHECKSUM_VALIDATION_OFFLOAD
Definition: decode.h:50
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
DPDKSetTimevalOfMachineStart
void DPDKSetTimevalOfMachineStart(void)
ThreadVars_::name
char name[16]
Definition: threadvars.h:64
PacketFreeOrRelease
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
Definition: decode.c:191
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1059
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:387
DPDK_COPY_MODE_IPS
@ DPDK_COPY_MODE_IPS
Definition: source-dpdk.h:33
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:99
TMM_DECODEDPDK
@ TMM_DECODEDPDK
Definition: tm-threads-common.h:59
action-globals.h
Packet_::flags
uint32_t flags
Definition: decode.h:463
DpdkCopyModeEnum
DpdkCopyModeEnum
Definition: source-dpdk.h:33
threads.h
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:456
LiveDevice_
Definition: util-device.h:39
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:333
StatsSetUI64
void StatsSetUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Sets a value of type double to the local counter.
Definition: counters.c:210
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:54
NoDPDKSupportExit
TmEcode NoDPDKSupportExit(ThreadVars *, const void *, void **)
this function prints an error message and exits.
Definition: source-dpdk.c:78
util-privs.h
StatsSyncCountersIfSignalled
#define StatsSyncCountersIfSignalled(tv)
Definition: counters.h:140
CHECKSUM_VALIDATION_DISABLE
@ CHECKSUM_VALIDATION_DISABLE
Definition: decode.h:45
PacketDecodeFinalize
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition: decode.c:147
DPDKIfaceConfig_
Definition: source-dpdk.h:45
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:356
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:85
tmqh-packetpool.h
TmModule_::PktAcqLoop
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-modules.h:54
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:84
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:49
Packet_::datalink
int datalink
Definition: decode.h:607
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1062
DecodeRegisterPerfCounters
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition: decode.c:526
Packet_::level3_comp_csum
int32_t level3_comp_csum
Definition: decode.h:527
TmModuleReceiveDPDKRegister
void TmModuleReceiveDPDKRegister(void)
Definition: source-dpdk.c:50
decode.h
Packet_::level4_comp_csum
int32_t level4_comp_csum
Definition: decode.h:529
PKT_SRC_WIRE
@ PKT_SRC_WIRE
Definition: decode.h:54
TmModule_::PktAcqBreakLoop
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition: tm-modules.h:57
Packet_::ts
SCTime_t ts
Definition: decode.h:471
LiveGetDevice
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
Definition: util-device.c:242
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:219
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
SCTIME_FROM_TIMEVAL
#define SCTIME_FROM_TIMEVAL(tv)
Definition: util-time.h:65
TmModule_::Func
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition: tm-modules.h:52
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
PKT_IS_ICMPV6
#define PKT_IS_ICMPV6(p)
Definition: decode.h:250
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:289
PacketPoolWait
void PacketPoolWait(void)
Definition: tmqh-packetpool.c:69
SCReturn
#define SCReturn
Definition: util-debug.h:273
Packet_::icmpv6h
ICMPV6Hdr * icmpv6h
Definition: decode.h:563
Packet_
Definition: decode.h:428
TM_FLAG_DECODE_TM
#define TM_FLAG_DECODE_TM
Definition: tm-modules.h:32
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:33
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:218
TmSlot_
Definition: tm-threads.h:53
PKT_IGNORE_CHECKSUM
#define PKT_IGNORE_CHECKSUM
Definition: decode.h:1019
SCTime_t
Definition: util-time.h:40
Packet_::livedev
struct LiveDevice_ * livedev
Definition: decode.h:586
DPDK_BURST_TX_WAIT_US
#define DPDK_BURST_TX_WAIT_US
Definition: source-dpdk.h:35
TmEcode
TmEcode
Definition: tm-threads-common.h:83
TmModule_::name
const char * name
Definition: tm-modules.h:44
DecodeThreadVars_::counter_vlan
uint16_t counter_vlan
Definition: decode.h:697
runmodes.h
TM_FLAG_RECEIVE_TM
#define TM_FLAG_RECEIVE_TM
Definition: tm-modules.h:31
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
Packet_::ReleasePacket
void(* ReleasePacket)(struct Packet_ *)
Definition: decode.h:515
util-dpdk.h
flags
uint8_t flags
Definition: decode-gre.h:0
DecodeThreadVarsFree
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition: decode.c:708
source-dpdk.h
ChecksumValidationMode
ChecksumValidationMode
Definition: decode.h:44
suricata-common.h
packet.h
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:230
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:47
FatalError
#define FatalError(...)
Definition: util-debug.h:502
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
TmModule_::ThreadExitPrintStats
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-modules.h:48
threadvars.h
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:664
DecodeThreadVarsAlloc
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition: decode.c:689
PacketSetData
int PacketSetData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Set data for Packet and set length when zero copy is used.
Definition: decode.c:728
util-dpdk-i40e.h
suricata.h
TmSlot_::slot_next
struct TmSlot_ * slot_next
Definition: tm-threads.h:62
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:376
TmModuleDecodeDPDKRegister
void TmModuleDecodeDPDKRegister(void)
Registration Function for DecodeDPDK.
Definition: source-dpdk.c:64
StatsRegisterCounter
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition: counters.c:955
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
PacketGetFromQueueOrAlloc
Packet * PacketGetFromQueueOrAlloc(void)
Get a packet. We try to get a packet from the packetpool first, but if that is empty we alloc a packe...
Definition: decode.c:208
SC_CAP_NET_RAW
#define SC_CAP_NET_RAW
Definition: util-privs.h:32
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:70
DPDK_COPY_MODE_TAP
@ DPDK_COPY_MODE_TAP
Definition: source-dpdk.h:33
DecodeUpdatePacketCounters
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition: decode.c:655
LINKTYPE_ETHERNET
#define LINKTYPE_ETHERNET
Definition: decode.h:972
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:164