fix(flow-entry): add an insertion that will not displace a live flow - #1736
Draft
daniel-noland wants to merge 1 commit into
Draft
fix(flow-entry): add an insertion that will not displace a live flow#1736daniel-noland wants to merge 1 commit into
daniel-noland wants to merge 1 commit into
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
daniel-noland
force-pushed
the
pr/daniel-noland/fuzz-flow-entry
branch
from
August 18, 2026 03:07
c806fa7 to
731db9d
Compare
daniel-noland
force-pushed
the
pr/daniel-noland/fuzz-flow-entry
branch
from
August 18, 2026 20:23
731db9d to
420ecb8
Compare
daniel-noland
force-pushed
the
pr/daniel-noland/fuzz-flow-entry
branch
from
August 18, 2026 20:31
420ecb8 to
dfdf917
Compare
daniel-noland
force-pushed
the
pr/daniel-noland/fuzz-flow-entry
branch
from
August 18, 2026 20:38
dfdf917 to
0c36ba2
Compare
daniel-noland
force-pushed
the
pr/daniel-noland/fuzz-flow-entry
branch
from
August 18, 2026 23:17
0c36ba2 to
5d59ca1
Compare
Two packets of one new flow can reach a NAT stage at the same time. Packets of a 5-tuple usually land on one core, but nothing guarantees that, and each packet builds a pair of its own before inserting it. With a plain insert, whoever gets there second displaces the other's forward flow -- and only that half. The two reverse keys carry the allocations that made them, no two allocations agree, so the reverses never collide and the loser's is never displaced along with its partner. It stays in the table, live, mapping a translation whose allocation goes back to the pool as soon as the displaced forward half is collected. Return traffic for that public pair, once it has been handed out again, is then translated for whoever held it before. Two changes, either of which leaves a hole on its own. insert_if_absent stands aside when a live flow already holds the key, and reports that flow so the caller can go on with it. Arbitrating on one key is enough, because racing packets of a single flow share their forward key by construction: only whoever wins it inserts a reverse. A flow that is present but no longer live is displaced as before, since it is a corpse its timer has not swept yet and standing aside for one would drop a packet that could have replaced it. Displacing a flow now also invalidates the other half of its pair, wherever it happens. The race is not the only way to reach the orphan: the flow timer expires the two halves separately, so an expired forward half could be replaced by an ordinary insert while its partner was still live. That path needs no concurrency at all. Three tests, each of which fails against the code without its guard: a live flow keeps its key, a dead one does not, and displacing a flow takes its partner with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Daniel Noland <daniel@githedgehog.com> Rebased onto a `related_pair` that is fallible and requires exactly one half of the pair to carry `INITIATOR`; both are invariants main gained after this was written. The test now marks the forward half and unwraps, matching the sibling test in `concurrent_fuzz.rs`.
daniel-noland
force-pushed
the
pr/daniel-noland/fuzz-flow-entry
branch
from
August 19, 2026 06:33
5d59ca1 to
809fc6d
Compare
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.
Fourth of five, stacked on #1735. One commit.
Adds an insertion that will not displace a live flow, and the test for it.
Displacing a flow takes the other half of its pair with it; the two halves have
different keys, so nothing displaces the partner in its own right, and it is
left live mapping a translation whose allocation has returned to the pool.
Small, but it is the commit that most needed adapting to a
mainthat has movedon, and it is worth knowing how it failed. It cherry-picked with no conflict,
then failed to compile because
FlowInfo::related_pairbecame fallible, thencompiled and failed with
InvalidPair("One of the flows must be the initiator")— an invariantmaingained after this was written, which the testwas violating by flagging neither half. The forward half is now marked
INITIATOR, matching the sibling test inconcurrent_fuzz.rs.Three distinct failure modes behind one clean cherry-pick. With CI unavailable
this only surfaced because everything was run locally, which is the argument for
not trusting a clean apply on any of these branches.
Verified locally:
dataplane-flow-entry14/14,fmt --checkclean.🤖 Generated with Claude Code