@@ -27,7 +27,7 @@ func newTestBaseHostInfo(vpnIp netip.Addr, localIdx, remoteIdx uint32, laneCount
2727 HandshakePacket : map [uint8 ][]byte {},
2828 }
2929 base .SetRemote (netip .MustParseAddrPort ("192.0.2.1:4242" ))
30- base .lanes = newLaneState (laneCount , uint16 (laneCount ), 4242 )
30+ base .lanes = newLaneState (laneCount , uint16 (laneCount ), 4242 , 0 )
3131 return base
3232}
3333
@@ -47,6 +47,62 @@ func newTestLaneHostInfo(base *HostInfo, laneIndex uint16, localIdx, remoteIdx u
4747 return lane
4848}
4949
50+ func TestLanePortOffset (t * testing.T ) {
51+ a := netip .MustParseAddr ("10.0.0.1" )
52+ b := netip .MustParseAddr ("10.0.0.2" )
53+
54+ // Deterministic and in range.
55+ for _ , count := range []uint16 {1 , 2 , 3 , 4 , 16 , 256 } {
56+ o := lanePortOffset (a , b , count )
57+ assert .Equal (t , o , lanePortOffset (a , b , count ), "count %d not deterministic" , count )
58+ assert .Less (t , o , count , "count %d out of range" , count )
59+ }
60+ assert .Equal (t , uint16 (0 ), lanePortOffset (a , b , 0 ), "zero port count" )
61+
62+ // The two sides' rotations cancel when port counts match, preserving the
63+ // lane-i-reverses-lane-j conntrack pairing.
64+ for _ , count := range []uint16 {2 , 3 , 4 , 7 , 16 } {
65+ for i := range 32 {
66+ peer := netip .AddrFrom4 ([4 ]byte {192 , 0 , 2 , byte (i )})
67+ oA := lanePortOffset (a , peer , count )
68+ oB := lanePortOffset (peer , a , count )
69+ assert .Equal (t , uint16 (0 ), (oA + oB )% count ,
70+ "offsets don't cancel for peer %s count %d" , peer , count )
71+ }
72+ }
73+
74+ // Distinct small peers land on distinct rotations of a big peer's range,
75+ // not all on the same first ports.
76+ const bigPeerPorts = 16
77+ distinct := map [uint16 ]struct {}{}
78+ for i := range 64 {
79+ client := netip .AddrFrom4 ([4 ]byte {192 , 0 , 2 , byte (i )})
80+ distinct [lanePortOffset (client , a , bigPeerPorts )] = struct {}{}
81+ }
82+ assert .GreaterOrEqual (t , len (distinct ), 8 , "64 clients only produced %d distinct offsets" , len (distinct ))
83+ }
84+
85+ func TestLaneTargetPort (t * testing.T ) {
86+ // No rotation: lane i targets base+i, wrapping past the peer's range.
87+ ls := newLaneState (4 , 4 , 4242 , 0 )
88+ for i , want := range map [int ]uint16 {1 : 4243 , 2 : 4244 , 3 : 4245 , 5 : 4243 } {
89+ assert .Equal (t , want , ls .laneTargetPort (i ), "lane %d" , i )
90+ }
91+
92+ // Rotation shifts the whole mapping; the wrapped lane lands on the base
93+ // port itself, which is a valid distinct 4-tuple (our source port differs).
94+ ls = newLaneState (4 , 4 , 4242 , 3 )
95+ for i , want := range map [int ]uint16 {1 : 4242 , 2 : 4243 , 3 : 4244 } {
96+ assert .Equal (t , want , ls .laneTargetPort (i ), "rotated lane %d" , i )
97+ }
98+
99+ // Fewer peer ports than local lanes: rotation still spreads across all of
100+ // the peer's ports.
101+ ls = newLaneState (16 , 2 , 4242 , 1 )
102+ assert .Equal (t , uint16 (4242 ), ls .laneTargetPort (1 ))
103+ assert .Equal (t , uint16 (4243 ), ls .laneTargetPort (2 ))
104+ }
105+
50106func TestLaneHostmapLifecycle (t * testing.T ) {
51107 l := test .NewLogger ()
52108 hostMap := newHostMap (l )
0 commit comments