gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/transport/tcp/testing/context/context.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 context provides a test context for use in tcp tests. It also 16 // provides helper methods to assert/check certain behaviours. 17 package context 18 19 import ( 20 "bytes" 21 "context" 22 "testing" 23 "time" 24 25 "gvisor.dev/gvisor/pkg/buffer" 26 "gvisor.dev/gvisor/pkg/tcpip" 27 "gvisor.dev/gvisor/pkg/tcpip/checker" 28 "gvisor.dev/gvisor/pkg/tcpip/checksum" 29 "gvisor.dev/gvisor/pkg/tcpip/header" 30 "gvisor.dev/gvisor/pkg/tcpip/link/channel" 31 "gvisor.dev/gvisor/pkg/tcpip/link/sniffer" 32 "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" 33 "gvisor.dev/gvisor/pkg/tcpip/network/ipv6" 34 "gvisor.dev/gvisor/pkg/tcpip/seqnum" 35 "gvisor.dev/gvisor/pkg/tcpip/stack" 36 "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" 37 "gvisor.dev/gvisor/pkg/waiter" 38 ) 39 40 const ( 41 42 // StackPort is used as the listening port in tests for passive 43 // connects. 44 StackPort = 1234 45 46 // TestPort is the TCP port used for packets sent to the stack 47 // via the link layer endpoint. 48 TestPort = 4096 49 50 // TestInitialSequenceNumber is the initial sequence number sent in packets that 51 // are sent in response to a SYN or in the initial SYN sent to the stack. 52 TestInitialSequenceNumber = 789 53 ) 54 55 var ( 56 // StackAddr is the IPv4 address assigned to the stack. 57 StackAddr = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x01")) 58 59 // TestAddr is the source address for packets sent to the stack via the 60 // link layer endpoint. 61 TestAddr = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x02")) 62 63 // StackV6Addr is the IPv6 address assigned to the stack. 64 StackV6Addr = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")) 65 66 // TestV6Addr is the source address for packets sent to the stack via 67 // the link layer endpoint. 68 TestV6Addr = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02")) 69 70 // StackV4MappedAddr is StackAddr as a mapped v6 address. 71 StackV4MappedAddr = tcpip.AddrFromSlice([]byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" + string(StackAddr.AsSlice()))) 72 73 // TestV4MappedAddr is TestAddr as a mapped v6 address. 74 TestV4MappedAddr = tcpip.AddrFromSlice([]byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" + string(TestAddr.AsSlice()))) 75 76 // V4MappedWildcardAddr is the mapped v6 representation of 0.0.0.0. 77 V4MappedWildcardAddr = tcpip.AddrFromSlice([]byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00")) 78 ) 79 80 // StackAddrWithPrefix is StackAddr with its associated prefix length. 81 var StackAddrWithPrefix = tcpip.AddressWithPrefix{ 82 Address: StackAddr, 83 PrefixLen: 24, 84 } 85 86 // StackV6AddrWithPrefix is StackV6Addr with its associated prefix length. 87 var StackV6AddrWithPrefix = tcpip.AddressWithPrefix{ 88 Address: StackV6Addr, 89 PrefixLen: header.IIDOffsetInIPv6Address * 8, 90 } 91 92 // Headers is used to represent the TCP header fields when building a 93 // new packet. 94 type Headers struct { 95 // SrcPort holds the src port value to be used in the packet. 96 SrcPort uint16 97 98 // DstPort holds the destination port value to be used in the packet. 99 DstPort uint16 100 101 // SeqNum is the value of the sequence number field in the TCP header. 102 SeqNum seqnum.Value 103 104 // AckNum represents the acknowledgement number field in the TCP header. 105 AckNum seqnum.Value 106 107 // Flags are the TCP flags in the TCP header. 108 Flags header.TCPFlags 109 110 // RcvWnd is the window to be advertised in the ReceiveWindow field of 111 // the TCP header. 112 RcvWnd seqnum.Size 113 114 // TCPOpts holds the options to be sent in the option field of the TCP 115 // header. 116 TCPOpts []byte 117 } 118 119 // Options contains options for creating a new test context. 120 type Options struct { 121 // EnableV4 indicates whether IPv4 should be enabled. 122 EnableV4 bool 123 124 // EnableV6 indicates whether IPv4 should be enabled. 125 EnableV6 bool 126 127 // MTU indicates the maximum transmission unit on the link layer. 128 MTU uint32 129 130 // Clock that is used by Stack. 131 Clock tcpip.Clock 132 } 133 134 // Context provides an initialized Network stack and a link layer endpoint 135 // for use in TCP tests. 136 type Context struct { 137 t *testing.T 138 linkEP *channel.Endpoint 139 s *stack.Stack 140 141 // IRS holds the initial sequence number in the SYN sent by endpoint in 142 // case of an active connect or the sequence number sent by the endpoint 143 // in the SYN-ACK sent in response to a SYN when listening in passive 144 // mode. 145 IRS seqnum.Value 146 147 // Port holds the port bound by EP below in case of an active connect or 148 // the listening port number in case of a passive connect. 149 Port uint16 150 151 // EP is the test endpoint in the stack owned by this context. This endpoint 152 // is used in various tests to either initiate an active connect or is used 153 // as a passive listening endpoint to accept inbound connections. 154 EP tcpip.Endpoint 155 156 // Wq is the wait queue associated with EP and is used to block for events 157 // on EP. 158 WQ waiter.Queue 159 160 // TimeStampEnabled is true if ep is connected with the timestamp option 161 // enabled. 162 TimeStampEnabled bool 163 164 // WindowScale is the expected window scale in SYN packets sent by 165 // the stack. 166 WindowScale uint8 167 168 // RcvdWindowScale is the actual window scale sent by the stack in 169 // SYN/SYN-ACK. 170 RcvdWindowScale uint8 171 } 172 173 // New allocates and initializes a test context containing a new 174 // stack and a link-layer endpoint. 175 func New(t *testing.T, mtu uint32) *Context { 176 return NewWithOpts(t, Options{ 177 EnableV4: true, 178 EnableV6: true, 179 MTU: mtu, 180 }) 181 } 182 183 // NewWithOpts allocates and initializes a test context containing a new 184 // stack and a link-layer endpoint with specific options. 185 func NewWithOpts(t *testing.T, opts Options) *Context { 186 if opts.MTU == 0 { 187 panic("MTU must be greater than 0") 188 } 189 190 stackOpts := stack.Options{ 191 TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol}, 192 Clock: opts.Clock, 193 } 194 if opts.EnableV4 { 195 stackOpts.NetworkProtocols = append(stackOpts.NetworkProtocols, ipv4.NewProtocol) 196 } 197 if opts.EnableV6 { 198 stackOpts.NetworkProtocols = append(stackOpts.NetworkProtocols, ipv6.NewProtocol) 199 } 200 s := stack.New(stackOpts) 201 202 const sendBufferSize = 1 << 20 // 1 MiB 203 const recvBufferSize = 1 << 20 // 1 MiB 204 // Allow minimum send/receive buffer sizes to be 1 during tests. 205 sendBufOpt := tcpip.TCPSendBufferSizeRangeOption{Min: 1, Default: sendBufferSize, Max: 10 * sendBufferSize} 206 if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &sendBufOpt); err != nil { 207 t.Fatalf("SetTransportProtocolOption(%d, &%#v) failed: %s", tcp.ProtocolNumber, sendBufOpt, err) 208 } 209 210 rcvBufOpt := tcpip.TCPReceiveBufferSizeRangeOption{Min: 1, Default: recvBufferSize, Max: 10 * recvBufferSize} 211 if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &rcvBufOpt); err != nil { 212 t.Fatalf("SetTransportProtocolOption(%d, &%#v) failed: %s", tcp.ProtocolNumber, rcvBufOpt, err) 213 } 214 215 // Increase minimum RTO in tests to avoid test flakes due to early 216 // retransmit in case the test executors are overloaded and cause timers 217 // to fire earlier than expected. 218 minRTOOpt := tcpip.TCPMinRTOOption(3 * time.Second) 219 if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &minRTOOpt); err != nil { 220 t.Fatalf("s.SetTransportProtocolOption(%d, &%T(%d)): %s", tcp.ProtocolNumber, minRTOOpt, minRTOOpt, err) 221 } 222 223 // Many tests verify the window size. Autotuning can change that value, 224 // so we turn it off. 225 autoTuneOpt := tcpip.TCPModerateReceiveBufferOption(false) 226 if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &autoTuneOpt); err != nil { 227 t.Fatalf("SetTransportProtocolOption(%d, &%T(%t)): %s", tcp.ProtocolNumber, autoTuneOpt, autoTuneOpt, err) 228 } 229 230 // Some of the congestion control tests send up to 640 packets, we so 231 // set the channel size to 1000. 232 ep := channel.New(1000, opts.MTU, "") 233 wep := stack.LinkEndpoint(ep) 234 if testing.Verbose() { 235 wep = sniffer.New(ep) 236 } 237 nicOpts := stack.NICOptions{Name: "nic1"} 238 if err := s.CreateNICWithOptions(1, wep, nicOpts); err != nil { 239 t.Fatalf("CreateNICWithOptions(_, _, %+v) failed: %v", opts, err) 240 } 241 wep2 := stack.LinkEndpoint(channel.New(1000, opts.MTU, "")) 242 if testing.Verbose() { 243 wep2 = sniffer.New(channel.New(1000, opts.MTU, "")) 244 } 245 opts2 := stack.NICOptions{Name: "nic2"} 246 if err := s.CreateNICWithOptions(2, wep2, opts2); err != nil { 247 t.Fatalf("CreateNICWithOptions(_, _, %+v) failed: %v", opts2, err) 248 } 249 250 var routeTable []tcpip.Route 251 252 if opts.EnableV4 { 253 v4ProtocolAddr := tcpip.ProtocolAddress{ 254 Protocol: ipv4.ProtocolNumber, 255 AddressWithPrefix: StackAddrWithPrefix, 256 } 257 if err := s.AddProtocolAddress(1, v4ProtocolAddr, stack.AddressProperties{}); err != nil { 258 t.Fatalf("AddProtocolAddress(1, %+v, {}): %s", v4ProtocolAddr, err) 259 } 260 routeTable = append(routeTable, tcpip.Route{ 261 Destination: header.IPv4EmptySubnet, 262 NIC: 1, 263 }) 264 } 265 266 if opts.EnableV6 { 267 v6ProtocolAddr := tcpip.ProtocolAddress{ 268 Protocol: ipv6.ProtocolNumber, 269 AddressWithPrefix: StackV6AddrWithPrefix, 270 } 271 if err := s.AddProtocolAddress(1, v6ProtocolAddr, stack.AddressProperties{}); err != nil { 272 t.Fatalf("AddProtocolAddress(1, %+v, {}): %s", v6ProtocolAddr, err) 273 } 274 routeTable = append(routeTable, tcpip.Route{ 275 Destination: header.IPv6EmptySubnet, 276 NIC: 1, 277 }) 278 } 279 280 s.SetRouteTable(routeTable) 281 282 return &Context{ 283 t: t, 284 s: s, 285 linkEP: ep, 286 WindowScale: uint8(tcp.FindWndScale(recvBufferSize)), 287 } 288 } 289 290 // Cleanup closes the context endpoint if required. 291 func (c *Context) Cleanup() { 292 if c.EP != nil { 293 c.EP.Close() 294 } 295 tcpip.ReleaseDanglingEndpoints() 296 c.Stack().Close() 297 c.Stack().Wait() 298 c.linkEP.Close() 299 } 300 301 // CloseNoWait closes the link and transport endpoints and does not wait for 302 // them to finish processing. 303 func (c *Context) CloseNoWait() { 304 c.EP.Close() 305 c.linkEP.Close() 306 } 307 308 // Stack returns a reference to the stack in the Context. 309 func (c *Context) Stack() *stack.Stack { 310 return c.s 311 } 312 313 // CheckNoPacketTimeout verifies that no packet is received during the time 314 // specified by wait. 315 func (c *Context) CheckNoPacketTimeout(errMsg string, wait time.Duration) { 316 c.t.Helper() 317 318 ctx, cancel := context.WithTimeout(context.Background(), wait) 319 defer cancel() 320 if pkt := c.linkEP.ReadContext(ctx); pkt != nil { 321 c.t.Fatal(errMsg) 322 } 323 } 324 325 // CheckNoPacket verifies that no packet is received for 1 second. 326 func (c *Context) CheckNoPacket(errMsg string) { 327 c.CheckNoPacketTimeout(errMsg, 1*time.Second) 328 } 329 330 // GetPacketWithTimeout reads a packet from the link layer endpoint and verifies 331 // that it is an IPv4 packet with the expected source and destination 332 // addresses. If no packet is received in the specified timeout it will return 333 // nil. 334 func (c *Context) GetPacketWithTimeout(timeout time.Duration) *buffer.View { 335 c.t.Helper() 336 337 ctx, cancel := context.WithTimeout(context.Background(), timeout) 338 defer cancel() 339 pkt := c.linkEP.ReadContext(ctx) 340 if pkt == nil { 341 return nil 342 } 343 defer pkt.DecRef() 344 345 if got, want := pkt.NetworkProtocolNumber, ipv4.ProtocolNumber; got != want { 346 c.t.Fatalf("got pkt.NetworkProtocolNumber = %d, want = %d", got, want) 347 } 348 349 // Just check that the stack set the transport protocol number for outbound 350 // TCP messages. 351 // TODO(gvisor.dev/issues/3810): Remove when protocol numbers are part 352 // of the headerinfo. 353 if got, want := pkt.TransportProtocolNumber, tcp.ProtocolNumber; got != want { 354 c.t.Fatalf("got pkt.TransportProtocolNumber = %d, want = %d", got, want) 355 } 356 357 view := pkt.ToView() 358 359 if pkt.GSOOptions.Type != stack.GSONone && pkt.GSOOptions.L3HdrLen != header.IPv4MinimumSize { 360 c.t.Errorf("got L3HdrLen = %d, want = %d", pkt.GSOOptions.L3HdrLen, header.IPv4MinimumSize) 361 } 362 363 checker.IPv4(c.t, view, checker.SrcAddr(StackAddr), checker.DstAddr(TestAddr)) 364 return view 365 } 366 367 // GetPacket reads a packet from the link layer endpoint and verifies 368 // that it is an IPv4 packet with the expected source and destination 369 // addresses. 370 func (c *Context) GetPacket() *buffer.View { 371 c.t.Helper() 372 373 p := c.GetPacketWithTimeout(5 * time.Second) 374 if p == nil { 375 c.t.Fatalf("Packet wasn't written out") 376 return nil 377 } 378 379 return p 380 } 381 382 // GetPacketNonBlocking reads a packet from the link layer endpoint 383 // and verifies that it is an IPv4 packet with the expected source 384 // and destination address. If no packet is available it will return 385 // nil immediately. 386 func (c *Context) GetPacketNonBlocking() *buffer.View { 387 c.t.Helper() 388 389 pkt := c.linkEP.Read() 390 if pkt == nil { 391 return nil 392 } 393 defer pkt.DecRef() 394 395 if got, want := pkt.NetworkProtocolNumber, ipv4.ProtocolNumber; got != want { 396 c.t.Fatalf("got pkt.NetworkProtocolNumber = %d, want = %d", got, want) 397 } 398 399 // Just check that the stack set the transport protocol number for outbound 400 // TCP messages. 401 // TODO(gvisor.dev/issues/3810): Remove when protocol numbers are part 402 // of the headerinfo. 403 if got, want := pkt.TransportProtocolNumber, tcp.ProtocolNumber; got != want { 404 c.t.Fatalf("got pkt.TransportProtocolNumber = %d, want = %d", got, want) 405 } 406 407 view := pkt.ToView() 408 409 checker.IPv4(c.t, view, checker.SrcAddr(StackAddr), checker.DstAddr(TestAddr)) 410 return view 411 } 412 413 // SendICMPPacket builds and sends an ICMPv4 packet via the link layer endpoint. 414 func (c *Context) SendICMPPacket(typ header.ICMPv4Type, code header.ICMPv4Code, p1, p2 *buffer.View, maxTotalSize int) { 415 // Allocate a buffer data and headers. 416 buf := buffer.NewViewSize(header.IPv4MinimumSize + header.ICMPv4PayloadOffset + p2.Size()) 417 if buf.Size() > maxTotalSize { 418 buf.CapLength(maxTotalSize) 419 } 420 421 ip := header.IPv4(buf.AsSlice()) 422 ip.Encode(&header.IPv4Fields{ 423 TotalLength: uint16(buf.Size()), 424 TTL: 65, 425 Protocol: uint8(header.ICMPv4ProtocolNumber), 426 SrcAddr: TestAddr, 427 DstAddr: StackAddr, 428 }) 429 ip.SetChecksum(^ip.CalculateChecksum()) 430 431 icmp := header.ICMPv4(buf.AsSlice()[header.IPv4MinimumSize:]) 432 icmp.SetType(typ) 433 icmp.SetCode(code) 434 const icmpv4VariableHeaderOffset = 4 435 copy(icmp[icmpv4VariableHeaderOffset:], p1.AsSlice()) 436 copy(icmp[header.ICMPv4PayloadOffset:], p2.AsSlice()) 437 icmp.SetChecksum(0) 438 xsum := ^checksum.Checksum(icmp, 0 /* initial */) 439 icmp.SetChecksum(xsum) 440 441 // Inject packet. 442 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 443 Payload: buffer.MakeWithView(buf), 444 }) 445 defer pkt.DecRef() 446 c.linkEP.InjectInbound(ipv4.ProtocolNumber, pkt) 447 } 448 449 // BuildSegment builds a TCP segment based on the given Headers and payload. 450 func (c *Context) BuildSegment(payload []byte, h *Headers) buffer.Buffer { 451 return c.BuildSegmentWithAddrs(payload, h, TestAddr, StackAddr) 452 } 453 454 // BuildSegmentWithAddrs builds a TCP segment based on the given Headers, 455 // payload and source and destination IPv4 addresses. 456 func (c *Context) BuildSegmentWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) buffer.Buffer { 457 // Allocate a buffer for data and headers. 458 buf := make([]byte, header.TCPMinimumSize+header.IPv4MinimumSize+len(h.TCPOpts)+len(payload)) 459 copy(buf[len(buf)-len(payload):], payload) 460 copy(buf[len(buf)-len(payload)-len(h.TCPOpts):], h.TCPOpts) 461 462 // Initialize the IP header. 463 ip := header.IPv4(buf) 464 ip.Encode(&header.IPv4Fields{ 465 TotalLength: uint16(len(buf)), 466 TTL: 65, 467 Protocol: uint8(tcp.ProtocolNumber), 468 SrcAddr: src, 469 DstAddr: dst, 470 }) 471 ip.SetChecksum(^ip.CalculateChecksum()) 472 473 // Initialize the TCP header. 474 t := header.TCP(buf[header.IPv4MinimumSize:]) 475 t.Encode(&header.TCPFields{ 476 SrcPort: h.SrcPort, 477 DstPort: h.DstPort, 478 SeqNum: uint32(h.SeqNum), 479 AckNum: uint32(h.AckNum), 480 DataOffset: uint8(header.TCPMinimumSize + len(h.TCPOpts)), 481 Flags: h.Flags, 482 WindowSize: uint16(h.RcvWnd), 483 }) 484 485 // Calculate the TCP pseudo-header checksum. 486 xsum := header.PseudoHeaderChecksum(tcp.ProtocolNumber, src, dst, uint16(len(t))) 487 488 // Calculate the TCP checksum and set it. 489 xsum = checksum.Checksum(payload, xsum) 490 t.SetChecksum(^t.CalculateChecksum(xsum)) 491 492 // Inject packet. 493 return buffer.MakeWithData(buf) 494 } 495 496 // SendSegment sends a TCP segment that has already been built and written to a 497 // buffer.VectorisedView. 498 func (c *Context) SendSegment(s buffer.Buffer) { 499 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 500 Payload: s, 501 }) 502 defer pkt.DecRef() 503 c.linkEP.InjectInbound(ipv4.ProtocolNumber, pkt) 504 } 505 506 // SendPacket builds and sends a TCP segment(with the provided payload & TCP 507 // headers) in an IPv4 packet via the link layer endpoint. 508 func (c *Context) SendPacket(payload []byte, h *Headers) { 509 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 510 Payload: c.BuildSegment(payload, h), 511 }) 512 defer pkt.DecRef() 513 c.linkEP.InjectInbound(ipv4.ProtocolNumber, pkt) 514 } 515 516 // SendPacketWithAddrs builds and sends a TCP segment(with the provided payload 517 // & TCPheaders) in an IPv4 packet via the link layer endpoint using the 518 // provided source and destination IPv4 addresses. 519 func (c *Context) SendPacketWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) { 520 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 521 Payload: c.BuildSegmentWithAddrs(payload, h, src, dst), 522 }) 523 defer pkt.DecRef() 524 c.linkEP.InjectInbound(ipv4.ProtocolNumber, pkt) 525 } 526 527 // SendAck sends an ACK packet. 528 func (c *Context) SendAck(seq seqnum.Value, bytesReceived int) { 529 c.SendAckWithSACK(seq, bytesReceived, nil) 530 } 531 532 // SendAckWithSACK sends an ACK packet which includes the sackBlocks specified. 533 func (c *Context) SendAckWithSACK(seq seqnum.Value, bytesReceived int, sackBlocks []header.SACKBlock) { 534 options := make([]byte, 40) 535 offset := 0 536 if len(sackBlocks) > 0 { 537 offset += header.EncodeNOP(options[offset:]) 538 offset += header.EncodeNOP(options[offset:]) 539 offset += header.EncodeSACKBlocks(sackBlocks, options[offset:]) 540 } 541 542 c.SendPacket(nil, &Headers{ 543 SrcPort: TestPort, 544 DstPort: c.Port, 545 Flags: header.TCPFlagAck, 546 SeqNum: seq, 547 AckNum: c.IRS.Add(1 + seqnum.Size(bytesReceived)), 548 RcvWnd: 30000, 549 TCPOpts: options[:offset], 550 }) 551 } 552 553 // ReceiveAndCheckPacket reads a packet from the link layer endpoint and 554 // verifies that the packet packet payload of packet matches the slice 555 // of data indicated by offset & size. 556 func (c *Context) ReceiveAndCheckPacket(data []byte, offset, size int) { 557 c.t.Helper() 558 559 c.ReceiveAndCheckPacketWithOptions(data, offset, size, 0) 560 } 561 562 // ReceiveAndCheckPacketWithOptions reads a packet from the link layer endpoint 563 // and verifies that the packet packet payload of packet matches the slice of 564 // data indicated by offset & size and skips optlen bytes in addition to the IP 565 // TCP headers when comparing the data. 566 func (c *Context) ReceiveAndCheckPacketWithOptions(data []byte, offset, size, optlen int) { 567 c.t.Helper() 568 569 v := c.GetPacket() 570 defer v.Release() 571 checker.IPv4(c.t, v, 572 checker.PayloadLen(size+header.TCPMinimumSize+optlen), 573 checker.TCP( 574 checker.DstPort(TestPort), 575 checker.TCPSeqNum(uint32(c.IRS.Add(seqnum.Size(1+offset)))), 576 checker.TCPAckNum(uint32(seqnum.Value(TestInitialSequenceNumber).Add(1))), 577 checker.TCPFlagsMatch(header.TCPFlagAck, ^header.TCPFlagPsh), 578 ), 579 ) 580 581 pdata := data[offset:][:size] 582 if p := v.AsSlice()[header.IPv4MinimumSize+header.TCPMinimumSize+optlen:]; bytes.Compare(pdata, p) != 0 { 583 c.t.Fatalf("Data is different: expected %v, got %v", pdata, p) 584 } 585 } 586 587 // ReceiveNonBlockingAndCheckPacket reads a packet from the link layer endpoint 588 // and verifies that the packet packet payload of packet matches the slice of 589 // data indicated by offset & size. It returns true if a packet was received and 590 // processed. 591 func (c *Context) ReceiveNonBlockingAndCheckPacket(data []byte, offset, size int) bool { 592 c.t.Helper() 593 594 v := c.GetPacketNonBlocking() 595 if v == nil { 596 return false 597 } 598 defer v.Release() 599 checker.IPv4(c.t, v, 600 checker.PayloadLen(size+header.TCPMinimumSize), 601 checker.TCP( 602 checker.DstPort(TestPort), 603 checker.TCPSeqNum(uint32(c.IRS.Add(seqnum.Size(1+offset)))), 604 checker.TCPAckNum(uint32(seqnum.Value(TestInitialSequenceNumber).Add(1))), 605 checker.TCPFlagsMatch(header.TCPFlagAck, ^header.TCPFlagPsh), 606 ), 607 ) 608 609 pdata := data[offset:][:size] 610 if p := v.AsSlice()[header.IPv4MinimumSize+header.TCPMinimumSize:]; bytes.Compare(pdata, p) != 0 { 611 c.t.Fatalf("Data is different: expected %v, got %v", pdata, p) 612 } 613 return true 614 } 615 616 // CreateV6Endpoint creates and initializes c.ep as a IPv6 Endpoint. If v6Only 617 // is true then it sets the IP_V6ONLY option on the socket to make it a IPv6 618 // only endpoint instead of a default dual stack socket. 619 func (c *Context) CreateV6Endpoint(v6only bool) { 620 var err tcpip.Error 621 c.EP, err = c.s.NewEndpoint(tcp.ProtocolNumber, ipv6.ProtocolNumber, &c.WQ) 622 if err != nil { 623 c.t.Fatalf("NewEndpoint failed: %v", err) 624 } 625 626 c.EP.SocketOptions().SetV6Only(v6only) 627 } 628 629 // GetV6Packet reads a single packet from the link layer endpoint of the context 630 // and asserts that it is an IPv6 Packet with the expected src/dest addresses. 631 func (c *Context) GetV6Packet() *buffer.View { 632 c.t.Helper() 633 634 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) 635 defer cancel() 636 pkt := c.linkEP.ReadContext(ctx) 637 if pkt == nil { 638 c.t.Fatalf("Packet wasn't written out") 639 return nil 640 } 641 defer pkt.DecRef() 642 643 if got, want := pkt.NetworkProtocolNumber, ipv6.ProtocolNumber; got != want { 644 c.t.Fatalf("got pkt.NetworkProtocolNumber = %d, want = %d", got, want) 645 } 646 v := pkt.ToView() 647 648 checker.IPv6(c.t, v, checker.SrcAddr(StackV6Addr), checker.DstAddr(TestV6Addr)) 649 return v 650 } 651 652 // SendV6Packet builds and sends an IPv6 Packet via the link layer endpoint of 653 // the context. 654 func (c *Context) SendV6Packet(payload []byte, h *Headers) { 655 c.SendV6PacketWithAddrs(payload, h, TestV6Addr, StackV6Addr) 656 } 657 658 // SendV6PacketWithAddrs builds and sends an IPv6 Packet via the link layer 659 // endpoint of the context using the provided source and destination IPv6 660 // addresses. 661 func (c *Context) SendV6PacketWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) { 662 // Allocate a buffer for data and headers. 663 buf := make([]byte, header.TCPMinimumSize+header.IPv6MinimumSize+len(payload)+len(h.TCPOpts)) 664 copy(buf[len(buf)-len(payload):], payload) 665 copy(buf[len(buf)-len(payload)-len(h.TCPOpts):], h.TCPOpts) 666 667 // Initialize the IP header. 668 ip := header.IPv6(buf) 669 ip.Encode(&header.IPv6Fields{ 670 PayloadLength: uint16(header.TCPMinimumSize + len(h.TCPOpts) + len(payload)), 671 TransportProtocol: tcp.ProtocolNumber, 672 HopLimit: 65, 673 SrcAddr: src, 674 DstAddr: dst, 675 }) 676 677 // Initialize the TCP header. 678 t := header.TCP(buf[header.IPv6MinimumSize:]) 679 t.Encode(&header.TCPFields{ 680 SrcPort: h.SrcPort, 681 DstPort: h.DstPort, 682 SeqNum: uint32(h.SeqNum), 683 AckNum: uint32(h.AckNum), 684 DataOffset: uint8(header.TCPMinimumSize + len(h.TCPOpts)), 685 Flags: h.Flags, 686 WindowSize: uint16(h.RcvWnd), 687 }) 688 689 // Calculate the TCP pseudo-header checksum. 690 xsum := header.PseudoHeaderChecksum(tcp.ProtocolNumber, src, dst, uint16(len(t))) 691 692 // Calculate the TCP checksum and set it. 693 xsum = checksum.Checksum(payload, xsum) 694 t.SetChecksum(^t.CalculateChecksum(xsum)) 695 696 // Inject packet. 697 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 698 Payload: buffer.MakeWithData(buf), 699 }) 700 defer pkt.DecRef() 701 c.linkEP.InjectInbound(ipv6.ProtocolNumber, pkt) 702 } 703 704 // CreateConnected creates a connected TCP endpoint. 705 func (c *Context) CreateConnected(iss seqnum.Value, rcvWnd seqnum.Size, epRcvBuf int) { 706 c.CreateConnectedWithRawOptions(iss, rcvWnd, epRcvBuf, nil) 707 } 708 709 // Connect performs the 3-way handshake for c.EP with the provided Initial 710 // Sequence Number (iss) and receive window(rcvWnd) and any options if 711 // specified. 712 // 713 // It also sets the receive buffer for the endpoint to the specified 714 // value in epRcvBuf. 715 // 716 // PreCondition: c.EP must already be created. 717 func (c *Context) Connect(iss seqnum.Value, rcvWnd seqnum.Size, options []byte) { 718 c.t.Helper() 719 720 // Start connection attempt. 721 waitEntry, notifyCh := waiter.NewChannelEntry(waiter.WritableEvents) 722 c.WQ.EventRegister(&waitEntry) 723 defer c.WQ.EventUnregister(&waitEntry) 724 725 err := c.EP.Connect(tcpip.FullAddress{Addr: TestAddr, Port: TestPort}) 726 if _, ok := err.(*tcpip.ErrConnectStarted); !ok { 727 c.t.Fatalf("Unexpected return value from Connect: %v", err) 728 } 729 730 // Receive SYN packet. 731 b := c.GetPacket() 732 defer b.Release() 733 checker.IPv4(c.t, b, 734 checker.TCP( 735 checker.DstPort(TestPort), 736 checker.TCPFlags(header.TCPFlagSyn), 737 ), 738 ) 739 if got, want := tcp.EndpointState(c.EP.State()), tcp.StateSynSent; got != want { 740 c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got) 741 } 742 743 tcpHdr := header.TCP(header.IPv4(b.AsSlice()).Payload()) 744 synOpts := header.ParseSynOptions(tcpHdr.Options(), false /* isAck */) 745 c.IRS = seqnum.Value(tcpHdr.SequenceNumber()) 746 747 c.SendPacket(nil, &Headers{ 748 SrcPort: tcpHdr.DestinationPort(), 749 DstPort: tcpHdr.SourcePort(), 750 Flags: header.TCPFlagSyn | header.TCPFlagAck, 751 SeqNum: iss, 752 AckNum: c.IRS.Add(1), 753 RcvWnd: rcvWnd, 754 TCPOpts: options, 755 }) 756 757 // Receive ACK packet. 758 b = c.GetPacket() 759 defer b.Release() 760 checker.IPv4(c.t, b, 761 checker.TCP( 762 checker.DstPort(TestPort), 763 checker.TCPFlags(header.TCPFlagAck), 764 checker.TCPSeqNum(uint32(c.IRS)+1), 765 checker.TCPAckNum(uint32(iss)+1), 766 ), 767 ) 768 769 // Wait for connection to be established. 770 select { 771 case <-notifyCh: 772 if err := c.EP.LastError(); err != nil { 773 c.t.Fatalf("Unexpected error when connecting: %v", err) 774 } 775 case <-time.After(1 * time.Second): 776 c.t.Fatalf("Timed out waiting for connection") 777 } 778 if got, want := tcp.EndpointState(c.EP.State()), tcp.StateEstablished; got != want { 779 c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got) 780 } 781 782 c.RcvdWindowScale = uint8(synOpts.WS) 783 c.Port = tcpHdr.SourcePort() 784 } 785 786 // Create creates a TCP endpoint. 787 func (c *Context) Create(epRcvBuf int) { 788 // Create TCP endpoint. 789 var err tcpip.Error 790 c.EP, err = c.s.NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ) 791 if err != nil { 792 c.t.Fatalf("NewEndpoint failed: %v", err) 793 } 794 795 if epRcvBuf != -1 { 796 c.EP.SocketOptions().SetReceiveBufferSize(int64(epRcvBuf)*2, true /* notify */) 797 } 798 } 799 800 // CreateConnectedWithRawOptions creates a connected TCP endpoint and sends 801 // the specified option bytes as the Option field in the initial SYN packet. 802 // 803 // It also sets the receive buffer for the endpoint to the specified 804 // value in epRcvBuf. 805 func (c *Context) CreateConnectedWithRawOptions(iss seqnum.Value, rcvWnd seqnum.Size, epRcvBuf int, options []byte) { 806 c.Create(epRcvBuf) 807 c.Connect(iss, rcvWnd, options) 808 } 809 810 // RawEndpoint is just a small wrapper around a TCP endpoint's state to make 811 // sending data and ACK packets easy while being able to manipulate the sequence 812 // numbers and timestamp values as needed. 813 type RawEndpoint struct { 814 C *Context 815 SrcPort uint16 816 DstPort uint16 817 Flags header.TCPFlags 818 NextSeqNum seqnum.Value 819 AckNum seqnum.Value 820 WndSize seqnum.Size 821 RecentTS uint32 // Stores the latest timestamp to echo back. 822 TSVal uint32 // TSVal stores the last timestamp sent by this endpoint. 823 824 // SackPermitted is true if SACKPermitted option was negotiated for this endpoint. 825 SACKPermitted bool 826 } 827 828 // SendPacketWithTS embeds the provided tsVal in the Timestamp option 829 // for the packet to be sent out. 830 func (r *RawEndpoint) SendPacketWithTS(payload []byte, tsVal uint32) { 831 r.TSVal = tsVal 832 tsOpt := [12]byte{header.TCPOptionNOP, header.TCPOptionNOP} 833 header.EncodeTSOption(r.TSVal, r.RecentTS, tsOpt[2:]) 834 r.SendPacket(payload, tsOpt[:]) 835 } 836 837 // SendPacket is a small wrapper function to build and send packets. 838 func (r *RawEndpoint) SendPacket(payload []byte, opts []byte) { 839 packetHeaders := &Headers{ 840 SrcPort: r.SrcPort, 841 DstPort: r.DstPort, 842 Flags: r.Flags, 843 SeqNum: r.NextSeqNum, 844 AckNum: r.AckNum, 845 RcvWnd: r.WndSize, 846 TCPOpts: opts, 847 } 848 r.C.SendPacket(payload, packetHeaders) 849 r.NextSeqNum = r.NextSeqNum.Add(seqnum.Size(len(payload))) 850 } 851 852 // VerifyAndReturnACKWithTS verifies that the tsEcr field int he ACK matches 853 // the provided tsVal as well as returns the original packet. 854 func (r *RawEndpoint) VerifyAndReturnACKWithTS(tsVal uint32) *buffer.View { 855 r.C.t.Helper() 856 // Read ACK and verify that tsEcr of ACK packet is [1,2,3,4] 857 ackPacket := r.C.GetPacket() 858 checker.IPv4(r.C.t, ackPacket, 859 checker.TCP( 860 checker.DstPort(r.SrcPort), 861 checker.TCPFlags(header.TCPFlagAck), 862 checker.TCPSeqNum(uint32(r.AckNum)), 863 checker.TCPAckNum(uint32(r.NextSeqNum)), 864 checker.TCPTimestampChecker(true, 0, tsVal), 865 ), 866 ) 867 // Store the parsed TSVal from the ack as recentTS. 868 tcpSeg := header.TCP(header.IPv4(ackPacket.AsSlice()).Payload()) 869 opts := tcpSeg.ParsedOptions() 870 r.RecentTS = opts.TSVal 871 return ackPacket 872 } 873 874 // VerifyACKWithTS verifies that the tsEcr field in the ack matches the provided 875 // tsVal. 876 func (r *RawEndpoint) VerifyACKWithTS(tsVal uint32) { 877 r.C.t.Helper() 878 p := r.VerifyAndReturnACKWithTS(tsVal) 879 p.Release() 880 } 881 882 // VerifyACKRcvWnd verifies that the window advertised by the incoming ACK 883 // matches the provided rcvWnd. 884 func (r *RawEndpoint) VerifyACKRcvWnd(rcvWnd uint16) { 885 r.C.t.Helper() 886 ackPacket := r.C.GetPacket() 887 defer ackPacket.Release() 888 checker.IPv4(r.C.t, ackPacket, 889 checker.TCP( 890 checker.DstPort(r.SrcPort), 891 checker.TCPFlags(header.TCPFlagAck), 892 checker.TCPSeqNum(uint32(r.AckNum)), 893 checker.TCPAckNum(uint32(r.NextSeqNum)), 894 checker.TCPWindow(rcvWnd), 895 ), 896 ) 897 } 898 899 // VerifyACKNoSACK verifies that the ACK does not contain a SACK block. 900 func (r *RawEndpoint) VerifyACKNoSACK() { 901 r.VerifyACKHasSACK(nil) 902 } 903 904 // VerifyACKHasSACK verifies that the ACK contains the specified SACKBlocks. 905 func (r *RawEndpoint) VerifyACKHasSACK(sackBlocks []header.SACKBlock) { 906 // Read ACK and verify that the TCP options in the segment do 907 // not contain a SACK block. 908 ackPacket := r.C.GetPacket() 909 defer ackPacket.Release() 910 checker.IPv4(r.C.t, ackPacket, 911 checker.TCP( 912 checker.DstPort(r.SrcPort), 913 checker.TCPFlags(header.TCPFlagAck), 914 checker.TCPSeqNum(uint32(r.AckNum)), 915 checker.TCPAckNum(uint32(r.NextSeqNum)), 916 checker.TCPSACKBlockChecker(sackBlocks), 917 ), 918 ) 919 } 920 921 // CreateConnectedWithOptionsNoDelay just calls CreateConnectedWithOptions 922 // without delay. 923 func (c *Context) CreateConnectedWithOptionsNoDelay(wantOptions header.TCPSynOptions) *RawEndpoint { 924 return c.CreateConnectedWithOptions(wantOptions, 0 /* delay */) 925 } 926 927 // CreateConnectedWithOptions creates and connects c.ep with the specified TCP 928 // options enabled and returns a RawEndpoint which represents the other end of 929 // the connection. It delays before a SYNACK is sent. This makes c.EP have a 930 // higher RTT estimate so that spurious TLPs aren't sent in tests, which helps 931 // reduce flakiness. 932 // 933 // It also verifies where required(eg.Timestamp) that the ACK to the SYN-ACK 934 // does not carry an option that was not requested. 935 func (c *Context) CreateConnectedWithOptions(wantOptions header.TCPSynOptions, delay time.Duration) *RawEndpoint { 936 var err tcpip.Error 937 c.EP, err = c.s.NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ) 938 if err != nil { 939 c.t.Fatalf("c.s.NewEndpoint(tcp, ipv4...) = %v", err) 940 } 941 if got, want := tcp.EndpointState(c.EP.State()), tcp.StateInitial; got != want { 942 c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got) 943 } 944 945 // Start connection attempt. 946 waitEntry, notifyCh := waiter.NewChannelEntry(waiter.WritableEvents) 947 c.WQ.EventRegister(&waitEntry) 948 defer c.WQ.EventUnregister(&waitEntry) 949 950 testFullAddr := tcpip.FullAddress{Addr: TestAddr, Port: TestPort} 951 err = c.EP.Connect(testFullAddr) 952 if _, ok := err.(*tcpip.ErrConnectStarted); !ok { 953 c.t.Fatalf("c.ep.Connect(%v) = %v", testFullAddr, err) 954 } 955 // Receive SYN packet. 956 b := c.GetPacket() 957 defer b.Release() 958 // Validate that the syn has the timestamp option and a valid 959 // TS value. 960 mss := uint16(c.linkEP.MTU() - header.IPv4MinimumSize - header.TCPMinimumSize) 961 962 synChecker := checker.TCP( 963 checker.DstPort(TestPort), 964 checker.TCPFlags(header.TCPFlagSyn), 965 checker.TCPSynOptions(header.TCPSynOptions{ 966 MSS: mss, 967 TS: true, 968 WS: int(c.WindowScale), 969 SACKPermitted: c.SACKEnabled(), 970 }), 971 ) 972 checker.IPv4(c.t, b, synChecker) 973 if got, want := tcp.EndpointState(c.EP.State()), tcp.StateSynSent; got != want { 974 c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got) 975 } 976 977 tcpSeg := header.TCP(header.IPv4(b.AsSlice()).Payload()) 978 synOptions := header.ParseSynOptions(tcpSeg.Options(), false) 979 980 // Build options w/ tsVal to be sent in the SYN-ACK. 981 synAckOptions := make([]byte, header.TCPOptionsMaximumSize) 982 offset := 0 983 if wantOptions.WS != -1 { 984 offset += header.EncodeWSOption(wantOptions.WS, synAckOptions[offset:]) 985 } 986 if wantOptions.TS { 987 offset += header.EncodeTSOption(wantOptions.TSVal, synOptions.TSVal, synAckOptions[offset:]) 988 } 989 if wantOptions.SACKPermitted { 990 offset += header.EncodeSACKPermittedOption(synAckOptions[offset:]) 991 } 992 993 offset += header.AddTCPOptionPadding(synAckOptions, offset) 994 995 // Build SYN-ACK. 996 c.IRS = seqnum.Value(tcpSeg.SequenceNumber()) 997 iss := seqnum.Value(TestInitialSequenceNumber) 998 if delay > 0 { 999 // Sleep so that RTT is increased. 1000 time.Sleep(delay) 1001 } 1002 c.SendPacket(nil, &Headers{ 1003 SrcPort: tcpSeg.DestinationPort(), 1004 DstPort: tcpSeg.SourcePort(), 1005 Flags: header.TCPFlagSyn | header.TCPFlagAck, 1006 SeqNum: iss, 1007 AckNum: c.IRS.Add(1), 1008 RcvWnd: 30000, 1009 TCPOpts: synAckOptions[:offset], 1010 }) 1011 1012 // Read ACK. 1013 var ackPacket *buffer.View 1014 // Ignore retransimitted SYN packets. 1015 for { 1016 packet := c.GetPacket() 1017 defer packet.Release() 1018 if header.TCP(header.IPv4(packet.AsSlice()).Payload()).Flags()&header.TCPFlagSyn != 0 { 1019 checker.IPv4(c.t, packet, synChecker) 1020 } else { 1021 ackPacket = packet 1022 break 1023 } 1024 } 1025 1026 // Verify TCP header fields. 1027 tcpCheckers := []checker.TransportChecker{ 1028 checker.DstPort(TestPort), 1029 checker.TCPFlags(header.TCPFlagAck), 1030 checker.TCPSeqNum(uint32(c.IRS) + 1), 1031 checker.TCPAckNum(uint32(iss) + 1), 1032 } 1033 1034 // Verify that tsEcr of ACK packet is wantOptions.TSVal if the 1035 // timestamp option was enabled, if not then we verify that 1036 // there is no timestamp in the ACK packet. 1037 if wantOptions.TS { 1038 tcpCheckers = append(tcpCheckers, checker.TCPTimestampChecker(true, 0, wantOptions.TSVal)) 1039 } else { 1040 tcpCheckers = append(tcpCheckers, checker.TCPTimestampChecker(false, 0, 0)) 1041 } 1042 1043 checker.IPv4(c.t, ackPacket, checker.TCP(tcpCheckers...)) 1044 1045 ackSeg := header.TCP(header.IPv4(ackPacket.AsSlice()).Payload()) 1046 ackOptions := ackSeg.ParsedOptions() 1047 1048 // Wait for connection to be established. 1049 select { 1050 case <-notifyCh: 1051 if err := c.EP.LastError(); err != nil { 1052 c.t.Fatalf("Unexpected error when connecting: %v", err) 1053 } 1054 case <-time.After(1 * time.Second): 1055 c.t.Fatalf("Timed out waiting for connection") 1056 } 1057 if got, want := tcp.EndpointState(c.EP.State()), tcp.StateEstablished; got != want { 1058 c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got) 1059 } 1060 1061 // Store the source port in use by the endpoint. 1062 c.Port = tcpSeg.SourcePort() 1063 1064 // Mark in context that timestamp option is enabled for this endpoint. 1065 c.TimeStampEnabled = true 1066 c.RcvdWindowScale = uint8(synOptions.WS) 1067 return &RawEndpoint{ 1068 C: c, 1069 SrcPort: tcpSeg.DestinationPort(), 1070 DstPort: tcpSeg.SourcePort(), 1071 Flags: header.TCPFlagAck | header.TCPFlagPsh, 1072 NextSeqNum: iss + 1, 1073 AckNum: c.IRS.Add(1), 1074 WndSize: 30000, 1075 RecentTS: ackOptions.TSVal, 1076 TSVal: wantOptions.TSVal, 1077 SACKPermitted: wantOptions.SACKPermitted, 1078 } 1079 } 1080 1081 // AcceptWithOptionsNoDelay delegates call to AcceptWithOptions without delay. 1082 func (c *Context) AcceptWithOptionsNoDelay(wndScale int, synOptions header.TCPSynOptions) *RawEndpoint { 1083 return c.AcceptWithOptions(wndScale, synOptions, 0 /* delay */) 1084 } 1085 1086 // AcceptWithOptions initializes a listening endpoint and connects to it with 1087 // the provided options enabled. It delays before the final ACK of the 3WHS is 1088 // sent. It also verifies that the SYN-ACK has the expected values for the 1089 // provided options. 1090 // 1091 // The function returns a RawEndpoint representing the other end of the accepted 1092 // endpoint. 1093 func (c *Context) AcceptWithOptions(wndScale int, synOptions header.TCPSynOptions, delay time.Duration) *RawEndpoint { 1094 // Create EP and start listening. 1095 wq := &waiter.Queue{} 1096 ep, err := c.s.NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, wq) 1097 if err != nil { 1098 c.t.Fatalf("NewEndpoint failed: %v", err) 1099 } 1100 defer ep.Close() 1101 1102 if err := ep.Bind(tcpip.FullAddress{Port: StackPort}); err != nil { 1103 c.t.Fatalf("Bind failed: %v", err) 1104 } 1105 if got, want := tcp.EndpointState(ep.State()), tcp.StateBound; got != want { 1106 c.t.Errorf("Unexpected endpoint state: want %v, got %v", want, got) 1107 } 1108 1109 if err := ep.Listen(10); err != nil { 1110 c.t.Fatalf("Listen failed: %v", err) 1111 } 1112 if got, want := tcp.EndpointState(ep.State()), tcp.StateListen; got != want { 1113 c.t.Errorf("Unexpected endpoint state: want %v, got %v", want, got) 1114 } 1115 1116 rep := c.PassiveConnectWithOptions(100, wndScale, synOptions, delay) 1117 1118 // Try to accept the connection. 1119 we, ch := waiter.NewChannelEntry(waiter.ReadableEvents) 1120 wq.EventRegister(&we) 1121 defer wq.EventUnregister(&we) 1122 1123 c.EP, _, err = ep.Accept(nil) 1124 if _, ok := err.(*tcpip.ErrWouldBlock); ok { 1125 // Wait for connection to be established. 1126 select { 1127 case <-ch: 1128 c.EP, _, err = ep.Accept(nil) 1129 if err != nil { 1130 c.t.Fatalf("Accept failed: %v", err) 1131 } 1132 1133 case <-time.After(1 * time.Second): 1134 c.t.Fatalf("Timed out waiting for accept") 1135 } 1136 } 1137 if got, want := tcp.EndpointState(c.EP.State()), tcp.StateEstablished; got != want { 1138 c.t.Errorf("Unexpected endpoint state: want %v, got %v", want, got) 1139 } 1140 1141 return rep 1142 } 1143 1144 // PassiveConnect just disables WindowScaling and delegates the call to 1145 // PassiveConnectWithOptions. 1146 func (c *Context) PassiveConnect(maxPayload, wndScale int, synOptions header.TCPSynOptions) { 1147 synOptions.WS = -1 1148 c.PassiveConnectWithOptions(maxPayload, wndScale, synOptions, 0 /* delay */) 1149 } 1150 1151 // PassiveConnectWithOptions initiates a new connection (with the specified TCP 1152 // options enabled) to the port on which the Context.ep is listening for new 1153 // connections. It also validates that the SYN-ACK has the expected values for 1154 // the enabled options. The final ACK of the handshake is delayed by specified 1155 // duration. 1156 // 1157 // NOTE: MSS is not a negotiated option and it can be asymmetric 1158 // in each direction. This function uses the maxPayload to set the MSS to be 1159 // sent to the peer on a connect and validates that the MSS in the SYN-ACK 1160 // response is equal to the MTU - (tcphdr len + iphdr len). 1161 // 1162 // wndScale is the expected window scale in the SYN-ACK and synOptions.WS is the 1163 // value of the window scaling option to be sent in the SYN. If synOptions.WS > 1164 // 0 then we send the WindowScale option. 1165 func (c *Context) PassiveConnectWithOptions(maxPayload, wndScale int, synOptions header.TCPSynOptions, delay time.Duration) *RawEndpoint { 1166 c.t.Helper() 1167 opts := make([]byte, header.TCPOptionsMaximumSize) 1168 offset := 0 1169 offset += header.EncodeMSSOption(uint32(maxPayload), opts) 1170 1171 if synOptions.WS >= 0 { 1172 offset += header.EncodeWSOption(3, opts[offset:]) 1173 } 1174 if synOptions.TS { 1175 offset += header.EncodeTSOption(synOptions.TSVal, synOptions.TSEcr, opts[offset:]) 1176 } 1177 1178 if synOptions.SACKPermitted { 1179 offset += header.EncodeSACKPermittedOption(opts[offset:]) 1180 } 1181 1182 paddingToAdd := 4 - offset%4 1183 // Now add any padding bytes that might be required to quad align the 1184 // options. 1185 for i := offset; i < offset+paddingToAdd; i++ { 1186 opts[i] = header.TCPOptionNOP 1187 } 1188 offset += paddingToAdd 1189 1190 // Send a SYN request. 1191 iss := seqnum.Value(TestInitialSequenceNumber) 1192 c.SendPacket(nil, &Headers{ 1193 SrcPort: TestPort, 1194 DstPort: StackPort, 1195 Flags: header.TCPFlagSyn | synOptions.Flags, 1196 SeqNum: iss, 1197 RcvWnd: 30000, 1198 TCPOpts: opts[:offset], 1199 }) 1200 1201 // Receive the SYN-ACK reply. Make sure MSS and other expected options 1202 // are present. 1203 b := c.GetPacket() 1204 defer b.Release() 1205 tcp := header.TCP(header.IPv4(b.AsSlice()).Payload()) 1206 rcvdSynOptions := header.ParseSynOptions(tcp.Options(), true /* isAck */) 1207 c.IRS = seqnum.Value(tcp.SequenceNumber()) 1208 1209 tcpCheckers := []checker.TransportChecker{ 1210 checker.SrcPort(StackPort), 1211 checker.DstPort(TestPort), 1212 checker.TCPFlags(header.TCPFlagAck | header.TCPFlagSyn), 1213 checker.TCPAckNum(uint32(iss) + 1), 1214 checker.TCPSynOptions(header.TCPSynOptions{MSS: synOptions.MSS, WS: wndScale, SACKPermitted: synOptions.SACKPermitted && c.SACKEnabled()}), 1215 } 1216 1217 // If TS option was enabled in the original SYN then add a checker to 1218 // validate the Timestamp option in the SYN-ACK. 1219 if synOptions.TS { 1220 tcpCheckers = append(tcpCheckers, checker.TCPTimestampChecker(synOptions.TS, 0, synOptions.TSVal)) 1221 } else { 1222 tcpCheckers = append(tcpCheckers, checker.TCPTimestampChecker(false, 0, 0)) 1223 } 1224 1225 checker.IPv4(c.t, b, checker.TCP(tcpCheckers...)) 1226 rcvWnd := seqnum.Size(30000) 1227 ackHeaders := &Headers{ 1228 SrcPort: TestPort, 1229 DstPort: StackPort, 1230 Flags: header.TCPFlagAck, 1231 SeqNum: iss + 1, 1232 AckNum: c.IRS + 1, 1233 RcvWnd: rcvWnd, 1234 } 1235 1236 // If WS was expected to be in effect then scale the advertised window 1237 // correspondingly. 1238 if synOptions.WS > 0 { 1239 ackHeaders.RcvWnd = rcvWnd >> byte(synOptions.WS) 1240 } 1241 1242 parsedOpts := tcp.ParsedOptions() 1243 if synOptions.TS { 1244 // Echo the tsVal back to the peer in the tsEcr field of the 1245 // timestamp option. 1246 // Increment TSVal by 1 from the value sent in the SYN and echo 1247 // the TSVal in the SYN-ACK in the TSEcr field. 1248 opts := [12]byte{header.TCPOptionNOP, header.TCPOptionNOP} 1249 header.EncodeTSOption(synOptions.TSVal+1, parsedOpts.TSVal, opts[2:]) 1250 ackHeaders.TCPOpts = opts[:] 1251 } 1252 1253 // Send ACK, delay if needed. 1254 if delay > 0 { 1255 time.Sleep(delay) 1256 } 1257 c.SendPacket(nil, ackHeaders) 1258 1259 c.RcvdWindowScale = uint8(rcvdSynOptions.WS) 1260 c.Port = StackPort 1261 1262 return &RawEndpoint{ 1263 C: c, 1264 SrcPort: TestPort, 1265 DstPort: StackPort, 1266 Flags: header.TCPFlagPsh | header.TCPFlagAck, 1267 NextSeqNum: iss + 1, 1268 AckNum: c.IRS + 1, 1269 WndSize: rcvWnd, 1270 SACKPermitted: synOptions.SACKPermitted && c.SACKEnabled(), 1271 RecentTS: parsedOpts.TSVal, 1272 TSVal: synOptions.TSVal + 1, 1273 } 1274 } 1275 1276 // SACKEnabled returns true if the TCP Protocol option SACKEnabled is set to true 1277 // for the Stack in the context. 1278 func (c *Context) SACKEnabled() bool { 1279 var v tcpip.TCPSACKEnabled 1280 if err := c.Stack().TransportProtocolOption(tcp.ProtocolNumber, &v); err != nil { 1281 // Stack doesn't support SACK. So just return. 1282 return false 1283 } 1284 return bool(v) 1285 } 1286 1287 // SetGSOEnabled enables or disables generic segmentation offload. 1288 func (c *Context) SetGSOEnabled(enable bool) { 1289 if enable { 1290 c.linkEP.SupportedGSOKind = stack.HostGSOSupported 1291 } else { 1292 c.linkEP.SupportedGSOKind = stack.GSONotSupported 1293 } 1294 } 1295 1296 // MSSWithoutOptions returns the value for the MSS used by the stack when no 1297 // options are in use. 1298 func (c *Context) MSSWithoutOptions() uint16 { 1299 return uint16(c.linkEP.MTU() - header.IPv4MinimumSize - header.TCPMinimumSize) 1300 } 1301 1302 // MSSWithoutOptionsV6 returns the value for the MSS used by the stack when no 1303 // options are in use for IPv6 packets. 1304 func (c *Context) MSSWithoutOptionsV6() uint16 { 1305 return uint16(c.linkEP.MTU() - header.IPv6MinimumSize - header.TCPMinimumSize) 1306 }