]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
dpdk: improve DPDK thread handling
authorLukas Sismis <lsismis@oisf.net>
Mon, 19 Jun 2023 15:23:36 +0000 (17:23 +0200)
committerVictor Julien <vjulien@oisf.net>
Mon, 10 Jul 2023 07:27:02 +0000 (09:27 +0200)
Ticket: #6106

src/runmode-dpdk.c
src/source-dpdk.c
src/util-affinity.c
src/util-affinity.h

index 687d88871a3db0ee044f759e671811064bc37437..da0ff052eda48c432b5eefd62c9c1b15b83ad1ec 100644 (file)
@@ -48,6 +48,7 @@
 #include "util-time.h"
 #include "util-conf.h"
 #include "suricata.h"
+#include "util-affinity.h"
 
 #ifdef HAVE_DPDK
 
@@ -355,8 +356,40 @@ static void ConfigSetIface(DPDKIfaceConfig *iconf, const char *entry_str)
 static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str)
 {
     SCEnter();
-    const char *active_runmode = RunmodeGetActive();
+    static int32_t remaining_auto_cpus = -1;
+    static uint32_t total_cpus = 0;
+    if (!threading_set_cpu_affinity) {
+        SCLogError("DPDK runmode requires configured thread affinity");
+        SCReturnInt(-EINVAL);
+    }
 
+    ThreadsAffinityType *wtaf = GetAffinityTypeFromName("worker-cpu-set");
+    if (wtaf == NULL) {
+        SCLogError("Specify worker-cpu-set list in the threading section");
+        SCReturnInt(-EINVAL);
+    }
+    ThreadsAffinityType *mtaf = GetAffinityTypeFromName("management-cpu-set");
+    if (mtaf == NULL) {
+        SCLogError("Specify management-cpu-set list in the threading section");
+        SCReturnInt(-EINVAL);
+    }
+    uint32_t sched_cpus = UtilAffinityGetAffinedCPUNum(wtaf);
+    if (sched_cpus == UtilCpuGetNumProcessorsOnline()) {
+        SCLogWarning(
+                "\"all\" specified in worker CPU cores affinity, excluding management threads");
+        UtilAffinityCpusExclude(wtaf, mtaf);
+        sched_cpus = UtilAffinityGetAffinedCPUNum(wtaf);
+    }
+
+    if (sched_cpus == 0) {
+        SCLogError("No worker CPU cores with configured affinity were configured");
+        SCReturnInt(-EINVAL);
+    } else if (UtilAffinityCpusOverlap(wtaf, mtaf) != 0) {
+        SCLogWarning("Worker threads should not overlap with management threads in the CPU core "
+                     "affinity configuration");
+    }
+
+    const char *active_runmode = RunmodeGetActive();
     if (active_runmode && !strcmp("single", active_runmode)) {
         iconf->threads = 1;
         SCReturnInt(0);
@@ -368,8 +401,23 @@ static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str)
     }
 
     if (strcmp(entry_str, "auto") == 0) {
-        iconf->threads = (int)UtilCpuGetNumProcessorsOnline();
-        SCLogPerf("%u cores, so using %u threads", iconf->threads, iconf->threads);
+        iconf->threads = (uint16_t)sched_cpus / LiveGetDeviceCount();
+        if (iconf->threads == 0) {
+            SCLogError("Not enough worker CPU cores with affinity were configured");
+            SCReturnInt(-ERANGE);
+        }
+
+        if (remaining_auto_cpus > 0) {
+            iconf->threads++;
+            remaining_auto_cpus--;
+        } else if (remaining_auto_cpus == -1) {
+            remaining_auto_cpus = (int32_t)sched_cpus % LiveGetDeviceCount();
+            if (remaining_auto_cpus > 0) {
+                iconf->threads++;
+                remaining_auto_cpus--;
+            }
+        }
+        SCLogPerf("%s: auto-assigned %u threads", iconf->iface, iconf->threads);
         SCReturnInt(0);
     }
 
@@ -379,8 +427,14 @@ static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str)
         SCReturnInt(-EINVAL);
     }
 
