Unable to listen to all ip addresses on the subnet on stm32

Post here first, or if you can't find a relevant section!
Vikranth.R
Posts: 6
Joined: Thu Oct 06, 2022 8:34 pm

Unable to listen to all ip addresses on the subnet on stm32

Post by Vikranth.R »

I have connected a STM32(NUCLEO-F767ZI) to my laptop via ethernet cable. The IP address of laptop ethernet is 169.252.72.123 with a subnet mask of 255.255.0.0.
When I bind my ethernet to 0.0.0.0 it must listen to all ip address in the subnet i.e. 169.252.72.123/16. i.e. when i send data from my laptop to say 169.252.72.155 on port 1024, STM32 must receive the data. But this is not happening. (as per my understanding binding to 0.0.0.0 is equivalent to binding to INADDR_ANY in udp.h)
However, when I use a particular ip address, say IPAddress ip(169,252,72,24); and Ethernet.begin on this ip (rest of the parameters mac, dns, gateway, subnet and port same as in below code) and send data from my laptop to this particular ip 169.252.72.24 on port 1024, then STM32 correctly receives the data.
How can i listen to all ip address on the subnet so that I can receive data on stm32 when my laptop sends data on any of the 169.252.72.123/16 addresses

On arduino IDE, I have the following code and loaded it onto the STM32

Code: Select all

#include <LwIP.h>
#include <STM32Ethernet.h>
#include <EthernetUdp.h>   

byte mac[] = { 0xAB, 0xCD, 0xEF, 0xFE, 0xCD, 0xAB };
IPAddress ip(0,0,0,0);
IPAddress dns(169,252,1,1);
IPAddress gateway(169,252,1,1);
IPAddress subnet(255,255,0,0);
EthernetUDP Udp;
unsigned int stm32localport = 1024; 
char packetBuffer[200]; //max 200 byte pkt; can be changed

void setup() {
  Serial.begin(115200);
   while (!Serial) {
    ; // wait for serial port to connect. 
  }
  Ethernet.begin(mac, ip, dns, gateway, subnet);
  Udp.begin(stm32localport);
}

void loop() {
  // if there's data available, read a packet

  int packetSize = Udp.parsePacket();
  if (packetSize) {
  Udp.read(packetBuffer, packetSize);
  Serial.println(packetBuffer);
 }
}
On the laptop, I have a simple python code to send a message:

Code: Select all

import socket
UDP_IP = "169.252.72.155"
UDP_PORT = 1024
MESSAGE = "Hello"
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.sendto(bytes(MESSAGE, "utf-8"), (UDP_IP, UDP_PORT))
Last edited by Vikranth.R on Fri Oct 07, 2022 2:50 am, edited 1 time in total.
GonzoG
Posts: 403
Joined: Wed Jan 15, 2020 11:30 am
Answers: 27
Location: Prudnik, Poland

Re: Unable to listen to all ip addresses on the subnet on stm32

Post by GonzoG »

It won't work. 169.252.72.555 is not a valid IP address.
Vikranth.R
Posts: 6
Joined: Thu Oct 06, 2022 8:34 pm

Re: Unable to listen to all ip addresses on the subnet on stm32

Post by Vikranth.R »

Its a typo. It should be 155, not 555. Ive corrected it on the question itself.

PS: In the question I had wrongly input 169.252.72.555 which is not valid. Later after it was pointed it was not a valid ip address, i corrected my typo and made it 169.252.72.155 in the question itself,
The main question still remains
GonzoG
Posts: 403
Joined: Wed Jan 15, 2020 11:30 am
Answers: 27
Location: Prudnik, Poland

Re: Unable to listen to all ip addresses on the subnet on stm32

Post by GonzoG »

Ehternet does not work like this. Normally a network device receives only data meant for this device.
Packets for other devices are dropped. You'll probably need to use HAL or LL to get all packets on the network.
Vikranth.R
Posts: 6
Joined: Thu Oct 06, 2022 8:34 pm

Re: Unable to listen to all ip addresses on the subnet on stm32

Post by Vikranth.R »

