[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190503155501.28182-1-dsahern@kernel.org>
Date: Fri, 3 May 2019 08:55:01 -0700
From: David Ahern <dsahern@...nel.org>
To: davem@...emloft.net
Cc: netdev@...r.kernel.org, alan.maguire@...cle.com,
jwestfall@...realistic.net, David Ahern <dsahern@...il.com>
Subject: [PATCH v2 net] neighbor: Call __ipv4_neigh_lookup_noref in neigh_xmit
From: David Ahern <dsahern@...il.com>
Commit cd9ff4de0107 changed the key for IFF_POINTOPOINT devices to
INADDR_ANY, but neigh_xmit which is used for MPLS encapsulations was not
updated to use the altered key. The result is that every packet Tx does
a lookup on the gateway address which does not find an entry, a new one
is created only to find the existing one in the table right before the
insert since arp_constructor was updated to reset the primary key. This
is seen in the allocs and destroys counters:
ip -s -4 ntable show | head -10 | grep alloc
which increase for each packet showing the unnecessary overhread.
Fix by having neigh_xmit use __ipv4_neigh_lookup_noref for NEIGH_ARP_TABLE.
Define __ipv4_neigh_lookup_noref in case CONFIG_INET is not set.
v2
- define __ipv4_neigh_lookup_noref in case CONFIG_INET is not set as
reported by kbuild test robot
Fixes: cd9ff4de0107 ("ipv4: Make neigh lookup keys for loopback/point-to-point devices be INADDR_ANY")
Reported-by: Alan Maguire <alan.maguire@...cle.com>
Signed-off-by: David Ahern <dsahern@...il.com>
Signed-off-by: David Ahern <dsahern@...il.com>
---
include/net/arp.h | 8 ++++++++
net/core/neighbour.c | 9 ++++++++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/include/net/arp.h b/include/net/arp.h
index 977aabfcdc03..c8f580a0e6b1 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -18,6 +18,7 @@ static inline u32 arp_hashfn(const void *pkey, const struct net_device *dev, u32
return val * hash_rnd[0];
}
+#ifdef CONFIG_INET
static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
{
if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
@@ -25,6 +26,13 @@ static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev
return ___neigh_lookup_noref(&arp_tbl, neigh_key_eq32, arp_hashfn, &key, dev);
}
+#else
+static inline
+struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
+{
+ return NULL;
+}
+#endif
static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key)
{
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 30f6fd8f68e0..0ba5018ccb7f 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -31,6 +31,7 @@
#include <linux/times.h>
#include <net/net_namespace.h>
#include <net/neighbour.h>
+#include <net/arp.h>
#include <net/dst.h>
#include <net/sock.h>
#include <net/netevent.h>
@@ -2982,7 +2983,13 @@ int neigh_xmit(int index, struct net_device *dev,
if (!tbl)
goto out;
rcu_read_lock_bh();
- neigh = __neigh_lookup_noref(tbl, addr, dev);
+ if (index == NEIGH_ARP_TABLE) {
+ u32 key = *((u32 *)addr);
+
+ neigh = __ipv4_neigh_lookup_noref(dev, key);
+ } else {
+ neigh = __neigh_lookup_noref(tbl, addr, dev);
+ }
if (!neigh)
neigh = __neigh_create(tbl, addr, dev, false);
err = PTR_ERR(neigh);
--
2.11.0
Powered by blists - more mailing lists