From fbadce4050fb6dae6aa93441f4a55939023d5001 Mon Sep 17 00:00:00 2001 From: Jan Sobol Date: Wed, 11 Feb 2026 17:24:46 +0100 Subject: [PATCH 1/5] cache: extract put_pkt method into put_pkt_recursive This change allows extracting side-effect parts which must be called once. --- src/plugins/storage/cache/src/cache.cpp | 11 ++++++++--- src/plugins/storage/cache/src/cache.hpp | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/plugins/storage/cache/src/cache.cpp b/src/plugins/storage/cache/src/cache.cpp index bda8bb4ac..c609d4f83 100644 --- a/src/plugins/storage/cache/src/cache.cpp +++ b/src/plugins/storage/cache/src/cache.cpp @@ -320,6 +320,11 @@ void NHTFlowCache::flush(Packet& pkt, size_t flow_index, int ret, bool source_fl } int NHTFlowCache::put_pkt(Packet& pkt) +{ + return put_pkt_recursive(pkt); +} + +int NHTFlowCache::put_pkt_recursive(Packet& pkt) { int ret = plugins_pre_create(pkt); @@ -429,7 +434,7 @@ int NHTFlowCache::put_pkt(Packet& pkt) // Flows with FIN or RST TCP flags are exported when new SYN packet arrives m_flow_table[flow_index]->m_flow.end_reason = FLOW_END_EOF; export_flow(flow_index); - put_pkt(pkt); + put_pkt_recursive(pkt); return 0; } @@ -453,7 +458,7 @@ int NHTFlowCache::put_pkt(Packet& pkt) #ifdef FLOW_CACHE_STATS m_expired++; #endif /* FLOW_CACHE_STATS */ - return put_pkt(pkt); + return put_pkt_recursive(pkt); } /* Check if flow record is expired (active timeout). */ @@ -464,7 +469,7 @@ int NHTFlowCache::put_pkt(Packet& pkt) #ifdef FLOW_CACHE_STATS m_expired++; #endif /* FLOW_CACHE_STATS */ - return put_pkt(pkt); + return put_pkt_recursive(pkt); } ret = plugins_pre_update(flow->m_flow, pkt); diff --git a/src/plugins/storage/cache/src/cache.hpp b/src/plugins/storage/cache/src/cache.hpp index 704d6e402..8f0f5db30 100644 --- a/src/plugins/storage/cache/src/cache.hpp +++ b/src/plugins/storage/cache/src/cache.hpp @@ -308,6 +308,7 @@ class NHTFlowCache FlowEndReasonStats m_flow_end_reason_stats = {}; FlowRecordStats m_flow_record_stats = {}; + int put_pkt_recursive(Packet& pkt); void try_to_fill_ports_to_fragmented_packet(Packet& packet); void flush(Packet& pkt, size_t flow_index, int ret, bool source_flow); bool create_hash_key(Packet& pkt); From 44be25fc1c7999494f2335405c5f0e17ade785fd Mon Sep 17 00:00:00 2001 From: Jan Sobol Date: Thu, 12 Feb 2026 15:06:14 +0100 Subject: [PATCH 2/5] cache: ensure that try_to_fill_ports_to_fragmented_packet is called only once --- src/plugins/storage/cache/src/cache.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/plugins/storage/cache/src/cache.cpp b/src/plugins/storage/cache/src/cache.cpp index c609d4f83..0fe470c48 100644 --- a/src/plugins/storage/cache/src/cache.cpp +++ b/src/plugins/storage/cache/src/cache.cpp @@ -321,6 +321,9 @@ void NHTFlowCache::flush(Packet& pkt, size_t flow_index, int ret, bool source_fl int NHTFlowCache::put_pkt(Packet& pkt) { + if (m_enable_fragmentation_cache) { + try_to_fill_ports_to_fragmented_packet(pkt); + } return put_pkt_recursive(pkt); } @@ -328,10 +331,6 @@ int NHTFlowCache::put_pkt_recursive(Packet& pkt) { int ret = plugins_pre_create(pkt); - if (m_enable_fragmentation_cache) { - try_to_fill_ports_to_fragmented_packet(pkt); - } - if (!create_hash_key(pkt)) { // saves key value and key length into attributes NHTFlowCache::key // and NHTFlowCache::m_keylen return 0; From bf6c354909447e01f1c0d574ba005b12f52cf8e4 Mon Sep 17 00:00:00 2001 From: Jan Sobol Date: Thu, 12 Feb 2026 15:10:16 +0100 Subject: [PATCH 3/5] parser: do not parse L4 if packet is continuing fragment --- src/plugins/input/parser/parser.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/plugins/input/parser/parser.cpp b/src/plugins/input/parser/parser.cpp index fcd117ea5..14b3dcdb8 100644 --- a/src/plugins/input/parser/parser.cpp +++ b/src/plugins/input/parser/parser.cpp @@ -758,12 +758,14 @@ void parse_packet( } l4_hdr_offset = data_offset; - if (pkt->ip_proto == IPPROTO_TCP) { - data_offset += parse_tcp_hdr(data + data_offset, caplen - data_offset, pkt, stats); - stats.tcp_packets++; - } else if (pkt->ip_proto == IPPROTO_UDP) { - data_offset += parse_udp_hdr(data + data_offset, caplen - data_offset, pkt, stats); - stats.udp_packets++; + if (pkt->frag_off == 0) { + if (pkt->ip_proto == IPPROTO_TCP) { + data_offset += parse_tcp_hdr(data + data_offset, caplen - data_offset, pkt, stats); + stats.tcp_packets++; + } else if (pkt->ip_proto == IPPROTO_UDP) { + data_offset += parse_udp_hdr(data + data_offset, caplen - data_offset, pkt, stats); + stats.udp_packets++; + } } } catch (const char* err) { DEBUG_MSG("%s\n", err); From a964b280c33469cc68140ae703bea475d380db49 Mon Sep 17 00:00:00 2001 From: Jan Sobol Date: Thu, 12 Feb 2026 15:16:01 +0100 Subject: [PATCH 4/5] parser: reset all packet data with calling constructor Fixes some members not resetting. Fixes inconsistent creation of fragmentation key and subsequent incorrect indexing in fragmentation table which was caused by not resetting ip addresses. Fixes incorrect marking some packets as fragments which was caused by not resetting frag_id and frag_off. --- src/plugins/input/parser/parser.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/plugins/input/parser/parser.cpp b/src/plugins/input/parser/parser.cpp index 14b3dcdb8..74cc0c476 100644 --- a/src/plugins/input/parser/parser.cpp +++ b/src/plugins/input/parser/parser.cpp @@ -682,6 +682,8 @@ void parse_packet( return; } Packet* pkt = &opt->pblock->pkts[opt->pblock->cnt]; + // reset all packet data + *pkt = Packet(); uint16_t data_offset = 0; DEBUG_MSG("---------- packet parser #%u -------------\n", ++s_total_pkts); @@ -693,18 +695,6 @@ void parse_packet( pkt->packet_len_wire = len; pkt->ts = ts; - pkt->src_port = 0; - pkt->dst_port = 0; - pkt->ip_proto = 0; - pkt->ip_ttl = 0; - pkt->ip_flags = 0; - pkt->ip_version = 0; - pkt->ip_payload_len = 0; - pkt->tcp_flags = 0; - pkt->tcp_window = 0; - pkt->tcp_options = 0; - pkt->tcp_mss = 0; - pkt->mplsTop = 0; stats.seen_packets++; From dffd2dcadb8eba62d7f4fcc252de009f7b368557 Mon Sep 17 00:00:00 2001 From: Jan Sobol Date: Mon, 16 Feb 2026 13:21:50 +0100 Subject: [PATCH 5/5] cache: track timeouted fragments in FragmentationCache telemetry --- .../cache/src/fragmentationCache/fragmentationCache.cpp | 3 +++ .../cache/src/fragmentationCache/fragmentationCache.hpp | 1 + 2 files changed, 4 insertions(+) diff --git a/src/plugins/storage/cache/src/fragmentationCache/fragmentationCache.cpp b/src/plugins/storage/cache/src/fragmentationCache/fragmentationCache.cpp index ea79dc570..000799f24 100644 --- a/src/plugins/storage/cache/src/fragmentationCache/fragmentationCache.cpp +++ b/src/plugins/storage/cache/src/fragmentationCache/fragmentationCache.cpp @@ -74,6 +74,8 @@ void FragmentationCache::fill_missing_packet_data( { if (!is_fragmentation_data_timedouted(packet, fragmentation_data)) { fill_ports_to_packet(packet, fragmentation_data); + } else { + m_stats.timeouted_fragments++; } } @@ -104,6 +106,7 @@ telemetry::Content FragmentationCache::get_cache_telemetry() dict["fragmentedTraffic"] = telemetry::ScalarWithUnit {trafficPercentage, "%"}; dict["fragmentedPackets"] = m_stats.fragmented_packets; dict["notFoundFragments"] = m_stats.not_found_fragments; + dict["timeoutedFragments"] = m_stats.timeouted_fragments; return dict; } diff --git a/src/plugins/storage/cache/src/fragmentationCache/fragmentationCache.hpp b/src/plugins/storage/cache/src/fragmentationCache/fragmentationCache.hpp index bb1633616..d8f2fa4b8 100644 --- a/src/plugins/storage/cache/src/fragmentationCache/fragmentationCache.hpp +++ b/src/plugins/storage/cache/src/fragmentationCache/fragmentationCache.hpp @@ -94,6 +94,7 @@ class FragmentationCache : TelemetryUtils { uint64_t first_fragments; uint64_t fragmented_packets; uint64_t not_found_fragments; + uint64_t timeouted_fragments; uint64_t total_packets; };