Send NUD probes in a separate gorountine

Send NUD probes in another gorountine to free the thread of execution for
finishing the state transition. This is necessary to avoid deadlock where
sending and processing probes are done in the same call stack, such as loopback
and integration tests.

Fixes #4701

PiperOrigin-RevId: 340362481
This commit is contained in:
Sam Balana 2020-11-02 19:18:28 -08:00 committed by gVisor bot
parent 51b062f6cd
commit c22067d3d4
2 changed files with 738 additions and 543 deletions

View File

@ -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)

File diff suppressed because it is too large Load Diff