What is Gratuitous ARP?
A Gratuitous ARP (or GARP) is where an ARP message is sent without a request being made.
Why Use Gratuitous ARP?
There are several reasons to use a Gratuitous ARP:
- Update the ARP tables of devices on the same Layer 2 network.
- Update the MAC address table of layer 2 devices, where the MAC address may have moved from one port to another.
- Possibly to update other hosts on the network about a new address being available, essentially pre-populating their ARP table so they do not have to ARP for the new address. This may depend on the behavior of the operating system, as in the examples below.
Some common scenarios where a Gratuitous ARP might be sent include:
- When an interface comes up or gets a new address, it may GARP to let other devices know it is there or something has changed.
- When a First-Hop Redundancy Protocol (FHRP) like VRRP has a mastership change, the new master will GARP to update MAC address tables on Layer 2 devices, letting them know the MAC address for the VIP address has moved.
- Some clustering scenarios may GARP after a mastership change, again to update ARP tables and MAC address tables.
Note that GARP is not used in duplicate address detection, instead, an ARP Probe is used. With an ARP Probe, the sender IP address field must be all zeroes, to avoid polluting ARP caches of devices on the network. Refer to RFC 5227 for more details on this.
What Does A Gratuitous ARP Message Look Like?
This is a good question, and there doesn’t appear to be a definitive answer. I always thought a GARP message would be an ARP Reply, instead it appears it is usually an ARP Request.
I say usually, as it may be implemented differently across systems and software. This is also discussed in RFC 5277 – IPv4 Address Conflict Detection, section 3 in particular.
It appears that in general, a GARP message should be:
- An ARP request
- Destined to the layer 2 broadcast address (ff:ff:ff:ff:ff:ff)
- The ARP payload should have the source and destination IP address set to the station that is sending the GARP.
A Gratuitous ARP Example
In the following examples, we’re going to look at what happens when we don’t use a Gratuitous ARP, followed by what happens when we do.
The example lab looks like this.

The test method is to:
- Check ARP tables on Linux-Attack, the default gateway, Host-1, and Host-2
- Ping from Host-1 and the default gateway to Linux-Attack to populate ARP tables
- Re-check ARP tables again
- Change the MAC address of Linux-Attack
- Test a ping from Host-1 to Linux-Attack again
- The expectation is that Host-1 will have a stale or wrong ARP entry to Linux-Attack, and the ping will timeout.
The second time we work through this when we change the MAC address of Linux-Attack, we will also simulate a GARP using the arping tool. We will then see if there is a difference between these two tests.
Test 1
Step 1 – Check ARP Tables on hosts
Gateway:
lab@vQFX-1> show arp
MAC Address Address Name Interface Flags
{master:0}
lab@vQFX-1>
Linux-Attack:
eve@linux-attack:~$ arp -n -i ens4
arp: in 1 entries no match found.
eve@linux-attack:~$
Host-1:
eve@Host-1:~$ arp -n -i ens4
arp: in 1 entries no match found.
eve@Host-1:~$
Host-2:
eve@Host-2:~$ arp -n -i ens4
arp: in 1 entries no match found.
eve@Host-2:~$
Step 2 – Ping from default gateway and Host-1 to Linux-Attack
Default Gateway:
{master:0}
lab@vQFX-1> ping 10.0.10.10 count 2
PING 10.0.10.10 (10.0.10.10): 56 data bytes
64 bytes from 10.0.10.10: icmp_seq=0 ttl=64 time=322.336 ms
64 bytes from 10.0.10.10: icmp_seq=1 ttl=64 time=107.818 ms
--- 10.0.10.10 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 107.818/215.077/322.336/107.259 ms
{master:0}
lab@vQFX-1>
Host-1:
eve@Host-1:~$ ping 10.0.10.10 -c2
PING 10.0.10.10 (10.0.10.10) 56(84) bytes of data.
64 bytes from 10.0.10.10: icmp_seq=1 ttl=64 time=358 ms
64 bytes from 10.0.10.10: icmp_seq=2 ttl=64 time=127 ms
--- 10.0.10.10 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 127.300/242.812/358.325/115.512 ms
eve@Host-1:~$
Step 3 – re-check ARP table
Default Gateway:
{master:0}
lab@vQFX-1> show arp
MAC Address Address Name Interface Flags
aa:bb:cc:00:10:10 10.0.10.10 10.0.10.10 irb.10 [xe-0/0/0.0] none
Total entries: 2
{master:0}
lab@vQFX-1>
Linux-Attack:
eve@linux-attack:~$ arp -n -i ens4
Address HWtype HWaddress Flags Mask Iface
10.0.10.2 ether aa:bb:cc:00:10:02 C ens4
10.0.10.1 ether aa:bb:cc:00:10:01 C ens4
eve@linux-attack:~$
Host-1:
eve@Host-1:~$ arp -n -i ens4
Address HWtype HWaddress Flags Mask Iface
10.0.10.10 ether aa:bb:cc:00:10:10 C ens4
eve@Host-1:~$
Host-2:
eve@Host-2:~$ arp -n -i ens4
arp: in 1 entries no match found.
eve@Host-2:~$
Step 4 – Change MAC address on Linux-Attack
eve@linux-attack:~$ sudo ip link set ens4 address aa:bb:cc:11:22:33
eve@linux-attack:~$
Step 5 – Ping from Host-1 to Linux-Attack
eve@Host-1:~$ ping 10.0.10.10
PING 10.0.10.10 (10.0.10.10) 56(84) bytes of data.
64 bytes from 10.0.10.10: icmp_seq=9 ttl=64 time=334 ms
64 bytes from 10.0.10.10: icmp_seq=10 ttl=64 time=107 ms
64 bytes from 10.0.10.10: icmp_seq=11 ttl=64 time=105 ms
64 bytes from 10.0.10.10: icmp_seq=12 ttl=64 time=106 ms
64 bytes from 10.0.10.10: icmp_seq=13 ttl=64 time=105 ms
64 bytes from 10.0.10.10: icmp_seq=14 ttl=64 time=105 ms
--- 10.0.10.10 ping statistics ---
14 packets transmitted, 6 received, 57.1429% packet loss, time 13208ms
rtt min/avg/max/mdev = 104.599/143.554/334.051/85.195 ms
^Ceve@Host-1:~$
Although it is not too clear on this output, there was quite a delay before we received the first response. You can see this with the first response being sequence 9 and at the end of the output we see 14 packets sent but only 6 received.
We can now quickly compare the arp tables on the default gateway and Host-1.
Default gateway:
{master:0}
lab@vQFX-1> show arp
MAC Address Address Name Interface Flags
aa:bb:cc:00:10:10 10.0.10.10 10.0.10.10 irb.10 [xe-0/0/0.0] none
Total entries: 2
{master:0}
lab@vQFX-1>
You can see the default gateway still has the old MAC address for 10.0.10.10.
Host-1:
eve@Host-1:~$ arp -n -i ens4
Address HWtype HWaddress Flags Mask Iface
10.0.10.10 ether aa:bb:cc:11:22:33 C ens4
eve@Host-1:~$
Test 1 Explanation
Based on the above output, we can see that Host-1 eventually managed to ping Linux-Attack, but it took some time. The default gateway still has the old or stale ARP entry as it has not had to talk to Linux-Attack again.
We can see what happened on Host-1 by looking at a packet capture when it was trying to ping Linux-Attack. I have added the source (src) and destination (dst) MAC address fields as well.

