从不使用时,STALE arp 条目何时会变为 FAILED?

Fox*_*Fox 8 linux arp

root@openwrt:~# ip -s -s -4 neigh show dev lan
10.64.42.121 lladdr b8:20:00:00:00:00 used 6387/6341/6313 probes 1 STALE
10.64.42.157 lladdr b8:20:00:00:00:00 used 24/813/19 probes 1 STALE
10.64.42.12  used 29066/30229/29063 probes 6 FAILED
10.64.42.1 lladdr e8:00:00:00:00:00 ref 1 used 10/5/5 probes 1 REACHABLE


root@openwrt:~# cat /proc/sys/net/ipv4/neigh/default/gc_interval 
30

root@openwrt:~# cat /proc/sys/net/ipv4/neigh/default/gc_stale_time
60

root@openwrt:~# cat /proc/sys/net/ipv4/neigh/lan/gc_stale_time
60
Run Code Online (Sandbox Code Playgroud)

局域网中的主机 (b8:20:00:00:00:00) 的 IP 地址为 10.64.42.121。此 IP 现在无效,该主机的 IP 现在为 10.64.42.157(新的 DHCP 租用)。

我试图弄清楚旧的 arp 缓存条目何时将状态更改为 FAILED(假设没有人尝试联系 IP)。

最后一次确认条目是在 6341 秒前(1 小时 45 前)。这大于 60 秒。为什么这个条目仍然处于 STALE 状态,它什么时候会变成 FAILED 状态(或被删除)(如果没有人尝试使用该条目)?

小智 7

Linux 内核中的邻居缓存并不那么简单。

邻居缓存条目实际上完全脱离缓存或只是被标记为陈旧/无效之间存在细微的差异。在base_reachable_time /2 和 3* base_reachable_time /2之间的某个时间点,该条目仍将在缓存中,但会标记为 STALE 状态。您应该能够使用“ip -s neighbor show”查看状态。

当处于上图所示的 STALE 状态时,如果我 ping 10.64.42.121,它将立即将数据包发送到 b8:20:00:00:00:00。大约一秒钟后,它通常会向拥有 10.64.42.121 的用户发送 ARP 请求,以便将其缓存更新回 REACHABLE 状态。但是,更令人困惑的是,内核有时会根据来自更高级别协议的积极反馈来更改超时值。这意味着如果我 ping 10.64.42.121 并且它回复,那么内核可能不会打扰发送 ARP 请求,因为它假定 pong 意味着它的 ARP 缓存条目是有效的。如果条目处于 STALE 状态,它也会被它碰巧看到的主动 ARP 回复更新。

现在,对于大多数情况,您只需要担心处于 STALE 状态的条目。为什么需要从缓存中完全删除条目?内核做了很多努力,通过改变缓存条目的状态而不是实际删除它们并将它们添加到缓存中,从而避免内存抖动。

如果您真的坚持认为它不仅会被标记为 STALE,而且实际上会从邻居缓存使用的哈希映射中删除,那么您必须注意一些事情。首先,如果条目没有被使用并且在gc_stale_time秒内是陈旧的,它应该有资格被删除。如果gc_stale_time过去了,并且将条目标记为可以删除,它将在垃圾收集器运行时(通常在gc_interval秒之后)被删除。

现在的问题是,如果正在引用邻居条目,则不会删除它。您将遇到的主要问题是来自ipv4 路由表的引用。有很多复杂的垃圾收集东西,但需要注意的重要一点是,路由缓存的垃圾收集器在很多内核上每 5 分钟(/proc/sys/net/ipv4/route/gc_timeout秒)才会使条目过期. 这意味着必须将邻居条目标记为陈旧(可能是 30 秒,具体取决于base_reachable_time),然后在路由缓存停止引用条目之前必须经过 5 分钟(如果幸运的话),然后是一些组合的gc_stale_timegc_interval在它实际被清理之前就通过了(所以,总的来说,大约 5-10 分钟会过去)。

总结:您可以尝试将/proc/sys/net/ipv4/route/gc_timeout 减小到更短的值,但是变量很多,很难全部控制。通过不要过早删除缓存中的条目(而是将它们标记为 STALE 甚至 FAILED),我们付出了很多努力来使事情表现良好。


yad*_*taf 3

gc_stale_time是调整以从 ARP 表中逐出 STALE 条目的正确参数。但还有更多:

ARP 垃圾收集在周期性函数中运行neigh_periodic_work。可以通过 /proc/sys 变量调整间隔gc_interval

然后它会检查ARP 表中是否至少gc_thresh1有条目。如果表太小而无法在内存方面看到任何实际好处,这将避免消耗额外的 CPU 周期。

就你而言,我怀疑gc_thresh1是你想要调整的变量。降低它会迫使 GC 更频繁地运行。不过,这可能会对性能产生负面影响,具体取决于运行间隔。

注:gc_thresh3是硬阈值。该表永远不会保留比该值更多的条目。小心调整它。