github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/transport/tcp/protocol.go (about) 1 // Copyright 2018 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 tcp contains the implementation of the TCP transport protocol. To use 16 // it in the networking stack, this package must be added to the project, and 17 // activated on the stack by passing tcp.NewProtocol() as one of the 18 // transport protocols when calling stack.New(). Then endpoints can be created 19 // by passing tcp.ProtocolNumber as the transport protocol number when calling 20 // Stack.NewEndpoint(). 21 package tcp 22 23 import ( 24 "strings" 25 "sync" 26 27 "github.com/FlowerWrong/netstack/tcpip" 28 "github.com/FlowerWrong/netstack/tcpip/buffer" 29 "github.com/FlowerWrong/netstack/tcpip/header" 30 "github.com/FlowerWrong/netstack/tcpip/seqnum" 31 "github.com/FlowerWrong/netstack/tcpip/stack" 32 "github.com/FlowerWrong/netstack/tcpip/transport/raw" 33 "github.com/FlowerWrong/netstack/waiter" 34 ) 35 36 const ( 37 // ProtocolNumber is the tcp protocol number. 38 ProtocolNumber = header.TCPProtocolNumber 39 40 // MinBufferSize is the smallest size of a receive or send buffer. 41 MinBufferSize = 4 << 10 // 4096 bytes. 42 43 // DefaultSendBufferSize is the default size of the send buffer for 44 // an endpoint. 45 DefaultSendBufferSize = 1 << 20 // 1MB 46 47 // DefaultReceiveBufferSize is the default size of the receive buffer 48 // for an endpoint. 49 DefaultReceiveBufferSize = 1 << 20 // 1MB 50 51 // MaxBufferSize is the largest size a receive/send buffer can grow to. 52 MaxBufferSize = 4 << 20 // 4MB 53 54 // MaxUnprocessedSegments is the maximum number of unprocessed segments 55 // that can be queued for a given endpoint. 56 MaxUnprocessedSegments = 300 57 ) 58 59 // SACKEnabled option can be used to enable SACK support in the TCP 60 // protocol. See: https://tools.ietf.org/html/rfc2018. 61 type SACKEnabled bool 62 63 // SendBufferSizeOption allows the default, min and max send buffer sizes for 64 // TCP endpoints to be queried or configured. 65 type SendBufferSizeOption struct { 66 Min int 67 Default int 68 Max int 69 } 70 71 // ReceiveBufferSizeOption allows the default, min and max receive buffer size 72 // for TCP endpoints to be queried or configured. 73 type ReceiveBufferSizeOption struct { 74 Min int 75 Default int 76 Max int 77 } 78 79 const ( 80 ccReno = "reno" 81 ccCubic = "cubic" 82 ) 83 84 type protocol struct { 85 mu sync.Mutex 86 sackEnabled bool 87 sendBufferSize SendBufferSizeOption 88 recvBufferSize ReceiveBufferSizeOption 89 congestionControl string 90 availableCongestionControl []string 91 moderateReceiveBuffer bool 92 } 93 94 // Number returns the tcp protocol number. 95 func (*protocol) Number() tcpip.TransportProtocolNumber { 96 return ProtocolNumber 97 } 98 99 // NewEndpoint creates a new tcp endpoint. 100 func (*protocol) NewEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { 101 return newEndpoint(stack, netProto, waiterQueue), nil 102 } 103 104 // NewRawEndpoint creates a new raw TCP endpoint. Raw TCP sockets are currently 105 // unsupported. It implements stack.TransportProtocol.NewRawEndpoint. 106 func (p *protocol) NewRawEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { 107 return raw.NewEndpoint(stack, netProto, header.TCPProtocolNumber, waiterQueue) 108 } 109 110 // MinimumPacketSize returns the minimum valid tcp packet size. 111 func (*protocol) MinimumPacketSize() int { 112 return header.TCPMinimumSize 113 } 114 115 // ParsePorts returns the source and destination ports stored in the given tcp 116 // packet. 117 func (*protocol) ParsePorts(v buffer.View) (src, dst uint16, err *tcpip.Error) { 118 h := header.TCP(v) 119 return h.SourcePort(), h.DestinationPort(), nil 120 } 121 122 // HandleUnknownDestinationPacket handles packets targeted at this protocol but 123 // that don't match any existing endpoint. 124 // 125 // RFC 793, page 36, states that "If the connection does not exist (CLOSED) then 126 // a reset is sent in response to any incoming segment except another reset. In 127 // particular, SYNs addressed to a non-existent connection are rejected by this 128 // means." 129 func (*protocol) HandleUnknownDestinationPacket(r *stack.Route, id stack.TransportEndpointID, netHeader buffer.View, vv buffer.VectorisedView) bool { 130 s := newSegment(r, id, vv) 131 defer s.decRef() 132 133 if !s.parse() || !s.csumValid { 134 return false 135 } 136 137 // There's nothing to do if this is already a reset packet. 138 if s.flagIsSet(header.TCPFlagRst) { 139 return true 140 } 141 142 replyWithReset(s) 143 return true 144 } 145 146 // replyWithReset replies to the given segment with a reset segment. 147 func replyWithReset(s *segment) { 148 // Get the seqnum from the packet if the ack flag is set. 149 seq := seqnum.Value(0) 150 if s.flagIsSet(header.TCPFlagAck) { 151 seq = s.ackNumber 152 } 153 154 ack := s.sequenceNumber.Add(s.logicalLen()) 155 156 sendTCP(&s.route, s.id, buffer.VectorisedView{}, s.route.DefaultTTL(), header.TCPFlagRst|header.TCPFlagAck, seq, ack, 0, nil /* options */, nil /* gso */) 157 } 158 159 // SetOption implements TransportProtocol.SetOption. 160 func (p *protocol) SetOption(option interface{}) *tcpip.Error { 161 switch v := option.(type) { 162 case SACKEnabled: 163 p.mu.Lock() 164 p.sackEnabled = bool(v) 165 p.mu.Unlock() 166 return nil 167 168 case SendBufferSizeOption: 169 if v.Min <= 0 || v.Default < v.Min || v.Default > v.Max { 170 return tcpip.ErrInvalidOptionValue 171 } 172 p.mu.Lock() 173 p.sendBufferSize = v 174 p.mu.Unlock() 175 return nil 176 177 case ReceiveBufferSizeOption: 178 if v.Min <= 0 || v.Default < v.Min || v.Default > v.Max { 179 return tcpip.ErrInvalidOptionValue 180 } 181 p.mu.Lock() 182 p.recvBufferSize = v 183 p.mu.Unlock() 184 return nil 185 186 case tcpip.CongestionControlOption: 187 for _, c := range p.availableCongestionControl { 188 if string(v) == c { 189 p.mu.Lock() 190 p.congestionControl = string(v) 191 p.mu.Unlock() 192 return nil 193 } 194 } 195 // linux returns ENOENT when an invalid congestion control 196 // is specified. 197 return tcpip.ErrNoSuchFile 198 199 case tcpip.ModerateReceiveBufferOption: 200 p.mu.Lock() 201 p.moderateReceiveBuffer = bool(v) 202 p.mu.Unlock() 203 return nil 204 205 default: 206 return tcpip.ErrUnknownProtocolOption 207 } 208 } 209 210 // Option implements TransportProtocol.Option. 211 func (p *protocol) Option(option interface{}) *tcpip.Error { 212 switch v := option.(type) { 213 case *SACKEnabled: 214 p.mu.Lock() 215 *v = SACKEnabled(p.sackEnabled) 216 p.mu.Unlock() 217 return nil 218 219 case *SendBufferSizeOption: 220 p.mu.Lock() 221 *v = p.sendBufferSize 222 p.mu.Unlock() 223 return nil 224 225 case *ReceiveBufferSizeOption: 226 p.mu.Lock() 227 *v = p.recvBufferSize 228 p.mu.Unlock() 229 return nil 230 231 case *tcpip.CongestionControlOption: 232 p.mu.Lock() 233 *v = tcpip.CongestionControlOption(p.congestionControl) 234 p.mu.Unlock() 235 return nil 236 237 case *tcpip.AvailableCongestionControlOption: 238 p.mu.Lock() 239 *v = tcpip.AvailableCongestionControlOption(strings.Join(p.availableCongestionControl, " ")) 240 p.mu.Unlock() 241 return nil 242 243 case *tcpip.ModerateReceiveBufferOption: 244 p.mu.Lock() 245 *v = tcpip.ModerateReceiveBufferOption(p.moderateReceiveBuffer) 246 p.mu.Unlock() 247 return nil 248 249 default: 250 return tcpip.ErrUnknownProtocolOption 251 } 252 } 253 254 // NewProtocol returns a TCP transport protocol. 255 func NewProtocol() stack.TransportProtocol { 256 return &protocol{ 257 sendBufferSize: SendBufferSizeOption{MinBufferSize, DefaultSendBufferSize, MaxBufferSize}, 258 recvBufferSize: ReceiveBufferSizeOption{MinBufferSize, DefaultReceiveBufferSize, MaxBufferSize}, 259 congestionControl: ccReno, 260 availableCongestionControl: []string{ccReno, ccCubic}, 261 } 262 }