From 35dffc6b32edefdccff18710abdb6f7bc6a1145f Mon Sep 17 00:00:00 2001 From: Lukas Sismis Date: Wed, 26 Jun 2024 23:33:52 +0200 Subject: [PATCH 1/2] dpdk: replace TSC clock with GetTime (gettimeofday) function Getting clock through Time Stamp Counter (TSC) can be precise and fast, however only for a short duration of time. The implementation across CPUs seems to vary. The original idea is to increment the counter with every tick. Then dividing the delta of CPU ticks by the CPU frequency can return the time that passed. However, the CPU clock/frequency can change over time, resulting in uneven incrementation of TSC. On some CPUs this is handled by extra logic. As a result, obtaining time through this method might drift from the real time. This commit therefore substitues TSC time retrieval by the standard system call wrapped in GetTime function - on Linux it is gettimeofday. Ticket: 7115 --- src/runmode-dpdk.c | 1 - src/source-dpdk.c | 66 ++++------------------------------------------ 2 files changed, 5 insertions(+), 62 deletions(-) diff --git a/src/runmode-dpdk.c b/src/runmode-dpdk.c index 0e814cbec9c0..46d486e0cc12 100644 --- a/src/runmode-dpdk.c +++ b/src/runmode-dpdk.c @@ -305,7 +305,6 @@ static void InitEal(void) if (retval < 0) { // retval bound to the result of rte_eal_init FatalError("DPDK EAL initialization error: %s", rte_strerror(-retval)); } - DPDKSetTimevalOfMachineStart(); } static void DPDKDerefConfig(void *conf) diff --git a/src/source-dpdk.c b/src/source-dpdk.c index cb486de0069d..1453b3ba7a13 100644 --- a/src/source-dpdk.c +++ b/src/source-dpdk.c @@ -92,7 +92,6 @@ TmEcode NoDPDKSupportExit(ThreadVars *tv, const void *initdata, void **data) #include #define BURST_SIZE 32 -static struct timeval machine_start_time = { 0, 0 }; // interrupt mode constants #define MIN_ZERO_POLL_COUNT 10U #define MIN_ZERO_POLL_COUNT_TO_SLEEP 10U @@ -146,11 +145,7 @@ static TmEcode DecodeDPDKThreadInit(ThreadVars *, const void *, void **); static TmEcode DecodeDPDKThreadDeinit(ThreadVars *tv, void *data); static TmEcode DecodeDPDK(ThreadVars *, Packet *, void *); -static uint64_t CyclesToMicroseconds(uint64_t cycles); -static uint64_t CyclesToSeconds(uint64_t cycles); static void DPDKFreeMbufArray(struct rte_mbuf **mbuf_array, uint16_t mbuf_cnt, uint16_t offset); -static uint64_t DPDKGetSeconds(void); - static bool InterruptsRXEnable(uint16_t port_id, uint16_t queue_id) { uint32_t event_data = port_id << UINT16_WIDTH | queue_id; @@ -193,57 +188,6 @@ static inline void DPDKFreeMbufArray( } } -static uint64_t CyclesToMicroseconds(const uint64_t cycles) -{ - const uint64_t ticks_per_us = rte_get_tsc_hz() / 1000000; - if (ticks_per_us == 0) { - return 0; - } - return cycles / ticks_per_us; -} - -static uint64_t CyclesToSeconds(const uint64_t cycles) -{ - const uint64_t ticks_per_s = rte_get_tsc_hz(); - if (ticks_per_s == 0) { - return 0; - } - return cycles / ticks_per_s; -} - -static void CyclesAddToTimeval( - const uint64_t cycles, struct timeval *orig_tv, struct timeval *new_tv) -{ - uint64_t usec = CyclesToMicroseconds(cycles) + orig_tv->tv_usec; - new_tv->tv_sec = orig_tv->tv_sec + usec / 1000000; - new_tv->tv_usec = (usec % 1000000); -} - -void DPDKSetTimevalOfMachineStart(void) -{ - gettimeofday(&machine_start_time, NULL); - machine_start_time.tv_sec -= DPDKGetSeconds(); -} - -/** - * Initializes real_tv to the correct real time. Adds TSC counter value to the timeval of - * the machine start - * @param machine_start_tv - timestamp when the machine was started - * @param real_tv - */ -static SCTime_t DPDKSetTimevalReal(struct timeval *machine_start_tv) -{ - struct timeval real_tv; - CyclesAddToTimeval(rte_get_tsc_cycles(), machine_start_tv, &real_tv); - return SCTIME_FROM_TIMEVAL(&real_tv); -} - -/* get number of seconds from the reset of TSC counter (typically from the machine start) */ -static uint64_t DPDKGetSeconds(void) -{ - return CyclesToSeconds(rte_get_tsc_cycles()); -} - static void DevicePostStartPMDSpecificActions(DPDKThreadVars *ptv, const char *driver_name) { if (strcmp(driver_name, "net_bonding") == 0) { @@ -415,7 +359,7 @@ static TmEcode ReceiveDPDKLoopInit(ThreadVars *tv, DPDKThreadVars *ptv) static inline void LoopHandleTimeoutOnIdle(ThreadVars *tv) { static thread_local uint64_t last_timeout_msec = 0; - SCTime_t t = DPDKSetTimevalReal(&machine_start_time); + SCTime_t t = TimeGet(); uint64_t msecs = SCTIME_MSECS(t); if (msecs > last_timeout_msec + 100) { TmThreadsCaptureHandleTimeout(tv, NULL); @@ -474,7 +418,7 @@ static inline Packet *PacketInitFromMbuf(DPDKThreadVars *ptv, struct rte_mbuf *m p->flags |= PKT_IGNORE_CHECKSUM; } - p->ts = DPDKSetTimevalReal(&machine_start_time); + p->ts = TimeGet(); p->dpdk_v.mbuf = mbuf; p->ReleasePacket = DPDKReleasePacket; p->dpdk_v.copy_mode = ptv->copy_mode; @@ -554,10 +498,10 @@ static void HandleShutdown(DPDKThreadVars *ptv) static void PeriodicDPDKDumpCounters(DPDKThreadVars *ptv) { - static thread_local time_t last_dump = 0; - time_t current_time = DPDKGetSeconds(); + static thread_local SCTime_t last_dump = { 0 }; + SCTime_t current_time = TimeGet(); /* Trigger one dump of stats every second */ - if (current_time != last_dump) { + if (current_time.secs != last_dump.secs) { DPDKDumpCounters(ptv); last_dump = current_time; } From eeec609ac822a9d3ffc407428d6e6a75f4e30afa Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 4 Jul 2024 13:55:27 +0200 Subject: [PATCH 2/2] util/thash: decrease memuse if array was allocated THashInitConfig may not allocate array and increase memuse. Such a failure leads to THashShutdown which should not decrease the memuse. Ticket: 7135 --- src/util-thash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util-thash.c b/src/util-thash.c index 649d8b98b845..74c74e245a69 100644 --- a/src/util-thash.c +++ b/src/util-thash.c @@ -378,8 +378,8 @@ void THashShutdown(THashTableContext *ctx) } SCFreeAligned(ctx->array); ctx->array = NULL; + (void)SC_ATOMIC_SUB(ctx->memuse, ctx->config.hash_size * sizeof(THashHashRow)); } - (void) SC_ATOMIC_SUB(ctx->memuse, ctx->config.hash_size * sizeof(THashHashRow)); THashDataQueueDestroy(&ctx->spare_q); DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(ctx->memuse) != 0); SCFree(ctx);