tun_tester.go 3.1 KB

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