userspace_test.go 6.8 KB

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