From 39191ab6f0e5bf483a9621b2f92aa9600caebda8 Mon Sep 17 00:00:00 2001 From: Moses Narrow <36607567+0pcom@users.noreply.github.com> Date: Sat, 22 Aug 2026 20:58:28 -0500 Subject: [PATCH] feat(routing-policy): add experimental 'coupled' preset (MPTCP-style coupled congestion control) A new opt-in preset inspired by MPTCP's coupled congestion control (LIA/OLIA). It provisions a modest symmetric mux (4) over the multi-hop overlay and weights bytes toward the best legs (Distribution "auto"), then couples the aggregate in on_tick using per-leg retransmit-delta (loss) and EWMA latency: - coupled INCREASE (LIA-cautious): promote at most one warm spare per tick, and only when NO active leg shows rising loss. - coupled DECREASE: the instant any active leg's loss rises, shed the worst leg (highest loss, latency-tiebroken; never leg 0, never below a floor of 2) so aggregate aggressiveness stays bounded and traffic concentrates on the good legs rather than equal-spreading across a lossy one. Deterministic (no time.Now/rand) so the native and wazero paths stay byte-identical. Registered in preset dispatch, names, and the bundle manifest; bundle.wasm rebuilt. No existing default changes - decideAdaptive untouched. Adds native unit tests (loss->shed-worst, clean->cautious-promote, coupling-forbids-grow-under-loss) and coupled decide+tick cases to the native<->wazero parity suite. --- .../routing-policies/wasm/bundle/bundle.wasm | Bin 557025 -> 564358 bytes pkg/router/policy/preset/names.go | 1 + pkg/router/policy/preset/preset.go | 32 ++++ pkg/router/policy/preset/preset_test.go | 88 ++++++++++ pkg/router/policy/preset/tick.go | 166 ++++++++++++++++++ pkg/router/policy/wasm/presets/bundle.wasm | Bin 557025 -> 564358 bytes pkg/router/policy/wasm/presets/manifest.json | 1 + pkg/router/policy/wasm/presets/parity_test.go | 21 +++ 8 files changed, 309 insertions(+) diff --git a/docs/examples/routing-policies/wasm/bundle/bundle.wasm b/docs/examples/routing-policies/wasm/bundle/bundle.wasm index d7f09d68fe65f7b841998c715752357386550050..6f494149fdd837308c237c49648fcb8967617cbf 100644 GIT binary patch delta 79791 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%0A5>f|t79@g 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 Bh!y|< diff --git a/pkg/router/policy/preset/names.go b/pkg/router/policy/preset/names.go index 4d0c5bc42a..dde757c0d1 100644 --- a/pkg/router/policy/preset/names.go +++ b/pkg/router/policy/preset/names.go @@ -15,6 +15,7 @@ func Names() []string { "latency-adaptive", "elastic-mux", "probe-and-prune", + "coupled", "adaptive", "geo-avoid", "transport-diverse", diff --git a/pkg/router/policy/preset/preset.go b/pkg/router/policy/preset/preset.go index 95dd85f569..c7d7c8c211 100644 --- a/pkg/router/policy/preset/preset.go +++ b/pkg/router/policy/preset/preset.go @@ -108,6 +108,8 @@ func Decide(name string, ctx Context, cands []Candidate) Spec { return decideElasticMux(ctx) case "probe-and-prune": return decideProbeAndPrune(ctx) + case "coupled": + return decideCoupled(ctx) case "adaptive": return decideAdaptive(ctx, cands) case "app-mux": @@ -234,6 +236,36 @@ func decideProbeAndPrune(ctx Context) Spec { return Spec{} } +// decideCoupled is the EXPERIMENTAL "coupled" preset's decide logic — a +// multipath policy inspired by MPTCP's coupled congestion control (LIA/OLIA). +// It provisions a modest symmetric mux (coupledMux legs) over the multi-hop +// overlay and asks the host to weight bytes toward the best legs (Distribution +// "auto" = inverse-latency), NOT spread them equally across a lossy path. The +// on_tick controller (tickCoupled) then "couples" the aggregate: it grows the +// active set CAUTIOUSLY — at most one promote per tick, and only when NO active +// leg shows rising loss (LIA's coupled increase) — and sheds the WORST leg +// (highest loss, latency-tiebroken) the moment congestion appears, so total +// aggressiveness stays bounded and traffic concentrates on the good legs. +// Latency-sensitive chat stays a single lean route; non-target apps inherit the +// visor default. +func decideCoupled(ctx Context) Spec { + switch ctx.App { + case "skychat", "skychat-client": + return Spec{Mux: 1} + case "vpn-client", "skysocks-client", "skynet-client": + return Spec{ + Mux: coupledMux, + MinHops: 2, + RotationIntervalSeconds: 20, + // Weight bytes toward the lowest-latency/lowest-loss legs (the + // "coupled" bias) rather than round-robin's equal spread across a + // congested leg. + Distribution: "auto", + } + } + return Spec{} +} + // decideAdaptive is the COMPOSITE "adaptive" preset's decide logic — the // intended converged default (the config generator wires "preset:adaptive"). // diff --git a/pkg/router/policy/preset/preset_test.go b/pkg/router/policy/preset/preset_test.go index 8c976c8ee5..1e64cbaf1e 100644 --- a/pkg/router/policy/preset/preset_test.go +++ b/pkg/router/policy/preset/preset_test.go @@ -532,3 +532,91 @@ func TestEngine_OnTick_LedbatGrowsWhenNoQueuing(t *testing.T) { t.Errorf("grow must not shed; got %+v", got) } } + +// TestDecide_Coupled pins the coupled preset's decide shape: a modest symmetric +// mux over the multi-hop overlay with best-leg (auto) byte weighting for target +// apps, a single lean route for chat, defaults for everything else. +func TestDecide_Coupled(t *testing.T) { + if got := Decide("coupled", Context{App: "skysocks-client"}, nil); !reflect.DeepEqual( + got, Spec{Mux: 4, MinHops: 2, RotationIntervalSeconds: 20, Distribution: "auto"}) { + t.Errorf("coupled/proxy: Decide=%+v", got) + } + if got := Decide("coupled", Context{App: "skychat"}, nil); !reflect.DeepEqual(got, Spec{Mux: 1}) { + t.Errorf("coupled/chat: Decide=%+v want {Mux:1}", got) + } + if got := Decide("coupled", Context{App: "other"}, nil); !reflect.DeepEqual(got, Spec{}) { + t.Errorf("coupled/other: Decide=%+v want {}", got) + } +} + +// TestEngine_OnTick_CoupledShedsWorstOnLoss drives the coupled controller with a +// clean 4-wide active set, then makes one leg's retransmits rise, and asserts the +// COUPLED DECREASE: the worst (lossy) leg is shed to standby — a lone demote, +// concentrating traffic on the good legs. +func TestEngine_OnTick_CoupledShedsWorstOnLoss(t *testing.T) { + e := New() + base := func(retrans2 uint64) []LegInfo { + return []LegInfo{ + {Index: 0, TransportID: "t0", Kind: "stcpr", LatencyMs: 50, Alive: true}, + {Index: 1, TransportID: "t1", Kind: "stcpr", LatencyMs: 50, Alive: true}, + {Index: 2, TransportID: "t2", Kind: "stcpr", LatencyMs: 50, Alive: true, Retransmits: retrans2}, + {Index: 3, TransportID: "t3", Kind: "stcpr", LatencyMs: 50, Alive: true}, + } + } + // Tick 1 establishes the retransmit baseline; a clean 4-wide set at the ceiling + // is a no-op (no grow, no loss to shed). + if got := e.OnTick("coupled", base(0)); !reflect.DeepEqual(got, RotationAction{}) { + t.Fatalf("baseline tick must be a no-op; got %+v", got) + } + // Tick 2: leg 2's retransmits jumped → rising loss → shed the worst leg (2). + got := e.OnTick("coupled", base(100)) + if len(got.DemoteToStandby) != 1 || got.DemoteToStandby[0] != 2 { + t.Errorf("coupled must shed the lossy leg (2) to standby; got %+v", got) + } + if got.AddLeg || len(got.PromoteFromStandby) != 0 || len(got.DropLegs) != 0 { + t.Errorf("coupled decrease must be a lone demote (no grow/drop); got %+v", got) + } +} + +// TestEngine_OnTick_CoupledCautiousPromoteWhenClean asserts the COUPLED INCREASE: +// a loss-free active set below the ceiling with a warm spare promotes AT MOST one +// leg (LIA's cautious coupled increase). +func TestEngine_OnTick_CoupledCautiousPromoteWhenClean(t *testing.T) { + e := New() + legs := []LegInfo{ + {Index: 0, TransportID: "t0", Kind: "stcpr", LatencyMs: 50, Alive: true}, + {Index: 1, TransportID: "t1", Kind: "stcpr", LatencyMs: 50, Alive: true}, + {Index: 2, TransportID: "t2", Kind: "stcpr", LatencyMs: 50, Alive: true}, + {Index: 3, TransportID: "s0", Kind: "stcpr", LatencyMs: 45, Alive: true, Standby: true}, + } + got := e.OnTick("coupled", legs) + if len(got.PromoteFromStandby) != 1 || got.PromoteFromStandby[0] != 3 { + t.Errorf("clean active set below the ceiling must cautiously promote the spare; got %+v", got) + } + if got.AddLeg || len(got.DemoteToStandby) != 0 || len(got.DropLegs) != 0 { + t.Errorf("cautious increase must be a lone promote; got %+v", got) + } +} + +// TestEngine_OnTick_CoupledNoGrowUnderLoss is the coupling property: even with a +// warm spare available and the active set below the ceiling, rising loss on an +// active leg FORBIDS growth — the controller sheds the lossy leg instead of +// promoting. (The loss baseline is seeded white-box so the rise reads on the very +// first tick, without an intervening clean tick consuming the spare.) +func TestEngine_OnTick_CoupledNoGrowUnderLoss(t *testing.T) { + e := New() + e.coupledPrevRetransmits["t1"] = 0 + legs := []LegInfo{ + {Index: 0, TransportID: "t0", Kind: "stcpr", LatencyMs: 50, Alive: true}, + {Index: 1, TransportID: "t1", Kind: "stcpr", LatencyMs: 50, Alive: true, Retransmits: 100}, + {Index: 2, TransportID: "t2", Kind: "stcpr", LatencyMs: 50, Alive: true}, + {Index: 3, TransportID: "s0", Kind: "stcpr", LatencyMs: 45, Alive: true, Standby: true}, + } + got := e.OnTick("coupled", legs) + if len(got.PromoteFromStandby) != 0 { + t.Errorf("coupled must NOT grow while an active leg shows rising loss (a spare is available); got %+v", got) + } + if len(got.DemoteToStandby) != 1 || got.DemoteToStandby[0] != 1 { + t.Errorf("coupled should shed the lossy leg (1) instead; got %+v", got) + } +} diff --git a/pkg/router/policy/preset/tick.go b/pkg/router/policy/preset/tick.go index 4e3a2cac32..c435d2861e 100644 --- a/pkg/router/policy/preset/tick.go +++ b/pkg/router/policy/preset/tick.go @@ -60,6 +60,13 @@ type Engine struct { ledbatEWMA map[string]float64 // per-leg EWMA-smoothed one-way-ish delay (ms) ledbatBase map[string]float64 // per-leg base (running-min smoothed) delay (ms) ledbatSeen map[string]bool // transport_ids present this tick (for GC) + + // coupled (MPTCP-style coupled congestion control) + coupledLatEWMA map[string]float64 // per-leg smoothed latency (worst-leg tiebreak) + coupledPrevRetransmits map[string]uint64 // per-leg last-tick retransmit counter (loss delta) + coupledPrevSent map[string]uint64 // per-leg last-tick sent bytes (packet-normalize loss) + coupledSeen map[string]bool // transport_ids present this tick (stale-state GC) + coupledCooldown int // ticks held steady after a grow/shed (anti-churn) } // New returns an Engine with initialized state maps and the @@ -86,6 +93,11 @@ func New() *Engine { ledbatEWMA: map[string]float64{}, ledbatBase: map[string]float64{}, ledbatSeen: map[string]bool{}, + + coupledLatEWMA: map[string]float64{}, + coupledPrevRetransmits: map[string]uint64{}, + coupledPrevSent: map[string]uint64{}, + coupledSeen: map[string]bool{}, } } @@ -103,6 +115,8 @@ func (e *Engine) OnTick(name string, legs []LegInfo) RotationAction { return e.tickElasticMux(legs) case "probe-and-prune": return e.tickProbeAndPrune(legs) + case "coupled": + return e.tickCoupled(legs) case "adaptive": return e.tickAdaptive(legs) case "ledbat": @@ -954,3 +968,155 @@ func (e *Engine) tickLedbat(legs []LegInfo) RotationAction { } return RotationAction{} } + +// --- coupled (MPTCP-style coupled congestion control) --- + +const ( + // coupledMux is the modest symmetric mux the coupled preset provisions and + // the CEILING the cautious coupled-increase grows the active set back up to. + coupledMux = 4 + // coupledFloor is the minimum active width the coupled-decrease will never + // shed below — the aggregate keeps at least this many legs carrying traffic. + coupledFloor = 2 + // coupledAlpha smooths per-leg latency (the worst-leg tiebreak signal). + coupledAlpha = 0.3 + // coupledCooldownTicks holds the active set steady for a few ticks after any + // grow/shed so a transient loss blip can't churn the mux every tick. + coupledCooldownTicks = 3 +) + +// tickCoupled is the coupled congestion controller. The two congestion signals +// are per-leg: the RETRANSMIT delta since last tick (loss, packet-normalized by +// the sent-bytes delta) and the EWMA-smoothed latency. It arbitrates at most one +// structural change per tick, in priority order: +// +// (0) no active legs -> bring one up (promote a spare, else dial) +// (1) active < floor -> restore the floor (recovery; bypasses cooldown) +// cooldown active -> hold steady (anti-churn) +// (2) any active leg's loss RISING -> COUPLED DECREASE: shed the WORST leg +// (highest loss, latency-tiebroken; never leg 0, never below the floor), +// concentrating traffic on the good legs instead of equal-spreading it +// across a lossy one. +// (3) NO active leg showing rising loss AND active < ceiling -> COUPLED +// INCREASE (LIA-cautious): promote AT MOST one warm spare. +// +// Because a shed fires the instant loss appears and a grow fires only when the +// WHOLE active set is loss-free, aggregate aggressiveness stays bounded — the +// "coupling" property. Deterministic (no time.Now/rand) for wasm parity. +func (e *Engine) tickCoupled(legs []LegInfo) RotationAction { + for k := range e.coupledSeen { + delete(e.coupledSeen, k) + } + activeCount := 0 + standbyCount := 0 + promotable := -1 + worstIdx := -1 + worstScore := -1.0 + anyRisingLoss := false + for _, l := range legs { + tid := l.TransportID + if tid != "" { + e.coupledSeen[tid] = true + } + if !l.Alive { + continue + } + if l.Standby { + standbyCount++ + if promotable == -1 || l.Index < promotable { + promotable = l.Index + } + continue + } + activeCount++ + if tid == "" { + continue + } + if l.LatencyMs > 0 { + sample := float64(l.LatencyMs) + if prev, ok := e.coupledLatEWMA[tid]; ok { + e.coupledLatEWMA[tid] = coupledAlpha*sample + (1-coupledAlpha)*prev + } else { + e.coupledLatEWMA[tid] = sample + } + } + var retransDelta, sentDelta uint64 + if prev, ok := e.coupledPrevRetransmits[tid]; ok && l.Retransmits >= prev { + retransDelta = l.Retransmits - prev + } + if prev, ok := e.coupledPrevSent[tid]; ok && l.SentBytes >= prev { + sentDelta = l.SentBytes - prev + } + e.coupledPrevRetransmits[tid] = l.Retransmits + e.coupledPrevSent[tid] = l.SentBytes + if retransDelta > 0 { + anyRisingLoss = true + } + // Loss ratio = retransmits / sent-segments this tick (a ~1KB segment unit; + // +1 avoids divide-by-zero when a leg sent nothing). Loss dominates the + // worst-leg score; smoothed latency breaks ties. Leg 0 (the primary) is + // never a shed candidate. + sentSegs := sentDelta / 1024 + lossRatio := float64(retransDelta) / float64(sentSegs+1) + score := lossRatio*1e6 + e.coupledLatEWMA[tid] + if l.Index != 0 && score > worstScore { + worstScore = score + worstIdx = l.Index + } + } + for tid := range e.coupledLatEWMA { + if !e.coupledSeen[tid] { + delete(e.coupledLatEWMA, tid) + } + } + for tid := range e.coupledPrevRetransmits { + if !e.coupledSeen[tid] { + delete(e.coupledPrevRetransmits, tid) + } + } + for tid := range e.coupledPrevSent { + if !e.coupledSeen[tid] { + delete(e.coupledPrevSent, tid) + } + } + + if e.coupledCooldown > 0 { + e.coupledCooldown-- + } + + // (0) No active legs — bring capacity up (recovery, bypasses cooldown). + if activeCount == 0 { + if promotable >= 0 { + return RotationAction{PromoteFromStandby: []int{promotable}} + } + return RotationAction{AddLeg: true} + } + // (1) Restore the floor if an active leg dropped (recovery, bypasses cooldown). + if activeCount < coupledFloor { + if promotable >= 0 { + return RotationAction{PromoteFromStandby: []int{promotable}} + } + return RotationAction{AddLeg: true} + } + // Anti-churn: hold the set steady during cooldown. + if e.coupledCooldown > 0 { + return RotationAction{} + } + + // (2) Coupled DECREASE: congestion (rising loss on any active leg) -> shed the + // worst leg so aggregate aggressiveness stays bounded. + if anyRisingLoss && activeCount > coupledFloor && worstIdx > 0 { + e.coupledCooldown = coupledCooldownTicks + if standbyCount < nodipStandbyMax { + return RotationAction{DemoteToStandby: []int{worstIdx}} + } + return RotationAction{DropLegs: []int{worstIdx}} + } + // (3) Coupled INCREASE (LIA-cautious): the whole active set is loss-free and we + // are below the ceiling -> promote at most one warm spare. + if !anyRisingLoss && activeCount < coupledMux && promotable >= 0 { + e.coupledCooldown = coupledCooldownTicks + return RotationAction{PromoteFromStandby: []int{promotable}} + } + return RotationAction{} +} diff --git a/pkg/router/policy/wasm/presets/bundle.wasm b/pkg/router/policy/wasm/presets/bundle.wasm index d7f09d68fe65f7b841998c715752357386550050..6f494149fdd837308c237c49648fcb8967617cbf 100755 GIT binary patch delta 79791 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%0A5>f|t79@g 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 Bh!y|< diff --git a/pkg/router/policy/wasm/presets/manifest.json b/pkg/router/policy/wasm/presets/manifest.json index e95fed3beb..a674893d69 100644 --- a/pkg/router/policy/wasm/presets/manifest.json +++ b/pkg/router/policy/wasm/presets/manifest.json @@ -4,6 +4,7 @@ "latency-adaptive": "latency-adaptive — mux=4 multi-hop that evicts the slowest leg each 30s (when its EWMA-smoothed latency is a >=1.5x-median outlier) until the leg set converges to low-latency disjoint paths, then holds (hysteresis-damped; no churn once converged).", "elastic-mux": "elastic-mux — AIMD scaling of the mux leg count to load: grows a leg (up to 6) when the group is saturated, releases one (down to 2) when idle.", "probe-and-prune": "probe-and-prune — periodically adds one speculative leg over a fresh path, observes its EWMA latency a few ticks, and keeps it only if it beats the current worst leg (continuous explore/exploit).", + "coupled": "coupled (experimental) — MPTCP-style coupled congestion control over a modest mux (4): weights bytes toward the best legs (auto), grows the active set cautiously (at most one promote per tick, only when NO active leg shows rising loss — LIA's coupled increase), and sheds the worst (highest-loss, latency-tiebroken) leg the instant congestion appears, so aggregate aggressiveness stays bounded and traffic concentrates on the good legs.", "adaptive": "adaptive — the app-agnostic performance+stability default (chat excepted): a single lean forward leg and a reverse mux that stays at ONE healthy leg for interactive/idle flows and only widens under sustained bulk load; holds an always-on warm-standby reserve for instant dip-free promotion, keeps gross-latency-outlier and dead legs OUT of the active mux, and rate-limits reshapes (hysteresis + cooldown) so the active set stays stable — one arbitrated action per tick.", "geo-avoid": "geo-avoid — chooses the lowest-latency route whose hops transit NONE of the countries in cli_overrides.avoid_geo (comma-separated ISO codes); defers rather than pick a violating path when none is clean.", "transport-diverse": "transport-diverse — chooses the route whose hops span the most distinct transport types (ties broken by latency), so no single transport technology failing takes the path down; seeds a mux of 2.", diff --git a/pkg/router/policy/wasm/presets/parity_test.go b/pkg/router/policy/wasm/presets/parity_test.go index 0a61771d10..4271848567 100644 --- a/pkg/router/policy/wasm/presets/parity_test.go +++ b/pkg/router/policy/wasm/presets/parity_test.go @@ -154,6 +154,8 @@ func TestDecideParity_NativeMatchesWazero(t *testing.T) { {"latency-adaptive/other", "latency-adaptive", policy.RoutingContext{App: "skychat"}, nil}, {"elastic-mux", "elastic-mux", policy.RoutingContext{App: "skysocks-client"}, nil}, {"probe-and-prune", "probe-and-prune", policy.RoutingContext{App: "skynet-client"}, nil}, + {"coupled", "coupled", policy.RoutingContext{App: "skysocks-client"}, nil}, + {"coupled/chat", "coupled", policy.RoutingContext{App: "skychat"}, nil}, {"adaptive", "adaptive", policy.RoutingContext{App: "vpn-client"}, nil}, // adaptive with real transport-kind metadata: both paths must seed the // most transport-diverse forward candidate (cand b, 2 distinct kinds). @@ -271,11 +273,30 @@ func TestTickParity_NativeMatchesWazero(t *testing.T) { {leg(0, "a", "stcpr", 40, true, false, 0), leg(1, "b", "stcpr", 40, true, true, 0), leg(2, "c", "stcpr", 40, true, true, 0)}, } + // coupled: a clean 4-wide set, then rising loss on one leg (shed), a couple of + // cooldown ticks, then a clean below-ceiling set with a warm spare (cautious + // promote) — exercises both coupled-decrease and coupled-increase. + rl := func(idx int, tid string, lat int, retrans uint64) policy.LegInfo { + return policy.LegInfo{Index: idx, TransportID: tid, Kind: "stcpr", LatencyMs: lat, Alive: true, Retransmits: retrans} + } + sb := func(idx int, tid string, lat int) policy.LegInfo { + return policy.LegInfo{Index: idx, TransportID: tid, Kind: "stcpr", LatencyMs: lat, Alive: true, Standby: true} + } + cpl := [][]policy.LegInfo{ + {rl(0, "a", 50, 0), rl(1, "b", 50, 0), rl(2, "c", 50, 0), rl(3, "d", 50, 0)}, + {rl(0, "a", 50, 0), rl(1, "b", 50, 0), rl(2, "c", 50, 500), rl(3, "d", 50, 0)}, + {rl(0, "a", 50, 0), rl(1, "b", 50, 0), rl(3, "d", 50, 0), sb(2, "c", 50)}, + {rl(0, "a", 50, 0), rl(1, "b", 50, 0), rl(3, "d", 50, 0), sb(2, "c", 50)}, + {rl(0, "a", 50, 0), rl(1, "b", 50, 0), rl(3, "d", 50, 0), sb(2, "c", 50)}, + {rl(0, "a", 50, 0), rl(1, "b", 50, 0), rl(3, "d", 50, 0), sb(2, "c", 50)}, + } + cases := []tickCase{ {"rotating-bw", "rotating-bw", rbw}, {"latency-adaptive", "latency-adaptive", la}, {"elastic-mux", "elastic-mux", em}, {"probe-and-prune", "probe-and-prune", pp}, + {"coupled", "coupled", cpl}, {"adaptive", "adaptive", ad}, {"ledbat", "ledbat", lb}, }