lanes_test.go 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. package nebula
  2. import (
  3. "log/slog"
  4. "net/netip"
  5. "testing"
  6. "time"
  7. "github.com/gaissmai/bart"
  8. "github.com/slackhq/nebula/cert"
  9. "github.com/slackhq/nebula/config"
  10. "github.com/slackhq/nebula/firewall"
  11. "github.com/slackhq/nebula/handshake"
  12. "github.com/slackhq/nebula/header"
  13. "github.com/slackhq/nebula/overlay/overlaytest"
  14. "github.com/slackhq/nebula/overlay/tio"
  15. "github.com/slackhq/nebula/test"
  16. "github.com/slackhq/nebula/udp"
  17. "github.com/stretchr/testify/assert"
  18. "github.com/stretchr/testify/require"
  19. )
  20. var (
  21. testMyAddr = netip.MustParseAddr("10.0.0.1")
  22. testPeerAddr = netip.MustParseAddr("10.0.0.2")
  23. )
  24. // newTestLaneSet builds a lane set from a real handshake result so the sessions
  25. // it derives hold usable keys.
  26. func newTestLaneSet(t *testing.T, r *handshake.Result, myLanes int, peerPorts, peerBase, peerTxLanes uint32) *laneSet {
  27. t.Helper()
  28. r.PeerPortCount = peerPorts
  29. r.PeerBasePort = peerBase
  30. r.PeerTxLanes = peerTxLanes
  31. return newLaneSet(r, myLanes, testMyAddr, testPeerAddr)
  32. }
  33. // laneSessionFor derives lane s's session and installs it, standing in for the
  34. // data-plane call that would normally be the first to need it.
  35. func laneSessionFor(t *testing.T, ls *laneSet, s int) *ConnectionState {
  36. t.Helper()
  37. cs, err := ls.session(s)
  38. require.NoError(t, err)
  39. require.NotNil(t, cs)
  40. return cs
  41. }
  42. func newTestLaneHostInfo(t *testing.T, r *handshake.Result, ls *laneSet) *HostInfo {
  43. t.Helper()
  44. cs, err := newConnectionStateFromResult(r)
  45. require.NoError(t, err)
  46. hi := &HostInfo{
  47. vpnAddrs: []netip.Addr{testPeerAddr},
  48. localIndexId: 100,
  49. remoteIndexId: 200,
  50. remotes: NewRemoteList([]netip.Addr{testPeerAddr}, nil),
  51. HandshakePacket: map[uint8][]byte{},
  52. ConnectionState: cs,
  53. lanes: ls,
  54. }
  55. hi.SetRemote(netip.MustParseAddrPort("192.0.2.1:4242"))
  56. return hi
  57. }
  58. func TestLanePortOffset(t *testing.T) {
  59. a := netip.MustParseAddr("10.0.0.1")
  60. b := netip.MustParseAddr("10.0.0.2")
  61. // Deterministic and in range.
  62. for _, count := range []uint16{1, 2, 3, 4, 16, 256} {
  63. o := lanePortOffset(a, b, count)
  64. assert.Equal(t, o, lanePortOffset(a, b, count), "count %d not deterministic", count)
  65. assert.Less(t, o, count, "count %d out of range", count)
  66. }
  67. assert.Equal(t, uint16(0), lanePortOffset(a, b, 0), "zero port count")
  68. // The two sides' rotations cancel when port counts match, preserving the
  69. // lane-i-reverses-lane-j conntrack pairing.
  70. for _, count := range []uint16{2, 3, 4, 7, 16} {
  71. for i := range 32 {
  72. peer := netip.AddrFrom4([4]byte{192, 0, 2, byte(i)})
  73. oA := lanePortOffset(a, peer, count)
  74. oB := lanePortOffset(peer, a, count)
  75. assert.Equal(t, uint16(0), (oA+oB)%count,
  76. "offsets don't cancel for peer %s count %d", peer, count)
  77. }
  78. }
  79. // Distinct small peers land on distinct rotations of a big peer's range,
  80. // not all on the same first ports.
  81. const bigPeerPorts = 16
  82. distinct := map[uint16]struct{}{}
  83. for i := range 64 {
  84. client := netip.AddrFrom4([4]byte{192, 0, 2, byte(i)})
  85. distinct[lanePortOffset(client, a, bigPeerPorts)] = struct{}{}
  86. }
  87. assert.GreaterOrEqual(t, len(distinct), 8, "64 clients only produced %d distinct offsets", len(distinct))
  88. }
  89. func TestLaneTargetPort(t *testing.T) {
  90. ls := &laneSet{peerBasePort: 4242, peerPortCount: 4}
  91. // No rotation: lane i targets base+i, wrapping past the peer's range.
  92. for i, want := range map[int]uint16{1: 4243, 2: 4244, 3: 4245, 5: 4243} {
  93. assert.Equal(t, want, ls.laneTargetPortLocked(i), "lane %d", i)
  94. }
  95. // Rotation shifts the whole mapping; the wrapped lane lands on the base
  96. // port itself, which is a valid distinct 4-tuple (our source port differs).
  97. ls.portOffset = 3
  98. for i, want := range map[int]uint16{1: 4242, 2: 4243, 3: 4244} {
  99. assert.Equal(t, want, ls.laneTargetPortLocked(i), "rotated lane %d", i)
  100. }
  101. // Fewer peer ports than local lanes: rotation still spreads across all of
  102. // the peer's ports.
  103. ls = &laneSet{peerBasePort: 4242, peerPortCount: 2, portOffset: 1}
  104. assert.Equal(t, uint16(4242), ls.laneTargetPortLocked(1))
  105. assert.Equal(t, uint16(4243), ls.laneTargetPortLocked(2))
  106. }
  107. // A lane's keys are derived, not negotiated, so the whole design rests on the
  108. // two sides landing on the same pair without exchanging anything.
  109. func TestLaneKeyDerivationSymmetry(t *testing.T) {
  110. initR, respR := runTestHandshake(t)
  111. initLS := newTestLaneSet(t, initR, 4, 4, 4242, 4)
  112. respLS := newTestLaneSet(t, respR, 4, 4, 4242, 4)
  113. require.Len(t, initLS.sessions, 4)
  114. assert.Nil(t, initLS.sessions[0].Load(), "lane 0 is the base session, not a derived one")
  115. nb := make([]byte, 12)
  116. for s := 1; s < 4; s++ {
  117. out := header.EncodeLane(make([]byte, 0, mtu), header.Version, header.Message, 0, 200, 1, uint8(s))
  118. ct, err := laneSessionFor(t, initLS, s).eKey.EncryptDanger(out, out, []byte("lane payload"), 1, nb)
  119. require.NoError(t, err)
  120. pt, err := laneSessionFor(t, respLS, s).Decrypt(test.NewLogger(), 1, ct, nb)
  121. require.NoError(t, err, "lane %d keys did not match", s)
  122. assert.Equal(t, []byte("lane payload"), pt)
  123. }
  124. // Distinct lanes get distinct keys: lane 2's session must not open lane 1's
  125. // ciphertext, or the header's lane index would be forgeable in effect.
  126. out := header.EncodeLane(make([]byte, 0, mtu), header.Version, header.Message, 0, 200, 7, 1)
  127. ct, err := laneSessionFor(t, initLS, 1).eKey.EncryptDanger(out, out, []byte("lane payload"), 7, nb)
  128. require.NoError(t, err)
  129. _, err = laneSessionFor(t, respLS, 2).Decrypt(test.NewLogger(), 7, ct, nb)
  130. assert.Error(t, err)
  131. }
  132. func TestNewLaneSetSizing(t *testing.T) {
  133. initR, _ := runTestHandshake(t)
  134. // A peer with no multiport advert gets no lanes at all.
  135. assert.Nil(t, newLaneSet(&handshake.Result{}, 4, testMyAddr, testPeerAddr))
  136. // One lane means only the base tunnel, which is not a lane set.
  137. assert.Nil(t, newLaneSet(&handshake.Result{PeerPortCount: 4, PeerTxLanes: 1}, 1, testMyAddr, testPeerAddr))
  138. // Sessions cover both directions: enough for everything the peer may send,
  139. // even though we may only send on a few.
  140. ls := newTestLaneSet(t, initR, 2, 8, 4242, 6)
  141. assert.Len(t, ls.sessions, 6, "sessions must cover the peer's tx lanes")
  142. assert.Equal(t, 2, ls.txLanes, "we may only send on our own lanes")
  143. // The peer's advert sizes the session table but nothing else. Its lane count
  144. // is its own choice, so it must not be able to make us allocate per-lane tx
  145. // state we will never use.
  146. assert.Len(t, ls.txAddr, 2)
  147. assert.Len(t, ls.demand, 2)
  148. assert.Len(t, ls.probe, 2)
  149. // Nothing is derived up front, for the same reason.
  150. for s := range ls.sessions {
  151. assert.Nil(t, ls.sessions[s].Load(), "lane %d derived before anything needed it", s)
  152. }
  153. // Every lane starts demanded so the first traffic tick probes them all: a
  154. // lane that only comes up after its flows do is a lane the flows never move
  155. // onto, because the kernel has pinned them to the queue they started on.
  156. ls = newTestLaneSet(t, initR, 4, 4, 4242, 4)
  157. for s := 1; s < ls.txLanes; s++ {
  158. assert.True(t, ls.demand[s].Load(), "lane %d not demanded at creation", s)
  159. }
  160. // Our tx lanes are clamped to the ports the peer actually bound: a lane
  161. // aimed past the peer's range would land on some unrelated socket.
  162. ls = newTestLaneSet(t, initR, 8, 3, 4242, 8)
  163. assert.Equal(t, 3, ls.txLanes)
  164. assert.Len(t, ls.sessions, 8)
  165. }
  166. // The handshake log lines carry the negotiated lanes, so an operator can tell a
  167. // peer that got none from one that was never asked.
  168. func TestLaneLogAttr(t *testing.T) {
  169. initR, _ := runTestHandshake(t)
  170. // Not running multiport: an empty attr, which slog drops entirely.
  171. assert.Equal(t, slog.Attr{}, laneLogAttr(0, nil))
  172. // Running multiport against a peer that isn't: zeros, not silence.
  173. assert.Equal(t, m{"tx": 0, "sessions": 0}, laneLogAttr(4, nil).Value.Any())
  174. ls := newTestLaneSet(t, initR, 2, 8, 4242, 6)
  175. attr := laneLogAttr(2, ls)
  176. assert.Equal(t, "lanes", attr.Key)
  177. assert.Equal(t, m{
  178. "tx": 2,
  179. "sessions": 6,
  180. "peerBasePort": uint16(4242),
  181. "peerPorts": uint16(8),
  182. "portOffset": ls.portOffset,
  183. }, attr.Value.Any())
  184. }
  185. // The RX path must not cache a session for a lane until a packet on it has
  186. // actually decrypted, or a spoofer naming lanes at random could make us hold a
  187. // replay window and two cipher states per lane without authenticating anything.
  188. func TestLaneSessionRxDerivation(t *testing.T) {
  189. initR, respR := runTestHandshake(t)
  190. respLS := newTestLaneSet(t, respR, 4, 4, 4242, 4)
  191. hi := newTestLaneHostInfo(t, respR, respLS)
  192. ci, cached, err := hi.laneSession(2)
  193. require.NoError(t, err)
  194. require.NotNil(t, ci)
  195. assert.False(t, cached, "the first packet on a lane derives, it does not hit")
  196. assert.Nil(t, respLS.sessions[2].Load(), "an unauthenticated packet must not install a session")
  197. // The lane the peer really is using decrypts, and that is what installs it.
  198. nb := make([]byte, 12)
  199. out := header.EncodeLane(make([]byte, 0, mtu), header.Version, header.Message, 0, 200, 1, 2)
  200. ct, err := laneSessionFor(t, newTestLaneSet(t, initR, 4, 4, 4242, 4), 2).
  201. eKey.EncryptDanger(out, out, []byte("real lane traffic"), 1, nb)
  202. require.NoError(t, err)
  203. pt, err := ci.Decrypt(test.NewLogger(), 1, ct, nb)
  204. require.NoError(t, err)
  205. assert.Equal(t, []byte("real lane traffic"), pt)
  206. respLS.installSession(test.NewLogger(), 2, ci, 1)
  207. assert.Same(t, ci, respLS.sessions[2].Load())
  208. // Now it is a hit, and the replay window the decrypt above advanced is the
  209. // one the next packet sees.
  210. got, cached, err := hi.laneSession(2)
  211. require.NoError(t, err)
  212. assert.True(t, cached)
  213. assert.Same(t, ci, got)
  214. // A racing install loses rather than swapping the session out, which would
  215. // throw away the replay window the live one has been accumulating. The loser's
  216. // packet still has to be marked seen on the winner, or dropping its session
  217. // would make that one counter replayable.
  218. other, err := newLaneConnectionState(&respLS.material, 2)
  219. require.NoError(t, err)
  220. require.True(t, ci.window.Check(test.NewLogger(), 7), "counter 7 seen before the race")
  221. respLS.installSession(test.NewLogger(), 2, other, 7)
  222. assert.Same(t, ci, respLS.sessions[2].Load())
  223. assert.False(t, ci.window.Check(test.NewLogger(), 7),
  224. "the loser's counter was not carried to the surviving window")
  225. }
  226. func TestLaneTxGate(t *testing.T) {
  227. initR, _ := runTestHandshake(t)
  228. ls := newTestLaneSet(t, initR, 4, 4, 4242, 4)
  229. for s := range ls.demand {
  230. // Creation seeds demand on every lane; start from cold so this test can
  231. // tell what the TX path itself raises.
  232. ls.demand[s].Store(false)
  233. }
  234. // A down lane hands back nothing and raises demand, which is what gets it
  235. // re-probed after a demotion.
  236. ci, addr := ls.txLane(1)
  237. assert.Nil(t, ci)
  238. assert.False(t, addr.IsValid())
  239. assert.True(t, ls.demand[1].Load())
  240. assert.False(t, ls.demand[2].Load(), "demand raised on an untouched lane")
  241. // An up lane with no session derived yet cannot happen — the probe that
  242. // promoted it derived one — but it must fall back rather than send in the
  243. // clear if it ever does.
  244. want := netip.MustParseAddrPort("192.0.2.1:4243")
  245. ls.txAddr[1].Store(&want)
  246. ci, _ = ls.txLane(1)
  247. assert.Nil(t, ci)
  248. // Promotion publishes the session and destination together.
  249. sess := laneSessionFor(t, ls, 1)
  250. ls.demand[1].Store(false)
  251. ci, addr = ls.txLane(1)
  252. assert.Same(t, sess, ci)
  253. assert.Equal(t, want, addr)
  254. assert.False(t, ls.demand[1].Load(), "a hit must not raise demand")
  255. // Lane 0 is the base tunnel and lanes at or above txLanes are receive-only.
  256. ci, _ = ls.txLane(0)
  257. assert.Nil(t, ci)
  258. ci, _ = ls.txLane(4)
  259. assert.Nil(t, ci)
  260. }
  261. func TestLaneSessionLookup(t *testing.T) {
  262. initR, _ := runTestHandshake(t)
  263. ls := newTestLaneSet(t, initR, 3, 4, 4242, 3)
  264. hi := newTestLaneHostInfo(t, initR, ls)
  265. assertNoLane := func(s uint8, msg string) {
  266. t.Helper()
  267. ci, cached, err := hi.laneSession(s)
  268. require.NoError(t, err)
  269. assert.Nil(t, ci, msg)
  270. assert.False(t, cached, msg)
  271. }
  272. assertNoLane(0, "lane 0 is the base session")
  273. assertNoLane(3, "a lane beyond what this tunnel covers")
  274. assertNoLane(255, "a lane beyond what this tunnel covers")
  275. // An already-derived lane is returned as a hit.
  276. sess := laneSessionFor(t, ls, 2)
  277. ci, cached, err := hi.laneSession(2)
  278. require.NoError(t, err)
  279. assert.Same(t, sess, ci)
  280. assert.True(t, cached)
  281. // A peer without lanes answers nil for every lane rather than panicking.
  282. bare := &HostInfo{}
  283. ci, _, err = bare.laneSession(1)
  284. require.NoError(t, err)
  285. assert.Nil(t, ci)
  286. }
  287. func TestMaxMessageCounter(t *testing.T) {
  288. initR, _ := runTestHandshake(t)
  289. ls := newTestLaneSet(t, initR, 3, 4, 4242, 3)
  290. hi := newTestLaneHostInfo(t, initR, ls)
  291. hi.ConnectionState.messageCounter.Store(5)
  292. assert.Equal(t, uint64(5), hi.maxMessageCounter())
  293. // A lane past the base is what the rehandshake threshold has to notice: the
  294. // base counter would sit still while the lane burns through its nonces.
  295. laneSessionFor(t, ls, 2).messageCounter.Store(9000)
  296. assert.Equal(t, uint64(9000), hi.maxMessageCounter())
  297. assert.Equal(t, uint64(0), (&HostInfo{}).maxMessageCounter())
  298. }
  299. func TestLaneRetryDelay(t *testing.T) {
  300. assert.Equal(t, laneRetryBase, laneRetryDelay(0))
  301. assert.Equal(t, 2*laneRetryBase, laneRetryDelay(1))
  302. assert.Equal(t, laneRetryMax, laneRetryDelay(laneMaxFails), "backoff must saturate")
  303. }
  304. func newLaneTestInterface(hostMap *HostMap) *Interface {
  305. l := test.NewLogger()
  306. lh := newTestLighthouse()
  307. cs := &CertState{
  308. initiatingVersion: cert.Version1,
  309. privateKey: []byte{},
  310. v1Cert: &dummyCert{version: cert.Version1},
  311. v1Credential: nil,
  312. }
  313. ifce := &Interface{
  314. hostMap: hostMap,
  315. inside: &overlaytest.NoopTun{},
  316. outside: &udp.NoopConn{},
  317. firewall: &Firewall{},
  318. lightHouse: lh,
  319. pki: &PKI{},
  320. handshakeManager: NewHandshakeManager(l, hostMap, lh, &udp.NoopConn{}, defaultHandshakeConfig),
  321. myVpnNetworksTable: new(bart.Lite),
  322. messageMetrics: newMessageMetricsOnlyRecvError(),
  323. writers: []udp.Conn{&udp.NoopConn{}, &udp.NoopConn{}, &udp.NoopConn{}, &udp.NoopConn{}},
  324. // One socket per port keeps writers indexed by lane, which is what most of
  325. // these tests want; the tests that care about the group layout set their own.
  326. routinesPerPort: 1,
  327. l: l,
  328. }
  329. ifce.pki.cs.Store(cs)
  330. conf := config.NewC(l)
  331. punchy := NewPunchyFromConfig(l, conf, nil)
  332. cm := newConnectionManagerFromConfig(l, conf, hostMap, punchy)
  333. cm.intf = ifce
  334. ifce.connectionManager = cm
  335. ifce.handshakeManager.f = ifce
  336. return ifce
  337. }
  338. // The full TX lifecycle of a lane: demand -> probe -> ack -> up, then an
  339. // unanswered keepalive -> demoted.
  340. func TestLaneProbeLifecycle(t *testing.T) {
  341. hostMap := newHostMap(test.NewLogger())
  342. ifce := newLaneTestInterface(hostMap)
  343. initR, _ := runTestHandshake(t)
  344. ls := newTestLaneSet(t, initR, 4, 4, 5353, 4)
  345. hi := newTestLaneHostInfo(t, initR, ls)
  346. nb := make([]byte, 12)
  347. out := make([]byte, mtu)
  348. now := time.Now()
  349. // No demand: nothing is probed, so a peer we barely talk to costs nothing
  350. // beyond its base tunnel. (Creation seeds demand on every lane, so clear it
  351. // to get at the no-demand case.)
  352. for s := range ls.demand {
  353. ls.demand[s].Store(false)
  354. }
  355. ifce.probeLanes(hi, now, nb, out)
  356. ls.mu.Lock()
  357. for s := 1; s < 4; s++ {
  358. assert.True(t, ls.probe[s].sentAt.IsZero(), "lane %d probed without demand", s)
  359. }
  360. ls.mu.Unlock()
  361. // Demand on lane 1 alone probes lane 1 alone, aimed at the peer's port for
  362. // that lane.
  363. ls.demand[1].Store(true)
  364. ifce.probeLanes(hi, now, nb, out)
  365. ls.mu.Lock()
  366. require.False(t, ls.probe[1].sentAt.IsZero(), "demand did not produce a probe")
  367. assert.True(t, ls.probe[2].sentAt.IsZero())
  368. wantPort := ls.laneTargetPortLocked(1)
  369. assert.Equal(t, netip.AddrPortFrom(netip.MustParseAddr("192.0.2.1"), wantPort), ls.probe[1].target)
  370. gen := ls.probe[1].gen
  371. assert.False(t, ls.demand[1].Load(), "the probe did not consume the demand")
  372. ls.mu.Unlock()
  373. // The lane stays down until the ack lands, and a stale generation cannot
  374. // bring it up.
  375. assert.Nil(t, ls.txAddr[1].Load())
  376. _, promoted := ls.noteAck(1, gen+1, now)
  377. assert.False(t, promoted, "an ack for a superseded probe promoted the lane")
  378. assert.Nil(t, ls.txAddr[1].Load())
  379. // The matching ack promotes it, and the destination is the probed target.
  380. ackTarget, promoted := ls.noteAck(1, gen, now)
  381. assert.True(t, promoted)
  382. assert.Equal(t, netip.AddrPortFrom(netip.MustParseAddr("192.0.2.1"), wantPort), ackTarget)
  383. addr := ls.txAddr[1].Load()
  384. require.NotNil(t, addr)
  385. assert.Equal(t, netip.AddrPortFrom(netip.MustParseAddr("192.0.2.1"), wantPort), *addr)
  386. // A second ack is a keepalive, not a promotion.
  387. ls.mu.Lock()
  388. ls.probe[1].sentAt = now
  389. ls.mu.Unlock()
  390. _, promoted = ls.noteAck(1, gen, now)
  391. assert.False(t, promoted)
  392. assert.NotNil(t, ls.txAddr[1].Load())
  393. // An up lane is left alone until the keepalive comes due.
  394. ifce.probeLanes(hi, now, nb, out)
  395. ls.mu.Lock()
  396. assert.True(t, ls.probe[1].sentAt.IsZero(), "an up lane was re-probed early")
  397. ls.mu.Unlock()
  398. // Past the keepalive it re-proves its path...
  399. now = now.Add(laneKeepalive + time.Second)
  400. ifce.probeLanes(hi, now, nb, out)
  401. ls.mu.Lock()
  402. require.False(t, ls.probe[1].sentAt.IsZero(), "keepalive did not probe")
  403. ls.mu.Unlock()
  404. assert.NotNil(t, ls.txAddr[1].Load(), "lane demoted before its probe aged out")
  405. // ...and an unanswered keepalive demotes it with backoff, so the routine
  406. // falls back to the base tunnel.
  407. now = now.Add(laneProbeTimeout + time.Second)
  408. ifce.probeLanes(hi, now, nb, out)
  409. assert.Nil(t, ls.txAddr[1].Load(), "unanswered keepalive did not demote the lane")
  410. ls.mu.Lock()
  411. assert.Equal(t, uint8(1), ls.probe[1].fails)
  412. assert.True(t, ls.probe[1].retryAt.After(now))
  413. ls.mu.Unlock()
  414. // The backoff holds even with fresh demand.
  415. ls.demand[1].Store(true)
  416. ifce.probeLanes(hi, now, nb, out)
  417. ls.mu.Lock()
  418. assert.True(t, ls.probe[1].sentAt.IsZero(), "backoff was ignored")
  419. ls.mu.Unlock()
  420. }
  421. // A lane aims at its own peer port and nothing else. There is no fallback to the
  422. // peer's base port: sharing that destination would cost the peer the receive
  423. // spread lanes exist to create, so an unreachable lane port just means this lane
  424. // stays down and its flows ride the base tunnel.
  425. func TestLaneProbeAlwaysTargetsItsOwnPort(t *testing.T) {
  426. hostMap := newHostMap(test.NewLogger())
  427. ifce := newLaneTestInterface(hostMap)
  428. initR, _ := runTestHandshake(t)
  429. ls := newTestLaneSet(t, initR, 4, 4, 5353, 4)
  430. hi := newTestLaneHostInfo(t, initR, ls)
  431. nb := make([]byte, 12)
  432. out := make([]byte, mtu)
  433. now := time.Now()
  434. ls.mu.Lock()
  435. lanePort := ls.laneTargetPortLocked(1)
  436. ls.mu.Unlock()
  437. require.NotEqual(t, ls.peerBasePort, lanePort, "this test needs a lane that isn't aimed at the base port")
  438. // Repeated failures never move the target off the lane's own port.
  439. for i := 0; i < 4; i++ {
  440. ls.demand[1].Store(true)
  441. ifce.probeLanes(hi, now, nb, out)
  442. ls.mu.Lock()
  443. require.False(t, ls.probe[1].sentAt.IsZero(), "the lane was not probed")
  444. assert.Equal(t, lanePort, ls.probe[1].target.Port(), "probe %d left the lane port", i)
  445. gen := ls.probe[1].gen
  446. ls.mu.Unlock()
  447. // Age the probe out, then wait out the backoff for the next attempt.
  448. now = now.Add(laneProbeTimeout + time.Second)
  449. ifce.probeLanes(hi, now, nb, out)
  450. require.Nil(t, ls.txAddr[1].Load())
  451. assert.False(t, promotedByAck(ls, 1, gen, now), "an aged-out probe was still promotable")
  452. now = now.Add(laneRetryMax + time.Second)
  453. }
  454. // It comes up on that port, and the keepalive re-proves the same one.
  455. ls.demand[1].Store(true)
  456. ifce.probeLanes(hi, now, nb, out)
  457. ls.mu.Lock()
  458. gen := ls.probe[1].gen
  459. ls.mu.Unlock()
  460. target, promoted := ls.noteAck(1, gen, now)
  461. require.True(t, promoted)
  462. assert.Equal(t, lanePort, target.Port())
  463. now = now.Add(laneKeepalive + time.Second)
  464. ifce.probeLanes(hi, now, nb, out)
  465. ls.mu.Lock()
  466. require.False(t, ls.probe[1].sentAt.IsZero(), "the keepalive did not probe")
  467. assert.Equal(t, lanePort, ls.probe[1].target.Port(), "the keepalive left the lane port")
  468. ls.mu.Unlock()
  469. // And a demotion returns to probing that same port.
  470. now = now.Add(laneProbeTimeout + time.Second)
  471. ifce.probeLanes(hi, now, nb, out)
  472. require.Nil(t, ls.txAddr[1].Load(), "the unanswered keepalive did not demote the lane")
  473. now = now.Add(laneRetryMax + time.Second)
  474. ls.demand[1].Store(true)
  475. ifce.probeLanes(hi, now, nb, out)
  476. ls.mu.Lock()
  477. require.False(t, ls.probe[1].sentAt.IsZero(), "the lane was not retried")
  478. assert.Equal(t, lanePort, ls.probe[1].target.Port())
  479. ls.mu.Unlock()
  480. }
  481. // promotedByAck is noteAck's boolean alone, for assertions that only care whether
  482. // an ack could bring the lane up.
  483. func promotedByAck(ls *laneSet, s int, gen uint8, now time.Time) bool {
  484. _, promoted := ls.noteAck(s, gen, now)
  485. return promoted
  486. }
  487. // A roam is a new path with no derivable relationship to the old lane ports, so
  488. // every lane has to be rebuilt rather than moved.
  489. func TestLaneProbeRoamResets(t *testing.T) {
  490. hostMap := newHostMap(test.NewLogger())
  491. ifce := newLaneTestInterface(hostMap)
  492. initR, _ := runTestHandshake(t)
  493. ls := newTestLaneSet(t, initR, 4, 4, 5353, 4)
  494. hi := newTestLaneHostInfo(t, initR, ls)
  495. now := time.Now()
  496. nb := make([]byte, 12)
  497. out := make([]byte, mtu)
  498. ls.demand[1].Store(true)
  499. ifce.probeLanes(hi, now, nb, out)
  500. ls.mu.Lock()
  501. gen := ls.probe[1].gen
  502. ls.mu.Unlock()
  503. _, promoted := ls.noteAck(1, gen, now)
  504. require.True(t, promoted)
  505. require.NotNil(t, ls.txAddr[1].Load())
  506. // New remote address: the lane is taken down, not retargeted.
  507. hi.SetRemote(netip.MustParseAddrPort("198.51.100.7:4242"))
  508. ifce.probeLanes(hi, now, nb, out)
  509. assert.Nil(t, ls.txAddr[1].Load(), "lane survived a roam")
  510. ls.mu.Lock()
  511. assert.Zero(t, ls.probe[1].fails, "a roam is not a lane failure")
  512. assert.Equal(t, netip.MustParseAddr("198.51.100.7"), ls.peerAddr)
  513. ls.mu.Unlock()
  514. // A late ack for the probe sent before the roam must not promote the lane
  515. // on the new path, so the generation has to carry across the reset.
  516. ls.demand[1].Store(true)
  517. ifce.probeLanes(hi, now, nb, out)
  518. _, promoted = ls.noteAck(1, gen, now)
  519. assert.False(t, promoted, "an ack from before the roam promoted the lane")
  520. assert.Nil(t, ls.txAddr[1].Load())
  521. // Relayed (no direct remote) means no lanes at all.
  522. ls.demand[1].Store(true)
  523. ifce.probeLanes(hi, now, nb, out)
  524. ls.mu.Lock()
  525. gen = ls.probe[1].gen
  526. ls.mu.Unlock()
  527. _, promoted = ls.noteAck(1, gen, now)
  528. require.True(t, promoted)
  529. hi.SetRemote(netip.AddrPort{})
  530. ifce.probeLanes(hi, now, nb, out)
  531. assert.Nil(t, ls.txAddr[1].Load(), "lane survived losing the direct path")
  532. }
  533. // A peer answers lane traffic it can't place with a recv_error from the lane
  534. // socket it arrived on, so the spoof guard must accept one from an up lane's
  535. // target and still refuse one from anywhere else.
  536. func TestHandleRecvErrorFromLane(t *testing.T) {
  537. hostMap := newHostMap(test.NewLogger())
  538. ifce := newLaneTestInterface(hostMap)
  539. initR, _ := runTestHandshake(t)
  540. ls := newTestLaneSet(t, initR, 4, 4, 4242, 4)
  541. hi := newTestLaneHostInfo(t, initR, ls)
  542. hostMap.unlockedAddHostInfo(hi, ifce)
  543. now := time.Now()
  544. ifce.probeLanes(hi, now, make([]byte, 12), make([]byte, mtu))
  545. ls.mu.Lock()
  546. gen := ls.probe[1].gen
  547. ls.mu.Unlock()
  548. laneAddr, promoted := ls.noteAck(1, gen, now)
  549. require.True(t, promoted)
  550. require.NotEqual(t, hi.GetRemote(), laneAddr)
  551. h := &header.H{Type: header.RecvError, RemoteIndex: hi.remoteIndexId}
  552. ifce.handleRecvError(netip.MustParseAddrPort("192.0.2.1:9999"), h)
  553. require.NotNil(t, hostMap.QueryReverseIndex(hi.remoteIndexId), "a recv_error from an unknown port closed the tunnel")
  554. ifce.handleRecvError(laneAddr, h)
  555. assert.Nil(t, hostMap.QueryReverseIndex(hi.remoteIndexId), "a recv_error from an up lane's target was ignored")
  556. }
  557. // An idle tunnel is not probed, so its lanes' keepalives can't keep it alive.
  558. // Probing resumes on the first tick that sees traffic.
  559. func TestIdleTunnelSkipsLaneProbes(t *testing.T) {
  560. hostMap := newHostMap(test.NewLogger())
  561. ifce := newLaneTestInterface(hostMap)
  562. initR, _ := runTestHandshake(t)
  563. ls := newTestLaneSet(t, initR, 4, 4, 4242, 4)
  564. hi := newTestLaneHostInfo(t, initR, ls)
  565. hostMap.unlockedAddHostInfo(hi, ifce)
  566. // An empty pool fails every cert, which with pki.disconnect_invalid off
  567. // leaves the tunnel up.
  568. ifce.pki.caPool.Store(cert.NewCAPool())
  569. cm := ifce.connectionManager
  570. p := []byte("")
  571. nb := make([]byte, 12)
  572. out := make([]byte, mtu)
  573. probed := func() bool {
  574. ls.mu.Lock()
  575. defer ls.mu.Unlock()
  576. return !ls.probe[1].sentAt.IsZero()
  577. }
  578. // Adding the tunnel records outbound traffic; drop it so the tick sees idle.
  579. hi.takeTraffic()
  580. cm.doTrafficCheck(hi.localIndexId, p, nb, out, time.Now())
  581. assert.False(t, probed(), "an idle tunnel was probed")
  582. cm.In(hi)
  583. cm.doTrafficCheck(hi.localIndexId, p, nb, out, time.Now())
  584. assert.True(t, probed(), "a tunnel with traffic was not probed")
  585. }
  586. // A lane probe is answered on the base tunnel, echoing the header's lane, so a
  587. // peer cannot get us to vouch for a lane it never probed.
  588. func TestHandleLaneProbe(t *testing.T) {
  589. hostMap := newHostMap(test.NewLogger())
  590. ifce := newLaneTestInterface(hostMap)
  591. initR, respR := runTestHandshake(t)
  592. ls := newTestLaneSet(t, respR, 4, 4, 4242, 4)
  593. hi := newTestLaneHostInfo(t, respR, ls)
  594. rxc := &rxContext{nb: make([]byte, 12), scratch: make([]byte, mtu)}
  595. sent := &recordingUdpConn{}
  596. ifce.writers = []udp.Conn{sent, &udp.NoopConn{}, &udp.NoopConn{}, &udp.NoopConn{}}
  597. // The payload's lane is ignored in favour of the header's.
  598. ifce.handleLaneProbe(hi, 2, []byte{3, 42}, rxc)
  599. require.Len(t, sent.bufs, 1, "the ack must ride the base tunnel's socket")
  600. h := &header.H{}
  601. require.NoError(t, h.Parse(sent.bufs[0]))
  602. assert.Equal(t, header.Test, h.Type)
  603. assert.Equal(t, header.LaneProbeAck, h.Subtype)
  604. assert.Equal(t, uint8(0), h.Lane(), "the ack is base-tunnel traffic")
  605. assert.False(t, hi.sentSinceCheck(), "a probe ack must not count as tunnel traffic")
  606. pt, err := laneSessionFor(t, newTestLaneSet(t, initR, 4, 4, 4242, 4), 1).dKey.DecryptDanger(
  607. nil, sent.bufs[0][:header.Len], sent.bufs[0][header.Len:], h.MessageCounter, make([]byte, 12))
  608. _ = pt
  609. assert.Error(t, err, "the ack must not be readable with a lane key")
  610. // A probe claiming lane 0 or with a truncated payload is answered with
  611. // nothing at all.
  612. sent.bufs = nil
  613. ifce.handleLaneProbe(hi, 0, []byte{1, 2}, rxc)
  614. ifce.handleLaneProbe(hi, 1, []byte{1}, rxc)
  615. assert.Empty(t, sent.bufs)
  616. }
  617. func TestHandleLaneProbeAck(t *testing.T) {
  618. hostMap := newHostMap(test.NewLogger())
  619. ifce := newLaneTestInterface(hostMap)
  620. initR, _ := runTestHandshake(t)
  621. ls := newTestLaneSet(t, initR, 4, 4, 5353, 4)
  622. hi := newTestLaneHostInfo(t, initR, ls)
  623. now := time.Now()
  624. ls.demand[1].Store(true)
  625. ifce.probeLanes(hi, now, make([]byte, 12), make([]byte, mtu))
  626. ls.mu.Lock()
  627. gen := ls.probe[1].gen
  628. ls.mu.Unlock()
  629. // A short or out-of-range ack is ignored, and a peer without lanes does not
  630. // panic the handler.
  631. ifce.handleLaneProbeAck(hi, []byte{1})
  632. ifce.handleLaneProbeAck(hi, []byte{99, gen})
  633. ifce.handleLaneProbeAck(&HostInfo{}, []byte{1, gen})
  634. assert.Nil(t, ls.txAddr[1].Load())
  635. ifce.handleLaneProbeAck(hi, []byte{1, gen})
  636. assert.NotNil(t, ls.txAddr[1].Load())
  637. }
  638. // recordingUdpConn records what was written to it, one datagram per write.
  639. type recordingUdpConn struct {
  640. udp.NoopConn
  641. bufs [][]byte
  642. dsts []netip.AddrPort
  643. }
  644. func (c *recordingUdpConn) WriteTo(b []byte, addr netip.AddrPort) error {
  645. c.bufs = append(c.bufs, append([]byte(nil), b...))
  646. c.dsts = append(c.dsts, addr)
  647. return nil
  648. }
  649. // recordingBatchConn is a udp.Conn that records the batches flushed to it, so a
  650. // test can see which socket a packet left on.
  651. type recordingBatchConn struct {
  652. udp.NoopConn
  653. bufs [][]byte
  654. dsts []netip.AddrPort
  655. }
  656. func (c *recordingBatchConn) WriteBatch(bufs [][]byte, addrs []netip.AddrPort) (int, error) {
  657. for i := range bufs {
  658. c.bufs = append(c.bufs, append([]byte(nil), bufs[i]...))
  659. c.dsts = append(c.dsts, addrs[i])
  660. }
  661. return len(bufs), nil
  662. }
  663. // laneOfFlow is what the TX path computes to pick a lane, without needing a
  664. // promoted lane to observe it.
  665. func laneOfFlow(ls *laneSet, p *firewall.Packet) int {
  666. return int((laneFlowHash(p) + uint32(ls.laneBias)) % uint32(ls.txLanes))
  667. }
  668. func testFlow(port uint16) *firewall.Packet {
  669. return &firewall.Packet{
  670. LocalAddr: testMyAddr,
  671. RemoteAddr: testPeerAddr,
  672. LocalPort: port,
  673. RemotePort: 443,
  674. Protocol: 6,
  675. }
  676. }
  677. // flowForLane finds a flow that hashes onto lane s, so a test can aim traffic at
  678. // a specific lane.
  679. func flowForLane(t *testing.T, ls *laneSet, s int) *firewall.Packet {
  680. t.Helper()
  681. for port := uint16(1024); port < 4096; port++ {
  682. p := testFlow(port)
  683. if laneOfFlow(ls, p) == s {
  684. return p
  685. }
  686. }
  687. t.Fatalf("no flow hashes onto lane %d", s)
  688. return nil
  689. }
  690. func TestSendInsideMessageLaneSwap(t *testing.T) {
  691. hostMap := newHostMap(test.NewLogger())
  692. ifce := newLaneTestInterface(hostMap)
  693. ifce.multiport = true
  694. ifce.laneCount = 4
  695. conns := []*recordingBatchConn{{}, {}, {}, {}}
  696. ifce.writers = []udp.Conn{conns[0], conns[1], conns[2], conns[3]}
  697. initR, respR := runTestHandshake(t)
  698. ls := newTestLaneSet(t, initR, 4, 4, 5353, 4)
  699. hi := newTestLaneHostInfo(t, initR, ls)
  700. peerLS := newTestLaneSet(t, respR, 4, 4, 4242, 4)
  701. tx := ifce.newTxQueue(1)
  702. pkt := tio.Packet{Bytes: []byte{0x45, 0, 0, 4, 1, 2, 3, 4}}
  703. nb := make([]byte, 12)
  704. flow1 := flowForLane(t, ls, 1)
  705. for s := range ls.demand {
  706. ls.demand[s].Store(false)
  707. }
  708. // A down lane rides the base tunnel and asks for a probe.
  709. ifce.sendInsideMessage(hi, pkt, flow1, nb, tx)
  710. tx.flush(ifce)
  711. require.Len(t, conns[0].bufs, 1)
  712. assert.Empty(t, conns[1].bufs)
  713. assert.True(t, ls.demand[1].Load(), "a miss did not raise demand")
  714. assert.False(t, ls.demand[2].Load(), "demand raised on a lane nothing hashed onto")
  715. h := &header.H{}
  716. require.NoError(t, h.Parse(conns[0].bufs[0]))
  717. assert.Equal(t, uint8(0), h.Lane())
  718. // Once the lane is up, a flow hashing onto it rides the lane session, the
  719. // lane socket and the lane's destination, tagged with the lane index.
  720. // Promotion normally happens on the ack of a probe, which is also what
  721. // derived the session, so stand both up here.
  722. laneRemote := netip.MustParseAddrPort("192.0.2.1:5354")
  723. laneSessionFor(t, ls, 1)
  724. ls.txAddr[1].Store(&laneRemote)
  725. ls.demand[1].Store(false)
  726. ifce.sendInsideMessage(hi, pkt, flow1, nb, tx)
  727. tx.flush(ifce)
  728. require.Len(t, conns[1].bufs, 1)
  729. assert.Equal(t, laneRemote, conns[1].dsts[0])
  730. assert.False(t, ls.demand[1].Load(), "a hit raised demand")
  731. require.NoError(t, h.Parse(conns[1].bufs[0]))
  732. assert.Equal(t, uint8(1), h.Lane())
  733. assert.Equal(t, hi.remoteIndexId, h.RemoteIndex)
  734. // And the peer's derived lane-1 session is what opens it.
  735. pt, err := laneSessionFor(t, peerLS, 1).Decrypt(test.NewLogger(), h.MessageCounter, conns[1].bufs[0], nb)
  736. require.NoError(t, err)
  737. assert.Equal(t, pkt.Bytes, pt)
  738. // Another routine sending the same flow rides the same lane socket and
  739. // session: the lane follows the flow, not the routine.
  740. tx2 := ifce.newTxQueue(2)
  741. ifce.sendInsideMessage(hi, pkt, flow1, nb, tx2)
  742. tx2.flush(ifce)
  743. require.Len(t, conns[1].bufs, 2)
  744. require.NoError(t, h.Parse(conns[1].bufs[1]))
  745. assert.Equal(t, uint8(1), h.Lane())
  746. // A flow that hashes onto lane 0 stays on the base tunnel even with lane 1
  747. // up: a full share of flows belongs there.
  748. ifce.sendInsideMessage(hi, pkt, flowForLane(t, ls, 0), nb, tx)
  749. tx.flush(ifce)
  750. require.Len(t, conns[0].bufs, 2)
  751. assert.Equal(t, hi.GetRemote(), conns[0].dsts[1])
  752. require.NoError(t, h.Parse(conns[0].bufs[1]))
  753. assert.Equal(t, uint8(0), h.Lane())
  754. // Demotion falls back to the base tunnel on the very next packet.
  755. ls.txAddr[1].Store(nil)
  756. ifce.sendInsideMessage(hi, pkt, flow1, nb, tx)
  757. tx.flush(ifce)
  758. require.Len(t, conns[0].bufs, 3)
  759. require.Len(t, conns[1].bufs, 2)
  760. }
  761. // Without multiport nothing about the send path changes: every socket shares one
  762. // port under SO_REUSEPORT, so a routine keeps writing to its own, and there are
  763. // no lane batches at all. A peer that negotiated no lanes is the same story on a
  764. // node that does run multiport, except that base traffic owes its 4-tuple to
  765. // socket 0.
  766. func TestTxQueueWithoutLanes(t *testing.T) {
  767. hostMap := newHostMap(test.NewLogger())
  768. ifce := newLaneTestInterface(hostMap)
  769. conns := []*recordingBatchConn{{}, {}, {}, {}}
  770. ifce.writers = []udp.Conn{conns[0], conns[1], conns[2], conns[3]}
  771. initR, _ := runTestHandshake(t)
  772. hi := newTestLaneHostInfo(t, initR, nil)
  773. pkt := tio.Packet{Bytes: []byte{0x45, 0, 0, 4, 1, 2, 3, 4}}
  774. nb := make([]byte, 12)
  775. flow := testFlow(1234)
  776. tx := ifce.newTxQueue(2)
  777. assert.Empty(t, tx.lane, "a queue with no lanes must not hold lane batches")
  778. require.Len(t, tx.live, 1)
  779. ifce.sendInsideMessage(hi, pkt, flow, nb, tx)
  780. tx.flush(ifce)
  781. assert.Len(t, conns[2].bufs, 1, "routine 2 did not send on its own socket")
  782. assert.Empty(t, conns[0].bufs)
  783. // Multiport on, but this peer has no lanes: socket 0, lane 0, one batch.
  784. ifce.multiport = true
  785. ifce.laneCount = 4
  786. tx = ifce.newTxQueue(2)
  787. require.Len(t, tx.live, 1)
  788. ifce.sendInsideMessage(hi, pkt, flow, nb, tx)
  789. tx.flush(ifce)
  790. require.Len(t, conns[0].bufs, 1, "base traffic left a socket other than 0")
  791. assert.Len(t, conns[2].bufs, 1)
  792. h := &header.H{}
  793. require.NoError(t, h.Parse(conns[0].bufs[0]))
  794. assert.Equal(t, uint8(0), h.Lane())
  795. assert.Len(t, tx.live, 1, "a lane batch was built for a peer with no lanes")
  796. }
  797. // `routines` is per port, so a port's sockets are a group sharing it through
  798. // SO_REUSEPORT and every routine has a sibling of its own on every port. Pin the
  799. // arithmetic that turns (queue, lane) into one of them.
  800. func TestLaneSockGroupLayout(t *testing.T) {
  801. hostMap := newHostMap(test.NewLogger())
  802. ifce := newLaneTestInterface(hostMap)
  803. // Two routines per port over three ports: writers[s*2+r] is the r'th socket
  804. // on port listen.port+s.
  805. ifce.routinesPerPort = 2
  806. ifce.routines = 6
  807. ifce.laneCount = 3
  808. // Off, every socket is on the one port, so a routine keeps writing to its own
  809. // and any of them can carry any lane.
  810. for q := 0; q < ifce.routines; q++ {
  811. assert.Equal(t, q, ifce.egressSock(q))
  812. for s := 0; s < ifce.laneCount; s++ {
  813. assert.Equal(t, q, ifce.laneSock(q, s))
  814. }
  815. }
  816. ifce.multiport = true
  817. for q := 0; q < ifce.routines; q++ {
  818. // Base traffic is lane 0's port, and each routine has its own socket
  819. // there rather than sharing one with the other five.
  820. assert.Equal(t, q%2, ifce.egressSock(q), "queue %d", q)
  821. for s := 0; s < ifce.laneCount; s++ {
  822. assert.Equal(t, s*2+q%2, ifce.laneSock(q, s), "queue %d lane %d", q, s)
  823. }
  824. }
  825. // Sibling routines land on different sockets of the same port, so a lane's
  826. // port is served by its whole group and not by one socket.
  827. assert.NotEqual(t, ifce.laneSock(0, 2), ifce.laneSock(1, 2))
  828. assert.Equal(t, ifce.laneSock(0, 2), ifce.laneSock(2, 2), "queues 0 and 2 share a group position")
  829. }
  830. // The lane batches a routine builds must flush to that routine's own sockets, not
  831. // to whatever socket happens to be indexed by the lane.
  832. func TestTxQueueLaneBatchesFollowTheGroup(t *testing.T) {
  833. hostMap := newHostMap(test.NewLogger())
  834. ifce := newLaneTestInterface(hostMap)
  835. ifce.multiport = true
  836. ifce.routinesPerPort = 2
  837. ifce.routines = 4
  838. ifce.laneCount = 2
  839. conns := []*recordingBatchConn{{}, {}, {}, {}}
  840. ifce.writers = []udp.Conn{conns[0], conns[1], conns[2], conns[3]}
  841. initR, _ := runTestHandshake(t)
  842. ls := newTestLaneSet(t, initR, 2, 2, 5353, 2)
  843. hi := newTestLaneHostInfo(t, initR, ls)
  844. laneSessionFor(t, ls, 1)
  845. laneRemote := netip.MustParseAddrPort("192.0.2.1:5354")
  846. ls.txAddr[1].Store(&laneRemote)
  847. pkt := tio.Packet{Bytes: []byte{0x45, 0, 0, 4, 1, 2, 3, 4}}
  848. nb := make([]byte, 12)
  849. flow1 := flowForLane(t, ls, 1)
  850. // Routine 1 is the second socket in each group, so its lane 1 traffic leaves
  851. // writers[1*2+1].
  852. tx := ifce.newTxQueue(1)
  853. ifce.sendInsideMessage(hi, pkt, flow1, nb, tx)
  854. tx.flush(ifce)
  855. require.Len(t, conns[3].bufs, 1, "lane 1 did not leave routine 1's socket on the lane port")
  856. assert.Equal(t, laneRemote, conns[3].dsts[0])
  857. assert.Empty(t, conns[2].bufs)
  858. // Routine 0 sends the same flow out the other socket on that same port.
  859. tx0 := ifce.newTxQueue(0)
  860. ifce.sendInsideMessage(hi, pkt, flow1, nb, tx0)
  861. tx0.flush(ifce)
  862. require.Len(t, conns[2].bufs, 1, "sibling routine shared a socket instead of its own")
  863. assert.Len(t, conns[3].bufs, 1)
  864. }
  865. // One routine has to be able to reach every lane, since the kernel decides which
  866. // routine sees a flow and it may well hand one routine everything.
  867. func TestTxLaneForFlowSpread(t *testing.T) {
  868. initR, _ := runTestHandshake(t)
  869. ls := newTestLaneSet(t, initR, 4, 4, 5353, 4)
  870. seen := map[int]int{}
  871. for port := uint16(1024); port < 1224; port++ {
  872. s := laneOfFlow(ls, testFlow(port))
  873. require.Less(t, s, ls.txLanes)
  874. seen[s]++
  875. }
  876. assert.Len(t, seen, 4, "200 flows did not reach all four lanes: %v", seen)
  877. for s, n := range seen {
  878. assert.Greater(t, n, 10, "lane %d got a negligible share of flows", s)
  879. }
  880. // A flow's lane is a function of its 5-tuple alone, so it never moves
  881. // mid-flow.
  882. p := testFlow(1234)
  883. assert.Equal(t, laneOfFlow(ls, p), laneOfFlow(ls, p))
  884. // A tunnel with nothing but the base lane always answers lane 0.
  885. one := newTestLaneSet(t, initR, 1, 1, 5353, 4)
  886. s, ci, addr := one.txLaneForFlow(p)
  887. assert.Zero(t, s)
  888. assert.Nil(t, ci)
  889. assert.False(t, addr.IsValid())
  890. s, ci, _ = (*laneSet)(nil).txLaneForFlow(p)
  891. assert.Zero(t, s)
  892. assert.Nil(t, ci)
  893. }
  894. // The two ends of a flow have to pick partner lanes, or the flow's two
  895. // directions use unrelated 4-tuples instead of exact reverses and neither side's
  896. // traffic arrives through the conntrack entry the other's probe opened.
  897. func TestLaneFlowSymmetry(t *testing.T) {
  898. initR, respR := runTestHandshake(t)
  899. // Our side is the low address; the peer builds the same pair reversed.
  900. const ourBase, peerBase = 4242, 5353
  901. ourLS := newTestLaneSet(t, initR, 4, 4, peerBase, 4)
  902. respR.PeerPortCount, respR.PeerBasePort, respR.PeerTxLanes = 4, ourBase, 4
  903. peerLS := newLaneSet(respR, 4, testPeerAddr, testMyAddr)
  904. require.NotNil(t, peerLS)
  905. require.Equal(t, uint16(0), ourLS.laneBias, "the low address hashes straight")
  906. partnered := 0
  907. for port := uint16(1024); port < 1124; port++ {
  908. p := testFlow(port)
  909. reverse := &firewall.Packet{
  910. LocalAddr: p.RemoteAddr, RemoteAddr: p.LocalAddr,
  911. LocalPort: p.RemotePort, RemotePort: p.LocalPort,
  912. Protocol: p.Protocol,
  913. }
  914. ours := laneOfFlow(ourLS, p)
  915. theirs := laneOfFlow(peerLS, reverse)
  916. require.Equal(t, (ours+int(ourLS.portOffset))%4, theirs,
  917. "flow on port %d: our lane %d is not partnered with their lane %d", port, ours, theirs)
  918. if ours == 0 || theirs == 0 {
  919. // The lane that lands on the other side's base port has no partner
  920. // lane; that flow rides one side's base tunnel. See lanePortOffset.
  921. continue
  922. }
  923. partnered++
  924. // Our source and destination ports are the reverse of theirs.
  925. ourLS.mu.Lock()
  926. peerLS.mu.Lock()
  927. assert.Equal(t, uint16(peerBase+theirs), ourLS.laneTargetPortLocked(ours), "flow on port %d", port)
  928. assert.Equal(t, uint16(ourBase+ours), peerLS.laneTargetPortLocked(theirs), "flow on port %d", port)
  929. peerLS.mu.Unlock()
  930. ourLS.mu.Unlock()
  931. }
  932. assert.Greater(t, partnered, 0, "no flow landed on a partnered lane")
  933. }
  934. // Regression: deleting a hostinfo whose pending entry is NOT the one recorded
  935. // in vpnIps must not evict a concurrently pending handshake for that address.
  936. func TestHandshakeManagerVpnIpsIdentityDelete(t *testing.T) {
  937. l := test.NewLogger()
  938. hostMap := newHostMap(l)
  939. lh := newTestLighthouse()
  940. hm := NewHandshakeManager(l, hostMap, lh, &udp.NoopConn{}, defaultHandshakeConfig)
  941. vpnIp := netip.MustParseAddr("172.1.1.4")
  942. pendingBase := hm.StartHandshake(vpnIp, nil)
  943. require.NotNil(t, pendingBase)
  944. other := &HostInfo{vpnAddrs: []netip.Addr{vpnIp}, localIndexId: 999}
  945. hm.DeleteHostInfo(other)
  946. // The pending base handshake must still be tracked.
  947. assert.Equal(t, pendingBase, hm.QueryVpnAddr(vpnIp))
  948. // And deleting the actual owner still works.
  949. hm.DeleteHostInfo(pendingBase)
  950. assert.Nil(t, hm.QueryVpnAddr(vpnIp))
  951. }