File each lost observation against the packet it belonged to - #16
Closed
copyleftdev wants to merge 2 commits into
Closed
File each lost observation against the packet it belonged to#16copyleftdev wants to merge 2 commits into
copyleftdev wants to merge 2 commits into
Conversation
Attributing a hole to a probe narrowed where to look but left every absence unusable: knowing that ip_rcv failed to emit somewhere says nothing about whether a particular packet's missing hop was never reached or merely never observed. Every absence in a lossy capture stayed unknown, which is the weaker claim the footer has always had to make. The identity of the packet is already in scope wherever a reserve fails, so record the loss itself rather than inferring it later: a table keyed by packet and probe, written only on the failure path. Deliberately a plain hash and not an LRU. A full LRU evicts silently, and a silently evicted entry would make a packet look like it lost nothing, which is exactly the claim this table exists to support. A plain hash refuses the insert and counts the refusal instead. While that count is zero the table is exhaustive, so a packet absent from it provably lost nothing and a function missing from its chain was never reached. explain now rules per packet: complete, lost, or unknown. Reserve failures are the only loss kind a packet can own. A recursion miss never reaches the emit path, and a decode, enrichment or output failure discards a record after the kernel has handed it over, by which point nothing knows which packet it described. Any of those leaves a hole no packet can be cleared of, so clearing any packet requires all of them to be zero. A packet can now appear in the ledger while appearing nowhere in the capture. That is a packet whose every observation was dropped, which previously left no trace at all; replay counts these separately from the packets it actually observed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Resolves against the base branch's parameterised into_reliability by giving kernel_loss_by_skb the same treatment: both breakdowns are now parameters, so neither can be left unset by a future call site. skb_loss gets the same dedupe as probe_loss. A revisited key matters more here than it does there: a duplicate entry would put the same packet in the ledger twice, and that ledger is what a reader consults to decide whether a given packet lost anything. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Owner
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #15 — base is
attribute-ring-buffer-loss, so the diff here is only this change. Merge #15 first and this retargets tomain.Evidence change
#15 narrowed a hole to a probe, but left every absence unusable. Knowing
ip_rcvfailed to emit somewhere says nothing about whether a particular packet's missing hop was never reached or merely never observed, socomplete: falsestill downgraded every absence in the capture.This files each hole against the packet it belonged to. Two packets from the same globally-incomplete capture (16,382 reserve failures), on a live kernel:
For the second packet, a function absent from those 10 hops was never reached. That is "this function was never hit" separated from "we lost that one" — per packet, inside a capture that is not complete overall.
Closes the question from the DEV thread that prompted #15.
Why a plain hash, not an LRU
This is the load-bearing decision. A full LRU evicts silently, and a silently evicted entry would make a packet look like it lost nothing — turning the feature into a lie under exactly the load that makes it matter. A plain hash refuses the insert and counts the refusal in
kernel_skb_loss_unattributed.That refusal is what makes the negative claim provable rather than merely likely: while the counter is zero the table is exhaustive, so a packet absent from it lost nothing. An LRU would trade that proof for a bounded amount of memory.
Reserve failures are the only loss a packet can own
loss_is_fully_attributed()requires the skb table to be exhaustive andkernel_recursion_misses,userspace_decode_failures,userspace_enrichment_failuresandoutput_failuresto all be zero. A recursion miss never reaches the emit path; a decode, enrichment or output failure discards a record after the kernel handed it over, when nothing knows which packet it described. Any of those leaves a hole no packet can be cleared of.Read failures are deliberately excluded — they degrade fields on an event that was still emitted, and are already visible on it.
An earlier draft checked only the skb table and would have cleared packets in captures with output loss. Test
loss_that_no_packet_owns_defeats_attributionpins each case.Design note: this is not what the follow-up in #15 described
#15 proposed per-skb emit sequencing — stamp a counter into every record, infer loss from gaps. The identity turns out to be in scope at all 16 failure sites, which makes recording the loss directly strictly better:
The trailing-event blind spot decided it: #15 already noted sequencing could not see a lost last hop. This has no such gap, and needs no flag because it costs nothing until something is already failing.
Packets that were previously invisible
The first draft of the summary line printed
363 of 320 packets affected. Not a formatting bug — 104 packets lost every observation, so they appear in the ledger but nowhere in the capture. A wholly-dropped chain previously left no trace at all. Replay now reports these asskbs_lost_entirely, separate fromdistinct_skbs, which counts only packets actually observed.Change design
BPF_MAP_TYPE_HASH, 4096 entries, preallocated. Written only on the failure path. Overflow is counted, never silent.kernel_skb_loss_unattributedis the single gate on whether any packet may be cleared; non-zero collapses the claim for all of them at once.#[serde(default)]and absent fromrequired; the pre-existing fixture still parses and replays.Checks run
make checkandmake build, both exit 0.explainverdicts, missing-footer, and entirely-lost packets.unattributed=0) → per-packetcomplete/lost; heavy loss (table full at 4096, 11,866 unfiled) →unknownfor every packet; lossless →complete. Filed + unfiled reconciled againstkernel_reserve_failuresexactly.Untested
Unchanged from #15: the TC/XDP program-site path never executes here.Now verified live. Both paths were exercised under forced loss in isolated network namespaces, and the per-packet ledger carries the program id the same way the per-probe table does:explainrules correctly on TC-traced packets from a lossy capture —{"verdict": "lost", "observations_lost": 1}for an affected packet,{"verdict": "complete"}for one the ledger clears.Full live suite: 13/14 pass.
live-bpf-helperfails identically onmainat b378c01, so it is pre-existing on this host, not caused by this change.4096 entries is sized for the light-loss case this feature is for. Under heavy loss the table fills and every verdict degrades to
unknown, which is correct but means the guarantee is only available when loss is bounded. That ceiling is a judgement call, not a measurement.🤖 Generated with Claude Code