summaryrefslogtreecommitdiffhomepage
path: root/test/packetimpact/testbench
diff options
context:
space:
mode:
authorZeling Feng <zeling@google.com>2020-11-24 13:39:39 -0800
committergVisor bot <gvisor-bot@google.com>2020-11-24 13:42:07 -0800
commitd492b21319676bc9a9f97b9633b3be387c0b60a5 (patch)
tree77d26b346ed6071add162c11ee852137845227ed /test/packetimpact/testbench
parent732e98985546958fdab8ae3d49e36f17ae89f71c (diff)
Fix a potential indefinite blocking in packetimpact testbench
1. setsockopt(SO_RCVTIMEO, 0) == never timeout 2. float64(time.Microsecond/time.Second) == 0 3. packetimpact tests use a lot of 1s timeouts This becomes a more significant problem because of a recent change that binds the sniffer only on the specific testNet interface so now the traffic on the ctrlNet cannot wake up the blocking call anymore. PiperOrigin-RevId: 344123465
Diffstat (limited to 'test/packetimpact/testbench')
-rw-r--r--test/packetimpact/testbench/rawsockets.go11
1 files changed, 8 insertions, 3 deletions
diff --git a/test/packetimpact/testbench/rawsockets.go b/test/packetimpact/testbench/rawsockets.go
index fd8015ce2..1ac96626a 100644
--- a/test/packetimpact/testbench/rawsockets.go
+++ b/test/packetimpact/testbench/rawsockets.go
@@ -74,7 +74,8 @@ func (n *DUTTestNet) NewSniffer(t *testing.T) (Sniffer, error) {
// packet too large for the buffer arrives, the test will get a fatal error.
const maxReadSize int = 65536
-// Recv tries to read one frame until the timeout is up.
+// Recv tries to read one frame until the timeout is up. If the timeout given
+// is 0, then no read attempt will be made.
func (s *Sniffer) Recv(t *testing.T, timeout time.Duration) []byte {
t.Helper()
@@ -87,9 +88,13 @@ func (s *Sniffer) Recv(t *testing.T, timeout time.Duration) []byte {
whole, frac := math.Modf(timeout.Seconds())
tv := unix.Timeval{
Sec: int64(whole),
- Usec: int64(frac * float64(time.Microsecond/time.Second)),
+ Usec: int64(frac * float64(time.Second/time.Microsecond)),
+ }
+ // The following should never happen, but having this guard here is better
+ // than blocking indefinitely in the future.
+ if tv.Sec == 0 && tv.Usec == 0 {
+ t.Fatal("setting SO_RCVTIMEO to 0 means blocking indefinitely")
}
-
if err := unix.SetsockoptTimeval(s.fd, unix.SOL_SOCKET, unix.SO_RCVTIMEO, &tv); err != nil {
t.Fatalf("can't setsockopt SO_RCVTIMEO: %s", err)
}