tun_gvisor.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. //go:build linux && ((linux && amd64) || (linux && arm64))
  2. // +build linux
  3. // +build linux,amd64 linux,arm64
  4. package tun
  5. import (
  6. "github.com/v2fly/v2ray-core/v5/app/tun/device"
  7. "golang.org/x/sys/unix"
  8. "gvisor.dev/gvisor/pkg/tcpip/stack"
  9. "gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
  10. "gvisor.dev/gvisor/pkg/tcpip/link/rawfile"
  11. "gvisor.dev/gvisor/pkg/tcpip/link/tun"
  12. )
  13. type TUN struct {
  14. stack.LinkEndpoint
  15. options device.Options
  16. fd int
  17. mtu uint32 // real MTU
  18. }
  19. func New(options device.Options) (device.Device, error) {
  20. t := &TUN{options: options}
  21. if len(options.Name) > unix.IFNAMSIZ {
  22. return nil, newError("name too long").AtError()
  23. }
  24. fd, err := tun.Open(options.Name)
  25. if err != nil {
  26. return nil, newError("failed to open tun device").Base(err).AtError()
  27. }
  28. t.fd = fd
  29. // TODO: set MTU
  30. mtu, err := rawfile.GetMTU(options.Name)
  31. if err != nil {
  32. return nil, newError("failed to get mtu").Base(err).AtError()
  33. }
  34. t.mtu = mtu
  35. linkEndpoint, err := fdbased.New(&fdbased.Options{
  36. FDs: []int{fd},
  37. MTU: mtu,
  38. // TUN is not need to process ethernet header.
  39. EthernetHeader: false,
  40. // Readv is the default dispatch mode and is the least performant of the
  41. // dispatch options but the one that is supported by all underlying FD
  42. // types.
  43. PacketDispatchMode: fdbased.Readv,
  44. MaxSyscallHeaderBytes: 0x00,
  45. })
  46. if err != nil {
  47. return nil, newError("failed to create link endpoint").Base(err).AtError()
  48. }
  49. t.LinkEndpoint = linkEndpoint
  50. return t, nil
  51. }
  52. func (t *TUN) Close() error {
  53. return unix.Close(t.fd)
  54. }