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 状態のときに、192.168.42.1 に ping を実行すると、すぐにパケットが 00:25:90:7d:7e:cd に送信されます。1 秒ほど後に、キャッシュを更新して REACHABLE 状態に戻すために、通常は 192.168.42.1 を持つユーザーに対して ARP 要求を送信します。しかし、問題をさらに混乱させるために、カーネルはより高いレベルのプロトコルからの肯定的なフィードバックに基づいてタイムアウト値を変更することがあります。これが意味することは、192.168.42.1 に ping を実行して応答があった場合、カーネルは、pong が ARP キャッシュ エントリが有効であることを意味していると想定するため、わざわざ ARP 要求を送信しない可能性があるということです。エントリが STALE 状態にある場合、たまたま見た非請求 ARP 応答によっても更新されます。
現在、ほとんどの場合、心配する必要があるのはエントリが STALE 状態にあることだけです。エントリをキャッシュから完全に削除する必要があるのはなぜですか? カーネルは、キャッシュエントリを実際に削除してキャッシュに常に追加するのではなく、キャッシュエントリの状態を変更するだけで、メモリをスラッシングしないように多大な努力を払っています。
STALE としてマークされるだけでなく、近隣キャッシュによって使用されるハッシュマップから実際に削除されることを本当に主張する場合は、いくつかのことに注意する必要があります。まず、エントリが使用されておらず、gc_stale_time秒間古い場合は、削除する資格があります。gc_stale_timeが経過し、エントリを削除してもよいとマークされた場合、ガベージ コレクタの実行時に (通常は gc_interval 秒後に)エントリが削除されます。
ここでの問題は、参照されている場合に隣接エントリが削除されないことです。問題が発生する主なものは、ipv4 ルーティング テーブルからの参照です。ガベージ コレクションには複雑なものがたくさんありますが、多くのカーネルでは、ルート キャッシュのガベージ コレクタが 5 分 ( /proc/sys/net/ipv4/route/gc_timeout秒)ごとにエントリを期限切れにするだけであることに注意してください。 . これは、ネイバー エントリが古いものとしてマークされる必要があることを意味し ( base_reachable_timeによっては 30 秒程度)、ルート キャッシュがエントリの参照を停止するまでに 5 分 (運が良ければ)、その後にいくつかの組み合わせが続く必要があります。gc_stale_timeの_実際にクリーンアップされる前にgc_intervalが経過します (したがって、全体として、5 ~ 10 分が経過します)。
要約: /proc/sys/net/ipv4/route/gc_timeoutをより短い値に減らしてみることはできますが、多くの変数があり、それらをすべて制御することは困難です。キャッシュ内のエントリを削除するのが早すぎないようにする (代わりに、それらを STALE または FAILED としてマークするだけである) ことで、うまく機能させるために多くの努力が払われています。