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