2000-06-05 11:46:40 +00:00
|
|
|
/*
|
|
|
|
* BIRD Internet Routing Daemon -- Random Numbers
|
|
|
|
*
|
|
|
|
* (c) 2000 Martin Mares <mj@ucw.cz>
|
|
|
|
*
|
|
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2021-04-01 17:20:13 +00:00
|
|
|
#include <fcntl.h>
|
2021-04-07 23:15:17 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2021-04-01 17:20:13 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "sysdep/config.h"
|
2021-04-07 23:15:17 +00:00
|
|
|
#include "nest/bird.h"
|
2021-04-01 17:20:13 +00:00
|
|
|
|
2021-04-07 23:15:17 +00:00
|
|
|
#ifdef HAVE_GETRANDOM
|
|
|
|
#include <sys/random.h>
|
2021-04-01 17:20:13 +00:00
|
|
|
#endif
|
2000-06-05 11:46:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
u32
|
|
|
|
random_u32(void)
|
|
|
|
{
|
Nest: Parametric network hashes
Currently, all fib hash tables use the same hashing function. This leads
to a situation where feeding routes through a pipe from one table to
another causes significant number of collisions, as routes are fed in the
order of increasing hash values, but dst tables are sized based on the
number of stored routes.
The patch makes fib hashing function parametric and chooses random
parameter for each table. Also generally improves quality of hashing
functions.
Unfortunately, while this patch fixes the issue with initial collisions,
having different hashing functions leads to 2x slowdown of pipe feeding,
presumably due to worse cache behavior in dst tables. Also, the original
issue significantly affects just the initial part of feed, when the dst
table is small, so even ideal fix would not improve that much.
Therefore, no merge for this patch.
2022-06-14 16:15:30 +00:00
|
|
|
u32 rand_low, rand_high;
|
2000-06-05 11:46:40 +00:00
|
|
|
|
|
|
|
rand_low = random();
|
|
|
|
rand_high = random();
|
|
|
|
return (rand_low & 0xffff) | ((rand_high & 0xffff) << 16);
|
|
|
|
}
|
2021-04-01 17:20:13 +00:00
|
|
|
|
Nest: Parametric network hashes
Currently, all fib hash tables use the same hashing function. This leads
to a situation where feeding routes through a pipe from one table to
another causes significant number of collisions, as routes are fed in the
order of increasing hash values, but dst tables are sized based on the
number of stored routes.
The patch makes fib hashing function parametric and chooses random
parameter for each table. Also generally improves quality of hashing
functions.
Unfortunately, while this patch fixes the issue with initial collisions,
having different hashing functions leads to 2x slowdown of pipe feeding,
presumably due to worse cache behavior in dst tables. Also, the original
issue significantly affects just the initial part of feed, when the dst
table is small, so even ideal fix would not improve that much.
Therefore, no merge for this patch.
2022-06-14 16:15:30 +00:00
|
|
|
/* Generate random hash parameter (odd, bits roughly balanced) */
|
|
|
|
u32
|
|
|
|
random_hash_param(void)
|
|
|
|
{
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
u32 p = random_u32() | 1;
|
|
|
|
u32 c = u32_popcount(p);
|
|
|
|
|
|
|
|
if ((c >= 12) && (c <= 20))
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-01 17:20:13 +00:00
|
|
|
|
2021-04-07 23:15:17 +00:00
|
|
|
/* If there is no getrandom() / getentropy(), use /dev/urandom */
|
|
|
|
#if !defined(HAVE_GETRANDOM) && !defined(HAVE_GETENTROPY)
|
|
|
|
|
|
|
|
#define HAVE_URANDOM_FD 1
|
|
|
|
static int urandom_fd = -1;
|
|
|
|
|
2021-04-01 17:20:13 +00:00
|
|
|
int
|
2021-04-07 23:15:17 +00:00
|
|
|
read_urandom_fd(void *buf, uint count)
|
2021-04-01 17:20:13 +00:00
|
|
|
{
|
2021-04-07 23:15:17 +00:00
|
|
|
if (urandom_fd < 0)
|
|
|
|
{
|
|
|
|
urandom_fd = open("/dev/urandom", O_RDONLY);
|
|
|
|
if (urandom_fd < 0)
|
|
|
|
die("Cannot open /dev/urandom: %m");
|
2021-04-01 17:20:13 +00:00
|
|
|
}
|
|
|
|
|
2021-04-07 23:15:17 +00:00
|
|
|
return read(urandom_fd, buf, count);
|
2021-04-01 17:20:13 +00:00
|
|
|
}
|
2021-04-07 23:15:17 +00:00
|
|
|
#endif
|
2021-04-01 17:20:13 +00:00
|
|
|
|
|
|
|
|
2021-04-07 23:15:17 +00:00
|
|
|
void
|
|
|
|
random_init(void)
|
|
|
|
{
|
|
|
|
uint seed;
|
2021-04-01 17:20:13 +00:00
|
|
|
|
2021-04-07 23:15:17 +00:00
|
|
|
/* Get random bytes to trip any errors early and to seed random() */
|
|
|
|
random_bytes(&seed, sizeof(seed));
|
|
|
|
|
|
|
|
srandom(seed);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
random_bytes(void *buf, size_t count)
|
2021-04-01 17:20:13 +00:00
|
|
|
{
|
2021-04-07 23:15:17 +00:00
|
|
|
ASSERT(count <= 256);
|
2021-04-01 17:20:13 +00:00
|
|
|
|
2021-04-07 23:15:17 +00:00
|
|
|
while (count > 0)
|
2021-04-01 17:20:13 +00:00
|
|
|
{
|
2021-04-07 23:15:17 +00:00
|
|
|
int n = -1;
|
2021-04-01 17:20:13 +00:00
|
|
|
|
2021-04-07 23:15:17 +00:00
|
|
|
#if defined(HAVE_GETRANDOM)
|
|
|
|
n = getrandom(buf, count, 0);
|
|
|
|
#elif defined(HAVE_GETENTROPY)
|
|
|
|
n = getentropy(buf, count);
|
|
|
|
n = !n ? (int) count : n;
|
|
|
|
#elif defined(HAVE_URANDOM_FD)
|
|
|
|
n = read_urandom_fd(buf, count);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (n < 0)
|
|
|
|
{
|
2021-04-01 17:20:13 +00:00
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
2021-04-07 23:15:17 +00:00
|
|
|
die("Cannot get random bytes: %m");
|
2021-04-01 17:20:13 +00:00
|
|
|
}
|
|
|
|
|
2021-04-07 23:15:17 +00:00
|
|
|
buf += n;
|
|
|
|
count -= n;
|
2021-04-01 17:20:13 +00:00
|
|
|
}
|
|
|
|
}
|