From e2d2676dfce963908d862f2e7a41f4c0ba1150db Mon Sep 17 00:00:00 2001 From: AkinoKaede Date: Sun, 28 May 2023 15:26:36 +0800 Subject: [PATCH] feat: set MTU for gVisor tun --- app/tun/device/tun/tun_gvisor.go | 43 +++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/app/tun/device/tun/tun_gvisor.go b/app/tun/device/tun/tun_gvisor.go index 2197d3c09..1a0a5c730 100644 --- a/app/tun/device/tun/tun_gvisor.go +++ b/app/tun/device/tun/tun_gvisor.go @@ -5,6 +5,9 @@ package tun import ( + "fmt" + "unsafe" + "github.com/v2fly/v2ray-core/v5/app/tun/device" "golang.org/x/sys/unix" "gvisor.dev/gvisor/pkg/tcpip/stack" @@ -14,6 +17,10 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/link/tun" ) +const ( + ifReqSize = unix.IFNAMSIZ + 64 +) + type TUN struct { stack.LinkEndpoint @@ -36,7 +43,9 @@ func New(options device.Options) (device.Device, error) { } t.fd = fd - // TODO: set MTU + if options.MTU > 0 { + setMTU(options.Name, int(options.MTU)) + } mtu, err := rawfile.GetMTU(options.Name) if err != nil { @@ -66,3 +75,35 @@ func New(options device.Options) (device.Device, error) { func (t *TUN) Close() error { return unix.Close(t.fd) } + +// Modified from golang.zx2c4.com/wireguard/tun/tun_linux.go +func setMTU(name string, n int) error { + // open datagram socket + fd, err := unix.Socket( + unix.AF_INET, + unix.SOCK_DGRAM|unix.SOCK_CLOEXEC, + 0, + ) + if err != nil { + return err + } + + defer unix.Close(fd) + + // do ioctl call + var ifr [ifReqSize]byte + copy(ifr[:], name) + *(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint32(n) + _, _, errno := unix.Syscall( + unix.SYS_IOCTL, + uintptr(fd), + uintptr(unix.SIOCSIFMTU), + uintptr(unsafe.Pointer(&ifr[0])), + ) + + if errno != 0 { + return fmt.Errorf("failed to set MTU of TUN device: %w", errno) + } + + return nil +}