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);