1
0

tun_reload_linux_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. //go:build !e2e_testing
  2. package overlay
  3. import (
  4. "net/netip"
  5. "os"
  6. "testing"
  7. "github.com/slackhq/nebula/config"
  8. "github.com/slackhq/nebula/routing"
  9. "github.com/slackhq/nebula/test"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/stretchr/testify/require"
  12. )
  13. // Only tun.mtu changes. The system calls fail without a real device, what matters is the routes nebula keeps
  14. func TestReloadMTUOnlyKeepsRoutes(t *testing.T) {
  15. routes := " unsafe_routes:\n - route: 192.168.100.0/24\n via: 10.1.0.1\n"
  16. c := config.NewC(test.NewLogger())
  17. require.NoError(t, c.LoadString("tun:\n mtu: 1300\n"+routes))
  18. tn := &tun{
  19. l: test.NewLogger(),
  20. vpnNetworks: []netip.Prefix{netip.MustParsePrefix("10.1.0.2/24")},
  21. ioctlFd: ^uintptr(0),
  22. routesFromSystem: map[netip.Prefix]routing.Gateways{},
  23. }
  24. require.NoError(t, tn.reload(c, true, nil))
  25. require.NoError(t, c.ReloadConfigString("tun:\n mtu: 1400\n"+routes).Err)
  26. _ = tn.reload(c, false, nil)
  27. got := *tn.Routes.Load()
  28. require.Len(t, got, 1)
  29. assert.Equal(t, netip.MustParsePrefix("192.168.100.0/24"), got[0].Cidr)
  30. assert.Equal(t, 1400, got[0].MTU)
  31. assert.Equal(t, 1400, tn.DefaultMTU)
  32. }
  33. // The device mtu has to fit the largest route mtu, wherever it sits in the list
  34. func TestReloadMaxMTUIsTheLargestRoute(t *testing.T) {
  35. c := config.NewC(test.NewLogger())
  36. require.NoError(t, c.LoadString("tun:\n mtu: 1300\n unsafe_routes:\n"+
  37. " - route: 192.168.100.0/24\n via: 10.1.0.1\n mtu: 1500\n"+
  38. " - route: 192.168.101.0/24\n via: 10.1.0.1\n mtu: 1400\n"))
  39. tn := &tun{
  40. l: test.NewLogger(),
  41. vpnNetworks: []netip.Prefix{netip.MustParsePrefix("10.1.0.2/24")},
  42. ioctlFd: ^uintptr(0),
  43. routesFromSystem: map[netip.Prefix]routing.Gateways{},
  44. }
  45. require.NoError(t, tn.reload(c, true, nil))
  46. assert.Equal(t, 1500, tn.MaxMTU)
  47. assert.Equal(t, 1300, tn.DefaultMTU)
  48. }
  49. // There is no device behind this tun, so adding a route always fails. Removing one is refused without root, as root the
  50. // kernel answers that the route isn't there, which is what we wanted
  51. func TestReloadRouteFailures(t *testing.T) {
  52. route := "tun:\n mtu: 1300\n unsafe_routes:\n - route: 192.168.100.0/24\n via: 10.1.0.1\n"
  53. cases := []struct {
  54. name string
  55. from, to string
  56. wantFails bool
  57. }{
  58. {"added", "tun:\n mtu: 1300\n", route, true},
  59. {"removed", route, "tun:\n mtu: 1300\n", os.Geteuid() != 0},
  60. {"unchanged", route, route + "punchy:\n punch: true\n", false},
  61. }
  62. for _, tc := range cases {
  63. t.Run(tc.name, func(t *testing.T) {
  64. c := config.NewC(test.NewLogger())
  65. require.NoError(t, c.LoadString(tc.from))
  66. tn := &tun{
  67. l: test.NewLogger(),
  68. vpnNetworks: []netip.Prefix{netip.MustParsePrefix("10.1.0.2/24")},
  69. ioctlFd: ^uintptr(0),
  70. routesFromSystem: map[netip.Prefix]routing.Gateways{},
  71. }
  72. require.NoError(t, tn.reload(c, true, nil))
  73. c.RegisterReloadCallback(func(c *config.C, r *config.Reload) {
  74. require.NoError(t, tn.reload(c, false, r))
  75. })
  76. res := c.ReloadConfigString(tc.to)
  77. require.NoError(t, res.Err)
  78. assert.Equal(t, tc.wantFails, res.Failed)
  79. })
  80. }
  81. }
  82. // Keys only read when the device is created need a restart to apply
  83. func TestTunReloadRestartKeys(t *testing.T) {
  84. c := config.NewC(test.NewLogger())
  85. require.NoError(t, c.LoadString("tun:\n dev: nebrk0\n"))
  86. tn, err := NewDeviceFromConfig(c, test.NewLogger(), []netip.Prefix{netip.MustParsePrefix("10.1.0.2/24")}, 1)
  87. if err != nil {
  88. t.Skipf("can't create a tun device here: %v", err)
  89. }
  90. t.Cleanup(func() { _ = tn.Close() })
  91. res := c.ReloadConfigString("tun:\n disabled: true\n dev: nebrk1\n tx_queue: 100\n")
  92. require.NoError(t, res.Err)
  93. assert.ElementsMatch(t, []string{"tun.disabled", "tun.dev", "tun.tx_queue"}, res.RestartKeys)
  94. }