TUN vectorised reads/writes (#1145)

This PR updates the Wireguard dependency and updates to use new
vectorised reads/writes, which should reduce the number of syscalls and
improve performance.

This will only make a difference on Linux as this is the only platform
for which the Wireguard TUN library supports vectorised reads/writes.
For other platforms, single reads and writes will be performed as usual.

---------

Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
This commit is contained in:
Neil 2024-07-20 15:24:30 +01:00 committed by GitHub
parent 04c0acf71b
commit 02d92ff81c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 92 additions and 24 deletions

View file

@ -10,9 +10,11 @@ import (
"fmt"
"io"
"net"
"sync"
"time"
"github.com/Arceliar/phony"
"golang.zx2c4.com/wireguard/tun"
wgtun "golang.zx2c4.com/wireguard/tun"
"github.com/yggdrasil-network/yggdrasil-go/src/address"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
@ -39,7 +41,7 @@ type TunAdapter struct {
addr address.Address
subnet address.Subnet
mtu uint64
iface tun.Device
iface wgtun.Device
phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
isOpen bool
isEnabled bool // Used by the writer to drop sessionTraffic if not enabled
@ -48,6 +50,7 @@ type TunAdapter struct {
name InterfaceName
mtu InterfaceMTU
}
ch chan []byte
}
// Gets the maximum supported MTU for the platform based on the defaults in
@ -62,6 +65,20 @@ func getSupportedMTU(mtu uint64) uint64 {
return mtu
}
func waitForTUNUp(ch <-chan wgtun.Event) bool {
t := time.After(time.Second * 5)
for {
select {
case ev := <-ch:
if ev == wgtun.EventUp {
return true
}
case <-t:
return false
}
}
}
// Name returns the name of the adapter, e.g. "tun0". On Windows, this may
// return a canonical adapter name instead.
func (tun *TunAdapter) Name() string {
@ -145,6 +162,8 @@ func (tun *TunAdapter) _start() error {
tun.rwc.SetMTU(tun.MTU())
tun.isOpen = true
tun.isEnabled = true
tun.ch = make(chan []byte, tun.iface.BatchSize())
go tun.queue()
go tun.read()
go tun.write()
return nil
@ -178,3 +197,12 @@ func (tun *TunAdapter) _stop() error {
}
return nil
}
const bufPoolSize = TUN_OFFSET_BYTES + 65535
var bufPool = sync.Pool{
New: func() any {
b := [bufPoolSize]byte{}
return b[:]
},
}