问题描述
Linux协议栈实现为ARP缓存维护了一个状态机,如下图所示(图片来源:《Understading Linux Networking Internals》图26-13修改):
图中的ARP邻居条目在超过base_reachable_time
时间后不会立即被删除,而是状态切换为Stale
状态,在经过gc_stale_time
时间后被删除。前面提到的arp状态可以使用如下命令查看:
ip neigh show all
192.168.184.1 dev ens160 lladdr 00:50:56:c0:00:08 REACHABLE
192.168.184.2 dev ens160 lladdr 00:50:56:f1:b9:fe STALE
与arp老化有关的超时参数可以使用sysctl
或者proc
文件系统进行查看,下面以ens160
网卡为例查看arp相关优化参数:
root@ABC:/proc/sys/net/ipv4/neigh/ens160# ls
anycast_delay base_reachable_time delay_first_probe_time locktime mcast_solicit proxy_qlen retrans_time_ms unres_qlen
app_solicit base_reachable_time_ms gc_stale_time mcast_resolicit proxy_delay retrans_time ucast_solicit unres_qlen_bytes
那么一条处于Stale
老化状态的ARP邻居条目会在静默gc_stale_time
时间后被完全删除吗? 这里先给出答案,实测这条arp条目在gc_stale_time
时间里没有被引用,还是不会被删除的。
ARP邻居条目的删除条件
以下几点因素影响邻居条目的删除:
- linux系统下的邻居条目被引用时不会被删除。一个邻居条目引用的主要影响因素是IPv4路由表。
清理路由缓存的定时器时间为5min(/proc/sys/net/ipv4/route/gc_timeout
单位是秒)。
也可以手动使用ip r show cache; ip r flush cache
命令清除缓存; - ARP定时清理函数
neigh_periodic_work
会检查老化邻居条目数量,当小于/proc/sys/net/ipv4/neigh/default/gc_thresh1
时,不进行清理。 - 老化邻居清理时间
gc_stale_time
和邻居垃圾清理定时器时间gc_interval
所以一条邻居条目从生成到被删除的过程如下:
- 发出arp请求时变为Delay状态
- 收到arp响应变为Reachable状态
- 不使用此邻居条目后,经过
base_reachable_time
秒后变为Stale状态 - 路由缓存不引用此邻居条目后(定时5min清理)
- 检查老化邻居条目数量大于等于
gc_thresh1
时进行下一步,否则不清理 -
gc_interval
定期进行邻居清理,邻居条目处于stale状态超出gc_stale_time
秒后,此老化邻居条目才会被删除
经过实测,不清除路由缓存项后,9分钟后stale状态的邻居条目会被删除(一般来说5~10分钟老化邻居条目会被删除);
清除路由缓存项,经过gc_stale_time
时间后老化邻居条目会被删除。
结论
综上所述,老化的邻居条目的删除时间被多种因素控制(不仅仅是gc_stale_time
超时时间)。linux内核不轻易删除arp老化邻居的目的主要基于以下两点考虑
- 避免频繁的增删ARP邻居条目,复用老化的邻居条目内存结构
- 避免频繁的进行ARP广播请求
在配置ARP老化时间时,只需要配置base_reachable_time
参数。一条邻居条目从Reachable状态转换为Stale状态即认为是老化状态。
至于Stale状态的邻居条目缓存什么时候会被回收清理,交给内核处理即可。