From: Lukas Sismis Date: Wed, 16 Aug 2023 21:51:10 +0000 (+0200) Subject: dpdk: add hugepage hint to lower the amount of reserved hugepages X-Git-Tag: suricata-7.0.2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1bcea5a992ab80cd4ae658732029ffa06ff280f3;p=thirdparty%2Fsuricata.git dpdk: add hugepage hint to lower the amount of reserved hugepages If a user allocates too many hugepages and those are largely not used then Suricata suggests that the user can lower the amount of hugepages and therefore save memory for other purposes. Ticket: #5966 --- diff --git a/configure.ac b/configure.ac index 8bb752715f..cf6b8f6252 100644 --- a/configure.ac +++ b/configure.ac @@ -137,6 +137,7 @@ AC_CHECK_HEADERS([getopt.h]) AC_CHECK_HEADERS([limits.h netdb.h netinet/in.h poll.h sched.h signal.h]) AC_CHECK_HEADERS([stdarg.h stdint.h stdio.h stdlib.h stdbool.h string.h strings.h sys/ioctl.h]) + AC_CHECK_HEADERS([math.h]) AC_CHECK_HEADERS([syslog.h sys/prctl.h sys/socket.h sys/stat.h sys/syscall.h]) AC_CHECK_HEADERS([sys/time.h time.h unistd.h sys/param.h]) AC_CHECK_HEADERS([sys/ioctl.h linux/if_ether.h linux/if_packet.h linux/filter.h]) diff --git a/src/suricata-common.h b/src/suricata-common.h index 47d578f727..fe8ec179df 100644 --- a/src/suricata-common.h +++ b/src/suricata-common.h @@ -280,6 +280,10 @@ typedef unsigned char u_char; #include #endif +#ifdef HAVE_MATH_H +#include +#endif + /* we need this to stringify the defines which are supplied at compiletime see: http://gcc.gnu.org/onlinedocs/gcc-3.4.1/cpp/Stringification.html#Stringification */ #define xstr(s) str(s) diff --git a/src/suricata.c b/src/suricata.c index d9adcaf07b..30e6490826 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -3037,6 +3037,8 @@ int SuricataMain(int argc, char **argv) PostRunStartedDetectSetup(&suricata); + DPDKEvaluateHugepages(); + SCPledge(); SuricataMainLoop(&suricata); diff --git a/src/util-dpdk.c b/src/util-dpdk.c index c9c1d73d03..089aa45674 100644 --- a/src/util-dpdk.c +++ b/src/util-dpdk.c @@ -24,6 +24,7 @@ #include "suricata.h" #include "util-dpdk.h" #include "util-debug.h" +#include "util-byte.h" void DPDKCleanupEAL(void) { @@ -65,6 +66,104 @@ void DPDKFreeDevice(LiveDevice *ldev) #endif } +static FILE *HugepagesMeminfoOpen(void) +{ + FILE *fp = fopen("/proc/meminfo", "r"); + if (fp == NULL) { + SCLogInfo("Can't analyze hugepage usage: failed to open /proc/meminfo"); + } + return fp; +} + +static void HugepagesMeminfoClose(FILE *fp) +{ + if (fp) { + fclose(fp); + } +} + +/** + * Parsing values of meminfo + * + * \param fp Opened file pointer for reading of file /proc/meminfo at beginning + * \param keyword Entry to look for e.g. "HugePages_Free:" + * \return n Value of the entry + * \return -1 On error + * + */ +static int32_t MemInfoParseValue(FILE *fp, const char *keyword) +{ + char path[256], value_str[64]; + int32_t value = -1; + + while (fscanf(fp, "%255s", path) != EOF) { + if (strcmp(path, keyword) == 0) { + if (fscanf(fp, "%63s", value_str) == EOF) { + SCLogDebug("%s: not followed by any number", keyword); + break; + } + + if (StringParseInt32(&value, 10, 23, value_str) < 0) { + SCLogDebug("Failed to convert %s from /proc/meminfo", keyword); + value = -1; + } + break; + } + } + return value; +} + +static void MemInfoEvaluateHugepages(FILE *fp) +{ + int32_t free_hugepages = MemInfoParseValue(fp, "HugePages_Free:"); + if (free_hugepages < 0) { + SCLogInfo("HugePages_Free information not found in /proc/meminfo"); + return; + } + + rewind(fp); + + int32_t total_hugepages = MemInfoParseValue(fp, "HugePages_Total:"); + if (total_hugepages < 0) { + SCLogInfo("HugePages_Total information not found in /proc/meminfo"); + return; + } else if (total_hugepages == 0) { + SCLogInfo("HugePages_Total equals to zero"); + return; + } + + float free_hugepages_ratio = (float)free_hugepages / (float)total_hugepages; + if (free_hugepages_ratio > 0.5) { + SCLogInfo("%" PRIu32 " of %" PRIu32 + " of hugepages are free - number of hugepages can be lowered to e.g. %.0lf", + free_hugepages, total_hugepages, ceil((total_hugepages - free_hugepages) * 1.15)); + } +} + +static void MemInfoWith(void (*callback)(FILE *)) +{ + FILE *fp = HugepagesMeminfoOpen(); + if (fp) { + callback(fp); + HugepagesMeminfoClose(fp); + } +} + +void DPDKEvaluateHugepages(void) +{ + if (run_mode != RUNMODE_DPDK) + return; + +#ifdef HAVE_DPDK + if (rte_eal_has_hugepages() == 0) { // hugepages disabled + SCLogPerf("Hugepages not enabled - enabling hugepages can improve performance"); + return; + } +#endif + + MemInfoWith(MemInfoEvaluateHugepages); +} + #ifdef HAVE_DPDK /** diff --git a/src/util-dpdk.h b/src/util-dpdk.h index 1fb3532f5d..a94f462252 100644 --- a/src/util-dpdk.h +++ b/src/util-dpdk.h @@ -121,6 +121,7 @@ void DPDKCleanupEAL(void); void DPDKCloseDevice(LiveDevice *ldev); void DPDKFreeDevice(LiveDevice *ldev); +void DPDKEvaluateHugepages(void); #ifdef HAVE_DPDK const char *DPDKGetPortNameByPortID(uint16_t pid);