From 59329f20b5542114a264d7d0b5d3f54aaba20cd1 Mon Sep 17 00:00:00 2001 From: Jeff Martin Date: Thu, 6 Apr 2023 08:03:17 -0700 Subject: [PATCH] tcpip/stack: Export the NeighborCacheSize constant Fuchsia's Netstack component would like to depend on this constant when setting the buffer size for neighbor events. See https://fxrev.dev/824598. Fixes #8766 PiperOrigin-RevId: 522337436 --- pkg/tcpip/stack/neighbor_cache.go | 8 +++++--- pkg/tcpip/stack/neighbor_cache_test.go | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/pkg/tcpip/stack/neighbor_cache.go b/pkg/tcpip/stack/neighbor_cache.go index c63740074..b38bef4e2 100644 --- a/pkg/tcpip/stack/neighbor_cache.go +++ b/pkg/tcpip/stack/neighbor_cache.go @@ -20,7 +20,9 @@ import ( "gvisor.dev/gvisor/pkg/tcpip" ) -const neighborCacheSize = 512 // max entries per interface +// NeighborCacheSize is the size of the neighborCache. Exceeding this size will +// result in the least recently used entry being evicted. +const NeighborCacheSize = 512 // max entries per interface // NeighborStats holds metrics for the neighbor table. type NeighborStats struct { @@ -87,7 +89,7 @@ func (n *neighborCache) getOrCreateEntry(remoteAddr tcpip.Address) *neighborEntr // The entry that needs to be created must be dynamic since all static // entries are directly added to the cache via addStaticEntry. entry := newNeighborEntry(n, remoteAddr, n.state) - if n.mu.dynamic.count == neighborCacheSize { + if n.mu.dynamic.count == NeighborCacheSize { e := n.mu.dynamic.lru.Back() e.mu.Lock() @@ -300,6 +302,6 @@ func (n *neighborCache) init(nic *nic, r LinkAddressResolver) { linkRes: r, } n.mu.Lock() - n.mu.cache = make(map[tcpip.Address]*neighborEntry, neighborCacheSize) + n.mu.cache = make(map[tcpip.Address]*neighborEntry, NeighborCacheSize) n.mu.Unlock() } diff --git a/pkg/tcpip/stack/neighbor_cache_test.go b/pkg/tcpip/stack/neighbor_cache_test.go index af419ae07..7ce67f660 100644 --- a/pkg/tcpip/stack/neighbor_cache_test.go +++ b/pkg/tcpip/stack/neighbor_cache_test.go @@ -36,7 +36,7 @@ const ( // the neighbor cache to give ample opportunity for verifying behavior during // cache overflows. Four times the size of the neighbor cache allows for // three complete cache overflows. - entryStoreSize = 4 * neighborCacheSize + entryStoreSize = 4 * NeighborCacheSize // typicalLatency is the typical latency for an ARP or NDP packet to travel // to a router and back. @@ -471,10 +471,10 @@ func (c *testContext) overflowCache(opts overflowOptions) error { // When beyond the full capacity, the cache will evict an entry as per the // LRU eviction strategy. Note that the number of static entries should not // affect the total number of dynamic entries that can be added. - if i >= neighborCacheSize+opts.startAtEntryIndex { - removedEntry, ok := c.linkRes.entries.entry(i - neighborCacheSize) + if i >= NeighborCacheSize+opts.startAtEntryIndex { + removedEntry, ok := c.linkRes.entries.entry(i - NeighborCacheSize) if !ok { - return fmt.Errorf("got linkRes.entries.entry(%d) = _, false, want = true", i-neighborCacheSize) + return fmt.Errorf("got linkRes.entries.entry(%d) = _, false, want = true", i-NeighborCacheSize) } removedEntries = append(removedEntries, removedEntry) } @@ -492,7 +492,7 @@ func (c *testContext) overflowCache(opts overflowOptions) error { // by entries() is nondeterministic, so entries have to be sorted before // comparison. wantUnorderedEntries := opts.wantStaticEntries - for i := c.linkRes.entries.size() - neighborCacheSize; i < c.linkRes.entries.size(); i++ { + for i := c.linkRes.entries.size() - NeighborCacheSize; i < c.linkRes.entries.size(); i++ { entry, ok := c.linkRes.entries.entry(i) if !ok { return fmt.Errorf("got c.linkRes.entries.entry(%d) = _, false, want = true", i) @@ -1065,7 +1065,7 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) { // periodically refreshes the frequently used entry. // Fill the neighbor cache to capacity - for i := uint16(0); i < neighborCacheSize; i++ { + for i := uint16(0); i < NeighborCacheSize; i++ { entry, ok := linkRes.entries.entry(i) if !ok { t.Fatalf("got linkRes.entries.entry(%d) = _, false, want = true", i) @@ -1081,9 +1081,9 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) { } // Keep adding more entries - for i := uint16(neighborCacheSize); i < linkRes.entries.size(); i++ { + for i := uint16(NeighborCacheSize); i < linkRes.entries.size(); i++ { // Periodically refresh the frequently used entry - if i%(neighborCacheSize/2) == 0 { + if i%(NeighborCacheSize/2) == 0 { if _, _, err := linkRes.neigh.entry(frequentlyUsedEntry.Addr, "", nil); err != nil { t.Errorf("unexpected error from linkRes.neigh.entry(%s, '', nil): %s", frequentlyUsedEntry.Addr, err) } @@ -1095,9 +1095,9 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) { } // An entry should have been removed, as per the LRU eviction strategy - removedEntry, ok := linkRes.entries.entry(i - neighborCacheSize + 1) + removedEntry, ok := linkRes.entries.entry(i - NeighborCacheSize + 1) if !ok { - t.Fatalf("got linkRes.entries.entry(%d) = _, false, want = true", i-neighborCacheSize+1) + t.Fatalf("got linkRes.entries.entry(%d) = _, false, want = true", i-NeighborCacheSize+1) } if err := addReachableEntryWithRemoved(&nudDisp, clock, linkRes, entry, []NeighborEntry{removedEntry}); err != nil { @@ -1119,7 +1119,7 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) { }, } - for i := linkRes.entries.size() - neighborCacheSize + 1; i < linkRes.entries.size(); i++ { + for i := linkRes.entries.size() - NeighborCacheSize + 1; i < linkRes.entries.size(); i++ { entry, ok := linkRes.entries.entry(i) if !ok { t.Fatalf("got linkRes.entries.entry(%d) = _, false, want = true", i) @@ -1182,7 +1182,7 @@ func TestNeighborCacheConcurrent(t *testing.T) { // The order of entries reported by entries() is nondeterministic, so entries // have to be sorted before comparison. var wantUnsortedEntries []NeighborEntry - for i := linkRes.entries.size() - neighborCacheSize; i < linkRes.entries.size(); i++ { + for i := linkRes.entries.size() - NeighborCacheSize; i < linkRes.entries.size(); i++ { entry, ok := linkRes.entries.entry(i) if !ok { t.Errorf("got linkRes.entries.entry(%d) = _, false, want = true", i) @@ -1615,7 +1615,7 @@ func BenchmarkCacheClear(b *testing.B) { linkRes.delay = 0 // Clear for every possible size of the cache - for cacheSize := uint16(0); cacheSize < neighborCacheSize; cacheSize++ { + for cacheSize := uint16(0); cacheSize < NeighborCacheSize; cacheSize++ { // Fill the neighbor cache to capacity. for i := uint16(0); i < cacheSize; i++ { entry, ok := linkRes.entries.entry(i)