tun_tester.go 3.2 KB

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