[netstack] Add SOL_TCP options to SocketOptions.

Ports the following options:
- TCP_NODELAY
- TCP_CORK
- TCP_QUICKACK

Also deletes the {Get/Set}SockOptBool interface methods from all implementations

PiperOrigin-RevId: 344378824
This commit is contained in:
Ayush Ranjan
2020-11-26 00:43:13 -08:00
committed by gVisor bot
parent bebadb5182
commit ad83112423
13 changed files with 111 additions and 219 deletions
+27 -39
View File
@@ -240,10 +240,6 @@ type commonEndpoint interface {
// transport.Endpoint.SetSockOpt.
SetSockOpt(tcpip.SettableSocketOption) *tcpip.Error
// SetSockOptBool implements tcpip.Endpoint.SetSockOptBool and
// transport.Endpoint.SetSockOptBool.
SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error
// SetSockOptInt implements tcpip.Endpoint.SetSockOptInt and
// transport.Endpoint.SetSockOptInt.
SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error
@@ -252,10 +248,6 @@ type commonEndpoint interface {
// transport.Endpoint.GetSockOpt.
GetSockOpt(tcpip.GettableSocketOption) *tcpip.Error
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool and
// transport.Endpoint.GetSockOpt.
GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error)
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt and
// transport.Endpoint.GetSockOpt.
GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error)
@@ -338,9 +330,7 @@ type socketOpsCommon struct {
// New creates a new endpoint socket.
func New(t *kernel.Task, family int, skType linux.SockType, protocol int, queue *waiter.Queue, endpoint tcpip.Endpoint) (*fs.File, *syserr.Error) {
if skType == linux.SOCK_STREAM {
if err := endpoint.SetSockOptBool(tcpip.DelayOption, true); err != nil {
return nil, syserr.TranslateNetstackError(err)
}
endpoint.SocketOptions().SetDelayOption(true)
}
dirent := socket.NewDirent(t, netstackDevice)
@@ -1007,7 +997,7 @@ func GetSockOpt(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, family in
return getSockOptSocket(t, s, ep, family, skType, name, outLen)
case linux.SOL_TCP:
return getSockOptTCP(t, ep, name, outLen)
return getSockOptTCP(t, s, ep, name, outLen)
case linux.SOL_IPV6:
return getSockOptIPv6(t, s, ep, name, outPtr, outLen)
@@ -1241,46 +1231,36 @@ func getSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, fam
}
// getSockOptTCP implements GetSockOpt when level is SOL_TCP.
func getSockOptTCP(t *kernel.Task, ep commonEndpoint, name, outLen int) (marshal.Marshallable, *syserr.Error) {
func getSockOptTCP(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name, outLen int) (marshal.Marshallable, *syserr.Error) {
if _, skType, skProto := s.Type(); !isTCPSocket(skType, skProto) {
log.Warningf("SOL_TCP options are only supported on TCP sockets: skType, skProto = %v, %d", skType, skProto)
return nil, syserr.ErrUnknownProtocolOption
}
switch name {
case linux.TCP_NODELAY:
if outLen < sizeOfInt32 {
return nil, syserr.ErrInvalidArgument
}
v, err := ep.GetSockOptBool(tcpip.DelayOption)
if err != nil {
return nil, syserr.TranslateNetstackError(err)
}
vP := primitive.Int32(boolToInt32(!v))
return &vP, nil
v := primitive.Int32(boolToInt32(!ep.SocketOptions().GetDelayOption()))
return &v, nil
case linux.TCP_CORK:
if outLen < sizeOfInt32 {
return nil, syserr.ErrInvalidArgument
}
v, err := ep.GetSockOptBool(tcpip.CorkOption)
if err != nil {
return nil, syserr.TranslateNetstackError(err)
}
vP := primitive.Int32(boolToInt32(v))
return &vP, nil
v := primitive.Int32(boolToInt32(ep.SocketOptions().GetCorkOption()))
return &v, nil
case linux.TCP_QUICKACK:
if outLen < sizeOfInt32 {
return nil, syserr.ErrInvalidArgument
}
v, err := ep.GetSockOptBool(tcpip.QuickAckOption)
if err != nil {
return nil, syserr.TranslateNetstackError(err)
}
vP := primitive.Int32(boolToInt32(v))
return &vP, nil
v := primitive.Int32(boolToInt32(ep.SocketOptions().GetQuickAck()))
return &v, nil
case linux.TCP_MAXSEG:
if outLen < sizeOfInt32 {
@@ -1804,7 +1784,7 @@ func SetSockOpt(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, level int
return setSockOptSocket(t, s, ep, name, optVal)
case linux.SOL_TCP:
return setSockOptTCP(t, ep, name, optVal)
return setSockOptTCP(t, s, ep, name, optVal)
case linux.SOL_IPV6:
return setSockOptIPv6(t, s, ep, name, optVal)
@@ -1994,7 +1974,12 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
}
// setSockOptTCP implements SetSockOpt when level is SOL_TCP.
func setSockOptTCP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *syserr.Error {
func setSockOptTCP(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name int, optVal []byte) *syserr.Error {
if _, skType, skProto := s.Type(); !isTCPSocket(skType, skProto) {
log.Warningf("SOL_TCP options are only supported on TCP sockets: skType, skProto = %v, %d", skType, skProto)
return syserr.ErrUnknownProtocolOption
}
switch name {
case linux.TCP_NODELAY:
if len(optVal) < sizeOfInt32 {
@@ -2002,7 +1987,8 @@ func setSockOptTCP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *
}
v := usermem.ByteOrder.Uint32(optVal)
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.DelayOption, v == 0))
ep.SocketOptions().SetDelayOption(v == 0)
return nil
case linux.TCP_CORK:
if len(optVal) < sizeOfInt32 {
@@ -2010,7 +1996,8 @@ func setSockOptTCP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *
}
v := usermem.ByteOrder.Uint32(optVal)
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.CorkOption, v != 0))
ep.SocketOptions().SetCorkOption(v != 0)
return nil
case linux.TCP_QUICKACK:
if len(optVal) < sizeOfInt32 {
@@ -2018,7 +2005,8 @@ func setSockOptTCP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *
}
v := usermem.ByteOrder.Uint32(optVal)
return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.QuickAckOption, v != 0))
ep.SocketOptions().SetQuickAck(v != 0)
return nil
case linux.TCP_MAXSEG:
if len(optVal) < sizeOfInt32 {
+1 -3
View File
@@ -51,9 +51,7 @@ var _ = socket.SocketVFS2(&SocketVFS2{})
// NewVFS2 creates a new endpoint socket.
func NewVFS2(t *kernel.Task, family int, skType linux.SockType, protocol int, queue *waiter.Queue, endpoint tcpip.Endpoint) (*vfs.FileDescription, *syserr.Error) {
if skType == linux.SOCK_STREAM {
if err := endpoint.SetSockOptBool(tcpip.DelayOption, true); err != nil {
return nil, syserr.TranslateNetstackError(err)
}
endpoint.SocketOptions().SetDelayOption(true)
}
mnt := t.Kernel().SocketMount()
-18
View File
@@ -178,10 +178,6 @@ type Endpoint interface {
// SetSockOpt sets a socket option.
SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error
// SetSockOptBool sets a socket option for simple cases when a value has
// the int type.
SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error
// SetSockOptInt sets a socket option for simple cases when a value has
// the int type.
SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error
@@ -189,10 +185,6 @@ type Endpoint interface {
// GetSockOpt gets a socket option.
GetSockOpt(opt tcpip.GettableSocketOption) *tcpip.Error
// GetSockOptBool gets a socket option for simple cases when a return
// value has the int type.
GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error)
// GetSockOptInt gets a socket option for simple cases when a return
// value has the int type.
GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error)
@@ -857,11 +849,6 @@ func (e *baseEndpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error {
return nil
}
func (e *baseEndpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
log.Warningf("Unsupported socket option: %d", opt)
return nil
}
func (e *baseEndpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
switch opt {
case tcpip.SendBufferSizeOption:
@@ -872,11 +859,6 @@ func (e *baseEndpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
return nil
}
func (e *baseEndpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
log.Warningf("Unsupported socket option: %d", opt)
return false, tcpip.ErrUnknownProtocolOption
}
func (e *baseEndpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
switch opt {
case tcpip.ReceiveQueueSizeOption:
+59 -1
View File
@@ -30,6 +30,13 @@ type SocketOptionsHandler interface {
// OnKeepAliveSet is invoked when SO_KEEPALIVE is set for an endpoint.
OnKeepAliveSet(v bool)
// OnDelayOptionSet is invoked when TCP_NODELAY is set for an endpoint.
// Note that v will be the inverse of TCP_NODELAY option.
OnDelayOptionSet(v bool)
// OnCorkOptionSet is invoked when TCP_CORK is set for an endpoint.
OnCorkOptionSet(v bool)
}
// DefaultSocketOptionsHandler is an embeddable type that implements no-op
@@ -47,8 +54,14 @@ func (*DefaultSocketOptionsHandler) OnReusePortSet(bool) {}
// OnKeepAliveSet implements SocketOptionsHandler.OnKeepAliveSet.
func (*DefaultSocketOptionsHandler) OnKeepAliveSet(bool) {}
// OnDelayOptionSet implements SocketOptionsHandler.OnDelayOptionSet.
func (*DefaultSocketOptionsHandler) OnDelayOptionSet(bool) {}
// OnCorkOptionSet implements SocketOptionsHandler.OnCorkOptionSet.
func (*DefaultSocketOptionsHandler) OnCorkOptionSet(bool) {}
// SocketOptions contains all the variables which store values for SOL_SOCKET,
// SOL_IP and SOL_IPV6 level options.
// SOL_IP, SOL_IPV6 and SOL_TCP level options.
//
// +stateify savable
type SocketOptions struct {
@@ -104,6 +117,19 @@ type SocketOptions struct {
// v6OnlyEnabled is used to determine whether an IPv6 socket is to be
// restricted to sending and receiving IPv6 packets only.
v6OnlyEnabled uint32
// quickAckEnabled is used to represent the value of TCP_QUICKACK option.
// It currently does not have any effect on the TCP endpoint.
quickAckEnabled uint32
// delayOptionEnabled is used to specify if data should be sent out immediately
// by the transport protocol. For TCP, it determines if the Nagle algorithm
// is on or off.
delayOptionEnabled uint32
// corkOptionEnabled is used to specify if data should be held until segments
// are full by the TCP transport protocol.
corkOptionEnabled uint32
}
// InitHandler initializes the handler. This must be called before using the
@@ -244,3 +270,35 @@ func (so *SocketOptions) GetV6Only() bool {
func (so *SocketOptions) SetV6Only(v bool) {
storeAtomicBool(&so.v6OnlyEnabled, v)
}
// GetQuickAck gets value for TCP_QUICKACK option.
func (so *SocketOptions) GetQuickAck() bool {
return atomic.LoadUint32(&so.quickAckEnabled) != 0
}
// SetQuickAck sets value for TCP_QUICKACK option.
func (so *SocketOptions) SetQuickAck(v bool) {
storeAtomicBool(&so.quickAckEnabled, v)
}
// GetDelayOption gets inverted value for TCP_NODELAY option.
func (so *SocketOptions) GetDelayOption() bool {
return atomic.LoadUint32(&so.delayOptionEnabled) != 0
}
// SetDelayOption sets inverted value for TCP_NODELAY option.
func (so *SocketOptions) SetDelayOption(v bool) {
storeAtomicBool(&so.delayOptionEnabled, v)
so.handler.OnDelayOptionSet(v)
}
// GetCorkOption gets value for TCP_CORK option.
func (so *SocketOptions) GetCorkOption() bool {
return atomic.LoadUint32(&so.corkOptionEnabled) != 0
}
// SetCorkOption sets value for TCP_CORK option.
func (so *SocketOptions) SetCorkOption(v bool) {
storeAtomicBool(&so.corkOptionEnabled, v)
so.handler.OnCorkOptionSet(v)
}
-10
View File
@@ -118,21 +118,11 @@ func (*fakeTransportEndpoint) SetSockOpt(tcpip.SettableSocketOption) *tcpip.Erro
return tcpip.ErrInvalidEndpointState
}
// SetSockOptBool sets a socket option. Currently not supported.
func (*fakeTransportEndpoint) SetSockOptBool(tcpip.SockOptBool, bool) *tcpip.Error {
return tcpip.ErrInvalidEndpointState
}
// SetSockOptInt sets a socket option. Currently not supported.
func (*fakeTransportEndpoint) SetSockOptInt(tcpip.SockOptInt, int) *tcpip.Error {
return tcpip.ErrInvalidEndpointState
}
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool.
func (*fakeTransportEndpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
return false, tcpip.ErrUnknownProtocolOption
}
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
func (*fakeTransportEndpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
return -1, tcpip.ErrUnknownProtocolOption
-26
View File
@@ -603,10 +603,6 @@ type Endpoint interface {
// SetSockOpt sets a socket option.
SetSockOpt(opt SettableSocketOption) *Error
// SetSockOptBool sets a socket option, for simple cases where a value
// has the bool type.
SetSockOptBool(opt SockOptBool, v bool) *Error
// SetSockOptInt sets a socket option, for simple cases where a value
// has the int type.
SetSockOptInt(opt SockOptInt, v int) *Error
@@ -614,10 +610,6 @@ type Endpoint interface {
// GetSockOpt gets a socket option.
GetSockOpt(opt GettableSocketOption) *Error
// GetSockOptBool gets a socket option for simple cases where a return
// value has the bool type.
GetSockOptBool(SockOptBool) (bool, *Error)
// GetSockOptInt gets a socket option for simple cases where a return
// value has the int type.
GetSockOptInt(SockOptInt) (int, *Error)
@@ -704,24 +696,6 @@ type WriteOptions struct {
Atomic bool
}
// SockOptBool represents socket options which values have the bool type.
type SockOptBool int
const (
// CorkOption is used by SetSockOptBool/GetSockOptBool to specify if
// data should be held until segments are full by the TCP transport
// protocol.
CorkOption SockOptBool = iota
// DelayOption is used by SetSockOptBool/GetSockOptBool to specify if
// data should be sent out immediately by the transport protocol. For
// TCP, it determines if the Nagle algorithm is on or off.
DelayOption
// QuickAckOption is stubbed out in SetSockOptBool/GetSockOptBool.
QuickAckOption
)
// SockOptInt represents socket options which values have the int type.
type SockOptInt int
-10
View File
@@ -368,11 +368,6 @@ func (e *endpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error {
return nil
}
// SetSockOptBool sets a socket option. Currently not supported.
func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
return nil
}
// SetSockOptInt sets a socket option. Currently not supported.
func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
switch opt {
@@ -385,11 +380,6 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
return nil
}
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool.
func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
return false, tcpip.ErrUnknownProtocolOption
}
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
switch opt {
-10
View File
@@ -321,11 +321,6 @@ func (ep *endpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error {
}
}
// SetSockOptBool implements tcpip.Endpoint.SetSockOptBool.
func (ep *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
return tcpip.ErrUnknownProtocolOption
}
// SetSockOptInt implements tcpip.Endpoint.SetSockOptInt.
func (ep *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
switch opt {
@@ -393,11 +388,6 @@ func (ep *endpoint) GetSockOpt(opt tcpip.GettableSocketOption) *tcpip.Error {
}
}
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool.
func (*endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
return false, tcpip.ErrNotSupported
}
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
func (ep *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
switch opt {
-10
View File
@@ -535,11 +535,6 @@ func (e *endpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error {
}
}
// SetSockOptBool implements tcpip.Endpoint.SetSockOptBool.
func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
return tcpip.ErrUnknownProtocolOption
}
// SetSockOptInt implements tcpip.Endpoint.SetSockOptInt.
func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
switch opt {
@@ -598,11 +593,6 @@ func (e *endpoint) GetSockOpt(opt tcpip.GettableSocketOption) *tcpip.Error {
}
}
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool.
func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
return false, tcpip.ErrUnknownProtocolOption
}
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
switch opt {
+14 -68
View File
@@ -497,24 +497,9 @@ type endpoint struct {
// delay is a boolean (0 is false) and must be accessed atomically.
delay uint32
// cork holds back segments until full.
//
// cork is a boolean (0 is false) and must be accessed atomically.
cork uint32
// scoreboard holds TCP SACK Scoreboard information for this endpoint.
scoreboard *SACKScoreboard
// The options below aren't implemented, but we remember the user
// settings because applications expect to be able to set/query these
// options.
// slowAck holds the negated state of quick ack. It is stubbed out and
// does nothing.
//
// slowAck is a boolean (0 is false) and must be accessed atomically.
slowAck uint32
// segmentQueue is used to hand received segments to the protocol
// goroutine. Segments are queued as long as the queue is not full,
// and dropped when it is.
@@ -874,6 +859,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue
}
e.ops.InitHandler(e)
e.ops.SetMulticastLoop(true)
e.ops.SetQuickAck(true)
var ss tcpip.TCPSendBufferSizeRangeOption
if err := s.TransportProtocolOption(ProtocolNumber, &ss); err == nil {
@@ -897,7 +883,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue
var de tcpip.TCPDelayEnabled
if err := s.TransportProtocolOption(ProtocolNumber, &de); err == nil && de {
e.SetSockOptBool(tcpip.DelayOption, true)
e.ops.SetDelayOption(true)
}
var tcpLT tcpip.TCPLingerTimeoutOption
@@ -1640,41 +1626,20 @@ func (e *endpoint) OnKeepAliveSet(v bool) {
e.notifyProtocolGoroutine(notifyKeepaliveChanged)
}
// SetSockOptBool sets a socket option.
func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
switch opt {
case tcpip.CorkOption:
e.LockUser()
if !v {
atomic.StoreUint32(&e.cork, 0)
// Handle the corked data.
e.sndWaker.Assert()
} else {
atomic.StoreUint32(&e.cork, 1)
}
e.UnlockUser()
case tcpip.DelayOption:
if v {
atomic.StoreUint32(&e.delay, 1)
} else {
atomic.StoreUint32(&e.delay, 0)
// Handle delayed data.
e.sndWaker.Assert()
}
case tcpip.QuickAckOption:
o := uint32(1)
if v {
o = 0
}
atomic.StoreUint32(&e.slowAck, o)
// OnDelayOptionSet implements tcpip.SocketOptionsHandler.OnDelayOptionSet.
func (e *endpoint) OnDelayOptionSet(v bool) {
if !v {
// Handle delayed data.
e.sndWaker.Assert()
}
}
return nil
// OnCorkOptionSet implements tcpip.SocketOptionsHandler.OnCorkOptionSet.
func (e *endpoint) OnCorkOptionSet(v bool) {
if !v {
// Handle the corked data.
e.sndWaker.Assert()
}
}
// SetSockOptInt sets a socket option.
@@ -1956,25 +1921,6 @@ func (e *endpoint) readyReceiveSize() (int, *tcpip.Error) {
return e.rcvBufUsed, nil
}
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool.
func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
switch opt {
case tcpip.CorkOption:
return atomic.LoadUint32(&e.cork) != 0, nil
case tcpip.DelayOption:
return atomic.LoadUint32(&e.delay) != 0, nil
case tcpip.QuickAckOption:
v := atomic.LoadUint32(&e.slowAck) == 0
return v, nil
default:
return false, tcpip.ErrUnknownProtocolOption
}
}
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
switch opt {
+2 -3
View File
@@ -18,7 +18,6 @@ import (
"fmt"
"math"
"sort"
"sync/atomic"
"time"
"gvisor.dev/gvisor/pkg/sleep"
@@ -813,7 +812,7 @@ func (s *sender) maybeSendSegment(seg *segment, limit int, end seqnum.Value) (se
}
if !nextTooBig && seg.data.Size() < available {
// Segment is not full.
if s.outstanding > 0 && atomic.LoadUint32(&s.ep.delay) != 0 {
if s.outstanding > 0 && s.ep.ops.GetDelayOption() {
// Nagle's algorithm. From Wikipedia:
// Nagle's algorithm works by
// combining a number of small
@@ -832,7 +831,7 @@ func (s *sender) maybeSendSegment(seg *segment, limit int, end seqnum.Value) (se
// send space and MSS.
// TODO(gvisor.dev/issue/2833): Drain the held segments after a
// timeout.
if seg.data.Size() < s.maxPayloadSize && atomic.LoadUint32(&s.ep.cork) != 0 {
if seg.data.Size() < s.maxPayloadSize && s.ep.ops.GetCorkOption() {
return false
}
}
+8 -11
View File
@@ -2529,10 +2529,10 @@ func TestSegmentMerging(t *testing.T) {
{
"cork",
func(ep tcpip.Endpoint) {
ep.SetSockOptBool(tcpip.CorkOption, true)
ep.SocketOptions().SetCorkOption(true)
},
func(ep tcpip.Endpoint) {
ep.SetSockOptBool(tcpip.CorkOption, false)
ep.SocketOptions().SetCorkOption(false)
},
},
}
@@ -2624,7 +2624,7 @@ func TestDelay(t *testing.T) {
c.CreateConnected(789, 30000, -1 /* epRcvBuf */)
c.EP.SetSockOptBool(tcpip.DelayOption, true)
c.EP.SocketOptions().SetDelayOption(true)
var allData []byte
for i, data := range [][]byte{{0}, {1, 2, 3, 4}, {5, 6, 7}, {8, 9}, {10}, {11}} {
@@ -2672,7 +2672,7 @@ func TestUndelay(t *testing.T) {
c.CreateConnected(789, 30000, -1 /* epRcvBuf */)
c.EP.SetSockOptBool(tcpip.DelayOption, true)
c.EP.SocketOptions().SetDelayOption(true)
allData := [][]byte{{0}, {1, 2, 3}}
for i, data := range allData {
@@ -2705,7 +2705,7 @@ func TestUndelay(t *testing.T) {
// Check that we don't get the second packet yet.
c.CheckNoPacketTimeout("delayed second packet transmitted", 100*time.Millisecond)
c.EP.SetSockOptBool(tcpip.DelayOption, false)
c.EP.SocketOptions().SetDelayOption(false)
// Check that data is received.
second := c.GetPacket()
@@ -2742,8 +2742,8 @@ func TestMSSNotDelayed(t *testing.T) {
fn func(tcpip.Endpoint)
}{
{"no-op", func(tcpip.Endpoint) {}},
{"delay", func(ep tcpip.Endpoint) { ep.SetSockOptBool(tcpip.DelayOption, true) }},
{"cork", func(ep tcpip.Endpoint) { ep.SetSockOptBool(tcpip.CorkOption, true) }},
{"delay", func(ep tcpip.Endpoint) { ep.SocketOptions().SetDelayOption(true) }},
{"cork", func(ep tcpip.Endpoint) { ep.SocketOptions().SetCorkOption(true) }},
}
for _, test := range tests {
@@ -6374,10 +6374,7 @@ func checkDelayOption(t *testing.T, c *context.Context, wantDelayEnabled tcpip.T
if err != nil {
t.Fatalf("NewEndPoint(tcp, ipv4, new(waiter.Queue)) failed: %s", err)
}
gotDelayOption, err := ep.GetSockOptBool(tcpip.DelayOption)
if err != nil {
t.Fatalf("ep.GetSockOptBool(tcpip.DelayOption) failed: %s", err)
}
gotDelayOption := ep.SocketOptions().GetDelayOption()
if gotDelayOption != wantDelayOption {
t.Errorf("ep.GetSockOptBool(tcpip.DelayOption) got: %t, want: %t", gotDelayOption, wantDelayOption)
}
-10
View File
@@ -575,11 +575,6 @@ func (e *endpoint) OnReusePortSet(v bool) {
e.mu.Unlock()
}
// SetSockOptBool implements tcpip.Endpoint.SetSockOptBool.
func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error {
return nil
}
// SetSockOptInt implements tcpip.Endpoint.SetSockOptInt.
func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error {
switch opt {
@@ -789,11 +784,6 @@ func (e *endpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error {
return nil
}
// GetSockOptBool implements tcpip.Endpoint.GetSockOptBool.
func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) {
return false, tcpip.ErrUnknownProtocolOption
}
// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) {
switch opt {