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"
Best regards,
Simon