aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-03-30 02:14:47 +0900
committerOphestra <cat@gensokyo.uk>2026-03-30 02:14:47 +0900
commit584e30216896fd4de6301f9cf937829e16d22c49 (patch)
treec9838372b7bf39cb9508e318634f405868dfd05a
parent141958656f8a83a4f5703bd4890389dd1f180e0a (diff)
internal/netlink: set receive buffer size
This is done by both systemd sd-device and AOSP ueventd to improve robustness. Rosa OS will still handle ENOBUFS via coldboot but a big buffer should mitigate this as well. Signed-off-by: Ophestra <cat@gensokyo.uk>
-rw-r--r--container/dispatcher.go2
-rw-r--r--internal/netlink/netlink.go23
-rw-r--r--internal/netlink/rtnl.go4
-rw-r--r--internal/uevent/uevent.go4
-rw-r--r--internal/uevent/uevent_test.go4
5 files changed, 29 insertions, 8 deletions
diff --git a/container/dispatcher.go b/container/dispatcher.go
index 9f971fa5..d3ff4f00 100644
--- a/container/dispatcher.go
+++ b/container/dispatcher.go
@@ -179,7 +179,7 @@ func (direct) mustLoopback(ctx context.Context, msg message.Msg) {
lo = ifi.Index
}
- c, err := netlink.DialRoute()
+ c, err := netlink.DialRoute(0)
if err != nil {
msg.GetLogger().Fatalln(err)
}
diff --git a/internal/netlink/netlink.go b/internal/netlink/netlink.go
index 7324f1a7..6cd15610 100644
--- a/internal/netlink/netlink.go
+++ b/internal/netlink/netlink.go
@@ -46,7 +46,11 @@ type Conn struct {
// Dial returns the address of a newly connected generic netlink connection of
// specified family and groups.
-func Dial(family int, groups uint32) (*Conn, error) {
+//
+// For a nonzero rcvbuf, the socket receive buffer size is set to its absolute
+// value via SO_RCVBUF for a positive value, or SO_RCVBUFFORCE for a negative
+// value.
+func Dial(family int, groups uint32, rcvbuf int64) (*Conn, error) {
var c Conn
if fd, err := syscall.Socket(
syscall.AF_NETLINK,
@@ -75,6 +79,23 @@ func Dial(family int, groups uint32) (*Conn, error) {
return nil, syscall.ENOTRECOVERABLE
}
+ if rcvbuf != 0 {
+ opt := syscall.SO_RCVBUF
+ if rcvbuf < 0 {
+ opt = syscall.SO_RCVBUFFORCE
+ rcvbuf = -rcvbuf
+ }
+ if err = syscall.SetsockoptInt(
+ fd,
+ syscall.SOL_SOCKET,
+ opt,
+ int(rcvbuf),
+ ); err != nil {
+ _ = syscall.Close(fd)
+ return nil, os.NewSyscallError("setsockopt", err)
+ }
+ }
+
c.family = family
c.f = os.NewFile(uintptr(fd), "netlink")
if c.raw, err = c.f.SyscallConn(); err != nil {
diff --git a/internal/netlink/rtnl.go b/internal/netlink/rtnl.go
index e370bae7..521e8569 100644
--- a/internal/netlink/rtnl.go
+++ b/internal/netlink/rtnl.go
@@ -13,8 +13,8 @@ type RouteConn struct{ conn *Conn }
func (c *RouteConn) Close() error { return c.conn.Close() }
// DialRoute returns the address of a newly connected [RouteConn].
-func DialRoute() (*RouteConn, error) {
- c, err := Dial(syscall.NETLINK_ROUTE, 0)
+func DialRoute(rcvbuf int64) (*RouteConn, error) {
+ c, err := Dial(syscall.NETLINK_ROUTE, 0, rcvbuf)
if err != nil {
return nil, err
}
diff --git a/internal/uevent/uevent.go b/internal/uevent/uevent.go
index 47091f59..25fd02be 100644
--- a/internal/uevent/uevent.go
+++ b/internal/uevent/uevent.go
@@ -50,9 +50,9 @@ func (c *Conn) exitExcl() { c.excl.Store(false) }
func (c *Conn) Close() error { return c.conn.Close() }
// Dial returns the address of a newly connected [Conn].
-func Dial() (*Conn, error) {
+func Dial(rcvbuf int64) (*Conn, error) {
// kernel group is hard coded in lib/kobject_uevent.c, undocumented
- c, err := netlink.Dial(syscall.NETLINK_KOBJECT_UEVENT, 1)
+ c, err := netlink.Dial(syscall.NETLINK_KOBJECT_UEVENT, 1, rcvbuf)
if err != nil {
return nil, err
}
diff --git a/internal/uevent/uevent_test.go b/internal/uevent/uevent_test.go
index 7dce4798..9b986ff3 100644
--- a/internal/uevent/uevent_test.go
+++ b/internal/uevent/uevent_test.go
@@ -116,7 +116,7 @@ func adeB[V any, S interface {
func TestDialConsume(t *testing.T) {
t.Parallel()
- c, err := uevent.Dial()
+ c, err := uevent.Dial(0)
if err != nil {
t.Fatalf("Dial: error = %v", err)
}
@@ -127,7 +127,7 @@ func TestDialConsume(t *testing.T) {
})
// check kernel-assigned port id
- c0, err0 := uevent.Dial()
+ c0, err0 := uevent.Dial(0)
if err0 != nil {
t.Fatalf("Dial: error = %v", err)
}