zoukankan      html  css  js  c++  java
  • Linux中arp表的老化机制

    Linux中arp表的老化机制

    来源 https://juejin.im/post/6844904166545080334

    Linux内核网络协议栈中自动维护着一堆网络协议,这堆网络协议在内核中也是不同的存在,对于arp,Linux内核就提供了一种缓存机制来维护这张表。

    实际的使用场景是,网络设备维护的arp表与内核维护的arp表相同步,一旦有变化,便通过钩子通知到上层的arp模块。但对于网络设备的arp模块来说,还需要实现一个arp老化时间的功能,这个功能的实现便也依靠了linux内核的arp表老化。

    内核是如何维护arp表

    首先来看内核是如何维护arp表的:

    如果调用命令(需要在busybox中编译):
    ' ip -s neigh '

    可以看到一个完整的arp条目变化的流程。其中有三个计时器,第一个表示到达delay之后的计时,第二个表示到达reachable的计时,第三个表示条目状态变成stale之后的计时。 对于delay和reachable我们不做多解释,重要的状态在于stale。 当条目处于stale状态时,可能会发现几个问题,为什么没有变成delay状态?为什么过了stale_time,条目还不老化? 先一个一个问题解决。

    为什么没有变成delay状态?

    之所以使用stale状态,是因为要减少网络中arp交互的开销,也就是尽量减少arp交互,但当条目变为stale之后,就说明,使用这个条目是不安全的不确定的。但是如果有应用用到这个条目发包,linux内核仍不进行arp交互,而是设立了一个delay的状态,在这个状态的持续过程中,收到了来自邻居的包,那么说明,此条目可用,则转为reachable的状态,如果没有,那么则会真正的进行arp交互,如果还没有,那么说明在这个网络中,此ip已经不对应任何一个mac地址,也没有必要存在了,置为failed。

    所以可见,linux设计这个缓存机制的目的主要有二,一减少arp交互,二减少条目的增加和删除操作造成的开销。 第二个问题,为什么过了这个时间还不老化,这也是这一次的主要bug。

    首先我们先知道几个参数的设置:

     

    如果一个条目从reachable到老化需要经过多少时间
    Timeout =random( base_reachable_time/2,  3*base_reachable_time/2) + gc_stale_time

    这个时候,表项将被置为invalid状态,等待下一个gc时间的到来,回收删除。

    所以问题,看定出在gc的时间。同时我们也得知了,设定老化时间的存在,必然不会非常准确,而是一个大概的值,所需要配置的项就是gc_stale_time。 这时我们留意到:

    net.ipv4.neigh.default.gc_thresh1

    存在于ARP高速缓存中的最少个数,如果少于这个数,垃圾收集器将不会运行 问题似乎就是在此,默认设置为128条,也就是说当条目大于128时,gc才会工作,只要将此项配置成0,便可以正常的实现arp老化。

    当然,其实还是有简单粗暴的方法,比如当已经过了stale_time状态时,调用一下

    ip neigh flush 

    就好了。 其实还是有一个疑问,这个bug在linux4.4中出现,本人使用linux host也是一样的表现,而其他的使用linux3.6或者更低版本的linux中,只需要配置gc_stale_time便可以实现老化,其他的参数配置完全一致,却没有出现不能老化的问题,或许内核版本差异,表项和gc的关系之间存在着不同,或是其他原因,尚未解决。

    还记得在在查找资料的过程中,看到的,内核其实已经对维护arp表的存在进行了很多的努力,但是你却对着这些优化绞尽脑汁,这就有点。。。。。

    Linux ARP缓存配置和状态查看命令

    https://www.cnblogs.com/yorkwoo/p/4664535.html

    • 查看Linux ARP缓存老化时间

    cat /proc/sys/net/ipv4/neigh/eth0/base_reachable_time
    同目录下还有一个文件gc_stale_time,官方解释如下:
    Determines how often to check for stale neighbour entries.
    When a neighbour entry is considered stale it is resolved again before sending data to it.
    Defaults to 60 seconds.

    • 查看Linux ARP缓存状态

    arp -a    #代码对应于ioctl(s, SIOCGARP, &arpreq),没法看到每条缓存的状态是REACHABLE还是STALE

    /isam/slot_1101/run # arp -a
    ? (135.251.197.136) at 00:19:8f:5f:bd:87 [ether] on eth0
    ? (135.251.196.1) at 00:e0:b1:ca:5a:48 [ether] on eth0

    ip neigh show    #实现上是通过另一种系统调用netlink来获取的

    /proc/sys/net/ipv4/neigh/eth0 # ip neigh
    135.251.197.136 dev eth0 lladdr 00:19:8f:5f:bd:87 REACHABLE
    135.251.196.1 dev eth0 lladdr 00:e0:b1:ca:5a:48 STALE

    • 应用程序如何触发arp缓存的添加和刷新呢?

    经过一系列测试,结论如下:

    执行arping命令,无法添加新的arp缓存。但是可以把STALE的缓存刷新为REACHABLE状态。

    arping有如下选项,是不是我少加了什么选项呢?注释符#后面的解释是man命令里面摘过来的。

    arping -I eth0 135.251.196.1 -c 10

    /isam/slot_default/run # arping -h
    arping: invalid option -- 'h'
    BusyBox v1.22.1 (2015-07-11 21:41:15 CEST) multi-call binary.

    Usage: arping [-fqbDUA] [-c CNT] [-w TIMEOUT] [-I IFACE] [-s SRC_IP] DST_IP

    Send ARP requests/replies

    -f Quit on first ARP reply    #Finish after the first reply confirming that target is alive.
    -q Quiet    #Quiet output. Nothing is displayed.
    -b Keep broadcasting, don't go unicast    #Send only MAC level broadcasts. Normally arping starts from sending broadcast, and switch to unicast after reply received.
    -D Duplicated address detection mode    #Duplicate address detection mode (DAD). See RFC2131, 4.4.1.  Returns 0, if DAD succeeded i.e. no replies are received    #如果是DAD模式,则原源主机地址一直没有设置,那么就意味着源地址为0.0.0.0。这样当目的主机接到之后,就会向0.0.0.0发送回复,就相当于广播给以太网中所有的主机。因为进行D重复地址检测模式的原因很可能是由于源主机的IP地址没有设置,从而想设置自身的IP地址。在IP地址没有设置的时候,主机只能接受到地址为0.0.0.0的广播信号。
    -U Unsolicited ARP mode, update your neighbors    #Unsolicited ARP mode to update neighbours<80><99> ARP caches.  No replies are expected.    #为了更新以太网邻居的ARP快速缓存而主动进行的ARP。也就是免费ARP(gratuitous ARP),即请求自己的ip地址的mac地址。
    -A ARP answer mode, update your neighbors    #与-U选项类似,但是发送的是ARP 回复报文,而不是ARP请求报文。
    -c N Stop after sending N ARP requests
    -w TIMEOUT Time to wait for ARP reply, seconds
    -I IFACE Interface to use (default eth0)
    -s SRC_IP Sender IP address
    DST_IP Target IP address

    从以上选项可以看出,我们并没有漏掉什么选项,所以内核就是这么设计的。

    还进行过如下测试,Linux shell ping竟然只能添加arp缓存,但是并不能把STALE的缓存刷新为REACHABLE状态。而且ping是通的,这也说明了STALE还在被引用。

    ============== End

  • 相关阅读:
    leetcode 33. Search in Rotated Sorted Array
    leetcode 32. Longest Valid Parentheses
    leetcode 28. Implement strStr()
    leetcode 27. Remove Element
    leetcode 26. Remove Duplicates from Sorted Array
    leetcode 24. Swap Nodes in Pairs
    leetcode 22. Generate Parentheses
    树莓派的频率管理和热控制
    sql执行insert插入一条记录同时获取刚插入的id
    全程直播个人博客重构过程,采用springboot+dubbo+jpa技术栈。
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/13749751.html
Copyright © 2011-2022 走看看