diff options
author | Bhasker Hariharan <bhaskerh@google.com> | 2019-01-29 01:37:54 -0800 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-01-29 01:39:01 -0800 |
commit | 24cb2c0a7256cdb515c2fc2cfc90d130e2a405ef (patch) | |
tree | 602c0214434145c9ee6518fbb6a2c422149e026a /pkg/tcpip/link/rawfile/rawfile_unsafe.go | |
parent | b44699c5299bb0fc1b16d25a9ac2250cf0a7446d (diff) |
Use recvmmsg() instead of readv() to read packets from NIC.
This should reduce the number of syscalls required to process packets
significantly and improve throughputs.
PiperOrigin-RevId: 231366886
Change-Id: I8b38077262bf9c53176bc4a94b530188d3d7c0ca
Diffstat (limited to 'pkg/tcpip/link/rawfile/rawfile_unsafe.go')
-rw-r--r-- | pkg/tcpip/link/rawfile/rawfile_unsafe.go | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/pkg/tcpip/link/rawfile/rawfile_unsafe.go b/pkg/tcpip/link/rawfile/rawfile_unsafe.go index be4a4fa9c..5deea093a 100644 --- a/pkg/tcpip/link/rawfile/rawfile_unsafe.go +++ b/pkg/tcpip/link/rawfile/rawfile_unsafe.go @@ -124,7 +124,7 @@ func BlockingRead(fd int, b []byte) (int, *tcpip.Error) { // BlockingReadv reads from a file descriptor that is set up as non-blocking and // stores the data in a list of iovecs buffers. If no data is available, it will -// block in a poll() syscall until the file descirptor becomes readable. +// block in a poll() syscall until the file descriptor becomes readable. func BlockingReadv(fd int, iovecs []syscall.Iovec) (int, *tcpip.Error) { for { n, _, e := syscall.RawSyscall(syscall.SYS_READV, uintptr(fd), uintptr(unsafe.Pointer(&iovecs[0])), uintptr(len(iovecs))) @@ -143,3 +143,32 @@ func BlockingReadv(fd int, iovecs []syscall.Iovec) (int, *tcpip.Error) { } } } + +// MMsgHdr represents the mmsg_hdr structure required by recvmmsg() on linux. +type MMsgHdr struct { + Msg syscall.Msghdr + Len uint32 + _ [4]byte +} + +// BlockingRecvMMsg reads from a file descriptor that is set up as non-blocking +// and stores the received messages in a slice of MMsgHdr structures. If no data +// is available, it will block in a poll() syscall until the file descriptor +// becomes readable. +func BlockingRecvMMsg(fd int, msgHdrs []MMsgHdr) (int, *tcpip.Error) { + for { + n, _, e := syscall.RawSyscall6(syscall.SYS_RECVMMSG, uintptr(fd), uintptr(unsafe.Pointer(&msgHdrs[0])), uintptr(len(msgHdrs)), syscall.MSG_DONTWAIT, 0, 0) + if e == 0 { + return int(n), nil + } + + event := pollEvent{ + fd: int32(fd), + events: 1, // POLLIN + } + + if _, e := blockingPoll(&event, 1, -1); e != 0 && e != syscall.EINTR { + return 0, TranslateErrno(e) + } + } +} |