Align linux UDP performance optimizations with configuration (#275)

* Remove unused (*udpConn).Read method

* Align linux UDP performance optimizations with configuration

While attempting to run nebula on an older Synology NAS, it became
apparent that some of the performance optimizations effectively
block support for older kernels. The recvmmsg syscall was added in
linux kernel 2.6.33, and the Synology DS212j (among other models)
is pinned to 2.6.32.12.

Similarly, SO_REUSEPORT was added to the kernel in the 3.9 cycle.
While this option has been backported into some older trees, it
is also missing from the Synology kernel.

This commit allows nebula to be run on linux devices with older
kernels if the config options are set up with a single listener
and a UDP batch size of 1.
This commit is contained in:
forfuncsake 2020-08-13 08:24:05 +10:00 committed by GitHub
parent 32fe9bfe75
commit 2e5a477a50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 19 additions and 23 deletions

View File

@ -71,8 +71,10 @@ func NewListener(ip string, port int, multi bool) (*udpConn, error) {
var lip [4]byte
copy(lip[:], net.ParseIP(ip).To4())
if err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
return nil, fmt.Errorf("unable to set SO_REUSEPORT: %s", err)
if multi {
if err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
return nil, fmt.Errorf("unable to set SO_REUSEPORT: %s", err)
}
}
if err = unix.Bind(fd, &unix.SockaddrInet4{Addr: lip, Port: port}); err != nil {
@ -143,9 +145,13 @@ func (u *udpConn) ListenOut(f *Interface) {
//TODO: should we track this?
//metric := metrics.GetOrRegisterHistogram("test.batch_read", nil, metrics.NewExpDecaySample(1028, 0.015))
msgs, buffers, names := u.PrepareRawMessages(f.udpBatchSize)
read := u.ReadMulti
if f.udpBatchSize == 1 {
read = u.ReadSingle
}
for {
n, err := u.ReadMulti(msgs)
n, err := read(msgs)
if err != nil {
l.WithError(err).Error("Failed to read packets")
continue
@ -161,34 +167,24 @@ func (u *udpConn) ListenOut(f *Interface) {
}
}
func (u *udpConn) Read(addr *udpAddr, b []byte) ([]byte, error) {
var rsa rawSockaddrAny
var rLen = unix.SizeofSockaddrAny
func (u *udpConn) ReadSingle(msgs []rawMessage) (int, error) {
for {
n, _, err := unix.Syscall6(
unix.SYS_RECVFROM,
unix.SYS_RECVMSG,
uintptr(u.sysFd),
uintptr(unsafe.Pointer(&b[0])),
uintptr(len(b)),
uintptr(0),
uintptr(unsafe.Pointer(&rsa)),
uintptr(unsafe.Pointer(&rLen)),
uintptr(unsafe.Pointer(&(msgs[0].Hdr))),
0,
0,
0,
0,
)
if err != 0 {
return nil, &net.OpError{Op: "read", Err: err}
return 0, &net.OpError{Op: "recvmsg", Err: err}
}
if rsa.Addr.Family == unix.AF_INET {
addr.Port = uint16(rsa.Addr.Data[0])<<8 + uint16(rsa.Addr.Data[1])
addr.IP = uint32(rsa.Addr.Data[2])<<24 + uint32(rsa.Addr.Data[3])<<16 + uint32(rsa.Addr.Data[4])<<8 + uint32(rsa.Addr.Data[5])
} else {
addr.Port = 0
addr.IP = 0
}
return b[:n], nil
msgs[0].Len = uint32(n)
return 1, nil
}
}