From eefa0150b93b8446ba239a58d347088cb42d6d61 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 15 Mar 2023 14:25:22 +0100 Subject: [PATCH] PktSrc: Add HasBeenIdleFor() method This method will be used by the main loop to determine if an interface has become idle. Initially this will be used to determine when it is acceptable to update network_time to the current time (wallclock). --- src/iosource/PktSrc.cc | 22 ++++++++++++++++++++++ src/iosource/PktSrc.h | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index 2ca5d2720e..0fa9585621 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -139,6 +139,16 @@ void PktSrc::Done() Close(); } +bool PktSrc::HasBeenIdleFor(double interval) const + { + if ( have_packet || had_packet ) + return false; + + // Take the hit of a current_time() call now. + double now = zeek::util::current_time(true); + return idle_at_wallclock < now - interval; + }; + void PktSrc::Process() { if ( ! IsOpen() ) @@ -191,6 +201,18 @@ bool PktSrc::ExtractNextPacketInternal() } else { + // Update the idle_at timestamp the first time we've failed + // to extract a packet. This assumes ExtractNextPacket() is + // called regularly which is true for non-selectable PktSrc + // instances, but even for selectable ones with an FD the + // main-loop will call Process() on the interface regularly + // and detect it as idle. + if ( had_packet ) + { + DBG_LOG(DBG_PKTIO, "source %s is idle now", props.path.c_str()); + idle_at_wallclock = zeek::util::current_time(true); + } + had_packet = false; } diff --git a/src/iosource/PktSrc.h b/src/iosource/PktSrc.h index d93b5d60bc..a1ef1c6e64 100644 --- a/src/iosource/PktSrc.h +++ b/src/iosource/PktSrc.h @@ -88,6 +88,24 @@ public: */ bool IsError() const; + /** + * Return true if the source has been observed idle for the given + * wallclock interval. + * + * The default implementation looks at failing ExtractNextPacket() calls + * and keeps the wallclock timestamp when there was no packet available. + * The source is considered idle when there has not been a packet since + * \a interval seconds. + * + * Alternative implementations may check internally buffered packets + * or queue lengths. + * + * @param interval Interval in seconds. + * + * @return True if the source has been idle for \a interval seconds. + */ + virtual bool HasBeenIdleFor(double interval) const; + /** * If the source encountered an error, returns a corresponding error * message. Returns an empty string otherwise. @@ -365,6 +383,8 @@ private: // Did the previous call to ExtractNextPacket() yield a packet. bool had_packet; + double idle_at_wallclock = 0.0; + // For BPF filtering support. std::vector filters;