We can see that Host-1 (10.0.10.2) tries to ping Linux-Attack (10.0.10.10) and that the destination MAC is set to aa:bb:cc:00:10:10, which matches the ARP entry we see on Host-1.
After several failed pings Host-1 sends unicast ARP requests to Linux-Attack – packets 6, 8, and 10. Since we changed the MAC address on Linux-Attack it doesn’t listen to these requests, and Host-1 finally sends a broadcast ARP request, which does get a response. The ping requests are then addressed to the correct MAC address, and Linux-Attack responds with Echo Reply messages.
This behavior may be specific to the Linux version I was using. Clearly, it is doing something a little bit smarter by re-ARPing. I’m not certain that other devices or operating systems would act the same way.
Out of curiosity, I also tested pinging from the default gateway to Linux-Attack and all the pings timed out. It seems as if the ARP table needed to be cleared manually, or left for the entry to time out, so it would ARP again for Linux-Attack.
Test 2
Now let’s repeat the test, but this time we’ll simulate a Gratuitous ARP when we change the MAC address of Linux-Attack.
Step 1 – Check ARP Tables on hosts
Gateway:
{master:0}
lab@vQFX-1> show arp
MAC Address Address Name Interface Flags
{master:0}
lab@vQFX-1>
Linux-Attack:
eve@linux-attack:~$ arp -n -i ens4
arp: in 1 entries no match found.
eve@linux-attack:~$
Host-1:
eve@Host-1:~$ arp -n -i ens4
arp: in 1 entries no match found.
eve@Host-1:~$
Host-2:
eve@Host-2:~$ arp -n -i ens4
arp: in 1 entries no match found.
eve@Host-2:~$
Step 2 – Ping from default gateway and Host-1 to Linux-Attack
Default Gateway:
{master:0}
lab@vQFX-1> ping 10.0.10.10 count 2
PING 10.0.10.10 (10.0.10.10): 56 data bytes
64 bytes from 10.0.10.10: icmp_seq=0 ttl=64 time=313.068 ms
64 bytes from 10.0.10.10: icmp_seq=1 ttl=64 time=109.836 ms
--- 10.0.10.10 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 109.836/211.452/313.068/101.616 ms
{master:0}
lab@vQFX-1>
Host-1:
eve@Host-1:~$ ping 10.0.10.10 -c2
PING 10.0.10.10 (10.0.10.10) 56(84) bytes of data.
64 bytes from 10.0.10.10: icmp_seq=1 ttl=64 time=310 ms
64 bytes from 10.0.10.10: icmp_seq=2 ttl=64 time=105 ms
--- 10.0.10.10 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 105.212/207.577/309.943/102.365 ms
eve@Host-1:~$
Step 3 – re-check ARP table
Default Gateway:
{master:0}
lab@vQFX-1> show arp
MAC Address Address Name Interface Flags
aa:bb:cc:00:10:10 10.0.10.10 10.0.10.10 irb.10 [xe-0/0/0.0] none
Total entries: 2
{master:0}
lab@vQFX-1>
Linux-Attack:
eve@linux-attack:~$ arp -n -i ens4
Address HWtype HWaddress Flags Mask Iface
10.0.10.2 ether aa:bb:cc:00:10:02 C ens4
10.0.10.1 ether aa:bb:cc:00:10:01 C ens4
eve@linux-attack:~$
Host-1:
eve@Host-1:~$ arp -n -i ens4
Address HWtype HWaddress Flags Mask Iface
10.0.10.10 ether aa:bb:cc:00:10:10 C ens4
eve@Host-1:~$
Host-2:
eve@Host-2:~$ arp -n -i ens4
arp: in 1 entries no match found.
eve@Host-2:~$
Step 4 – Change MAC address on Linux-Attack and send Gratuitous ARP
The arping command is used to send the Gratuitous ARP. The -i specifies interface, -U for an unsolicited ARP, -S the source address and the last IP is the destination we are trying to ping for.
To be clear, we’re using this to simulate a Gratuitous ARP request.
eve@linux-attack:~$ sudo ip link set ens4 address aa:bb:cc:11:22:33
eve@linux-attack:~$ sudo arping -i ens4 -U -S 10.0.10.10 10.0.10.10
ARPING 10.0.10.10
Timeout
Timeout
^C
--- 10.0.10.10 statistics ---
3 packets transmitted, 0 packets received, 100% unanswered (0 extra)
eve@linux-attack:~$
Step 5 – Ping from Host-1 to Linux-Attack
eve@Host-1:~$ ping 10.0.10.10
PING 10.0.10.10 (10.0.10.10) 56(84) bytes of data.
64 bytes from 10.0.10.10: icmp_seq=1 ttl=64 time=307 ms
64 bytes from 10.0.10.10: icmp_seq=2 ttl=64 time=106 ms
64 bytes from 10.0.10.10: icmp_seq=3 ttl=64 time=107 ms
64 bytes from 10.0.10.10: icmp_seq=4 ttl=64 time=105 ms
64 bytes from 10.0.10.10: icmp_seq=5 ttl=64 time=105 ms
^C
--- 10.0.10.10 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4007ms
rtt min/avg/max/mdev = 104.968/145.925/307.051/80.564 ms
eve@Host-1:~$
This time the ping worked immediately. There was no delay like we saw in the first test.
We can now quickly compare the arp tables on the default gateway and Host-1:
Default gateway:
{master:0}
lab@vQFX-1> show arp
MAC Address Address Name Interface Flags
aa:bb:cc:11:22:33 10.0.10.10 10.0.10.10 irb.10 [xe-0/0/0.0] none
Total entries: 2
{master:0}
lab@vQFX-1>
This time the default gateway has an updated MAC for 10.0.10.10.
Host-1:
eve@Host-1:~$ arp -n -i ens4
Address HWtype HWaddress Flags Mask Iface
10.0.10.10 ether aa:bb:cc:11:22:33 C ens4
eve@Host-1:~$
Host-2
eve@Host-2:~$ arp -n -i ens4
arp: in 1 entries no match found.
eve@Host-2:~$
Test 2 Explanation
This second test shows GARP having the desired effect. Both Host-1 and the default gateway updated their ARP tables.
So when Host-1 tried to ping Linux-Attack, it already had the correct entry in its ARP table.
If we look at the packet capture we can see the GARP being sent as a broadcast ARP request.

The details of the GARP are shown below. Note how the sender IP address and target IP address are set to the same value.

The other thing to talk about here is Host-2. Its ARP table remained empty throughout this whole test. We did not do anything on Host-2 that would cause it to populate its ARP table, but it also shows that it didn’t use the GARP from Linux-Attack to populate the ARP table either. This behavior may differ on other operating systems.
In this testing, it appears a host only updates its ARP table due to a GARP if it already had an entry for the host sending the GARP packet.
Conclusions
Based on the testing above and some prior experiences, GARP definitely works to update ARP tables of hosts and layer 3 devices such as routers, and will update the MAC address table on layer 2 devices such as switches.
By doing this it reduces or removes outages that occur due to stale ARP entries or MAC address table entries.
GARP might cause some operating systems to pre-populate their ARP tables, but the above testing was limited and didn’t show that behavior.