diff options
| author | Dimitri Staessens <dimitri@ouroboros.rocks> | 2026-07-05 18:58:37 +0200 |
|---|---|---|
| committer | Sander Vrijders <sander@ouroboros.rocks> | 2026-07-19 11:44:36 +0200 |
| commit | d050aea4cd892d71ed7fc78b6c6149a7231db5fc (patch) | |
| tree | 81947bcfafe8e92b850ccf510a598581172acf32 /cmake | |
| parent | 573b4798008555b0776c1d3699d13bfad36cbbd0 (diff) | |
| download | ouroboros-d050aea4cd892d71ed7fc78b6c6149a7231db5fc.tar.gz ouroboros-d050aea4cd892d71ed7fc78b6c6149a7231db5fc.zip | |
ipcpd: Rework congestion avoidance
Congestion avoidance is a property of the layer, orthogonal to ARQ
and to flow control: FRCP retransmits and lets the peer pace the
sender, per flow, end-to-end; the IPCP paces path aggregates. Each
signal means one thing: a loss triggers a retransmission, a mark
means congestion, the peer window means a slow receiver. Every flow
is paced by the same rate law whatever its QoS, so a greedy raw
sender shares a bottleneck fairly with a reliable stream.
The unit of control is the (destination address, QoS cube)
aggregate: all flows toward that destination share one controller
and one rate; a start-time fair-queuing pacer divides the rate
across them by deadline instead of blocking the send path, and a
new flow rides the aggregate's estimates at its current rate, with
no probing of its own. Slow start runs once per aggregate.
The congestion signal is a multi-bit magnitude: forwarders mark
packets with their standing queue depth, MAX-combined across hops,
so a packet carries the deepest queue on its path. The receiver
feeds back a time-integral mean over a window that adapts to the
flow's byte rate, measuring a slow flow with the same fidelity as a
fast one. The sender runs AIMD scaled by elapsed wall-clock time,
which makes the steady-state allocation RTT-independent.
The PCI gains one byte: the path capacity as a quarter-log2 code.
Forwarders estimate their egress rate from busy-period drain and
MIN-stamp the byte, the receiver returns the window minimum with
its feedback, and the sender scales its rate floor and additive
slope to the bottleneck (C / 32). A deep cut implies a backlogged
bottleneck and a backlogged bottleneck advertises its capacity, so
the scaled floor is live exactly when recovery needs it: the probe
heals a halving in seconds at any link rate, and the floor bounds
the deepest hole to a factor 32 below the bottleneck.
Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'cmake')
| -rw-r--r-- | cmake/config/ipcp/unicast.cmake | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/cmake/config/ipcp/unicast.cmake b/cmake/config/ipcp/unicast.cmake index b8d4d516..92eeae65 100644 --- a/cmake/config/ipcp/unicast.cmake +++ b/cmake/config/ipcp/unicast.cmake @@ -9,6 +9,25 @@ set(IPCP_UNICAST_MTU 1400 CACHE STRING set(PFT_SIZE 256 CACHE STRING "Prefix forwarding table size for the Unicast IPCP") +# Aggregate congestion-avoidance context interning. One ctx is shared +# per (peer, qos cube); this is the hash table bucket count. Must be a +# power of two (the bucket index masks with CA_BUCKETS - 1). +set(IPCP_CA_BUCKETS 64 CACHE STRING + "Hash buckets for aggregate CA context interning (power of two)") +math(EXPR IPCP_CA_BUCKETS_POW2 "${IPCP_CA_BUCKETS} & (${IPCP_CA_BUCKETS} - 1)") +if((IPCP_CA_BUCKETS LESS 1) OR (NOT IPCP_CA_BUCKETS_POW2 EQUAL 0)) + message(FATAL_ERROR "IPCP_CA_BUCKETS must be a positive power of two") +endif() + +# Per-flow (non-aggregated) congestion avoidance. Aggregate CA per +# (peer, qos cube) is the production behaviour; enable this only to +# build the legacy per-flow reference for A/B testing and bisection. +set(IPCP_CA_PER_FLOW FALSE CACHE BOOL + "Use per-flow congestion avoidance (testing only)") +if(IPCP_CA_PER_FLOW) + message(STATUS "IPCP per-flow congestion avoidance (testing build)") +endif() + # Protocol debugging set(DEBUG_PROTO_DHT FALSE CACHE BOOL "Add DHT protocol debug logging") |
