diff options
author | gVisor bot <gvisor-bot@google.com> | 2020-11-24 23:40:55 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-11-24 23:40:55 +0000 |
commit | 7e4b4bcc8c5bf7a0c2133137cd3b6c57ca127d43 (patch) | |
tree | 20fa31f4029f92e6d35e6a86ad532aaa52c1918a /pkg/tcpip/stack | |
parent | 5a994e663e1c392ef01cdc86b4c6b2782d6e2f65 (diff) | |
parent | 99f2d0ea2f2ec7a9758584d53db64008be33fac4 (diff) |
Merge release-20201109.0-114-g99f2d0ea2 (automated)
Diffstat (limited to 'pkg/tcpip/stack')
-rw-r--r-- | pkg/tcpip/stack/neighbor_cache.go | 2 | ||||
-rw-r--r-- | pkg/tcpip/stack/neighbor_entry.go | 22 |
2 files changed, 23 insertions, 1 deletions
diff --git a/pkg/tcpip/stack/neighbor_cache.go b/pkg/tcpip/stack/neighbor_cache.go index 13ea2d1d9..0d3f626cf 100644 --- a/pkg/tcpip/stack/neighbor_cache.go +++ b/pkg/tcpip/stack/neighbor_cache.go @@ -233,6 +233,8 @@ func (n *neighborCache) addStaticEntry(addr tcpip.Address, linkAddr tcpip.LinkAd } // removeEntryLocked removes the specified entry from the neighbor cache. +// +// Prerequisite: n.mu and entry.mu MUST be locked. func (n *neighborCache) removeEntryLocked(entry *neighborEntry) { if entry.neigh.State != Static { n.dynamic.lru.Remove(entry) diff --git a/pkg/tcpip/stack/neighbor_entry.go b/pkg/tcpip/stack/neighbor_entry.go index 65fbd0ac3..32399b4f5 100644 --- a/pkg/tcpip/stack/neighbor_entry.go +++ b/pkg/tcpip/stack/neighbor_entry.go @@ -258,7 +258,7 @@ func (e *neighborEntry) setStateLocked(next NeighborState) { case Failed: e.notifyWakersLocked() - e.job = e.nic.stack.newJob(&e.mu, func() { + e.job = e.nic.stack.newJob(&doubleLock{first: &e.nic.neigh.mu, second: &e.mu}, func() { e.nic.neigh.removeEntryLocked(e) }) e.job.Schedule(config.UnreachableTime) @@ -512,3 +512,23 @@ func (e *neighborEntry) handleUpperLevelConfirmationLocked() { panic(fmt.Sprintf("Invalid cache entry state: %s", e.neigh.State)) } } + +// doubleLock combines two locks into one while maintaining lock ordering. +// +// TODO(gvisor.dev/issue/4796): Remove this once subsequent traffic to a Failed +// neighbor is allowed. +type doubleLock struct { + first, second sync.Locker +} + +// Lock locks both locks in order: first then second. +func (l *doubleLock) Lock() { + l.first.Lock() + l.second.Lock() +} + +// Unlock unlocks both locks in reverse order: second then first. +func (l *doubleLock) Unlock() { + l.second.Unlock() + l.first.Unlock() +} |