Loading content...
Without the ARP cache, every single IP packet destined for a local host would require a broadcast and reply cycle—introducing latency, consuming bandwidth, and overwhelming the network with redundant traffic. The ARP cache is what transforms ARP from a constant overhead into an occasional lookup.
The cache is deceptively simple in concept: it's just a table mapping IP addresses to MAC addresses. But its implementation involves sophisticated data structures, careful timing policies, multiple entry states, and security considerations. A well-managed ARP cache is invisible; a corrupted or stale cache causes mysterious connectivity failures that frustrate even experienced engineers.
By the end of this page, you will understand how operating systems structure and manage their ARP caches, the different entry states and their transitions, aging and expiration policies, how to inspect and manipulate the cache, and the tradeoffs involved in cache timeout tuning.
The ARP cache (also called the ARP table, neighbor cache, or ARP resolution cache) is a local database maintained by each host's operating system. It stores the results of successful ARP resolutions, allowing future packets to the same destination to be transmitted immediately without waiting for new ARP exchanges.
Fundamental Cache Properties:
Basic Cache Entry Structure:
Each cache entry typically contains:
| Field | Description |
|---|---|
| IP Address | The Layer 3 address that was resolved |
| MAC Address | The corresponding Layer 2 hardware address |
| Interface | Which NIC the entry applies to |
| State | Current entry state (complete, incomplete, stale, etc.) |
| Timestamp | When the entry was created or last confirmed |
| Expiration | When the entry becomes invalid |
| Flags | Static/dynamic, publish, etc. |
The terms 'ARP cache' and 'ARP table' are often used interchangeably. Technically, 'cache' emphasizes the temporary, performance-oriented nature, while 'table' focuses on the data structure. Windows documentation tends to use 'table'; Linux/Unix documentation prefers 'cache' or 'neighbor cache.'
Modern operating systems implement ARP cache entries as state machines. Rather than simple present/absent, entries transition through multiple states that affect how they're used and refreshed.
Linux Neighbor Cache States (also applicable to IPv6 NDP):
| State | Description | Entry Usable? | Next Transition |
|---|---|---|---|
| NONE | No entry exists for this IP | No | → INCOMPLETE when resolution starts |
| INCOMPLETE | ARP request sent, awaiting reply | No (packets queued) | → REACHABLE (on reply) or FAILED (on timeout) |
| REACHABLE | Entry confirmed valid, actively used | Yes | → STALE (after reachable timeout) |
| STALE | Entry aged, validity unconfirmed | Yes (with caveats) | → DELAY when used, or removed |
| DELAY | Stale entry used, confirmation pending | Yes | → REACHABLE (confirmed) or PROBE (timeout) |
| PROBE | Sending ARP to verify entry still valid | Yes | → REACHABLE (reply) or FAILED (no reply) |
| FAILED | Resolution failed, entry invalid | No | Entry removed after brief period |
Key Concepts:
REACHABLE vs. Stale: An entry is REACHABLE when the operating system has recent evidence that the entry is correct. This evidence can come from:
Without confirmation, entries transition to STALE. Stale entries are still usable, but the system knows it should verify them soon.
The DELAY State: When a STALE entry is used, it doesn't immediately trigger ARP. Instead, the system enters DELAY, expecting upper-layer confirmation (like a TCP ACK). This optimization avoids ARP traffic when TCP already confirms reachability. If no confirmation arrives within the delay timeout, the system PROBES with a direct unicast ARP (not broadcast).
The PROBE State: Probing sends ARP directly to the cached MAC address (unicast, not broadcast). If the host is still there with the same MAC, it replies. This is more efficient than broadcast re-resolution.
Windows uses a simpler model: entries are either 'dynamic' (learned) or 'static' (manually configured), with a single reachable timeout. It doesn't expose the STALE/DELAY/PROBE states to administrators, though similar logic exists internally.
ARP cache timeouts balance two competing concerns:
Different operating systems and environments choose different balances.
| Operating System | Default Reachable Timeout | Default Stale Behavior | Maximum Entries |
|---|---|---|---|
| Linux (default) | 30 seconds (base_reachable_time) | Transitions to STALE, may linger | 1024 per interface (tunable) |
| Windows 10/11 | 15-45 seconds (random within range) | Re-resolved on use after timeout | Dynamic, typically thousands |
| macOS | 20 minutes | Hard expiration | Dynamic |
| FreeBSD | 20 minutes | Similar to macOS | Dynamic |
| Cisco IOS | 4 hours | Long-lived by default | Configurable |
Linux Timeout Parameters (sysctl tunables):
# View current settings
sysctl net.ipv4.neigh.default.base_reachable_time_ms
sysctl net.ipv4.neigh.default.gc_stale_time
sysctl net.ipv4.neigh.default.delay_first_probe_time
# Typical defaults:
# base_reachable_time_ms = 30000 (30 seconds)
# gc_stale_time = 60 (seconds, when stale entries can be garbage collected)
# delay_first_probe_time = 5 (seconds before probing a stale entry)
The Randomization Factor:
To prevent synchronized cache expirations (which would cause ARP broadcast storms as many hosts simultaneously re-resolve), operating systems randomize actual timeout values around the base timeout:
This spreads cache expirations over time, smoothing network load.
Shorter timeouts detect MAC changes faster but increase ARP traffic. In hypervisor environments where VMs migrate frequently, short timeouts (seconds) are critical. In stable server networks, longer timeouts (minutes) reduce overhead. The 'right' value depends entirely on your environment's dynamism.
Every network professional must know how to inspect the ARP cache on various platforms. This is fundamental troubleshooting.
Linux:
1234567891011121314
# Traditional command (deprecated but ubiquitous)$ arp -arouter (192.168.1.1) at a0:b1:c2:d3:e4:f5 [ether] on eth0webserver (192.168.1.50) at 00:11:22:33:44:55 [ether] on eth0 # Modern command (iproute2 - recommended)$ ip neigh show192.168.1.1 dev eth0 lladdr a0:b1:c2:d3:e4:f5 REACHABLE192.168.1.50 dev eth0 lladdr 00:11:22:33:44:55 STALE192.168.1.200 dev eth0 FAILED # Detailed view with timestamps$ ip -s neigh show192.168.1.1 dev eth0 lladdr a0:b1:c2:d3:e4:f5 ref 4 used 0/0/0 probes 0 REACHABLEWindows:
123456789101112131415161718
# Command PromptC:\> arp -a Interface: 192.168.1.100 --- 0x4 Internet Address Physical Address Type 192.168.1.1 a0-b1-c2-d3-e4-f5 dynamic 192.168.1.50 00-11-22-33-44-55 dynamic 192.168.1.255 ff-ff-ff-ff-ff-ff static 224.0.0.22 01-00-5e-00-00-16 static # PowerShell (more detailed)PS C:\> Get-NetNeighbor | Format-Table -AutoSize ifIndex IPAddress LinkLayerAddress State------- --------- ---------------- -----4 192.168.1.1 A0-B1-C2-D3-E4-F5 Reachable4 192.168.1.50 00-11-22-33-44-55 Stale4 192.168.1.255 FF-FF-FF-FF-FF-FF PermanentmacOS:
1234567
# Standard command$ arp -arouter (192.168.1.1) at a0:b1:c2:d3:e4:f5 on en0 ifscope [ethernet]webserver (192.168.1.50) at 00:11:22:33:44:55 on en0 ifscope [ethernet] # More detailed with interface specification$ arp -a -i en0When troubleshooting, look for: (1) Missing entries for devices that should be reachable, (2) FAILED/INCOMPLETE entries indicating resolution problems, (3) Wrong MAC addresses that might indicate ARP spoofing, (4) Stale entries for hosts that have moved or changed NICs.
Sometimes administrators need to manually modify the ARP cache—adding static entries for security, deleting stale entries for troubleshooting, or flushing the entire cache to force re-resolution.
Adding Static Entries:
Static entries never expire and take precedence over dynamic ones. They're useful for:
123456789101112
# Linux (requires root)$ sudo arp -s 192.168.1.1 a0:b1:c2:d3:e4:f5# Or using ip command$ sudo ip neigh add 192.168.1.1 lladdr a0:b1:c2:d3:e4:f5 nud permanent dev eth0 # Windows (requires Administrator)C:\> arp -s 192.168.1.1 a0-b1-c2-d3-e4-f5# Or using netshC:\> netsh interface ipv4 add neighbors "Ethernet" 192.168.1.1 a0-b1-c2-d3-e4-f5 # macOS (requires root)$ sudo arp -s 192.168.1.1 a0:b1:c2:d3:e4:f5 permanentDeleting Entries:
1234567891011121314
# Linux$ sudo arp -d 192.168.1.50# Or$ sudo ip neigh del 192.168.1.50 dev eth0 # WindowsC:\> arp -d 192.168.1.50# Or delete all entriesC:\> arp -d *# Or using netshC:\> netsh interface ipv4 delete neighbors "Ethernet" 192.168.1.50 # macOS$ sudo arp -d 192.168.1.50Flushing the Entire Cache:
Complete cache flush forces all entries to be re-resolved—useful when troubleshooting widespread connectivity issues or after significant network changes.
12345678
# Linux - Flush all neighbor entries$ sudo ip neigh flush all # Windows - Delete all entries from specific interfaceC:\> netsh interface ipv4 delete arpcache # macOS - Delete all entries$ sudo arp -a -dFlushing the ARP cache causes temporary connectivity impact. Every subsequent packet will trigger ARP resolution, introducing latency until caches repopulate. On busy servers, this can cause noticeable delays. Plan cache flushes during maintenance windows when possible.
The distinction between static and dynamic entries is fundamental to ARP cache management. Each has specific use cases and tradeoffs.
When to Use Static Entries:
1. Gateway/Router Protection
The default gateway is the most critical ARP entry. If an attacker spoofs the gateway's MAC, they can intercept all external traffic. Static entries for gateways prevent this:
# Linux: Protect gateway from spoofing
sudo ip neigh add 192.168.1.1 lladdr a0:b1:c2:d3:e4:f5 nud permanent dev eth0
2. Critical Server Protection
DNS servers, domain controllers, and other infrastructure should have static entries on client machines to prevent redirection attacks.
3. High-Availability Pairs
When two servers share a virtual IP and fail over between them, static entries ensure the MAC address handoff is controlled, not subject to racing ARP replies.
4. Embedded Systems
Devices with fixed network topology benefit from static entries that survive ARP cache timeout cycles.
By default, static ARP entries are lost on reboot. To make them persistent, add the commands to startup scripts (rc.local on Linux, Task Scheduler on Windows) or use configuration management tools (Ansible, Puppet, GPO). Some systems support /etc/ethers or similar files for persistent entries.
Operating systems implement ARP caches using efficient data structures optimized for fast lookups. Understanding these internals helps explain behavior and performance characteristics.
Common Implementation Approaches:
| Approach | Lookup Time | Memory Usage | Used By |
|---|---|---|---|
| Hash Table | O(1) average | Moderate (hash buckets) | Linux (neighbor cache), Windows |
| Radix Tree / Trie | O(k) where k = key length | Efficient for sparse data | Some BSD variants |
| Simple Array | O(n) linear scan | Minimal overhead | Simple embedded systems |
| LRU Cache + Hash | O(1) with bounded size | Fixed, predictable | Memory-constrained systems |
Linux Neighbor Cache Implementation:
Linux uses a hash table with configurable bucket count. Each bucket contains a linked list of entries that hash to that bucket. Key parameters:
# View neighbor table size parameters
sysctl net.ipv4.neigh.default.gc_thresh1 # Minimum entries before GC
sysctl net.ipv4.neigh.default.gc_thresh2 # Soft limit (GC more aggressive)
sysctl net.ipv4.neigh.default.gc_thresh3 # Hard limit (refuse new entries)
# Typical defaults:
# gc_thresh1 = 128 (don't GC below this)
# gc_thresh2 = 512 (start considering GC)
# gc_thresh3 = 1024 (hard maximum)
Garbage Collection (GC):
When the cache grows beyond thresholds, garbage collection removes entries based on:
GC runs periodically (gc_interval, typically 30 seconds) or when hard limits are reached.
In networks with many hosts (thousands), hitting gc_thresh3 causes new ARP entries to fail. Symptoms include intermittent connectivity and 'neighbour table overflow' kernel messages. Increase thresholds for large networks or implement network segmentation to reduce broadcast domain size.
The ARP cache is a local data structure with no distributed coordination. This creates coherency challenges when network conditions change.
Problem 1: MAC Address Changes
When a host's MAC address changes (NIC replacement, VM migration, failover), cached entries across the network become stale. Until caches expire or are updated, traffic may be misdirected.
Solutions:
Problem 2: Host Movement (VM Migration)
Virtual machines can migrate between physical hosts, changing their Layer 2 location while keeping the same MAC/IP. Switches must update their MAC tables, and peers may need cache updates.
Solutions:
In environments with frequent changes (cloud, containers, VMs), shorter ARP timeouts trade broadcast overhead for faster coherency. Data center networks often use 30-60 second timeouts rather than the 20-minute defaults of traditional workstations.
The ARP cache transforms ARP from a constant overhead into occasional lookups. Understanding its structure, states, and management is essential for network troubleshooting and optimization. Let's consolidate the key takeaways:
What's Next:
With the cache understood, we'll dive deeper into the ARP Request/Reply cycle—examining the specific packet formats, Ethernet frame construction, and the nuances of how requests and replies are matched and processed.
You now have comprehensive knowledge of the ARP cache. From state machines to garbage collection, you understand how operating systems store and manage IP-to-MAC mappings. Next, we'll examine the ARP request/reply packets themselves in precise detail.