Port, board and/or hardware
pico2w
MicroPython version
v1.29.0
Reproduction
Build with USB-NCM enabled and run this on a Pico W/Pico 2 W:
import network
# Brings up the SoftAP - own DHCP server on 192.168.4.0/24.
ap = network.WLAN(network.AP_IF)
ap.config(ssid="repro-ap", password="testtest", security=network.WLAN.SEC_WPA_WPA2)
ap.active(True)
print("AP up:", ap.ifconfig()) # ('192.168.4.1', '255.255.255.0', ...)
# Brings up USB-NCM - its own separate DHCP server on a MAC-derived
# 169.254.x.0/16 pool, active unconditionally regardless of WiFi mode.
nic = network.USBD_NCM()
nic.active(True)
print("USB-NCM up:", nic.ifconfig()) # ('169.254.X.1', '255.255.0.0', ...)
Then connect any WiFi client (phone/laptop) to repro-ap. Expected: the client gets a 192.168.4.x lease. Actual: the client gets a 169.254.X.y lease (confirm via the client's own reported gateway/DNS, which will read back as the USB-NCM interface's own 169.254.X.1 address) and cannot reach 192.168.4.1.
Expected behaviour
Get an IP-Address in the 192.168.0.0/16 range
Observed behaviour
Getting a local link 169.254 IP via the WiFi AP DHCP, which is identical to the one on the USB-NCM
Additional Information
Suggested fix
Scope each DHCP server's UDP PCB to its own interface with the existing udp_bind_netif() API, so lwIP's first-line netif check in udp_input_local_match() (if (pcb->netif_idx != NETIF_NO_INDEX && pcb->netif_idx != netif_get_index(current_input_netif)) return 0;) rejects it outright for any broadcast arriving on a different interface:
Add a struct netif *netif parameter to dhcp_server_init() (shared/netutils/dhcpserver.h/.c).
In dhcp_server_init(), after dhcp_socket_bind()'s udp_bind() call, add udp_bind_netif(d->udp, netif);.
Update both call sites to pass their own netif:
extmod/network_cyw43.c's AP-mode cyw43_cb_tcpip_init() path (in lib/cyw43-driver/src/cyw43_lwip.c) — pass n (the netif it just created).
extmod/network_usbd_ncm.c's ncm_init() — pass &ncm_obj.netif.
This keeps both DHCP servers fully functional and correctly isolated to their own interface, rather than requiring either one to be disabled to avoid the collision.
Code of Conduct
Yes, I agree
Port, board and/or hardware
pico2w
MicroPython version
v1.29.0
Reproduction
Build with USB-NCM enabled and run this on a Pico W/Pico 2 W:
Then connect any WiFi client (phone/laptop) to repro-ap. Expected: the client gets a 192.168.4.x lease. Actual: the client gets a 169.254.X.y lease (confirm via the client's own reported gateway/DNS, which will read back as the USB-NCM interface's own 169.254.X.1 address) and cannot reach 192.168.4.1.
Expected behaviour
Get an IP-Address in the 192.168.0.0/16 range
Observed behaviour
Getting a local link 169.254 IP via the WiFi AP DHCP, which is identical to the one on the USB-NCM
Additional Information
Suggested fix
Scope each DHCP server's UDP PCB to its own interface with the existing udp_bind_netif() API, so lwIP's first-line netif check in udp_input_local_match() (if (pcb->netif_idx != NETIF_NO_INDEX && pcb->netif_idx != netif_get_index(current_input_netif)) return 0;) rejects it outright for any broadcast arriving on a different interface:
Add a struct netif *netif parameter to dhcp_server_init() (shared/netutils/dhcpserver.h/.c).
In dhcp_server_init(), after dhcp_socket_bind()'s udp_bind() call, add udp_bind_netif(d->udp, netif);.
Update both call sites to pass their own netif:
extmod/network_cyw43.c's AP-mode cyw43_cb_tcpip_init() path (in lib/cyw43-driver/src/cyw43_lwip.c) — pass n (the netif it just created).
extmod/network_usbd_ncm.c's ncm_init() — pass &ncm_obj.netif.
This keeps both DHCP servers fully functional and correctly isolated to their own interface, rather than requiring either one to be disabled to avoid the collision.
Code of Conduct
Yes, I agree