cancel
Showing results for 
Search instead for 
Did you mean: 

LWIP. Is there STM32CubeMX friendly way to define LWIP_RAND?

Ivan Pletnev
Associate II

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?

1 ACCEPTED SOLUTION

Accepted Solutions
Piranha
Chief II

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!

View solution in original post

6 REPLIES 6
Imen.D
ST Employee

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".
Thanks
Imen
Ivan Pletnev
Associate II

Hello! I am using STM32F427 and STM32CubeIDE Version 1.6.0

Piranha
Chief II

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!

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
Associate

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

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!