2021-03-03 06:16 AM
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?
Solved! Go to Solution.
2021-03-06 05:20 AM
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!
2021-03-04 05:19 AM
Hello @Ivan Pletnev ,
Which device and STM32CubeMX version are you using ?
Imen
2021-03-04 05:31 AM
Hello! I am using STM32F427 and STM32CubeIDE Version 1.6.0
2021-03-06 05:20 AM
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!
2021-03-06 08:38 AM
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!
2021-07-06 09:12 PM
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
2023-06-02 02:36 AM
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!