Linux 配置ARP年龄超时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15372011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Configuring ARP age timeout
提问by Thomas
I am trying to configure the ARP age timeout. I think I should set /proc/sys/net/ipv4/neigh/default/base_reachable_time_ms
to the desired timeout. But although I set this to 30000ms (30sec) it still takes close to 10mins for an entry to get removed from the ARP cache. After reading few articles I see there are few more settings that affect the timeout:
我正在尝试配置 ARP 年龄超时。我想我应该设置/proc/sys/net/ipv4/neigh/default/base_reachable_time_ms
为所需的超时时间。但是,尽管我将其设置为 30000 毫秒(30 秒),但仍需要将近 10 分钟的时间才能将条目从 ARP 缓存中删除。在阅读了几篇文章后,我发现还有一些影响超时的设置:
/proc/sys/net/ipv4/neigh/default/gc_interval
/proc/sys/net/ipv4/neigh/default/gc_stale_time
/proc/sys/net/ipv4/route/gc_interval
/proc/sys/net/ipv4/route/gc_timeout
I am not sure what to program for these. The gc_timeout
defaults to 5 minutes in Linux. I changed that to 30 seconds but still I don't see the entry getting removed within base_reachable_time/2
or 3*base_reachable_time/2
.
我不确定要为这些编程什么。该gc_timeout
默认为在Linux下5分钟。我将其更改为 30 秒,但仍然没有看到条目在base_reachable_time/2
或内被删除3*base_reachable_time/2
。
How can I set the expiration time for the ARP cache?
如何设置 ARP 缓存的过期时间?
回答by PherricOxide
The neighbor cache in the Linux kernel isn't as simple as one would think. I'll try to explain some of the quirks with it.
Linux 内核中的邻居缓存并不像人们想象的那么简单。我将尝试用它来解释一些怪癖。
There are subtle differences between an neighbor cache entry actually falling out of the cache entirely or just being marked as stale/invalid. At some point between base_reachable_time/2 and 3*base_reachable_time/2, the entry will still be in the cache, but it will be marked with a state of STALE. You should be able to view the state with "ip -s neighbor show",
邻居缓存条目实际上完全脱离缓存或只是被标记为陈旧/无效之间存在细微的差异。在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
When in the STALE state like show above, if I ping 192.168.42.1, it will send the packet to 00:25:90:7d:7e:cd right away. A second or so later it will usually send an ARP request for who has 192.168.42.1 in order to update it's cache back to a REACHABLE state. BUT, to make matters more confusing, the kernel will sometimes change timeout values based on positive feedback from higher level protocols. What this means is that if I ping 192.168.42.1 and it replies, then the kernel might not bother sending an ARP request because it assumes that the pong meant that it's ARP cache entry is valid. If the entry is in the STALE state, it will also be updated by unsolicited ARP replies that it happens to see.
当处于上图所示的 STALE 状态时,如果我 ping 192.168.42.1,它将立即将数据包发送到 00:25:90:7d:7e:cd。大约一秒钟后,它通常会向拥有 192.168.42.1 的用户发送 ARP 请求,以便将其缓存更新回 REACHABLE 状态。但是,更令人困惑的是,内核有时会根据来自更高级别协议的积极反馈来更改超时值。这意味着如果我 ping 192.168.42.1 并且它回复,那么内核可能不会打扰发送 ARP 请求,因为它假定 pong 意味着它的 ARP 缓存条目是有效的。如果条目处于 STALE 状态,它也会被它碰巧看到的主动 ARP 回复更新。
Now, for the majority of cases, the entry being in the STALE state is all you need to worry about.Why do you need the entry to be removed from the cache entirely? The kernel goes to a lot of effort to not thrash memory by just changing the state of cache entries instead of actually removing and adding them to the cache all the time.
现在,对于大多数情况,您只需要担心处于 STALE 状态的条目。为什么需要从缓存中完全删除条目?内核做了很多努力,通过改变缓存条目的状态而不是实际删除它们并将它们添加到缓存中,从而避免内存抖动。
If you really really insist that it not only will be marked as STALE, but will actually be removed from the hashmap used by the neighbor cache, you have to beware of a few things. First, if the entry hasn't been used and is stale for gc_stale_timeseconds, it should be eligible to be removed. If gc_stale_timepassed and marked the entry as okay to be removed, it will be removed when the garbage collector runs (usually after gc_intervalseconds).
如果您真的坚持认为它不仅会被标记为 STALE,而且实际上会从邻居缓存使用的哈希映射中删除,那么您必须注意一些事情。首先,如果条目没有被使用并且在gc_stale_time秒内是陈旧的,它应该有资格被删除。如果gc_stale_time过去了,并且将条目标记为可以删除,它将在垃圾收集器运行时(通常在gc_interval秒之后)被删除。
Now the problem is that the neighbor entry will not be deleted if it's being referenced. The main thing that you're going to have problems with is the reference from the ipv4 routing table. There's a lot of complicated garbage collection stuff, but the important thing to note is that the garbage collector for the route cache only expires entries every 5 minutes (/proc/sys/net/ipv4/route/gc_timeoutseconds) on a lot of kernels. This means the neighbor entry will have to be marked as stale (maybe 30 seconds, depending on base_reachable_time), then 5 minutes will have to go by before the route cache stops referencing the entry (if you're lucky), followed by some combination of gc_stale_timeand gc_intervalpassing before it actually gets cleaned up (so, overall, somewhere between 5-10 minutes will pass).
现在的问题是,如果正在引用邻居条目,则不会删除它。您将遇到的主要问题是来自ipv4 路由表的引用。有很多复杂的垃圾收集东西,但需要注意的重要一点是,路由缓存的垃圾收集器在很多内核上每 5 分钟(/proc/sys/net/ipv4/route/gc_timeout秒)才会使条目过期. 这意味着必须将邻居条目标记为陈旧(可能是 30 秒,具体取决于base_reachable_time),然后必须经过 5 分钟,路由缓存才会停止引用该条目(如果幸运的话),然后是一些组合的gc_stale_time和gc_interval在它实际被清理之前就通过了(所以,总的来说,大约 5-10 分钟会过去)。
Summary: you can try decreasing /proc/sys/net/ipv4/route/gc_timeoutto a shorter value, but there are a lot of variables and it's difficult to control them all. There's a lot of effort put in to making things perform well by not removing entries in the cache too early (but instead just marking them as STALE or even FAILED).
总结:您可以尝试将/proc/sys/net/ipv4/route/gc_timeout 减小到更短的值,但是变量很多,很难全部控制。通过不要过早删除缓存中的条目(而是将它们标记为 STALE 甚至 FAILED),我们付出了很多努力来使事情表现良好。
回答by Marco Mellia
The simplest way to completely clean the arp cache is to bring the interface down and then up again. Clearly this has lot more implications, e.g., possibly breaking ongoing TCP connections, being unreachable for a while, etc. But that seems to be the only means to really remove an entry from the arp cache in the latest kernels :(
彻底清除 arp 缓存的最简单方法是关闭接口然后再打开。显然,这有更多的含义,例如,可能会破坏正在进行的 TCP 连接,暂时无法访问等。但这似乎是在最新内核中真正从 arp 缓存中删除条目的唯一方法:(
回答by nyet
ip link set arp off dev eth0; ip link set arp on dev eth0