mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[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:
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user