diff --git a/interface.go b/interface.go index 082906d9..0194a945 100644 --- a/interface.go +++ b/interface.go @@ -222,6 +222,13 @@ func (f *Interface) activate() { WithField("boringcrypto", boringEnabled()). Info("Nebula interface is active") + if f.routines > 1 { + if !f.inside.SupportsMultiqueue() || !f.outside.SupportsMultipleReaders() { + f.routines = 1 + f.l.Warn("routines is not supported on this platform, falling back to a single routine") + } + } + metrics.GetOrRegisterGauge("routines", nil).Update(int64(f.routines)) // Prepare n tun queues diff --git a/overlay/device.go b/overlay/device.go index 07146ab3..b6077aba 100644 --- a/overlay/device.go +++ b/overlay/device.go @@ -13,5 +13,6 @@ type Device interface { Networks() []netip.Prefix Name() string RoutesFor(netip.Addr) routing.Gateways + SupportsMultiqueue() bool NewMultiQueueReader() (io.ReadWriteCloser, error) } diff --git a/overlay/tun_android.go b/overlay/tun_android.go index df1ed8d8..eddef882 100644 --- a/overlay/tun_android.go +++ b/overlay/tun_android.go @@ -95,6 +95,10 @@ func (t *tun) Name() string { return "android" } +func (t *tun) SupportsMultiqueue() bool { + return false +} + func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return nil, fmt.Errorf("TODO: multiqueue not implemented for android") } diff --git a/overlay/tun_darwin.go b/overlay/tun_darwin.go index 34c2a71c..128c2001 100644 --- a/overlay/tun_darwin.go +++ b/overlay/tun_darwin.go @@ -549,6 +549,10 @@ func (t *tun) Name() string { return t.Device } +func (t *tun) SupportsMultiqueue() bool { + return false +} + func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return nil, fmt.Errorf("TODO: multiqueue not implemented for darwin") } diff --git a/overlay/tun_disabled.go b/overlay/tun_disabled.go index 131879d2..5d512963 100644 --- a/overlay/tun_disabled.go +++ b/overlay/tun_disabled.go @@ -105,6 +105,10 @@ func (t *disabledTun) Write(b []byte) (int, error) { return len(b), nil } +func (t *disabledTun) SupportsMultiqueue() bool { + return false +} + func (t *disabledTun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return t, nil } diff --git a/overlay/tun_freebsd.go b/overlay/tun_freebsd.go index 0dd82286..8d292263 100644 --- a/overlay/tun_freebsd.go +++ b/overlay/tun_freebsd.go @@ -450,6 +450,10 @@ func (t *tun) Name() string { return t.Device } +func (t *tun) SupportsMultiqueue() bool { + return false +} + func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return nil, fmt.Errorf("TODO: multiqueue not implemented for freebsd") } diff --git a/overlay/tun_ios.go b/overlay/tun_ios.go index e51e1120..0ce01df8 100644 --- a/overlay/tun_ios.go +++ b/overlay/tun_ios.go @@ -151,6 +151,10 @@ func (t *tun) Name() string { return "iOS" } +func (t *tun) SupportsMultiqueue() bool { + return false +} + func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return nil, fmt.Errorf("TODO: multiqueue not implemented for ios") } diff --git a/overlay/tun_linux.go b/overlay/tun_linux.go index 44d87465..f31ce2b7 100644 --- a/overlay/tun_linux.go +++ b/overlay/tun_linux.go @@ -216,6 +216,10 @@ func (t *tun) reload(c *config.C, initial bool) error { return nil } +func (t *tun) SupportsMultiqueue() bool { + return true +} + func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { fd, err := unix.Open("/dev/net/tun", os.O_RDWR, 0) if err != nil { diff --git a/overlay/tun_netbsd.go b/overlay/tun_netbsd.go index 49ac19fb..2986c895 100644 --- a/overlay/tun_netbsd.go +++ b/overlay/tun_netbsd.go @@ -390,6 +390,10 @@ func (t *tun) Name() string { return t.Device } +func (t *tun) SupportsMultiqueue() bool { + return false +} + func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return nil, fmt.Errorf("TODO: multiqueue not implemented for netbsd") } diff --git a/overlay/tun_openbsd.go b/overlay/tun_openbsd.go index 52d5297a..9209b795 100644 --- a/overlay/tun_openbsd.go +++ b/overlay/tun_openbsd.go @@ -310,6 +310,10 @@ func (t *tun) Name() string { return t.Device } +func (t *tun) SupportsMultiqueue() bool { + return false +} + func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return nil, fmt.Errorf("TODO: multiqueue not implemented for openbsd") } diff --git a/overlay/tun_tester.go b/overlay/tun_tester.go index b6712fbb..3477de3d 100644 --- a/overlay/tun_tester.go +++ b/overlay/tun_tester.go @@ -132,6 +132,10 @@ func (t *TestTun) Read(b []byte) (int, error) { return len(p), nil } +func (t *TestTun) SupportsMultiqueue() bool { + return false +} + func (t *TestTun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return nil, fmt.Errorf("TODO: multiqueue not implemented") } diff --git a/overlay/tun_windows.go b/overlay/tun_windows.go index 7aac1289..b4d78b66 100644 --- a/overlay/tun_windows.go +++ b/overlay/tun_windows.go @@ -234,6 +234,10 @@ func (t *winTun) Write(b []byte) (int, error) { return t.tun.Write(b, 0) } +func (t *winTun) SupportsMultiqueue() bool { + return false +} + func (t *winTun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return nil, fmt.Errorf("TODO: multiqueue not implemented for windows") } diff --git a/overlay/user.go b/overlay/user.go index 8a56d667..1f92d4e9 100644 --- a/overlay/user.go +++ b/overlay/user.go @@ -46,6 +46,10 @@ func (d *UserDevice) RoutesFor(ip netip.Addr) routing.Gateways { return routing.Gateways{routing.NewGateway(ip, 1)} } +func (d *UserDevice) SupportsMultiqueue() bool { + return true +} + func (d *UserDevice) NewMultiQueueReader() (io.ReadWriteCloser, error) { return d, nil } diff --git a/udp/conn.go b/udp/conn.go index 895b0df3..1ae585c2 100644 --- a/udp/conn.go +++ b/udp/conn.go @@ -19,6 +19,7 @@ type Conn interface { ListenOut(r EncReader) WriteTo(b []byte, addr netip.AddrPort) error ReloadConfig(c *config.C) + SupportsMultipleReaders() bool Close() error } @@ -33,6 +34,9 @@ func (NoopConn) LocalAddr() (netip.AddrPort, error) { func (NoopConn) ListenOut(_ EncReader) { return } +func (NoopConn) SupportsMultipleReaders() bool { + return false +} func (NoopConn) WriteTo(_ []byte, _ netip.AddrPort) error { return nil } diff --git a/udp/udp_darwin.go b/udp/udp_darwin.go index c0c6233c..db16d945 100644 --- a/udp/udp_darwin.go +++ b/udp/udp_darwin.go @@ -184,6 +184,10 @@ func (u *StdConn) ListenOut(r EncReader) { } } +func (u *StdConn) SupportsMultipleReaders() bool { + return false +} + func (u *StdConn) Rebind() error { var err error if u.isV4 { diff --git a/udp/udp_generic.go b/udp/udp_generic.go index cb21e574..3cefc904 100644 --- a/udp/udp_generic.go +++ b/udp/udp_generic.go @@ -85,3 +85,7 @@ func (u *GenericConn) ListenOut(r EncReader) { r(netip.AddrPortFrom(rua.Addr().Unmap(), rua.Port()), buffer[:n]) } } + +func (u *GenericConn) SupportsMultipleReaders() bool { + return false +} diff --git a/udp/udp_linux.go b/udp/udp_linux.go index ec0bf64b..e7759329 100644 --- a/udp/udp_linux.go +++ b/udp/udp_linux.go @@ -72,6 +72,10 @@ func NewListener(l *logrus.Logger, ip netip.Addr, port int, multi bool, batch in return &StdConn{sysFd: fd, isV4: ip.Is4(), l: l, batch: batch}, err } +func (u *StdConn) SupportsMultipleReaders() bool { + return true +} + func (u *StdConn) Rebind() error { return nil } diff --git a/udp/udp_rio_windows.go b/udp/udp_rio_windows.go index 886e0244..1d602d01 100644 --- a/udp/udp_rio_windows.go +++ b/udp/udp_rio_windows.go @@ -315,6 +315,10 @@ func (u *RIOConn) LocalAddr() (netip.AddrPort, error) { } +func (u *RIOConn) SupportsMultipleReaders() bool { + return false +} + func (u *RIOConn) Rebind() error { return nil } diff --git a/udp/udp_tester.go b/udp/udp_tester.go index 8d5e6c14..5f0f7765 100644 --- a/udp/udp_tester.go +++ b/udp/udp_tester.go @@ -127,6 +127,10 @@ func (u *TesterConn) LocalAddr() (netip.AddrPort, error) { return u.Addr, nil } +func (u *TesterConn) SupportsMultipleReaders() bool { + return false +} + func (u *TesterConn) Rebind() error { return nil }