-    if (iconf->threads < 0) {
-        SCLogError("Interface %s has a negative number of threads", iconf->iface);
+    if (iconf->threads <= 0) {
+        SCLogError("%s: positive number of threads required", iconf->iface);
+        SCReturnInt(-ERANGE);
+    }
+
+    total_cpus += iconf->threads;
+    if (total_cpus > sched_cpus) {
+        SCLogError("Interfaces requested more cores than configured in the threading section");
         SCReturnInt(-ERANGE);
     }
 
index cc9dcd6f6e6206d736d7e5001e3934a691c60dc1..51b60fd40988fd9ba00235d23b2be8176e5306c2 100644 (file)
@@ -85,6 +85,7 @@ TmEcode NoDPDKSupportExit(ThreadVars *tv, const void *initdata, void **data)
 
 #else /* We have DPDK support */
 
+#include "util-affinity.h"
 #include "util-dpdk.h"
 #include "util-dpdk-i40e.h"
 #include "util-dpdk-bonding.h"
index c84de75f0011f0406e4610145bba9ab73aceacac..06256db5b8cdc02211c323e34f31bd02b5499275 100644 (file)
@@ -306,3 +306,59 @@ uint16_t AffinityGetNextCPU(ThreadsAffinityType *taf)
 #endif /* OS_WIN32 and __OpenBSD__ */
     return ncpu;
 }
+
+uint16_t UtilAffinityGetAffinedCPUNum(ThreadsAffinityType *taf)
+{
+    uint16_t ncpu = 0;
+#if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined sun
+    SCMutexLock(&taf->taf_mutex);
+    for (int i = UtilCpuGetNumProcessorsOnline(); i >= 0; i--)
+        if (CPU_ISSET(i, &taf->cpu_set))
+            ncpu++;
+    SCMutexUnlock(&taf->taf_mutex);
+#endif
+    return ncpu;
+}
+
+#ifdef HAVE_DPDK
+/**
+ * Find if CPU sets overlap
+ * \return 1 if CPUs overlap, 0 otherwise
+ */
+uint16_t UtilAffinityCpusOverlap(ThreadsAffinityType *taf1, ThreadsAffinityType *taf2)
+{
+    ThreadsAffinityType tmptaf;
+    CPU_ZERO(&tmptaf);
+    SCMutexInit(&tmptaf.taf_mutex, NULL);
+
+    cpu_set_t tmpcset;
+
+    SCMutexLock(&taf1->taf_mutex);
+    SCMutexLock(&taf2->taf_mutex);
+    CPU_AND(&tmpcset, &taf1->cpu_set, &taf2->cpu_set);
+    SCMutexUnlock(&taf2->taf_mutex);
+    SCMutexUnlock(&taf1->taf_mutex);
+
+    for (int i = UtilCpuGetNumProcessorsOnline(); i >= 0; i--)
+        if (CPU_ISSET(i, &tmpcset))
+            return 1;
+    return 0;
+}
+
+/**
+ * Function makes sure that CPUs of different types don't overlap by excluding
+ * one affinity type from the other
+ * \param mod_taf - CPU set to be modified
+ * \param static_taf - static CPU set to be used only for evaluation
+ */
+void UtilAffinityCpusExclude(ThreadsAffinityType *mod_taf, ThreadsAffinityType *static_taf)
+{
+    cpu_set_t tmpset;
+    SCMutexLock(&mod_taf->taf_mutex);
+    SCMutexLock(&static_taf->taf_mutex);
+    CPU_XOR(&tmpset, &mod_taf->cpu_set, &static_taf->cpu_set);
+    SCMutexUnlock(&static_taf->taf_mutex);
+    mod_taf->cpu_set = tmpset;
+    SCMutexUnlock(&mod_taf->taf_mutex);
+}
+#endif /* HAVE_DPDK */
index 91a6f97261a6d046b7084f3b35cd1a7e45c5bdf6..ef3c556498d92c5ef3c675646e18f0f53efbecaa 100644 (file)
@@ -87,6 +87,11 @@ void AffinitySetupLoadFromConfig(void);
 ThreadsAffinityType * GetAffinityTypeFromName(const char *name);
 
 uint16_t AffinityGetNextCPU(ThreadsAffinityType *taf);
+uint16_t UtilAffinityGetAffinedCPUNum(ThreadsAffinityType *taf);
+#ifdef HAVE_DPDK
+uint16_t UtilAffinityCpusOverlap(ThreadsAffinityType *taf1, ThreadsAffinityType *taf2);
+void UtilAffinityCpusExclude(ThreadsAffinityType *mod_taf, ThreadsAffinityType *static_taf);
+#endif /* HAVE_DPDK */
 
 void BuildCpusetWithCallback(const char *name, ConfNode *node,
                              void (*Callback)(int i, void * data),