userspace_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package wgengine
  4. import (
  5. "fmt"
  6. "net/netip"
  7. "os"
  8. "reflect"
  9. "runtime"
  10. "testing"
  11. "go4.org/mem"
  12. "tailscale.com/cmd/testwrapper/flakytest"
  13. "tailscale.com/control/controlknobs"
  14. "tailscale.com/envknob"
  15. "tailscale.com/health"
  16. "tailscale.com/net/dns"
  17. "tailscale.com/net/netaddr"
  18. "tailscale.com/net/tstun"
  19. "tailscale.com/tailcfg"
  20. "tailscale.com/tstest"
  21. "tailscale.com/tstime/mono"
  22. "tailscale.com/types/key"
  23. "tailscale.com/types/netmap"
  24. "tailscale.com/types/opt"
  25. "tailscale.com/util/eventbus"
  26. "tailscale.com/util/usermetric"
  27. "tailscale.com/wgengine/router"
  28. "tailscale.com/wgengine/wgcfg"
  29. )
  30. func TestNoteReceiveActivity(t *testing.T) {
  31. now := mono.Time(123456)
  32. var logBuf tstest.MemLogger
  33. confc := make(chan bool, 1)
  34. gotConf := func() bool {
  35. select {
  36. case <-confc:
  37. return true
  38. default:
  39. return false
  40. }
  41. }
  42. e := &userspaceEngine{
  43. timeNow: func() mono.Time { return now },
  44. recvActivityAt: map[key.NodePublic]mono.Time{},
  45. logf: logBuf.Logf,
  46. tundev: new(tstun.Wrapper),
  47. testMaybeReconfigHook: func() { confc <- true },
  48. trimmedNodes: map[key.NodePublic]bool{},
  49. }
  50. ra := e.recvActivityAt
  51. nk := key.NewNode().Public()
  52. // Activity on an untracked key should do nothing.
  53. e.noteRecvActivity(nk)
  54. if len(ra) != 0 {
  55. t.Fatalf("unexpected growth in map: now has %d keys; want 0", len(ra))
  56. }
  57. if logBuf.Len() != 0 {
  58. t.Fatalf("unexpected log write (and thus activity): %s", logBuf.Bytes())
  59. }
  60. // Now track it, but don't mark it trimmed, so shouldn't update.
  61. ra[nk] = 0
  62. e.noteRecvActivity(nk)
  63. if len(ra) != 1 {
  64. t.Fatalf("unexpected growth in map: now has %d keys; want 1", len(ra))
  65. }
  66. if got := ra[nk]; got != now {
  67. t.Fatalf("time in map = %v; want %v", got, now)
  68. }
  69. if gotConf() {
  70. t.Fatalf("unexpected reconfig")
  71. }
  72. // Now mark it trimmed and expect an update.
  73. e.trimmedNodes[nk] = true
  74. e.noteRecvActivity(nk)
  75. if len(ra) != 1 {
  76. t.Fatalf("unexpected growth in map: now has %d keys; want 1", len(ra))
  77. }
  78. if got := ra[nk]; got != now {
  79. t.Fatalf("time in map = %v; want %v", got, now)
  80. }
  81. if !gotConf() {
  82. t.Fatalf("didn't get expected reconfig")
  83. }
  84. }
  85. func nodeViews(v []*tailcfg.Node) []tailcfg.NodeView {
  86. nv := make([]tailcfg.NodeView, len(v))
  87. for i, n := range v {
  88. nv[i] = n.View()
  89. }
  90. return nv
  91. }
  92. func TestUserspaceEngineReconfig(t *testing.T) {
  93. bus := eventbus.New()
  94. defer bus.Close()
  95. ht := new(health.Tracker)
  96. reg := new(usermetric.Registry)
  97. e, err := NewFakeUserspaceEngine(t.Logf, 0, ht, reg, bus)
  98. if err != nil {
  99. t.Fatal(err)
  100. }
  101. t.Cleanup(e.Close)
  102. ue := e.(*userspaceEngine)
  103. routerCfg := &router.Config{}
  104. for _, nodeHex := range []string{
  105. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  106. "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
  107. } {
  108. nm := &netmap.NetworkMap{
  109. Peers: nodeViews([]*tailcfg.Node{
  110. {
  111. ID: 1,
  112. Key: nkFromHex(nodeHex),
  113. },
  114. }),
  115. }
  116. nk, err := key.ParseNodePublicUntyped(mem.S(nodeHex))
  117. if err != nil {
  118. t.Fatal(err)
  119. }
  120. cfg := &wgcfg.Config{
  121. Peers: []wgcfg.Peer{
  122. {
  123. PublicKey: nk,
  124. AllowedIPs: []netip.Prefix{
  125. netip.PrefixFrom(netaddr.IPv4(100, 100, 99, 1), 32),
  126. },
  127. },
  128. },
  129. }
  130. e.SetNetworkMap(nm)
  131. err = e.Reconfig(cfg, routerCfg, &dns.Config{})
  132. if err != nil {
  133. t.Fatal(err)
  134. }
  135. wantRecvAt := map[key.NodePublic]mono.Time{
  136. nkFromHex(nodeHex): 0,
  137. }
  138. if got := ue.recvActivityAt; !reflect.DeepEqual(got, wantRecvAt) {
  139. t.Errorf("wrong recvActivityAt\n got: %v\nwant: %v\n", got, wantRecvAt)
  140. }
  141. wantTrimmedNodes := map[key.NodePublic]bool{
  142. nkFromHex(nodeHex): true,
  143. }
  144. if got := ue.trimmedNodes; !reflect.DeepEqual(got, wantTrimmedNodes) {
  145. t.Errorf("wrong wantTrimmedNodes\n got: %v\nwant: %v\n", got, wantTrimmedNodes)
  146. }
  147. }
  148. }
  149. func TestUserspaceEnginePortReconfig(t *testing.T) {
  150. flakytest.Mark(t, "https://github.com/tailscale/tailscale/issues/2855")
  151. const defaultPort = 49983
  152. var knobs controlknobs.Knobs
  153. bus := eventbus.New()
  154. defer bus.Close()
  155. // Keep making a wgengine until we find an unused port
  156. var ue *userspaceEngine
  157. ht := new(health.Tracker)
  158. reg := new(usermetric.Registry)
  159. for i := range 100 {
  160. attempt := uint16(defaultPort + i)
  161. e, err := NewFakeUserspaceEngine(t.Logf, attempt, &knobs, ht, reg, bus)
  162. if err != nil {
  163. t.Fatal(err)
  164. }
  165. ue = e.(*userspaceEngine)
  166. if ue.magicConn.LocalPort() == attempt {
  167. break
  168. }
  169. ue.Close()
  170. ue = nil
  171. }
  172. if ue == nil {
  173. t.Fatal("could not create a wgengine with a specific port")
  174. }
  175. t.Cleanup(ue.Close)
  176. startingPort := ue.magicConn.LocalPort()
  177. nodeKey, err := key.ParseNodePublicUntyped(mem.S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
  178. if err != nil {
  179. t.Fatal(err)
  180. }
  181. cfg := &wgcfg.Config{
  182. Peers: []wgcfg.Peer{
  183. {
  184. PublicKey: nodeKey,
  185. AllowedIPs: []netip.Prefix{
  186. netip.PrefixFrom(netaddr.IPv4(100, 100, 99, 1), 32),
  187. },
  188. },
  189. },
  190. }
  191. routerCfg := &router.Config{}
  192. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}); err != nil {
  193. t.Fatal(err)
  194. }
  195. if got := ue.magicConn.LocalPort(); got != startingPort {
  196. t.Errorf("no debug setting changed local port to %d from %d", got, startingPort)
  197. }
  198. knobs.RandomizeClientPort.Store(true)
  199. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}); err != nil {
  200. t.Fatal(err)
  201. }
  202. if got := ue.magicConn.LocalPort(); got == startingPort {
  203. t.Errorf("debug setting did not change local port from %d", startingPort)
  204. }
  205. lastPort := ue.magicConn.LocalPort()
  206. knobs.RandomizeClientPort.Store(false)
  207. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}); err != nil {
  208. t.Fatal(err)
  209. }
  210. if startingPort == defaultPort {
  211. // Only try this if we managed to bind defaultPort the first time.
  212. // Otherwise, assume someone else on the computer is using defaultPort
  213. // and so Reconfig would have caused magicSockt to bind some other port.
  214. if got := ue.magicConn.LocalPort(); got != defaultPort {
  215. t.Errorf("debug setting did not change local port from %d to %d", startingPort, defaultPort)
  216. }
  217. }
  218. if got := ue.magicConn.LocalPort(); got == lastPort {
  219. t.Errorf("Reconfig did not change local port from %d", lastPort)
  220. }
  221. }
  222. // Test that enabling and disabling peer path MTU discovery works correctly.
  223. func TestUserspaceEnginePeerMTUReconfig(t *testing.T) {
  224. if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
  225. t.Skipf("skipping on %q; peer MTU not supported", runtime.GOOS)
  226. }
  227. defer os.Setenv("TS_DEBUG_ENABLE_PMTUD", os.Getenv("TS_DEBUG_ENABLE_PMTUD"))
  228. envknob.Setenv("TS_DEBUG_ENABLE_PMTUD", "")
  229. // Turn on debugging to help diagnose problems.
  230. defer os.Setenv("TS_DEBUG_PMTUD", os.Getenv("TS_DEBUG_PMTUD"))
  231. envknob.Setenv("TS_DEBUG_PMTUD", "true")
  232. var knobs controlknobs.Knobs
  233. bus := eventbus.New()
  234. defer bus.Close()
  235. ht := new(health.Tracker)
  236. reg := new(usermetric.Registry)
  237. e, err := NewFakeUserspaceEngine(t.Logf, 0, &knobs, ht, reg, bus)
  238. if err != nil {
  239. t.Fatal(err)
  240. }
  241. t.Cleanup(e.Close)
  242. ue := e.(*userspaceEngine)
  243. if ue.magicConn.PeerMTUEnabled() != false {
  244. t.Error("peer MTU enabled by default, should not be")
  245. }
  246. osDefaultDF, err := ue.magicConn.DontFragSetting()
  247. if err != nil {
  248. t.Errorf("get don't fragment bit failed: %v", err)
  249. }
  250. t.Logf("Info: OS default don't fragment bit(s) setting: %v", osDefaultDF)
  251. // Build a set of configs to use as we change the peer MTU settings.
  252. nodeKey, err := key.ParseNodePublicUntyped(mem.S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
  253. if err != nil {
  254. t.Fatal(err)
  255. }
  256. cfg := &wgcfg.Config{
  257. Peers: []wgcfg.Peer{
  258. {
  259. PublicKey: nodeKey,
  260. AllowedIPs: []netip.Prefix{
  261. netip.PrefixFrom(netaddr.IPv4(100, 100, 99, 1), 32),
  262. },
  263. },
  264. },
  265. }
  266. routerCfg := &router.Config{}
  267. tests := []struct {
  268. desc string // test description
  269. wantP bool // desired value of PMTUD setting
  270. wantDF bool // desired value of don't fragment bits
  271. shouldP opt.Bool // if set, force peer MTU to this value
  272. }{
  273. {desc: "after_first_reconfig", wantP: false, wantDF: osDefaultDF, shouldP: ""},
  274. {desc: "enabling_PMTUD_first_time", wantP: true, wantDF: true, shouldP: "true"},
  275. {desc: "disabling_PMTUD", wantP: false, wantDF: false, shouldP: "false"},
  276. {desc: "enabling_PMTUD_second_time", wantP: true, wantDF: true, shouldP: "true"},
  277. {desc: "returning_to_default_PMTUD", wantP: false, wantDF: false, shouldP: ""},
  278. }
  279. for _, tt := range tests {
  280. t.Run(tt.desc, func(t *testing.T) {
  281. if v, ok := tt.shouldP.Get(); ok {
  282. knobs.PeerMTUEnable.Store(v)
  283. } else {
  284. knobs.PeerMTUEnable.Store(false)
  285. }
  286. if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}); err != nil {
  287. t.Fatal(err)
  288. }
  289. if v := ue.magicConn.PeerMTUEnabled(); v != tt.wantP {
  290. t.Errorf("peer MTU set to %v, want %v", v, tt.wantP)
  291. }
  292. if v, err := ue.magicConn.DontFragSetting(); v != tt.wantDF || err != nil {
  293. t.Errorf("don't fragment bit set to %v, want %v, err %v", v, tt.wantP, err)
  294. }
  295. })
  296. }
  297. }
  298. func nkFromHex(hex string) key.NodePublic {
  299. if len(hex) != 64 {
  300. panic(fmt.Sprintf("%q is len %d; want 64", hex, len(hex)))
  301. }
  302. k, err := key.ParseNodePublicUntyped(mem.S(hex[:64]))
  303. if err != nil {
  304. panic(fmt.Sprintf("%q is not hex: %v", hex, err))
  305. }
  306. return k
  307. }
  308. // an experiment to see if genLocalAddrFunc was worth it. As of Go
  309. // 1.16, it still very much is. (30-40x faster)
  310. func BenchmarkGenLocalAddrFunc(b *testing.B) {
  311. la1 := netip.MustParseAddr("1.2.3.4")
  312. la2 := netip.MustParseAddr("::4")
  313. lanot := netip.MustParseAddr("5.5.5.5")
  314. var x bool
  315. b.Run("map1", func(b *testing.B) {
  316. b.ReportAllocs()
  317. b.ResetTimer()
  318. m := map[netip.Addr]bool{
  319. la1: true,
  320. }
  321. for range b.N {
  322. x = m[la1]
  323. x = m[lanot]
  324. }
  325. })
  326. b.Run("map2", func(b *testing.B) {
  327. b.ReportAllocs()
  328. b.ResetTimer()
  329. m := map[netip.Addr]bool{
  330. la1: true,
  331. la2: true,
  332. }
  333. for range b.N {
  334. x = m[la1]
  335. x = m[lanot]
  336. }
  337. })
  338. b.Run("or1", func(b *testing.B) {
  339. b.ReportAllocs()
  340. b.ResetTimer()
  341. f := func(t netip.Addr) bool {
  342. return t == la1
  343. }
  344. for range b.N {
  345. x = f(la1)
  346. x = f(lanot)
  347. }
  348. })
  349. b.Run("or2", func(b *testing.B) {
  350. b.ReportAllocs()
  351. b.ResetTimer()
  352. f := func(t netip.Addr) bool {
  353. return t == la1 || t == la2
  354. }
  355. for range b.N {
  356. x = f(la1)
  357. x = f(lanot)
  358. }
  359. })
  360. b.Logf("x = %v", x)
  361. }