mirror of
https://github.com/slackhq/nebula.git
synced 2026-11-15 18:16:52 +01:00
Build multiport lanes lazily, on data-plane demand
Lanes were established for every slot as soon as the base tunnel came up, so a host with `routines: N` paid N-1 extra Noise handshakes, sessions and keepalives for every peer it talked to, including peers it exchanges a trickle with. Only routines that actually carry traffic to a peer need a lane. Add a per-slot demand flag to laneState. sendInsideMessage already loads txLanes[laneSlot] on every direct-path packet; that load missing is now the signal, and EnsureLanes only starts slots the data plane asked for. The miss path is unchanged otherwise: the packet rides the base tunnel, the same fallback used while a lane is down. noteLaneDemand load-guards its store so repeated misses on a lane-less slot are plain reads rather than a cache line ping-ponging between the routines sharing it. The demand check is EnsureLanes' last condition, so a slot that is pending or inside its backoff keeps the flag for the tick that can act on it. Consuming the flag also stops a lane whose routine went quiet from being rebuilt forever after it dies. The wire format, lane negotiation and port-offset scheme are untouched, so a lazy node interoperates with an eager one in both directions, and inbound lane handshakes from a busy peer are still accepted regardless of our own demand.
This commit is contained in:
1 parent
192d994273
commit
11528c6e02
6 files changed
+154
-11
No files matched your search
@@ -233,6 +233,13 @@ func (f *Interface) sendInsideMessage(hostinfo *HostInfo, pkt tio.Packet, nb []b
|
||||
// The pointer is only published once the lane's ConnectionState is fully
|
||||
// populated, so a non-nil Load is always usable. On lane death the slot
|
||||
// CAS-clears and traffic falls back to the base tunnel instantly.
|
||||
//
|
||||
// A miss is also how lanes get built in the first place: flagging demand
|
||||
// here is the only thing that asks the handshake manager for this slot,
|
||||
// so we pay for a lane exactly where real traffic wanted one. The
|
||||
// connection manager's next tick on this tunnel picks the flag up, which
|
||||
// bounds establishment by one check interval — until then the traffic
|
||||
// rides the base tunnel, the same fallback a dead lane uses.
|
||||
if ls := hostinfo.lanes; ls != nil && tx.laneSlot < len(ls.txLanes) {
|
||||
if lane := ls.txLanes[tx.laneSlot].Load(); lane != nil {
|
||||
if lci := lane.ConnectionState; lci != nil && lci.eKey != nil {
|
||||
@@ -241,6 +248,8 @@ func (f *Interface) sendInsideMessage(hostinfo *HostInfo, pkt tio.Packet, nb []b
|
||||
remote = lane.GetRemote()
|
||||
sendBatch = tx.lane
|
||||
}
|
||||
} else {
|
||||
ls.noteLaneDemand(tx.laneSlot)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user