From fdc17b212586eef4a9c88580837bca4bd841eda9 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Tue, 1 Apr 2025 16:03:46 -0600 Subject: [PATCH] pcap-log: add stats for written and filtered Filtered is the number of packets not written as they were filtered out. --- etc/schema.json | 14 +++++++++++++ src/log-pcap.c | 53 +++++++++++++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/etc/schema.json b/etc/schema.json index 95b9a90f58..6d21b74204 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -6643,6 +6643,20 @@ }, "additionalProperties": false }, + "pcap_log": { + "type": "object", + "properties": { + "written": { + "description": "Number of packets written", + "type": "integer" + }, + "filtered_bpf": { + "description": "Number of packets filtered out by bpf (not written)", + "type": "integer" + } + }, + "additionalProperties": false + }, "tcp": { "type": "object", "properties": { diff --git a/src/log-pcap.c b/src/log-pcap.c index 48261b3fe0..45c6e2aaf1 100644 --- a/src/log-pcap.c +++ b/src/log-pcap.c @@ -189,6 +189,8 @@ typedef struct PcapLogData_ { typedef struct PcapLogThreadData_ { PcapLogData *pcap_log; MemBuffer *buf; + uint16_t counter_written; /**< Counter for number of packets written */ + uint16_t counter_filtered_bpf; /**< Counter for number of packets filtered out and not writen */ } PcapLogThreadData; /* Pattern for extracting timestamp from pcap log files. */ @@ -493,24 +495,29 @@ static void PcapLogUnlock(PcapLogData *pl) } static inline int PcapWrite( - PcapLogData *pl, PcapLogCompressionData *comp, const uint8_t *data, const size_t len) + ThreadVars *tv, PcapLogThreadData *td, const uint8_t *data, const size_t len) { struct timeval current_dump; gettimeofday(¤t_dump, NULL); + PcapLogData *pl = td->pcap_log; if (pl->bpfp) { if (pcap_offline_filter(pl->bpfp, pl->h, data) == 0) { SCLogDebug("Packet doesn't match filter, will not be logged."); + StatsIncr(tv, td->counter_filtered_bpf); return TM_ECODE_OK; } } + StatsIncr(tv, td->counter_written); + pcap_dump((u_char *)pl->pcap_dumper, pl->h, data); if (pl->compression.format == PCAP_LOG_COMPRESSION_FORMAT_NONE) { pl->size_current += len; } #ifdef HAVE_LIBLZ4 - else if (comp->format == PCAP_LOG_COMPRESSION_FORMAT_LZ4) { + else if (pl->compression.format == PCAP_LOG_COMPRESSION_FORMAT_LZ4) { + PcapLogCompressionData *comp = &pl->compression; pcap_dump_flush(pl->pcap_dumper); long in_size = ftell(comp->pcap_buf_wrapper); if (in_size < 0) { @@ -547,9 +554,8 @@ static inline int PcapWrite( } struct PcapLogCallbackContext { - PcapLogData *pl; - PcapLogCompressionData *comp; - MemBuffer *buf; + ThreadVars *tv; + PcapLogThreadData *td; }; static int PcapLogSegmentCallback( @@ -560,26 +566,26 @@ static int PcapLogSegmentCallback( if (seg->pcap_hdr_storage->pktlen) { struct timeval tv; SCTIME_TO_TIMEVAL(&tv, seg->pcap_hdr_storage->ts); - pctx->pl->h->ts.tv_sec = tv.tv_sec; - pctx->pl->h->ts.tv_usec = tv.tv_usec; - pctx->pl->h->len = seg->pcap_hdr_storage->pktlen + buflen; - pctx->pl->h->caplen = seg->pcap_hdr_storage->pktlen + buflen; - MemBufferReset(pctx->buf); - MemBufferWriteRaw(pctx->buf, seg->pcap_hdr_storage->pkt_hdr, seg->pcap_hdr_storage->pktlen); - MemBufferWriteRaw(pctx->buf, buf, buflen); + pctx->td->pcap_log->h->ts.tv_sec = tv.tv_sec; + pctx->td->pcap_log->h->ts.tv_usec = tv.tv_usec; + pctx->td->pcap_log->h->len = seg->pcap_hdr_storage->pktlen + buflen; + pctx->td->pcap_log->h->caplen = seg->pcap_hdr_storage->pktlen + buflen; + MemBufferReset(pctx->td->buf); + MemBufferWriteRaw( + pctx->td->buf, seg->pcap_hdr_storage->pkt_hdr, seg->pcap_hdr_storage->pktlen); + MemBufferWriteRaw(pctx->td->buf, buf, buflen); - PcapWrite(pctx->pl, pctx->comp, (uint8_t *)pctx->buf->buffer, pctx->pl->h->len); + PcapWrite(pctx->tv, pctx->td, (uint8_t *)pctx->td->buf->buffer, pctx->td->pcap_log->h->len); } return 1; } -static void PcapLogDumpSegments( - PcapLogThreadData *td, PcapLogCompressionData *comp, const Packet *p) +static void PcapLogDumpSegments(ThreadVars *tv, PcapLogThreadData *td, const Packet *p) { uint8_t flag = STREAM_DUMP_HEADERS; /* Loop on segment from this side */ - struct PcapLogCallbackContext data = { td->pcap_log, comp, td->buf }; + struct PcapLogCallbackContext data = { tv, td }; StreamSegmentForSession(p, flag, PcapLogSegmentCallback, (void *)&data); } @@ -593,7 +599,7 @@ static void PcapLogDumpSegments( * \retval TM_ECODE_OK on succes * \retval TM_ECODE_FAILED on serious error */ -static int PcapLog (ThreadVars *t, void *thread_data, const Packet *p) +static int PcapLog(ThreadVars *tv, void *thread_data, const Packet *p) { size_t len; int ret = 0; @@ -635,7 +641,7 @@ static int PcapLog (ThreadVars *t, void *thread_data, const Packet *p) PcapLogCompressionData *comp = &pl->compression; if (comp->format == PCAP_LOG_COMPRESSION_FORMAT_NONE) { if ((pl->size_current + len) > pl->size_limit) { - if (PcapLogRotateFile(t,pl) < 0) { + if (PcapLogRotateFile(tv, pl) < 0) { PcapLogUnlock(pl); SCLogDebug("rotation of pcap failed"); return TM_ECODE_FAILED; @@ -651,7 +657,7 @@ static int PcapLog (ThreadVars *t, void *thread_data, const Packet *p) * act as if they would be written uncompressed. */ if ((pl->size_current + comp->bytes_in_block + len) > pl->size_limit) { - if (PcapLogRotateFile(t,pl) < 0) { + if (PcapLogRotateFile(tv, pl) < 0) { PcapLogUnlock(pl); SCLogDebug("rotation of pcap failed"); return TM_ECODE_FAILED; @@ -676,7 +682,7 @@ static int PcapLog (ThreadVars *t, void *thread_data, const Packet *p) if ((p->flags & PKT_FIRST_ALERTS) && (td->pcap_log->conditional != LOGMODE_COND_ALL)) { if (PacketIsTCP(p)) { /* dump fake packets for all segments we have on acked by packet */ - PcapLogDumpSegments(td, comp, p); + PcapLogDumpSegments(tv, td, p); if (p->flags & PKT_PSEUDO_STREAM_END) { PcapLogUnlock(pl); @@ -701,9 +707,9 @@ static int PcapLog (ThreadVars *t, void *thread_data, const Packet *p) if (p->ttype == PacketTunnelChild) { rp = p->root; - ret = PcapWrite(pl, comp, GET_PKT_DATA(rp), len); + ret = PcapWrite(tv, td, GET_PKT_DATA(rp), len); } else { - ret = PcapWrite(pl, comp, GET_PKT_DATA(p), len); + ret = PcapWrite(tv, td, GET_PKT_DATA(p), len); } if (ret != TM_ECODE_OK) { PCAPLOG_PROFILE_END(pl->profile_write); @@ -1033,6 +1039,9 @@ static TmEcode PcapLogDataInit(ThreadVars *t, const void *initdata, void **data) if (unlikely(td == NULL)) return TM_ECODE_FAILED; + td->counter_written = StatsRegisterCounter("pcap_log.written", t); + td->counter_filtered_bpf = StatsRegisterCounter("pcap_log.filtered_bpf", t); + if (pl->mode == LOGMODE_MULTI) td->pcap_log = PcapLogDataCopy(pl); else -- 2.47.2