Actually if we check the file EthernetUdp.cpp in the STM32Ethernet library
(https://github.com/stm32duino/STM32Ethe ... netUdp.cpp) it has two functions like :
  • uint8_t EthernetUDP::begin(uint16_t port)
  • uint8_t EthernetUDP::begin(IPAddress ip, uint16_t port, bool multicast)
Now when I call Udp.bind(localPort), it calls the first function above. This inturn calls:
  • return begin(Ethernet.localIP(), port);
Now because I have used Ethernet.begin(mac, "0.0.0.0", myDns, gateway, subnet) before calling Udp.bind(localPort) in the code, my Ethernet.localIP() is 0.0.0.0. Thus it is same as calling Udp.bind(ip,localPort,1) i.e. bool multicast=1. When multicast is 1, the function call inturn becomes :
  • udp_bind(_udp.pcb, IP_ADDR_ANY, port); (function definition is in EthernetUdp.cpp)
IP_ADDR_ANY value is "0x00000000" and the explanation(just google IP_ADDR_ANY and many references will pop up; I have put wikipedia reference below) is that the connection will receive from any IP addresses in the network. Infact I even tried by using Udp.bind("0.0.0.0",localPort,1) i.e. calling by using multicast =1 and still I can't listen to any ip address. (Please note that when I call Udp.bind("0.0.0.0",localPort,1), the first argument "0.0.0.0" is irrelevant, as the function inside checks if multicast==1 (i.e. the3rd argument) and inturn calls udp_bind(_udp.pcb, IP_ADDR_ANY, port); A look inside EthernetUdp.cpp will be helpful)

Reference : https://en.wikipedia.org/wiki/0.0.0.0

Appreciate anyone helping to explain why I can't bind to any ip address over the network/subnet and what i should do to listen to any ip address
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Unable to listen to all ip addresses on the subnet on stm32

Post by ag123 »

https://en.wikipedia.org/wiki/0.0.0.0
In the Internet Protocol Version 4, the address 0.0.0.0 is a non-routable meta-address used to designate an invalid, unknown or non-applicable target. It may also be used for when the client is offline
this means, you need to patch an IP address if you want to be on the network
and on top of that the IP address must have a netmask on the local subnet e.g. 192.168.0.100 mask 255.255.255.0 or some such setup
and it needs to have a routing table e.g.

Code: Select all

192.168.0.0 mask 255.255.255.0 eth0
0.0.0.0 gw 192.168.0.1 default - this is the default route
and your ethernet will only receive IP traffic addressed to *one and only one IP address* e.g. 192.168.0.100 and nowhere else.

if you don't have a valid IP address, the usual ways are DHCP
https://www.ietf.org/rfc/rfc2131.txt - this is likely superseded, find the relevant rfcs
or the even older BOOTP
https://datatracker.ietf.org/doc/html/rfc951

it is unlikely your stm32 libraries and all have a full IP stack, and you probably need to implement BOOTP and DHCP (client) yourself

for true IP stuff, you would need to use a cortex A type CPU e.g. STM32MP1, it needs to be a full blown computer and it needs to run Linux
IP stacks on microcontrollers can never do what a full featured cpu does, to do that you need megabytes of ram (if you implement that by using external dram (e.g. sdram) on the microcontroller *board*, chances are that you may be able to do it) and megabytes of flash - e.g. if you use external flash you may be able to do it.
and last but not least, you may need to rewrite the whole IP stack on the microcontroller to just do that.

tcp/ip is 'simple':
if you have an ip packet, mask it against the netmask, if it looks like 192.168.0.0 place it on eth0, the relevant receiving station will pick it up.
if it doesn't look like the above route, send it to the default route by the gateway, i.e. the gateway has to be the *know it all* (i.e. router) and the gateway does all the routing from there.
if it doesn't even have a gateway, then it is simply *network unreachable*, it did not even matter what ip address you specify
Last edited by ag123 on Fri Oct 07, 2022 5:19 pm, edited 2 times in total.
Vikranth.R
Posts: 6
Joined: Thu Oct 06, 2022 8:34 pm

Re: Unable to listen to all ip addresses on the subnet on stm32

Post by Vikranth.R »

In the same wiki page "https://en.wikipedia.org/wiki/0.0.0.0" it is written
"In the context of servers, 0.0.0.0 can mean "all IPv4 addresses on the local machine". If a host has two IP addresses, 192.168.1.1 and 10.1.2.1, and a server running on the host is configured to listen on 0.0.0.0, it will be reachable at both of those IP addresses".

This is exactly what I want. In my case my STM32 is connected via ethernet to the laptop which is on ip 169.252.72.123/16 I need my STM32 to be reachable at all IP addresses in the subnet mask (i.e. all 2^16 IP addresses). Also, in the code I have alread used Ethernet.begin(mac, ip, dns, gateway, subnet) after defining the arguments i.e.

Code: Select all

byte mac[] = { 0xAB, 0xCD, 0xEF, 0xFE, 0xCD, 0xAB };
IPAddress ip(0,0,0,0);
IPAddress dns(169,252,1,1);
IPAddress gateway(169,252,1,1);
IPAddress subnet(255,255,0,0);
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Unable to listen to all ip addresses on the subnet on stm32

Post by ag123 »

it didn't matter about specs, the IP stack on your microcontroller probably don't have all those features.
if you need a routable IP address, get that ip address using DHCP or maybe BOOTP
(most of the time using DHCP would put you on the correct subnet)
another simple common way is to patch a *fixed* static address with masks and route(s), this has been the most common way to put a device/host on the network. this is also known as the 'manual' way and is perhaps the 'simplest' for a network that you can manually define for all the devices and hosts on the network.

that is the *standard* way for all networks to work, even simple *home* networks to large corporate networks to the whole internet

and these are not the only protocols, there is DNS and mDNS
https://www.rfc-editor.org/rfc/rfc6762
mDNS is commonly used by 'iot' devices to announce their hostnames so that hosts e.g. PCs on the same network segment can find them.
here is how esp8266 does it
https://tttapa.github.io/ESP8266/Chap08%20-%20mDNS.html
the thing is you need to create a whole IP stack to have all that DHCP, BOOTP, DNS, mDNS, HTTP, HTTPS, SSL, FTP, SSH, etc, etc, etc
and if you need to run servers for all those services a simple RPi has *gigabytes* of memory runs Linux and can do all those things

on a microcontroller, it is up to you to try to stretch your ip capabilities as far as the little ip stack, the extremely limited sram and flash takes you.
chances are that if the ip stack don't even have DHCP or BOOTP, you may need to write/code it yourself.

and last but not least, it is ipv6 these days. most microcontrollers ip stacks may not even have it

----
out of curiosity I took a look at this
https://www.arduino.cc/reference/en/libraries/ethernet/
and this
https://github.com/stm32duino/STM32Ethernet
the interface is pretty basic as far as ip features are provided
if it don't have DHCP, then the *static ip address and route* also known as manual way is probably the way to go.

and a search further down it seemed it has some rudimentary DHCP support
https://www.arduino.cc/reference/en/lib ... net.begin/
so you may like to try those if you need DHCP to get an ip address.
GonzoG
Posts: 403
Joined: Wed Jan 15, 2020 11:30 am
Answers: 27
Location: Prudnik, Poland

Re: Unable to listen to all ip addresses on the subnet on stm32

Post by GonzoG »

There is no such thing as "universal IP address" that will listen to all traffic.
There is also another thing - you're sending data over ethernet, that has own way of transmitting data. Ethernet uses MAC addresses and any frame that isn't addressed to a device is dropped.
Even if NIC won't drop other frames, library you use probably filters any unwanted traffic and gives you only what is meant for your device.
Vikranth.R
Posts: 6
Joined: Thu Oct 06, 2022 8:34 pm

Re: Unable to listen to all ip addresses on the subnet on stm32

Post by Vikranth.R »

I went through your explanations and based on them I understand that my computer (python) program that send's data to STM32 MUST bind to a specific address within its ethernet subnet mask i.e. any one of the 169.252.72.123/16 in my case. This is because there is no IP stack on the STM32 to read data from any of the 2^16 IP addresses in 169.252.72.123/16 range.

However, Could anyone explain what err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT); is doing in the following file
https://github.com/STMicroelectronics/S ... hoserver.c

The above is STM32CubeF2 IDE library for ethernet connection. The explanation says "Using IP_ADDR_ANY allow the upcb to be used by any local interface" which is same as using a "universal IP" address that will listen to all traffic. Is it that the STM32 Ethernet library that I am using on Arduino IDE does not support this, but the above library for STM32 Cube will support listening to all traffic because the above implements the IP stack that @ag123 was explaining before?
Post Reply

Return to “General discussion”