dpdk: improve DPDK thread handling

Ticket: #6106
pull/9198/head
Lukas Sismis 2 years ago committed by Victor Julien
parent 5a3ecbde62
commit 3d54a103d0

@ -48,6 +48,7 @@
#include "util-time.h" #include "util-time.h"
#include "util-conf.h" #include "util-conf.h"
#include "suricata.h" #include "suricata.h"
#include "util-affinity.h"
#ifdef HAVE_DPDK #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) static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str)
{ {
SCEnter(); 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)) { if (active_runmode && !strcmp("single", active_runmode)) {
iconf->threads = 1; iconf->threads = 1;
SCReturnInt(0); SCReturnInt(0);
@ -368,8 +401,23 @@ static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str)
} }
if (strcmp(entry_str, "auto") == 0) { if (strcmp(entry_str, "auto") == 0) {
iconf->threads = (int)UtilCpuGetNumProcessorsOnline(); iconf->threads = (uint16_t)sched_cpus / LiveGetDeviceCount();
SCLogPerf("%u cores, so using %u threads", iconf->threads, iconf->threads); 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); SCReturnInt(0);
} }
@ -379,8 +427,14 @@ static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str)
SCReturnInt(-EINVAL); SCReturnInt(-EINVAL);
} }
if (iconf->threads < 0) { if (iconf->threads <= 0) {
SCLogError("Interface %s has a negative number of threads", iconf->iface); 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); SCReturnInt(-ERANGE);
} }

@ -85,6 +85,7 @@ TmEcode NoDPDKSupportExit(ThreadVars *tv, const void *initdata, void **data)
#else /* We have DPDK support */ #else /* We have DPDK support */
#include "util-affinity.h"
#include "util-dpdk.h" #include "util-dpdk.h"
#include "util-dpdk-i40e.h" #include "util-dpdk-i40e.h"
#include "util-dpdk-bonding.h" #include "util-dpdk-bonding.h"

@ -306,3 +306,59 @@ uint16_t AffinityGetNextCPU(ThreadsAffinityType *taf)
#endif /* OS_WIN32 and __OpenBSD__ */ #endif /* OS_WIN32 and __OpenBSD__ */
return ncpu; 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 */

@ -87,6 +87,11 @@ void AffinitySetupLoadFromConfig(void);
ThreadsAffinityType * GetAffinityTypeFromName(const char *name); ThreadsAffinityType * GetAffinityTypeFromName(const char *name);
uint16_t AffinityGetNextCPU(ThreadsAffinityType *taf); 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 BuildCpusetWithCallback(const char *name, ConfNode *node,
void (*Callback)(int i, void * data), void (*Callback)(int i, void * data),

Loading…
Cancel
Save