github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/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  	"testing"
    22  	"time"
    23  
    24  	"github.com/google/netstack/tcpip"
    25  	"github.com/google/netstack/tcpip/buffer"
    26  	"github.com/google/netstack/tcpip/checker"
    27  	"github.com/google/netstack/tcpip/header"
    28  	"github.com/google/netstack/tcpip/link/channel"
    29  	"github.com/google/netstack/tcpip/link/sniffer"
    30  	"github.com/google/netstack/tcpip/network/ipv4"
    31  	"github.com/google/netstack/tcpip/network/ipv6"
    32  	"github.com/google/netstack/tcpip/seqnum"
    33  	"github.com/google/netstack/tcpip/stack"
    34  	"github.com/google/netstack/tcpip/transport/tcp"
    35  	"github.com/google/netstack/waiter"
    36  )
    37  
    38  const (
    39  	// StackAddr is the IPv4 address assigned to the stack.
    40  	StackAddr = "\x0a\x00\x00\x01"
    41  
    42  	// StackPort is used as the listening port in tests for passive
    43  	// connects.
    44  	StackPort = 1234
    45  
    46  	// TestAddr is the source address for packets sent to the stack via the
    47  	// link layer endpoint.
    48  	TestAddr = "\x0a\x00\x00\x02"
    49  
    50  	// TestPort is the TCP port used for packets sent to the stack
    51  	// via the link layer endpoint.
    52  	TestPort = 4096
    53  
    54  	// StackV6Addr is the IPv6 address assigned to the stack.
    55  	StackV6Addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
    56  
    57  	// TestV6Addr is the source address for packets sent to the stack via
    58  	// the link layer endpoint.
    59  	TestV6Addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
    60  
    61  	// StackV4MappedAddr is StackAddr as a mapped v6 address.
    62  	StackV4MappedAddr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" + StackAddr
    63  
    64  	// TestV4MappedAddr is TestAddr as a mapped v6 address.
    65  	TestV4MappedAddr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" + TestAddr
    66  
    67  	// V4MappedWildcardAddr is the mapped v6 representation of 0.0.0.0.
    68  	V4MappedWildcardAddr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00"
    69  
    70  	// testInitialSequenceNumber is the initial sequence number sent in packets that
    71  	// are sent in response to a SYN or in the initial SYN sent to the stack.
    72  	testInitialSequenceNumber = 789
    73  )
    74  
    75  // Headers is used to represent the TCP header fields when building a
    76  // new packet.
    77  type Headers struct {
    78  	// SrcPort holds the src port value to be used in the packet.
    79  	SrcPort uint16
    80  
    81  	// DstPort holds the destination port value to be used in the packet.
    82  	DstPort uint16
    83  
    84  	// SeqNum is the value of the sequence number field in the TCP header.
    85  	SeqNum seqnum.Value
    86  
    87  	// AckNum represents the acknowledgement number field in the TCP header.
    88  	AckNum seqnum.Value
    89  
    90  	// Flags are the TCP flags in the TCP header.
    91  	Flags int
    92  
    93  	// RcvWnd is the window to be advertised in the ReceiveWindow field of
    94  	// the TCP header.
    95  	RcvWnd seqnum.Size
    96  
    97  	// TCPOpts holds the options to be sent in the option field of the TCP
    98  	// header.
    99  	TCPOpts []byte
   100  }
   101  
   102  // Context provides an initialized Network stack and a link layer endpoint
   103  // for use in TCP tests.
   104  type Context struct {
   105  	t      *testing.T
   106  	linkEP *channel.Endpoint
   107  	s      *stack.Stack
   108  
   109  	// IRS holds the initial sequence number in the SYN sent by endpoint in
   110  	// case of an active connect or the sequence number sent by the endpoint
   111  	// in the SYN-ACK sent in response to a SYN when listening in passive
   112  	// mode.
   113  	IRS seqnum.Value
   114  
   115  	// Port holds the port bound by EP below in case of an active connect or
   116  	// the listening port number in case of a passive connect.
   117  	Port uint16
   118  
   119  	// EP is the test endpoint in the stack owned by this context. This endpoint
   120  	// is used in various tests to either initiate an active connect or is used
   121  	// as a passive listening endpoint to accept inbound connections.
   122  	EP tcpip.Endpoint
   123  
   124  	// Wq is the wait queue associated with EP and is used to block for events
   125  	// on EP.
   126  	WQ waiter.Queue
   127  
   128  	// TimeStampEnabled is true if ep is connected with the timestamp option
   129  	// enabled.
   130  	TimeStampEnabled bool
   131  
   132  	// WindowScale is the expected window scale in SYN packets sent by
   133  	// the stack.
   134  	WindowScale uint8
   135  }
   136  
   137  // New allocates and initializes a test context containing a new
   138  // stack and a link-layer endpoint.
   139  func New(t *testing.T, mtu uint32) *Context {
   140  	s := stack.New(stack.Options{
   141  		NetworkProtocols:   []stack.NetworkProtocol{ipv4.NewProtocol(), ipv6.NewProtocol()},
   142  		TransportProtocols: []stack.TransportProtocol{tcp.NewProtocol()},
   143  	})
   144  
   145  	// Allow minimum send/receive buffer sizes to be 1 during tests.
   146  	if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, tcp.SendBufferSizeOption{1, tcp.DefaultSendBufferSize, 10 * tcp.DefaultSendBufferSize}); err != nil {
   147  		t.Fatalf("SetTransportProtocolOption failed: %v", err)
   148  	}
   149  
   150  	if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, tcp.ReceiveBufferSizeOption{1, tcp.DefaultReceiveBufferSize, 10 * tcp.DefaultReceiveBufferSize}); err != nil {
   151  		t.Fatalf("SetTransportProtocolOption failed: %v", err)
   152  	}
   153  
   154  	// Some of the congestion control tests send up to 640 packets, we so
   155  	// set the channel size to 1000.
   156  	ep := channel.New(1000, mtu, "")
   157  	wep := stack.LinkEndpoint(ep)
   158  	if testing.Verbose() {
   159  		wep = sniffer.New(ep)
   160  	}
   161  	if err := s.CreateNamedNIC(1, "nic1", wep); err != nil {
   162  		t.Fatalf("CreateNIC failed: %v", err)
   163  	}
   164  	wep2 := stack.LinkEndpoint(channel.New(1000, mtu, ""))
   165  	if testing.Verbose() {
   166  		wep2 = sniffer.New(channel.New(1000, mtu, ""))
   167  	}
   168  	if err := s.CreateNamedNIC(2, "nic2", wep2); err != nil {
   169  		t.Fatalf("CreateNIC failed: %v", err)
   170  	}
   171  
   172  	if err := s.AddAddress(1, ipv4.ProtocolNumber, StackAddr); err != nil {
   173  		t.Fatalf("AddAddress failed: %v", err)
   174  	}
   175  
   176  	if err := s.AddAddress(1, ipv6.ProtocolNumber, StackV6Addr); err != nil {
   177  		t.Fatalf("AddAddress failed: %v", err)
   178  	}
   179  
   180  	s.SetRouteTable([]tcpip.Route{
   181  		{
   182  			Destination: header.IPv4EmptySubnet,
   183  			NIC:         1,
   184  		},
   185  		{
   186  			Destination: header.IPv6EmptySubnet,
   187  			NIC:         1,
   188  		},
   189  	})
   190  
   191  	return &Context{
   192  		t:           t,
   193  		s:           s,
   194  		linkEP:      ep,
   195  		WindowScale: uint8(tcp.FindWndScale(tcp.DefaultReceiveBufferSize)),
   196  	}
   197  }
   198  
   199  // Cleanup closes the context endpoint if required.
   200  func (c *Context) Cleanup() {
   201  	if c.EP != nil {
   202  		c.EP.Close()
   203  	}
   204  }
   205  
   206  // Stack returns a reference to the stack in the Context.
   207  func (c *Context) Stack() *stack.Stack {
   208  	return c.s
   209  }
   210  
   211  // CheckNoPacketTimeout verifies that no packet is received during the time
   212  // specified by wait.
   213  func (c *Context) CheckNoPacketTimeout(errMsg string, wait time.Duration) {
   214  	c.t.Helper()
   215  
   216  	select {
   217  	case <-c.linkEP.C:
   218  		c.t.Fatal(errMsg)
   219  
   220  	case <-time.After(wait):
   221  	}
   222  }
   223  
   224  // CheckNoPacket verifies that no packet is received for 1 second.
   225  func (c *Context) CheckNoPacket(errMsg string) {
   226  	c.CheckNoPacketTimeout(errMsg, 1*time.Second)
   227  }
   228  
   229  // GetPacket reads a packet from the link layer endpoint and verifies
   230  // that it is an IPv4 packet with the expected source and destination
   231  // addresses. It will fail with an error if no packet is received for
   232  // 2 seconds.
   233  func (c *Context) GetPacket() []byte {
   234  	select {
   235  	case p := <-c.linkEP.C:
   236  		if p.Proto != ipv4.ProtocolNumber {
   237  			c.t.Fatalf("Bad network protocol: got %v, wanted %v", p.Proto, ipv4.ProtocolNumber)
   238  		}
   239  
   240  		hdr := p.Pkt.Header.View()
   241  		b := append(hdr[:len(hdr):len(hdr)], p.Pkt.Data.ToView()...)
   242  
   243  		if p.GSO != nil && p.GSO.L3HdrLen != header.IPv4MinimumSize {
   244  			c.t.Errorf("L3HdrLen %v (expected %v)", p.GSO.L3HdrLen, header.IPv4MinimumSize)
   245  		}
   246  
   247  		checker.IPv4(c.t, b, checker.SrcAddr(StackAddr), checker.DstAddr(TestAddr))
   248  		return b
   249  
   250  	case <-time.After(2 * time.Second):
   251  		c.t.Fatalf("Packet wasn't written out")
   252  	}
   253  
   254  	return nil
   255  }
   256  
   257  // GetPacketNonBlocking reads a packet from the link layer endpoint
   258  // and verifies that it is an IPv4 packet with the expected source
   259  // and destination address. If no packet is available it will return
   260  // nil immediately.
   261  func (c *Context) GetPacketNonBlocking() []byte {
   262  	select {
   263  	case p := <-c.linkEP.C:
   264  		if p.Proto != ipv4.ProtocolNumber {
   265  			c.t.Fatalf("Bad network protocol: got %v, wanted %v", p.Proto, ipv4.ProtocolNumber)
   266  		}
   267  
   268  		hdr := p.Pkt.Header.View()
   269  		b := append(hdr[:len(hdr):len(hdr)], p.Pkt.Data.ToView()...)
   270  
   271  		checker.IPv4(c.t, b, checker.SrcAddr(StackAddr), checker.DstAddr(TestAddr))
   272  		return b
   273  	default:
   274  		return nil
   275  	}
   276  }
   277  
   278  // SendICMPPacket builds and sends an ICMPv4 packet via the link layer endpoint.
   279  func (c *Context) SendICMPPacket(typ header.ICMPv4Type, code uint8, p1, p2 []byte, maxTotalSize int) {
   280  	// Allocate a buffer data and headers.
   281  	buf := buffer.NewView(header.IPv4MinimumSize + header.ICMPv4PayloadOffset + len(p2))
   282  	if len(buf) > maxTotalSize {
   283  		buf = buf[:maxTotalSize]
   284  	}
   285  
   286  	ip := header.IPv4(buf)
   287  	ip.Encode(&header.IPv4Fields{
   288  		IHL:         header.IPv4MinimumSize,
   289  		TotalLength: uint16(len(buf)),
   290  		TTL:         65,
   291  		Protocol:    uint8(header.ICMPv4ProtocolNumber),
   292  		SrcAddr:     TestAddr,
   293  		DstAddr:     StackAddr,
   294  	})
   295  	ip.SetChecksum(^ip.CalculateChecksum())
   296  
   297  	icmp := header.ICMPv4(buf[header.IPv4MinimumSize:])
   298  	icmp.SetType(typ)
   299  	icmp.SetCode(code)
   300  	const icmpv4VariableHeaderOffset = 4
   301  	copy(icmp[icmpv4VariableHeaderOffset:], p1)
   302  	copy(icmp[header.ICMPv4PayloadOffset:], p2)
   303  
   304  	// Inject packet.
   305  	c.linkEP.InjectInbound(ipv4.ProtocolNumber, tcpip.PacketBuffer{
   306  		Data: buf.ToVectorisedView(),
   307  	})
   308  }
   309  
   310  // BuildSegment builds a TCP segment based on the given Headers and payload.
   311  func (c *Context) BuildSegment(payload []byte, h *Headers) buffer.VectorisedView {
   312  	return c.BuildSegmentWithAddrs(payload, h, TestAddr, StackAddr)
   313  }
   314  
   315  // BuildSegmentWithAddrs builds a TCP segment based on the given Headers,
   316  // payload and source and destination IPv4 addresses.
   317  func (c *Context) BuildSegmentWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) buffer.VectorisedView {
   318  	// Allocate a buffer for data and headers.
   319  	buf := buffer.NewView(header.TCPMinimumSize + header.IPv4MinimumSize + len(h.TCPOpts) + len(payload))
   320  	copy(buf[len(buf)-len(payload):], payload)
   321  	copy(buf[len(buf)-len(payload)-len(h.TCPOpts):], h.TCPOpts)
   322  
   323  	// Initialize the IP header.
   324  	ip := header.IPv4(buf)
   325  	ip.Encode(&header.IPv4Fields{
   326  		IHL:         header.IPv4MinimumSize,
   327  		TotalLength: uint16(len(buf)),
   328  		TTL:         65,
   329  		Protocol:    uint8(tcp.ProtocolNumber),
   330  		SrcAddr:     src,
   331  		DstAddr:     dst,
   332  	})
   333  	ip.SetChecksum(^ip.CalculateChecksum())
   334  
   335  	// Initialize the TCP header.
   336  	t := header.TCP(buf[header.IPv4MinimumSize:])
   337  	t.Encode(&header.TCPFields{
   338  		SrcPort:    h.SrcPort,
   339  		DstPort:    h.DstPort,
   340  		SeqNum:     uint32(h.SeqNum),
   341  		AckNum:     uint32(h.AckNum),
   342  		DataOffset: uint8(header.TCPMinimumSize + len(h.TCPOpts)),
   343  		Flags:      uint8(h.Flags),
   344  		WindowSize: uint16(h.RcvWnd),
   345  	})
   346  
   347  	// Calculate the TCP pseudo-header checksum.
   348  	xsum := header.PseudoHeaderChecksum(tcp.ProtocolNumber, src, dst, uint16(len(t)))
   349  
   350  	// Calculate the TCP checksum and set it.
   351  	xsum = header.Checksum(payload, xsum)
   352  	t.SetChecksum(^t.CalculateChecksum(xsum))
   353  
   354  	// Inject packet.
   355  	return buf.ToVectorisedView()
   356  }
   357  
   358  // SendSegment sends a TCP segment that has already been built and written to a
   359  // buffer.VectorisedView.
   360  func (c *Context) SendSegment(s buffer.VectorisedView) {
   361  	c.linkEP.InjectInbound(ipv4.ProtocolNumber, tcpip.PacketBuffer{
   362  		Data: s,
   363  	})
   364  }
   365  
   366  // SendPacket builds and sends a TCP segment(with the provided payload & TCP
   367  // headers) in an IPv4 packet via the link layer endpoint.
   368  func (c *Context) SendPacket(payload []byte, h *Headers) {
   369  	c.linkEP.InjectInbound(ipv4.ProtocolNumber, tcpip.PacketBuffer{
   370  		Data: c.BuildSegment(payload, h),
   371  	})
   372  }
   373  
   374  // SendPacketWithAddrs builds and sends a TCP segment(with the provided payload
   375  // & TCPheaders) in an IPv4 packet via the link layer endpoint using the
   376  // provided source and destination IPv4 addresses.
   377  func (c *Context) SendPacketWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) {
   378  	c.linkEP.InjectInbound(ipv4.ProtocolNumber, tcpip.PacketBuffer{
   379  		Data: c.BuildSegmentWithAddrs(payload, h, src, dst),
   380  	})
   381  }
   382  
   383  // SendAck sends an ACK packet.
   384  func (c *Context) SendAck(seq seqnum.Value, bytesReceived int) {
   385  	c.SendAckWithSACK(seq, bytesReceived, nil)
   386  }
   387  
   388  // SendAckWithSACK sends an ACK packet which includes the sackBlocks specified.
   389  func (c *Context) SendAckWithSACK(seq seqnum.Value, bytesReceived int, sackBlocks []header.SACKBlock) {
   390  	options := make([]byte, 40)
   391  	offset := 0
   392  	if len(sackBlocks) > 0 {
   393  		offset += header.EncodeNOP(options[offset:])
   394  		offset += header.EncodeNOP(options[offset:])
   395  		offset += header.EncodeSACKBlocks(sackBlocks, options[offset:])
   396  	}
   397  
   398  	c.SendPacket(nil, &Headers{
   399  		SrcPort: TestPort,
   400  		DstPort: c.Port,
   401  		Flags:   header.TCPFlagAck,
   402  		SeqNum:  seq,
   403  		AckNum:  c.IRS.Add(1 + seqnum.Size(bytesReceived)),
   404  		RcvWnd:  30000,
   405  		TCPOpts: options[:offset],
   406  	})
   407  }
   408  
   409  // ReceiveAndCheckPacket reads a packet from the link layer endpoint and
   410  // verifies that the packet packet payload of packet matches the slice
   411  // of data indicated by offset & size.
   412  func (c *Context) ReceiveAndCheckPacket(data []byte, offset, size int) {
   413  	c.ReceiveAndCheckPacketWithOptions(data, offset, size, 0)
   414  }
   415  
   416  // ReceiveAndCheckPacketWithOptions reads a packet from the link layer endpoint
   417  // and verifies that the packet packet payload of packet matches the slice of
   418  // data indicated by offset & size and skips optlen bytes in addition to the IP
   419  // TCP headers when comparing the data.
   420  func (c *Context) ReceiveAndCheckPacketWithOptions(data []byte, offset, size, optlen int) {
   421  	b := c.GetPacket()
   422  	checker.IPv4(c.t, b,
   423  		checker.PayloadLen(size+header.TCPMinimumSize+optlen),
   424  		checker.TCP(
   425  			checker.DstPort(TestPort),
   426  			checker.SeqNum(uint32(c.IRS.Add(seqnum.Size(1+offset)))),
   427  			checker.AckNum(uint32(seqnum.Value(testInitialSequenceNumber).Add(1))),
   428  			checker.TCPFlagsMatch(header.TCPFlagAck, ^uint8(header.TCPFlagPsh)),
   429  		),
   430  	)
   431  
   432  	pdata := data[offset:][:size]
   433  	if p := b[header.IPv4MinimumSize+header.TCPMinimumSize+optlen:]; bytes.Compare(pdata, p) != 0 {
   434  		c.t.Fatalf("Data is different: expected %v, got %v", pdata, p)
   435  	}
   436  }
   437  
   438  // ReceiveNonBlockingAndCheckPacket reads a packet from the link layer endpoint
   439  // and verifies that the packet packet payload of packet matches the slice of
   440  // data indicated by offset & size. It returns true if a packet was received and
   441  // processed.
   442  func (c *Context) ReceiveNonBlockingAndCheckPacket(data []byte, offset, size int) bool {
   443  	b := c.GetPacketNonBlocking()
   444  	if b == nil {
   445  		return false
   446  	}
   447  	checker.IPv4(c.t, b,
   448  		checker.PayloadLen(size+header.TCPMinimumSize),
   449  		checker.TCP(
   450  			checker.DstPort(TestPort),
   451  			checker.SeqNum(uint32(c.IRS.Add(seqnum.Size(1+offset)))),
   452  			checker.AckNum(uint32(seqnum.Value(testInitialSequenceNumber).Add(1))),
   453  			checker.TCPFlagsMatch(header.TCPFlagAck, ^uint8(header.TCPFlagPsh)),
   454  		),
   455  	)
   456  
   457  	pdata := data[offset:][:size]
   458  	if p := b[header.IPv4MinimumSize+header.TCPMinimumSize:]; bytes.Compare(pdata, p) != 0 {
   459  		c.t.Fatalf("Data is different: expected %v, got %v", pdata, p)
   460  	}
   461  	return true
   462  }
   463  
   464  // CreateV6Endpoint creates and initializes c.ep as a IPv6 Endpoint. If v6Only
   465  // is true then it sets the IP_V6ONLY option on the socket to make it a IPv6
   466  // only endpoint instead of a default dual stack socket.
   467  func (c *Context) CreateV6Endpoint(v6only bool) {
   468  	var err *tcpip.Error
   469  	c.EP, err = c.s.NewEndpoint(tcp.ProtocolNumber, ipv6.ProtocolNumber, &c.WQ)
   470  	if err != nil {
   471  		c.t.Fatalf("NewEndpoint failed: %v", err)
   472  	}
   473  
   474  	var v tcpip.V6OnlyOption
   475  	if v6only {
   476  		v = 1
   477  	}
   478  	if err := c.EP.SetSockOpt(v); err != nil {
   479  		c.t.Fatalf("SetSockOpt failed failed: %v", err)
   480  	}
   481  }
   482  
   483  // GetV6Packet reads a single packet from the link layer endpoint of the context
   484  // and asserts that it is an IPv6 Packet with the expected src/dest addresses.
   485  func (c *Context) GetV6Packet() []byte {
   486  	select {
   487  	case p := <-c.linkEP.C:
   488  		if p.Proto != ipv6.ProtocolNumber {
   489  			c.t.Fatalf("Bad network protocol: got %v, wanted %v", p.Proto, ipv6.ProtocolNumber)
   490  		}
   491  		b := make([]byte, p.Pkt.Header.UsedLength()+p.Pkt.Data.Size())
   492  		copy(b, p.Pkt.Header.View())
   493  		copy(b[p.Pkt.Header.UsedLength():], p.Pkt.Data.ToView())
   494  
   495  		checker.IPv6(c.t, b, checker.SrcAddr(StackV6Addr), checker.DstAddr(TestV6Addr))
   496  		return b
   497  
   498  	case <-time.After(2 * time.Second):
   499  		c.t.Fatalf("Packet wasn't written out")
   500  	}
   501  
   502  	return nil
   503  }
   504  
   505  // SendV6Packet builds and sends an IPv6 Packet via the link layer endpoint of
   506  // the context.
   507  func (c *Context) SendV6Packet(payload []byte, h *Headers) {
   508  	c.SendV6PacketWithAddrs(payload, h, TestV6Addr, StackV6Addr)
   509  }
   510  
   511  // SendV6PacketWithAddrs builds and sends an IPv6 Packet via the link layer
   512  // endpoint of the context using the provided source and destination IPv6
   513  // addresses.
   514  func (c *Context) SendV6PacketWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) {
   515  	// Allocate a buffer for data and headers.
   516  	buf := buffer.NewView(header.TCPMinimumSize + header.IPv6MinimumSize + len(payload))
   517  	copy(buf[len(buf)-len(payload):], payload)
   518  
   519  	// Initialize the IP header.
   520  	ip := header.IPv6(buf)
   521  	ip.Encode(&header.IPv6Fields{
   522  		PayloadLength: uint16(header.TCPMinimumSize + len(payload)),
   523  		NextHeader:    uint8(tcp.ProtocolNumber),
   524  		HopLimit:      65,
   525  		SrcAddr:       src,
   526  		DstAddr:       dst,
   527  	})
   528  
   529  	// Initialize the TCP header.
   530  	t := header.TCP(buf[header.IPv6MinimumSize:])
   531  	t.Encode(&header.TCPFields{
   532  		SrcPort:    h.SrcPort,
   533  		DstPort:    h.DstPort,
   534  		SeqNum:     uint32(h.SeqNum),
   535  		AckNum:     uint32(h.AckNum),
   536  		DataOffset: header.TCPMinimumSize,
   537  		Flags:      uint8(h.Flags),
   538  		WindowSize: uint16(h.RcvWnd),
   539  	})
   540  
   541  	// Calculate the TCP pseudo-header checksum.
   542  	xsum := header.PseudoHeaderChecksum(tcp.ProtocolNumber, src, dst, uint16(len(t)))
   543  
   544  	// Calculate the TCP checksum and set it.
   545  	xsum = header.Checksum(payload, xsum)
   546  	t.SetChecksum(^t.CalculateChecksum(xsum))
   547  
   548  	// Inject packet.
   549  	c.linkEP.InjectInbound(ipv6.ProtocolNumber, tcpip.PacketBuffer{
   550  		Data: buf.ToVectorisedView(),
   551  	})
   552  }
   553  
   554  // CreateConnected creates a connected TCP endpoint.
   555  func (c *Context) CreateConnected(iss seqnum.Value, rcvWnd seqnum.Size, epRcvBuf int) {
   556  	c.CreateConnectedWithRawOptions(iss, rcvWnd, epRcvBuf, nil)
   557  }
   558  
   559  // Connect performs the 3-way handshake for c.EP with the provided Initial
   560  // Sequence Number (iss) and receive window(rcvWnd) and any options if
   561  // specified.
   562  //
   563  // It also sets the receive buffer for the endpoint to the specified
   564  // value in epRcvBuf.
   565  //
   566  // PreCondition: c.EP must already be created.
   567  func (c *Context) Connect(iss seqnum.Value, rcvWnd seqnum.Size, options []byte) {
   568  	// Start connection attempt.
   569  	waitEntry, notifyCh := waiter.NewChannelEntry(nil)
   570  	c.WQ.EventRegister(&waitEntry, waiter.EventOut)
   571  	defer c.WQ.EventUnregister(&waitEntry)
   572  
   573  	if err := c.EP.Connect(tcpip.FullAddress{Addr: TestAddr, Port: TestPort}); err != tcpip.ErrConnectStarted {
   574  		c.t.Fatalf("Unexpected return value from Connect: %v", err)
   575  	}
   576  
   577  	// Receive SYN packet.
   578  	b := c.GetPacket()
   579  	checker.IPv4(c.t, b,
   580  		checker.TCP(
   581  			checker.DstPort(TestPort),
   582  			checker.TCPFlags(header.TCPFlagSyn),
   583  		),
   584  	)
   585  	if got, want := tcp.EndpointState(c.EP.State()), tcp.StateSynSent; got != want {
   586  		c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got)
   587  	}
   588  
   589  	tcpHdr := header.TCP(header.IPv4(b).Payload())
   590  	c.IRS = seqnum.Value(tcpHdr.SequenceNumber())
   591  
   592  	c.SendPacket(nil, &Headers{
   593  		SrcPort: tcpHdr.DestinationPort(),
   594  		DstPort: tcpHdr.SourcePort(),
   595  		Flags:   header.TCPFlagSyn | header.TCPFlagAck,
   596  		SeqNum:  iss,
   597  		AckNum:  c.IRS.Add(1),
   598  		RcvWnd:  rcvWnd,
   599  		TCPOpts: options,
   600  	})
   601  
   602  	// Receive ACK packet.
   603  	checker.IPv4(c.t, c.GetPacket(),
   604  		checker.TCP(
   605  			checker.DstPort(TestPort),
   606  			checker.TCPFlags(header.TCPFlagAck),
   607  			checker.SeqNum(uint32(c.IRS)+1),
   608  			checker.AckNum(uint32(iss)+1),
   609  		),
   610  	)
   611  
   612  	// Wait for connection to be established.
   613  	select {
   614  	case <-notifyCh:
   615  		if err := c.EP.GetSockOpt(tcpip.ErrorOption{}); err != nil {
   616  			c.t.Fatalf("Unexpected error when connecting: %v", err)
   617  		}
   618  	case <-time.After(1 * time.Second):
   619  		c.t.Fatalf("Timed out waiting for connection")
   620  	}
   621  	if got, want := tcp.EndpointState(c.EP.State()), tcp.StateEstablished; got != want {
   622  		c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got)
   623  	}
   624  
   625  	c.Port = tcpHdr.SourcePort()
   626  }
   627  
   628  // Create creates a TCP endpoint.
   629  func (c *Context) Create(epRcvBuf int) {
   630  	// Create TCP endpoint.
   631  	var err *tcpip.Error
   632  	c.EP, err = c.s.NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ)
   633  	if err != nil {
   634  		c.t.Fatalf("NewEndpoint failed: %v", err)
   635  	}
   636  
   637  	if epRcvBuf != -1 {
   638  		if err := c.EP.SetSockOptInt(tcpip.ReceiveBufferSizeOption, epRcvBuf); err != nil {
   639  			c.t.Fatalf("SetSockOpt failed failed: %v", err)
   640  		}
   641  	}
   642  }
   643  
   644  // CreateConnectedWithRawOptions creates a connected TCP endpoint and sends
   645  // the specified option bytes as the Option field in the initial SYN packet.
   646  //
   647  // It also sets the receive buffer for the endpoint to the specified
   648  // value in epRcvBuf.
   649  func (c *Context) CreateConnectedWithRawOptions(iss seqnum.Value, rcvWnd seqnum.Size, epRcvBuf int, options []byte) {
   650  	c.Create(epRcvBuf)
   651  	c.Connect(iss, rcvWnd, options)
   652  }
   653  
   654  // RawEndpoint is just a small wrapper around a TCP endpoint's state to make
   655  // sending data and ACK packets easy while being able to manipulate the sequence
   656  // numbers and timestamp values as needed.
   657  type RawEndpoint struct {
   658  	C          *Context
   659  	SrcPort    uint16
   660  	DstPort    uint16
   661  	Flags      int
   662  	NextSeqNum seqnum.Value
   663  	AckNum     seqnum.Value
   664  	WndSize    seqnum.Size
   665  	RecentTS   uint32 // Stores the latest timestamp to echo back.
   666  	TSVal      uint32 // TSVal stores the last timestamp sent by this endpoint.
   667  
   668  	// SackPermitted is true if SACKPermitted option was negotiated for this endpoint.
   669  	SACKPermitted bool
   670  }
   671  
   672  // SendPacketWithTS embeds the provided tsVal in the Timestamp option
   673  // for the packet to be sent out.
   674  func (r *RawEndpoint) SendPacketWithTS(payload []byte, tsVal uint32) {
   675  	r.TSVal = tsVal
   676  	tsOpt := [12]byte{header.TCPOptionNOP, header.TCPOptionNOP}
   677  	header.EncodeTSOption(r.TSVal, r.RecentTS, tsOpt[2:])
   678  	r.SendPacket(payload, tsOpt[:])
   679  }
   680  
   681  // SendPacket is a small wrapper function to build and send packets.
   682  func (r *RawEndpoint) SendPacket(payload []byte, opts []byte) {
   683  	packetHeaders := &Headers{
   684  		SrcPort: r.SrcPort,
   685  		DstPort: r.DstPort,
   686  		Flags:   r.Flags,
   687  		SeqNum:  r.NextSeqNum,
   688  		AckNum:  r.AckNum,
   689  		RcvWnd:  r.WndSize,
   690  		TCPOpts: opts,
   691  	}
   692  	r.C.SendPacket(payload, packetHeaders)
   693  	r.NextSeqNum = r.NextSeqNum.Add(seqnum.Size(len(payload)))
   694  }
   695  
   696  // VerifyACKWithTS verifies that the tsEcr field in the ack matches the provided
   697  // tsVal.
   698  func (r *RawEndpoint) VerifyACKWithTS(tsVal uint32) {
   699  	// Read ACK and verify that tsEcr of ACK packet is [1,2,3,4]
   700  	ackPacket := r.C.GetPacket()
   701  	checker.IPv4(r.C.t, ackPacket,
   702  		checker.TCP(
   703  			checker.DstPort(r.SrcPort),
   704  			checker.TCPFlags(header.TCPFlagAck),
   705  			checker.SeqNum(uint32(r.AckNum)),
   706  			checker.AckNum(uint32(r.NextSeqNum)),
   707  			checker.TCPTimestampChecker(true, 0, tsVal),
   708  		),
   709  	)
   710  	// Store the parsed TSVal from the ack as recentTS.
   711  	tcpSeg := header.TCP(header.IPv4(ackPacket).Payload())
   712  	opts := tcpSeg.ParsedOptions()
   713  	r.RecentTS = opts.TSVal
   714  }
   715  
   716  // VerifyACKRcvWnd verifies that the window advertised by the incoming ACK
   717  // matches the provided rcvWnd.
   718  func (r *RawEndpoint) VerifyACKRcvWnd(rcvWnd uint16) {
   719  	ackPacket := r.C.GetPacket()
   720  	checker.IPv4(r.C.t, ackPacket,
   721  		checker.TCP(
   722  			checker.DstPort(r.SrcPort),
   723  			checker.TCPFlags(header.TCPFlagAck),
   724  			checker.SeqNum(uint32(r.AckNum)),
   725  			checker.AckNum(uint32(r.NextSeqNum)),
   726  			checker.Window(rcvWnd),
   727  		),
   728  	)
   729  }
   730  
   731  // VerifyACKNoSACK verifies that the ACK does not contain a SACK block.
   732  func (r *RawEndpoint) VerifyACKNoSACK() {
   733  	r.VerifyACKHasSACK(nil)
   734  }
   735  
   736  // VerifyACKHasSACK verifies that the ACK contains the specified SACKBlocks.
   737  func (r *RawEndpoint) VerifyACKHasSACK(sackBlocks []header.SACKBlock) {
   738  	// Read ACK and verify that the TCP options in the segment do
   739  	// not contain a SACK block.
   740  	ackPacket := r.C.GetPacket()
   741  	checker.IPv4(r.C.t, ackPacket,
   742  		checker.TCP(
   743  			checker.DstPort(r.SrcPort),
   744  			checker.TCPFlags(header.TCPFlagAck),
   745  			checker.SeqNum(uint32(r.AckNum)),
   746  			checker.AckNum(uint32(r.NextSeqNum)),
   747  			checker.TCPSACKBlockChecker(sackBlocks),
   748  		),
   749  	)
   750  }
   751  
   752  // CreateConnectedWithOptions creates and connects c.ep with the specified TCP
   753  // options enabled and returns a RawEndpoint which represents the other end of
   754  // the connection.
   755  //
   756  // It also verifies where required(eg.Timestamp) that the ACK to the SYN-ACK
   757  // does not carry an option that was not requested.
   758  func (c *Context) CreateConnectedWithOptions(wantOptions header.TCPSynOptions) *RawEndpoint {
   759  	var err *tcpip.Error
   760  	c.EP, err = c.s.NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ)
   761  	if err != nil {
   762  		c.t.Fatalf("c.s.NewEndpoint(tcp, ipv4...) = %v", err)
   763  	}
   764  	if got, want := tcp.EndpointState(c.EP.State()), tcp.StateInitial; got != want {
   765  		c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got)
   766  	}
   767  
   768  	// Start connection attempt.
   769  	waitEntry, notifyCh := waiter.NewChannelEntry(nil)
   770  	c.WQ.EventRegister(&waitEntry, waiter.EventOut)
   771  	defer c.WQ.EventUnregister(&waitEntry)
   772  
   773  	testFullAddr := tcpip.FullAddress{Addr: TestAddr, Port: TestPort}
   774  	err = c.EP.Connect(testFullAddr)
   775  	if err != tcpip.ErrConnectStarted {
   776  		c.t.Fatalf("c.ep.Connect(%v) = %v", testFullAddr, err)
   777  	}
   778  	// Receive SYN packet.
   779  	b := c.GetPacket()
   780  	// Validate that the syn has the timestamp option and a valid
   781  	// TS value.
   782  	mss := uint16(c.linkEP.MTU() - header.IPv4MinimumSize - header.TCPMinimumSize)
   783  
   784  	checker.IPv4(c.t, b,
   785  		checker.TCP(
   786  			checker.DstPort(TestPort),
   787  			checker.TCPFlags(header.TCPFlagSyn),
   788  			checker.TCPSynOptions(header.TCPSynOptions{
   789  				MSS:           mss,
   790  				TS:            true,
   791  				WS:            int(c.WindowScale),
   792  				SACKPermitted: c.SACKEnabled(),
   793  			}),
   794  		),
   795  	)
   796  	if got, want := tcp.EndpointState(c.EP.State()), tcp.StateSynSent; got != want {
   797  		c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got)
   798  	}
   799  
   800  	tcpSeg := header.TCP(header.IPv4(b).Payload())
   801  	synOptions := header.ParseSynOptions(tcpSeg.Options(), false)
   802  
   803  	// Build options w/ tsVal to be sent in the SYN-ACK.
   804  	synAckOptions := make([]byte, header.TCPOptionsMaximumSize)
   805  	offset := 0
   806  	if wantOptions.WS != -1 {
   807  		offset += header.EncodeWSOption(wantOptions.WS, synAckOptions[offset:])
   808  	}
   809  	if wantOptions.TS {
   810  		offset += header.EncodeTSOption(wantOptions.TSVal, synOptions.TSVal, synAckOptions[offset:])
   811  	}
   812  	if wantOptions.SACKPermitted {
   813  		offset += header.EncodeSACKPermittedOption(synAckOptions[offset:])
   814  	}
   815  
   816  	offset += header.AddTCPOptionPadding(synAckOptions, offset)
   817  
   818  	// Build SYN-ACK.
   819  	c.IRS = seqnum.Value(tcpSeg.SequenceNumber())
   820  	iss := seqnum.Value(testInitialSequenceNumber)
   821  	c.SendPacket(nil, &Headers{
   822  		SrcPort: tcpSeg.DestinationPort(),
   823  		DstPort: tcpSeg.SourcePort(),
   824  		Flags:   header.TCPFlagSyn | header.TCPFlagAck,
   825  		SeqNum:  iss,
   826  		AckNum:  c.IRS.Add(1),
   827  		RcvWnd:  30000,
   828  		TCPOpts: synAckOptions[:offset],
   829  	})
   830  
   831  	// Read ACK.
   832  	ackPacket := c.GetPacket()
   833  
   834  	// Verify TCP header fields.
   835  	tcpCheckers := []checker.TransportChecker{
   836  		checker.DstPort(TestPort),
   837  		checker.TCPFlags(header.TCPFlagAck),
   838  		checker.SeqNum(uint32(c.IRS) + 1),
   839  		checker.AckNum(uint32(iss) + 1),
   840  	}
   841  
   842  	// Verify that tsEcr of ACK packet is wantOptions.TSVal if the
   843  	// timestamp option was enabled, if not then we verify that
   844  	// there is no timestamp in the ACK packet.
   845  	if wantOptions.TS {
   846  		tcpCheckers = append(tcpCheckers, checker.TCPTimestampChecker(true, 0, wantOptions.TSVal))
   847  	} else {
   848  		tcpCheckers = append(tcpCheckers, checker.TCPTimestampChecker(false, 0, 0))
   849  	}
   850  
   851  	checker.IPv4(c.t, ackPacket, checker.TCP(tcpCheckers...))
   852  
   853  	ackSeg := header.TCP(header.IPv4(ackPacket).Payload())
   854  	ackOptions := ackSeg.ParsedOptions()
   855  
   856  	// Wait for connection to be established.
   857  	select {
   858  	case <-notifyCh:
   859  		err = c.EP.GetSockOpt(tcpip.ErrorOption{})
   860  		if err != nil {
   861  			c.t.Fatalf("Unexpected error when connecting: %v", err)
   862  		}
   863  	case <-time.After(1 * time.Second):
   864  		c.t.Fatalf("Timed out waiting for connection")
   865  	}
   866  	if got, want := tcp.EndpointState(c.EP.State()), tcp.StateEstablished; got != want {
   867  		c.t.Fatalf("Unexpected endpoint state: want %v, got %v", want, got)
   868  	}
   869  
   870  	// Store the source port in use by the endpoint.
   871  	c.Port = tcpSeg.SourcePort()
   872  
   873  	// Mark in context that timestamp option is enabled for this endpoint.
   874  	c.TimeStampEnabled = true
   875  
   876  	return &RawEndpoint{
   877  		C:             c,
   878  		SrcPort:       tcpSeg.DestinationPort(),
   879  		DstPort:       tcpSeg.SourcePort(),
   880  		Flags:         header.TCPFlagAck | header.TCPFlagPsh,
   881  		NextSeqNum:    iss + 1,
   882  		AckNum:        c.IRS.Add(1),
   883  		WndSize:       30000,
   884  		RecentTS:      ackOptions.TSVal,
   885  		TSVal:         wantOptions.TSVal,
   886  		SACKPermitted: wantOptions.SACKPermitted,
   887  	}
   888  }
   889  
   890  // AcceptWithOptions initializes a listening endpoint and connects to it with the
   891  // provided options enabled. It also verifies that the SYN-ACK has the expected
   892  // values for the provided options.
   893  //
   894  // The function returns a RawEndpoint representing the other end of the accepted
   895  // endpoint.
   896  func (c *Context) AcceptWithOptions(wndScale int, synOptions header.TCPSynOptions) *RawEndpoint {
   897  	// Create EP and start listening.
   898  	wq := &waiter.Queue{}
   899  	ep, err := c.s.NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, wq)
   900  	if err != nil {
   901  		c.t.Fatalf("NewEndpoint failed: %v", err)
   902  	}
   903  	defer ep.Close()
   904  
   905  	if err := ep.Bind(tcpip.FullAddress{Port: StackPort}); err != nil {
   906  		c.t.Fatalf("Bind failed: %v", err)
   907  	}
   908  	if got, want := tcp.EndpointState(ep.State()), tcp.StateBound; got != want {
   909  		c.t.Errorf("Unexpected endpoint state: want %v, got %v", want, got)
   910  	}
   911  
   912  	if err := ep.Listen(10); err != nil {
   913  		c.t.Fatalf("Listen failed: %v", err)
   914  	}
   915  	if got, want := tcp.EndpointState(ep.State()), tcp.StateListen; got != want {
   916  		c.t.Errorf("Unexpected endpoint state: want %v, got %v", want, got)
   917  	}
   918  
   919  	rep := c.PassiveConnectWithOptions(100, wndScale, synOptions)
   920  
   921  	// Try to accept the connection.
   922  	we, ch := waiter.NewChannelEntry(nil)
   923  	wq.EventRegister(&we, waiter.EventIn)
   924  	defer wq.EventUnregister(&we)
   925  
   926  	c.EP, _, err = ep.Accept()
   927  	if err == tcpip.ErrWouldBlock {
   928  		// Wait for connection to be established.
   929  		select {
   930  		case <-ch:
   931  			c.EP, _, err = ep.Accept()
   932  			if err != nil {
   933  				c.t.Fatalf("Accept failed: %v", err)
   934  			}
   935  
   936  		case <-time.After(1 * time.Second):
   937  			c.t.Fatalf("Timed out waiting for accept")
   938  		}
   939  	}
   940  	if got, want := tcp.EndpointState(c.EP.State()), tcp.StateEstablished; got != want {
   941  		c.t.Errorf("Unexpected endpoint state: want %v, got %v", want, got)
   942  	}
   943  
   944  	return rep
   945  }
   946  
   947  // PassiveConnect just disables WindowScaling and delegates the call to
   948  // PassiveConnectWithOptions.
   949  func (c *Context) PassiveConnect(maxPayload, wndScale int, synOptions header.TCPSynOptions) {
   950  	synOptions.WS = -1
   951  	c.PassiveConnectWithOptions(maxPayload, wndScale, synOptions)
   952  }
   953  
   954  // PassiveConnectWithOptions initiates a new connection (with the specified TCP
   955  // options enabled) to the port on which the Context.ep is listening for new
   956  // connections. It also validates that the SYN-ACK has the expected values for
   957  // the enabled options.
   958  //
   959  // NOTE: MSS is not a negotiated option and it can be asymmetric
   960  // in each direction. This function uses the maxPayload to set the MSS to be
   961  // sent to the peer on a connect and validates that the MSS in the SYN-ACK
   962  // response is equal to the MTU - (tcphdr len + iphdr len).
   963  //
   964  // wndScale is the expected window scale in the SYN-ACK and synOptions.WS is the
   965  // value of the window scaling option to be sent in the SYN. If synOptions.WS >
   966  // 0 then we send the WindowScale option.
   967  func (c *Context) PassiveConnectWithOptions(maxPayload, wndScale int, synOptions header.TCPSynOptions) *RawEndpoint {
   968  	opts := make([]byte, header.TCPOptionsMaximumSize)
   969  	offset := 0
   970  	offset += header.EncodeMSSOption(uint32(maxPayload), opts)
   971  
   972  	if synOptions.WS >= 0 {
   973  		offset += header.EncodeWSOption(3, opts[offset:])
   974  	}
   975  	if synOptions.TS {
   976  		offset += header.EncodeTSOption(synOptions.TSVal, synOptions.TSEcr, opts[offset:])
   977  	}
   978  
   979  	if synOptions.SACKPermitted {
   980  		offset += header.EncodeSACKPermittedOption(opts[offset:])
   981  	}
   982  
   983  	paddingToAdd := 4 - offset%4
   984  	// Now add any padding bytes that might be required to quad align the
   985  	// options.
   986  	for i := offset; i < offset+paddingToAdd; i++ {
   987  		opts[i] = header.TCPOptionNOP
   988  	}
   989  	offset += paddingToAdd
   990  
   991  	// Send a SYN request.
   992  	iss := seqnum.Value(testInitialSequenceNumber)
   993  	c.SendPacket(nil, &Headers{
   994  		SrcPort: TestPort,
   995  		DstPort: StackPort,
   996  		Flags:   header.TCPFlagSyn,
   997  		SeqNum:  iss,
   998  		RcvWnd:  30000,
   999  		TCPOpts: opts[:offset],
  1000  	})
  1001  
  1002  	// Receive the SYN-ACK reply. Make sure MSS and other expected options
  1003  	// are present.
  1004  	b := c.GetPacket()
  1005  	tcp := header.TCP(header.IPv4(b).Payload())
  1006  	c.IRS = seqnum.Value(tcp.SequenceNumber())
  1007  
  1008  	tcpCheckers := []checker.TransportChecker{
  1009  		checker.SrcPort(StackPort),
  1010  		checker.DstPort(TestPort),
  1011  		checker.TCPFlags(header.TCPFlagAck | header.TCPFlagSyn),
  1012  		checker.AckNum(uint32(iss) + 1),
  1013  		checker.TCPSynOptions(header.TCPSynOptions{MSS: synOptions.MSS, WS: wndScale, SACKPermitted: synOptions.SACKPermitted && c.SACKEnabled()}),
  1014  	}
  1015  
  1016  	// If TS option was enabled in the original SYN then add a checker to
  1017  	// validate the Timestamp option in the SYN-ACK.
  1018  	if synOptions.TS {
  1019  		tcpCheckers = append(tcpCheckers, checker.TCPTimestampChecker(synOptions.TS, 0, synOptions.TSVal))
  1020  	} else {
  1021  		tcpCheckers = append(tcpCheckers, checker.TCPTimestampChecker(false, 0, 0))
  1022  	}
  1023  
  1024  	checker.IPv4(c.t, b, checker.TCP(tcpCheckers...))
  1025  	rcvWnd := seqnum.Size(30000)
  1026  	ackHeaders := &Headers{
  1027  		SrcPort: TestPort,
  1028  		DstPort: StackPort,
  1029  		Flags:   header.TCPFlagAck,
  1030  		SeqNum:  iss + 1,
  1031  		AckNum:  c.IRS + 1,
  1032  		RcvWnd:  rcvWnd,
  1033  	}
  1034  
  1035  	// If WS was expected to be in effect then scale the advertised window
  1036  	// correspondingly.
  1037  	if synOptions.WS > 0 {
  1038  		ackHeaders.RcvWnd = rcvWnd >> byte(synOptions.WS)
  1039  	}
  1040  
  1041  	parsedOpts := tcp.ParsedOptions()
  1042  	if synOptions.TS {
  1043  		// Echo the tsVal back to the peer in the tsEcr field of the
  1044  		// timestamp option.
  1045  		// Increment TSVal by 1 from the value sent in the SYN and echo
  1046  		// the TSVal in the SYN-ACK in the TSEcr field.
  1047  		opts := [12]byte{header.TCPOptionNOP, header.TCPOptionNOP}
  1048  		header.EncodeTSOption(synOptions.TSVal+1, parsedOpts.TSVal, opts[2:])
  1049  		ackHeaders.TCPOpts = opts[:]
  1050  	}
  1051  
  1052  	// Send ACK.
  1053  	c.SendPacket(nil, ackHeaders)
  1054  
  1055  	c.Port = StackPort
  1056  
  1057  	return &RawEndpoint{
  1058  		C:             c,
  1059  		SrcPort:       TestPort,
  1060  		DstPort:       StackPort,
  1061  		Flags:         header.TCPFlagPsh | header.TCPFlagAck,
  1062  		NextSeqNum:    iss + 1,
  1063  		AckNum:        c.IRS + 1,
  1064  		WndSize:       rcvWnd,
  1065  		SACKPermitted: synOptions.SACKPermitted && c.SACKEnabled(),
  1066  		RecentTS:      parsedOpts.TSVal,
  1067  		TSVal:         synOptions.TSVal + 1,
  1068  	}
  1069  }
  1070  
  1071  // SACKEnabled returns true if the TCP Protocol option SACKEnabled is set to true
  1072  // for the Stack in the context.
  1073  func (c *Context) SACKEnabled() bool {
  1074  	var v tcp.SACKEnabled
  1075  	if err := c.Stack().TransportProtocolOption(tcp.ProtocolNumber, &v); err != nil {
  1076  		// Stack doesn't support SACK. So just return.
  1077  		return false
  1078  	}
  1079  	return bool(v)
  1080  }
  1081  
  1082  // SetGSOEnabled enables or disables generic segmentation offload.
  1083  func (c *Context) SetGSOEnabled(enable bool) {
  1084  	c.linkEP.GSO = enable
  1085  }
  1086  
  1087  // MSSWithoutOptions returns the value for the MSS used by the stack when no
  1088  // options are in use.
  1089  func (c *Context) MSSWithoutOptions() uint16 {
  1090  	return uint16(c.linkEP.MTU() - header.IPv4MinimumSize - header.TCPMinimumSize)
  1091  }