summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/stack/neighbor_entry.go
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2020-11-03 03:24:20 +0000
committergVisor bot <gvisor-bot@google.com>2020-11-03 03:24:20 +0000
commitae4df8d6c4f447bc68f7c578282ad5dc03d3b6a1 (patch)
tree4576416688a733121d90ac726c3f1c4cb6971fbc /pkg/tcpip/stack/neighbor_entry.go
parentf75db1230a6cc509259917da3271ea84b4b1a3ec (diff)
parentc22067d3d4452ac6b65bd56daf796ffeca09e65c (diff)
Merge release-20201027.0-54-gc22067d3d (automated)
Diffstat (limited to 'pkg/tcpip/stack/neighbor_entry.go')
-rw-r--r--pkg/tcpip/stack/neighbor_entry.go21
1 files changed, 19 insertions, 2 deletions
diff --git a/pkg/tcpip/stack/neighbor_entry.go b/pkg/tcpip/stack/neighbor_entry.go
index aec77610d..493e48031 100644
--- a/pkg/tcpip/stack/neighbor_entry.go
+++ b/pkg/tcpip/stack/neighbor_entry.go
@@ -17,12 +17,19 @@ package stack
import (
"fmt"
"sync"
+ "time"
"gvisor.dev/gvisor/pkg/sleep"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
)
+const (
+ // immediateDuration is a duration of zero for scheduling work that needs to
+ // be done immediately but asynchronously to avoid deadlock.
+ immediateDuration time.Duration = 0
+)
+
// NeighborEntry describes a neighboring device in the local network.
type NeighborEntry struct {
Addr tcpip.Address
@@ -242,7 +249,12 @@ func (e *neighborEntry) setStateLocked(next NeighborState) {
e.job.Schedule(config.RetransmitTimer)
}
- sendUnicastProbe()
+ // Send a probe in another gorountine to free this thread of execution
+ // for finishing the state transition. This is necessary to avoid
+ // deadlock where sending and processing probes are done synchronously,
+ // such as loopback and integration tests.
+ e.job = e.nic.stack.newJob(&e.mu, sendUnicastProbe)
+ e.job.Schedule(immediateDuration)
case Failed:
e.notifyWakersLocked()
@@ -324,7 +336,12 @@ func (e *neighborEntry) handlePacketQueuedLocked(localAddr tcpip.Address) {
e.job.Schedule(config.RetransmitTimer)
}
- sendMulticastProbe()
+ // Send a probe in another gorountine to free this thread of execution
+ // for finishing the state transition. This is necessary to avoid
+ // deadlock where sending and processing probes are done synchronously,
+ // such as loopback and integration tests.
+ e.job = e.nic.stack.newJob(&e.mu, sendMulticastProbe)
+ e.job.Schedule(immediateDuration)
case Stale:
e.setStateLocked(Delay)