Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions _Log.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
## 2026-07-08 — #4409 increment 1: extract reuse_existing_lease_locked

- **Timestamp**: 2026-07-08
- **Action**: #4409 (Rust NAT modules — `nat/allocator.rs` PortAllocator
god-struct/god-functions), increment 1. Pure code-motion extraction of
the #2397 persistent-NAT lease-reuse block (57 interior LOC) out of the
`allocate_translation` god-function into a new private
`fn reuse_existing_lease_locked(&self, live: &mut PortAllocatorLiveState,
key, flow, persistent_nat_timeout_ns, now_ns) -> Option<TranslatedTuple>`.
The block handled the "lease already exists for this persistent key" case
(reuse a still-valid lease and return its tuple, or tear down an expired
lease and fall through). Its only non-linear exit was the inner
`return Ok(translated)`, which maps cleanly to the helper's
`Some(TranslatedTuple)` return — the caller does
`if let Some(t) = self.reuse_existing_lease_locked(...) { return Ok(t); }`.
Behaviour is identical: same mutation order, same side effects
(`reuses_total` bump, `live_by_flow` insert, expiry-index removal,
`release_translated_locked`, `persistent_by_source.remove`), same lock
scope — the caller keeps holding its `live` MutexGuard and passes it by
`&mut`, so nothing runs outside the existing critical section. The only
textual change beyond the move is `&mut live` -> `live` at the internal
helper calls (inside the helper `live` is already `&mut
PortAllocatorLiveState`). This is NOT the #2852 Phase-1 lock-free change
(that is a behaviour change tracked separately, needs /triple-review).
Validation: full `cargo test` 3830/0 (nat:: subset 205/0), build clean,
rustfmt-clean on the changed lines (the only remaining local-rustfmt diff
is the pre-existing `use`-ordering at line 42, untouched).
- **File(s)**: userspace-dp/src/nat/allocator.rs, _Log.md

## 2026-07-08 — #4408 increment 1: extract compute_forwarded_egress_ptb

