Skip to content

Commit

Permalink
ipv4: arp: update neighbour address when a gratuitous arp is received…
Browse files Browse the repository at this point in the history
… and arp_accept is set

Gratuitous arp packets are useful in switchover scenarios to update
client arp tables as quickly as possible. Currently, the mac address
of a neighbour is only updated after a locktime period has elapsed
since the last update. In most use cases such delays are unacceptable
for network admins. Moreover, the "updated" field of the neighbour
stucture doesn't record the last time the address of a neighbour
changed but records any change that happens to the neighbour. This is
clearly a bug since locktime uses that field as meaning "addr_updated".
With this observation, I was able to perpetuate a stale address by
sending a stream of gratuitous arp packets spaced less than locktime
apart. With this change the address is updated when a gratuitous arp
is received and the arp_accept sysctl is set.

Signed-off-by: Salam Noureddine <noureddine@aristanetworks.com>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Salam Noureddine authored and David S. Miller committed Jan 2, 2014
1 parent e824353 commit 56022a8
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions net/ipv4/arp.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ static int arp_process(struct sk_buff *skb)
int addr_type;
struct neighbour *n;
struct net *net = dev_net(dev);
bool is_garp = false;

/* arp_rcv below verifies the ARP header and verifies the device
* is ARP'able.
Expand Down Expand Up @@ -898,10 +899,12 @@ static int arp_process(struct sk_buff *skb)
It is possible, that this option should be enabled for some
devices (strip is candidate)
*/
is_garp = arp->ar_op == htons(ARPOP_REQUEST) && tip == sip &&
inet_addr_type(net, sip) == RTN_UNICAST;

if (n == NULL &&
(arp->ar_op == htons(ARPOP_REPLY) ||
(arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) &&
inet_addr_type(net, sip) == RTN_UNICAST)
((arp->ar_op == htons(ARPOP_REPLY) &&
inet_addr_type(net, sip) == RTN_UNICAST) || is_garp))
n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
}

Expand All @@ -914,8 +917,10 @@ static int arp_process(struct sk_buff *skb)
agents are active. Taking the first reply prevents
arp trashing and chooses the fastest router.
*/
override = time_after(jiffies, n->updated +
NEIGH_VAR(n->parms, LOCKTIME));
override = time_after(jiffies,
n->updated +
NEIGH_VAR(n->parms, LOCKTIME)) ||
is_garp;

/* Broadcast replies and request packets
do not assert neighbour reachability.
Expand Down

0 comments on commit 56022a8

Please sign in to comment.