]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
dpdk: add hugepage hint to lower the amount of reserved hugepages
authorLukas Sismis <lsismis@oisf.net>
Wed, 16 Aug 2023 21:51:10 +0000 (23:51 +0200)
committerVictor Julien <victor@inliniac.net>
Mon, 16 Oct 2023 19:16:36 +0000 (21:16 +0200)
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

configure.ac
src/suricata-common.h
src/suricata.c
src/util-dpdk.c
src/util-dpdk.h

index 8bb752715f531e137b8600ae372e9982f7c3add8..cf6b8f6252566f9d1881f5140d3f199512e562f5 100644 (file)
     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])
index 47d578f72780d9dbfa05ff945fab6e02d90002ee..fe8ec179dff31eb4f277efd8b1afd4cab3b67021 100644 (file)
@@ -280,6 +280,10 @@ typedef unsigned char u_char;
 #include <magic.h>
 #endif
 
+#ifdef HAVE_MATH_H
+#include <math.h>
+#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)
index d9adcaf07b26bff5a4c5d8c9b652d93bf6efe0f2..30e6490826c7df17be52b239ea6fd133002f151e 100644 (file)
@@ -3037,6 +3037,8 @@ int SuricataMain(int argc, char **argv)
 
     PostRunStartedDetectSetup(&suricata);
 
+    DPDKEvaluateHugepages();
+
     SCPledge();
     SuricataMainLoop(&suricata);
 
index c9c1d73d03148f9d878f2608af400c71c5398907..089aa45674ae89428acc2f50d4884716ac607471 100644 (file)
@@ -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
 
 /**
index 1fb3532f5d4dbe252df865abf41010752384e715..a94f462252176909f417795fb5fae15c0700296c 100644 (file)
@@ -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);