- **Timestamp**: 2026-07-08
Expand Down
144 changes: 91 additions & 53 deletions userspace-dp/src/nat/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,59 +441,14 @@ impl PortAllocator {
let persistent_key =
persistent_nat.then(|| flow.persistent_source_key(persistent_nat_permit));
if let Some(key) = persistent_key {
if live.persistent_by_source.contains_key(&key) {
let mut reusable = None;
let mut expired = None;
let mut remove_expiry = None;
if let Some(lease) = live.persistent_by_source.get_mut(&key) {
if lease.active_flows > 0 || lease.expires_at_ns > now_ns {
let translated = lease.translated;
if lease.active_flows == 0 {
remove_expiry = Some(lease.expires_at_ns);
lease.activation_saw_completion = false;
lease.activation_previous_expires_at_ns = lease.expires_at_ns;
lease.activation_had_previous_lease = true;
}
lease.active_flows = lease.active_flows.saturating_add(1);
let expires_at_ns =
now_ns.saturating_add(persistent_nat_timeout_ns.max(NS_PER_SEC));
lease.expires_at_ns = expires_at_ns;
reusable = Some(translated);
} else {
expired = Some((lease.translated, lease.addr_index, lease.expires_at_ns));
}
}
if let Some(expires_at_ns) = remove_expiry {
if let Some(addr_index) = live
.persistent_by_source
.get(&key)
.map(|lease| lease.addr_index)
{
Self::remove_lease_expiration_locked(
&mut live,
addr_index,
expires_at_ns,
key,
);
}
}
if let Some(translated) = reusable {
live.live_by_flow.insert(
flow,
LiveAllocation {
translated,
persistent_key: Some(key),
deterministic: false,
},
);
self.shared.reuses_total.fetch_add(1, Ordering::Relaxed);
return Ok(translated);
}
if let Some((translated, addr_index, expires_at_ns)) = expired {
Self::remove_lease_expiration_locked(&mut live, addr_index, expires_at_ns, key);
self.release_translated_locked(&mut live, translated);
live.persistent_by_source.remove(&key);
}
if let Some(translated) = self.reuse_existing_lease_locked(
&mut live,
key,
flow,
persistent_nat_timeout_ns,
now_ns,
) {
return Ok(translated);
}
}

Expand Down Expand Up @@ -573,6 +528,89 @@ impl PortAllocator {
Err(super::source::SourceNatFailureReason::AllocatorExhausted)
}

/// #2397 persistent-NAT lease reuse, run under the live-state lock as the
/// first persistent-key step of `allocate_translation`.
///
/// When a lease already exists for `key`:
/// - a still-valid lease (an active flow, or one whose inactivity timeout
/// has not yet elapsed) is REUSED — on the 0 -> 1 active-flow edge its
/// activation-rollback bookkeeping is re-armed and its old expiry index
/// entry is dropped, its inactivity expiry is pushed out, the flow is
/// recorded in `live_by_flow`, `reuses_total` is bumped, and the reused
/// translated tuple is returned as `Some(_)` (the caller returns it
/// directly);
/// - an expired lease is torn down (expiry index entry removed, translated
/// tuple released, lease dropped) and `None` is returned so the caller
/// falls through to a fresh allocation.
///
/// Returns `None` when no lease exists for `key` or the lease was expired and
/// reclaimed.
///
/// #4409 increment 1: PURE lock-scoped code-motion out of the
/// `allocate_translation` god-function — identical mutation order and side
/// effects, executed under the caller's already-held `live` lock (the caller
/// passes its `MutexGuard` by `&mut`, so the lock scope is unchanged).
fn reuse_existing_lease_locked(
&self,
live: &mut PortAllocatorLiveState,
key: PersistentSourceKey,
flow: SourceNatFlowKey,
persistent_nat_timeout_ns: u64,
now_ns: u64,
) -> Option<TranslatedTuple> {
if !live.persistent_by_source.contains_key(&key) {
return None;
}
Comment on lines +561 to +563
let mut reusable = None;
let mut expired = None;
let mut remove_expiry = None;
if let Some(lease) = live.persistent_by_source.get_mut(&key) {
if lease.active_flows > 0 || lease.expires_at_ns > now_ns {
let translated = lease.translated;
if lease.active_flows == 0 {
remove_expiry = Some(lease.expires_at_ns);
lease.activation_saw_completion = false;
lease.activation_previous_expires_at_ns = lease.expires_at_ns;
lease.activation_had_previous_lease = true;
}
lease.active_flows = lease.active_flows.saturating_add(1);
let expires_at_ns =
now_ns.saturating_add(persistent_nat_timeout_ns.max(NS_PER_SEC));
lease.expires_at_ns = expires_at_ns;
reusable = Some(translated);
} else {
expired = Some((lease.translated, lease.addr_index, lease.expires_at_ns));
}
}
if let Some(expires_at_ns) = remove_expiry {
if let Some(addr_index) = live
.persistent_by_source
.get(&key)
.map(|lease| lease.addr_index)
{
Self::remove_lease_expiration_locked(live, addr_index, expires_at_ns, key);
}
}
if let Some(translated) = reusable {
live.live_by_flow.insert(
flow,
LiveAllocation {
translated,
persistent_key: Some(key),
deterministic: false,
},
);
self.shared.reuses_total.fetch_add(1, Ordering::Relaxed);
return Some(translated);
}
if let Some((translated, addr_index, expires_at_ns)) = expired {
Self::remove_lease_expiration_locked(live, addr_index, expires_at_ns, key);
self.release_translated_locked(live, translated);
live.persistent_by_source.remove(&key);
}
None
}

fn claim_free_port_locked(
&self,
live: &mut PortAllocatorLiveState,
Expand Down