summaryrefslogtreecommitdiffstats
path: root/net/ipv4/arp.c
diff options
context:
space:
mode:
authorIhar Hrachyshka <ihrachys@redhat.com>2017-05-18 21:41:21 +0200
committerDavid S. Miller <davem@davemloft.net>2017-05-21 19:26:45 +0200
commit7d472a59c0e5ec117220a05de6b370447fb6cb66 (patch)
tree601cf49aa80d31c5805f2aa6b596b748560daf61 /net/ipv4/arp.c
parentarp: postpone addr_type calculation to as late as possible (diff)
downloadlinux-7d472a59c0e5ec117220a05de6b370447fb6cb66.tar.xz
linux-7d472a59c0e5ec117220a05de6b370447fb6cb66.zip
arp: always override existing neigh entries with gratuitous ARP
Currently, when arp_accept is 1, we always override existing neigh entries with incoming gratuitous ARP replies. Otherwise, we override them only if new replies satisfy _locktime_ conditional (packets arrive not earlier than _locktime_ seconds since the last update to the neigh entry). The idea behind locktime is to pick the very first (=> close) reply received in a unicast burst when ARP proxies are used. This helps to avoid ARP thrashing where Linux would switch back and forth from one proxy to another. This logic has nothing to do with gratuitous ARP replies that are generally not aligned in time when multiple IP address carriers send them into network. This patch enforces overriding of existing neigh entries by all incoming gratuitous ARP packets, irrespective of their time of arrival. This will make the kernel honour all incoming gratuitous ARP packets. Signed-off-by: Ihar Hrachyshka <ihrachys@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r--net/ipv4/arp.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index c22103cec823..ae96e6f3e0cb 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -863,16 +863,17 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
- if (IN_DEV_ARP_ACCEPT(in_dev)) {
+ if (n || IN_DEV_ARP_ACCEPT(in_dev)) {
addr_type = -1;
+ is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
+ sip, tip, sha, tha);
+ }
+ if (IN_DEV_ARP_ACCEPT(in_dev)) {
/* Unsolicited ARP is not accepted by default.
It is possible, that this option should be enabled for some
devices (strip is candidate)
*/
- is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
- sip, tip, sha, tha);
-
if (!n &&
(is_garp ||
(arp->ar_op == htons(ARPOP_REPLY) &&