userspace_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package wgengine
  4. import (
  5. "fmt"
  6. "net/netip"
  7. "reflect"
  8. "testing"
  9. "go4.org/mem"
  10. "tailscale.com/cmd/testwrapper/flakytest"
  11. "tailscale.com/net/dns"
  12. "tailscale.com/net/netaddr"
  13. "tailscale.com/net/tstun"
  14. "tailscale.com/tailcfg"
  15. "tailscale.com/tstest"
  16. "tailscale.com/tstime/mono"
  17. "tailscale.com/types/key"
  18. "tailscale.com/types/netmap"
  19. "tailscale.com/wgengine/router"
  20. "tailscale.com/wgengine/wgcfg"
  21. )
  22. func TestNoteReceiveActivity(t *testing.T) {
  23. now := mono.Time(123456)
  24. var logBuf tstest.MemLogger
  25. confc := make(chan bool, 1)
  26. gotConf := func() bool {
  27. select {
  28. case <-confc:
  29. return true
  30. default:
  31. return false
  32. }
  33. }
  34. e := &userspaceEngine{
  35. timeNow: func() mono.Time { return now },
  36. recvActivityAt: map[key.NodePublic]mono.Time{},
  37. logf: logBuf.Logf,
  38. tundev: new(tstun.Wrapper),
  39. testMaybeReconfigHook: func() { confc <- true },
  40. trimmedNodes: map[key.NodePublic]bool{},
  41. }
  42. ra := e.recvActivityAt
  43. nk := key.NewNode().Public()
  44. // Activity on an untracked key should do nothing.
  45. e.noteRecvActivity(nk)
  46. if len(ra) != 0 {
  47. t.Fatalf("unexpected growth in map: now has %d keys; want 0", len(ra))
  48. }
  49. if logBuf.Len() != 0 {
  50. t.Fatalf("unexpected log write (and thus activity): %s", logBuf.Bytes())
  51. }
  52. // Now track it, but don't mark it trimmed, so shouldn't update.
  53. ra[nk] = 0
  54. e.noteRecvActivity(nk)
  55. if len(ra) != 1 {
  56. t.Fatalf("unexpected growth in map: now has %d keys; want 1", len(ra))
  57. }
  58. if got := ra[nk]; got != now {
  59. t.Fatalf("time in map = %v; want %v", got, now)
  60. }
  61. if gotConf() {
  62. t.Fatalf("unexpected reconfig")
  63. }
  64. // Now mark it trimmed and expect an update.
  65. e.trimmedNodes[nk] = true
  66. e.noteRecvActivity(nk)
  67. if len(ra) != 1 {
  68. t.Fatalf("unexpected growth in map: now has %d keys; want 1", len(ra))
  69. }
  70. if got := ra[nk]; got != now {
  71. t.Fatalf("time in map = %v; want %v", got, now)
  72. }
  73. if !gotConf() {
  74. t.Fatalf("didn't get expected reconfig")
  75. }
  76. }
  77. func TestUserspaceEngineReconfig(t *testing.T) {
  78. e, err := NewFakeUserspaceEngine(t.Logf, 0)
  79. if err != nil {
  80. t.Fatal(err)
  81. }
  82. t.Cleanup(e.Close)
  83. ue := e.(*userspaceEngine)
  84. routerCfg := &router.Config{}
  85. for _, nodeHex := range []string{
  86. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  87. "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
  88. } {
  89. nm := &netmap.NetworkMap{
  90. Peers: []*tailcfg.Node{
  91. {
  92. Key: nkFromHex(nodeHex),
  93. },
  94. },
  95. }
  96. nk, err := key.ParseNodePublicUntyped(mem.S(nodeHex))
  97. if err != nil {
  98. t.Fatal(err)
  99. }
  100. cfg := &wgcfg.Config{
  101. Peers: []wgcfg.Peer{
  102. {
  103. PublicKey: nk,
  104. AllowedIPs: []netip.Prefix{
  105. netip.PrefixFrom(netaddr.IPv4(100, 100, 99, 1), 32),
  106. },
  107. },
  108. },
  109. }
  110. e.SetNetworkMap(nm)
  111. err = e.Reconfig(cfg, routerCfg, &dns.Config{}, nil)
  112. if err != nil {
  113. t.Fatal(err)
  114. }
  115. wantRecvAt := map[key.NodePublic]mono.Time{
  116. nkFromHex(nodeHex): 0,
  117. }
  118. if got := ue.recvActivityAt; !reflect.DeepEqual(got, wantRecvAt) {
  119. t.Errorf("wrong recvActivityAt\n got: %v\nwant: %v\n", got, wantRecvAt)
  120. }
  121. wantTrimmedNodes := map[key.NodePublic]bool{
  122. nkFromHex(nodeHex): true,
  123. }
  124. if got := ue.trimmedNodes; !reflect.DeepEqual(got, wantTrimmedNodes) {
  125. t.Errorf("wrong wantTrimmedNodes\n got: %v\nwant: %v\n", got, wantTrimmedNodes)
  126. }
  127. }
  128. }
  129. func TestUserspaceEnginePortReconfig(t *testing.T) {
  130. flakytest.Mark(t, "https://github.com/tailscale/tailscale/issues/2855")
  131. const defaultPort = 49983
  132. // Keep making a wgengine until we find an unused port
  133. var ue *userspaceEngine
  134. for i := 0; i < 100; i++ {
  135. attempt := uint16(defaultPort + i)
  136. e, err := NewFakeUserspaceEngine(t.Logf, attempt)
  137. if err != nil {
  138. t.Fatal(err)
  139. }
  140. ue = e.(*userspaceEngine)
  141. if ue.magicConn.LocalPort() == attempt {
  142. break
  143. }
  144. ue.Close()
  145. ue = nil
  146. }
  147. if ue == nil {
  148. t.Fatal("could not create a wgengine with a specific port")
  149. }
  150. t.Cleanup(ue.Close)
  151. startingPort := ue.magicConn.LocalPort()
  152. nodeKey, err := key.ParseNodePublicUntyped(mem.S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
  153. if err != nil {
  154. t.Fatal(err)
  155. }
  156. cfg := &wgcfg.Config{
  157. Peers: []wgcfg.Peer{
  158. {
  159. PublicKey: nodeKey,
  160. AllowedIPs: []netip.Prefix{
  161. netip.PrefixFrom(netaddr.IPv4(100, 100, 99, 1), 32),
  162. },
  163. },
  164. },
  165. }
  166. routerCfg := &router.Config{}
  167. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}, nil); err != nil {
  168. t.Fatal(err)
  169. }
  170. if got := ue.magicConn.LocalPort(); got != startingPort {
  171. t.Errorf("no debug setting changed local port to %d from %d", got, startingPort)
  172. }
  173. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}, &tailcfg.Debug{RandomizeClientPort: true}); err != nil {
  174. t.Fatal(err)
  175. }
  176. if got := ue.magicConn.LocalPort(); got == startingPort {
  177. t.Errorf("debug setting did not change local port from %d", startingPort)
  178. }
  179. lastPort := ue.magicConn.LocalPort()
  180. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}, nil); err != nil {
  181. t.Fatal(err)
  182. }
  183. if startingPort == defaultPort {
  184. // Only try this if we managed to bind defaultPort the first time.
  185. // Otherwise, assume someone else on the computer is using defaultPort
  186. // and so Reconfig would have caused magicSockt to bind some other port.
  187. if got := ue.magicConn.LocalPort(); got != defaultPort {
  188. t.Errorf("debug setting did not change local port from %d to %d", startingPort, defaultPort)
  189. }
  190. }
  191. if got := ue.magicConn.LocalPort(); got == lastPort {
  192. t.Errorf("Reconfig did not change local port from %d", lastPort)
  193. }
  194. }
  195. func nkFromHex(hex string) key.NodePublic {
  196. if len(hex) != 64 {
  197. panic(fmt.Sprintf("%q is len %d; want 64", hex, len(hex)))
  198. }
  199. k, err := key.ParseNodePublicUntyped(mem.S(hex[:64]))
  200. if err != nil {
  201. panic(fmt.Sprintf("%q is not hex: %v", hex, err))
  202. }
  203. return k
  204. }
  205. // an experiment to see if genLocalAddrFunc was worth it. As of Go
  206. // 1.16, it still very much is. (30-40x faster)
  207. func BenchmarkGenLocalAddrFunc(b *testing.B) {
  208. la1 := netip.MustParseAddr("1.2.3.4")
  209. la2 := netip.MustParseAddr("::4")
  210. lanot := netip.MustParseAddr("5.5.5.5")
  211. var x bool
  212. b.Run("map1", func(b *testing.B) {
  213. b.ReportAllocs()
  214. b.ResetTimer()
  215. m := map[netip.Addr]bool{
  216. la1: true,
  217. }
  218. for i := 0; i < b.N; i++ {
  219. x = m[la1]
  220. x = m[lanot]
  221. }
  222. })
  223. b.Run("map2", func(b *testing.B) {
  224. b.ReportAllocs()
  225. b.ResetTimer()
  226. m := map[netip.Addr]bool{
  227. la1: true,
  228. la2: true,
  229. }
  230. for i := 0; i < b.N; i++ {
  231. x = m[la1]
  232. x = m[lanot]
  233. }
  234. })
  235. b.Run("or1", func(b *testing.B) {
  236. b.ReportAllocs()
  237. b.ResetTimer()
  238. f := func(t netip.Addr) bool {
  239. return t == la1
  240. }
  241. for i := 0; i < b.N; i++ {
  242. x = f(la1)
  243. x = f(lanot)
  244. }
  245. })
  246. b.Run("or2", func(b *testing.B) {
  247. b.ReportAllocs()
  248. b.ResetTimer()
  249. f := func(t netip.Addr) bool {
  250. return t == la1 || t == la2
  251. }
  252. for i := 0; i < b.N; i++ {
  253. x = f(la1)
  254. x = f(lanot)
  255. }
  256. })
  257. b.Logf("x = %v", x)
  258. }