Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db9ca5ca authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ipv4-Make-neigh-lookup-keys-for-loopback-point-to-point-devices-be-INADDR_ANY'



Jim Westfall says:

====================
ipv4: Make neigh lookup keys for loopback/point-to-point devices be INADDR_ANY

This used to be the previous behavior in older kernels but became broken in
a263b309 (ipv4: Make neigh lookups directly in output packet path)
and then later removed because it was broken in 0bb4087c (ipv4: Fix neigh
lookup keying over loopback/point-to-point devices)

Not having this results in there being an arp entry for every remote ip
address that the device talks to.  Given a fairly active device it can
cause the arp table to become huge and/or having to add/purge large number
of entires to keep within table size thresholds.

$ ip -4 neigh show nud noarp | grep tun | wc -l
55850

$ lnstat -k arp_cache:entries,arp_cache:allocs,arp_cache:destroys -c 10
arp_cach|arp_cach|arp_cach|
 entries|  allocs|destroys|
   81493|620166816|620126069|
  101867|   10186|       0|
  113854|    5993|       0|
  118773|    2459|       0|
   27937|   18579|   63998|
   39256|    5659|       0|
   56231|    8487|       0|
   65602|    4685|       0|
   79697|    7047|       0|
   90733|    5517|       0|

v2:
 - fixes coding style issues
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 17d0fb0c cd9ff4de
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -20,6 +20,9 @@ static inline u32 arp_hashfn(const void *pkey, const struct net_device *dev, u32

static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
{
	if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
		key = INADDR_ANY;

	return ___neigh_lookup_noref(&arp_tbl, neigh_key_eq32, arp_hashfn, &key, dev);
}

+2 −2
Original line number Diff line number Diff line
@@ -532,7 +532,7 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
	if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
		nht = neigh_hash_grow(tbl, nht->hash_shift + 1);

	hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
	hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);

	if (n->parms->dead) {
		rc = ERR_PTR(-EINVAL);
@@ -544,7 +544,7 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
	     n1 != NULL;
	     n1 = rcu_dereference_protected(n1->next,
			lockdep_is_held(&tbl->lock))) {
		if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
		if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
			if (want_ref)
				neigh_hold(n1);
			rc = n1;
+6 −1
Original line number Diff line number Diff line
@@ -223,11 +223,16 @@ static bool arp_key_eq(const struct neighbour *neigh, const void *pkey)

static int arp_constructor(struct neighbour *neigh)
{
	__be32 addr = *(__be32 *)neigh->primary_key;
	__be32 addr;
	struct net_device *dev = neigh->dev;
	struct in_device *in_dev;
	struct neigh_parms *parms;
	u32 inaddr_any = INADDR_ANY;

	if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
		memcpy(neigh->primary_key, &inaddr_any, arp_tbl.key_len);

	addr = *(__be32 *)neigh->primary_key;
	rcu_read_lock();
	in_dev = __in_dev_get_rcu(dev);
	if (!in_dev) {