server6_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright 2018-present the CoreDHCP Authors. All rights reserved
  2. // This source code is licensed under the MIT license found in the
  3. // LICENSE file in the root directory of this source tree.
  4. // +build integration
  5. package e2e_test
  6. import (
  7. "fmt"
  8. "log"
  9. "net"
  10. "runtime"
  11. "testing"
  12. "github.com/insomniacslk/dhcp/dhcpv6"
  13. "github.com/insomniacslk/dhcp/dhcpv6/client6"
  14. "github.com/insomniacslk/dhcp/iana"
  15. "github.com/stretchr/testify/require"
  16. "github.com/vishvananda/netns"
  17. "github.com/coredhcp/coredhcp/config"
  18. "github.com/coredhcp/coredhcp/plugins"
  19. "github.com/coredhcp/coredhcp/server"
  20. // Plugins
  21. "github.com/coredhcp/coredhcp/plugins/file"
  22. "github.com/coredhcp/coredhcp/plugins/serverid"
  23. )
  24. var serverConfig = config.Config{
  25. Server6: &config.ServerConfig{
  26. Addresses: []net.UDPAddr{
  27. {
  28. IP: net.ParseIP("ff02::1:2"),
  29. Port: dhcpv6.DefaultServerPort,
  30. Zone: "cdhcp_srv",
  31. },
  32. },
  33. Plugins: []config.PluginConfig{
  34. {Name: "server_id", Args: []string{"LL", "11:22:33:44:55:66"}},
  35. {Name: "file", Args: []string{"./leases-dhcpv6-test.txt"}},
  36. },
  37. },
  38. }
  39. // This function *must* be run in its own routine
  40. // For now this assumes ns are created outside.
  41. // TODO: dynamically create NS and interfaces directly in the test program
  42. func runServer(readyCh chan<- struct{}, nsName string, desiredPlugins []*plugins.Plugin) {
  43. runtime.LockOSThread()
  44. defer runtime.UnlockOSThread()
  45. ns, err := netns.GetFromName(nsName)
  46. if err != nil {
  47. log.Panicf("Netns `%s` not set up: %v", nsName, err)
  48. }
  49. if err := netns.Set(ns); err != nil {
  50. log.Panicf("Failed to switch to netns `%s`: %v", nsName, err)
  51. }
  52. // register plugins
  53. for _, pl := range desiredPlugins {
  54. if err := plugins.RegisterPlugin(pl); err != nil {
  55. log.Panicf("Failed to register plugin `%s`: %v", pl.Name, err)
  56. }
  57. }
  58. // start DHCP server
  59. srv, err := server.Start(&serverConfig)
  60. if err != nil {
  61. log.Panicf("Server could not start: %v", err)
  62. }
  63. readyCh <- struct{}{}
  64. if err := srv.Wait(); err != nil {
  65. log.Panicf("Server errored during run: %v", err)
  66. }
  67. }
  68. // runInNs will execute the provided cmd in the namespace nsName.
  69. // It returns the error status of the cmd. Errors in NS management will panic
  70. func runClient6(nsName, iface string, modifiers ...dhcpv6.Modifier) error {
  71. runtime.LockOSThread()
  72. defer runtime.UnlockOSThread()
  73. backupNS, err := netns.Get()
  74. if err != nil {
  75. panic("Could not save handle to original NS")
  76. }
  77. ns, err := netns.GetFromName(nsName)
  78. if err != nil {
  79. panic("netns not set up")
  80. }
  81. if err := netns.Set(ns); err != nil {
  82. panic(fmt.Sprintf("Couldn't switch to test NS: %v", err))
  83. }
  84. client := client6.NewClient()
  85. _, cErr := client.Exchange(iface, modifiers...)
  86. if netns.Set(backupNS) != nil {
  87. panic("couldn't switch back to original NS")
  88. }
  89. return cErr
  90. }
  91. // TestDora creates a server and attempts to connect to it
  92. func TestDora(t *testing.T) {
  93. readyCh := make(chan struct{}, 1)
  94. go runServer(readyCh,
  95. "coredhcp-direct-upper",
  96. []*plugins.Plugin{
  97. &serverid.Plugin, &file.Plugin,
  98. },
  99. )
  100. // wait for server to be ready before sending DHCP request
  101. <-readyCh
  102. mac, err := net.ParseMAC("de:ad:be:ef:00:00")
  103. if err != nil {
  104. panic(err)
  105. }
  106. require.NoError(t, runClient6(
  107. "coredhcp-direct-lower", "cdhcp_cli",
  108. dhcpv6.WithClientID(dhcpv6.Duid{
  109. Type: dhcpv6.DUID_LL,
  110. HwType: iana.HWTypeEthernet,
  111. LinkLayerAddr: mac,
  112. }),
  113. ))
  114. }