| // Copyright 2020 The gVisor Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package stack |
| |
| import ( |
| "time" |
| |
| "gvisor.dev/gvisor/pkg/tcpip" |
| ) |
| |
| const ( |
| // MinBufferSize is the smallest size of a receive or send buffer. |
| MinBufferSize = 4 << 10 // 4 KiB |
| |
| // DefaultBufferSize is the default size of the send/recv buffer for a |
| // transport endpoint. |
| DefaultBufferSize = 212 << 10 // 212 KiB |
| |
| // DefaultMaxBufferSize is the default maximum permitted size of a |
| // send/receive buffer. |
| DefaultMaxBufferSize = 4 << 20 // 4 MiB |
| |
| // defaultTCPInvalidRateLimit is the default value for |
| // stack.TCPInvalidRateLimit. |
| defaultTCPInvalidRateLimit = 500 * time.Millisecond |
| ) |
| |
| // ReceiveBufferSizeOption is used by stack.(Stack*).Option/SetOption to |
| // get/set the default, min and max receive buffer sizes. |
| type ReceiveBufferSizeOption struct { |
| Min int |
| Default int |
| Max int |
| } |
| |
| // TCPInvalidRateLimitOption is used by stack.(Stack*).Option/SetOption to get/set |
| // stack.tcpInvalidRateLimit. |
| type TCPInvalidRateLimitOption time.Duration |
| |
| // SetOption allows setting stack wide options. |
| func (s *Stack) SetOption(option interface{}) tcpip.Error { |
| switch v := option.(type) { |
| case tcpip.SendBufferSizeOption: |
| // Make sure we don't allow lowering the buffer below minimum |
| // required for stack to work. |
| if v.Min < MinBufferSize { |
| return &tcpip.ErrInvalidOptionValue{} |
| } |
| |
| if v.Default < v.Min || v.Default > v.Max { |
| return &tcpip.ErrInvalidOptionValue{} |
| } |
| |
| s.mu.Lock() |
| s.sendBufferSize = v |
| s.mu.Unlock() |
| return nil |
| |
| case ReceiveBufferSizeOption: |
| // Make sure we don't allow lowering the buffer below minimum |
| // required for stack to work. |
| if v.Min < MinBufferSize { |
| return &tcpip.ErrInvalidOptionValue{} |
| } |
| |
| if v.Default < v.Min || v.Default > v.Max { |
| return &tcpip.ErrInvalidOptionValue{} |
| } |
| |
| s.mu.Lock() |
| s.receiveBufferSize = v |
| s.mu.Unlock() |
| return nil |
| |
| case TCPInvalidRateLimitOption: |
| if v < 0 { |
| return &tcpip.ErrInvalidOptionValue{} |
| } |
| s.mu.Lock() |
| s.tcpInvalidRateLimit = time.Duration(v) |
| s.mu.Unlock() |
| return nil |
| |
| default: |
| return &tcpip.ErrUnknownProtocolOption{} |
| } |
| } |
| |
| // Option allows retrieving stack wide options. |
| func (s *Stack) Option(option interface{}) tcpip.Error { |
| switch v := option.(type) { |
| case *tcpip.SendBufferSizeOption: |
| s.mu.RLock() |
| *v = s.sendBufferSize |
| s.mu.RUnlock() |
| return nil |
| |
| case *ReceiveBufferSizeOption: |
| s.mu.RLock() |
| *v = s.receiveBufferSize |
| s.mu.RUnlock() |
| return nil |
| |
| case *TCPInvalidRateLimitOption: |
| s.mu.RLock() |
| *v = TCPInvalidRateLimitOption(s.tcpInvalidRateLimit) |
| s.mu.RUnlock() |
| return nil |
| |
| default: |
| return &tcpip.ErrUnknownProtocolOption{} |
| } |
| } |