Skip to content

Commit

Permalink
handle: get/set receive buffer size
Browse files Browse the repository at this point in the history
When receiving a lot of route changes (10,000 routes are enough), the
default receive buffer size (value of
`/proc/sys/net/core/rmem_default`) is too small and we get a `ENOBUF`
error. A user may want to increase the buffer size up to the value of
`/proc/sys/net/core/rmem_max` (by default, this is the same value). A
`SetSocketReceiveBufferSize()` function is provided to this
destination.

Possible improvements:

 1. automatically increase receive buffer size in higher level
    functions until we hit a maximum (get an error and/or the current
    value is smaller than expected)

 2. accept a "force" argument to use `SO_RCVBUFFORCE` to increase the
    value over `rmem_max` value
  • Loading branch information
vincentbernat authored and vishvananda committed Oct 20, 2017
1 parent ef2b2c4 commit ef84ebb
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
32 changes: 32 additions & 0 deletions handle_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,38 @@ func (h *Handle) SetSocketTimeout(to time.Duration) error {
return nil
}

// SetSocketReceiveBufferSize sets the receive buffer size for each
// socket in the netlink handle. The maximum value is capped by
// /proc/sys/net/core/rmem_max.
func (h *Handle) SetSocketReceiveBufferSize(size int) error {
for _, sh := range h.sockets {
fd := sh.Socket.GetFd()
err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, size)
if err != nil {
return err
}
}
return nil
}

// GetSocketReceiveBufferSize gets the receiver buffer size for each
// socket in the netlink handle. The retrieved value should be the
// double to the one set for SetSocketReceiveBufferSize.
func (h *Handle) GetSocketReceiveBufferSize() ([]int, error) {
results := make([]int, len(h.sockets))
i := 0
for _, sh := range h.sockets {
fd := sh.Socket.GetFd()
size, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF)
if err != nil {
return nil, err
}
results[i] = size
i++
}
return results, nil
}

// NewHandle returns a netlink handle on the network namespace
// specified by ns. If ns=netns.None(), current network namespace
// will be assumed
Expand Down
25 changes: 25 additions & 0 deletions handle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,31 @@ func TestHandleTimeout(t *testing.T) {
}
}

func TestHandleReceiveBuffer(t *testing.T) {
h, err := NewHandle()
if err != nil {
t.Fatal(err)
}
defer h.Delete()
if err := h.SetSocketReceiveBufferSize(65536); err != nil {
t.Fatal(err)
}
sizes, err := h.GetSocketReceiveBufferSize()
if err != nil {
t.Fatal(err)
}
if len(sizes) != len(h.sockets) {
t.Fatalf("Unexpected number of socket buffer sizes: %d (expected %d)",
len(sizes), len(h.sockets))
}
for _, s := range sizes {
if s < 65536 || s > 2*65536 {
t.Fatalf("Unexpected socket receive buffer size: %d (expected around %d)",
s, 65536)
}
}
}

func verifySockTimeVal(t *testing.T, fd int, tv syscall.Timeval) {
var (
tr syscall.Timeval
Expand Down

0 comments on commit ef84ebb

Please # to comment.