summaryrefslogtreecommitdiffstats
path: root/src/source-dpdk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/source-dpdk.c')
-rw-r--r--src/source-dpdk.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/src/source-dpdk.c b/src/source-dpdk.c
index cf26af5..6a7833e 100644
--- a/src/source-dpdk.c
+++ b/src/source-dpdk.c
@@ -93,6 +93,13 @@ TmEcode NoDPDKSupportExit(ThreadVars *tv, const void *initdata, void **data)
#define BURST_SIZE 32
static struct timeval machine_start_time = { 0, 0 };
+// interrupt mode constants
+#define MIN_ZERO_POLL_COUNT 10U
+#define MIN_ZERO_POLL_COUNT_TO_SLEEP 10U
+#define MINIMUM_SLEEP_TIME_US 1U
+#define STANDARD_SLEEP_TIME_US 100U
+#define MAX_EPOLL_TIMEOUT_MS 500U
+static rte_spinlock_t intr_lock[RTE_MAX_ETHPORTS];
/**
* \brief Structure to hold thread specific variables.
@@ -104,6 +111,7 @@ typedef struct DPDKThreadVars_ {
TmSlot *slot;
LiveDevice *livedev;
ChecksumValidationMode checksum_mode;
+ bool intr_enabled;
/* references to packet and drop counters */
uint16_t capture_dpdk_packets;
uint16_t capture_dpdk_rx_errs;
@@ -142,6 +150,40 @@ static uint64_t CyclesToSeconds(uint64_t cycles);
static void DPDKFreeMbufArray(struct rte_mbuf **mbuf_array, uint16_t mbuf_cnt, uint16_t offset);
static uint64_t DPDKGetSeconds(void);
+static bool InterruptsRXEnable(uint16_t port_id, uint16_t queue_id)
+{
+ uint32_t event_data = port_id << UINT16_WIDTH | queue_id;
+ int32_t ret = rte_eth_dev_rx_intr_ctl_q(port_id, queue_id, RTE_EPOLL_PER_THREAD,
+ RTE_INTR_EVENT_ADD, (void *)((uintptr_t)event_data));
+
+ if (ret != 0) {
+ SCLogError("%s-Q%d: failed to enable interrupt mode: %s", DPDKGetPortNameByPortID(port_id),
+ queue_id, rte_strerror(-ret));
+ return false;
+ }
+ return true;
+}
+
+static inline uint32_t InterruptsSleepHeuristic(uint32_t no_pkt_polls_count)
+{
+ if (no_pkt_polls_count < MIN_ZERO_POLL_COUNT_TO_SLEEP)
+ return MINIMUM_SLEEP_TIME_US;
+
+ return STANDARD_SLEEP_TIME_US;
+}
+
+static inline void InterruptsTurnOnOff(uint16_t port_id, uint16_t queue_id, bool on)
+{
+ rte_spinlock_lock(&(intr_lock[port_id]));
+
+ if (on)
+ rte_eth_dev_rx_intr_enable(port_id, queue_id);
+ else
+ rte_eth_dev_rx_intr_disable(port_id, queue_id);
+
+ rte_spinlock_unlock(&(intr_lock[port_id]));
+}
+
static void DPDKFreeMbufArray(struct rte_mbuf **mbuf_array, uint16_t mbuf_cnt, uint16_t offset)
{
for (int i = offset; i < mbuf_cnt; i++) {
@@ -377,6 +419,11 @@ static TmEcode ReceiveDPDKLoop(ThreadVars *tv, void *data, void *slot)
rte_eth_stats_reset(ptv->port_id);
rte_eth_xstats_reset(ptv->port_id);
+
+ uint32_t pwd_zero_rx_packet_polls_count = 0;
+ if (ptv->intr_enabled && !InterruptsRXEnable(ptv->port_id, ptv->queue_id))
+ SCReturnInt(TM_ECODE_FAILED);
+
while (1) {
if (unlikely(suricata_ctl_flags != 0)) {
SCLogDebug("Stopping Suricata!");
@@ -398,7 +445,27 @@ static TmEcode ReceiveDPDKLoop(ThreadVars *tv, void *data, void *slot)
TmThreadsCaptureHandleTimeout(tv, NULL);
last_timeout_msec = msecs;
}
- continue;
+
+ if (!ptv->intr_enabled)
+ continue;
+
+ pwd_zero_rx_packet_polls_count++;
+ if (pwd_zero_rx_packet_polls_count <= MIN_ZERO_POLL_COUNT)
+ continue;
+
+ uint32_t pwd_idle_hint = InterruptsSleepHeuristic(pwd_zero_rx_packet_polls_count);
+
+ if (pwd_idle_hint < STANDARD_SLEEP_TIME_US) {
+ rte_delay_us(pwd_idle_hint);
+ } else {
+ InterruptsTurnOnOff(ptv->port_id, ptv->queue_id, true);
+ struct rte_epoll_event event;
+ rte_epoll_wait(RTE_EPOLL_PER_THREAD, &event, 1, MAX_EPOLL_TIMEOUT_MS);
+ InterruptsTurnOnOff(ptv->port_id, ptv->queue_id, false);
+ continue;
+ }
+ } else if (ptv->intr_enabled && pwd_zero_rx_packet_polls_count) {
+ pwd_zero_rx_packet_polls_count = 0;
}
ptv->pkts += (uint64_t)nb_rx;
@@ -522,6 +589,7 @@ static TmEcode ReceiveDPDKThreadInit(ThreadVars *tv, const void *initdata, void
ptv->checksum_mode = dpdk_config->checksum_mode;
ptv->threads = dpdk_config->threads;
+ ptv->intr_enabled = (dpdk_config->flags & DPDK_IRQ_MODE) ? true : false;
ptv->port_id = dpdk_config->port_id;
ptv->out_port_id = dpdk_config->out_port_id;
ptv->port_socket_id = dpdk_config->socket_id;
@@ -569,6 +637,9 @@ static TmEcode ReceiveDPDKThreadInit(ThreadVars *tv, const void *initdata, void
"%s: unable to determine NIC's NUMA node, degraded performance can be expected",
dpdk_config->iface);
}
+ if (ptv->intr_enabled) {
+ rte_spinlock_init(&intr_lock[ptv->port_id]);
+ }
}
*data = (void *)ptv;