pull/15352/merge
SamareshSingh 23 hours ago committed by GitHub
commit 20f1e06d57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1415,13 +1415,22 @@
AC_CHECK_FUNCS([bpf_xdp_query_id]) AC_CHECK_FUNCS([bpf_xdp_query_id])
]) ])
# Optional libnuma probe (used for memory affinity binding, also
# mandatory for DPDK and Napatech below). Sets HAVE_LIBNUMA and links
# -lnuma when available.
AC_CHECK_LIB(numa, numa_available, [
have_libnuma=yes
AC_DEFINE([HAVE_LIBNUMA], [1], [Define to 1 if you have libnuma.])
LIBS="${LIBS} -lnuma"
], [have_libnuma=no])
# DPDK support # DPDK support
enable_dpdk_bond_pmd="no" enable_dpdk_bond_pmd="no"
AC_ARG_ENABLE(dpdk, AC_ARG_ENABLE(dpdk,
AS_HELP_STRING([--enable-dpdk], [Enable DPDK support [default=no]]), AS_HELP_STRING([--enable-dpdk], [Enable DPDK support [default=no]]),
[enable_dpdk=$enableval],[enable_dpdk=no]) [enable_dpdk=$enableval],[enable_dpdk=no])
AS_IF([test "x$enable_dpdk" = "xyes"], [ AS_IF([test "x$enable_dpdk" = "xyes"], [
AC_CHECK_LIB(numa, numa_available,, [numa_found="no"]) if test "$have_libnuma" = "no"; then numa_found="no"; fi
if test "$numa_found" = "no"; then if test "$numa_found" = "no"; then
echo echo
echo " ERROR! libnuma not found by pkg-config, go get it" echo " ERROR! libnuma not found by pkg-config, go get it"

@ -889,6 +889,17 @@ packets to process. The detect threads running on other cores will
process more packets. This is only the case after setting the option process more packets. This is only the case after setting the option
to 'yes'. to 'yes'.
On NUMA systems where ``set-cpu-affinity`` is enabled you can also opt
into binding each thread's memory to its local NUMA node so per-flow,
per-thread and packet pool allocations stay on the same node as the
worker CPU::
set-memory-affinity: yes
This requires Suricata to be built with libnuma (already pulled in by
``--enable-dpdk`` and the Napatech build). On a single NUMA node system
the option has no effect.
*Example 7 Balancing workload* *Example 7 Balancing workload*
.. image:: suricata-yaml/balancing_workload.png .. image:: suricata-yaml/balancing_workload.png

@ -59,6 +59,7 @@
int debuglog_enabled = 0; int debuglog_enabled = 0;
bool threading_set_cpu_affinity = false; bool threading_set_cpu_affinity = false;
bool threading_set_memory_affinity = false;
uint64_t threading_set_stack_size = 0; uint64_t threading_set_stack_size = 0;
/* Runmode Global Thread Names */ /* Runmode Global Thread Names */
@ -968,6 +969,25 @@ void RunModeInitializeThreadSettings(void)
if (threading_set_cpu_affinity) { if (threading_set_cpu_affinity) {
AffinitySetupLoadFromConfig(); AffinitySetupLoadFromConfig();
} }
int memory_affinity = 0;
if ((SCConfGetBool("threading.set-memory-affinity", &memory_affinity)) == 0) {
threading_set_memory_affinity = false;
} else {
threading_set_memory_affinity = memory_affinity == 1;
}
if (threading_set_memory_affinity && !threading_set_cpu_affinity) {
SCLogWarning("threading.set-memory-affinity has no effect without "
"threading.set-cpu-affinity, ignoring");
threading_set_memory_affinity = false;
}
#ifndef HAVE_LIBNUMA
if (threading_set_memory_affinity) {
SCLogWarning("threading.set-memory-affinity requested but Suricata "
"was built without libnuma, ignoring");
threading_set_memory_affinity = false;
}
#endif
if ((SCConfGetFloat("threading.detect-thread-ratio", &threading_detect_ratio)) != 1) { if ((SCConfGetFloat("threading.detect-thread-ratio", &threading_detect_ratio)) != 1) {
if (SCConfGetNode("threading.detect-thread-ratio") != NULL) if (SCConfGetNode("threading.detect-thread-ratio") != NULL)
WarnInvalidConfEntry("threading.detect-thread-ratio", "%s", "1"); WarnInvalidConfEntry("threading.detect-thread-ratio", "%s", "1");

@ -104,6 +104,7 @@ void RunModeEnablesBypassManager(void);
int RunModeNeedsBypassManager(void); int RunModeNeedsBypassManager(void);
extern bool threading_set_cpu_affinity; extern bool threading_set_cpu_affinity;
extern bool threading_set_memory_affinity;
extern float threading_detect_ratio; extern float threading_detect_ratio;
extern uint64_t threading_set_stack_size; extern uint64_t threading_set_stack_size;

@ -48,6 +48,10 @@
#include "util-validate.h" #include "util-validate.h"
#include "source-pcap-file-helper.h" #include "source-pcap-file-helper.h"
#ifdef HAVE_LIBNUMA
#include <numa.h>
#endif
#ifdef PROFILE_LOCKING #ifdef PROFILE_LOCKING
thread_local uint64_t mutex_lock_contention; thread_local uint64_t mutex_lock_contention;
thread_local uint64_t mutex_lock_wait_ticks; thread_local uint64_t mutex_lock_wait_ticks;
@ -864,6 +868,33 @@ int TmThreadGetNbThreads(uint8_t type)
return thread_affinity[type].nb_threads; return thread_affinity[type].nb_threads;
} }
/**
* \brief Bind subsequent allocations on this thread to the local NUMA node.
*
* Must be called after the thread's CPU affinity has been pinned. Uses
* MPOL_LOCAL (via numa_set_localalloc) so allocations prefer the node of
* the running CPU but can fall back to other nodes when local memory is
* exhausted. No-op when libnuma is not compiled in or the system has a
* single NUMA node.
*/
static void SetMemoryAffinityLocal(const char *name)
{
#ifdef HAVE_LIBNUMA
if (!threading_set_memory_affinity)
return;
if (numa_available() == -1)
return;
if (numa_max_node() < 1)
return;
numa_set_localalloc();
SCLogPerf("Setting memory affinity for thread \"%s\" to local NUMA node, "
"thread id %lu",
name, SCGetThreadIdLong());
#else
(void)name;
#endif
}
/** /**
* \brief Set the thread options (cpu affinitythread). * \brief Set the thread options (cpu affinitythread).
* Priority should be already set by pthread_create. * Priority should be already set by pthread_create.
@ -877,6 +908,7 @@ TmEcode TmThreadSetupOptions(ThreadVars *tv)
"%"PRIu16", thread id %lu", tv->name, tv->cpu_affinity, "%"PRIu16", thread id %lu", tv->name, tv->cpu_affinity,
SCGetThreadIdLong()); SCGetThreadIdLong());
SetCPUAffinity(tv->cpu_affinity); SetCPUAffinity(tv->cpu_affinity);
SetMemoryAffinityLocal(tv->name);
} }
#if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined __sun #if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined __sun
@ -923,6 +955,7 @@ TmEcode TmThreadSetupOptions(ThreadVars *tv)
"thread id %lu", tv->thread_priority, "thread id %lu", tv->thread_priority,
tv->name, SCGetThreadIdLong()); tv->name, SCGetThreadIdLong());
} }
SetMemoryAffinityLocal(tv->name);
TmThreadSetPrio(tv); TmThreadSetPrio(tv);
} }
#endif #endif

@ -1939,6 +1939,12 @@ spm-algo: auto
# Suricata is multi-threaded. Here the threading can be influenced. # Suricata is multi-threaded. Here the threading can be influenced.
threading: threading:
set-cpu-affinity: no set-cpu-affinity: no
# When set-cpu-affinity is enabled, also bind thread heap allocations
# to the local NUMA node so per-flow, per-thread and packet pool memory
# stays on the same NUMA as the worker CPU. Requires libnuma at build
# time (already present when DPDK or Napatech is enabled). Has no effect
# on single-NUMA systems.
set-memory-affinity: no
autopin: no autopin: no
# Tune cpu affinity of threads. Each family of threads can be bound # Tune cpu affinity of threads. Each family of threads can be bound
# to specific CPUs. # to specific CPUs.

Loading…
Cancel
Save