#define net_random()           prandom_u32()
 #define net_srandom(seed)      prandom_seed((__force u32)(seed))
 
+bool __net_get_random_once(void *buf, int nbytes, bool *done,
+                          struct static_key *done_key);
+
+#ifdef HAVE_JUMP_LABEL
+#define ___NET_RANDOM_STATIC_KEY_INIT ((struct static_key) \
+               { .enabled = ATOMIC_INIT(0), .entries = (void *)1 })
+#else /* !HAVE_JUMP_LABEL */
+#define ___NET_RANDOM_STATIC_KEY_INIT STATIC_KEY_INIT_FALSE
+#endif /* HAVE_JUMP_LABEL */
+
+/* BE CAREFUL: this function is not interrupt safe */
+#define net_get_random_once(buf, nbytes)                               \
+       ({                                                              \
+               bool ___ret = false;                                    \
+               static bool ___done = false;                            \
+               static struct static_key ___done_key =                  \
+                       ___NET_RANDOM_STATIC_KEY_INIT;                  \
+               if (!static_key_true(&___done_key))                     \
+                       ___ret = __net_get_random_once(buf,             \
+                                                      nbytes,          \
+                                                      &___done,        \
+                                                      &___done_key);   \
+               ___ret;                                                 \
+       })
+
 int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
                   size_t num, size_t len);
 int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
 
                                  csum_unfold(*sum)));
 }
 EXPORT_SYMBOL(inet_proto_csum_replace16);
+
+struct __net_random_once_work {
+       struct work_struct work;
+       struct static_key *key;
+};
+
+static void __net_random_once_deferred(struct work_struct *w)
+{
+       struct __net_random_once_work *work =
+               container_of(w, struct __net_random_once_work, work);
+       if (!static_key_enabled(work->key))
+               static_key_slow_inc(work->key);
+       kfree(work);
+}
+
+static void __net_random_once_disable_jump(struct static_key *key)
+{
+       struct __net_random_once_work *w;
+
+       w = kmalloc(sizeof(*w), GFP_ATOMIC);
+       if (!w)
+               return;
+
+       INIT_WORK(&w->work, __net_random_once_deferred);
+       w->key = key;
+       schedule_work(&w->work);
+}
+
+bool __net_get_random_once(void *buf, int nbytes, bool *done,
+                          struct static_key *done_key)
+{
+       static DEFINE_SPINLOCK(lock);
+
+       spin_lock_bh(&lock);
+       if (*done) {
+               spin_unlock_bh(&lock);
+               return false;
+       }
+
+       get_random_bytes(buf, nbytes);
+       *done = true;
+       spin_unlock_bh(&lock);
+
+       __net_random_once_disable_jump(done_key);
+
+       return true;
+}
+EXPORT_SYMBOL(__net_get_random_once);