tun_wg.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. //go:build !android && !netbsd && !e2e_testing
  2. // +build !android,!netbsd,!e2e_testing
  3. package overlay
  4. import (
  5. "fmt"
  6. "io"
  7. "net/netip"
  8. "sync/atomic"
  9. "github.com/gaissmai/bart"
  10. "github.com/sirupsen/logrus"
  11. "github.com/slackhq/nebula/config"
  12. "github.com/slackhq/nebula/routing"
  13. "github.com/slackhq/nebula/util"
  14. wgtun "golang.zx2c4.com/wireguard/tun"
  15. )
  16. // wgTun wraps a WireGuard TUN device and implements the overlay.Device interface
  17. type wgTun struct {
  18. tunDevice wgtun.Device
  19. vpnNetworks []netip.Prefix
  20. MaxMTU int
  21. DefaultMTU int
  22. Routes atomic.Pointer[[]Route]
  23. routeTree atomic.Pointer[bart.Table[routing.Gateways]]
  24. routeChan chan struct{}
  25. // Platform-specific route management
  26. routeManager *tun
  27. l *logrus.Logger
  28. }
  29. // BatchReader interface for readers that support vectorized I/O
  30. type BatchReader interface {
  31. BatchRead(buffers [][]byte, sizes []int) (int, error)
  32. }
  33. // BatchWriter interface for writers that support vectorized I/O
  34. type BatchWriter interface {
  35. BatchWrite(packets [][]byte) (int, error)
  36. }
  37. // wgTunReader wraps a single TUN queue for multi-queue support
  38. type wgTunReader struct {
  39. parent *wgTun
  40. tunDevice wgtun.Device
  41. offset int
  42. l *logrus.Logger
  43. }
  44. func (t *wgTun) Networks() []netip.Prefix {
  45. return t.vpnNetworks
  46. }
  47. func (t *wgTun) Name() string {
  48. name, err := t.tunDevice.Name()
  49. if err != nil {
  50. t.l.WithError(err).Error("Failed to get TUN device name")
  51. return "unknown"
  52. }
  53. return name
  54. }
  55. func (t *wgTun) RoutesFor(ip netip.Addr) routing.Gateways {
  56. r, _ := t.routeTree.Load().Lookup(ip)
  57. return r
  58. }
  59. func (t *wgTun) Activate() error {
  60. if t.routeManager == nil {
  61. return fmt.Errorf("route manager not initialized")
  62. }
  63. return t.routeManager.Activate(t)
  64. }
  65. // Read implements single-packet read for backward compatibility
  66. func (t *wgTun) Read(b []byte) (int, error) {
  67. bufs := [][]byte{b}
  68. sizes := []int{0}
  69. n, err := t.tunDevice.Read(bufs, sizes, 0)
  70. if err != nil {
  71. return 0, err
  72. }
  73. if n == 0 {
  74. return 0, io.ErrNoProgress
  75. }
  76. return sizes[0], nil
  77. }
  78. // Write implements single-packet write for backward compatibility
  79. func (t *wgTun) Write(b []byte) (int, error) {
  80. bufs := [][]byte{b}
  81. offset := 0
  82. // WireGuard TUN expects the packet data to start at offset 0
  83. n, err := t.tunDevice.Write(bufs, offset)
  84. if err != nil {
  85. return 0, err
  86. }
  87. if n == 0 {
  88. return 0, io.ErrShortWrite
  89. }
  90. return len(b), nil
  91. }
  92. func (t *wgTun) Close() error {
  93. if t.routeChan != nil {
  94. close(t.routeChan)
  95. }
  96. if t.tunDevice != nil {
  97. return t.tunDevice.Close()
  98. }
  99. return nil
  100. }
  101. func (t *wgTun) NewMultiQueueReader() (io.ReadWriteCloser, error) {
  102. // For WireGuard TUN, we need to create separate TUN device instances for multi-queue
  103. // The platform-specific implementation will handle this
  104. if t.routeManager == nil {
  105. return nil, fmt.Errorf("route manager not initialized for multi-queue reader")
  106. }
  107. return t.routeManager.NewMultiQueueReader(t)
  108. }
  109. func (t *wgTun) reload(c *config.C, initial bool) error {
  110. routeChange, routes, err := getAllRoutesFromConfig(c, t.vpnNetworks, initial)
  111. if err != nil {
  112. return err
  113. }
  114. if !initial && !routeChange && !c.HasChanged("tun.mtu") {
  115. return nil
  116. }
  117. routeTree, err := makeRouteTree(t.l, routes, true)
  118. if err != nil {
  119. return err
  120. }
  121. oldDefaultMTU := t.DefaultMTU
  122. oldMaxMTU := t.MaxMTU
  123. newDefaultMTU := c.GetInt("tun.mtu", DefaultMTU)
  124. newMaxMTU := newDefaultMTU
  125. for i, r := range routes {
  126. if r.MTU == 0 {
  127. routes[i].MTU = newDefaultMTU
  128. }
  129. if r.MTU > t.MaxMTU {
  130. newMaxMTU = r.MTU
  131. }
  132. }
  133. t.MaxMTU = newMaxMTU
  134. t.DefaultMTU = newDefaultMTU
  135. // Teach nebula how to handle the routes before establishing them in the system table
  136. oldRoutes := t.Routes.Swap(&routes)
  137. t.routeTree.Store(routeTree)
  138. if !initial && t.routeManager != nil {
  139. if oldMaxMTU != newMaxMTU {
  140. t.routeManager.SetMTU(t, t.MaxMTU)
  141. t.l.Infof("Set max MTU to %v was %v", t.MaxMTU, oldMaxMTU)
  142. }
  143. if oldDefaultMTU != newDefaultMTU {
  144. for i := range t.vpnNetworks {
  145. err := t.routeManager.SetDefaultRoute(t, t.vpnNetworks[i])
  146. if err != nil {
  147. t.l.Warn(err)
  148. } else {
  149. t.l.Infof("Set default MTU to %v was %v", t.DefaultMTU, oldDefaultMTU)
  150. }
  151. }
  152. }
  153. // Remove first, if the system removes a wanted route hopefully it will be re-added next
  154. t.routeManager.RemoveRoutes(t, findRemovedRoutes(routes, *oldRoutes))
  155. // Ensure any routes we actually want are installed
  156. err = t.routeManager.AddRoutes(t, true)
  157. if err != nil {
  158. // This should never be called since AddRoutes should log its own errors in a reload condition
  159. util.LogWithContextIfNeeded("Failed to refresh routes", err, t.l)
  160. }
  161. }
  162. return nil
  163. }
  164. // BatchRead reads multiple packets from the TUN device using vectorized I/O
  165. // The caller provides buffers and sizes slices, and this function returns the number of packets read.
  166. func (r *wgTunReader) BatchRead(buffers [][]byte, sizes []int) (int, error) {
  167. return r.tunDevice.Read(buffers, sizes, r.offset)
  168. }
  169. // Read implements io.Reader for wgTunReader (single packet for compatibility)
  170. func (r *wgTunReader) Read(b []byte) (int, error) {
  171. bufs := [][]byte{b}
  172. sizes := []int{0}
  173. n, err := r.tunDevice.Read(bufs, sizes, r.offset)
  174. if err != nil {
  175. return 0, err
  176. }
  177. if n == 0 {
  178. return 0, io.ErrNoProgress
  179. }
  180. return sizes[0], nil
  181. }
  182. // Write implements io.Writer for wgTunReader
  183. func (r *wgTunReader) Write(b []byte) (int, error) {
  184. bufs := [][]byte{b}
  185. n, err := r.tunDevice.Write(bufs, r.offset)
  186. if err != nil {
  187. return 0, err
  188. }
  189. if n == 0 {
  190. return 0, io.ErrShortWrite
  191. }
  192. return len(b), nil
  193. }
  194. // BatchWrite writes multiple packets to the TUN device using vectorized I/O
  195. func (r *wgTunReader) BatchWrite(packets [][]byte) (int, error) {
  196. return r.tunDevice.Write(packets, r.offset)
  197. }
  198. func (r *wgTunReader) Close() error {
  199. if r.tunDevice != nil {
  200. return r.tunDevice.Close()
  201. }
  202. return nil
  203. }