* [RFC] enhanced version of net_random()
@ 2004-08-12 17:48 Stephen Hemminger
2004-08-12 19:48 ` David S. Miller
` (2 more replies)
0 siblings, 3 replies; 17+ messages in thread
From: Stephen Hemminger @ 2004-08-12 17:48 UTC (permalink / raw)
To: David S. Miller; +Cc: Alan Cox, Theodore Ts'o, netdev, linux-kernel
While doing the network emulator, I discovered that the default net_random()
is too stupid, and get_random_bytes() is more than needed. Rather than put
another function in just for sch_netem, how about making net_random() smarter?
The tin-hat crowd already replace net_random() with get_random_bytes anyway.
Here is a proposed alternative to use a longer period PRNG for net_random().
The choice of TT800 was because it was freely available, had a long period,
was fast and relatively small footprint. The existing net_random() was not
really thread safe, but was immune to thread corruption.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
diff -Nru a/net/core/utils.c b/net/core/utils.c
--- a/net/core/utils.c 2004-08-12 10:40:05 -07:00
+++ b/net/core/utils.c 2004-08-12 10:40:05 -07:00
@@ -2,6 +2,7 @@
* Generic address resultion entity
*
* Authors:
+ * net_random update to TT800 Stephen Hemminger
* net_random Alan Cox
* net_ratelimit Andy Kleen
*
@@ -23,6 +24,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_EMBEDDED
static unsigned long net_rand_seed = 152L;
unsigned long net_random(void)
@@ -34,8 +36,79 @@
void net_srandom(unsigned long entropy)
{
net_rand_seed ^= entropy;
+ net_random();
+}
+#else
+/*
+ * This is the TT800 twisted Global Finite Shift Register random number
+ * generator originally by M. Matsumoto, email: matumoto@math.keio.ac.jp.
+ * July 8th 1996 Version
+ *
+ * See: ACM Transactions on Modelling and Computer Simulation,
+ * Vol. 4, No. 3, 1994, pages 254-266.
+ *
+ * It has a large period 2^800 and good distribution properties
+ * up to dimension 25, and passes statistical tests.
+ *
+ * Don't use for cryptographic purposes, see get_random_bytes instead.
+ */
+#define N 25
+#define M 7
+
+static unsigned long net_rand_seed[N] = {
+ 0x95f24dab, 0x0b685215, 0xe76ccae7, 0xaf3ec239, 0x715fad23,
+ 0x24a590ad, 0x69e4b5ef, 0xbf456141, 0x96bc1b7b, 0xa7bdf825,
+ 0xc1de75b7, 0x8858a9c9, 0x2da87693, 0xb657f9dd, 0xffdc8a9f,
+ 0x8121da71, 0x8b823ecb, 0x885d05f5, 0x4e20cd47, 0x5a9ad5d9,
+ 0x512c0c03, 0xea857ccd, 0x4cc1d30f, 0x8891a8a1, 0xa6b7aadb
+};
+
+static spinlock_t net_random_lock = SPIN_LOCK_UNLOCKED;
+
+unsigned long net_random(void)
+{
+ unsigned long y;
+ unsigned long flags;
+ static int k;
+ static const unsigned long mag01[2]={ 0x0, 0x8ebfd028 };
+#define X net_rand_seed
+
+ /* generate N words at one time */
+ spin_lock_irqsave(&net_random_lock, flags);
+ if (k == N) {
+ int kk;
+ for (kk=0; kk< N - M; kk++) {
+ X[kk] = X[kk+M] ^ (X[kk] >> 1) ^ mag01[X[kk] % 2];
+ }
+
+ for (; kk < N; kk++) {
+ X[kk] = X[kk+(M-N)] ^ (X[kk] >> 1) ^ mag01[X[kk] % 2];
+ }
+ k = 0;
+ }
+
+ y = X[k];
+ y ^= (y << 7) & 0x2b5b2500; /* s and b, magic vectors */
+ y ^= (y << 15) & 0xdb8b0000; /* t and c, magic vectors */
+
+ /*
+ * the following line was added by Makoto Matsumoto in the 1996 version
+ * to improve lower bit's corellation.
+ * Delete this line to o use the code published in 1994.
+ */
+ y ^= (y >> 16); /* added to the 1994 version */
+ k++;
+ spin_unlock_irqrestore(&net_random_lock, flags);
+#undef X
+ return y;
+}
+
+void net_srandom(unsigned long entropy)
+{
+ net_rand_seed[0] ^= entropy;
net_random();
}
+#endif
int net_msg_cost = 5*HZ;
int net_msg_burst = 10;
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [RFC] enhanced version of net_random() 2004-08-12 17:48 [RFC] enhanced version of net_random() Stephen Hemminger @ 2004-08-12 19:48 ` David S. Miller 2004-08-13 18:51 ` Stephen Hemminger 2004-08-12 20:02 ` Ben Greear 2004-08-20 17:59 ` Jean-Luc Cooke 2 siblings, 1 reply; 17+ messages in thread From: David S. Miller @ 2004-08-12 19:48 UTC (permalink / raw) To: Stephen Hemminger; +Cc: alan, tytso, netdev, linux-kernel On Thu, 12 Aug 2004 10:48:35 -0700 Stephen Hemminger <shemminger@osdl.org> wrote: > Here is a proposed alternative to use a longer period PRNG for net_random(). > The choice of TT800 was because it was freely available, had a long period, > was fast and relatively small footprint. The existing net_random() was not > really thread safe, but was immune to thread corruption. Any chance of a version that doesn't grab a global lock and disable interrupts every call? :( ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-12 19:48 ` David S. Miller @ 2004-08-13 18:51 ` Stephen Hemminger 2004-08-13 19:28 ` Andi Kleen 0 siblings, 1 reply; 17+ messages in thread From: Stephen Hemminger @ 2004-08-13 18:51 UTC (permalink / raw) To: David S. Miller; +Cc: alan, tytso, netdev, linux-kernel, Ben Greear Here is another alternative, using tansworthe generator. It uses percpu state. The one small semantic change is the net_srandom() only affects the current cpu's seed. The problem was that having it change all cpu's seed would mean adding locking and the only user's today are a couple of places that feed in mac address to try make sure address resolution to collide. diff -Nru a/include/linux/net.h b/include/linux/net.h --- a/include/linux/net.h 2004-08-13 11:48:43 -07:00 +++ b/include/linux/net.h 2004-08-13 11:48:43 -07:00 @@ -169,6 +169,7 @@ extern int net_ratelimit(void); extern unsigned long net_random(void); extern void net_srandom(unsigned long); +extern void net_random_init(void); extern int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t len); diff -Nru a/net/core/dev.c b/net/core/dev.c --- a/net/core/dev.c 2004-08-13 11:48:43 -07:00 +++ b/net/core/dev.c 2004-08-13 11:48:43 -07:00 @@ -3280,6 +3280,8 @@ BUG_ON(!dev_boot_phase); + net_random_init(); + if (dev_proc_init()) goto out; diff -Nru a/net/core/utils.c b/net/core/utils.c --- a/net/core/utils.c 2004-08-13 11:48:43 -07:00 +++ b/net/core/utils.c 2004-08-13 11:48:43 -07:00 @@ -19,22 +19,116 @@ #include <linux/mm.h> #include <linux/string.h> #include <linux/types.h> +#include <linux/random.h> +#include <linux/percpu.h> #include <asm/system.h> #include <asm/uaccess.h> -static unsigned long net_rand_seed = 152L; + +/* + This is a maximally equidistributed combined Tausworthe generator + based on code from GNU Scientific Library 1.5 (30 Jun 2004) + + x_n = (s1_n ^ s2_n ^ s3_n) + + s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19)) + s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25)) + s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11)) + + The period of this generator is about 2^88. + + From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe + Generators", Mathematics of Computation, 65, 213 (1996), 203--213. + + This is available on the net from L'Ecuyer's home page, + + http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps + ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps + + There is an erratum in the paper "Tables of Maximally + Equidistributed Combined LFSR Generators", Mathematics of + Computation, 68, 225 (1999), 261--269: + http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps + + ... the k_j most significant bits of z_j must be non- + zero, for each j. (Note: this restriction also applies to the + computer code given in [4], but was mistakenly not mentioned in + that paper.) + + This affects the seeding procedure by imposing the requirement + s1 > 1, s2 > 7, s3 > 15. + +*/ +struct nrnd_state { + u32 s1, s2, s3; +}; + +static DEFINE_PER_CPU(struct nrnd_state, net_rand_state); + +static u32 __net_random(struct nrnd_state *state) +{ +#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b) + + state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12); + state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4); + state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17); + + return (state->s1 ^ state->s2 ^ state->s3); +} + +static void __net_srandom(struct nrnd_state *state, unsigned long entropy) +{ + u32 s = state->s1 ^ entropy; + + if (s == 0) + s = 1; /* default seed is 1 */ + +#define LCG(n) (69069 * n) + state->s1 = LCG(s); + state->s2 = LCG(state->s1); + state->s3 = LCG(state->s2); + + /* "warm it up" */ + __net_random(state); + __net_random(state); + __net_random(state); + __net_random(state); + __net_random(state); + __net_random(state); +} + unsigned long net_random(void) { - net_rand_seed=net_rand_seed*69069L+1; - return net_rand_seed^jiffies; + unsigned long r; + struct nrnd_state *state = &get_cpu_var(net_rand_state); + r = __net_random(state); + put_cpu_var(state); + return r; } + void net_srandom(unsigned long entropy) { - net_rand_seed ^= entropy; - net_random(); + struct nrnd_state *state = &get_cpu_var(net_rand_state); + __net_srandom(state, entropy); + put_cpu_var(state); +} + +void __init net_random_init(void) +{ + int i; + unsigned long seed[NR_CPUS]; + + get_random_bytes(seed, sizeof(seed)); + + for (i = 0; i < NR_CPUS; i++) { + struct nrnd_state *state = &per_cpu(net_rand_state,i); + + memset(state, 0, sizeof(*state)); + __net_srandom(state, seed[i]); + } } int net_msg_cost = 5*HZ; ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-13 18:51 ` Stephen Hemminger @ 2004-08-13 19:28 ` Andi Kleen 2004-08-16 6:27 ` David S. Miller 0 siblings, 1 reply; 17+ messages in thread From: Andi Kleen @ 2004-08-13 19:28 UTC (permalink / raw) To: Stephen Hemminger; +Cc: davem, alan, tytso, netdev, linux-kernel, greearb On Fri, 13 Aug 2004 11:51:40 -0700 Stephen Hemminger <shemminger@osdl.org> wrote: > Here is another alternative, using tansworthe generator. It uses percpu > state. The one small semantic change is the net_srandom() only affects > the current cpu's seed. The problem was that having it change all cpu's > seed would mean adding locking I would just update the other CPUs without locking. Taking a random number from a partially updated state shouldn't be a big issue. -Andi ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-13 19:28 ` Andi Kleen @ 2004-08-16 6:27 ` David S. Miller 0 siblings, 0 replies; 17+ messages in thread From: David S. Miller @ 2004-08-16 6:27 UTC (permalink / raw) To: Andi Kleen; +Cc: shemminger, alan, tytso, netdev, linux-kernel, greearb On Fri, 13 Aug 2004 21:28:57 +0200 Andi Kleen <ak@suse.de> wrote: > On Fri, 13 Aug 2004 11:51:40 -0700 > Stephen Hemminger <shemminger@osdl.org> wrote: > > > Here is another alternative, using tansworthe generator. It uses percpu > > state. The one small semantic change is the net_srandom() only affects > > the current cpu's seed. The problem was that having it change all cpu's > > seed would mean adding locking > > I would just update the other CPUs without locking. Taking > a random number from a partially updated state shouldn't be a big > issue. I personally don't think we need to touch the other cpus at all, and that having a different current seed on each cpu might actually be a good thing. Stephen, I like this one a lot, especially compared to what we had before. I'm going to add this to my tree for the time being. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-12 17:48 [RFC] enhanced version of net_random() Stephen Hemminger 2004-08-12 19:48 ` David S. Miller @ 2004-08-12 20:02 ` Ben Greear 2004-08-20 17:59 ` Jean-Luc Cooke 2 siblings, 0 replies; 17+ messages in thread From: Ben Greear @ 2004-08-12 20:02 UTC (permalink / raw) To: Stephen Hemminger Cc: David S. Miller, Alan Cox, Theodore Ts'o, netdev, linux-kernel Stephen Hemminger wrote: > While doing the network emulator, I discovered that the default net_random() > is too stupid, and get_random_bytes() is more than needed. Rather than put > another function in just for sch_netem, how about making net_random() smarter? > The tin-hat crowd already replace net_random() with get_random_bytes anyway. > > Here is a proposed alternative to use a longer period PRNG for net_random(). > The choice of TT800 was because it was freely available, had a long period, > was fast and relatively small footprint. The existing net_random() was not > really thread safe, but was immune to thread corruption. Is it really worth the extra spin lock & math? Maybe we could have a net_more_random() method instead that encompasses this improved random logic? Ben -- Ben Greear <greearb@candelatech.com> Candela Technologies Inc http://www.candelatech.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-12 17:48 [RFC] enhanced version of net_random() Stephen Hemminger 2004-08-12 19:48 ` David S. Miller 2004-08-12 20:02 ` Ben Greear @ 2004-08-20 17:59 ` Jean-Luc Cooke 2004-08-20 18:47 ` David S. Miller 2004-08-20 18:59 ` Andreas Dilger 2 siblings, 2 replies; 17+ messages in thread From: Jean-Luc Cooke @ 2004-08-20 17:59 UTC (permalink / raw) To: Stephen Hemminger Cc: David S. Miller, Alan Cox, Theodore Ts'o, netdev, linux-kernel Is there a reason why get_random_bytes() is unsuitable? Keeping the number of PRNGs in the kernel to a minimum should a goal we can all share. JLC On Thu, Aug 12, 2004 at 10:48:35AM -0700, Stephen Hemminger wrote: > While doing the network emulator, I discovered that the default net_random() > is too stupid, and get_random_bytes() is more than needed. Rather than put > another function in just for sch_netem, how about making net_random() smarter? > The tin-hat crowd already replace net_random() with get_random_bytes anyway. > > Here is a proposed alternative to use a longer period PRNG for net_random(). > The choice of TT800 was because it was freely available, had a long period, > was fast and relatively small footprint. The existing net_random() was not > really thread safe, but was immune to thread corruption. > > Signed-off-by: Stephen Hemminger <shemminger@osdl.org> > > diff -Nru a/net/core/utils.c b/net/core/utils.c > --- a/net/core/utils.c 2004-08-12 10:40:05 -07:00 > +++ b/net/core/utils.c 2004-08-12 10:40:05 -07:00 > @@ -2,6 +2,7 @@ > * Generic address resultion entity > * > * Authors: > + * net_random update to TT800 Stephen Hemminger > * net_random Alan Cox > * net_ratelimit Andy Kleen > * > @@ -23,6 +24,7 @@ > #include <asm/system.h> > #include <asm/uaccess.h> > > +#ifdef CONFIG_EMBEDDED > static unsigned long net_rand_seed = 152L; > > unsigned long net_random(void) > @@ -34,8 +36,79 @@ > void net_srandom(unsigned long entropy) > { > net_rand_seed ^= entropy; > + net_random(); > +} > +#else > +/* > + * This is the TT800 twisted Global Finite Shift Register random number > + * generator originally by M. Matsumoto, email: matumoto@math.keio.ac.jp. > + * July 8th 1996 Version > + * > + * See: ACM Transactions on Modelling and Computer Simulation, > + * Vol. 4, No. 3, 1994, pages 254-266. > + * > + * It has a large period 2^800 and good distribution properties > + * up to dimension 25, and passes statistical tests. > + * > + * Don't use for cryptographic purposes, see get_random_bytes instead. > + */ > +#define N 25 > +#define M 7 > + > +static unsigned long net_rand_seed[N] = { > + 0x95f24dab, 0x0b685215, 0xe76ccae7, 0xaf3ec239, 0x715fad23, > + 0x24a590ad, 0x69e4b5ef, 0xbf456141, 0x96bc1b7b, 0xa7bdf825, > + 0xc1de75b7, 0x8858a9c9, 0x2da87693, 0xb657f9dd, 0xffdc8a9f, > + 0x8121da71, 0x8b823ecb, 0x885d05f5, 0x4e20cd47, 0x5a9ad5d9, > + 0x512c0c03, 0xea857ccd, 0x4cc1d30f, 0x8891a8a1, 0xa6b7aadb > +}; > + > +static spinlock_t net_random_lock = SPIN_LOCK_UNLOCKED; > + > +unsigned long net_random(void) > +{ > + unsigned long y; > + unsigned long flags; > + static int k; > + static const unsigned long mag01[2]={ 0x0, 0x8ebfd028 }; > +#define X net_rand_seed > + > + /* generate N words at one time */ > + spin_lock_irqsave(&net_random_lock, flags); > + if (k == N) { > + int kk; > + for (kk=0; kk< N - M; kk++) { > + X[kk] = X[kk+M] ^ (X[kk] >> 1) ^ mag01[X[kk] % 2]; > + } > + > + for (; kk < N; kk++) { > + X[kk] = X[kk+(M-N)] ^ (X[kk] >> 1) ^ mag01[X[kk] % 2]; > + } > + k = 0; > + } > + > + y = X[k]; > + y ^= (y << 7) & 0x2b5b2500; /* s and b, magic vectors */ > + y ^= (y << 15) & 0xdb8b0000; /* t and c, magic vectors */ > + > + /* > + * the following line was added by Makoto Matsumoto in the 1996 version > + * to improve lower bit's corellation. > + * Delete this line to o use the code published in 1994. > + */ > + y ^= (y >> 16); /* added to the 1994 version */ > + k++; > + spin_unlock_irqrestore(&net_random_lock, flags); > +#undef X > + return y; > +} > + > +void net_srandom(unsigned long entropy) > +{ > + net_rand_seed[0] ^= entropy; > net_random(); > } > +#endif > > int net_msg_cost = 5*HZ; > int net_msg_burst = 10; > - > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-20 17:59 ` Jean-Luc Cooke @ 2004-08-20 18:47 ` David S. Miller 2004-08-20 18:59 ` Andreas Dilger 1 sibling, 0 replies; 17+ messages in thread From: David S. Miller @ 2004-08-20 18:47 UTC (permalink / raw) To: Jean-Luc Cooke; +Cc: shemminger, alan, tytso, netdev, linux-kernel On Fri, 20 Aug 2004 13:59:52 -0400 Jean-Luc Cooke <jlcooke@certainkey.com> wrote: > Is there a reason why get_random_bytes() is unsuitable? > > Keeping the number of PRNGs in the kernel to a minimum should a goal we can > all share. Too expensive, this routine will get called potentially multiple times per packet. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-20 17:59 ` Jean-Luc Cooke 2004-08-20 18:47 ` David S. Miller @ 2004-08-20 18:59 ` Andreas Dilger 2004-08-20 19:22 ` Richard B. Johnson 2004-08-20 21:24 ` Lee Revell 1 sibling, 2 replies; 17+ messages in thread From: Andreas Dilger @ 2004-08-20 18:59 UTC (permalink / raw) To: Jean-Luc Cooke Cc: Stephen Hemminger, David S. Miller, Alan Cox, Theodore Ts'o, netdev, linux-kernel [-- Attachment #1: Type: text/plain, Size: 810 bytes --] On Aug 20, 2004 13:59 -0400, Jean-Luc Cooke wrote: > Is there a reason why get_random_bytes() is unsuitable? > > Keeping the number of PRNGs in the kernel to a minimum should a goal we can > all share. For some uses a decent PRNG is enough, and the overhead of get_random_bytes() is much too high. We've needed something like this for a long time (something that gives decenly uniform numbers) and hacks to use useconds/cycles/etc do not cut it. I for one welcome a simple in-kernel interface to e.g. get_urandom_bytes() (or net_random() as this is maybe inappropriately called) that is only pseudo-random but fast and efficient. Cheers, Andreas -- Andreas Dilger http://sourceforge.net/projects/ext2resize/ http://members.shaw.ca/adilger/ http://members.shaw.ca/golinux/ [-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-20 18:59 ` Andreas Dilger @ 2004-08-20 19:22 ` Richard B. Johnson 2004-08-20 19:48 ` David S. Miller 2004-08-23 17:05 ` Stephen Hemminger 2004-08-20 21:24 ` Lee Revell 1 sibling, 2 replies; 17+ messages in thread From: Richard B. Johnson @ 2004-08-20 19:22 UTC (permalink / raw) To: Andreas Dilger Cc: Jean-Luc Cooke, Stephen Hemminger, David S. Miller, Alan Cox, Theodore Ts'o, netdev, Linux kernel [-- Attachment #1: Type: TEXT/PLAIN, Size: 1186 bytes --] On Fri, 20 Aug 2004, Andreas Dilger wrote: > On Aug 20, 2004 13:59 -0400, Jean-Luc Cooke wrote: > > Is there a reason why get_random_bytes() is unsuitable? > > > > Keeping the number of PRNGs in the kernel to a minimum should a goal we can > > all share. > > For some uses a decent PRNG is enough, and the overhead of get_random_bytes() > is much too high. We've needed something like this for a long time (something > that gives decenly uniform numbers) and hacks to use useconds/cycles/etc do > not cut it. I for one welcome a simple in-kernel interface to > e.g. get_urandom_bytes() (or net_random() as this is maybe inappropriately > called) that is only pseudo-random but fast and efficient. > > Cheers, Andreas > -- > Andreas Dilger The attached code will certainly work on Intel machines. It is in the public domain, having been modified by myself to produce a very long sequence... I wouldn't suggest converting it to 'C' because the rotation takes many CPU instructions when one tries to do the test, shift, and OR in 'C', Cheers, Dick Johnson Penguin : Linux version 2.4.26 on an i686 machine (5570.56 BogoMips). Note 96.31% of all statistics are fiction. [-- Attachment #2: Type: TEXT/PLAIN, Size: 1530 bytes --] #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # # File rnd.S Created 04-FEB-1999 Richard B. Johnson # # Simple random number generator. Based upon Alan R. Miller's # algorithm. Professor of Metallurgy, University of New Mexico # Institute of Mining and Technology, circa 1980. Published # In the 8080/Z-80 Assembly Language manual he wrote. # # unsigned size_t rnd((size_t *) seed); # # The seed can be initialized with time(&seed); on each boot. # MAGIC = 0x72b6078b INTPTR = 0x08 DIVISR = 0x0c .section .text .global rnd .type rnd,@function .align 0x04 rnd: pushl %ebx movl INTPTR(%esp), %ebx movl (%ebx), %eax rorl $3, %eax addl $MAGIC, %eax movl %eax, (%ebx) popl %ebx ret #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # # This returns a random number between 0 and one less than the # input divisor, i.e. n mod rand(x). # # size_t modrnd((size_t *) seed, size_t divisor); # .type modrnd,@function .global modrnd .align 0x04 modrnd: pushl %ebx movl INTPTR(%esp), %ebx movl (%ebx), %eax rorl $3, %eax addl $MAGIC, %eax movl %eax, (%ebx) xorl %edx, %edx divl DIVISR(%esp) movl %edx, %eax popl %ebx ret .end #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-20 19:22 ` Richard B. Johnson @ 2004-08-20 19:48 ` David S. Miller 2004-08-20 19:53 ` Jean-Luc Cooke 2004-08-22 15:04 ` Andi Kleen 2004-08-23 17:05 ` Stephen Hemminger 1 sibling, 2 replies; 17+ messages in thread From: David S. Miller @ 2004-08-20 19:48 UTC (permalink / raw) To: root; +Cc: adilger, jlcooke, shemminger, alan, tytso, netdev, linux-kernel On Fri, 20 Aug 2004 15:22:09 -0400 (EDT) "Richard B. Johnson" <root@chaos.analogic.com> wrote: > The attached code will certainly work on Intel machines. It is > in the public domain, having been modified by myself to produce > a very long sequence... How long a period does it have? The one we're adding to the networking has one which is 2^88. > I wouldn't suggest converting it to 'C' because the rotation > takes many CPU instructions when one tries to do the test, shift, > and OR in 'C', You only need 2 'shifts' and an 'or' to do a rotate in C. No tests are needed. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-20 19:48 ` David S. Miller @ 2004-08-20 19:53 ` Jean-Luc Cooke 2004-08-22 15:04 ` Andi Kleen 1 sibling, 0 replies; 17+ messages in thread From: Jean-Luc Cooke @ 2004-08-20 19:53 UTC (permalink / raw) To: David S. Miller Cc: root, adilger, shemminger, alan, tytso, netdev, linux-kernel If speed is what you want, and you want a period > 2^N. Then a single get_rand_bytes() to fill a seed of a simple LFSR might do. Seed value will be N+1 bits long. Rochard's PRNG does not have a period > 2^32, that's for sure. JLC On Fri, Aug 20, 2004 at 12:48:23PM -0700, David S. Miller wrote: > On Fri, 20 Aug 2004 15:22:09 -0400 (EDT) > "Richard B. Johnson" <root@chaos.analogic.com> wrote: > > > The attached code will certainly work on Intel machines. It is > > in the public domain, having been modified by myself to produce > > a very long sequence... > > How long a period does it have? The one we're adding to the > networking has one which is 2^88. > > > I wouldn't suggest converting it to 'C' because the rotation > > takes many CPU instructions when one tries to do the test, shift, > > and OR in 'C', > > You only need 2 'shifts' and an 'or' to do a rotate in C. > No tests are needed. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-20 19:48 ` David S. Miller 2004-08-20 19:53 ` Jean-Luc Cooke @ 2004-08-22 15:04 ` Andi Kleen 1 sibling, 0 replies; 17+ messages in thread From: Andi Kleen @ 2004-08-22 15:04 UTC (permalink / raw) To: David S. Miller Cc: root, adilger, jlcooke, shemminger, alan, tytso, netdev, linux-kernel On Fri, 20 Aug 2004 12:48:23 -0700 "David S. Miller" <davem@redhat.com> wrote: > > I wouldn't suggest converting it to 'C' because the rotation > > takes many CPU instructions when one tries to do the test, shift, > > and OR in 'C', > > You only need 2 'shifts' and an 'or' to do a rotate in C. > No tests are needed. gcc is clever enough to detect the common C patterns for rotate and generate a real ROL when the CPU supports it. -Andi ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-20 19:22 ` Richard B. Johnson 2004-08-20 19:48 ` David S. Miller @ 2004-08-23 17:05 ` Stephen Hemminger 2004-08-23 18:09 ` Richard B. Johnson 1 sibling, 1 reply; 17+ messages in thread From: Stephen Hemminger @ 2004-08-23 17:05 UTC (permalink / raw) To: root Cc: Andreas Dilger, Jean-Luc Cooke, David S. Miller, Alan Cox, Theodore Ts'o, netdev, Linux kernel > The attached code will certainly work on Intel machines. It is > in the public domain, having been modified by myself to produce > a very long sequence... > > I wouldn't suggest converting it to 'C' because the rotation > takes many CPU instructions when one tries to do the test, shift, > and OR in 'C', > > Cheers, > Dick Johnson > Penguin : Linux version 2.4.26 on an i686 machine (5570.56 BogoMips). > Note 96.31% of all statistics are fiction. > > My choice of PRNG was not random. I am not a mathematician (IANAM), but what I was looking for was: + well researched + fast + good distribution + small seed (since per cpu) + Free and open The second version uses tausworthe because it was the fastest in the GNU scientific library and had good properties. See: http://www1.physik.tu-muenchen.de/~gammel/matpack/html/LibDoc/Numbers/Random.html ---------- Returns integer pseudorandom numbers uniformly distributed within [0,4294967295]. The period length is approximately 288 (which is 3*1026). This is Pierre L'Ecuyer's 1996 three-component Tausworthe generator "taus88" This generator is very fast and passes all standard statistical tests. P. L'Ecuyer, Maximally equidistributed combined Tausworthe generators, Mathematics of Computation 65, 203-213 (1996), see Figure 4. P. L'Ecuyer, Random number generation, chapter 4 of the Handbook on Simulation, Ed. Jerry Banks, Wiley, 1997. -------- http://www.gnu.org/software/gsl/manual/gsl-ref_17.html Performance The following table shows the relative performance of a selection the available random number generators. The fastest simulation quality generators are taus, gfsr4 and mt19937. The generators which offer the best mathematically-proven quality are those based on the RANLUX algorithm. 1754 k ints/sec, 870 k doubles/sec, taus 1613 k ints/sec, 855 k doubles/sec, gfsr4 1370 k ints/sec, 769 k doubles/sec, mt19937 565 k ints/sec, 571 k doubles/sec, ranlxs0 400 k ints/sec, 405 k doubles/sec, ranlxs1 490 k ints/sec, 389 k doubles/sec, mrg 407 k ints/sec, 297 k doubles/sec, ranlux 243 k ints/sec, 254 k doubles/sec, ranlxd1 251 k ints/sec, 253 k doubles/sec, ranlxs2 238 k ints/sec, 215 k doubles/sec, cmrg 247 k ints/sec, 198 k doubles/sec, ranlux389 141 k ints/sec, 140 k doubles/sec, ranlxd2 1852 k ints/sec, 935 k doubles/sec, ran3 813 k ints/sec, 575 k doubles/sec, ran0 787 k ints/sec, 476 k doubles/sec, ran1 379 k ints/sec, 292 k doubles/sec, ran2 ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-23 17:05 ` Stephen Hemminger @ 2004-08-23 18:09 ` Richard B. Johnson 0 siblings, 0 replies; 17+ messages in thread From: Richard B. Johnson @ 2004-08-23 18:09 UTC (permalink / raw) To: Stephen Hemminger Cc: Andreas Dilger, Jean-Luc Cooke, David S. Miller, Alan Cox, Theodore Ts'o, netdev, Linux kernel On Mon, 23 Aug 2004, Stephen Hemminger wrote: > > > The attached code will certainly work on Intel machines. It is > > in the public domain, having been modified by myself to produce > > a very long sequence... > > > > I wouldn't suggest converting it to 'C' because the rotation > > takes many CPU instructions when one tries to do the test, shift, > > and OR in 'C', > > > > My choice of PRNG was not random. I am not a mathematician (IANAM), > but what I was looking for was: > > + well researched > + fast > + good distribution > + small seed (since per cpu) > + Free and open > > The second version uses tausworthe because it was the fastest in the GNU scientific > library and had good properties. > > See: > > http://www1.physik.tu-muenchen.de/~gammel/matpack/html/LibDoc/Numbers/Random.html > ---------- > Returns integer pseudorandom numbers uniformly distributed within [0,4294967295]. > The period length is approximately 288 (which is 3*1026). > > This is Pierre L'Ecuyer's 1996 three-component Tausworthe generator "taus88" > > This generator is very fast and passes all standard statistical tests. > > P. L'Ecuyer, Maximally equidistributed combined Tausworthe generators, Mathematics of Computation 65, 203-213 (1996), see Figure 4. > P. L'Ecuyer, Random number generation, chapter 4 of the Handbook on Simulation, Ed. Jerry Banks, Wiley, 1997. > -------- > http://www.gnu.org/software/gsl/manual/gsl-ref_17.html > > Performance > The following table shows the relative performance of a selection the available random number generators. The fastest simulation quality generators are taus, gfsr4 and mt19937. The generators which offer the best mathematically-proven quality are those based on the RANLUX algorithm. > > 1754 k ints/sec, 870 k doubles/sec, taus > 1613 k ints/sec, 855 k doubles/sec, gfsr4 > 1370 k ints/sec, 769 k doubles/sec, mt19937 > 565 k ints/sec, 571 k doubles/sec, ranlxs0 > 400 k ints/sec, 405 k doubles/sec, ranlxs1 > 490 k ints/sec, 389 k doubles/sec, mrg > 407 k ints/sec, 297 k doubles/sec, ranlux > 243 k ints/sec, 254 k doubles/sec, ranlxd1 > 251 k ints/sec, 253 k doubles/sec, ranlxs2 > 238 k ints/sec, 215 k doubles/sec, cmrg > 247 k ints/sec, 198 k doubles/sec, ranlux389 > 141 k ints/sec, 140 k doubles/sec, ranlxd2 > > 1852 k ints/sec, 935 k doubles/sec, ran3 > 813 k ints/sec, 575 k doubles/sec, ran0 > 787 k ints/sec, 476 k doubles/sec, ran1 > 379 k ints/sec, 292 k doubles/sec, ran2 The rnd that I submitted is fast. That's all. For communications it has been found to be good enough. Remember the saying; "Better is the enemy of good enough". It obviously can't have a period of better than 2^32 and, in fact, it has a period of: 4294896635 [0xfffeebfb]. This generates 199,962,632 integers per second on this 2.8 GHz machine. This is a callable procedure that uses a pointer to private data. The speed could be improved if this overhead is not required. The distribution has also been found to be good enough for spread- spectrum use. There are no missing codes although a sorted- list of return values will show that there are some values (codes) that are generated close together, in other words some people expect that if you get a return code of '1', the next one won't be '2', but something "very far away". This generator seems to work more like "real world" noise sources except that such noise sources may give you duplicate values, which this won't. Depending upon how much time you wish to waste for making it better than "good enough", this can be cascaded to give a period of any length (you use one generator to produce the "magic number" for another, etc.) Cheers, Dick Johnson Penguin : Linux version 2.4.26 on an i686 machine (5570.56 BogoMips). Note 96.31% of all statistics are fiction. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-20 18:59 ` Andreas Dilger 2004-08-20 19:22 ` Richard B. Johnson @ 2004-08-20 21:24 ` Lee Revell 2004-08-20 23:55 ` Alan Cox 1 sibling, 1 reply; 17+ messages in thread From: Lee Revell @ 2004-08-20 21:24 UTC (permalink / raw) To: Andreas Dilger Cc: Jean-Luc Cooke, Stephen Hemminger, David S. Miller, Alan Cox, Theodore Ts'o, netdev, linux-kernel On Fri, 2004-08-20 at 14:59, Andreas Dilger wrote: > On Aug 20, 2004 13:59 -0400, Jean-Luc Cooke wrote: > > Is there a reason why get_random_bytes() is unsuitable? > > > > Keeping the number of PRNGs in the kernel to a minimum should a goal we can > > all share. > > For some uses a decent PRNG is enough, and the overhead of get_random_bytes() > is much too high. Agreed. I have numbers to support the above. > We've needed something like this for a long time (something > that gives decenly uniform numbers) and hacks to use useconds/cycles/etc do > not cut it. I for one welcome a simple in-kernel interface to > e.g. get_urandom_bytes() (or net_random() as this is maybe inappropriately > called) that is only pseudo-random but fast and efficient. One problem is that AIUI, we incur this overhead even if a hardware RNG is present. This does not seem right. Hardware RNGs are increasingly common, Linux supports hardware RNGs from AMD, Intel, and VIA. Lee ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] enhanced version of net_random() 2004-08-20 21:24 ` Lee Revell @ 2004-08-20 23:55 ` Alan Cox 0 siblings, 0 replies; 17+ messages in thread From: Alan Cox @ 2004-08-20 23:55 UTC (permalink / raw) To: Lee Revell Cc: Andreas Dilger, Jean-Luc Cooke, Stephen Hemminger, David S. Miller, Theodore Ts'o, netdev, Linux Kernel Mailing List On Gwe, 2004-08-20 at 22:24, Lee Revell wrote: > One problem is that AIUI, we incur this overhead even if a hardware RNG > is present. This does not seem right. Hardware RNGs are increasingly > common, Linux supports hardware RNGs from AMD, Intel, and VIA. Hardware RNG's are actually fairly slow and thus are better as sources to perturb a PRNG. ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2004-08-23 18:09 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-08-12 17:48 [RFC] enhanced version of net_random() Stephen Hemminger 2004-08-12 19:48 ` David S. Miller 2004-08-13 18:51 ` Stephen Hemminger 2004-08-13 19:28 ` Andi Kleen 2004-08-16 6:27 ` David S. Miller 2004-08-12 20:02 ` Ben Greear 2004-08-20 17:59 ` Jean-Luc Cooke 2004-08-20 18:47 ` David S. Miller 2004-08-20 18:59 ` Andreas Dilger 2004-08-20 19:22 ` Richard B. Johnson 2004-08-20 19:48 ` David S. Miller 2004-08-20 19:53 ` Jean-Luc Cooke 2004-08-22 15:04 ` Andi Kleen 2004-08-23 17:05 ` Stephen Hemminger 2004-08-23 18:09 ` Richard B. Johnson 2004-08-20 21:24 ` Lee Revell 2004-08-20 23:55 ` Alan Cox
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).