pub struct UdpFlow {
pub client: SocketAddr,
pub backend_id: Option<String>,
pub backend_addr: Option<SocketAddr>,
pub phase: FlowPhase,
pub config: ClusterConfig,
pub requests_seen: u32,
pub responses_seen: u32,
pub idle_deadline: Instant,
pub timer_gen: u64,
pub first_upstream_pending: bool,
}Expand description
Per-admitted-flow state. Slab slot payload owned by the manager.
Fields§
§client: SocketAddrReal (pre-NAT) client source address — the symmetric NAT return target and the PPv2 source address.
backend_id: Option<String>Backend id, set when the core selects the flow’s backend at admission.
backend_addr: Option<SocketAddr>Backend address, set when the core selects the flow’s backend at admission.
phase: FlowPhaseLifecycle phase.
config: ClusterConfigCaptured per-cluster knobs (responses/requests/timeouts/PPv2). Captured at admission so a mid-flow reconfig does not change a live flow’s teardown contract (stable affinity).
requests_seen: u32Client datagrams forwarded so far (counts toward requests).
responses_seen: u32Backend replies returned so far (counts toward responses).
idle_deadline: InstantAbsolute idle deadline; reset on every datagram in either direction.
timer_gen: u64Refresh counter. Incremented every time the idle deadline is pushed
back. No expiry path reads it: a wheel expiry closes the flow only when
idle_deadline is still <= now (deadline revalidation in
UdpManager::handle_timeout), which is what keeps a stale expiry from
closing a refreshed flow.
first_upstream_pending: boolTrue until the first upstream datagram is sent; gates PPv2 prefixing
when proxy_protocol_every_datagram is false (first-datagram-only).
Implementations§
Source§impl UdpFlow
impl UdpFlow
Sourcepub fn new(
client: SocketAddr,
config: ClusterConfig,
backend_id: BackendId,
backend_addr: SocketAddr,
now: Instant,
) -> Self
pub fn new( client: SocketAddr, config: ClusterConfig, backend_id: BackendId, backend_addr: SocketAddr, now: Instant, ) -> Self
Create a flow for client on the backend admission just selected, with
its idle deadline armed front_timeout from now.
The backend arrives at construction because selection happens before the flow exists: a flow is never without one.
Sourcepub fn touch(&mut self, timeout: Duration, now: Instant) -> u64
pub fn touch(&mut self, timeout: Duration, now: Instant) -> u64
Push the idle deadline back to now + timeout and advance timer_gen.
The later deadline is what invalidates an in-flight wheel expiry for the
old one: UdpManager::handle_timeout revalidates idle_deadline <= now
before closing. Returns the new timer_gen; no caller consumes it.
Sourcepub fn on_client_datagram(&mut self, now: Instant) -> u64
pub fn on_client_datagram(&mut self, now: Instant) -> u64
Record that one client datagram was actually forwarded upstream: bump
the requests counter and refresh the front idle deadline. Returns the
new timer_gen. Call this only at a real forward site, so
requests measures datagrams that actually reached a backend. Use
touch for an idle refresh that is not a forward.
Sourcepub fn on_backend_datagram(&mut self, now: Instant) -> u64
pub fn on_backend_datagram(&mut self, now: Instant) -> u64
Record that one backend reply was returned; refresh the back idle
deadline. Returns the new timer_gen.
Sourcepub fn set_phase(&mut self, next: FlowPhase)
pub fn set_phase(&mut self, next: FlowPhase)
Transition the flow to next, asserting the move is legal. One edge
remains: Established → Closing, a live flow torn down. A flow is
admitted Established, so there is no forward edge left, and every
other transition — including a self-loop — is a bug.
The idempotent-close case does not reach here: UdpManager::close_flow
returns early on a flow already Closing rather than re-setting it.
Debug-only guard — the assignment itself is unconditional so release behavior is identical.
Sourcepub fn requests_exhausted(&self) -> bool
pub fn requests_exhausted(&self) -> bool
Whether the requests knob has been exhausted (0 = unlimited).
Sourcepub fn responses_exhausted(&self) -> bool
pub fn responses_exhausted(&self) -> bool
Whether the responses knob has been exhausted (0 = unlimited). A DNS
flow with responses = 1 closes after its single reply.
Sourcepub fn teardown_reason(&self) -> Option<CloseReason>
pub fn teardown_reason(&self) -> Option<CloseReason>
The teardown reason if any knob is exhausted, else None. Idle is
handled separately by the manager via the timer wheel.
Sourcepub fn take_proxy_protocol(&mut self) -> bool
pub fn take_proxy_protocol(&mut self) -> bool
Whether this upstream datagram should carry a PPv2 DGRAM prefix, given the cluster’s first-datagram-only vs every-datagram policy. Marks the first-datagram bookkeeping as consumed.