Skip to content

Commit 22aeb5e

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 12f9094 commit 22aeb5e

File tree

16 files changed

+667
-87
lines changed

16 files changed

+667
-87
lines changed

benchmarks/tcp/tcp_proxy.go

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

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

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

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

816+
// StackSACKEnabled option can be used to enable SACK support in the TCP
817+
// protocol. See: https://tools.ietf.org/html/rfc2018.
818+
type StackSACKEnabled bool
819+
820+
// StackDelayEnabled option can be used to enable Nagle's algorithm in the TCP protocol.
821+
type StackDelayEnabled bool
822+
823+
// StackSendBufferSizeOption allows the stack-wide default, min and max send
824+
// buffer sizes to be queried or configured.
825+
type StackSendBufferSizeOption struct {
826+
Min int
827+
Default int
828+
Max int
829+
}
830+
831+
// StackReceiveBufferSizeOption allows the stack-wide default, min and max
832+
// receive buffer sizes to be queried or configured.
833+
type StackReceiveBufferSizeOption struct {
834+
Min int
835+
Default int
836+
Max int
837+
}
838+
839+
//
816840
// IPPacketInfo is the message struture for IP_PKTINFO.
817841
//
818842
// +stateify savable

pkg/tcpip/transport/raw/endpoint.go

+58-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,42 @@ 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+
var ss tcpip.StackSendBufferSizeOption
543+
if err := e.stack.TransportProtocolOption(e.TransProto, &ss); err != nil {
544+
panic(fmt.Sprintf("s.TransportProtocolOption(%d, %+v) = err", e.TransProto, ss))
545+
}
546+
if v > ss.Max {
547+
v = ss.Max
548+
}
549+
if v < ss.Min {
550+
v = ss.Min
551+
}
552+
e.mu.Lock()
553+
e.sndBufSizeMax = v
554+
e.mu.Unlock()
555+
return nil
556+
557+
case tcpip.ReceiveBufferSizeOption:
558+
var rs tcpip.StackReceiveBufferSizeOption
559+
if err := e.stack.TransportProtocolOption(e.TransProto, &rs); err != nil {
560+
panic(fmt.Sprintf("s.TransportProtocolOption(%d, %+v) = err", e.TransProto, rs))
561+
}
562+
if v > rs.Max {
563+
v = rs.Max
564+
}
565+
if v < rs.Min {
566+
v = rs.Min
567+
}
568+
e.rcvMu.Lock()
569+
e.rcvBufSizeMax = v
570+
e.rcvMu.Unlock()
571+
return nil
572+
573+
default:
574+
return tcpip.ErrUnknownProtocolOption
575+
}
527576
}
528577

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

564613
case tcpip.SendBufferSizeOption:
565614
e.mu.Lock()
566-
v := e.sndBufSize
615+
v := e.sndBufSizeMax
567616
e.mu.Unlock()
568617
return v, nil
569618

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
@@ -847,12 +847,12 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue
847847
maxSynRetries: DefaultSynRetries,
848848
}
849849

850-
var ss SendBufferSizeOption
850+
var ss tcpip.StackSendBufferSizeOption
851851
if err := s.TransportProtocolOption(ProtocolNumber, &ss); err == nil {
852852
e.sndBufSize = ss.Default
853853
}
854854

855-
var rs ReceiveBufferSizeOption
855+
var rs tcpip.StackReceiveBufferSizeOption
856856
if err := s.TransportProtocolOption(ProtocolNumber, &rs); err == nil {
857857
e.rcvBufSize = rs.Default
858858
}
@@ -867,7 +867,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue
867867
e.rcvAutoParams.disabled = !bool(mrb)
868868
}
869869

870-
var de DelayEnabled
870+
var de tcpip.StackDelayEnabled
871871
if err := s.TransportProtocolOption(ProtocolNumber, &de); err == nil && de {
872872
e.SetSockOptBool(tcpip.DelayOption, true)
873873
}
@@ -1582,7 +1582,7 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
15821582
case tcpip.ReceiveBufferSizeOption:
15831583
// Make sure the receive buffer size is within the min and max
15841584
// allowed.
1585-
var rs ReceiveBufferSizeOption
1585+
var rs tcpip.StackReceiveBufferSizeOption
15861586
if err := e.stack.TransportProtocolOption(ProtocolNumber, &rs); err == nil {
15871587
if v < rs.Min {
15881588
v = rs.Min
@@ -1632,7 +1632,7 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
16321632
case tcpip.SendBufferSizeOption:
16331633
// Make sure the send buffer size is within the min and max
16341634
// allowed.
1635-
var ss SendBufferSizeOption
1635+
var ss tcpip.StackSendBufferSizeOption
16361636
if err := e.stack.TransportProtocolOption(ProtocolNumber, &ss); err == nil {
16371637
if v < ss.Min {
16381638
v = ss.Min
@@ -1672,7 +1672,7 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
16721672
return tcpip.ErrInvalidOptionValue
16731673
}
16741674
}
1675-
var rs ReceiveBufferSizeOption
1675+
var rs tcpip.StackReceiveBufferSizeOption
16761676
if err := e.stack.TransportProtocolOption(ProtocolNumber, &rs); err == nil {
16771677
if v < rs.Min/2 {
16781678
v = rs.Min / 2
@@ -2594,7 +2594,7 @@ func (e *endpoint) receiveBufferSize() int {
25942594
}
25952595

25962596
func (e *endpoint) maxReceiveBufferSize() int {
2597-
var rs ReceiveBufferSizeOption
2597+
var rs tcpip.StackReceiveBufferSizeOption
25982598
if err := e.stack.TransportProtocolOption(ProtocolNumber, &rs); err != nil {
25992599
// As a fallback return the hardcoded max buffer size.
26002600
return MaxBufferSize
@@ -2675,7 +2675,7 @@ func timeStampOffset() uint32 {
26752675
// if the SYN options indicate that the SACK option was negotiated and the TCP
26762676
// stack is configured to enable TCP SACK option.
26772677
func (e *endpoint) maybeEnableSACKPermitted(synOpts *header.TCPSynOptions) {
2678-
var v SACKEnabled
2678+
var v tcpip.StackSACKEnabled
26792679
if err := e.stack.TransportProtocolOption(ProtocolNumber, &v); err != nil {
26802680
// Stack doesn't support SACK. So just return.
26812681
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)