tun_tester.go 3.2 KB

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