RPI PICO W Regression: Setting DNS results in address resolution failure
Port, board and/or hardware
RPI PICO W
MicroPython version
MicroPython v1.24.0-preview.224.g6c3dc0c0b on 2024-08-22; Raspberry Pi Pico W with RP2040
Reproduction
import socket
import network
import asyncio
async def test():
print("Connecting to WiFi...")
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect("---", "---")
while not sta_if.isconnected():
await asyncio.sleep_ms(100)
print("Setting DNS...")
cfg = list(sta_if.ifconfig())
cfg[-1] = "8.8.8.8"
sta_if.ifconfig(cfg)
server, port = "blynk.cloud", 443
print("Resolving IP...")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
addr = socket.getaddrinfo(server, port)[0][-1]
print("Connecting...")
sock.connect(addr)
print("OK")
asyncio.run(test())
Expected behaviour
MicroPython v1.23.0 on 2024-06-02; Raspberry Pi Pico W with RP2040:
MPY: soft reboot
Connecting to WiFi...
Setting DNS...
Resolving IP...
Connecting...
OK
Observed behaviour
MicroPython v1.24.0-preview.224.g6c3dc0c0b on 2024-08-22; Raspberry Pi Pico W with RP2040:
MPY: soft reboot
Connecting to WiFi...
Setting DNS...
Resolving IP...
Traceback (most recent call last):
File "main.py", line 22, in test # socket.getaddrinfo
OSError: -2
Additional Information
No response
Code of Conduct
Yes, I agree
I cannot reproduce the problem using the supplied code, and the referenced commit version. It works fine, does a DNS lookup and connects to the remote host.
But I do notice that the DNS lookup takes longer than expected. With 8.8.8.8 it takes around 6-9 seconds. With the default DNS it takes about 1-2 seconds, sometimes less.
So maybe in your case it's just timing out because it's taking to long?
Note that Pico W now supports IPv6, but DNS lookups still prefer IPv4 by default. You can check this with network.ipconfig('prefer'), and also see if you have an IPv6 address with sta_if.ipconfig('addr6').
I see. Is there any way to change the DNS timeout, so I can confirm? Interestingly, I don't observe the long DNS lookup on 1.23.0, it's as fast as usual.
addr6: [('FE80::2ACD:C1FF:FE0F:1EAA', 48, 0, 0), ('FD73:C90F:6670:0:2ACD:C1FF:FE0F:1EAA', 48, -1, -1)]
prefer: 4
+1, just experienced the -2 error on getaddrinfo when compiling the firmware from master. I also used 8.8.8.8, and it also works fine for me on 1.23.0.
FWIW, the doc says that ifconfig() is deprecated and to use ipconfig(), but ipconfig('dns') does not work on Pico-W.
As for ifconfig, it is marked as deprecated in AbstractNIC, but in implementations, e.g. WLAN, it is not, and the ipconfig isn't even documented there (even though other methods are repeated), which makes the whole deprecation information very easy to miss.
but ipconfig('dns') does not work on Pico-W.
@n1kdo ipconfig.('dns') is available as method of the network class: network.ipconfig(). That's in addition to the ipconfig method of the NIC, like WLAN.ipconfig() and somwhat confusing.
Looks like I cannot reproduce the issue by setting DNS server via:
network.ipconfig(dns='8.8.8.8')
Also, I'm now developing a asyncio-based DNS client to mitigate the blocking nature of socket.getaddrinfo.
Looks working so far on ESP32, Pi Pico W and WM W600.
It should also provide a solution for https://github.com/micropython/micropython/issues/15777
aiodns has been published: https://github.com/vshymanskyy/aiodns
aiodnshas been published
That looks good! We do need a proper solution for DNS lookup in asyncio, it should not be blocking.
@dpgeorge glad you liked it. Maybe you can comment on this please? https://github.com/vshymanskyy/aiodns/issues/3
Got it ! :) it's dev issue, i made same error: do not use ifconfig but ipconfig to handle network conf.
replace your line : sta_if.ifconfig(cfg)
by something like:
sta_if.ipconfig(addr4=(cfg[0],cfg[1]))
sta_if.ipconfig(gw4=cfg[2])
network.ipconfig(dns='8.8.8.8')
-> wlan.ipconfig do not handle dns but network.ipconfig do it.