On Mon, Aug 10, 2020 at 11:04:55PM +0200, Willy Tarreau wrote: > What could be improved is the way the input values are mixed (just > added hence commutative for now). I didn't want to call a siphash > round on the hot paths, but just shifting the previous noise value > before adding would work, such as the following for example: > > void prandom_u32_add_noise(a, b, c, d) > { > unsigned long *noise = get_cpu_ptr(&net_rand_noise); > > #if BITS_PER_LONG == 64 > *noise = rol64(*noise, 7) + a + b + c + d; > #else > *noise = rol32(*noise, 7) + a + b + c + d; > #endif > put_cpu_ptr(&net_rand_noise); > > }
If you think this is enough seed material, I'm fine with it. I don't hugely like the fact that you sum all the inputs, since entropy tends to be concentrated in the low-order words, and summing risks cancellation. You can't afford even one SIPROUND as a non-cryptographic hash? E.g. DEFINE_PER_CPU(unsigned long[4], net_rand_noise); EXPORT_SYMBOL(net_rand_noise); void prandom_u32_add_noise(a, b, c, d) { unsigned long *noise = get_cpu_ptr(&net_rand_noise); a ^= noise[0]; b ^= noise[1]; c ^= noise[2]; d ^= noise[3]; /* * This is not used cryptographically; it's just * a convenient 4-word hash function. */ SIPROUND(a, b, c, d); noise[0] = a; noise[1] = b; noise[2] = c; put_cpu_ptr(&net_rand_noise); } (And then you mix in net_rand_noise[0].) Other options are HASH_MIX() from fs/namei.c, but that's more sequential. There's also a simple Xorshift generator.