Skip to content

test: cover the remaining nat_enospc sources — pool dry + hash-add ENOSPC#83

Merged
w180112 merged 1 commit into
masterfrom
test/nat-enospc-paths
Jul 9, 2026
Merged

test: cover the remaining nat_enospc sources — pool dry + hash-add ENOSPC#83
w180112 merged 1 commit into
masterfrom
test/nat-enospc-paths

Conversation

@w180112

@w180112 w180112 commented Jul 9, 2026

Copy link
Copy Markdown
Member

Summary

nat_enospc has three sources in nat_learning_port_reuse(); only the "every port reserved" one was tested. This PR covers the other two flagged in the PR #73#75 coverage analysis: free-ring exhaustion inside nat_slot_alloc() (pool dry) and rte_hash_add_key_data() ENOSPC on each of the two hashes. Test-only change; no production code touched.

New cases in unit_test/pppd/nat_test.c (22 assertions)

test_pool_dry_enospc (real fixture)

  • One flow is learned and expired, then the free ring is drained to simulate exhaustion by live flows
  • A new learn must fail and account exactly one nat_enospc
  • The emergency GC inside nat_slot_alloc demonstrably runs: the expired flow's keys are deleted (nat_gc_reclaimed+1, reverse lookup misses) — but the slot cannot come back in-call because the RCU defer queue needs reader quiescence first
  • Recovery: after an explicit quiesce + defer-queue reclaim, the slot returns to the ring and the same flow learns successfully with no further enospc

test_reverse_hash_full_enospc / test_forward_hash_full_enospc (small deterministic fixture)

The real hashes (262144-entry cuckoo, multi-writer + LF) have no deterministic fill-to-fail point — filling them to failure would make the test flaky. These cases build a small hand-assembled fixture (8-entry, single-writer hashes: key slots == entries exactly, so the 9th add fails with ENOSPC deterministically) and drive the very same nat_learning_port_reuse() code path:

  • Reverse full: every candidate port's reverse add hits ENOSPC → after the full port wrap the flow fails with one nat_enospc; the never-published slot returns to the ring on every failed iteration (no slot leak across 64k+ attempts), and the forward hash stays unpolluted
  • Forward full: reverse add succeeds, forward add hits ENOSPC → the reverse key is unpublished (the WAN side cannot reach the dead slot), the flow fails immediately with one nat_enospc, and the slot goes to deferred reclaim rather than straight back to the free ring (a reader may already hold the published entry)

Existing cases untouched.

Testing

  • make test: 1426/1426 pass
  • e2e_test/run_e2e_test.sh: 73 PASS / 0 FAIL / 0 SKIP

…OSPC

The existing enospc test only exercised the "every port reserved" source.
The other two sources in nat_learning_port_reuse were untested (flagged in
the coverage analysis of PR #73-#75): free-ring exhaustion inside
nat_slot_alloc, and rte_hash_add_key_data failure for each hash.

New cases in unit_test/pppd/nat_test.c (22 assertions):

- test_pool_dry_enospc: drains the free ring (with one expired flow left
  behind), then a new learn must fail with nat_enospc+1 while the
  emergency GC inside nat_slot_alloc demonstrably runs (expired flow's
  keys deleted, nat_gc_reclaimed+1) yet cannot return the slot in-call
  because the RCU defer queue needs reader quiescence. After an explicit
  quiesce+reclaim the slot returns and the same flow learns successfully.

- test_reverse_hash_full_enospc / test_forward_hash_full_enospc: the real
  hashes (262144-entry cuckoo, multi-writer) have no deterministic
  fill-to-fail point, so these use a small hand-built fixture (8-entry
  single-writer hashes → exactly 8 adds succeed, the 9th fails with
  ENOSPC) driving the same nat_learning_port_reuse code:
  - reverse full: every candidate port fails, one enospc after the full
    port wrap, the never-published slot returns to the ring on every
    iteration (no slot leak), no forward-key pollution.
  - forward full: reverse key gets unpublished (WAN side cannot reach
    the dead slot), flow fails immediately with one enospc, and the slot
    goes to deferred reclaim rather than straight back to the ring.

Existing cases untouched. make test 1426/1426; e2e 73/73 PASS 0 SKIP.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@w180112 w180112 closed this Jul 9, 2026
@w180112 w180112 reopened this Jul 9, 2026
@w180112 w180112 closed this Jul 9, 2026
@w180112 w180112 reopened this Jul 9, 2026
@w180112 w180112 closed this Jul 9, 2026
@w180112 w180112 reopened this Jul 9, 2026
@w180112 w180112 closed this Jul 9, 2026
@w180112 w180112 reopened this Jul 9, 2026
@w180112 w180112 merged commit f560024 into master Jul 9, 2026
25 checks passed
@w180112 w180112 deleted the test/nat-enospc-paths branch July 9, 2026 07:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant