LWIP-ipv6 handling in Chibios

Use this forum for requesting small changes in ChibiOS. Large changes should be discussed in the development forum. This forum is NOT for support.
louled
Posts: 2
Joined: Fri Apr 07, 2023 8:14 pm

LWIP-ipv6 handling in Chibios

Postby louled » Fri Apr 07, 2023 9:41 pm

Hullo.

Last week, I received a new router from my internet provider. And guess what, it is ipv6 only :( . Really, it has no local ipv4 possibilities at all.
Since I have a few objects running chibios with LWIP, I did try to make them work with ipv6.


I found that it quite lacks of working example in both LWIP and Chibios forums, and we are speaking about the future of internet here.I will not provide a patch, but show the steps I performed to get the ipv6-ping working. I think a few change are in order in Chibios to add the ipv6 support.

I will make a very brief summary about ipv4 and ipv6 change here, as I had only a vague idea about what ipv6 was two weeks ago: that it was using non-human friendly adresses like 1234:5678:1234:567[...] to overcome the ipv4 adress pool starvation.

Let's say a STM32 using LWIP is wired on a home ETH network with a router. In ipv4, it would use DHCP to get an adress and then ARP to make adress related discovery.
Now using ipv6 make it quite different. The STM32 guess an adress (Stateless Address Autoconfiguration, SLAAC), and see using ICMPv6 messages if it is free or not. It doesn't use DHCPv6, nor ARP. My router doesn't implement DHCP statefull, neither does LWIP. If one look into LWIP code, he'll see that DHCPv6 actually only perform DNS and NTP in the current implementation.

I did update to lwip-2.1.3 after having read in the changelog it shipped with ipv6 bug fixes. I kept chibios "2.1.2" bindings. And besides a few missing defines in lwipopts.h, I can say it works well in ipv6.

Those are the options that I added into lwipopts.h:

Code: Select all

#define LWIP_IPV6   1
#define LWIP_ICMP6   1
#define LWIP_IPV6_AUTOCONFIG   1


I modified lwipthread.c THD_FUNCTION as follow:

Code: Select all

ETH->MACFFR |= ETH_MACFFR_PAM; // activate multicast

thisif.flags |= NETIF_FLAG_MLD6; // netif_set_flags(&thisif, NETIF_FLAG_MLD6);
thisif.ip6_autoconfig_enabled = 1;

thisif.output_ip6 = ethip6_output; // so it can send ipv6 packets

// optional, guess an adress using the MAC address, in my case: fe80::XXXX:XXXX:XXXX:4
netif_create_ip6_linklocal_address(&thisif, 1);
netif_ip6_addr_set_state(&thisif, 0, IP6_ADDR_TENTATIVE); // linklocal address

ip6_addr_t my_addr;
//here I hardcoded an ip in my router's local network adress pool range: 2a02:XXXX:XXXX:XXXX::f
IP6_ADDR_PART(&my_addr, 0, 0x2A, 0x02, 0xXX, 0xXX);
IP6_ADDR_PART(&my_addr, 1, 0xXX, 0xXX, 0xXX, 0xXX);
IP6_ADDR_PART(&my_addr, 2, 0x00, 0x00, 0x00, 0x00);
IP6_ADDR_PART(&my_addr, 3, 0x00, 0x00, 0x00, 0x0F);
ip_addr_copy_from_ip6(thisif.ip6_addr[1], my_addr);
netif_ip6_addr_set_state(&thisif, 1, IP6_ADDR_TENTATIVE);

netifapi_netif_set_default(&thisif);
netifapi_netif_set_up(&thisif);


and a few lines below, one has to add ETHTYPE_IPV6, otherwise it never receive any ipv6 packets ;)

Code: Select all

