Skip to content

feat(skysocks): re-dial dead multi-tunnels + reliable sequential diversification - #4216

Merged
0pcom merged 1 commit into
skycoin:developfrom
0pcom:feat/multitunnel-redial
Aug 26, 2026
Merged

feat(skysocks): re-dial dead multi-tunnels + reliable sequential diversification#4216
0pcom merged 1 commit into
skycoin:developfrom
0pcom:feat/multitunnel-redial

Conversation

@0pcom

@0pcom 0pcom commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Keep N healthy tunnels in the multi-tunnel skysocks client so bandwidth-aggregation width does not bleed down over time. The keepalive loop previously only SKIPPED a dead tunnel (pickSession routes around it) and never replaced one, so a long-lived --tunnels N client decayed toward a single tunnel and lost the aggregation.

The Client now stores the target N and, when a tunnel dies and the live count falls below N (but at least one survives), re-dials a fresh DISJOINT replacement via a callback the app wires in (SetTunnelRedial closes over the same diversify=true dial the initial extra tunnels use, so the visor steers the replacement off the survivors' first-hop transports, #4214). Re-dial is bounded: one in-flight attempt (atomic CAS guard) plus a back-off after consecutive failures until the next death re-arms it, so a persistently unreachable exit does not spin. N==1 never re-dials — its lone tunnel's death is total collapse, still owned by the app's --reconnect runCycle — so the default path is byte-identical.

Sequential diversification is reliable without a router change or an added delay: the visor registers each tunnel's primary route group (with its first-hop transport in rg.tps) into rgsNs synchronously inside saveRouteGroupRules, before the dial RPC returns; #4209 defers only auxiliary mux legs, which skysocks tunnels never request. Because the extra-tunnel loop dials sequentially, tunnel i is always visible to tunnel i+1's sibling-exclusion scan.

Throughput-based eviction of a slow-but-alive tunnel (the "drop the underperforming" half of docs/mux_aggregation_rfc.md step 4) is deferred: it needs the gigabit validation rig to tune the slow-leg threshold. This change is liveness-only.

Builds on #4213/#4214/#4215. Unit tests cover: one dead tunnel triggers exactly one re-dial that restores the count; the in-flight guard suppresses a concurrent re-dial; N==1 / all-closed / no-callback never re-dial; and the failure back-off + reset. go test ./pkg/skysocks/ -race, go vet, and golangci-lint on the touched files are clean.

…rsification

Keep N healthy tunnels in the multi-tunnel skysocks client so the aggregation
width does not bleed down over time. Previously the keepalive loop only SKIPPED
a dead tunnel (pickSession routes around it); it never replaced one, so a
long-lived --tunnels N client decayed toward a single tunnel and lost the
bandwidth aggregation.

The Client now stores the target N and, when a tunnel dies and the live count
falls below N (but at least one survives), re-dials a fresh DISJOINT replacement
via a callback the app wires in (SetTunnelRedial closes over the same
diversify=true dialServer path the initial extra tunnels use, so the visor steers
the replacement off the survivors' first-hop transports, skycoin#4214). Re-dial is
bounded: a single in-flight attempt (atomic CAS guard) and a back-off after
consecutive failures until the next tunnel death re-arms it, so a persistently
unreachable exit does not spin. N==1 never re-dials — its lone tunnel's death is
total collapse, still owned by the app's --reconnect runCycle — so the default
path is byte-identical.

Sequential diversification is reliable without a router change or an added delay:
the visor registers each tunnel's primary route group (with its first-hop
transport) into rgsNs synchronously inside saveRouteGroupRules, before the dial
RPC returns; skycoin#4209 defers only auxiliary mux legs, which skysocks tunnels never
request. Because the extra-tunnel loop dials sequentially, tunnel i is always
visible to tunnel i+1's sibling-exclusion scan. Documented at both sites.

Throughput-based eviction of a slow-but-alive tunnel (the "drop the
underperforming" half of RFC step 4) is deferred: it needs the gigabit
validation rig to tune the slow-leg threshold. This change is liveness-only.
@0pcom
0pcom merged commit 3b891eb into skycoin:develop Aug 26, 2026
12 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant