Skip to content

Commit 2824b70

Browse files
hbhaskergvisor-bot
authored andcommitted
Support setsockopt SO_SNDBUF/SO_RCVBUF for raw/udp sockets.
Updates #173,#6 Fixes #2888 PiperOrigin-RevId: 312689994
1 parent d58d576 commit 2824b70

File tree

17 files changed

+816
-99
lines changed

17 files changed

+816
-99
lines changed

benchmarks/tcp/tcp_proxy.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -228,19 +228,19 @@ func newNetstackImpl(mode string) (impl, error) {
228228
})
229229

230230
// Set protocol options.
231-
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, tcp.SACKEnabled(*sack)); err != nil {
232-
return nil, fmt.Errorf("SetTransportProtocolOption for SACKEnabled failed: %v", err)
231+
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.StackSACKEnabled(*sack)); err != nil {
232+
return nil, fmt.Errorf("SetTransportProtocolOption for SACKEnabled failed: %s", err)
233233
}
234234

235235
// Enable Receive Buffer Auto-Tuning.
236236
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.ModerateReceiveBufferOption(*moderateRecvBuf)); err != nil {
237-
return nil, fmt.Errorf("SetTransportProtocolOption failed: %v", err)
237+
return nil, fmt.Errorf("SetTransportProtocolOption failed: %s", err)
238238
}
239239

240240
// Set Congestion Control to cubic if requested.
241241
if *cubic {
242242
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.CongestionControlOption("cubic")); err != nil {
243-
return nil, fmt.Errorf("SetTransportProtocolOption for CongestionControlOption(cubic) failed: %v", err)
243+
return nil, fmt.Errorf("SetTransportProtocolOption for CongestionControlOption(cubic) failed: %s", err)
244244
}
245245
}
246246

