pub struct SessionManagerConfig {Show 17 fields
pub frame_mtu: usize,
pub max_frame_timeout: Duration,
pub max_buffered_segments: usize,
pub max_frames_behind_gap: Option<usize>,
pub initiation_timeout_base: Duration,
pub idle_timeout: Duration,
pub min_session_touch_period: Duration,
pub balancer_sampling_interval: Duration,
pub initial_return_session_egress_rate: usize,
pub minimum_surb_buffer_duration: Duration,
pub maximum_surb_buffer_size: usize,
pub surb_balance_notify_period: Option<Duration>,
pub surb_target_notify: bool,
pub maximum_sessions: usize,
pub session_forward_capacity: usize,
pub pix_config: IncomingSessionPixConfig,
pub max_ssas_per_ssa_request: usize,
}Expand description
Configuration for the SessionManager.
Fields§
§frame_mtu: usizeThe maximum chunk of data that can be written to the Session’s input buffer.
Default is 1500.
max_frame_timeout: DurationThe maximum time for an incomplete frame to stay in the Session’s output buffer.
Must exceed the worst-case SURB replenishment latency on the return path. The SURB balancer replenishes via KeepAlive every ~2 s; the retry loop in the routing resolver sleeps 5 ms per attempt and can block for the full replenishment cycle. Setting this below the KeepAlive period causes the sequencer to discard frames that arrive after a SURB-starved peer finally gets new SURBs and sends its echo.
Default is 3 s.
max_buffered_segments: usizeMaximum number of segments to buffer in the downstream transport of a Session’s socket. If 0 is given, the transport is unbuffered.
Default is 0.
max_frames_behind_gap: Option<usize>Abandon the frame due next once this many later frames are waiting behind it, rather than
holding them for the whole of Self::max_frame_timeout.
The two answer different questions. max_frame_timeout is how long a missing frame is
waited for, and is set here to exceed the ~2 s SURB KeepAlive so a starved peer’s late echo
is not discarded. This bounds how much already received data is held hostage during that
wait – a cost paid once per gap, which compounds as later frames queue up.
Without it, a session that cannot retransmit waits the full timeout for a frame that will never arrive. Measured on a 5-node cluster after killing a return relayer: 98.5 % of bytes returned over the wire, 0.60 % reached the application, and the application-side inter-arrival median sat exactly on the 3 s timeout.
The right value tracks reordering depth – throughput x latency spread / frame size – so
it is deployment-specific. Tune with SessionConfig::max_frames_behind_gap; too low converts
ordinary reordering into loss, too high leaves the stall in place.
Default is 256, which is roughly 3-4x the reordering depth of the cluster it was measured on (~0.5 MB/s over paths spread across 10-260 ms, 1500 B frames, so ~70-85 frames in flight out of order). The margin is not cosmetic: at 64 – about one reordering depth – a healthy baseline dropped from 100 % to 92.2 % arrival, because ordinary reordering was being read as loss. At 256 the same baseline returned 100 % while a return relayer killed mid-session still recovered 97.1 %, against 0.60 % with the bound absent.
Default is 256.
initiation_timeout_base: DurationThe base timeout for initiation of Session initiation.
The actual timeout is adjusted according to the number of hops for that Session:
t = initiation_time_out_base * (num_forward_hops + num_return_hops + 2)
Default is 500 milliseconds.
idle_timeout: DurationTimeout for Session to be closed due to inactivity.
Default is 180 seconds.
min_session_touch_period: DurationMinimum interval at which an establishing Session’s cache slot is refreshed
(“touched”) to keep idle_timeout from evicting it while
SURBs pre-load.
The touch period is idle_timeout / 2, floored to this
value so it never drops below a sane minimum for very short idle timeouts.
Default is 100 milliseconds.
balancer_sampling_interval: DurationThe sampling interval for SURB balancer. It will make SURB control decisions regularly at this interval.
Default is 100 milliseconds.
initial_return_session_egress_rate: usizeInitial packets per second egress rate on an incoming Session.
This only applies to incoming Sessions without the Capability::NoRateControl flag set.
Default is 10 packets/second.
minimum_surb_buffer_duration: DurationMinimum period of time for which a SURB buffer at the Exit must endure if no SURBs are being received.
In other words, it is the minimum period of time an Exit must withstand when no SURBs are received from the Entry at all. To do so, the egress traffic will be shaped accordingly to meet this requirement.
This only applies to incoming Sessions without the Capability::NoRateControl flag set.
Default is 5 seconds, minimum is 1 second.
maximum_surb_buffer_size: usizeIndicates the maximum number of SURBs in the SURB buffer to be requested when creating a new Session.
This value is theoretically capped by the size of the global transport SURB ring buffer, so values greater than that do not make sense. This value should be ideally set equal to the size of the global transport SURB RB.
Default is 10 000 SURBs.
surb_balance_notify_period: Option<Duration>If set, the Session recipient (Exit) will notify the Session initiator (Entry) about its SURB balance for the Session using keep-alive packets periodically.
Keep in mind that each notification also costs 1 SURB, so the notification period should not be too frequent.
Default is None (no notification sent to the client), minimum is 1 second.
surb_target_notify: boolIf set, the Session initiator (Entry) will notify the Session recipient (Exit) about the local SURB balancer target using keep-alive packets from the SURB balancer.
This is useful when the client plans to change the SURB balancer target dynamically.
Default is true.
maximum_sessions: usizeMaximum number of concurrent sessions allowed.
Default is 10_000.
session_forward_capacity: usizeHow many packets can be buffered if the HoprSession input socket is not fast enough.
Controls the capacity of the internal crossfire channel used for each session slot.
Default is 10 000.
pix_config: IncomingSessionPixConfigConfiguration of the PIX protocol for the Exit nodes.
max_ssas_per_ssa_request: usizeMaximum number of SSA commitments this node, acting as an Entry, will accept in a single
[SsaServerCommitmentMessage].
This is the Entry’s protection against a misbehaving Exit, not a preference: every accepted
entry costs a full new_ssa_commitment, thousands of outbound SsaCommit packets and its own
on-chain deposit, so without a cap one inbound packet amplifies into minutes of CPU, a large
packet burst, and as many simultaneous deposits as the wire format admits. An over-cap request
is rejected in full, before any commitment is generated or any ReadyToDeposit is emitted, and
the Exit is told with a SessionError — see refuse_ssa_request.
It must be at least the ssas_per_request of every Exit this node connects to — see
IncomingSessionPixConfig::ssas_per_request for why a mismatch loses every Session.
Clamped to 1..=MAX_SSA_BATCH_SIZE in SessionManager::new.
Defaults to DEFAULT_MAX_SSAS_PER_SSA_REQUEST (2).
Trait Implementations§
Source§impl Clone for SessionManagerConfig
impl Clone for SessionManagerConfig
Source§fn clone(&self) -> SessionManagerConfig
fn clone(&self) -> SessionManagerConfig
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SessionManagerConfig
impl Debug for SessionManagerConfig
Source§impl Default for SessionManagerConfig
impl Default for SessionManagerConfig
Source§fn default() -> Self
fn default() -> Self
Return SessionManagerConfig { frame_mtu: 1500, max_frame_timeout: Duration::from_secs(3), max_buffered_segments: 0, max_frames_behind_gap: Some(256), initiation_timeout_base: Duration::from_millis(500), idle_timeout: Duration::from_secs(180), min_session_touch_period: Duration::from_millis(100), balancer_sampling_interval: Duration::from_millis(100), initial_return_session_egress_rate: 10, minimum_surb_buffer_duration: Duration::from_secs(5), maximum_surb_buffer_size: 10_000, surb_balance_notify_period: None, surb_target_notify: true, maximum_sessions: 10_000, session_forward_capacity: 10000, pix_config: Default::default(), max_ssas_per_ssa_request: DEFAULT_MAX_SSAS_PER_SSA_REQUEST }
Source§impl PartialEq for SessionManagerConfig
impl PartialEq for SessionManagerConfig
impl StructuralPartialEq for SessionManagerConfig
Auto Trait Implementations§
impl Freeze for SessionManagerConfig
impl RefUnwindSafe for SessionManagerConfig
impl Send for SessionManagerConfig
impl Sync for SessionManagerConfig
impl Unpin for SessionManagerConfig
impl UnsafeUnpin for SessionManagerConfig
impl UnwindSafe for SessionManagerConfig
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.