aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorSalam Noureddine <noureddine@aristanetworks.com>2013-12-24 17:17:02 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-02 00:08:38 -0500
commit56022a8fdd874c56bb61d8c82559e43044d1aa06 (patch)
treecf2b3afdd11d5a2a9244afcc36b22e11dfd69c3c /net/ipv4
parente82435341ff08769b70400b72a7a8efda83c5014 (diff)
ipv4: arp: update neighbour address when a gratuitous arp is received 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>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/arp.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 5bf408b466b1..1a9b99e04465 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -732,6 +732,7 @@ static int arp_process(struct sk_buff *skb)
732 int addr_type; 732 int addr_type;
733 struct neighbour *n; 733 struct neighbour *n;
734 struct net *net = dev_net(dev); 734 struct net *net = dev_net(dev);
735 bool is_garp = false;
735 736
736 /* arp_rcv below verifies the ARP header and verifies the device 737 /* arp_rcv below verifies the ARP header and verifies the device
737 * is ARP'able. 738 * is ARP'able.
@@ -898,10 +899,12 @@ static int arp_process(struct sk_buff *skb)
898 It is possible, that this option should be enabled for some 899 It is possible, that this option should be enabled for some
899 devices (strip is candidate) 900 devices (strip is candidate)
900 */ 901 */
902 is_garp = arp->ar_op == htons(ARPOP_REQUEST) && tip == sip &&
903 inet_addr_type(net, sip) == RTN_UNICAST;
904
901 if (n == NULL && 905 if (n == NULL &&
902 (arp->ar_op == htons(ARPOP_REPLY) || 906 ((arp->ar_op == htons(ARPOP_REPLY) &&
903 (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) && 907 inet_addr_type(net, sip) == RTN_UNICAST) || is_garp))
904 inet_addr_type(net, sip) == RTN_UNICAST)
905 n = __neigh_lookup(&arp_tbl, &sip, dev, 1); 908 n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
906 } 909 }
907 910
@@ -914,8 +917,10 @@ static int arp_process(struct sk_buff *skb)
914 agents are active. Taking the first reply prevents 917 agents are active. Taking the first reply prevents
915 arp trashing and chooses the fastest router. 918 arp trashing and chooses the fastest router.
916 */ 919 */
917 override = time_after(jiffies, n->updated + 920 override = time_after(jiffies,
918 NEIGH_VAR(n->parms, LOCKTIME)); 921 n->updated +
922 NEIGH_VAR(n->parms, LOCKTIME)) ||
923 is_garp;
919 924
920 /* Broadcast replies and request packets 925 /* Broadcast replies and request packets
921 do not assert neighbour reachability. 926 do not assert neighbour reachability.