RIOT-OS / RIOT

RIOT - The friendly OS for IoT
https://riot-os.org
GNU Lesser General Public License v2.1
4.92k stars 1.99k forks source link

test/lwip: enabling both, IPv4 and IPv6, results in unexpected behavior #18097

Open OlegHahm opened 2 years ago

OlegHahm commented 2 years ago

Description

When enabling IPv4 and IPv6 for the lwip test application, some values will default to IPv6.

For example, the formatting of IP addresses will always expect IPv6 addresses and a socket will default to IPv6.

One reason is that in common.h you find

 #if IS_USED(MODULE_LWIP_IPV6)                                                                                           
 #include "net/ipv6.h"                                                                                                   
 #define SOCK_IP_EP_ANY  SOCK_IPV6_EP_ANY                                                                                
 #elif IS_USED(MODULE_LWIP_IPV4)                                                                                         
 #include "net/ipv4.h"                                                                                                   
 #define SOCK_IP_EP_ANY  SOCK_IPV4_EP_ANY                                                                                
 #endif 

Hence, SOCK_IP_EP_ANY is set to IPv6 only.

An interesting observation that may lead to an actual bug in the network stack is that IPv4 datagrams are received on the IPv6 only socket nevertheless.

Steps to reproduce the issue

Build the lwip test application with LWIP_IPV4=1. Add something like

#define _TEST_ADDR4_LOCAL  (0x974fa8c0U)   /* 192.168.79.150 */
#define _TEST_ADDR4_MASK   (0x00ffffffU)   /* 255.255.255.0 */
sys_lock_tcpip_core();
struct netif *iface = netif_find("ET0");
ip4_addr_t ip, subnet;
ip.addr = _TEST_ADDR4_LOCAL;
subnet.addr = _TEST_ADDR4_MASK;
netif_set_addr(iface, &ip, &subnet, NULL);
sys_unlock_tcpip_core();

at the beginning of the main function and add something like

sock_udp_send(sock, sock_inbuf, res, &src);

to the _udp_recv() function to echo the received datagram.

Build the application on native and assign a matching IPv4 address to the bridge, e.g., sudo ip a a 192.168.79.151/24 dev tapbr0 Start the application, start a UDP server and use netcat to send anything to the server.

Expected results

In netcat one should the sent packet echoed and in the RIOT shell one should see the IPv4 address (e.g., 192.168.79.151) of the sender.

Actual results

The echo fails and an IPv6 formatted address is printed.

Versions

Test on RIOT 2022.04.

Should be irrelenvant but in any case:

Operating System Environment
----------------------------
         Operating System: "Arch Linux" 
                   Kernel: Linux 5.17.5-arch1-1 x86_64 unknown
             System shell: GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
             make's shell: GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)

Installed compiler toolchains
-----------------------------
               native gcc: gcc (GCC) 11.2.0
        arm-none-eabi-gcc: arm-none-eabi-gcc (Arch Repository) 12.1.0
                  avr-gcc: missing
         mips-mti-elf-gcc: missing
           msp430-elf-gcc: missing
       riscv-none-elf-gcc: missing
  riscv64-unknown-elf-gcc: missing
     riscv-none-embed-gcc: missing
     xtensa-esp32-elf-gcc: missing
   xtensa-esp8266-elf-gcc: missing
                    clang: clang version 13.0.1

Installed compiler libs
-----------------------
     arm-none-eabi-newlib: "4.2.0"
      mips-mti-elf-newlib: missing
        msp430-elf-newlib: missing
    riscv-none-elf-newlib: missing
riscv64-unknown-elf-newlib: missing
  riscv-none-embed-newlib: missing
  xtensa-esp32-elf-newlib: missing
xtensa-esp8266-elf-newlib: missing
                 avr-libc: missing (missing)

Installed development tools
---------------------------
                   ccache: ccache version 4.6
                    cmake: cmake version 3.23.1
                 cppcheck: missing
                  doxygen: missing
                      git: git version 2.36.1
                     make: GNU Make 4.3
                  openocd: Open On-Chip Debugger 0.11.0
                   python: Python 3.10.4
                  python2: Python 2.7.18
                  python3: Python 3.10.4
                   flake8: error: /usr/bin/python3: No module named flake8
               coccinelle: missing
yarrick commented 2 years ago

The socket layer might not be ready for dualstack - I would still expect receiving traffic to work though. Can you paste the output you get (from both IPv4 and IPv6 peers when dualstack is enabled for lwIP)?

Can you try reproducing it with normal DHCP instead of the extra code also? (I don't expect that to fix it)

The tests/lwip_sock_udp app has separate IPv4 and IPv6 tests, maybe you can expand it to create a test showing the issue.

OlegHahm commented 2 years ago

The socket layer might not be ready for dualstack - I would still expect receiving traffic to work though. Can you paste the output you get (from both IPv4 and IPv6 peers when dualstack is enabled for lwIP)?

Received UDP data from [fe80::a45d:54ff:fe4f:cdd7]:37768
00000000  61  64  66  61  73  64  0A
Received UDP data from [c0a8:4f98::]:51210
00000000  61  64  66  61  73  64  0A

Can you try reproducing it with normal DHCP instead of the extra code also? (I don't expect that to fix it)

The tests/lwip_sock_udp app has separate IPv4 and IPv6 tests, maybe you can expand it to create a test showing the issue.

Will do later.

OlegHahm commented 2 years ago

Okay, using DHCP didn't make any difference (as expected), but the first try to create a dualstack test failed and I won't have time to work on it during the next days.