diff options
Diffstat (limited to 'pkg')
24 files changed, 334 insertions, 324 deletions
diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go index 3f34668cf..b4d0651b8 100644 --- a/pkg/sentry/socket/netstack/netstack.go +++ b/pkg/sentry/socket/netstack/netstack.go @@ -846,7 +846,7 @@ func getSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, fam return nil, syserr.ErrInvalidArgument } - size, err := ep.GetSockOptInt(tcpip.SendBufferSizeOption) + size, err := ep.SocketOptions().GetSendBufferSize() if err != nil { return nil, syserr.TranslateNetstackError(err) } @@ -1615,8 +1615,21 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam return syserr.ErrInvalidArgument } + family, skType, skProto := s.Type() + // TODO(gvisor.dev/issue/5132): We currently do not support + // setting this option for unix sockets. + if family == linux.AF_UNIX { + return nil + } + + getBufferLimits := tcpip.GetStackSendBufferLimits + if isTCPSocket(skType, skProto) { + getBufferLimits = tcp.GetTCPSendBufferLimits + } + v := usermem.ByteOrder.Uint32(optVal) - return syserr.TranslateNetstackError(ep.SetSockOptInt(tcpip.SendBufferSizeOption, int(v))) + ep.SocketOptions().SetSendBufferSize(int64(v), true, getBufferLimits) + return nil case linux.SO_RCVBUF: if len(optVal) < sizeOfInt32 { diff --git a/pkg/sentry/socket/unix/transport/connectioned.go b/pkg/sentry/socket/unix/transport/connectioned.go index 9f7aca305..dbb7f7c31 100644 --- a/pkg/sentry/socket/unix/transport/connectioned.go +++ b/pkg/sentry/socket/unix/transport/connectioned.go @@ -128,7 +128,7 @@ func newConnectioned(ctx context.Context, stype linux.SockType, uid UniqueIDProv idGenerator: uid, stype: stype, } - ep.ops.InitHandler(ep) + ep.ops.InitHandler(ep, nil) return ep } @@ -173,7 +173,7 @@ func NewExternal(ctx context.Context, stype linux.SockType, uid UniqueIDProvider idGenerator: uid, stype: stype, } - ep.ops.InitHandler(ep) + ep.ops.InitHandler(ep, nil) return ep } @@ -296,7 +296,7 @@ func (e *connectionedEndpoint) BidirectionalConnect(ctx context.Context, ce Conn idGenerator: e.idGenerator, stype: e.stype, } - ne.ops.InitHandler(ne) + ne.ops.InitHandler(ne, nil) readQueue := &queue{ReaderQueue: ce.WaiterQueue(), WriterQueue: ne.Queue, limit: initialLimit} readQueue.InitRefs() diff --git a/pkg/sentry/socket/unix/transport/connectionless.go b/pkg/sentry/socket/unix/transport/connectionless.go index 0813ad87d..895d2322e 100644 --- a/pkg/sentry/socket/unix/transport/connectionless.go +++ b/pkg/sentry/socket/unix/transport/connectionless.go @@ -44,7 +44,7 @@ func NewConnectionless(ctx context.Context) Endpoint { q := queue{ReaderQueue: ep.Queue, WriterQueue: &waiter.Queue{}, limit: initialLimit} q.InitRefs() ep.receiver = &queueReceiver{readQueue: &q} - ep.ops.InitHandler(ep) + ep.ops.InitHandler(ep, nil) return ep } diff --git a/pkg/sentry/socket/unix/transport/unix.go b/pkg/sentry/socket/unix/transport/unix.go index 099a56281..0e3889c6d 100644 --- a/pkg/sentry/socket/unix/transport/unix.go +++ b/pkg/sentry/socket/unix/transport/unix.go @@ -842,7 +842,6 @@ func (e *baseEndpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error { func (e *baseEndpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error { switch opt { - case tcpip.SendBufferSizeOption: case tcpip.ReceiveBufferSizeOption: default: log.Warningf("Unsupported socket option: %d", opt) @@ -850,6 +849,27 @@ func (e *baseEndpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error { return nil } +// IsUnixSocket implements tcpip.SocketOptionsHandler.IsUnixSocket. +func (e *baseEndpoint) IsUnixSocket() bool { + return true +} + +// GetSendBufferSize implements tcpip.SocketOptionsHandler.GetSendBufferSize. +func (e *baseEndpoint) GetSendBufferSize() (int64, *tcpip.Error) { + e.Lock() + defer e.Unlock() + + if !e.Connected() { + return -1, tcpip.ErrNotConnected + } + + v := e.connected.SendMaxQueueSize() + if v < 0 { + return -1, tcpip.ErrQueueSizeNotSupported + } + return v, nil +} + func (e *baseEndpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) { switch opt { case tcpip.ReceiveQueueSizeOption: @@ -879,19 +899,6 @@ func (e *baseEndpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) { } return int(v), nil - case tcpip.SendBufferSizeOption: - e.Lock() - if !e.Connected() { - e.Unlock() - return -1, tcpip.ErrNotConnected - } - v := e.connected.SendMaxQueueSize() - e.Unlock() - if v < 0 { - return -1, tcpip.ErrQueueSizeNotSupported - } - return int(v), nil - case tcpip.ReceiveBufferSizeOption: e.Lock() if e.receiver == nil { diff --git a/pkg/tcpip/socketops.go b/pkg/tcpip/socketops.go index f3ad40fdf..4149b91da 100644 --- a/pkg/tcpip/socketops.go +++ b/pkg/tcpip/socketops.go @@ -15,11 +15,16 @@ package tcpip import ( + "math" "sync/atomic" "gvisor.dev/gvisor/pkg/sync" ) +// PacketOverheadFactor is used to multiply the value provided by the user on a +// SetSockOpt for setting the send/receive buffer sizes sockets. +const PacketOverheadFactor = 2 + // SocketOptionsHandler holds methods that help define endpoint specific // behavior for socket level socket options. These must be implemented by // endpoints to get notified when socket level options are set. @@ -48,6 +53,12 @@ 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 } // DefaultSocketOptionsHandler is an embeddable type that implements no-op @@ -84,6 +95,27 @@ 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 +} + +// StackHandler holds methods to access the stack options. These must be +// implemented by the stack. +type StackHandler interface { + // Option allows retrieving stack wide options. + Option(option interface{}) *Error + + // TransportProtocolOption allows retrieving individual protocol level + // option values. + TransportProtocolOption(proto TransportProtocolNumber, option GettableTransportProtocolOption) *Error +} + // SocketOptions contains all the variables which store values for SOL_SOCKET, // SOL_IP, SOL_IPV6 and SOL_TCP level options. // @@ -91,6 +123,9 @@ func (*DefaultSocketOptionsHandler) HasNIC(int32) bool { type SocketOptions struct { handler SocketOptionsHandler + // StackHandler is initialized at the creation time and will not change. + stackHandler StackHandler `state:"manual"` + // These fields are accessed and modified using atomic operations. // broadcastEnabled determines whether datagram sockets are allowed to @@ -170,6 +205,9 @@ type SocketOptions struct { // bindToDevice determines the device to which the socket is bound. bindToDevice int32 + // sendBufferSize determines the send buffer size for this socket. + sendBufferSize int64 + // mu protects the access to the below fields. mu sync.Mutex `state:"nosave"` @@ -180,8 +218,9 @@ type SocketOptions struct { // InitHandler initializes the handler. This must be called before using the // socket options utility. -func (so *SocketOptions) InitHandler(handler SocketOptionsHandler) { +func (so *SocketOptions) InitHandler(handler SocketOptionsHandler, stack StackHandler) { so.handler = handler + so.stackHandler = stack } func storeAtomicBool(addr *uint32, v bool) { @@ -518,3 +557,41 @@ func (so *SocketOptions) SetBindToDevice(bindToDevice int32) *Error { atomic.StoreInt32(&so.bindToDevice, bindToDevice) return nil } + +// 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 +} + +// 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, getBufferLimits GetSendBufferLimits) { + v := sendBufferSize + ss := getBufferLimits(so.stackHandler) + + if notify { + // TODO(b/176170271): Notify waiters after size has grown. + // Make sure the send buffer size is within the min and max + // allowed. + 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 + } + } + atomic.StoreInt64(&so.sendBufferSize, v) +} diff --git a/pkg/tcpip/stack/stack.go b/pkg/tcpip/stack/stack.go index ee05c6013..fc7b9ea56 100644 --- a/pkg/tcpip/stack/stack.go +++ b/pkg/tcpip/stack/stack.go @@ -444,7 +444,7 @@ type Stack struct { // sendBufferSize holds the min/default/max send buffer sizes for // endpoints other than TCP. - sendBufferSize SendBufferSizeOption + sendBufferSize tcpip.SendBufferSizeOption // receiveBufferSize holds the min/default/max receive buffer sizes for // endpoints other than TCP. @@ -646,7 +646,7 @@ func New(opts Options) *Stack { uniqueIDGenerator: opts.UniqueID, nudDisp: opts.NUDDisp, randomGenerator: mathrand.New(randSrc), - sendBufferSize: SendBufferSizeOption{ + sendBufferSize: tcpip.SendBufferSizeOption{ Min: MinBufferSize, Default: DefaultBufferSize, Max: DefaultMaxBufferSize, diff --git a/pkg/tcpip/stack/stack_options.go b/pkg/tcpip/stack/stack_options.go index 0b093e6c5..92e70f94e 100644 --- a/pkg/tcpip/stack/stack_options.go +++ b/pkg/tcpip/stack/stack_options.go @@ -14,7 +14,9 @@ package stack -import "gvisor.dev/gvisor/pkg/tcpip" +import ( + "gvisor.dev/gvisor/pkg/tcpip" +) const ( // MinBufferSize is the smallest size of a receive or send buffer. @@ -29,14 +31,6 @@ const ( DefaultMaxBufferSize = 4 << 20 // 4 MiB ) -// SendBufferSizeOption is used by stack.(Stack*).Option/SetOption to -// get/set the default, min and max send buffer sizes. -type SendBufferSizeOption struct { - Min int - Default int - Max int -} - // ReceiveBufferSizeOption is used by stack.(Stack*).Option/SetOption to // get/set the default, min and max receive buffer sizes. type ReceiveBufferSizeOption struct { @@ -48,7 +42,7 @@ type ReceiveBufferSizeOption struct { // SetOption allows setting stack wide options. func (s *Stack) SetOption(option interface{}) *tcpip.Error { switch v := option.(type) { - case SendBufferSizeOption: + case tcpip.SendBufferSizeOption: // Make sure we don't allow lowering the buffer below minimum // required for stack to work. if v.Min < MinBufferSize { @@ -88,7 +82,7 @@ func (s *Stack) SetOption(option interface{}) *tcpip.Error { // Option allows retrieving stack wide options. func (s *Stack) Option(option interface{}) *tcpip.Error { switch v := option.(type) { - case *SendBufferSizeOption: + case *tcpip.SendBufferSizeOption: s.mu.RLock() *v = s.sendBufferSize s.mu.RUnlock() diff --git a/pkg/tcpip/tcpip.go b/pkg/tcpip/tcpip.go index 32e4f02ca..4e2c4f906 100644 --- a/pkg/tcpip/tcpip.go +++ b/pkg/tcpip/tcpip.go @@ -826,10 +826,6 @@ const ( // number of unread bytes in the input buffer should be returned. ReceiveQueueSizeOption - // SendBufferSizeOption is used by SetSockOptInt/GetSockOptInt to - // specify the send buffer size option. - SendBufferSizeOption - // ReceiveBufferSizeOption is used by SetSockOptInt/GetSockOptInt to // specify the receive buffer size option. ReceiveBufferSizeOption @@ -1234,6 +1230,31 @@ type IPPacketInfo struct { DestinationAddr Address } +// SendBufferSizeOption is used by stack.(Stack*).Option/SetOption to +// get/set the default, min and max send buffer sizes. +type SendBufferSizeOption struct { + // Min is the minimum size for send buffer. + Min int + + // Default is the default size for send buffer. + Default int + + // Max is the maximum size for send buffer. + Max int +} + +// GetSendBufferLimits is used to get the send buffer size limits. +type GetSendBufferLimits func(StackHandler) SendBufferSizeOption + +// GetStackSendBufferLimits is used to get default, min and max send buffer size. +func GetStackSendBufferLimits(so StackHandler) SendBufferSizeOption { + var ss SendBufferSizeOption + if err := so.Option(&ss); err != nil { + panic(fmt.Sprintf("s.Option(%#v) = %s", ss, err)) + } + return ss +} + // Route is a row in the routing table. It specifies through which NIC (and // gateway) sets of packets should be routed. A row is considered viable if the // masked target address matches the destination address in the row. diff --git a/pkg/tcpip/tcpip_state_autogen.go b/pkg/tcpip/tcpip_state_autogen.go index c688eaff5..758ba538f 100644 --- a/pkg/tcpip/tcpip_state_autogen.go +++ b/pkg/tcpip/tcpip_state_autogen.go @@ -84,6 +84,7 @@ func (so *SocketOptions) StateFields() []string { "recvErrEnabled", "errQueue", "bindToDevice", + "sendBufferSize", "linger", } } @@ -112,7 +113,8 @@ func (so *SocketOptions) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(17, &so.recvErrEnabled) stateSinkObject.Save(18, &so.errQueue) stateSinkObject.Save(19, &so.bindToDevice) - stateSinkObject.Save(20, &so.linger) + stateSinkObject.Save(20, &so.sendBufferSize) + stateSinkObject.Save(21, &so.linger) } func (so *SocketOptions) afterLoad() {} @@ -138,7 +140,8 @@ func (so *SocketOptions) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(17, &so.recvErrEnabled) stateSourceObject.Load(18, &so.errQueue) stateSourceObject.Load(19, &so.bindToDevice) - stateSourceObject.Load(20, &so.linger) + stateSourceObject.Load(20, &so.sendBufferSize) + stateSourceObject.Load(21, &so.linger) } func (s *SockError) StateTypeName() string { diff --git a/pkg/tcpip/transport/icmp/endpoint.go b/pkg/tcpip/transport/icmp/endpoint.go index af00ed548..85b497365 100644 --- a/pkg/tcpip/transport/icmp/endpoint.go +++ b/pkg/tcpip/transport/icmp/endpoint.go @@ -69,8 +69,7 @@ type endpoint struct { rcvClosed bool // The following fields are protected by the mu mutex. - mu sync.RWMutex `state:"nosave"` - sndBufSize int + mu sync.RWMutex `state:"nosave"` // shutdownFlags represent the current shutdown state of the endpoint. shutdownFlags tcpip.ShutdownFlags state endpointState @@ -94,11 +93,17 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProt }, waiterQueue: waiterQueue, rcvBufSizeMax: 32 * 1024, - sndBufSize: 32 * 1024, state: stateInitial, uniqueID: s.UniqueID(), } - ep.ops.InitHandler(ep) + ep.ops.InitHandler(ep, ep.stack) + ep.ops.SetSendBufferSize(32*1024, false /* notify */, tcpip.GetStackSendBufferLimits) + + // Override with stack defaults. + var ss tcpip.SendBufferSizeOption + if err := s.Option(&ss); err == nil { + ep.ops.SetSendBufferSize(int64(ss.Default), false /* notify */, tcpip.GetStackSendBufferLimits) + } return ep, nil } @@ -363,11 +368,6 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) { } e.rcvMu.Unlock() return v, nil - case tcpip.SendBufferSizeOption: - e.mu.Lock() - v := e.sndBufSize - e.mu.Unlock() - return v, nil case tcpip.ReceiveBufferSizeOption: e.rcvMu.Lock() diff --git a/pkg/tcpip/transport/icmp/endpoint_state.go b/pkg/tcpip/transport/icmp/endpoint_state.go index 9d263c0ec..9335cbc5a 100644 --- a/pkg/tcpip/transport/icmp/endpoint_state.go +++ b/pkg/tcpip/transport/icmp/endpoint_state.go @@ -69,6 +69,7 @@ func (e *endpoint) afterLoad() { // Resume implements tcpip.ResumableEndpoint.Resume. func (e *endpoint) Resume(s *stack.Stack) { e.stack = s + e.ops.InitHandler(e, e.stack) if e.state != stateBound && e.state != stateConnected { return diff --git a/pkg/tcpip/transport/icmp/icmp_state_autogen.go b/pkg/tcpip/transport/icmp/icmp_state_autogen.go index 28a734f05..fe5af3d97 100644 --- a/pkg/tcpip/transport/icmp/icmp_state_autogen.go +++ b/pkg/tcpip/transport/icmp/icmp_state_autogen.go @@ -55,7 +55,6 @@ func (e *endpoint) StateFields() []string { "rcvBufSizeMax", "rcvBufSize", "rcvClosed", - "sndBufSize", "shutdownFlags", "state", "ttl", @@ -76,12 +75,11 @@ func (e *endpoint) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(5, &e.rcvList) stateSinkObject.Save(7, &e.rcvBufSize) stateSinkObject.Save(8, &e.rcvClosed) - stateSinkObject.Save(9, &e.sndBufSize) - stateSinkObject.Save(10, &e.shutdownFlags) - stateSinkObject.Save(11, &e.state) - stateSinkObject.Save(12, &e.ttl) - stateSinkObject.Save(13, &e.owner) - stateSinkObject.Save(14, &e.ops) + stateSinkObject.Save(9, &e.shutdownFlags) + stateSinkObject.Save(10, &e.state) + stateSinkObject.Save(11, &e.ttl) + stateSinkObject.Save(12, &e.owner) + stateSinkObject.Save(13, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { @@ -93,12 +91,11 @@ func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(5, &e.rcvList) stateSourceObject.Load(7, &e.rcvBufSize) stateSourceObject.Load(8, &e.rcvClosed) - stateSourceObject.Load(9, &e.sndBufSize) - stateSourceObject.Load(10, &e.shutdownFlags) - stateSourceObject.Load(11, &e.state) - stateSourceObject.Load(12, &e.ttl) - stateSourceObject.Load(13, &e.owner) - stateSourceObject.Load(14, &e.ops) + stateSourceObject.Load(9, &e.shutdownFlags) + stateSourceObject.Load(10, &e.state) + stateSourceObject.Load(11, &e.ttl) + stateSourceObject.Load(12, &e.owner) + stateSourceObject.Load(13, &e.ops) stateSourceObject.LoadValue(6, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/tcpip/transport/packet/endpoint.go b/pkg/tcpip/transport/packet/endpoint.go index 6fd116a98..9ca9c9780 100644 --- a/pkg/tcpip/transport/packet/endpoint.go +++ b/pkg/tcpip/transport/packet/endpoint.go @@ -79,13 +79,11 @@ type endpoint struct { rcvClosed bool // The following fields are protected by mu. - mu sync.RWMutex `state:"nosave"` - sndBufSize int - sndBufSizeMax int - closed bool - stats tcpip.TransportEndpointStats `state:"nosave"` - bound bool - boundNIC tcpip.NICID + mu sync.RWMutex `state:"nosave"` + closed bool + stats tcpip.TransportEndpointStats `state:"nosave"` + bound bool + boundNIC tcpip.NICID // lastErrorMu protects lastError. lastErrorMu sync.Mutex `state:"nosave"` @@ -106,14 +104,13 @@ func NewEndpoint(s *stack.Stack, cooked bool, netProto tcpip.NetworkProtocolNumb netProto: netProto, waiterQueue: waiterQueue, rcvBufSizeMax: 32 * 1024, - sndBufSize: 32 * 1024, } - ep.ops.InitHandler(ep) + ep.ops.InitHandler(ep, ep.stack) // Override with stack defaults. - var ss stack.SendBufferSizeOption + var ss tcpip.SendBufferSizeOption if err := s.Option(&ss); err == nil { - ep.sndBufSizeMax = ss.Default + ep.ops.SetSendBufferSize(int64(ss.Default), false /* notify */, tcpip.GetStackSendBufferLimits) } var rs stack.ReceiveBufferSizeOption @@ -320,24 +317,6 @@ func (ep *endpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error { // SetSockOptInt implements tcpip.Endpoint.SetSockOptInt. func (ep *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error { switch opt { - case tcpip.SendBufferSizeOption: - // Make sure the send buffer size is within the min and max - // allowed. - var ss stack.SendBufferSizeOption - if err := ep.stack.Option(&ss); err != nil { - panic(fmt.Sprintf("s.Option(%#v) = %s", ss, err)) - } - if v > ss.Max { - v = ss.Max - } - if v < ss.Min { - v = ss.Min - } - ep.mu.Lock() - ep.sndBufSizeMax = v - ep.mu.Unlock() - return nil - case tcpip.ReceiveBufferSizeOption: // Make sure the receive buffer size is within the min and max // allowed. @@ -395,12 +374,6 @@ func (ep *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) { ep.rcvMu.Unlock() return v, nil - case tcpip.SendBufferSizeOption: - ep.mu.Lock() - v := ep.sndBufSizeMax - ep.mu.Unlock() - return v, nil - case tcpip.ReceiveBufferSizeOption: ep.rcvMu.Lock() v := ep.rcvBufSizeMax diff --git a/pkg/tcpip/transport/packet/endpoint_state.go b/pkg/tcpip/transport/packet/endpoint_state.go index e2fa96d17..61221be71 100644 --- a/pkg/tcpip/transport/packet/endpoint_state.go +++ b/pkg/tcpip/transport/packet/endpoint_state.go @@ -63,8 +63,8 @@ func (ep *endpoint) loadRcvBufSizeMax(max int) { // afterLoad is invoked by stateify. func (ep *endpoint) afterLoad() { - // StackFromEnv is a stack used specifically for save/restore. ep.stack = stack.StackFromEnv + ep.ops.InitHandler(ep, ep.stack) // TODO(gvisor.dev/173): Once bind is supported, choose the right NIC. if err := ep.stack.RegisterPacketEndpoint(0, ep.netProto, ep); err != nil { diff --git a/pkg/tcpip/transport/packet/packet_state_autogen.go b/pkg/tcpip/transport/packet/packet_state_autogen.go index ccb66800b..4a62f1e4b 100644 --- a/pkg/tcpip/transport/packet/packet_state_autogen.go +++ b/pkg/tcpip/transport/packet/packet_state_autogen.go @@ -58,8 +58,6 @@ func (ep *endpoint) StateFields() []string { "rcvBufSizeMax", "rcvBufSize", "rcvClosed", - "sndBufSize", - "sndBufSizeMax", "closed", "bound", "boundNIC", @@ -73,7 +71,7 @@ func (ep *endpoint) StateSave(stateSinkObject state.Sink) { var rcvBufSizeMaxValue int = ep.saveRcvBufSizeMax() stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) var lastErrorValue string = ep.saveLastError() - stateSinkObject.SaveValue(14, lastErrorValue) + stateSinkObject.SaveValue(12, lastErrorValue) stateSinkObject.Save(0, &ep.TransportEndpointInfo) stateSinkObject.Save(1, &ep.DefaultSocketOptionsHandler) stateSinkObject.Save(2, &ep.netProto) @@ -82,12 +80,10 @@ func (ep *endpoint) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(5, &ep.rcvList) stateSinkObject.Save(7, &ep.rcvBufSize) stateSinkObject.Save(8, &ep.rcvClosed) - stateSinkObject.Save(9, &ep.sndBufSize) - stateSinkObject.Save(10, &ep.sndBufSizeMax) - stateSinkObject.Save(11, &ep.closed) - stateSinkObject.Save(12, &ep.bound) - stateSinkObject.Save(13, &ep.boundNIC) - stateSinkObject.Save(15, &ep.ops) + stateSinkObject.Save(9, &ep.closed) + stateSinkObject.Save(10, &ep.bound) + stateSinkObject.Save(11, &ep.boundNIC) + stateSinkObject.Save(13, &ep.ops) } func (ep *endpoint) StateLoad(stateSourceObject state.Source) { @@ -99,14 +95,12 @@ func (ep *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(5, &ep.rcvList) stateSourceObject.Load(7, &ep.rcvBufSize) stateSourceObject.Load(8, &ep.rcvClosed) - stateSourceObject.Load(9, &ep.sndBufSize) - stateSourceObject.Load(10, &ep.sndBufSizeMax) - stateSourceObject.Load(11, &ep.closed) - stateSourceObject.Load(12, &ep.bound) - stateSourceObject.Load(13, &ep.boundNIC) - stateSourceObject.Load(15, &ep.ops) + stateSourceObject.Load(9, &ep.closed) + stateSourceObject.Load(10, &ep.bound) + stateSourceObject.Load(11, &ep.boundNIC) + stateSourceObject.Load(13, &ep.ops) stateSourceObject.LoadValue(6, new(int), func(y interface{}) { ep.loadRcvBufSizeMax(y.(int)) }) - stateSourceObject.LoadValue(14, new(string), func(y interface{}) { ep.loadLastError(y.(string)) }) + stateSourceObject.LoadValue(12, new(string), func(y interface{}) { ep.loadLastError(y.(string)) }) stateSourceObject.AfterLoad(ep.afterLoad) } diff --git a/pkg/tcpip/transport/raw/endpoint.go b/pkg/tcpip/transport/raw/endpoint.go index 2dacf5a64..f038097e4 100644 --- a/pkg/tcpip/transport/raw/endpoint.go +++ b/pkg/tcpip/transport/raw/endpoint.go @@ -76,12 +76,10 @@ type endpoint struct { rcvClosed bool // The following fields are protected by mu. - mu sync.RWMutex `state:"nosave"` - sndBufSize int - sndBufSizeMax int - closed bool - connected bool - bound bool + mu sync.RWMutex `state:"nosave"` + closed bool + connected bool + bound bool // route is the route to a remote network endpoint. It is set via // Connect(), and is valid only when conneted is true. route *stack.Route `state:"manual"` @@ -112,16 +110,16 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProt }, waiterQueue: waiterQueue, rcvBufSizeMax: 32 * 1024, - sndBufSizeMax: 32 * 1024, associated: associated, } - e.ops.InitHandler(e) + e.ops.InitHandler(e, e.stack) e.ops.SetHeaderIncluded(!associated) + e.ops.SetSendBufferSize(32*1024, false /* notify */, tcpip.GetStackSendBufferLimits) // Override with stack defaults. - var ss stack.SendBufferSizeOption + var ss tcpip.SendBufferSizeOption if err := s.Option(&ss); err == nil { - e.sndBufSizeMax = ss.Default + e.ops.SetSendBufferSize(int64(ss.Default), false /* notify */, tcpip.GetStackSendBufferLimits) } var rs stack.ReceiveBufferSizeOption @@ -511,24 +509,6 @@ func (e *endpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error { // SetSockOptInt implements tcpip.Endpoint.SetSockOptInt. func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error { switch opt { - case tcpip.SendBufferSizeOption: - // Make sure the send buffer size is within the min and max - // allowed. - var ss stack.SendBufferSizeOption - if err := e.stack.Option(&ss); err != nil { - panic(fmt.Sprintf("s.Option(%#v) = %s", ss, err)) - } - if v > ss.Max { - v = ss.Max - } - if v < ss.Min { - v = ss.Min - } - e.mu.Lock() - e.sndBufSizeMax = v - e.mu.Unlock() - return nil - case tcpip.ReceiveBufferSizeOption: // Make sure the receive buffer size is within the min and max // allowed. @@ -570,12 +550,6 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) { e.rcvMu.Unlock() return v, nil - case tcpip.SendBufferSizeOption: - e.mu.Lock() - v := e.sndBufSizeMax - e.mu.Unlock() - return v, nil - case tcpip.ReceiveBufferSizeOption: e.rcvMu.Lock() v := e.rcvBufSizeMax diff --git a/pkg/tcpip/transport/raw/endpoint_state.go b/pkg/tcpip/transport/raw/endpoint_state.go index 4a7e1c039..e11ab38d5 100644 --- a/pkg/tcpip/transport/raw/endpoint_state.go +++ b/pkg/tcpip/transport/raw/endpoint_state.go @@ -69,6 +69,7 @@ func (e *endpoint) afterLoad() { // Resume implements tcpip.ResumableEndpoint.Resume. func (e *endpoint) Resume(s *stack.Stack) { e.stack = s + e.ops.InitHandler(e, e.stack) // If the endpoint is connected, re-connect. if e.connected { diff --git a/pkg/tcpip/transport/raw/raw_state_autogen.go b/pkg/tcpip/transport/raw/raw_state_autogen.go index a7ecccb20..db4b393a7 100644 --- a/pkg/tcpip/transport/raw/raw_state_autogen.go +++ b/pkg/tcpip/transport/raw/raw_state_autogen.go @@ -54,8 +54,6 @@ func (e *endpoint) StateFields() []string { "rcvBufSize", "rcvBufSizeMax", "rcvClosed", - "sndBufSize", - "sndBufSizeMax", "closed", "connected", "bound", @@ -75,13 +73,11 @@ func (e *endpoint) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(4, &e.rcvList) stateSinkObject.Save(5, &e.rcvBufSize) stateSinkObject.Save(7, &e.rcvClosed) - stateSinkObject.Save(8, &e.sndBufSize) - stateSinkObject.Save(9, &e.sndBufSizeMax) - stateSinkObject.Save(10, &e.closed) - stateSinkObject.Save(11, &e.connected) - stateSinkObject.Save(12, &e.bound) - stateSinkObject.Save(13, &e.owner) - stateSinkObject.Save(14, &e.ops) + stateSinkObject.Save(8, &e.closed) + stateSinkObject.Save(9, &e.connected) + stateSinkObject.Save(10, &e.bound) + stateSinkObject.Save(11, &e.owner) + stateSinkObject.Save(12, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { @@ -92,13 +88,11 @@ func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(4, &e.rcvList) stateSourceObject.Load(5, &e.rcvBufSize) stateSourceObject.Load(7, &e.rcvClosed) - stateSourceObject.Load(8, &e.sndBufSize) - stateSourceObject.Load(9, &e.sndBufSizeMax) - stateSourceObject.Load(10, &e.closed) - stateSourceObject.Load(11, &e.connected) - stateSourceObject.Load(12, &e.bound) - stateSourceObject.Load(13, &e.owner) - stateSourceObject.Load(14, &e.ops) + stateSourceObject.Load(8, &e.closed) + stateSourceObject.Load(9, &e.connected) + stateSourceObject.Load(10, &e.bound) + stateSourceObject.Load(11, &e.owner) + stateSourceObject.Load(12, &e.ops) stateSourceObject.LoadValue(6, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index 05c431e83..8e43fec81 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -557,7 +557,6 @@ type endpoint struct { // When the send side is closed, the protocol goroutine is notified via // sndCloseWaker, and sndClosed is set to true. sndBufMu sync.Mutex `state:"nosave"` - sndBufSize int sndBufUsed int sndClosed bool sndBufInQueue seqnum.Size @@ -869,7 +868,6 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue waiterQueue: waiterQueue, state: StateInitial, rcvBufSize: DefaultReceiveBufferSize, - sndBufSize: DefaultSendBufferSize, sndMTU: int(math.MaxInt32), keepalive: keepalive{ // Linux defaults. @@ -882,13 +880,14 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue windowClamp: DefaultReceiveBufferSize, maxSynRetries: DefaultSynRetries, } - e.ops.InitHandler(e) + e.ops.InitHandler(e, e.stack) e.ops.SetMulticastLoop(true) e.ops.SetQuickAck(true) + e.ops.SetSendBufferSize(DefaultSendBufferSize, false /* notify */, GetTCPSendBufferLimits) var ss tcpip.TCPSendBufferSizeRangeOption if err := s.TransportProtocolOption(ProtocolNumber, &ss); err == nil { - e.sndBufSize = ss.Default + e.ops.SetSendBufferSize(int64(ss.Default), false /* notify */, GetTCPSendBufferLimits) } var rs tcpip.TCPReceiveBufferSizeRangeOption @@ -967,7 +966,8 @@ func (e *endpoint) Readiness(mask waiter.EventMask) waiter.EventMask { // Determine if the endpoint is writable if requested. if (mask & waiter.EventOut) != 0 { e.sndBufMu.Lock() - if e.sndClosed || e.sndBufUsed < e.sndBufSize { + sndBufSize := e.getSendBufferSize() + if e.sndClosed || e.sndBufUsed < sndBufSize { result |= waiter.EventOut } e.sndBufMu.Unlock() @@ -1499,7 +1499,8 @@ func (e *endpoint) isEndpointWritableLocked() (int, *tcpip.Error) { return 0, tcpip.ErrClosedForSend } - avail := e.sndBufSize - e.sndBufUsed + sndBufSize := e.getSendBufferSize() + avail := sndBufSize - e.sndBufUsed if avail <= 0 { return 0, tcpip.ErrWouldBlock } @@ -1692,6 +1693,14 @@ 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) +} + // SetSockOptInt sets a socket option. func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error { // Lower 2 bits represents ECN bits. RFC 3168, section 23.1 @@ -1785,31 +1794,6 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error { e.rcvListMu.Unlock() e.UnlockUser() - case tcpip.SendBufferSizeOption: - // Make sure the send buffer size is within the min and max - // allowed. - var ss tcpip.TCPSendBufferSizeRangeOption - if err := e.stack.TransportProtocolOption(ProtocolNumber, &ss); err != nil { - panic(fmt.Sprintf("e.stack.TransportProtocolOption(%d, %#v) = %s", ProtocolNumber, &ss, err)) - } - - if v > ss.Max { - v = ss.Max - } - - if v < math.MaxInt32/SegOverheadFactor { - v *= SegOverheadFactor - if v < ss.Min { - v = ss.Min - } - } else { - v = math.MaxInt32 - } - - e.sndBufMu.Lock() - e.sndBufSize = v - e.sndBufMu.Unlock() - case tcpip.TTLOption: e.LockUser() e.ttl = uint8(v) @@ -1995,12 +1979,6 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) { case tcpip.ReceiveQueueSizeOption: return e.readyReceiveSize() - case tcpip.SendBufferSizeOption: - e.sndBufMu.Lock() - v := e.sndBufSize - e.sndBufMu.Unlock() - return v, nil - case tcpip.ReceiveBufferSizeOption: e.rcvListMu.Lock() v := e.rcvBufSize @@ -2749,13 +2727,14 @@ func (e *endpoint) HandleControlPacket(typ stack.ControlType, extra uint32, pkt // updateSndBufferUsage is called by the protocol goroutine when room opens up // in the send buffer. The number of newly available bytes is v. func (e *endpoint) updateSndBufferUsage(v int) { + sendBufferSize := e.getSendBufferSize() e.sndBufMu.Lock() - notify := e.sndBufUsed >= e.sndBufSize>>1 + notify := e.sndBufUsed >= sendBufferSize>>1 e.sndBufUsed -= v - // We only notify when there is half the sndBufSize available after + // We only notify when there is half the sendBufferSize available after // a full buffer event occurs. This ensures that we don't wake up // writers to queue just 1-2 segments and go back to sleep. - notify = notify && e.sndBufUsed < e.sndBufSize>>1 + notify = notify && e.sndBufUsed < int(sendBufferSize)>>1 e.sndBufMu.Unlock() if notify { @@ -2967,8 +2946,9 @@ func (e *endpoint) completeState() stack.TCPEndpointState { s.SACK.ReceivedBlocks, s.SACK.MaxSACKED = e.scoreboard.Copy() // Copy endpoint send state. + sndBufSize := e.getSendBufferSize() e.sndBufMu.Lock() - s.SndBufSize = e.sndBufSize + s.SndBufSize = sndBufSize s.SndBufUsed = e.sndBufUsed s.SndClosed = e.sndClosed s.SndBufInQueue = e.sndBufInQueue @@ -3113,3 +3093,17 @@ func (e *endpoint) Wait() { func (e *endpoint) SocketOptions() *tcpip.SocketOptions { return &e.ops } + +// GetTCPSendBufferLimits is used to get send buffer size limits for TCP. +func GetTCPSendBufferLimits(s tcpip.StackHandler) tcpip.SendBufferSizeOption { + var ss tcpip.TCPSendBufferSizeRangeOption + if err := s.TransportProtocolOption(header.TCPProtocolNumber, &ss); err != nil { + panic(fmt.Sprintf("s.TransportProtocolOption(%d, %#v) = %s", header.TCPProtocolNumber, ss, err)) + } + + return tcpip.SendBufferSizeOption{ + Min: ss.Min, + Default: ss.Default, + Max: ss.Max, + } +} diff --git a/pkg/tcpip/transport/tcp/endpoint_state.go b/pkg/tcpip/transport/tcp/endpoint_state.go index ba67176b5..19c1dc67a 100644 --- a/pkg/tcpip/transport/tcp/endpoint_state.go +++ b/pkg/tcpip/transport/tcp/endpoint_state.go @@ -179,14 +179,16 @@ func (e *endpoint) afterLoad() { // Resume implements tcpip.ResumableEndpoint.Resume. func (e *endpoint) Resume(s *stack.Stack) { e.stack = s + e.ops.InitHandler(e, e.stack) e.segmentQueue.thaw() epState := e.origEndpointState switch epState { case StateInitial, StateBound, StateListen, StateConnecting, StateEstablished: var ss tcpip.TCPSendBufferSizeRangeOption if err := e.stack.TransportProtocolOption(ProtocolNumber, &ss); err == nil { - if e.sndBufSize < ss.Min || e.sndBufSize > ss.Max { - panic(fmt.Sprintf("endpoint.sndBufSize %d is outside the min and max allowed [%d, %d]", e.sndBufSize, ss.Min, ss.Max)) + sendBufferSize := e.getSendBufferSize() + if sendBufferSize < ss.Min || sendBufferSize > ss.Max { + panic(fmt.Sprintf("endpoint sendBufferSize %d is outside the min and max allowed [%d, %d]", sendBufferSize, ss.Min, ss.Max)) } } diff --git a/pkg/tcpip/transport/tcp/tcp_state_autogen.go b/pkg/tcpip/transport/tcp/tcp_state_autogen.go index 6131d151a..c9926f8ca 100644 --- a/pkg/tcpip/transport/tcp/tcp_state_autogen.go +++ b/pkg/tcpip/transport/tcp/tcp_state_autogen.go @@ -195,7 +195,6 @@ func (e *endpoint) StateFields() []string { "userMSS", "maxSynRetries", "windowClamp", - "sndBufSize", "sndBufUsed", "sndClosed", "sndBufInQueue", @@ -232,7 +231,7 @@ func (e *endpoint) StateSave(stateSinkObject state.Sink) { var recentTSTimeValue unixTime = e.saveRecentTSTime() stateSinkObject.SaveValue(26, recentTSTimeValue) var acceptedChanValue []*endpoint = e.saveAcceptedChan() - stateSinkObject.SaveValue(50, acceptedChanValue) + stateSinkObject.SaveValue(49, acceptedChanValue) stateSinkObject.Save(0, &e.EndpointInfo) stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) stateSinkObject.Save(2, &e.waiterQueue) @@ -268,28 +267,27 @@ func (e *endpoint) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(36, &e.userMSS) stateSinkObject.Save(37, &e.maxSynRetries) stateSinkObject.Save(38, &e.windowClamp) - stateSinkObject.Save(39, &e.sndBufSize) - stateSinkObject.Save(40, &e.sndBufUsed) - stateSinkObject.Save(41, &e.sndClosed) - stateSinkObject.Save(42, &e.sndBufInQueue) - stateSinkObject.Save(43, &e.sndQueue) - stateSinkObject.Save(44, &e.cc) - stateSinkObject.Save(45, &e.packetTooBigCount) - stateSinkObject.Save(46, &e.sndMTU) - stateSinkObject.Save(47, &e.keepalive) - stateSinkObject.Save(48, &e.userTimeout) - stateSinkObject.Save(49, &e.deferAccept) - stateSinkObject.Save(51, &e.rcv) - stateSinkObject.Save(52, &e.snd) - stateSinkObject.Save(53, &e.connectingAddress) - stateSinkObject.Save(54, &e.amss) - stateSinkObject.Save(55, &e.sendTOS) - stateSinkObject.Save(56, &e.gso) - stateSinkObject.Save(57, &e.tcpLingerTimeout) - stateSinkObject.Save(58, &e.closed) - stateSinkObject.Save(59, &e.txHash) - stateSinkObject.Save(60, &e.owner) - stateSinkObject.Save(61, &e.ops) + stateSinkObject.Save(39, &e.sndBufUsed) + stateSinkObject.Save(40, &e.sndClosed) + stateSinkObject.Save(41, &e.sndBufInQueue) + stateSinkObject.Save(42, &e.sndQueue) + stateSinkObject.Save(43, &e.cc) + stateSinkObject.Save(44, &e.packetTooBigCount) + stateSinkObject.Save(45, &e.sndMTU) + stateSinkObject.Save(46, &e.keepalive) + stateSinkObject.Save(47, &e.userTimeout) + stateSinkObject.Save(48, &e.deferAccept) + stateSinkObject.Save(50, &e.rcv) + stateSinkObject.Save(51, &e.snd) + stateSinkObject.Save(52, &e.connectingAddress) + stateSinkObject.Save(53, &e.amss) + stateSinkObject.Save(54, &e.sendTOS) + stateSinkObject.Save(55, &e.gso) + stateSinkObject.Save(56, &e.tcpLingerTimeout) + stateSinkObject.Save(57, &e.closed) + stateSinkObject.Save(58, &e.txHash) + stateSinkObject.Save(59, &e.owner) + stateSinkObject.Save(60, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { @@ -328,33 +326,32 @@ func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(36, &e.userMSS) stateSourceObject.Load(37, &e.maxSynRetries) stateSourceObject.Load(38, &e.windowClamp) - stateSourceObject.Load(39, &e.sndBufSize) - stateSourceObject.Load(40, &e.sndBufUsed) - stateSourceObject.Load(41, &e.sndClosed) - stateSourceObject.Load(42, &e.sndBufInQueue) - stateSourceObject.LoadWait(43, &e.sndQueue) - stateSourceObject.Load(44, &e.cc) - stateSourceObject.Load(45, &e.packetTooBigCount) - stateSourceObject.Load(46, &e.sndMTU) - stateSourceObject.Load(47, &e.keepalive) - stateSourceObject.Load(48, &e.userTimeout) - stateSourceObject.Load(49, &e.deferAccept) - stateSourceObject.LoadWait(51, &e.rcv) - stateSourceObject.LoadWait(52, &e.snd) - stateSourceObject.Load(53, &e.connectingAddress) - stateSourceObject.Load(54, &e.amss) - stateSourceObject.Load(55, &e.sendTOS) - stateSourceObject.Load(56, &e.gso) - stateSourceObject.Load(57, &e.tcpLingerTimeout) - stateSourceObject.Load(58, &e.closed) - stateSourceObject.Load(59, &e.txHash) - stateSourceObject.Load(60, &e.owner) - stateSourceObject.Load(61, &e.ops) + stateSourceObject.Load(39, &e.sndBufUsed) + stateSourceObject.Load(40, &e.sndClosed) + stateSourceObject.Load(41, &e.sndBufInQueue) + stateSourceObject.LoadWait(42, &e.sndQueue) + stateSourceObject.Load(43, &e.cc) + stateSourceObject.Load(44, &e.packetTooBigCount) + stateSourceObject.Load(45, &e.sndMTU) + stateSourceObject.Load(46, &e.keepalive) + stateSourceObject.Load(47, &e.userTimeout) + stateSourceObject.Load(48, &e.deferAccept) + stateSourceObject.LoadWait(50, &e.rcv) + stateSourceObject.LoadWait(51, &e.snd) + stateSourceObject.Load(52, &e.connectingAddress) + stateSourceObject.Load(53, &e.amss) + stateSourceObject.Load(54, &e.sendTOS) + stateSourceObject.Load(55, &e.gso) + stateSourceObject.Load(56, &e.tcpLingerTimeout) + stateSourceObject.Load(57, &e.closed) + stateSourceObject.Load(58, &e.txHash) + stateSourceObject.Load(59, &e.owner) + stateSourceObject.Load(60, &e.ops) stateSourceObject.LoadValue(4, new(string), func(y interface{}) { e.loadHardError(y.(string)) }) stateSourceObject.LoadValue(5, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) stateSourceObject.LoadValue(13, new(EndpointState), func(y interface{}) { e.loadState(y.(EndpointState)) }) stateSourceObject.LoadValue(26, new(unixTime), func(y interface{}) { e.loadRecentTSTime(y.(unixTime)) }) - stateSourceObject.LoadValue(50, new([]*endpoint), func(y interface{}) { e.loadAcceptedChan(y.([]*endpoint)) }) + stateSourceObject.LoadValue(49, new([]*endpoint), func(y interface{}) { e.loadAcceptedChan(y.([]*endpoint)) }) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go index 8544fcb08..ee7e43b97 100644 --- a/pkg/tcpip/transport/udp/endpoint.go +++ b/pkg/tcpip/transport/udp/endpoint.go @@ -97,9 +97,7 @@ type endpoint struct { rcvClosed bool // The following fields are protected by the mu mutex. - mu sync.RWMutex `state:"nosave"` - sndBufSize int - sndBufSizeMax int + mu sync.RWMutex `state:"nosave"` // state must be read/set using the EndpointState()/setEndpointState() // methods. state EndpointState @@ -176,18 +174,18 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue // Linux defaults to TTL=1. multicastTTL: 1, rcvBufSizeMax: 32 * 1024, - sndBufSizeMax: 32 * 1024, multicastMemberships: make(map[multicastMembership]struct{}), state: StateInitial, uniqueID: s.UniqueID(), } - e.ops.InitHandler(e) + e.ops.InitHandler(e, e.stack) e.ops.SetMulticastLoop(true) + e.ops.SetSendBufferSize(32*1024, false /* notify */, tcpip.GetStackSendBufferLimits) // Override with stack defaults. - var ss stack.SendBufferSizeOption + var ss tcpip.SendBufferSizeOption if err := s.Option(&ss); err == nil { - e.sndBufSizeMax = ss.Default + e.ops.SetSendBufferSize(int64(ss.Default), false /* notify */, tcpip.GetStackSendBufferLimits) } var rs stack.ReceiveBufferSizeOption @@ -632,25 +630,6 @@ func (e *endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) *tcpip.Error { e.rcvBufSizeMax = v e.mu.Unlock() return nil - case tcpip.SendBufferSizeOption: - // Make sure the send buffer size is within the min and max - // allowed. - var ss stack.SendBufferSizeOption - if err := e.stack.Option(&ss); err != nil { - panic(fmt.Sprintf("e.stack.Option(%#v) = %s", ss, err)) - } - - if v < ss.Min { - v = ss.Min - } - if v > ss.Max { - v = ss.Max - } - - e.mu.Lock() - e.sndBufSizeMax = v - e.mu.Unlock() - return nil } return nil @@ -811,12 +790,6 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, *tcpip.Error) { e.rcvMu.Unlock() return v, nil - case tcpip.SendBufferSizeOption: - e.mu.Lock() - v := e.sndBufSizeMax - e.mu.Unlock() - return v, nil - case tcpip.ReceiveBufferSizeOption: e.rcvMu.Lock() v := e.rcvBufSizeMax diff --git a/pkg/tcpip/transport/udp/endpoint_state.go b/pkg/tcpip/transport/udp/endpoint_state.go index 13b72dc88..903397f1c 100644 --- a/pkg/tcpip/transport/udp/endpoint_state.go +++ b/pkg/tcpip/transport/udp/endpoint_state.go @@ -91,6 +91,7 @@ func (e *endpoint) Resume(s *stack.Stack) { defer e.mu.Unlock() e.stack = s + e.ops.InitHandler(e, e.stack) for m := range e.multicastMemberships { if err := e.stack.JoinGroup(e.NetProto, m.nicID, m.multicastAddr); err != nil { diff --git a/pkg/tcpip/transport/udp/udp_state_autogen.go b/pkg/tcpip/transport/udp/udp_state_autogen.go index 2b7726097..6f61505c9 100644 --- a/pkg/tcpip/transport/udp/udp_state_autogen.go +++ b/pkg/tcpip/transport/udp/udp_state_autogen.go @@ -64,8 +64,6 @@ func (e *endpoint) StateFields() []string { "rcvBufSizeMax", "rcvBufSize", "rcvClosed", - "sndBufSize", - "sndBufSizeMax", "state", "dstPort", "ttl", @@ -90,7 +88,7 @@ func (e *endpoint) StateSave(stateSinkObject state.Sink) { var rcvBufSizeMaxValue int = e.saveRcvBufSizeMax() stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) var lastErrorValue string = e.saveLastError() - stateSinkObject.SaveValue(18, lastErrorValue) + stateSinkObject.SaveValue(16, lastErrorValue) stateSinkObject.Save(0, &e.TransportEndpointInfo) stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) stateSinkObject.Save(2, &e.waiterQueue) @@ -99,23 +97,21 @@ func (e *endpoint) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(5, &e.rcvList) stateSinkObject.Save(7, &e.rcvBufSize) stateSinkObject.Save(8, &e.rcvClosed) - stateSinkObject.Save(9, &e.sndBufSize) - stateSinkObject.Save(10, &e.sndBufSizeMax) - stateSinkObject.Save(11, &e.state) - stateSinkObject.Save(12, &e.dstPort) - stateSinkObject.Save(13, &e.ttl) - stateSinkObject.Save(14, &e.multicastTTL) - stateSinkObject.Save(15, &e.multicastAddr) - stateSinkObject.Save(16, &e.multicastNICID) - stateSinkObject.Save(17, &e.portFlags) - stateSinkObject.Save(19, &e.boundBindToDevice) - stateSinkObject.Save(20, &e.boundPortFlags) - stateSinkObject.Save(21, &e.sendTOS) - stateSinkObject.Save(22, &e.shutdownFlags) - stateSinkObject.Save(23, &e.multicastMemberships) - stateSinkObject.Save(24, &e.effectiveNetProtos) - stateSinkObject.Save(25, &e.owner) - stateSinkObject.Save(26, &e.ops) + stateSinkObject.Save(9, &e.state) + stateSinkObject.Save(10, &e.dstPort) + stateSinkObject.Save(11, &e.ttl) + stateSinkObject.Save(12, &e.multicastTTL) + stateSinkObject.Save(13, &e.multicastAddr) + stateSinkObject.Save(14, &e.multicastNICID) + stateSinkObject.Save(15, &e.portFlags) + stateSinkObject.Save(17, &e.boundBindToDevice) + stateSinkObject.Save(18, &e.boundPortFlags) + stateSinkObject.Save(19, &e.sendTOS) + stateSinkObject.Save(20, &e.shutdownFlags) + stateSinkObject.Save(21, &e.multicastMemberships) + stateSinkObject.Save(22, &e.effectiveNetProtos) + stateSinkObject.Save(23, &e.owner) + stateSinkObject.Save(24, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { @@ -127,25 +123,23 @@ func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(5, &e.rcvList) stateSourceObject.Load(7, &e.rcvBufSize) stateSourceObject.Load(8, &e.rcvClosed) - stateSourceObject.Load(9, &e.sndBufSize) - stateSourceObject.Load(10, &e.sndBufSizeMax) - stateSourceObject.Load(11, &e.state) - stateSourceObject.Load(12, &e.dstPort) - stateSourceObject.Load(13, &e.ttl) - stateSourceObject.Load(14, &e.multicastTTL) - stateSourceObject.Load(15, &e.multicastAddr) - stateSourceObject.Load(16, &e.multicastNICID) - stateSourceObject.Load(17, &e.portFlags) - stateSourceObject.Load(19, &e.boundBindToDevice) - stateSourceObject.Load(20, &e.boundPortFlags) - stateSourceObject.Load(21, &e.sendTOS) - stateSourceObject.Load(22, &e.shutdownFlags) - stateSourceObject.Load(23, &e.multicastMemberships) - stateSourceObject.Load(24, &e.effectiveNetProtos) - stateSourceObject.Load(25, &e.owner) - stateSourceObject.Load(26, &e.ops) + stateSourceObject.Load(9, &e.state) + stateSourceObject.Load(10, &e.dstPort) + stateSourceObject.Load(11, &e.ttl) + stateSourceObject.Load(12, &e.multicastTTL) + stateSourceObject.Load(13, &e.multicastAddr) + stateSourceObject.Load(14, &e.multicastNICID) + stateSourceObject.Load(15, &e.portFlags) + stateSourceObject.Load(17, &e.boundBindToDevice) + stateSourceObject.Load(18, &e.boundPortFlags) + stateSourceObject.Load(19, &e.sendTOS) + stateSourceObject.Load(20, &e.shutdownFlags) + stateSourceObject.Load(21, &e.multicastMemberships) + stateSourceObject.Load(22, &e.effectiveNetProtos) + stateSourceObject.Load(23, &e.owner) + stateSourceObject.Load(24, &e.ops) stateSourceObject.LoadValue(6, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) - stateSourceObject.LoadValue(18, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) + stateSourceObject.LoadValue(16, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) stateSourceObject.AfterLoad(e.afterLoad) } |