1. Introduction

The Address Resolution Protocol (ARP) is a way for systems to map an Internet Protocol (IP) address to a Media Access Control (MAC) address. When it comes to Linux, the final map is a cache, also called an ARP table. Notably, for performance or other reasons, we may sometimes need to drop all entries in this table in favor of rebuilding it.

In this tutorial, we discuss ways to flush ARP information. First, we briefly refresh our knowledge about the ARP table cache. After that, we talk about deleting entries from the table via a standard ARP command. Next, we create a one-line shell script to clear the whole ARP table. Finally, we turn to the de facto standard utility for network control and configuration to also control the ARP cache.

We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.2.15. It should work in most POSIX-compliant environments unless otherwise specified.

2. ARP Table Cache

Before going through some ways to delete it, let’s first see and understand the information that ARP generates and stores:

+--------------+-------------------+
|  IP Address  |    MAC Address    |
+--------------+-------------------+
| 192.168.1.1  | 01-00-01-BE-E1-01 |
| 192.168.2.10 | FE-ED-1D-EA-F2-10 |
| 192.168.6.66 | DE-AD-BE-EF-06-66 |
+--------------+-------------------+

In this case, we have a general overview of the map between both address types. If we’ve had any form of communication with a network host, we’d see a mapping like this.

However, the actual information the kernel keeps in the ARP cache is a bit more comprehensive:

$ cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
192.168.1.1      0x1         0x2         01:00:01:be:e1:01     *        eth1
192.168.2.10     0x1         0x2         fe:ed:1d:ea:f2:10     *        eth0
192.168.6.66     0x1         0x6         de:ad:be:ef:06:66     *        tun0

In this case, we see the contents of the /proc/net/arp file in the /proc pseudo-filesystem. This file exposes the ARP table as the system sees it.

In particular, we can see a network interface associated with each entry. This is important, as it means the ARP protocol data can be separated by each physical and virtual device.

3. Using arp

Of course, we can delete specific ARP table entries with the classic arp command from the net-tools.

3.1. Remove Single Entry

Notably, the arp command enables us to remove one entry at a time:

$ arp --delete <ADDRESS>

To do so, we use the –delete (-d) flag with one of the [ADDRESS]es for a given entry. However, this solution isn’t optimal since it doesn’t flush all entries simultaneously.

3.2. Remove All Entries

Still, we can work on all entries with a one-liner.

First, let’s get the output of arp with the -a flag:

$ arp -a
? (192.168.1.1) at 01:00:01:be:e1:01 [ether] on eth1
? (192.168.2.10) at fe:ed:1d:ea:f2:10 [ether] on eth0
? (192.168.6.66) at de:ad:be:ef:06:66 [ether] on tun0

Notably, in this BSD-style format without fixed columns, the IP address appears in parentheses, so we can use them to extract it via sed:

$ arp -a | sed -n 's/.*(\([^()]*\)).*/\1/p'
192.168.1.1
192.168.2.10
192.168.6.66

To clarify, we can break down the sed command and regular expression:

  • -n suppresses the output of all lines by default
  • s/ performs a substitution on each line
  • .*(\([^()]*\)).* ignores all (.*) except the \(\) capture group surrounded by literal () parentheses
  • /\1/ substitutes everything with the contents of the first capture group
  • p prints only lines that underwent the substitution

Finally, we use the output of this command via command substitution:

$ for e in $(arp -a | sed -n 's/.*(\([^()]*\)).*/\1/p'); do arp -d $e; done

In particular, we use a for loop to iterate the results and run arp -d for each IP address. As a result, all entries should be gone from the ARP table.

4. Using ip

The standard ip command doesn’t only work with IP settings, as it can also go lower and even higher in the OSI model.

Since ARP exists between the Data Link layer two (2) and the Network layer three (3) of the OSI, we can control aspects of the protocol through ip commands that work with either.

The link scope exposes subcommands for the Data Link layer. Further, we can set settings like with other ip scopes:

$ ip link set [...]

In particular, let’s see the options we have for ARP:

$ ip link set help
[...]
[ arp { on | off } ]
[...]

While we don’t have direct access to the ARP table, the ip link set arp option provides a way for us to disable and enable ARP on a given interface.

Critically, disabling ARP interrupts all network connectivity on the interface that relies on the protocol, including but not limited to ongoing SSH sessions.

Because of this, we usually disable and reenable arp automatically as a one-liner:

$ ip link set arp off dev eth1; ip link set arp on dev eth1

At this point, we can verify that the entries associated with the eth1 interface are gone from the ARP cache:

$ cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
192.168.2.10     0x1         0x2         fe:ed:1d:ea:f2:10     *        eth0
192.168.6.66     0x1         0x6         de:ad:be:ef:06:66     *        tun0

However, depending on any ongoing communication, the entry might get restored as soon as ARP is back up. For example, running these commands through and for the network interface of an active local network SSH session, we would probably immediately see at least our own IP address in a table row.

Notably, since the dev option is mandatory for the commands above, using this approach to entirely clear the whole ARP table isn’t optimal.

4.2. Remove All Entries With ip [n]eighbour

In addition to the general Data Link layer commands, we have an ARP-specific ip scope called neighbour:

$ ip neighbour [...]

With it, we can control ARP table entries:

  • show all entries
  • flush all entries
  • get specific entries
  • add entry
  • delete entry
  • change entry
  • replace entries

When it comes to the flush command, we can remove all entries without risking connectivity interruptions:

$ ip neighbour flush all

Although we can specify a network interface via the dev option to limit the scope of flush, omitting that achieves our goal of dropping all rows. This is usually the safest approach.

5. Summary

Although vital for most network communication, certain situations, such as when testing and debugging, can cause unnecessary build-up of ARP table entries, requiring a quick way to clean up.

In this article, we talked about the ARP cache and ways to drop entries from it.

In conclusion, there are many ways to manipulate and delete entries from the ARP table, including arp and variations of the standard ip command.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.