@@ -15,8 +15,9 @@ import (
1515 "strings"
1616 "sync"
1717 "syscall"
18+ "time"
1819
19- lru "github.com/hashicorp/golang-lru/v2"
20+ "github.com/hashicorp/golang-lru/v2/expirable "
2021 "golang.org/x/net/route"
2122 "golang.org/x/sys/unix"
2223 "tailscale.com/envknob"
@@ -38,27 +39,24 @@ var errInterfaceStateInvalid = errors.New("interface state invalid")
3839// routeCache caches the results of interfaceIndexFor calls to avoid
3940// spamming the AF_ROUTE socket. This is used for soft
4041// isolation mode where we do many route lookups.
41- type routeCacheEntry struct {
42- ifIndex int
43- err error
44- }
45-
4642var (
47- routeCache * lru. Cache [string , routeCacheEntry ]
43+ routeCache * expirable. LRU [string , int ]
4844 routeCacheOnce sync.Once
4945)
5046
51- func getRouteCache () * lru. Cache [string , routeCacheEntry ] {
47+ func getRouteCache () * expirable. LRU [string , int ] {
5248 routeCacheOnce .Do (func () {
53- routeCache , _ = lru. New [string , routeCacheEntry ](256 )
49+ routeCache = expirable . NewLRU [string , int ](256 , nil , 15 * time . Second )
5450 })
5551 return routeCache
5652}
5753
5854// ClearRouteCache clears the route cache. This should be called by the
5955// network monitor when a link changes occur.
6056func ClearRouteCache () {
61- getRouteCache ().Purge ()
57+ if coderSoftIsolation .Load () {
58+ getRouteCache ().Purge ()
59+ }
6260}
6361
6462// isInterfaceCoderInterface can be swapped out in tests.
@@ -101,14 +99,9 @@ func parseAddrForRouting(address string) (netip.Addr, error) {
10199 return netip.Addr {}, fmt .Errorf ("invalid address %q: %w" , address , err )
102100 }
103101 if addr .Zone () != "" {
104- // Addresses with zones *can* be represented as a route lookup with extra
105- // effort, but we don't use or support them currently.
102+ // We're not supporting addresses with zones right now.
106103 return netip.Addr {}, fmt .Errorf ("invalid address %q, has zone: %q" , address , addr .Zone ())
107104 }
108- if addr .IsUnspecified () {
109- // This covers the cases of 0.0.0.0 and [::].
110- return netip.Addr {}, nil
111- }
112105
113106 return addr , nil
114107}
@@ -125,7 +118,7 @@ func shouldBindToDefaultInterface(logf logger.Logf, _ *netmon.Monitor, address s
125118 logf ("[unexpected] netns: Coder soft isolation: error parsing address %q, binding to default: %v" , address , err )
126119 return true
127120 }
128- if ! addr .IsValid () {
121+ if ! addr .IsValid () || addr . IsUnspecified () {
129122 // Unspecified addresses should not be bound to any interface.
130123 return false
131124 }
@@ -329,21 +322,21 @@ func getBestInterfaceCached(addr netip.Addr) (int, error) {
329322 key := addr .String ()
330323
331324 // Check cache first
332- if entry , ok := cache .Get (key ); ok {
333- return entry . ifIndex , entry . err
325+ if idx , ok := cache .Get (key ); ok {
326+ return idx , nil
334327 }
335328
336329 // Cache miss, do the actual lookup
337330 idx , err := interfaceIndexFor (addr , true /* canRecurse */ )
338-
339- // Cache the result
340- entry := routeCacheEntry {
341- ifIndex : idx ,
342- err : err ,
331+ if err != nil {
332+ // Don't cache errors
333+ return idx , err
343334 }
344- cache .Add (key , entry )
345335
346- return idx , err
336+ // Cache only successful results
337+ cache .Add (key , idx )
338+
339+ return idx , nil
347340}
348341
349342// SetListenConfigInterfaceIndex sets lc.Control such that sockets are bound
0 commit comments