diff --git a/udp/config.go b/udp/config.go new file mode 100644 index 0000000..98233ca --- /dev/null +++ b/udp/config.go @@ -0,0 +1,16 @@ +package udp + +import "sync/atomic" + +var disableUDPCsum atomic.Bool + +// SetDisableUDPCsum controls whether IPv4 UDP sockets opt out of kernel +// checksum calculation via SO_NO_CHECK. Only applicable on platforms that +// support the option (Linux). IPv6 always keeps the checksum enabled. +func SetDisableUDPCsum(disable bool) { + disableUDPCsum.Store(disable) +} + +func udpChecksumDisabled() bool { + return disableUDPCsum.Load() +} diff --git a/udp/msghdr_helper_linux_32.go b/udp/msghdr_helper_linux_32.go new file mode 100644 index 0000000..624bc0e --- /dev/null +++ b/udp/msghdr_helper_linux_32.go @@ -0,0 +1,25 @@ +//go:build linux && (386 || amd64p32 || arm || mips || mipsle) && !android && !e2e_testing +// +build linux +// +build 386 amd64p32 arm mips mipsle +// +build !android +// +build !e2e_testing + +package udp + +import "golang.org/x/sys/unix" + +func controllen(n int) uint32 { + return uint32(n) +} + +func setCmsgLen(h *unix.Cmsghdr, n int) { + h.Len = uint32(unix.CmsgLen(n)) +} + +func setIovecLen(v *unix.Iovec, n int) { + v.Len = uint32(n) +} + +func setMsghdrIovlen(m *unix.Msghdr, n int) { + m.Iovlen = uint32(n) +} diff --git a/udp/msghdr_helper_linux_64.go b/udp/msghdr_helper_linux_64.go new file mode 100644 index 0000000..9a4c71b --- /dev/null +++ b/udp/msghdr_helper_linux_64.go @@ -0,0 +1,25 @@ +//go:build linux && (amd64 || arm64 || ppc64 || ppc64le || mips64 || mips64le || s390x || riscv64 || loong64) && !android && !e2e_testing +// +build linux +// +build amd64 arm64 ppc64 ppc64le mips64 mips64le s390x riscv64 loong64 +// +build !android +// +build !e2e_testing + +package udp + +import "golang.org/x/sys/unix" + +func controllen(n int) uint64 { + return uint64(n) +} + +func setCmsgLen(h *unix.Cmsghdr, n int) { + h.Len = uint64(unix.CmsgLen(n)) +} + +func setIovecLen(v *unix.Iovec, n int) { + v.Len = uint64(n) +} + +func setMsghdrIovlen(m *unix.Msghdr, n int) { + m.Iovlen = uint64(n) +} diff --git a/udp/sendmmsg_linux_32.go b/udp/sendmmsg_linux_32.go new file mode 100644 index 0000000..fb2afec --- /dev/null +++ b/udp/sendmmsg_linux_32.go @@ -0,0 +1,25 @@ +//go:build linux && (386 || amd64p32 || arm || mips || mipsle) && !android && !e2e_testing + +package udp + +import ( + "unsafe" + + "golang.org/x/sys/unix" +) + +type linuxMmsgHdr struct { + Hdr unix.Msghdr + Len uint32 +} + +func sendmmsg(fd int, hdrs []linuxMmsgHdr, flags int) (int, error) { + if len(hdrs) == 0 { + return 0, nil + } + n, _, errno := unix.Syscall6(unix.SYS_SENDMMSG, uintptr(fd), uintptr(unsafe.Pointer(&hdrs[0])), uintptr(len(hdrs)), uintptr(flags), 0, 0) + if errno != 0 { + return int(n), errno + } + return int(n), nil +} diff --git a/udp/sendmmsg_linux_64.go b/udp/sendmmsg_linux_64.go new file mode 100644 index 0000000..2fa9920 --- /dev/null +++ b/udp/sendmmsg_linux_64.go @@ -0,0 +1,26 @@ +//go:build linux && (amd64 || arm64 || ppc64 || ppc64le || mips64 || mips64le || s390x || riscv64 || loong64) && !android && !e2e_testing + +package udp + +import ( + "unsafe" + + "golang.org/x/sys/unix" +) + +type linuxMmsgHdr struct { + Hdr unix.Msghdr + Len uint32 + _ uint32 +} + +func sendmmsg(fd int, hdrs []linuxMmsgHdr, flags int) (int, error) { + if len(hdrs) == 0 { + return 0, nil + } + n, _, errno := unix.Syscall6(unix.SYS_SENDMMSG, uintptr(fd), uintptr(unsafe.Pointer(&hdrs[0])), uintptr(len(hdrs)), uintptr(flags), 0, 0) + if errno != 0 { + return int(n), errno + } + return int(n), nil +}