github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/stack/stack_options.go (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package stack
    16  
    17  import (
    18  	"time"
    19  
    20  	"github.com/SagerNet/gvisor/pkg/tcpip"
    21  )
    22  
    23  const (
    24  	// MinBufferSize is the smallest size of a receive or send buffer.
    25  	MinBufferSize = 4 << 10 // 4 KiB
    26  
    27  	// DefaultBufferSize is the default size of the send/recv buffer for a
    28  	// transport endpoint.
    29  	DefaultBufferSize = 212 << 10 // 212 KiB
    30  
    31  	// DefaultMaxBufferSize is the default maximum permitted size of a
    32  	// send/receive buffer.
    33  	DefaultMaxBufferSize = 4 << 20 // 4 MiB
    34  
    35  	// defaultTCPInvalidRateLimit is the default value for
    36  	// stack.TCPInvalidRateLimit.
    37  	defaultTCPInvalidRateLimit = 500 * time.Millisecond
    38  )
    39  
    40  // ReceiveBufferSizeOption is used by stack.(Stack*).Option/SetOption to
    41  // get/set the default, min and max receive buffer sizes.
    42  type ReceiveBufferSizeOption struct {
    43  	Min     int
    44  	Default int
    45  	Max     int
    46  }
    47  
    48  // TCPInvalidRateLimitOption is used by stack.(Stack*).Option/SetOption to get/set
    49  // stack.tcpInvalidRateLimit.
    50  type TCPInvalidRateLimitOption time.Duration
    51  
    52  // SetOption allows setting stack wide options.
    53  func (s *Stack) SetOption(option interface{}) tcpip.Error {
    54  	switch v := option.(type) {
    55  	case tcpip.SendBufferSizeOption:
    56  		// Make sure we don't allow lowering the buffer below minimum
    57  		// required for stack to work.
    58  		if v.Min < MinBufferSize {
    59  			return &tcpip.ErrInvalidOptionValue{}
    60  		}
    61  
    62  		if v.Default < v.Min || v.Default > v.Max {
    63  			return &tcpip.ErrInvalidOptionValue{}
    64  		}
    65  
    66  		s.mu.Lock()
    67  		s.sendBufferSize = v
    68  		s.mu.Unlock()
    69  		return nil
    70  
    71  	case tcpip.ReceiveBufferSizeOption:
    72  		// Make sure we don't allow lowering the buffer below minimum
    73  		// required for stack to work.
    74  		if v.Min < MinBufferSize {
    75  			return &tcpip.ErrInvalidOptionValue{}
    76  		}
    77  
    78  		if v.Default < v.Min || v.Default > v.Max {
    79  			return &tcpip.ErrInvalidOptionValue{}
    80  		}
    81  
    82  		s.mu.Lock()
    83  		s.receiveBufferSize = v
    84  		s.mu.Unlock()
    85  		return nil
    86  
    87  	case TCPInvalidRateLimitOption:
    88  		if v < 0 {
    89  			return &tcpip.ErrInvalidOptionValue{}
    90  		}
    91  		s.mu.Lock()
    92  		s.tcpInvalidRateLimit = time.Duration(v)
    93  		s.mu.Unlock()
    94  		return nil
    95  
    96  	default:
    97  		return &tcpip.ErrUnknownProtocolOption{}
    98  	}
    99  }
   100  
   101  // Option allows retrieving stack wide options.
   102  func (s *Stack) Option(option interface{}) tcpip.Error {
   103  	switch v := option.(type) {
   104  	case *tcpip.SendBufferSizeOption:
   105  		s.mu.RLock()
   106  		*v = s.sendBufferSize
   107  		s.mu.RUnlock()
   108  		return nil
   109  
   110  	case *tcpip.ReceiveBufferSizeOption:
   111  		s.mu.RLock()
   112  		*v = s.receiveBufferSize
   113  		s.mu.RUnlock()
   114  		return nil
   115  
   116  	case *TCPInvalidRateLimitOption:
   117  		s.mu.RLock()
   118  		*v = TCPInvalidRateLimitOption(s.tcpInvalidRateLimit)
   119  		s.mu.RUnlock()
   120  		return nil
   121  
   122  	default:
   123  		return &tcpip.ErrUnknownProtocolOption{}
   124  	}
   125  }