pkg/sentry/socket/netstack/stack.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func (s *Stack) AddInterfaceAddr(idx int32, addr inet.InterfaceAddr) error {
144144

145145
// TCPReceiveBufferSize implements inet.Stack.TCPReceiveBufferSize.
146146
func (s *Stack) TCPReceiveBufferSize() (inet.TCPBufferSize, error) {
147-
var rs tcp.ReceiveBufferSizeOption
147+
var rs tcpip.StackReceiveBufferSizeOption
148148
err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &rs)
149149
return inet.TCPBufferSize{
150150
Min: rs.Min,
@@ -155,7 +155,7 @@ func (s *Stack) TCPReceiveBufferSize() (inet.TCPBufferSize, error) {
155155

156156
// SetTCPReceiveBufferSize implements inet.Stack.SetTCPReceiveBufferSize.
157157
func (s *Stack) SetTCPReceiveBufferSize(size inet.TCPBufferSize) error {
158-
rs := tcp.ReceiveBufferSizeOption{
158+
rs := tcpip.StackReceiveBufferSizeOption{
159159
Min: size.Min,
160160
Default: size.Default,
161161
Max: size.Max,
@@ -165,7 +165,7 @@ func (s *Stack) SetTCPReceiveBufferSize(size inet.TCPBufferSize) error {
165165

166166
// TCPSendBufferSize implements inet.Stack.TCPSendBufferSize.
167167
func (s *Stack) TCPSendBufferSize() (inet.TCPBufferSize, error) {
168-
var ss tcp.SendBufferSizeOption
168+
var ss tcpip.StackSendBufferSizeOption
169169
err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &ss)
170170
return inet.TCPBufferSize{
171171
Min: ss.Min,
@@ -176,7 +176,7 @@ func (s *Stack) TCPSendBufferSize() (inet.TCPBufferSize, error) {
176176

177177
// SetTCPSendBufferSize implements inet.Stack.SetTCPSendBufferSize.
178178
func (s *Stack) SetTCPSendBufferSize(size inet.TCPBufferSize) error {
179-
ss := tcp.SendBufferSizeOption{
179+
ss := tcpip.StackSendBufferSizeOption{
180180
Min: size.Min,
181181
Default: size.Default,
182182
Max: size.Max,
@@ -186,14 +186,14 @@ func (s *Stack) SetTCPSendBufferSize(size inet.TCPBufferSize) error {
186186

187187
// TCPSACKEnabled implements inet.Stack.TCPSACKEnabled.
188188
func (s *Stack) TCPSACKEnabled() (bool, error) {
189-
var sack tcp.SACKEnabled
189+
var sack tcpip.StackSACKEnabled
190190
err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &sack)
191191
return bool(sack), syserr.TranslateNetstackError(err).ToError()
192192
}
193193

194194
// SetTCPSACKEnabled implements inet.Stack.SetTCPSACKEnabled.
195195
func (s *Stack) SetTCPSACKEnabled(enabled bool) error {
196-
return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, tcp.SACKEnabled(enabled))).ToError()
196+
return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.StackSACKEnabled(enabled))).ToError()
197197
}
198198

199199
// Statistics implements inet.Stack.Statistics.

pkg/tcpip/tcpip.go

+26
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,32 @@ type OutOfBandInlineOption int
813813
// a default TTL.
814814
type DefaultTTLOption uint8
815815

816+
// StackSACKEnabled is used by stack.(*Stack).TransportProtocolOption to
817+
// enable/disable SACK support in TCP. See: https://tools.ietf.org/html/rfc2018.
818+
type StackSACKEnabled bool
819+
820+
// StackDelayEnabled is used by stack.(Stack*).TransportProtocolOption to
821+
// enable/disable Nagle's algorithm in TCP.
822+
type StackDelayEnabled bool
823+
824+
// StackSendBufferSizeOption is used by stack.(Stack*).TransportProtocolOption
825+
// to get/set the default, min and max send buffer sizes.
826+
type StackSendBufferSizeOption struct {
827+
Min int
828+
Default int
829+
Max int
830+
}
831+
832+
// StackReceiveBufferSizeOption is used by
833+
// stack.(Stack*).TransportProtocolOption to get/set the default, min and max
834+
// receive buffer sizes.
835+
type StackReceiveBufferSizeOption struct {
836+
Min int
837+
Default int
838+
Max int
839+
}
840+
841+
//
816842
// IPPacketInfo is the message struture for IP_PKTINFO.
817843
//
818844
// +stateify savable

pkg/tcpip/transport/raw/endpoint.go

+62-9
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
package raw
2727

2828
import (
29+
"fmt"
30+
2931
"gvisor.dev/gvisor/pkg/sync"
3032
"gvisor.dev/gvisor/pkg/tcpip"
3133
"gvisor.dev/gvisor/pkg/tcpip/buffer"
@@ -66,16 +68,17 @@ type endpoint struct {
6668
// protected by rcvMu.
6769
rcvMu sync.Mutex `state:"nosave"`
6870
rcvList rawPacketList
69-
rcvBufSizeMax int `state:".(int)"`
7071
rcvBufSize int
72+
rcvBufSizeMax int `state:".(int)"`
7173
rcvClosed bool
7274

7375
// The following fields are protected by mu.
74-
mu sync.RWMutex `state:"nosave"`
75-
sndBufSize int
76-
closed bool
77-
connected bool
78-
bound bool
76+
mu sync.RWMutex `state:"nosave"`
77+
sndBufSize int
78+
sndBufSizeMax int
79+
closed bool
80+
connected bool
81+
bound bool
7982
// route is the route to a remote network endpoint. It is set via
8083
// Connect(), and is valid only when conneted is true.
8184
route stack.Route `state:"manual"`
@@ -103,10 +106,21 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProt
103106
},
104107
waiterQueue: waiterQueue,
105108
rcvBufSizeMax: 32 * 1024,
106-
sndBufSize: 32 * 1024,
109+
sndBufSizeMax: 32 * 1024,
107110
associated: associated,
108111
}
109112

113+
// Override with stack defaults.
114+
var ss tcpip.StackSendBufferSizeOption
115+
if err := s.TransportProtocolOption(transProto, &ss); err == nil {
116+
e.sndBufSizeMax = ss.Default
117+
}
118+
119+
var rs tcpip.StackReceiveBufferSizeOption
120+
if err := s.TransportProtocolOption(transProto, &rs); err == nil {
121+
e.rcvBufSizeMax = rs.Default
122+
}
123+
110124
// Unassociated endpoints are write-only and users call Write() with IP
111125
// headers included. Because they're write-only, We don't need to
112126
// register with the stack.
@@ -523,7 +537,46 @@ func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
523537

524538
// SetSockOptInt implements tcpip.Endpoint.SetSockOptInt.
525539
func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
526-
return tcpip.ErrUnknownProtocolOption
540+
switch opt {
541+
case tcpip.SendBufferSizeOption:
542+
// Make sure the send buffer size is within the min and max
543+
// allowed.
544+
var ss tcpip.StackSendBufferSizeOption
545+
if err := e.stack.TransportProtocolOption(e.TransProto, &ss); err != nil {
546+
panic(fmt.Sprintf("s.TransportProtocolOption(%d, %+v) = %s", e.TransProto, ss, err))
547+
}
548+
if v > ss.Max {
549+
v = ss.Max
550+
}
551+
if v < ss.Min {
552+
v = ss.Min
553+
}
554+
e.mu.Lock()
555+
e.sndBufSizeMax = v
556+
e.mu.Unlock()
557+
return nil
558+
559+
case tcpip.ReceiveBufferSizeOption:
560+
// Make sure the receive buffer size is within the min and max
561+
// allowed.
562+
var rs tcpip.StackReceiveBufferSizeOption
563+
if err := e.stack.TransportProtocolOption(e.TransProto, &rs); err != nil {
564+
panic(fmt.Sprintf("s.TransportProtocolOption(%d, %+v) = %s", e.TransProto, rs, err))
565+
}
566+
if v > rs.Max {
567+
v = rs.Max
568+
}
569+
if v < rs.Min {
570+
v = rs.Min
571+
}
572+
e.rcvMu.Lock()
573+
e.rcvBufSizeMax = v
574+
e.rcvMu.Unlock()
575+
return nil
576+
577+
default:
578+
return tcpip.ErrUnknownProtocolOption
579+
}
527580
}
528581

529582
// GetSockOpt implements tcpip.Endpoint.GetSockOpt.
@@ -563,7 +616,7 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
563616

564617
case tcpip.SendBufferSizeOption:
565618
e.mu.Lock()
566-
v := e.sndBufSize
619+
v := e.sndBufSizeMax
567620
e.mu.Unlock()
568621
return v, nil
569622

pkg/tcpip/transport/tcp/connect.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ func (h *handshake) execute() *tcpip.Error {
521521
s.AddWaker(&h.ep.newSegmentWaker, wakerForNewSegment)
522522
defer s.Done()
523523

524-
var sackEnabled SACKEnabled
524+
var sackEnabled tcpip.StackSACKEnabled
525525
if err := h.ep.stack.TransportProtocolOption(ProtocolNumber, &sackEnabled); err != nil {
526526
// If stack returned an error when checking for SACKEnabled
527527
// status then just default to switching off SACK negotiation.

pkg/tcpip/transport/tcp/endpoint.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -851,12 +851,12 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue
851851
maxSynRetries: DefaultSynRetries,
852852
}
853853

854-
var ss SendBufferSizeOption
854+
var ss tcpip.StackSendBufferSizeOption
855855
if err := s.TransportProtocolOption(ProtocolNumber, &ss); err == nil {
856856
e.sndBufSize = ss.Default
857857
}
858858

859-
var rs ReceiveBufferSizeOption
859+
var rs tcpip.StackReceiveBufferSizeOption
860860
if err := s.TransportProtocolOption(ProtocolNumber, &rs); err == nil {
861861
e.rcvBufSize = rs.Default
862862
}
@@ -871,7 +871,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue
871871
e.rcvAutoParams.disabled = !bool(mrb)
872872
}
873873

874-
var de DelayEnabled
874+
var de tcpip.StackDelayEnabled
875875
if err := s.TransportProtocolOption(ProtocolNumber, &de); err == nil && de {
876876
e.SetSockOptBool(tcpip.DelayOption, true)
877877
}
@@ -1588,7 +1588,7 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
15881588
case tcpip.ReceiveBufferSizeOption:
15891589
// Make sure the receive buffer size is within the min and max
15901590
// allowed.
1591-
var rs ReceiveBufferSizeOption
1591+
var rs tcpip.StackReceiveBufferSizeOption
15921592
if err := e.stack.TransportProtocolOption(ProtocolNumber, &rs); err == nil {
15931593
if v < rs.Min {
15941594
v = rs.Min
@@ -1638,7 +1638,7 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
16381638
case tcpip.SendBufferSizeOption:
16391639
// Make sure the send buffer size is within the min and max
16401640
// allowed.
1641-
var ss SendBufferSizeOption
1641+
var ss tcpip.StackSendBufferSizeOption
16421642
if err := e.stack.TransportProtocolOption(ProtocolNumber, &ss); err == nil {
16431643
if v < ss.Min {
16441644
v = ss.Min
@@ -1678,7 +1678,7 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
16781678
return tcpip.ErrInvalidOptionValue
16791679
}
16801680
}
1681-
var rs ReceiveBufferSizeOption
1681+
var rs tcpip.StackReceiveBufferSizeOption
16821682
if err := e.stack.TransportProtocolOption(ProtocolNumber, &rs); err == nil {
16831683
if v < rs.Min/2 {
16841684
v = rs.Min / 2
@@ -2603,7 +2603,7 @@ func (e *endpoint) receiveBufferSize() int {
26032603
}
26042604

26052605
func (e *endpoint) maxReceiveBufferSize() int {
2606-
var rs ReceiveBufferSizeOption
2606+
var rs tcpip.StackReceiveBufferSizeOption
26072607
if err := e.stack.TransportProtocolOption(ProtocolNumber, &rs); err != nil {
26082608
// As a fallback return the hardcoded max buffer size.
26092609
return MaxBufferSize
@@ -2684,7 +2684,7 @@ func timeStampOffset() uint32 {
26842684
// if the SYN options indicate that the SACK option was negotiated and the TCP
26852685
// stack is configured to enable TCP SACK option.
26862686
func (e *endpoint) maybeEnableSACKPermitted(synOpts *header.TCPSynOptions) {
2687-
var v SACKEnabled
2687+
var v tcpip.StackSACKEnabled
26882688
if err := e.stack.TransportProtocolOption(ProtocolNumber, &v); err != nil {
26892689
// Stack doesn't support SACK. So just return.
26902690
return

pkg/tcpip/transport/tcp/endpoint_state.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func (e *endpoint) Resume(s *stack.Stack) {
186186
epState := e.origEndpointState
187187
switch epState {
188188
case StateInitial, StateBound, StateListen, StateConnecting, StateEstablished:
189-
var ss SendBufferSizeOption
189+
var ss tcpip.StackSendBufferSizeOption
190190
if err := e.stack.TransportProtocolOption(ProtocolNumber, &ss); err == nil {
191191
if e.sndBufSize < ss.Min || e.sndBufSize > ss.Max {
192192
panic(fmt.Sprintf("endpoint.sndBufSize %d is outside the min and max allowed [%d, %d]", e.sndBufSize, ss.Min, ss.Max))

0 commit comments

Comments
 (0)