mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Merge remote-tracking branch 'origin/topic/awelzel/2791-pcap-stat-overflow'
* origin/topic/awelzel/2791-pcap-stat-overflow: pcap/Source: Allow more than 32bit for link and dropped stats
This commit is contained in:
commit
f227b30d30
5 changed files with 118 additions and 3 deletions
27
CHANGES
27
CHANGES
|
@ -1,3 +1,30 @@
|
||||||
|
6.0.0-dev.467 | 2023-04-28 10:01:13 +0200
|
||||||
|
|
||||||
|
* GH-2791: pcap/Source: Allow more than 32bit for link and dropped stats (Arne Welzel, Corelight)
|
||||||
|
|
||||||
|
The PktSrc::Stats object works with 64bit unsigned integers. Unfortunately,
|
||||||
|
libpcap's struct pcap_stat is using 32bit values and users have reported
|
||||||
|
the wrapping of these values being visible in their stats.log roughly every
|
||||||
|
7.5 hours (~160kpps).
|
||||||
|
|
||||||
|
This change moves tracking of link and drop counters into the PktSrc::Stats
|
||||||
|
object (like is done for received and bytes_received) and updates them
|
||||||
|
on a call to PcapSource::Statistics() with the difference to the
|
||||||
|
previous stats values to prevent the wrap from becoming visible to
|
||||||
|
script land.
|
||||||
|
|
||||||
|
This doesn't cover the case of the stats counters wrapping around multiple
|
||||||
|
times between two invocations of PktSrc::Statistics(). With the default
|
||||||
|
interval of 5 minutes for the stats script, this seems acceptable.
|
||||||
|
|
||||||
|
Closes #2791.
|
||||||
|
|
||||||
|
* record_fields: Include information about optionality of fields (Arne Welzel, Corelight)
|
||||||
|
|
||||||
|
This was reported as a wish for log schema generation, so add it...
|
||||||
|
|
||||||
|
* Fix a few warnings from recent changes (Tim Wojtulewicz)
|
||||||
|
|
||||||
6.0.0-dev.461 | 2023-04-28 09:37:08 +0200
|
6.0.0-dev.461 | 2023-04-28 09:37:08 +0200
|
||||||
|
|
||||||
* Simplify btests using cluster_started event. (Jan Grashoefer, Corelight)
|
* Simplify btests using cluster_started event. (Jan Grashoefer, Corelight)
|
||||||
|
|
3
NEWS
3
NEWS
|
@ -300,6 +300,9 @@ Changed Functionality
|
||||||
masked to exclude PCP and DEI bits. Previously, these bits were included
|
masked to exclude PCP and DEI bits. Previously, these bits were included
|
||||||
and could cause invalid vlan values > 4095 to be reported.
|
and could cause invalid vlan values > 4095 to be reported.
|
||||||
|
|
||||||
|
- Libpcap based packet source now avoids the 32bit wraparound of link and
|
||||||
|
dropped packet counters as reported by users.
|
||||||
|
|
||||||
Removed Functionality
|
Removed Functionality
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
6.0.0-dev.461
|
6.0.0-dev.467
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "zeek/zeek-config.h"
|
#include "zeek/zeek-config.h"
|
||||||
|
|
||||||
|
#include "zeek/3rdparty/doctest.h"
|
||||||
|
|
||||||
#ifdef HAVE_PCAP_INT_H
|
#ifdef HAVE_PCAP_INT_H
|
||||||
#include <pcap-int.h>
|
#include <pcap-int.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -326,6 +328,23 @@ bool PcapSource::SetFilter(int index)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Given two pcap_stat structures, compute the difference of linked and dropped
|
||||||
|
// and add it to the given Stats object.
|
||||||
|
static void update_pktsrc_stats(PktSrc::Stats* stats, const struct pcap_stat* now,
|
||||||
|
const struct pcap_stat* prev)
|
||||||
|
{
|
||||||
|
decltype(now->ps_drop) ps_drop_diff = 0;
|
||||||
|
decltype(now->ps_recv) ps_recv_diff = 0;
|
||||||
|
|
||||||
|
// This is subtraction of unsigned ints: It's not undefined
|
||||||
|
// and results in modulo arithmetic.
|
||||||
|
ps_recv_diff = now->ps_recv - prev->ps_recv;
|
||||||
|
ps_drop_diff = now->ps_drop - prev->ps_drop;
|
||||||
|
|
||||||
|
stats->link += ps_recv_diff;
|
||||||
|
stats->dropped += ps_drop_diff;
|
||||||
|
}
|
||||||
|
|
||||||
void PcapSource::Statistics(Stats* s)
|
void PcapSource::Statistics(Stats* s)
|
||||||
{
|
{
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
@ -344,11 +363,13 @@ void PcapSource::Statistics(Stats* s)
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s->dropped = pstat.ps_drop;
|
update_pktsrc_stats(&stats, &pstat, &prev_pstat);
|
||||||
s->link = pstat.ps_recv;
|
prev_pstat = pstat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->link = stats.link;
|
||||||
|
s->dropped = stats.dropped;
|
||||||
s->received = stats.received;
|
s->received = stats.received;
|
||||||
s->bytes_received = stats.bytes_received;
|
s->bytes_received = stats.bytes_received;
|
||||||
|
|
||||||
|
@ -376,4 +397,67 @@ iosource::PktSrc* PcapSource::Instantiate(const std::string& path, bool is_live)
|
||||||
return new PcapSource(path, is_live);
|
return new PcapSource(path, is_live);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("pcap source update_pktsrc_stats")
|
||||||
|
{
|
||||||
|
PktSrc::Stats stats;
|
||||||
|
struct pcap_stat now = {0};
|
||||||
|
struct pcap_stat prev = {0};
|
||||||
|
|
||||||
|
SUBCASE("all zero")
|
||||||
|
{
|
||||||
|
update_pktsrc_stats(&stats, &now, &prev);
|
||||||
|
CHECK(stats.link == 0);
|
||||||
|
CHECK(stats.dropped == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("no overflow")
|
||||||
|
{
|
||||||
|
now.ps_recv = 7;
|
||||||
|
now.ps_drop = 3;
|
||||||
|
update_pktsrc_stats(&stats, &now, &prev);
|
||||||
|
CHECK(stats.link == 7);
|
||||||
|
CHECK(stats.dropped == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("no overflow prev")
|
||||||
|
{
|
||||||
|
stats.link = 2;
|
||||||
|
stats.dropped = 1;
|
||||||
|
prev.ps_recv = 2;
|
||||||
|
prev.ps_drop = 1;
|
||||||
|
now.ps_recv = 7;
|
||||||
|
now.ps_drop = 3;
|
||||||
|
|
||||||
|
update_pktsrc_stats(&stats, &now, &prev);
|
||||||
|
CHECK(stats.link == 7);
|
||||||
|
CHECK(stats.dropped == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("overflow")
|
||||||
|
{
|
||||||
|
prev.ps_recv = 4294967295;
|
||||||
|
prev.ps_drop = 4294967294;
|
||||||
|
now.ps_recv = 0;
|
||||||
|
now.ps_drop = 1;
|
||||||
|
|
||||||
|
update_pktsrc_stats(&stats, &now, &prev);
|
||||||
|
CHECK(stats.link == 1);
|
||||||
|
CHECK(stats.dropped == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("overflow 2")
|
||||||
|
{
|
||||||
|
stats.link = 4294967295;
|
||||||
|
stats.dropped = 4294967294;
|
||||||
|
prev.ps_recv = 4294967295;
|
||||||
|
prev.ps_drop = 4294967294;
|
||||||
|
now.ps_recv = 10;
|
||||||
|
now.ps_drop = 3;
|
||||||
|
|
||||||
|
update_pktsrc_stats(&stats, &now, &prev);
|
||||||
|
CHECK(stats.link == 4294967306); // 2**32 - 1 + 11
|
||||||
|
CHECK(stats.dropped == 4294967299); // 2**32 - 2 + 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace zeek::iosource::pcap
|
} // namespace zeek::iosource::pcap
|
||||||
|
|
|
@ -43,6 +43,7 @@ private:
|
||||||
Stats stats;
|
Stats stats;
|
||||||
|
|
||||||
pcap_t* pd;
|
pcap_t* pd;
|
||||||
|
struct pcap_stat prev_pstat = {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace zeek::iosource::pcap
|
} // namespace zeek::iosource::pcap
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue