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

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

ipv6: Use universal hash for NDISC.



In order to perform a proper universal hash on a vector of integers,
we have to use different universal hashes on each vector element.

Which means we need 4 different hash randoms for ipv6.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 32288eb4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct neigh_table *tbl, str

	rcu_read_lock_bh();
	nht = rcu_dereference_bh(tbl->nht);
	hash_val = arp_hashfn(key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
	hash_val = arp_hashfn(key, dev, nht->hash_rnd[0]) >> (32 - nht->hash_shift);
	for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
	     n != NULL;
	     n = rcu_dereference_bh(n->next)) {
+9 −0
Original line number Diff line number Diff line
@@ -79,6 +79,15 @@ struct nd_opt_hdr {
	__u8		nd_opt_len;
} __packed;

static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)
{
	const u32 *p32 = pkey;

	return (((p32[0] ^ dev->ifindex) * hash_rnd[0]) +
		(p32[1] * hash_rnd[1]) +
		(p32[2] * hash_rnd[2]) +
		(p32[3] * hash_rnd[3]));
}

extern int			ndisc_init(void);

+4 −2
Original line number Diff line number Diff line
@@ -139,10 +139,12 @@ struct pneigh_entry {
 *	neighbour table manipulation
 */

#define NEIGH_NUM_HASH_RND	4

struct neigh_hash_table {
	struct neighbour __rcu	**hash_buckets;
	unsigned int		hash_shift;
	__u32			hash_rnd;
	__u32			hash_rnd[NEIGH_NUM_HASH_RND];
	struct rcu_head		rcu;
};

@@ -154,7 +156,7 @@ struct neigh_table {
	int			key_len;
	__u32			(*hash)(const void *pkey,
					const struct net_device *dev,
					__u32 hash_rnd);
					__u32 *hash_rnd);
	int			(*constructor)(struct neighbour *);
	int			(*pconstructor)(struct pneigh_entry *);
	void			(*pdestructor)(struct pneigh_entry *);
+10 −3
Original line number Diff line number Diff line
@@ -322,11 +322,18 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device
	goto out;
}

static void neigh_get_hash_rnd(u32 *x)
{
	get_random_bytes(x, sizeof(*x));
	*x |= 1;
}

static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
{
	size_t size = (1 << shift) * sizeof(struct neighbour *);
	struct neigh_hash_table *ret;
	struct neighbour __rcu **buckets;
	int i;

	ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
	if (!ret)
@@ -343,8 +350,8 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
	}
	ret->hash_buckets = buckets;
	ret->hash_shift = shift;
	get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd));
	ret->hash_rnd |= 1;
	for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
		neigh_get_hash_rnd(&ret->hash_rnd[i]);
	return ret;
}

@@ -1828,7 +1835,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,

		rcu_read_lock_bh();
		nht = rcu_dereference_bh(tbl->nht);
		ndc.ndtc_hash_rnd = nht->hash_rnd;
		ndc.ndtc_hash_rnd = nht->hash_rnd[0];
		ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
		rcu_read_unlock_bh();

+2 −2
Original line number Diff line number Diff line
@@ -88,9 +88,9 @@ static const struct neigh_ops dn_phase3_ops = {

static u32 dn_neigh_hash(const void *pkey,
			 const struct net_device *dev,
			 __u32 hash_rnd)
			 __u32 *hash_rnd)
{
	return jhash_2words(*(__u16 *)pkey, 0, hash_rnd);
	return jhash_2words(*(__u16 *)pkey, 0, hash_rnd[0]);
}

struct neigh_table dn_neigh_table = {
Loading