The Linux kernel automatically maintains a list of network protocols in the network protocol stack, which also exists differently in the kernel. For ARP, the Linux kernel provides a caching mechanism to maintain this list.

In actual scenarios, the ARP table maintained by the network device is synchronized with the ARP table maintained by the kernel. Once there is any change, the arp table is notified to the upper-layer ARP module through the hook. However, the ARP module of the network device needs to implement an ARP aging time function, which also depends on the ARP table aging of the Linux kernel.

How does the kernel maintain arp tables

First, let’s look at how the kernel maintains ARP tables:

' ip -s neigh '
Copy the code

You can see a complete arp entry change process. There are three timers. The first one is the time when the object reaches delay, the second one is the time when the object reaches reachable, and the third one is the time when the object becomes stale. We don’t explain much about delay and reachable. The important state is stale. If an entry is stale, you may find several problems. Why is it not delayed? Why do entries not age after stale_time? Take it one problem at a time.

Why is it not in delay state?

The stale state is used to reduce the cost of ARP interaction on the network, that is, to minimize ARP interaction. However, if the entry becomes stale, it indicates that the entry is unsafe and uncertain. However, if an application uses this entry to send packets, the Linux kernel still does not implement ARP interaction. Instead, the Linux kernel sets up a delay state. During the duration of this state, when the packet from the neighbor is received, the entry is available and the packet becomes reachable. If the IP address does not correspond to any MAC address on the network and does not need to exist, set it to Failed.

Therefore, Linux designed this caching mechanism mainly for two purposes, one is to reduce ARP interaction, and the other is to reduce the overhead caused by the operation of adding and deleting entries. Second question, why does it not age after this time? This is also the main bug of this time.

First of all, we know the Settings of several parameters:

Timeout =random( base_reachable_time/2,  3*base_reachable_time/2) + gc_stale_time
Copy the code

At this point, the entry will be set to invalid and wait for the next GC time to reclaim and delete it.

So the problem is to determine the time at gc. At the same time, we also know that the aging time is not very accurate, but a approximate value. The item to be configured is gC_STALe_time. Then we noticed:

net.ipv4.neigh.default.gc_thresh1
Copy the code

The minimum number of entries that exist in the ARP cache, if less than this number, the garbage collector will not run. This seems to be the problem. The default setting is 128, meaning that the GC will only work when the entries are greater than 128.

Of course, there are simple and crude methods, such as calling stale_time when the stale_time state has passed

ip neigh flush 
Copy the code

It’ll be ok. In fact, there is still a question, this bug appears in Linux4.4, I use Linux host is the same performance, while other Linux 3.6 or lower version, only need to configure GC_STALe_time can realize aging, other parameters are completely consistent. There is no problem with aging, perhaps because of kernel version differences, the relationship between entries and GC, or other reasons that have not been resolved.

The kernel has made a lot of efforts to maintain the existence of ARP tables, but you are racking your brains for these optimizations, which is a bit…