2021-10-21 23:24:11 +02:00
|
|
|
//go:build !android && !e2e_testing
|
|
|
|
// +build !android,!e2e_testing
|
2020-06-30 20:48:58 +02:00
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
package udp
|
2019-11-19 18:00:20 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"syscall"
|
|
|
|
"unsafe"
|
|
|
|
|
2021-03-02 01:51:33 +01:00
|
|
|
"github.com/rcrowley/go-metrics"
|
2021-03-26 15:46:30 +01:00
|
|
|
"github.com/sirupsen/logrus"
|
2021-11-04 02:54:04 +01:00
|
|
|
"github.com/slackhq/nebula/config"
|
|
|
|
"github.com/slackhq/nebula/firewall"
|
|
|
|
"github.com/slackhq/nebula/header"
|
2019-11-19 18:00:20 +01:00
|
|
|
"golang.org/x/sys/unix"
|
|
|
|
)
|
|
|
|
|
|
|
|
//TODO: make it support reload as best you can!
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
type Conn struct {
|
2019-11-19 18:00:20 +01:00
|
|
|
sysFd int
|
2021-03-26 15:46:30 +01:00
|
|
|
l *logrus.Logger
|
2021-11-04 02:54:04 +01:00
|
|
|
batch int
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var x int
|
|
|
|
|
2021-03-02 01:51:33 +01:00
|
|
|
// From linux/sock_diag.h
|
|
|
|
const (
|
|
|
|
_SK_MEMINFO_RMEM_ALLOC = iota
|
|
|
|
_SK_MEMINFO_RCVBUF
|
|
|
|
_SK_MEMINFO_WMEM_ALLOC
|
|
|
|
_SK_MEMINFO_SNDBUF
|
|
|
|
_SK_MEMINFO_FWD_ALLOC
|
|
|
|
_SK_MEMINFO_WMEM_QUEUED
|
|
|
|
_SK_MEMINFO_OPTMEM
|
|
|
|
_SK_MEMINFO_BACKLOG
|
|
|
|
_SK_MEMINFO_DROPS
|
|
|
|
|
|
|
|
_SK_MEMINFO_VARS
|
|
|
|
)
|
|
|
|
|
|
|
|
type _SK_MEMINFO [_SK_MEMINFO_VARS]uint32
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func NewListener(l *logrus.Logger, ip string, port int, multi bool, batch int) (*Conn, error) {
|
2019-11-19 18:00:20 +01:00
|
|
|
syscall.ForkLock.RLock()
|
2021-03-19 02:37:24 +01:00
|
|
|
fd, err := unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, unix.IPPROTO_UDP)
|
2019-11-19 18:00:20 +01:00
|
|
|
if err == nil {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
unix.CloseOnExec(fd)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
syscall.ForkLock.RUnlock()
|
|
|
|
|
|
|
|
if err != nil {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
unix.Close(fd)
|
2019-11-23 00:22:31 +01:00
|
|
|
return nil, fmt.Errorf("unable to open socket: %s", err)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
2021-03-19 02:37:24 +01:00
|
|
|
var lip [16]byte
|
|
|
|
copy(lip[:], net.ParseIP(ip))
|
2019-11-19 18:00:20 +01:00
|
|
|
|
2020-08-13 00:24:05 +02:00
|
|
|
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)
|
|
|
|
}
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
2021-03-19 02:37:24 +01:00
|
|
|
//TODO: support multiple listening IPs (for limiting ipv6)
|
|
|
|
if err = unix.Bind(fd, &unix.SockaddrInet6{Addr: lip, Port: port}); err != nil {
|
2019-11-23 00:22:31 +01:00
|
|
|
return nil, fmt.Errorf("unable to bind to socket: %s", err)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: this may be useful for forcing threads into specific cores
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
//unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_INCOMING_CPU, x)
|
|
|
|
//v, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_INCOMING_CPU)
|
2019-11-19 18:00:20 +01:00
|
|
|
//l.Println(v, err)
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
return &Conn{sysFd: fd, l: l, batch: batch}, err
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) Rebind() error {
|
2020-09-18 16:20:09 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) SetRecvBuffer(n int) error {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, n)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) SetSendBuffer(n int) error {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_SNDBUFFORCE, n)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) GetRecvBuffer() (int, error) {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
return unix.GetsockoptInt(int(u.sysFd), unix.SOL_SOCKET, unix.SO_RCVBUF)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) GetSendBuffer() (int, error) {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
return unix.GetsockoptInt(int(u.sysFd), unix.SOL_SOCKET, unix.SO_SNDBUF)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) LocalAddr() (*Addr, error) {
|
2021-04-14 20:50:09 +02:00
|
|
|
sa, err := unix.Getsockname(u.sysFd)
|
|
|
|
if err != nil {
|
2019-11-19 18:00:20 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
addr := &Addr{}
|
2021-04-14 20:50:09 +02:00
|
|
|
switch sa := sa.(type) {
|
|
|
|
case *unix.SockaddrInet4:
|
|
|
|
addr.IP = net.IP{sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3]}.To16()
|
|
|
|
addr.Port = uint16(sa.Port)
|
|
|
|
case *unix.SockaddrInet6:
|
|
|
|
addr.IP = sa.Addr[0:]
|
|
|
|
addr.Port = uint16(sa.Port)
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
2021-03-19 02:37:24 +01:00
|
|
|
|
2019-11-19 18:00:20 +01:00
|
|
|
return addr, nil
|
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) ListenOut(r EncReader, lhf LightHouseHandlerFunc, cache *firewall.ConntrackCacheTicker, q int) {
|
|
|
|
plaintext := make([]byte, MTU)
|
|
|
|
h := &header.H{}
|
|
|
|
fwPacket := &firewall.Packet{}
|
|
|
|
udpAddr := &Addr{}
|
2019-11-19 18:00:20 +01:00
|
|
|
nb := make([]byte, 12, 12)
|
|
|
|
|
|
|
|
//TODO: should we track this?
|
|
|
|
//metric := metrics.GetOrRegisterHistogram("test.batch_read", nil, metrics.NewExpDecaySample(1028, 0.015))
|
2021-11-04 02:54:04 +01:00
|
|
|
msgs, buffers, names := u.PrepareRawMessages(u.batch)
|
2020-08-13 00:24:05 +02:00
|
|
|
read := u.ReadMulti
|
2021-11-04 02:54:04 +01:00
|
|
|
if u.batch == 1 {
|
2020-08-13 00:24:05 +02:00
|
|
|
read = u.ReadSingle
|
|
|
|
}
|
2019-11-19 18:00:20 +01:00
|
|
|
|
|
|
|
for {
|
2020-08-13 00:24:05 +02:00
|
|
|
n, err := read(msgs)
|
2019-11-19 18:00:20 +01:00
|
|
|
if err != nil {
|
2021-03-26 15:46:30 +01:00
|
|
|
u.l.WithError(err).Error("Failed to read packets")
|
2019-11-19 18:00:20 +01:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
//metric.Update(int64(n))
|
|
|
|
for i := 0; i < n; i++ {
|
2021-03-19 02:37:24 +01:00
|
|
|
udpAddr.IP = names[i][8:24]
|
2019-11-19 18:00:20 +01:00
|
|
|
udpAddr.Port = binary.BigEndian.Uint16(names[i][2:4])
|
2021-11-04 02:54:04 +01:00
|
|
|
r(udpAddr, plaintext[:0], buffers[i][:msgs[i].Len], h, fwPacket, lhf, nb, q, cache.Get(u.l))
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) ReadSingle(msgs []rawMessage) (int, error) {
|
2019-11-19 18:00:20 +01:00
|
|
|
for {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
n, _, err := unix.Syscall6(
|
2020-08-13 00:24:05 +02:00
|
|
|
unix.SYS_RECVMSG,
|
2019-11-19 18:00:20 +01:00
|
|
|
uintptr(u.sysFd),
|
2020-08-13 00:24:05 +02:00
|
|
|
uintptr(unsafe.Pointer(&(msgs[0].Hdr))),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2019-11-19 18:00:20 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
if err != 0 {
|
2020-08-13 00:24:05 +02:00
|
|
|
return 0, &net.OpError{Op: "recvmsg", Err: err}
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
|
2020-08-13 00:24:05 +02:00
|
|
|
msgs[0].Len = uint32(n)
|
|
|
|
return 1, nil
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) ReadMulti(msgs []rawMessage) (int, error) {
|
2019-11-19 18:00:20 +01:00
|
|
|
for {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
n, _, err := unix.Syscall6(
|
|
|
|
unix.SYS_RECVMMSG,
|
2019-11-19 18:00:20 +01:00
|
|
|
uintptr(u.sysFd),
|
|
|
|
uintptr(unsafe.Pointer(&msgs[0])),
|
|
|
|
uintptr(len(msgs)),
|
|
|
|
unix.MSG_WAITFORONE,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != 0 {
|
|
|
|
return 0, &net.OpError{Op: "recvmmsg", Err: err}
|
|
|
|
}
|
|
|
|
|
|
|
|
return int(n), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) WriteTo(b []byte, addr *Addr) error {
|
2019-11-19 18:00:20 +01:00
|
|
|
|
2021-03-19 02:37:24 +01:00
|
|
|
var rsa unix.RawSockaddrInet6
|
|
|
|
rsa.Family = unix.AF_INET6
|
2019-11-19 18:00:20 +01:00
|
|
|
p := (*[2]byte)(unsafe.Pointer(&rsa.Port))
|
|
|
|
p[0] = byte(addr.Port >> 8)
|
|
|
|
p[1] = byte(addr.Port)
|
2021-03-19 02:37:24 +01:00
|
|
|
copy(rsa.Addr[:], addr.IP)
|
2019-11-19 18:00:20 +01:00
|
|
|
|
|
|
|
for {
|
Add linux-386, linux-ppc64le targets (#56)
* Use golang.org/x/sys/unix for _linux.go sources
To support builds on GOARCH=386 and possibly elsewhere, it's necessary
to use the x/sys/unix package instead of the syscall package. This is
because the syscall package is frozen and does not support
SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386.
This commit alone doesn't add support for 386 builds, just gets things
onto x/sys/unix so that it's possible.
The remaining uses of the syscall package relate to signals, which
cannot be switched to the x/sys/unix package at this time. Windows
support breaks, so they can either continue using the syscall package
(it's frozen, this is safe for Go 1.x at minimum), or something can be
written to just use both windows- and unix-compatible signals.
* Add linux-386, ppc64le targets to Makefile
Because 'linux' is linux-amd64 already, just add linux-386 and
linux-ppc64le targets to distinguish them. Would rename the linux
target but that might break existing uses.
2019-12-12 02:51:55 +01:00
|
|
|
_, _, err := unix.Syscall6(
|
|
|
|
unix.SYS_SENDTO,
|
2019-11-19 18:00:20 +01:00
|
|
|
uintptr(u.sysFd),
|
|
|
|
uintptr(unsafe.Pointer(&b[0])),
|
|
|
|
uintptr(len(b)),
|
|
|
|
uintptr(0),
|
|
|
|
uintptr(unsafe.Pointer(&rsa)),
|
2021-03-19 02:37:24 +01:00
|
|
|
uintptr(unix.SizeofSockaddrInet6),
|
2019-11-19 18:00:20 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
if err != 0 {
|
|
|
|
return &net.OpError{Op: "sendto", Err: err}
|
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: handle incomplete writes
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) ReloadConfig(c *config.C) {
|
2019-11-19 18:00:20 +01:00
|
|
|
b := c.GetInt("listen.read_buffer", 0)
|
|
|
|
if b > 0 {
|
|
|
|
err := u.SetRecvBuffer(b)
|
|
|
|
if err == nil {
|
|
|
|
s, err := u.GetRecvBuffer()
|
|
|
|
if err == nil {
|
2021-03-26 15:46:30 +01:00
|
|
|
u.l.WithField("size", s).Info("listen.read_buffer was set")
|
2019-11-19 18:00:20 +01:00
|
|
|
} else {
|
2021-03-26 15:46:30 +01:00
|
|
|
u.l.WithError(err).Warn("Failed to get listen.read_buffer")
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
} else {
|
2021-03-26 15:46:30 +01:00
|
|
|
u.l.WithError(err).Error("Failed to set listen.read_buffer")
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
b = c.GetInt("listen.write_buffer", 0)
|
|
|
|
if b > 0 {
|
|
|
|
err := u.SetSendBuffer(b)
|
|
|
|
if err == nil {
|
|
|
|
s, err := u.GetSendBuffer()
|
|
|
|
if err == nil {
|
2021-03-26 15:46:30 +01:00
|
|
|
u.l.WithField("size", s).Info("listen.write_buffer was set")
|
2019-11-19 18:00:20 +01:00
|
|
|
} else {
|
2021-03-26 15:46:30 +01:00
|
|
|
u.l.WithError(err).Warn("Failed to get listen.write_buffer")
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
} else {
|
2021-03-26 15:46:30 +01:00
|
|
|
u.l.WithError(err).Error("Failed to set listen.write_buffer")
|
2019-11-19 18:00:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func (u *Conn) getMemInfo(meminfo *_SK_MEMINFO) error {
|
2021-03-02 01:51:33 +01:00
|
|
|
var vallen uint32 = 4 * _SK_MEMINFO_VARS
|
|
|
|
_, _, err := unix.Syscall6(unix.SYS_GETSOCKOPT, uintptr(u.sysFd), uintptr(unix.SOL_SOCKET), uintptr(unix.SO_MEMINFO), uintptr(unsafe.Pointer(meminfo)), uintptr(unsafe.Pointer(&vallen)), 0)
|
|
|
|
if err != 0 {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-11-04 02:54:04 +01:00
|
|
|
func NewUDPStatsEmitter(udpConns []*Conn) func() {
|
2021-03-02 01:51:33 +01:00
|
|
|
// Check if our kernel supports SO_MEMINFO before registering the gauges
|
|
|
|
var udpGauges [][_SK_MEMINFO_VARS]metrics.Gauge
|
|
|
|
var meminfo _SK_MEMINFO
|
|
|
|
if err := udpConns[0].getMemInfo(&meminfo); err == nil {
|
|
|
|
udpGauges = make([][_SK_MEMINFO_VARS]metrics.Gauge, len(udpConns))
|
|
|
|
for i := range udpConns {
|
|
|
|
udpGauges[i] = [_SK_MEMINFO_VARS]metrics.Gauge{
|
|
|
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.rmem_alloc", i), nil),
|
|
|
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.rcvbuf", i), nil),
|
|
|
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.wmem_alloc", i), nil),
|
|
|
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.sndbuf", i), nil),
|
|
|
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.fwd_alloc", i), nil),
|
|
|
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.wmem_queued", i), nil),
|
|
|
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.optmem", i), nil),
|
|
|
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.backlog", i), nil),
|
|
|
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.drops", i), nil),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return func() {
|
|
|
|
for i, gauges := range udpGauges {
|
|
|
|
if err := udpConns[i].getMemInfo(&meminfo); err == nil {
|
|
|
|
for j := 0; j < _SK_MEMINFO_VARS; j++ {
|
|
|
|
gauges[j].Update(int64(meminfo[j]))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|