diff options
author | gVisor bot <gvisor-bot@google.com> | 2020-04-07 17:48:06 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-04-07 17:49:21 -0700 |
commit | dbcc59af0b834b6295589a594fe4cc1c360e66f7 (patch) | |
tree | ea5e48327004da2f371a86a0c0333e6eda9acb3d /test/packetimpact/testbench/connections.go | |
parent | acf0259255bae190759e39fbff3bac6c94122734 (diff) |
Test TCP sender behavior against window shrinking
RFC 1122 Section 3.7: A sending TCP MUST be robust against window shrinking,
which may cause the "useable window" to become negative.
PiperOrigin-RevId: 305377072
Diffstat (limited to 'test/packetimpact/testbench/connections.go')
-rw-r--r-- | test/packetimpact/testbench/connections.go | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/test/packetimpact/testbench/connections.go b/test/packetimpact/testbench/connections.go index 8d1f562ee..579da59c3 100644 --- a/test/packetimpact/testbench/connections.go +++ b/test/packetimpact/testbench/connections.go @@ -187,9 +187,19 @@ func (conn *TCPIPv4) Send(tcp TCP, additionalLayers ...Layer) { conn.SendFrame(conn.CreateFrame(tcp, additionalLayers...)) } -// Recv gets a packet from the sniffer within the timeout provided. If no packet -// arrives before the timeout, it returns nil. +// Recv gets a packet from the sniffer within the timeout provided. +// If no packet arrives before the timeout, it returns nil. func (conn *TCPIPv4) Recv(timeout time.Duration) *TCP { + layers := conn.RecvFrame(timeout) + if tcpLayerIndex < len(layers) { + return layers[tcpLayerIndex].(*TCP) + } + return nil +} + +// RecvFrame gets a frame (of type Layers) within the timeout provided. +// If no frame arrives before the timeout, it returns nil. +func (conn *TCPIPv4) RecvFrame(timeout time.Duration) Layers { deadline := time.Now().Add(timeout) for { timeout = time.Until(deadline) @@ -216,14 +226,16 @@ func (conn *TCPIPv4) Recv(timeout time.Duration) *TCP { for i := tcpLayerIndex + 1; i < len(layers); i++ { conn.RemoteSeqNum.UpdateForward(seqnum.Size(layers[i].length())) } - return tcpHeader + return layers } return nil } // Expect a packet that matches the provided tcp within the timeout specified. -// If it doesn't arrive in time, the test fails. +// If it doesn't arrive in time, it returns nil. func (conn *TCPIPv4) Expect(tcp TCP, timeout time.Duration) *TCP { + // We cannot implement this directly using ExpectFrame as we cannot specify + // the Payload part. deadline := time.Now().Add(timeout) for { timeout = time.Until(deadline) @@ -231,15 +243,41 @@ func (conn *TCPIPv4) Expect(tcp TCP, timeout time.Duration) *TCP { return nil } gotTCP := conn.Recv(timeout) - if gotTCP == nil { - return nil - } if tcp.match(gotTCP) { return gotTCP } } } +// ExpectFrame expects a frame that matches the specified layers within the +// timeout specified. If it doesn't arrive in time, it returns nil. +func (conn *TCPIPv4) ExpectFrame(layers Layers, timeout time.Duration) Layers { + deadline := time.Now().Add(timeout) + for { + timeout = time.Until(deadline) + if timeout <= 0 { + return nil + } + gotLayers := conn.RecvFrame(timeout) + if layers.match(gotLayers) { + return gotLayers + } + } +} + +// ExpectData is a convenient method that expects a TCP packet along with +// the payload to arrive within the timeout specified. If it doesn't arrive +// in time, it causes a fatal test failure. +func (conn *TCPIPv4) ExpectData(tcp TCP, data []byte, timeout time.Duration) { + expected := []Layer{&Ether{}, &IPv4{}, &tcp} + if len(data) > 0 { + expected = append(expected, &Payload{Bytes: data}) + } + if conn.ExpectFrame(expected, timeout) == nil { + conn.t.Fatalf("expected to get a TCP frame %s with payload %x", &tcp, data) + } +} + // Handshake performs a TCP 3-way handshake. func (conn *TCPIPv4) Handshake() { // Send the SYN. |