199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2019 Ericsson AB 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #ifdef __RDSEED__ 699a2dd95SBruce Richardson #include <x86intrin.h> 799a2dd95SBruce Richardson #endif 899a2dd95SBruce Richardson #include <unistd.h> 999a2dd95SBruce Richardson 103d4e27fdSDavid Marchand #include <rte_bitops.h> 1199a2dd95SBruce Richardson #include <rte_branch_prediction.h> 1299a2dd95SBruce Richardson #include <rte_cycles.h> 1399a2dd95SBruce Richardson #include <rte_lcore.h> 14*29c39cd3SMattias Rönnblom #include <rte_lcore_var.h> 1599a2dd95SBruce Richardson #include <rte_random.h> 1699a2dd95SBruce Richardson 17c6552d9aSTyler Retzlaff struct __rte_cache_aligned rte_rand_state { 1899a2dd95SBruce Richardson uint64_t z1; 1999a2dd95SBruce Richardson uint64_t z2; 2099a2dd95SBruce Richardson uint64_t z3; 2199a2dd95SBruce Richardson uint64_t z4; 2299a2dd95SBruce Richardson uint64_t z5; 23c6552d9aSTyler Retzlaff }; 2499a2dd95SBruce Richardson 25*29c39cd3SMattias Rönnblom RTE_LCORE_VAR_HANDLE(struct rte_rand_state, rand_state); 26*29c39cd3SMattias Rönnblom 27*29c39cd3SMattias Rönnblom /* instance to be shared by all unregistered non-EAL threads */ 28*29c39cd3SMattias Rönnblom static struct rte_rand_state unregistered_rand_state; 2999a2dd95SBruce Richardson 3099a2dd95SBruce Richardson static uint32_t 3199a2dd95SBruce Richardson __rte_rand_lcg32(uint32_t *seed) 3299a2dd95SBruce Richardson { 3399a2dd95SBruce Richardson *seed = 1103515245U * *seed + 12345U; 3499a2dd95SBruce Richardson 3599a2dd95SBruce Richardson return *seed; 3699a2dd95SBruce Richardson } 3799a2dd95SBruce Richardson 3899a2dd95SBruce Richardson static uint64_t 3999a2dd95SBruce Richardson __rte_rand_lcg64(uint32_t *seed) 4099a2dd95SBruce Richardson { 4199a2dd95SBruce Richardson uint64_t low; 4299a2dd95SBruce Richardson uint64_t high; 4399a2dd95SBruce Richardson 4499a2dd95SBruce Richardson /* A 64-bit LCG would have been much cleaner, but good 4599a2dd95SBruce Richardson * multiplier/increments for such seem hard to come by. 4699a2dd95SBruce Richardson */ 4799a2dd95SBruce Richardson 4899a2dd95SBruce Richardson low = __rte_rand_lcg32(seed); 4999a2dd95SBruce Richardson high = __rte_rand_lcg32(seed); 5099a2dd95SBruce Richardson 5199a2dd95SBruce Richardson return low | (high << 32); 5299a2dd95SBruce Richardson } 5399a2dd95SBruce Richardson 5499a2dd95SBruce Richardson static uint64_t 5599a2dd95SBruce Richardson __rte_rand_lfsr258_gen_seed(uint32_t *seed, uint64_t min_value) 5699a2dd95SBruce Richardson { 5799a2dd95SBruce Richardson uint64_t res; 5899a2dd95SBruce Richardson 5999a2dd95SBruce Richardson res = __rte_rand_lcg64(seed); 6099a2dd95SBruce Richardson 6199a2dd95SBruce Richardson if (res < min_value) 6299a2dd95SBruce Richardson res += min_value; 6399a2dd95SBruce Richardson 6499a2dd95SBruce Richardson return res; 6599a2dd95SBruce Richardson } 6699a2dd95SBruce Richardson 6799a2dd95SBruce Richardson static void 6899a2dd95SBruce Richardson __rte_srand_lfsr258(uint64_t seed, struct rte_rand_state *state) 6999a2dd95SBruce Richardson { 7099a2dd95SBruce Richardson uint32_t lcg_seed; 7199a2dd95SBruce Richardson 7299a2dd95SBruce Richardson lcg_seed = (uint32_t)(seed ^ (seed >> 32)); 7399a2dd95SBruce Richardson 7499a2dd95SBruce Richardson state->z1 = __rte_rand_lfsr258_gen_seed(&lcg_seed, 2UL); 7599a2dd95SBruce Richardson state->z2 = __rte_rand_lfsr258_gen_seed(&lcg_seed, 512UL); 7699a2dd95SBruce Richardson state->z3 = __rte_rand_lfsr258_gen_seed(&lcg_seed, 4096UL); 7799a2dd95SBruce Richardson state->z4 = __rte_rand_lfsr258_gen_seed(&lcg_seed, 131072UL); 7899a2dd95SBruce Richardson state->z5 = __rte_rand_lfsr258_gen_seed(&lcg_seed, 8388608UL); 7999a2dd95SBruce Richardson } 8099a2dd95SBruce Richardson 8199a2dd95SBruce Richardson void 8299a2dd95SBruce Richardson rte_srand(uint64_t seed) 8399a2dd95SBruce Richardson { 8499a2dd95SBruce Richardson unsigned int lcore_id; 8599a2dd95SBruce Richardson 8699a2dd95SBruce Richardson /* add lcore_id to seed to avoid having the same sequence */ 87*29c39cd3SMattias Rönnblom for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 88*29c39cd3SMattias Rönnblom struct rte_rand_state *lcore_state = 89*29c39cd3SMattias Rönnblom RTE_LCORE_VAR_LCORE(lcore_id, rand_state); 90*29c39cd3SMattias Rönnblom 91*29c39cd3SMattias Rönnblom __rte_srand_lfsr258(seed + lcore_id, lcore_state); 92*29c39cd3SMattias Rönnblom } 93*29c39cd3SMattias Rönnblom 94*29c39cd3SMattias Rönnblom __rte_srand_lfsr258(seed + lcore_id, &unregistered_rand_state); 9599a2dd95SBruce Richardson } 9699a2dd95SBruce Richardson 9799a2dd95SBruce Richardson static __rte_always_inline uint64_t 9899a2dd95SBruce Richardson __rte_rand_lfsr258_comp(uint64_t z, uint64_t a, uint64_t b, uint64_t c, 9999a2dd95SBruce Richardson uint64_t d) 10099a2dd95SBruce Richardson { 10199a2dd95SBruce Richardson return ((z & c) << d) ^ (((z << a) ^ z) >> b); 10299a2dd95SBruce Richardson } 10399a2dd95SBruce Richardson 10499a2dd95SBruce Richardson /* Based on L’Ecuyer, P.: Tables of maximally equidistributed combined 10599a2dd95SBruce Richardson * LFSR generators. 10699a2dd95SBruce Richardson */ 10799a2dd95SBruce Richardson 10899a2dd95SBruce Richardson static __rte_always_inline uint64_t 10999a2dd95SBruce Richardson __rte_rand_lfsr258(struct rte_rand_state *state) 11099a2dd95SBruce Richardson { 11199a2dd95SBruce Richardson state->z1 = __rte_rand_lfsr258_comp(state->z1, 1UL, 53UL, 11299a2dd95SBruce Richardson 18446744073709551614UL, 10UL); 11399a2dd95SBruce Richardson state->z2 = __rte_rand_lfsr258_comp(state->z2, 24UL, 50UL, 11499a2dd95SBruce Richardson 18446744073709551104UL, 5UL); 11599a2dd95SBruce Richardson state->z3 = __rte_rand_lfsr258_comp(state->z3, 3UL, 23UL, 11699a2dd95SBruce Richardson 18446744073709547520UL, 29UL); 11799a2dd95SBruce Richardson state->z4 = __rte_rand_lfsr258_comp(state->z4, 5UL, 24UL, 11899a2dd95SBruce Richardson 18446744073709420544UL, 23UL); 11999a2dd95SBruce Richardson state->z5 = __rte_rand_lfsr258_comp(state->z5, 3UL, 33UL, 12099a2dd95SBruce Richardson 18446744073701163008UL, 8UL); 12199a2dd95SBruce Richardson 12299a2dd95SBruce Richardson return state->z1 ^ state->z2 ^ state->z3 ^ state->z4 ^ state->z5; 12399a2dd95SBruce Richardson } 12499a2dd95SBruce Richardson 12599a2dd95SBruce Richardson static __rte_always_inline 12699a2dd95SBruce Richardson struct rte_rand_state *__rte_rand_get_state(void) 12799a2dd95SBruce Richardson { 1287ea0ac41SMattias Rönnblom unsigned int idx; 12999a2dd95SBruce Richardson 1307ea0ac41SMattias Rönnblom idx = rte_lcore_id(); 13199a2dd95SBruce Richardson 1327ea0ac41SMattias Rönnblom if (unlikely(idx == LCORE_ID_ANY)) 133*29c39cd3SMattias Rönnblom return &unregistered_rand_state; 13499a2dd95SBruce Richardson 135*29c39cd3SMattias Rönnblom return RTE_LCORE_VAR(rand_state); 13699a2dd95SBruce Richardson } 13799a2dd95SBruce Richardson 13899a2dd95SBruce Richardson uint64_t 13999a2dd95SBruce Richardson rte_rand(void) 14099a2dd95SBruce Richardson { 14199a2dd95SBruce Richardson struct rte_rand_state *state; 14299a2dd95SBruce Richardson 14399a2dd95SBruce Richardson state = __rte_rand_get_state(); 14499a2dd95SBruce Richardson 14599a2dd95SBruce Richardson return __rte_rand_lfsr258(state); 14699a2dd95SBruce Richardson } 14799a2dd95SBruce Richardson 14899a2dd95SBruce Richardson uint64_t 14999a2dd95SBruce Richardson rte_rand_max(uint64_t upper_bound) 15099a2dd95SBruce Richardson { 15199a2dd95SBruce Richardson struct rte_rand_state *state; 15299a2dd95SBruce Richardson uint8_t ones; 15399a2dd95SBruce Richardson uint8_t leading_zeros; 15499a2dd95SBruce Richardson uint64_t mask = ~((uint64_t)0); 15599a2dd95SBruce Richardson uint64_t res; 15699a2dd95SBruce Richardson 15799a2dd95SBruce Richardson if (unlikely(upper_bound < 2)) 15899a2dd95SBruce Richardson return 0; 15999a2dd95SBruce Richardson 16099a2dd95SBruce Richardson state = __rte_rand_get_state(); 16199a2dd95SBruce Richardson 1623d4e27fdSDavid Marchand ones = rte_popcount64(upper_bound); 16399a2dd95SBruce Richardson 16499a2dd95SBruce Richardson /* Handle power-of-2 upper_bound as a special case, since it 16599a2dd95SBruce Richardson * has no bias issues. 16699a2dd95SBruce Richardson */ 16799a2dd95SBruce Richardson if (unlikely(ones == 1)) 16899a2dd95SBruce Richardson return __rte_rand_lfsr258(state) & (upper_bound - 1); 16999a2dd95SBruce Richardson 17099a2dd95SBruce Richardson /* The approach to avoiding bias is to create a mask that 17199a2dd95SBruce Richardson * stretches beyond the request value range, and up to the 17299a2dd95SBruce Richardson * next power-of-2. In case the masked generated random value 17399a2dd95SBruce Richardson * is equal to or greater than the upper bound, just discard 17499a2dd95SBruce Richardson * the value and generate a new one. 17599a2dd95SBruce Richardson */ 17699a2dd95SBruce Richardson 1773d4e27fdSDavid Marchand leading_zeros = rte_clz64(upper_bound); 17899a2dd95SBruce Richardson mask >>= leading_zeros; 17999a2dd95SBruce Richardson 18099a2dd95SBruce Richardson do { 18199a2dd95SBruce Richardson res = __rte_rand_lfsr258(state) & mask; 18299a2dd95SBruce Richardson } while (unlikely(res >= upper_bound)); 18399a2dd95SBruce Richardson 18499a2dd95SBruce Richardson return res; 18599a2dd95SBruce Richardson } 18699a2dd95SBruce Richardson 1870cd10724SStephen Hemminger double 1880cd10724SStephen Hemminger rte_drand(void) 1890cd10724SStephen Hemminger { 1900cd10724SStephen Hemminger static const uint64_t denom = (uint64_t)1 << 53; 1910cd10724SStephen Hemminger uint64_t rand64 = rte_rand(); 1920cd10724SStephen Hemminger 1930cd10724SStephen Hemminger /* 1940cd10724SStephen Hemminger * The double mantissa only has 53 bits, so we uniformly mask off the 1950cd10724SStephen Hemminger * high 11 bits and then floating-point divide by 2^53 to achieve a 1960cd10724SStephen Hemminger * result in [0, 1). 1970cd10724SStephen Hemminger * 1980cd10724SStephen Hemminger * We are not allowed to emit 1.0, so denom must be one greater than 1990cd10724SStephen Hemminger * the possible range of the preceding step. 2000cd10724SStephen Hemminger */ 2010cd10724SStephen Hemminger 2020cd10724SStephen Hemminger rand64 &= denom - 1; 2030cd10724SStephen Hemminger return (double)rand64 / denom; 2040cd10724SStephen Hemminger } 2050cd10724SStephen Hemminger 20699a2dd95SBruce Richardson static uint64_t 20799a2dd95SBruce Richardson __rte_random_initial_seed(void) 20899a2dd95SBruce Richardson { 20999a2dd95SBruce Richardson #ifdef RTE_LIBEAL_USE_GETENTROPY 21099a2dd95SBruce Richardson int ge_rc; 21199a2dd95SBruce Richardson uint64_t ge_seed; 21299a2dd95SBruce Richardson 21399a2dd95SBruce Richardson ge_rc = getentropy(&ge_seed, sizeof(ge_seed)); 21499a2dd95SBruce Richardson 21599a2dd95SBruce Richardson if (ge_rc == 0) 21699a2dd95SBruce Richardson return ge_seed; 21799a2dd95SBruce Richardson #endif 21899a2dd95SBruce Richardson #ifdef __RDSEED__ 21999a2dd95SBruce Richardson unsigned int rdseed_low; 22099a2dd95SBruce Richardson unsigned int rdseed_high; 22199a2dd95SBruce Richardson 22299a2dd95SBruce Richardson /* first fallback: rdseed instruction, if available */ 22399a2dd95SBruce Richardson if (_rdseed32_step(&rdseed_low) == 1 && 22499a2dd95SBruce Richardson _rdseed32_step(&rdseed_high) == 1) 22599a2dd95SBruce Richardson return (uint64_t)rdseed_low | ((uint64_t)rdseed_high << 32); 22699a2dd95SBruce Richardson #endif 22799a2dd95SBruce Richardson /* second fallback: seed using rdtsc */ 22899a2dd95SBruce Richardson return rte_get_tsc_cycles(); 22999a2dd95SBruce Richardson } 23099a2dd95SBruce Richardson 23199a2dd95SBruce Richardson RTE_INIT(rte_rand_init) 23299a2dd95SBruce Richardson { 23399a2dd95SBruce Richardson uint64_t seed; 23499a2dd95SBruce Richardson 235*29c39cd3SMattias Rönnblom RTE_LCORE_VAR_ALLOC(rand_state); 236*29c39cd3SMattias Rönnblom 23799a2dd95SBruce Richardson seed = __rte_random_initial_seed(); 23899a2dd95SBruce Richardson 23999a2dd95SBruce Richardson rte_srand(seed); 24099a2dd95SBruce Richardson } 241