UDP Reception Issue in Ethernet Controller Emulation

Problem Description

I've implemented a W5500 Ethernet controller emulation for NRF7002 modules. While UDP socket sending works correctly, receiving UDP packets is problematic. Specifically:

  • UDP echo servers work perfectly (send and receive from udp-echo.nordicsemi.academy). TCP connections work( both send and receive)
  • When receiving data from other UDP servers, packets don't show up but packets are sent succesfully
  • Wireshark captures show the response with "ICMP destination unreachable (port unreachable)" messages

Technical Details

  • The emulation uses Zephyr's socket API (zsock_*) to implement the W5500 socket functionality
  • UDP sockets are created with zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
  • Sockets are bound to their respective ports using zsock_bind()
  • For receiving, I'm using zsock_recvfrom() to properly capture the sender's information
  • The zsock_poll never triggers for a recieve on udp

Wireshark Analysis


272 3104.069937 192.168.137.31 192.168.137.1 ICMP 70 Destination unreachable (Port unreachable)
271 3103.830666 192.168.137.1 192.168.137.31 UDP 75 57560 → 57560 Len=33

The captures show that my PC (192.168.137.1) sends from ephemeral port 57560 to the NRF device on port 5000, but the NRF responds with "Port unreachable" errors. it sends from port 5000 to port 5000 on the PC (this works).

Current Implementation

I'm using a dedicated socket poll thread for receiving:

c
 if ((w5500_regs.sockets[sock_num].mr & 0x0F) == SOCK_MODE_UDP) {
                    struct sockaddr_in sender_addr;
                    socklen_t addr_len = sizeof(sender_addr);
                    
                    ret = zsock_recvfrom(fd, rx_buffer, sizeof(rx_buffer), 
                                        ZSOCK_MSG_DONTWAIT,
                                        (struct sockaddr *)&sender_addr, 
                                        &addr_len);
                    
                    if (ret > 0) {
                        // Log the sender info but don't update W5500 registers
                        uint8_t *sender_ip = (uint8_t*)&sender_addr.sin_addr.s_addr;
                        uint16_t sender_port = ntohs(sender_addr.sin_port);
                        
                        LOG_INF("UDP packet from %d.%d.%d.%d:%d to socket %d (%d bytes)",
                                sender_ip[0], sender_ip[1], sender_ip[2], sender_ip[3],
                                sender_port, sock_num, ret);
                        
                        // Queue the packet for processing
                        rx_queue_packet(sock_num, rx_buffer, ret);
                    }

Questions

  1. Why might the emulation be rejecting incoming UDP packets from non-echo servers?
  2. Is there a specific socket option or configuration needed for proper UDP packet reception?
  3. How do I properly handle the difference between well-known ports and ephemeral ports in this environment?
Parents Reply Children
No Data
Related