internal/netlink: enlarge recvfrom buffer
All checks were successful
Test / Create distribution (push) Successful in 1m13s
Test / Sandbox (push) Successful in 3m3s
Test / Hakurei (push) Successful in 4m19s
Test / ShareFS (push) Successful in 4m16s
Test / Sandbox (race detector) (push) Successful in 5m32s
Test / Hakurei (race detector) (push) Successful in 6m44s
Test / Flake checks (push) Successful in 1m22s

This also uses an array type for the buffer since its size now uses the hardcoded value found in the kernel.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-03-25 17:11:57 +09:00
parent d2b635eb55
commit d62516ed1e
2 changed files with 13 additions and 12 deletions

View File

@@ -23,6 +23,9 @@ func getpid() uint32 {
return nlPid
}
// net/netlink/af_netlink.c
const maxRecvmsgLen = 32768
// A conn represents resources associated to a netlink socket.
type conn struct {
// AF_NETLINK socket.
@@ -37,8 +40,8 @@ type conn struct {
typ, flags uint16
// Outgoing position in buf.
pos int
// A page holding incoming and outgoing messages.
buf []byte
// Pages holding incoming and outgoing messages.
buf [maxRecvmsgLen]byte
// An instant some time after conn was established, but before the first
// I/O operation on f through raw. This serves as a cached deadline to
// cancel blocking I/O.
@@ -70,17 +73,19 @@ func dial(family int) (*conn, error) {
}
c.pos = syscall.NLMSG_HDRLEN
c.buf = make([]byte, os.Getpagesize())
c.t = time.Now().UTC()
return &c, nil
}
// ok returns whether conn is still open.
func (c *conn) ok() bool { return c.family >= 0 }
// Close closes the underlying socket.
func (c *conn) Close() error {
if c.buf == nil {
if !c.ok() {
return syscall.EINVAL
}
c.buf = nil
c.family = -1
return c.f.Close()
}
@@ -245,7 +250,7 @@ type HandlerFunc func(resp []syscall.NetlinkMessage) error
// returned by f. An error of type [Complete] is returned as nil.
func (c *conn) receive(ctx context.Context, f HandlerFunc, flags int) error {
for {
buf := c.buf
buf := c.buf[:]
if n, _, err := c.recvfrom(ctx, buf, flags); err != nil {
return err
} else if n < syscall.NLMSG_HDRLEN {
@@ -276,7 +281,7 @@ func (c *conn) receive(ctx context.Context, f HandlerFunc, flags int) error {
// Roundtrip sends the pending message and handles the reply.
func (c *conn) Roundtrip(ctx context.Context, f HandlerFunc) error {
if c.buf == nil {
if !c.ok() {
return syscall.EINVAL
}
defer func() { c.seq++ }()

View File

@@ -1,7 +1,6 @@
package netlink
import (
"os"
"syscall"
"testing"
)
@@ -23,10 +22,7 @@ func checkPayload(t *testing.T, testCases []payloadTestCase) {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
c := conn{
pos: syscall.NLMSG_HDRLEN,
buf: make([]byte, os.Getpagesize()),
}
c := conn{pos: syscall.NLMSG_HDRLEN}
tc.f(&c)
if got := c.pending(); string(got) != string(tc.want) {
t.Errorf("pending: %#v, want %#v", got, tc.want)