The Address Resolution Protocol (ARP) maps IPv4 to MAC addresses and functions for layers 2 and 3 of the Open Systems Interconnection (OSI) model. In Linux, the arp utility supports listing and manipulating the ARP cache table. However, the tool doesn’t provide a mechanism for kernel configuration of the protocol settings.
In this tutorial, we explore getting and changing internal ARP settings such as the cache timeout. First, we discuss the Linux ARP implementation in general. After that, we delve into the settings that the kernel exposes.
We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments.
2. ARP Implementation
ARP is described in RFC 826 – An Ethernet Address Resolution Protocol. In Linux, the implementation of the ARP RFC is a kernel module.
To begin with, the module has several functions in relation to the cache:
Moreover, most of this functionality depends on positive feedback like a Transmission Control Protocol (TCP) ACK or a simple arping echo:
MACHINE1 MACHINE2 | +------------+ | |>>>>>>>>-+ TCP Data +->>>>>>>>| | +------------+ | | | | +------------+ | |<<<<<<<<-+ TCP ACK +-<<<<<<<<| | +------------+ | | | |->>>>--------------+ | | ARP ENTRY MACHINE2| | |-<<<<--------------+ | | |
In fact, positive feedback is the main protocol database driver. If it comes to that, we can issue an explicit ARP request as well.
In Linux, the ARP cache table is usually in /proc/net/arp. Actually, the /proc pseudo-filesystem exposes most ARP settings.
3. ARP Configuration
Indeed, depending on our needs, we can use /proc to manipulate global or interface-specific settings for ARP:
- /proc/sys/net/ipv4/neigh – directory with subdirectories for every system interface, with each setting exposed as a file of the same name
- /proc/sys/net/ipv4/neigh/default – directory with defaults for new interfaces
For example, to read and write a setting, we can use a simple template:
$ INTERFACE=eth1 $ SETTING=gc_thresh1 $ VALUE=256 $ cat /proc/sys/net/ipv4/neigh/$INTERFACE/$SETTING [...] $ echo $VALUE > /proc/sys/net/ipv4/neigh/$INTERFACE/$SETTING
By default, times are in seconds unless they end in *_ms (milliseconds). Let’s explore the available settings.
3.1. Garbage Collection
To prune table entries, the Linux ARP kernel module uses garbage collection (GC). Furthermore, the latter is controlled via several settings:
- gc_interval (default 30) – interval between GC runs
- gc_stale_time (default 60) – interval between stale neighbor checks
- gc_thresh1 (default 128) – minimum entries to keep before GC runs
- gc_thresh2 (default 512) – soft maximum entries to keep, after which GC waits 5 seconds and runs
- gc_thresh3 (default 1024) – hard maximum entries to keep before GC runs immediately
In case it’s stale, an ARP entry is rechecked.
On top of the other tools and components, Linux offers an arpd userspace ARP daemon. It’s responsible for collecting ARP information to avoid explicit querying.
When there is no positive feedback, the ARP kernel module assumes a stale entry. After waiting delay_first_probe_time (default 5) seconds, it begins probing:
- send app_solicit (default 0) queries to arpd
- send ucast_solicit (default 3) unicast probes
- send mcast_solicit (default 3) multicast or broadcast probes
If no queries or probes get a response, the probed ARP entry is considered invalid. Invalid and unresolved addresses can have up to unres_qlen (default 3) packets queued.
Requests are retransmitted at a rate of one per retrans_time (obsolete, default 1) seconds or retrans_time_ms (default 1000) milliseconds.
3.3. Cache Timeout
To prevent thrashing, the minimum amount of time an ARP entry resides in the cache is locktime (default 1) seconds.
On the other hand, the maximum amount of time an ARP entry is valid is base_reachable_time (default 30) seconds or base_reachable_time_ms (default 30000) milliseconds. The two settings affect each other when set:
$ cat /proc/sys/net/ipv4/neigh/eth1/base_reachable_time 30 $ cat /proc/sys/net/ipv4/neigh/eth1/base_reachable_time_ms 30000 $ echo 666 > /proc/sys/net/ipv4/neigh/eth1/base_reachable_time $ cat /proc/sys/net/ipv4/neigh/eth1/base_reachable_time_ms 666000
Once set, the final ARP cache entry timeout is a random number between [base_reachable_time_ms/2, 3*base_reachable_time_ms/2]. So, by default, this means [15, 45] seconds.
After getting an ARP request for an ARP proxy address, we wait for proxy_delay (default 0.8) seconds before responding.
Similar to unres_qlen, proxy_qlen (default 64) packets are the maximum that can be queued for an ARP proxy address.
In this article, we talked about the ARP protocol implementation in Linux and focused on its available settings.
In conclusion, by manipulating the files in /proc/sys/net/ipv4/neigh, we can get and configure the ARP kernel module.