Skip to main content
Ivan Pletnev
Associate II
March 3, 2021
Solved

LWIP. Is there STM32CubeMX friendly way to define LWIP_RAND?

  • March 3, 2021
  • 5 replies
  • 3292 views

Hello everybody!

LWIP has a possibility to assign new port number every time after reboot the device. There is define in cc.h

#define LWIP_RAND() ((u32_t)rand())

But it does not work properly. Every time after reboot I get same port number. For solve this, I defined in lwipopts.h:

#define LWIP_RAND() ((u32_t)(HAL_RNG_GetRandomNumber(&hrng)%16384+49152))

But compiler shown me warnings about redefine LWIP_RAND(). And I was forced to change the code in cc.h. CubeMX will overwrite this changes at next code generation. How to fix it?

This topic has been closed for replies.
Best answer by Piranha

https://en.cppreference.com/w/c/numeric/random/rand

The rand() is a pseudo-random generator and also needs a startup seed value.

LWIP_RAND has to provide a random 32-bit value, not force it to some specific range. Look at the actual lwIP code! It does adjust the values to specific ranges internally where necessary. And LWIP_RAND is used not only for port numbers!

5 replies

Technical Moderator
March 4, 2021

Hello @Ivan Pletnev​ ,

Which device and STM32CubeMX version are you using ?

Imen

"When your question is answered, please close this topic by clicking ""Accept as Solution"".ThanksImen"
Ivan Pletnev
Associate II
March 4, 2021

Hello! I am using STM32F427 and STM32CubeIDE Version 1.6.0

Piranha
PiranhaBest answer
Principal III
March 6, 2021

https://en.cppreference.com/w/c/numeric/random/rand

The rand() is a pseudo-random generator and also needs a startup seed value.

LWIP_RAND has to provide a random 32-bit value, not force it to some specific range. Look at the actual lwIP code! It does adjust the values to specific ranges internally where necessary. And LWIP_RAND is used not only for port numbers!

Ivan Pletnev
Associate II
March 6, 2021

This is strange a bit, but now everything works fine! With standard rand() function. I removed my randomizer code and bind() from client and everything works. Ports now assigning by LWIP properly. Thank you a lot!

QNguy.5
Visitor II
July 7, 2021

Hello

I downloaded the LWIP for F7 from https://github.com/hnkr/stm32_lwip, and try to run the code on nucleo-f767zi board. The cubeMxIDE can compiler and load the hex file the the board, howerver, I can't ping the boad and there is no Led blinking.

I tried to debug on-line step by step and found out that the software stuck at the line: LWIP_RAND() ((u32_t)rand()). It just stuck there and the software seems to be running in the infinite loop.

If I commented out the the LWIP_RAND() ((u32_t)rand()), and give the hard code number to rand() return, for example 23, the software can pass through and I can see the Led blinking writing by  

for(;;)

 {

 HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);

 osDelay(250);

 }

Still, I can't ping the board.

I am stuck at the problem for nearly 3 days, please give me some advice ?

Thanks in advance

JMarq.1
Associate III
June 2, 2023

Hi @Ivan Pletnev​ ,

I faced the same problem. LwIP uses rand() function in tcp_init(). As Piranha pointed, unless srand() is called passing as parameter a "best-effort" system random value prior to call tcp_init(), you will get always the same TCP port initial value.

To avoid this, I feel that LwIP should call srand() itself during LWIP_init() process, but probably was thought that this might have side effects on random usage in application code, so is up to the application developer where and how to call srand().

I created a routine init_random_TCPport() to solve this issue, calling tcp_init() again after lwip_init(); and my own initialization to srand() using RTC value. I am not sure whether tcp_init() can be called as many times as you need or it might be dangerous. Looking at LwIP source code, it is not in my opinion.

#include "tcp_priv.h" // tcp_init()
 
// In order to get a different TCP port at every startup:
// · Set random seed using srand() with a "best-effort" random value from the system (systicks, RTC values, AC A/D value, ???)
// · Reinitialize global variable tcp_port in LwIP calling tcp_init()
static void init_random_TCPport(void)
{
 //srand(HAL_GetTick()); // Not valid if init_random_TCPport(); is called at a deterministic point in code at each startup (quite often returns the same value)
 RTCTime t = RTCGetTime(); // Use a value from RTC time instead. RTC value kept using an external battery in backup RAM.
 srand((t.Minutes << 8) | t.Seconds);
 tcp_init(); // Re-seed tcp_port value in LwIP
}
 
int main(void)
{
 // some init code
 MX_LWIP_Init(); // lwip_init();
 // some code prior to network connections
 init_random_TCPport();
 // some code using network connections
}
 
 

Although this is working to me, I feel this is an ugly solution. Accessing a tcp_priv.h function in application code smells bad to me.... I would like to know how other community users solved this.

I was expecting from LwIP a second configuration parameter apart of LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS, something like i.e. LWIP_RANDOMIZE_SEED that was setting srand() to a LwIP generated random value inside lwip_init(), but I haven't found anything like that yet....

Thanks!