stack_options.go raw

   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  	"gvisor.dev/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 any) 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 any) 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  }
 126