summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip
diff options
context:
space:
mode:
authorBhasker Hariharan <bhaskerh@google.com>2021-02-09 21:52:50 -0800
committergVisor bot <gvisor-bot@google.com>2021-02-09 21:55:16 -0800
commit298c129cc151e197db35a927f9676cc40ec80d5c (patch)
treeab9ef4a5992e53a5020522018b1ea48b8a86bcbf /pkg/tcpip
parent2de36e44ed753c4cef2f9d71499fad6d87cb8b86 (diff)
Add support for setting SO_SNDBUF for unix domain sockets.
The limits for snd/rcv buffers for unix domain socket is controlled by the following sysctls on linux - net.core.rmem_default - net.core.rmem_max - net.core.wmem_default - net.core.wmem_max Today in gVisor we do not expose these sysctls but we do support setting the equivalent in netstack via stack.Options() method. But AF_UNIX sockets in gVisor can be used without netstack, with hostinet or even without any networking stack at all. Which means ideally these sysctls need to live as globals in gVisor. But rather than make this a big change for now we hardcode the limits in the AF_UNIX implementation itself (which in itself is better than where we were before) where it SO_SNDBUF was hardcoded to 16KiB. Further we bump the initial limit to a default value of 208 KiB to match linux from the paltry 16 KiB we use today. Updates #5132 PiperOrigin-RevId: 356665498
Diffstat (limited to 'pkg/tcpip')
-rw-r--r--pkg/tcpip/socketops.go73
-rw-r--r--pkg/tcpip/transport/tcp/endpoint.go6
-rw-r--r--pkg/tcpip/transport/tcp/tcp_test.go7
3 files changed, 35 insertions, 51 deletions
diff --git a/pkg/tcpip/socketops.go b/pkg/tcpip/socketops.go
index 1e00144a5..dc37e61a4 100644
--- a/pkg/tcpip/socketops.go
+++ b/pkg/tcpip/socketops.go
@@ -54,11 +54,10 @@ type SocketOptionsHandler interface {
// HasNIC is invoked to check if the NIC is valid for SO_BINDTODEVICE.
HasNIC(v int32) bool
- // GetSendBufferSize is invoked to get the SO_SNDBUFSIZE.
- GetSendBufferSize() (int64, Error)
-
- // IsUnixSocket is invoked to check if the socket is of unix domain.
- IsUnixSocket() bool
+ // OnSetSendBufferSize is invoked when the send buffer size for an endpoint is
+ // changed. The handler is invoked with the new value for the socket send
+ // buffer size. It also returns the newly set value.
+ OnSetSendBufferSize(v int64) (newSz int64)
}
// DefaultSocketOptionsHandler is an embeddable type that implements no-op
@@ -95,14 +94,9 @@ func (*DefaultSocketOptionsHandler) HasNIC(int32) bool {
return false
}
-// GetSendBufferSize implements SocketOptionsHandler.GetSendBufferSize.
-func (*DefaultSocketOptionsHandler) GetSendBufferSize() (int64, Error) {
- return 0, nil
-}
-
-// IsUnixSocket implements SocketOptionsHandler.IsUnixSocket.
-func (*DefaultSocketOptionsHandler) IsUnixSocket() bool {
- return false
+// OnSetSendBufferSize implements SocketOptionsHandler.OnSetSendBufferSize.
+func (*DefaultSocketOptionsHandler) OnSetSendBufferSize(v int64) (newSz int64) {
+ return v
}
// StackHandler holds methods to access the stack options. These must be
@@ -600,42 +594,41 @@ func (so *SocketOptions) SetBindToDevice(bindToDevice int32) Error {
}
// GetSendBufferSize gets value for SO_SNDBUF option.
-func (so *SocketOptions) GetSendBufferSize() (int64, Error) {
- if so.handler.IsUnixSocket() {
- return so.handler.GetSendBufferSize()
- }
- return atomic.LoadInt64(&so.sendBufferSize), nil
+func (so *SocketOptions) GetSendBufferSize() int64 {
+ return atomic.LoadInt64(&so.sendBufferSize)
}
// SetSendBufferSize sets value for SO_SNDBUF option. notify indicates if the
// stack handler should be invoked to set the send buffer size.
func (so *SocketOptions) SetSendBufferSize(sendBufferSize int64, notify bool) {
- if so.handler.IsUnixSocket() {
+ v := sendBufferSize
+
+ if !notify {
+ atomic.StoreInt64(&so.sendBufferSize, v)
return
}
- v := sendBufferSize
- if notify {
- // TODO(b/176170271): Notify waiters after size has grown.
- // Make sure the send buffer size is within the min and max
- // allowed.
- ss := so.getSendBufferLimits(so.stackHandler)
- min := int64(ss.Min)
- max := int64(ss.Max)
- // Validate the send buffer size with min and max values.
- // Multiply it by factor of 2.
- if v > max {
- v = max
- }
+ // Make sure the send buffer size is within the min and max
+ // allowed.
+ ss := so.getSendBufferLimits(so.stackHandler)
+ min := int64(ss.Min)
+ max := int64(ss.Max)
+ // Validate the send buffer size with min and max values.
+ // Multiply it by factor of 2.
+ if v > max {
+ v = max
+ }
- if v < math.MaxInt32/PacketOverheadFactor {
- v *= PacketOverheadFactor
- if v < min {
- v = min
- }
- } else {
- v = math.MaxInt32
+ if v < math.MaxInt32/PacketOverheadFactor {
+ v *= PacketOverheadFactor
+ if v < min {
+ v = min
}
+ } else {
+ v = math.MaxInt32
}
- atomic.StoreInt64(&so.sendBufferSize, v)
+
+ // Notify endpoint about change in buffer size.
+ newSz := so.handler.OnSetSendBufferSize(v)
+ atomic.StoreInt64(&so.sendBufferSize, newSz)
}
diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go
index 4e5a6089f..8c5be0586 100644
--- a/pkg/tcpip/transport/tcp/endpoint.go
+++ b/pkg/tcpip/transport/tcp/endpoint.go
@@ -1698,11 +1698,7 @@ func (e *endpoint) OnCorkOptionSet(v bool) {
}
func (e *endpoint) getSendBufferSize() int {
- sndBufSize, err := e.ops.GetSendBufferSize()
- if err != nil {
- panic(fmt.Sprintf("e.ops.GetSendBufferSize() = %s", err))
- }
- return int(sndBufSize)
+ return int(e.ops.GetSendBufferSize())
}
// SetSockOptInt sets a socket option.
diff --git a/pkg/tcpip/transport/tcp/tcp_test.go b/pkg/tcpip/transport/tcp/tcp_test.go
index cd3c4a027..0128c1f7e 100644
--- a/pkg/tcpip/transport/tcp/tcp_test.go
+++ b/pkg/tcpip/transport/tcp/tcp_test.go
@@ -4393,12 +4393,7 @@ func checkRecvBufferSize(t *testing.T, ep tcpip.Endpoint, v int) {
func checkSendBufferSize(t *testing.T, ep tcpip.Endpoint, v int) {
t.Helper()
- s, err := ep.SocketOptions().GetSendBufferSize()
- if err != nil {
- t.Fatalf("GetSendBufferSize failed: %s", err)
- }
-
- if int(s) != v {
+ if s := ep.SocketOptions().GetSendBufferSize(); int(s) != v {
t.Fatalf("got send buffer size = %d, want = %d", s, v)
}
}