summaryrefslogtreecommitdiff
path: root/src/ipcpd/unicast/ca/ops.h
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2026-07-05 18:58:37 +0200
committerSander Vrijders <sander@ouroboros.rocks>2026-07-19 11:44:36 +0200
commitd050aea4cd892d71ed7fc78b6c6149a7231db5fc (patch)
tree81947bcfafe8e92b850ccf510a598581172acf32 /src/ipcpd/unicast/ca/ops.h
parent573b4798008555b0776c1d3699d13bfad36cbbd0 (diff)
downloadouroboros-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 'src/ipcpd/unicast/ca/ops.h')
-rw-r--r--src/ipcpd/unicast/ca/ops.h20
1 files changed, 13 insertions, 7 deletions
diff --git a/src/ipcpd/unicast/ca/ops.h b/src/ipcpd/unicast/ca/ops.h
index 6d2ddf1d..a86c1b3b 100644
--- a/src/ipcpd/unicast/ca/ops.h
+++ b/src/ipcpd/unicast/ca/ops.h
@@ -30,24 +30,30 @@ struct ca_ops {
void (* ctx_destroy)(void * ctx);
- ca_wnd_t (* ctx_update_snd)(void * ctx,
- size_t len);
+ time_t (* ctx_update_snd)(void * ctx,
+ size_t len,
+ uint8_t lecn,
+ uint64_t * ftag);
bool (* ctx_update_rcv)(void * ctx,
size_t len,
uint8_t ecn,
- uint16_t * ece);
+ uint8_t cap,
+ uint16_t * ece,
+ uint8_t * fcap);
void (* ctx_update_ece)(void * ctx,
- uint16_t ece);
-
- void (* wnd_wait)(ca_wnd_t wnd);
+ uint16_t ece,
+ uint8_t cap);
- int (* calc_ecn)(int fd,
+ int (* calc_ecn)(size_t queued,
uint8_t * ecn,
qoscube_t qc,
size_t len);
+ /* True if calc_ecn inspects the queue; gates the lookup. */
+ bool marks_ecn;
+
/* Optional, can be NULL */
ssize_t (* print_stats)(void * ctx,
char * buf,