ecn: CE-mark on decap when the receive queue runs deep (nebula-as-AQM)

The tunnel's real bottleneck queue - the UDP receive buffer feeding the
decrypt loop - is invisible to every kernel AQM, so under overload it
regulates ECN-capable flows with tail-drop loss like it's 1993. Sample
SK_MEMINFO once per recvmmsg batch (tunnels.ecn_mark_threshold, fraction
of rcvbuf, 0=off) and treat depth beyond the threshold as an outer CE:
the existing RFC 6040 fold then CE-marks ECT inner packets and senders
back off without loss.
This commit is contained in:
JackDoan
2026-07-14 16:57:05 -05:00
parent 6783c90e72
commit d3779b6a39
5 changed files with 90 additions and 6 deletions
+9 -1
View File
@@ -573,7 +573,15 @@ func (f *Interface) handleOutsideMessagePacket(hostinfo *HostInfo, out []byte, s
// underlay into the inner header before firewall + TUN write. Other
// outer codepoints are advisory only — we keep the inner unchanged.
if f.ecnEnabled.Load() {
applyOuterECN(out, meta.OuterECN, hostinfo, f.l)
outerECN := meta.OuterECN
if meta.QueueCongested {
// nebula-as-AQM: our own receive queue is the congested hop on
// this path and no kernel AQM can see it. Depth beyond the
// marking threshold is treated as CE so ECT senders back off
// before the queue regulates by tail-drop instead.
outerECN = ecnCE
}
applyOuterECN(out, outerECN, hostinfo, f.l)
}
err := newPacket(out, true, fwPacket)