userspace_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package wgengine
  5. import (
  6. "fmt"
  7. "net/netip"
  8. "reflect"
  9. "testing"
  10. "go4.org/mem"
  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. const defaultPort = 49983
  131. // Keep making a wgengine until we find an unused port
  132. var ue *userspaceEngine
  133. for i := 0; i < 100; i++ {
  134. attempt := uint16(defaultPort + i)
  135. e, err := NewFakeUserspaceEngine(t.Logf, attempt)
  136. if err != nil {
  137. t.Fatal(err)
  138. }
  139. ue = e.(*userspaceEngine)
  140. if ue.magicConn.LocalPort() == attempt {
  141. break
  142. }
  143. ue.Close()
  144. ue = nil
  145. }
  146. if ue == nil {
  147. t.Fatal("could not create a wgengine with a specific port")
  148. }
  149. t.Cleanup(ue.Close)
  150. startingPort := ue.magicConn.LocalPort()
  151. nodeKey, err := key.ParseNodePublicUntyped(mem.S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
  152. if err != nil {
  153. t.Fatal(err)
  154. }
  155. cfg := &wgcfg.Config{
  156. Peers: []wgcfg.Peer{
  157. {
  158. PublicKey: nodeKey,
  159. AllowedIPs: []netip.Prefix{
  160. netip.PrefixFrom(netaddr.IPv4(100, 100, 99, 1), 32),
  161. },
  162. },
  163. },
  164. }
  165. routerCfg := &router.Config{}
  166. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}, nil); err != nil {
  167. t.Fatal(err)
  168. }
  169. if got := ue.magicConn.LocalPort(); got != startingPort {
  170. t.Errorf("no debug setting changed local port to %d from %d", got, startingPort)
  171. }
  172. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}, &tailcfg.Debug{RandomizeClientPort: true}); err != nil {
  173. t.Fatal(err)
  174. }
  175. if got := ue.magicConn.LocalPort(); got == startingPort {
  176. t.Errorf("debug setting did not change local port from %d", startingPort)
  177. }
  178. lastPort := ue.magicConn.LocalPort()
  179. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}, nil); err != nil {
  180. t.Fatal(err)
  181. }
  182. if startingPort == defaultPort {
  183. // Only try this if we managed to bind defaultPort the first time.
  184. // Otherwise, assume someone else on the computer is using defaultPort
  185. // and so Reconfig would have caused magicSockt to bind some other port.
  186. if got := ue.magicConn.LocalPort(); got != defaultPort {
  187. t.Errorf("debug setting did not change local port from %d to %d", startingPort, defaultPort)
  188. }
  189. }
  190. if got := ue.magicConn.LocalPort(); got == lastPort {
  191. t.Errorf("Reconfig did not change local port from %d", lastPort)
  192. }
  193. }
  194. func nkFromHex(hex string) key.NodePublic {
  195. if len(hex) != 64 {
  196. panic(fmt.Sprintf("%q is len %d; want 64", hex, len(hex)))
  197. }
  198. k, err := key.ParseNodePublicUntyped(mem.S(hex[:64]))
  199. if err != nil {
  200. panic(fmt.Sprintf("%q is not hex: %v", hex, err))
  201. }
  202. return k
  203. }
  204. // an experiment to see if genLocalAddrFunc was worth it. As of Go
  205. // 1.16, it still very much is. (30-40x faster)
  206. func BenchmarkGenLocalAddrFunc(b *testing.B) {
  207. la1 := netip.MustParseAddr("1.2.3.4")
  208. la2 := netip.MustParseAddr("::4")
  209. lanot := netip.MustParseAddr("5.5.5.5")
  210. var x bool
  211. b.Run("map1", func(b *testing.B) {
  212. b.ReportAllocs()
  213. b.ResetTimer()
  214. m := map[netip.Addr]bool{
  215. la1: true,
  216. }
  217. for i := 0; i < b.N; i++ {
  218. x = m[la1]
  219. x = m[lanot]
  220. }
  221. })
  222. b.Run("map2", func(b *testing.B) {
  223. b.ReportAllocs()
  224. b.ResetTimer()
  225. m := map[netip.Addr]bool{
  226. la1: true,
  227. la2: true,
  228. }
  229. for i := 0; i < b.N; i++ {
  230. x = m[la1]
  231. x = m[lanot]
  232. }
  233. })
  234. b.Run("or1", func(b *testing.B) {
  235. b.ReportAllocs()
  236. b.ResetTimer()
  237. f := func(t netip.Addr) bool {
  238. return t == la1
  239. }
  240. for i := 0; i < b.N; i++ {
  241. x = f(la1)
  242. x = f(lanot)
  243. }
  244. })
  245. b.Run("or2", func(b *testing.B) {
  246. b.ReportAllocs()
  247. b.ResetTimer()
  248. f := func(t netip.Addr) bool {
  249. return t == la1 || t == la2
  250. }
  251. for i := 0; i < b.N; i++ {
  252. x = f(la1)
  253. x = f(lanot)
  254. }
  255. })
  256. b.Logf("x = %v", x)
  257. }