Fix android GSO
This commit is contained in:
parent
ebd569670d
commit
5bb0784f61
2 changed files with 45 additions and 26 deletions
61
tun_linux.go
61
tun_linux.go
|
|
@ -76,6 +76,14 @@ func New(options Options) (Tun, error) {
|
||||||
tunFile: os.NewFile(uintptr(options.FileDescriptor), "tun"),
|
tunFile: os.NewFile(uintptr(options.FileDescriptor), "tun"),
|
||||||
options: options,
|
options: options,
|
||||||
}
|
}
|
||||||
|
if options.GSO {
|
||||||
|
err := nativeTun.enableGSO()
|
||||||
|
if err != nil {
|
||||||
|
if options.Logger != nil {
|
||||||
|
options.Logger.Warn(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nativeTun, nil
|
return nativeTun, nil
|
||||||
}
|
}
|
||||||
|
|
@ -189,28 +197,38 @@ func (t *NativeTun) enableGSO() error {
|
||||||
if !vnetHdrEnabled {
|
if !vnetHdrEnabled {
|
||||||
return E.Cause(err, "enable offload: IFF_VNET_HDR not enabled")
|
return E.Cause(err, "enable offload: IFF_VNET_HDR not enabled")
|
||||||
}
|
}
|
||||||
|
t.vnetHdr = true
|
||||||
|
t.writeBuffer = make([]byte, virtioNetHdrLen+gsoMaxSize)
|
||||||
|
t.pendingBuffer = make([]byte, virtioNetHdrLen+gsoMaxSize)
|
||||||
|
t.tcpGROTable = newTCPGROTable()
|
||||||
|
t.udpGROTable = newUDPGROTable()
|
||||||
err = setTCPOffload(t.tunFd)
|
err = setTCPOffload(t.tunFd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "enable TCP offload")
|
if !(errors.Is(err, unix.EPERM) && t.options.FileDescriptor != 0) {
|
||||||
|
t.options.Logger.Warn(E.Cause(err, "enable offload: set tcp offload"))
|
||||||
|
t.gro.disableTCPGRO()
|
||||||
|
t.gro.disableUDPGRO()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = setUDPOffload(t.tunFd)
|
||||||
|
if err != nil {
|
||||||
|
t.options.Logger.Warn(E.Cause(err, "enable offload: set udp offload"))
|
||||||
|
t.gro.disableUDPGRO()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.vnetHdr = true
|
|
||||||
t.writeBuffer = make([]byte, virtioNetHdrLen+int(gsoMaxSize))
|
|
||||||
t.pendingBuffer = make([]byte, virtioNetHdrLen+int(gsoMaxSize))
|
|
||||||
t.readRawConn, err = t.tunFile.SyscallConn()
|
t.readRawConn, err = t.tunFile.SyscallConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "enable offload: get raw conn")
|
return E.Cause(err, "enable offload: get raw conn")
|
||||||
}
|
}
|
||||||
t.tcpGROTable = newTCPGROTable()
|
|
||||||
t.udpGROTable = newUDPGROTable()
|
|
||||||
err = setUDPOffload(t.tunFd)
|
|
||||||
if err != nil {
|
|
||||||
t.gro.disableUDPGRO()
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *NativeTun) probeTCPGRO() error {
|
func (t *NativeTun) probeTCPGRO() error {
|
||||||
ipPort := netip.AddrPortFrom(t.options.Inet4Address[0].Addr(), 0)
|
probeAddr := netip.AddrFrom4([4]byte{127, 0, 0, 1})
|
||||||
|
if len(t.options.Inet4Address) > 0 {
|
||||||
|
probeAddr = t.options.Inet4Address[0].Addr()
|
||||||
|
}
|
||||||
|
ipPort := netip.AddrPortFrom(probeAddr, 0)
|
||||||
fingerprint := []byte("sing-tun-probe-tun-gro")
|
fingerprint := []byte("sing-tun-probe-tun-gro")
|
||||||
segmentSize := len(fingerprint)
|
segmentSize := len(fingerprint)
|
||||||
iphLen := 20
|
iphLen := 20
|
||||||
|
|
@ -267,6 +285,16 @@ func (t *NativeTun) Name() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *NativeTun) Start() error {
|
func (t *NativeTun) Start() error {
|
||||||
|
if t.vnetHdr && t.gro.canTCPGRO() {
|
||||||
|
err := t.probeTCPGRO()
|
||||||
|
if err != nil {
|
||||||
|
t.gro.disableTCPGRO()
|
||||||
|
t.gro.disableUDPGRO()
|
||||||
|
if t.options.Logger != nil {
|
||||||
|
t.options.Logger.Warn(E.Cause(err, "disabled TUN TCP & UDP GRO due to GRO probe error"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if t.options.FileDescriptor != 0 {
|
if t.options.FileDescriptor != 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -283,17 +311,6 @@ func (t *NativeTun) Start() error {
|
||||||
return E.Cause(err, "set tun up")
|
return E.Cause(err, "set tun up")
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.vnetHdr && len(t.options.Inet4Address) > 0 {
|
|
||||||
err = t.probeTCPGRO()
|
|
||||||
if err != nil {
|
|
||||||
t.gro.disableTCPGRO()
|
|
||||||
t.gro.disableUDPGRO()
|
|
||||||
if t.options.Logger != nil {
|
|
||||||
t.options.Logger.Warn(E.Cause(err, "disabled TUN TCP & UDP GRO due to GRO probe error"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.options.EXP_ExternalConfiguration {
|
if t.options.EXP_ExternalConfiguration {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -33,13 +31,17 @@ func checkVNETHDREnabled(fd int, name string) (bool, error) {
|
||||||
func setTCPOffload(fd int) error {
|
func setTCPOffload(fd int) error {
|
||||||
err := unix.IoctlSetInt(fd, unix.TUNSETOFFLOAD, tunTCPOffloads)
|
err := unix.IoctlSetInt(fd, unix.TUNSETOFFLOAD, tunTCPOffloads)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(os.NewSyscallError("TUNSETOFFLOAD", err), "enable offload")
|
return os.NewSyscallError("TUNSETOFFLOAD", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setUDPOffload(fd int) error {
|
func setUDPOffload(fd int) error {
|
||||||
return unix.IoctlSetInt(fd, unix.TUNSETOFFLOAD, tunTCPOffloads|tunUDPOffloads)
|
err := unix.IoctlSetInt(fd, unix.TUNSETOFFLOAD, tunTCPOffloads|tunUDPOffloads)
|
||||||
|
if err != nil {
|
||||||
|
return os.NewSyscallError("TUNSETOFFLOAD", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ifreqData struct {
|
type ifreqData struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue