esp32: UDP sendto causes memory leaks/ENOMEM error for most IP addresses
I'm trying to send UDP packets using socket.sendto(). I would expect this to succeed regardless of the destination IP address, but for most addresses this fails after exactly four packets with OSError ENOMEM. I do not see this exception when sending to the board's own IP or the broadcast address.
Hardware: ESP32 on an Olimex ESP32-PoE-ISO board, connected to a switch that has nothing else connected to it (as a minimal test setup).
ESPtool identifies the chip as ESP32D0WDQ5 (revision 3).
Firmware: OLIMEX_ESP32_POE-20231005-v1.21.0.bin
Version in REPL: MicroPython v1.21.0 on 2023-10-06; Olimex ESP32 ETH with ESP32
#4029 is a similar issue but uses WiFi and instead affects broadcast only. I'm seeing the opposite behavior.
This code example attempts to send 100 packets to IPs from 192.168.4.0 through to 192.168.4.255. This succeeds for IPs 192.168.4.250 (the board's own IP) and 192.168.4.255 (broadcast) but fails for every other address after the fourth attempt with OSError 12, ENOMEM.
import socket
import network
import machine
import time
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(12),
phy_type=network.PHY_LAN8720, phy_addr=0)
try:
lan.active(True)
except OSError as ex:
if ex.value == "ethernet enable failed":
print("Failed to enable ethernet - waiting a few seconds and doing a hardware reset.")
time.sleep(2)
machine.reset()
raise
my_ip = '192.168.4.250'
lan.ifconfig((my_ip, '255.255.255.0', '192.168.4.1', '192.168.4.1'))
sock1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock1.bind((my_ip, 10005))
buf = "hello"
port = 10000
for x in range(0, 256):
try:
for test in range(0, 100):
sock1.sendto(buf, (f"192.168.4.{x}", port))
print(f"192.168.4.{x}:{port}: PASS")
except OSError as e:
print(f"192.168.4.{x}:{port}: FAIL after {test+1} attempts with {e}")
Output:
192.168.4.0:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.1:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.2:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.3:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.4:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
...
192.168.4.248:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.249:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.250:10000: PASS
192.168.4.251:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.252:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.253:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.254:10000: FAIL after 4 attempts with [Errno 12] ENOMEM
192.168.4.255:10000: PASS
My next step is to dig into the MicroPython and IDF code, would appreciate any advice on tests to try.
Socket.sendto() never transmitting on ESP32
Hello all,
I'm writing some code in MicroPython for an ESP32-Devkitc-S1 that will need to send and receive UDP packets.
I've tested the code in Jupyter notebooks, and it's capable of both sending and receiving packets with my test socket.
On the ESP32, the same code is able to receive UDP packets just fine, but is incapable of sending packets (I've tried a few dozen times, so it doesn't seem like they're just dropped). The code runs without errors, and sock.sendto returns 17 as I'd expect, but the packets are never received.
I have an access point quite close to me, and the board is able to connect to the wifi without much hassle, so I don't think its an issue with the transmissions being too weak.
Please let me know if you have any suggestions, or if this is a known issue.
import network
import socket
import time
#I only run this on the SoC since my laptop is already connected to the wifi.
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.ifconfig(("192.168.100.102","255.255.255.0","192.168.1.1","8.8.8.8"))
wlan.connect("ap_ssid","ap_pass") #with my actual wifi credentials
def recv_packet(): #works on desktop and on SoC
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("",7777))
print("Waiting...")
data, addr = sock.recvfrom(2048)
print("Received: ", data, "from", addr)
sock.close()
time.sleep(3) #the socket needs time to close or we run out of mem
def send_packet(): #works on desktop, not on SoC
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
data = b'testing in Python'
addr = ("192.168.39.136", 7778) #a UDP socket on my phone to test
sock.sendto(data, addr)
print("Sent: ", data, "to", addr)
sock.close()
time.sleep(3) #the socket needs time to close or we run out of mem