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
Хост в локальной сети (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 (или будет удалена) (если никто никогда не пытается использовать запись)?
Соседний кеш в ядре Linux не так прост.
Существуют тонкие различия между записью соседнего кэша, фактически выпадающей из кеша полностью, или просто помеченной как устаревшая / недействительная. В какой-то момент между base_reachable_time/ 2 и 3 * base_reachable_time/ 2, запись все еще будет в кэше, но будет помечена как STALE. Вы должны иметь возможность просмотреть состояние с помощью «ip -s neighbour show».
В состоянии STALE, как показано выше, если я пингую 10.64.42.121, он сразу же отправит пакет на b8: 20: 00: 00: 00: 00. Примерно через секунду он обычно отправляет запрос ARP для того, у кого есть 10.64.42.121, чтобы обновить его кеш до состояния REACHABLE. НО, чтобы сделать ситуацию более запутанной, ядро иногда изменяет значения тайм-аута на основе положительной обратной связи от протоколов более высокого уровня. Это означает, что если я пингую 10.64.42.121, и он отвечает, тогда ядро может не беспокоиться об отправке запроса ARP, потому что оно предполагает, что pong означает, что запись в кэше ARP действительна. Если запись находится в состоянии STALE, она также будет обновляться незапрошенными ответами ARP, которые она случайно увидит.
Теперь в большинстве случаев вам нужно беспокоиться только о том, что запись находится в состоянии 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_time и gc_interval проходя до того, как он действительно будет очищен (так, в целом, пройдет где-то 5-10 минут).
Резюме: вы можете попробовать уменьшить / proc / sys / net / ipv4 / route / gc_timeout на более короткое значение, но есть много переменных, и контролировать их все сложно. Прилагается много усилий, чтобы все работало хорошо, не удаляя записи из кеша слишком рано (а вместо этого просто помечая их как УСТАРЕВШИЕ или даже ОТКАЗЫВАЕМЫЕ).
gc_stale_time
- это правильный параметр, который нужно настроить, чтобы удалить УСТАРЕВШИЕ записи из таблицы ARP. Но это еще не все:
Сборка мусора ARP выполняется в периодическом neigh_periodic_work
функция. Интервал можно настроить с помощью переменной / proc / sys. gc_interval
.
Затем он проверит наличие по крайней мере gc_thresh1
записи в таблице ARP. Это позволит избежать использования лишних циклов ЦП, если таблица слишком мала, чтобы увидеть какие-либо реальные преимущества с точки зрения памяти.
В вашем случае подозреваю gc_thresh1
- это переменная, которую вы хотите настроить. его понижение заставит сборщик мусора работать чаще. Однако это может отрицательно сказаться на производительности в зависимости от интервала запуска.
Примечание: gc_thresh3
это жесткий порог. В таблице никогда не будет больше записей, чем это значение. Настраивайте его осторожно.
Документ Kernel.org указывает, что
route/max_size - INTEGER
Maximum number of routes allowed in the kernel. Increase
this when using large numbers of interfaces and/or routes.
From linux kernel 3.6 onwards, this is deprecated for ipv4
as route cache is no longer used.
/proc/sys/net/ipv4/route/gc_timeout
существенно отличается от таблицы neigh по своему значению, и кеширование маршрутов больше не используется для ip4. Если вы сделаете sysctl net.ipv4.route.gc_thresh
вы, вероятно, увидите, что он установлен на -1
в функции neigh_periodic_work
, вот код ниже:
if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
goto out;
out:
/* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
* ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
* BASE_REACHABLE_TIME.
*/
schedule_delayed_work(&tbl->gc_work,
NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
write_unlock_bh(&tbl->lock);
если количество соседей меньше, чем gc_thresh1, затем goto out, задача gc отложена, поэтому он не может удалить таблицы соседей STALE и FAILED, вы можете изменить значение /proc/sys/net/ipv4/neigh/default/gc_thresh1
, по умолчанию 128 для ядра 3.10.0-327.36.3