summaryrefslogtreecommitdiffhomepage
path: root/test/packetimpact
diff options
context:
space:
mode:
authorBhasker Hariharan <bhaskerh@google.com>2020-05-08 15:38:42 -0700
committergVisor bot <gvisor-bot@google.com>2020-05-08 15:40:27 -0700
commite4d2d21f6b1b93146378ed5edc0c55d2ae4fb3af (patch)
tree5aade9f9682f663d4e55394325fc9859d723cc5d /test/packetimpact
parent21b71395a6aa2eafbc4c59222574d56c2db2e23b (diff)
Add UDP send/recv packetimpact tests.
Fixes #2654 PiperOrigin-RevId: 310642216
Diffstat (limited to 'test/packetimpact')
-rw-r--r--test/packetimpact/testbench/connections.go13
-rw-r--r--test/packetimpact/testbench/layers.go5
-rw-r--r--test/packetimpact/testbench/rawsockets.go2
-rw-r--r--test/packetimpact/tests/BUILD9
-rw-r--r--test/packetimpact/tests/udp_send_recv_dgram_test.go96
5 files changed, 120 insertions, 5 deletions
diff --git a/test/packetimpact/testbench/connections.go b/test/packetimpact/testbench/connections.go
index 56ac3fa54..28c841612 100644
--- a/test/packetimpact/testbench/connections.go
+++ b/test/packetimpact/testbench/connections.go
@@ -841,6 +841,7 @@ func (conn *UDPIPv4) SendIP(additionalLayers ...Layer) {
// Expect expects a frame with the UDP layer matching the provided UDP within
// the timeout specified. If it doesn't arrive in time, an error is returned.
func (conn *UDPIPv4) Expect(udp UDP, timeout time.Duration) (*UDP, error) {
+ conn.t.Helper()
layer, err := (*Connection)(conn).Expect(&udp, timeout)
if layer == nil {
return nil, err
@@ -852,6 +853,18 @@ func (conn *UDPIPv4) Expect(udp UDP, timeout time.Duration) (*UDP, error) {
return gotUDP, err
}
+// ExpectData is a convenient method that expects a Layer and the Layer after
+// it. If it doens't arrive in time, it returns nil.
+func (conn *UDPIPv4) ExpectData(udp UDP, payload Payload, timeout time.Duration) (Layers, error) {
+ conn.t.Helper()
+ expected := make([]Layer, len(conn.layerStates))
+ expected[len(expected)-1] = &udp
+ if payload.length() != 0 {
+ expected = append(expected, &payload)
+ }
+ return (*Connection)(conn).ExpectFrame(expected, timeout)
+}
+
// Close frees associated resources held by the UDPIPv4 connection.
func (conn *UDPIPv4) Close() {
(*Connection)(conn).Close()
diff --git a/test/packetimpact/testbench/layers.go b/test/packetimpact/testbench/layers.go
index 165f62d3b..49370377d 100644
--- a/test/packetimpact/testbench/layers.go
+++ b/test/packetimpact/testbench/layers.go
@@ -898,10 +898,7 @@ func (l *UDP) match(other Layer) bool {
}
func (l *UDP) length() int {
- if l.Length == nil {
- return header.UDPMinimumSize
- }
- return int(*l.Length)
+ return header.UDPMinimumSize
}
// merge implements Layer.merge.
diff --git a/test/packetimpact/testbench/rawsockets.go b/test/packetimpact/testbench/rawsockets.go
index ff722d4a6..a9ad72b63 100644
--- a/test/packetimpact/testbench/rawsockets.go
+++ b/test/packetimpact/testbench/rawsockets.go
@@ -169,7 +169,7 @@ func NewInjector(t *testing.T) (Injector, error) {
// Send a raw frame.
func (i *Injector) Send(b []byte) {
if _, err := unix.Write(i.fd, b); err != nil {
- i.t.Fatalf("can't write: %s", err)
+ i.t.Fatalf("can't write: %s of len %d", err, len(b))
}
}
diff --git a/test/packetimpact/tests/BUILD b/test/packetimpact/tests/BUILD
index 563823d04..c25b3b8c1 100644
--- a/test/packetimpact/tests/BUILD
+++ b/test/packetimpact/tests/BUILD
@@ -148,6 +148,15 @@ packetimpact_go_test(
],
)
+packetimpact_go_test(
+ name = "udp_send_recv_dgram",
+ srcs = ["udp_send_recv_dgram_test.go"],
+ deps = [
+ "//test/packetimpact/testbench",
+ "@org_golang_x_sys//unix:go_default_library",
+ ],
+)
+
sh_binary(
name = "test_runner",
srcs = ["test_runner.sh"],
diff --git a/test/packetimpact/tests/udp_send_recv_dgram_test.go b/test/packetimpact/tests/udp_send_recv_dgram_test.go
new file mode 100644
index 000000000..1c682831c
--- /dev/null
+++ b/test/packetimpact/tests/udp_send_recv_dgram_test.go
@@ -0,0 +1,96 @@
+// Copyright 2020 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package udp_send_recv_dgram_test
+
+import (
+ "math/rand"
+ "net"
+ "testing"
+ "time"
+
+ "golang.org/x/sys/unix"
+ tb "gvisor.dev/gvisor/test/packetimpact/testbench"
+)
+
+func generateRandomPayload(t *testing.T, n int) string {
+ t.Helper()
+ buf := make([]byte, n)
+ if _, err := rand.Read(buf); err != nil {
+ t.Fatalf("rand.Read(buf) failed: %s", err)
+ }
+ return string(buf)
+}
+
+func TestUDPRecv(t *testing.T) {
+ dut := tb.NewDUT(t)
+ defer dut.TearDown()
+ boundFD, remotePort := dut.CreateBoundSocket(unix.SOCK_DGRAM, unix.IPPROTO_UDP, net.ParseIP("0.0.0.0"))
+ defer dut.Close(boundFD)
+ conn := tb.NewUDPIPv4(t, tb.UDP{DstPort: &remotePort}, tb.UDP{SrcPort: &remotePort})
+ defer conn.Close()
+
+ testCases := []struct {
+ name string
+ payload string
+ }{
+ {"emptypayload", ""},
+ {"small payload", "hello world"},
+ {"1kPayload", generateRandomPayload(t, 1<<10)},
+ // Even though UDP allows larger dgrams we don't test it here as
+ // they need to be fragmented and written out as individual
+ // frames.
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ frame := conn.CreateFrame(&tb.UDP{}, &tb.Payload{Bytes: []byte(tc.payload)})
+ conn.SendFrame(frame)
+ if got, want := string(dut.Recv(boundFD, int32(len(tc.payload)), 0)), tc.payload; got != want {
+ t.Fatalf("received payload does not match sent payload got: %s, want: %s", got, want)
+ }
+ })
+ }
+}
+
+func TestUDPSend(t *testing.T) {
+ dut := tb.NewDUT(t)
+ defer dut.TearDown()
+ boundFD, remotePort := dut.CreateBoundSocket(unix.SOCK_DGRAM, unix.IPPROTO_UDP, net.ParseIP("0.0.0.0"))
+ defer dut.Close(boundFD)
+ conn := tb.NewUDPIPv4(t, tb.UDP{DstPort: &remotePort}, tb.UDP{SrcPort: &remotePort})
+ defer conn.Close()
+
+ testCases := []struct {
+ name string
+ payload string
+ }{
+ {"emptypayload", ""},
+ {"small payload", "hello world"},
+ {"1kPayload", generateRandomPayload(t, 1<<10)},
+ // Even though UDP allows larger dgrams we don't test it here as
+ // they need to be fragmented and written out as individual
+ // frames.
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ conn.Drain()
+ if got, want := int(dut.SendTo(boundFD, []byte(tc.payload), 0, conn.LocalAddr())), len(tc.payload); got != want {
+ t.Fatalf("short write got: %d, want: %d", got, want)
+ }
+ if _, err := conn.ExpectData(tb.UDP{SrcPort: &remotePort}, tb.Payload{Bytes: []byte(tc.payload)}, 1*time.Second); err != nil {
+ t.Fatal(err)
+ }
+ })
+ }
+}