tun_tester.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //go:build e2e_testing
  2. // +build e2e_testing
  3. package overlay
  4. import (
  5. "context"
  6. "fmt"
  7. "io"
  8. "log/slog"
  9. "net/netip"
  10. "os"
  11. "sync/atomic"
  12. "github.com/gaissmai/bart"
  13. "github.com/slackhq/nebula/config"
  14. "github.com/slackhq/nebula/overlay/tio"
  15. "github.com/slackhq/nebula/routing"
  16. )
  17. type TestTun struct {
  18. Device string
  19. vpnNetworks []netip.Prefix
  20. Routes []Route
  21. routeTree *bart.Table[routing.Gateways]
  22. l *slog.Logger
  23. closed atomic.Bool
  24. rxPackets chan []byte // Packets to receive into nebula
  25. TxPackets chan []byte // Packets transmitted outside by nebula
  26. batchRet [1][]byte
  27. }
  28. func (t *TestTun) Read() ([][]byte, error) {
  29. p, ok := <-t.rxPackets
  30. if !ok {
  31. return nil, os.ErrClosed
  32. }
  33. t.batchRet[0] = p
  34. return t.batchRet[:], nil
  35. }
  36. func newTun(c *config.C, l *slog.Logger, vpnNetworks []netip.Prefix, _ bool) (*TestTun, error) {
  37. _, routes, err := getAllRoutesFromConfig(c, vpnNetworks, true)
  38. if err != nil {
  39. return nil, err
  40. }
  41. routeTree, err := makeRouteTree(l, routes, false)
  42. if err != nil {
  43. return nil, err
  44. }
  45. return &TestTun{
  46. Device: c.GetString("tun.dev", ""),
  47. vpnNetworks: vpnNetworks,
  48. Routes: routes,
  49. routeTree: routeTree,
  50. l: l,
  51. rxPackets: make(chan []byte, 10),
  52. TxPackets: make(chan []byte, 10),
  53. }, nil
  54. }
  55. func newTunFromFd(_ *config.C, _ *slog.Logger, _ int, _ []netip.Prefix) (*TestTun, error) {
  56. return nil, fmt.Errorf("newTunFromFd not supported")
  57. }
  58. // Send will place a byte array onto the receive queue for nebula to consume
  59. // These are unencrypted ip layer frames destined for another nebula node.
  60. // packets should exit the udp side, capture them with udpConn.Get
  61. func (t *TestTun) Send(packet []byte) {
  62. if t.closed.Load() {
  63. return
  64. }
  65. if t.l.Enabled(context.Background(), slog.LevelDebug) {
  66. t.l.Debug("Tun receiving injected packet", "dataLen", len(packet))
  67. }
  68. t.rxPackets <- packet
  69. }
  70. // Get will pull an unencrypted ip layer frame from the transmit queue
  71. // nebula meant to send this message to some application on the local system
  72. // packets were ingested from the udp side, you can send them with udpConn.Send
  73. func (t *TestTun) Get(block bool) []byte {
  74. if block {
  75. return <-t.TxPackets
  76. }
  77. select {
  78. case p := <-t.TxPackets:
  79. return p
  80. default:
  81. return nil
  82. }
  83. }
  84. //********************************************************************************************************************//
  85. // Below this is boilerplate implementation to make nebula actually work
  86. //********************************************************************************************************************//
  87. func (t *TestTun) RoutesFor(ip netip.Addr) routing.Gateways {
  88. r, _ := t.routeTree.Lookup(ip)
  89. return r
  90. }
  91. func (t *TestTun) Activate() error {
  92. return nil
  93. }
  94. func (t *TestTun) Networks() []netip.Prefix {
  95. return t.vpnNetworks
  96. }
  97. func (t *TestTun) Name() string {
  98. return t.Device
  99. }
  100. func (t *TestTun) Write(b []byte) (n int, err error) {
  101. if t.closed.Load() {
  102. return 0, io.ErrClosedPipe
  103. }
  104. packet := make([]byte, len(b), len(b))
  105. copy(packet, b)
  106. t.TxPackets <- packet
  107. return len(b), nil
  108. }
  109. func (t *TestTun) Close() error {
  110. if t.closed.CompareAndSwap(false, true) {
  111. close(t.rxPackets)
  112. close(t.TxPackets)
  113. }
  114. return nil
  115. }
  116. func (t *TestTun) Readers() []tio.Queue {
  117. return []tio.Queue{t}
  118. }
  119. func (t *TestTun) SupportsMultiqueue() bool {
  120. return false
  121. }
  122. func (t *TestTun) NewMultiQueueReader() error {
  123. return fmt.Errorf("TODO: multiqueue not implemented")
  124. }