examples/config.yml still described lanes as extra tunnels with their own
handshakes, built lazily per routine. Rewrite it for lanes as sessions derived
from the base tunnel, and say that multiport.lanes only bounds sending.
In design/multiport.md, correct the partner-lane pairing (our lane s pairs
with the peer's lane s+portOffset, which laneBias lines up), the asymmetric
host example, the retry backoff, which reader owns what, the full-path
diagram, the demand-after-reset story and the metric descriptions.
Drop comments left over from earlier iterations: base traffic on "socket 0",
lanes picked by routine, lane handshakes, and multiport defaulting on.
- Ignore a lane advert with a zero base port or a range running past 65535,
with a warning, instead of aiming lanes at ports that wrapped.
- Warn once when a lane that has never come up misses 3 probes in a row.
Until now that was silent above debug, including the common case of a
firewall that only opens the base port.
- Don't probe lanes on a tunnel idle in both directions, and don't count lane
probes or their acks as tunnel traffic. A lane's own keepalive was keeping
idle tunnels from ever being dropped by tunnels.drop_inactive.
- Accept a recv_error from an up lane's target. The peer answers lane traffic
from the lane socket it arrived on, and the spoof guard only accepted the
base remote, so recv_errors for lane traffic were ignored.
- Keep the probe generation across a lane reset, so an ack for a probe sent
before a roam can't promote the lane on the new path.
- Bring handshake.proto in line with payload.go: field 3 is reserved and
TxLanes is field 4.
Describe what a lane is, the grouped socket layout, negotiation and port
pairing, how a lane comes up, how a flow stays on one lane and one routine
(including the kernel tun queue feedback loop that forces the lane to come
from the flow hash rather than the routine index), and every level at which
multiport falls back to the old single-port behavior.