Linux内核中的邻居缓存不像我们想象的那么简单。我会试着解释一些与它的怪癖。
在实际上完全从高速缓存中掉出或仅被标记为失效/无效的邻居高速缓存条目之间存在细微差异。在base_reachable_time / 2和3 * base_reachable_time / 2之间的某个点,条目仍然在缓存中,但是它将被标记为STALE的状态。你应该能够通过“ip -s neighbor show”查看状态,
pherricoxide@midigaurd:~$ ip -s neighbor list
192.168.42.1 dev eth0 lladdr 00:25:90:7d:7e:cd ref 2 used 184/184/139 probes 4 STALE
192.168.10.2 dev eth0 lladdr 00:1c:23:cf:0b:6a ref 3 used 33/28/0 probes 1 REACHABLE
192.168.10.1 dev eth0 lladdr 00:17:c5:d8:90:a4 ref 219 used 275/4/121 probes 1 REACHABLE
当处于如上所示的STALE状态时,如果我ping 192.168.42.1,它将立即发送分组到00:25:90:7d:7e:cd。一秒钟左右,它通常会发送一个ARP请求谁有192.168.42.1为了更新它的缓存回到REACHABLE状态。但是,为了使事情更加混乱,内核有时会基于来自更高级协议的正反馈来改变超时值。这意味着如果我ping 192.168.42.1并且它回复,则内核可能不打扰发送ARP请求,因为它假设pong意味着它的ARP缓存条目是有效的。如果条目处于STALE状态,它也将通过它发生的未经请求的ARP应答更新。
现在,在大多数情况下,条目处于STALE状态是所有你需要担心的。为什么你需要完全从缓存中删除该条目?内核通过更改缓存条目的状态而不是实际删除并将它们一直添加到缓存中,而不是破坏内存。
如果你真的坚持认为它不仅会被标记为STALE,但实际上将从邻居缓存使用的hashmap中删除,你必须小心几个事情。首先,如果条目没有被使用,并且对于gc_stale_time秒过时,它应该能够被删除。如果gc_stale_time通过,并且标记该条目为可以删除,它将在垃圾收集器运行时删除(通常在gc_interval秒后)。
现在的问题是,如果相邻条目被引用,则不会被删除。你会遇到问题的主要是从ipv4 routing table引用。有很多复杂的垃圾收集的东西,但重要的是要注意的是路由缓存的垃圾收集器只会每隔5分钟过期条目/ proc / sys / net / ipv4 / route / gc_timeout秒)在很多内核。这意味着相邻条目将被标记为陈旧的(也许30秒,取决于base_reachable_time),然后5分钟必须去之前路由缓存停止引用条目(如果你幸运),其次是一些组合的gc_stale_time和gc_interval在它实际上被清理之前传递(所以,总体来说,5-10分钟之间的时间将通过)。
总结:你可以尝试将/ proc / sys / net / ipv4 / route / gc_timeout减小到一个更小的值,但有很多变量,很难控制它们。通过不太早地删除缓存中的条目(而是将其标记为STALE或甚至失败),有很多努力使事情执行得很好。