switch (htons(ethhdr->type)) {
   /* IP or ARP packet? */
   case ETHTYPE_IP:
   case ETHTYPE_ARP:
   case ETHTYPE_IPV6:
   /* full packet send to tcpip_thread to process */
   if (thisif.input(p, &thisif) == ERR_OK)


Then in my main.c I do polling on the address to detect when it is assigned and then continue:

Code: Select all

while(netif_default->ip6_addr[1].u_addr.ip4.addr == 0)
   chThdSleepSeconds(1);


Note that DHCP can be tested using:

Code: Select all

#define LWIP_IPV6_DHCP6         1
dhcp6_enable_stateless(&thisif);


Usefull functions from the Chibios forum for serial printing:

Code: Select all

#define LWIP_DEBUG    1
#define LWIP_DBG_MIN_LEVEL   LWIP_DBG_LEVEL_ALL
#define IP6_DEBUG   LWIP_DBG_ON
#define DHCP6_DEBUG   LWIP_DBG_ON

#define U8_F "c"
#define S8_F "c"
#define X8_F "x"
#define U16_F "u"
#define S16_F "d"
#define X16_F "x"
#define U32_F "u"
#define S32_F "d"
#define X32_F "x"

#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#define PRINTFREPLACEMENT(...) chprintf((BaseSequentialStream*) &SD3, __VA_ARGS__) // My STM32 VCOM
#define LWIP_PLATFORM_DIAG(x) do { PRINTFREPLACEMENT x; PRINTFREPLACEMENT("\r\n"); } while (0)


Unfortunately, activating ipv6 break things in my codes, but it is in fact quite limited to ip handling and display. For example servers logs, or screen display in the form should be reworked. Example of former server logs:

Code: Select all

192.168.1.197 - admin [02/Apr/2023:18:54:40 +0200] "GET /adminpanel.html? HTTP/1.1" 200 -


And to finish, the genuine ipv6 ping:

Code: Select all

ping 2A02:XXXX:XXXX:XXXX::F

Envoi d’une requête 'Ping'  2a02:XXXX:XXXX:XXXX::f avec 32 octets de données :
Réponse de 2a02:XXXX:XXXX:XXXX::f : temps<1ms
Réponse de 2a02:XXXX:XXXX:XXXX::f : temps<1ms
Réponse de 2a02:XXXX:XXXX:XXXX::f : temps<1ms
Réponse de 2a02:XXXX:XXXX:XXXX::f : temps<1ms


I think the lwipthread.c should be reworked a bit so it is possible to use ipv4 or ipv4&ipv6 or ipv6, but atm I don't see an EZ way of patching that without breaking the backwards compatibility. But hopefully, it would be "a small change" :D

Best regards,

Simon

User avatar
Giovanni
Site Admin
Posts: 14458
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: LWIP-ipv6 handling in Chibios

Postby Giovanni » Sat Apr 08, 2023 6:05 am

Hi,

Is this breaking IPv4 functionality? I will update lwIP for sure anyway.

Giovanni

louled
Posts: 2
Joined: Fri Apr 07, 2023 8:14 pm

Re: LWIP-ipv6 handling in Chibios

Postby louled » Sat Apr 08, 2023 3:06 pm

Giovanni wrote:Hi,

Is this breaking IPv4 functionality? I will update lwIP for sure anyway.

Giovanni


Hullo.

Everything works with ipv4 as much as I have tested. I'm using mbedtls over LWIP to have https functionalities, and I was able to verify all my objects were working fine in ipv4 while using the ipv4&ipv6 stack mode with my old router before packing it.

To run the dual stack the options are as follow:

Code: Select all

#define LWIP_IPV4   1 // and in lwipopts I had the usual ipv4 modules activated ARP, ICMP, DNS, DHCP, UDP, TCP, SOCK
#define LWIP_IPV6   1
#define LWIP_ICMP6   1
#define LWIP_IPV6_AUTOCONFIG   1


The only changes I had to do is tweak a bit my code to use things like:

Code: Select all

//while(netif_default->ip_addr.addr == 0) // ivp4 only
while(netif_default->ip_addr.u_addr.ip4.addr == 0) // ipv4&ipv6 or ipv6
        chThdSleepSeconds(1);

To wait until the ipv4 was getting allocated by the DHCPv4 module

That's where is the biggest difficulty I guess.
The ip_addr_t structure is changing a bit if we add LWIP_IPV6 or not. Maybe the need of ip4_addr_t usage will be required, but I don't think one could avoid this without using plenty #ifdef everywhere a generic ip_addr_t was used.

Best regards,

Simon


Return to “Small Change Requests”

Who is online

Users browsing this forum: No registered users and 3 guests