Border Router OTA using WiFi

Do configure a static prefix, you really need cooperation from the upstream router as that prefix will need to be configured to be routed via the address of your host.

To enable a static prefix in the gnrc_border_router example, select PREFIX_CONF=static, set IPV6_PREFIX to the prefix you were assigned and IPV6_ADDR to the address configured as the next hop for the prefix on the router.

Unfortunately interface auto-selection will assume the uplink interface is wired, in your case it’s not, so you’ll also have to set

CFLAGS += -DCONFIG_GNRC_IPV6_STATIC_ADDR_UPSTREAM=<pid>

where <pid> is the interface ID of your upstream interface.

If you can advertise larger prefixes you could also use RIOT’s subnet auto-configuration, but at least Linux will ignore non /64 prefixes for SLAAC, so that won’t work on a general purpose network.

1 Like

That’s excellent news! I see that PD server is on by default. I haven’t seen this in the luci interface, but maybe I’m not running a new enough version. Once I upgrade, and verify this works for me, I’ll try to capture some images for documentation.

How do I find the interface ID of the upstream interface?

Hi. I’ve been away for a while and now decided to come back to try and tackle this problem. I am still unable to figure out how to configure a static prefix. I selected PREFIX_CONF=static and IPV6_PREFIX as 2001:db8:: and IPV6_ADDR as 2001:db8::1. I also set CFLAGS += -DCONFIG_GNRC_IPV6_STATIC_ADDR_UPSTREAM=<pid>. I tried with various pid values, from 1 to 10 but none of them work.

The interface auto-selection is still probably selecting the wired uplink because the ethos “termprog” is still running when I run the terminal and if I try to set UPLINK=wifi manually, I’m running into a “RIOT kernel panic” problem.

Is there anything else I can check or am I doing something wrong here?

You are doing nothing wrong, in fact you have found a two bugs! I see that the address of the failed assertion is not properly printed, but enabling VERBOSE_ASSERT=1 will print the source of the culprit.

See #19854 and #19855 for a simple fix.

With those applied what works for me is

make BOARD=esp32-wroom-32 UPLINK=wifi PREFIX_CONF=static IPV6_PREFIX=2001:db8::/64

with

--- a/examples/gnrc_border_router/Makefile.board.dep
+++ b/examples/gnrc_border_router/Makefile.board.dep
@@ -8,8 +8,12 @@ ifeq (,$(filter native,$(BOARD)))
     ifneq (,$(filter esp32 esp8266,$(CPU)))
       USEMODULE += esp_wifi
       ifneq (ble, $(DOWNLINK))
-        USEMODULE += esp_now
+#        USEMODULE += esp_now
       endif
+      USEMODULE += slipdev_l2addr
+      CFLAGS += -DSLIPDEV_PARAM_UART=UART_DEV\(1\)
+      CFLAGS += -DCONFIG_GNRC_IPV6_STATIC_ADDR_UPSTREAM=8      # netif-esp-wifi
+      CFLAGS += -DCONFIG_GNRC_IPV6_STATIC_ADDR_DOWNSTREAM=9    # slipdev
     else
       $(error Only esp32 and esp8266 are currently supported)
     endif

Mind you that the upstream network and the downstream network can’t have the same prefix, so you can’t have both 2001:db8::1 on the upstream and 2001:db8::/64 on the downstream. But if you want routing to the internet, you’d have to use your real prefixes anyway.

Thank you very much! Finally there’s something new to see! :slight_smile:

My problem is only half solved, though.

This is the output that I’m getting now.

I’m finally seeing the global ipv6 address, which probably means that the ESP32 router assigned a global address to the downstream (wired) interface. I still have a small issue and another question.

Firstly, I’ve also added these lines USEMODULE += slipdev_l2addr and CFLAGS += -DSLIPDEV_PARAM_UART=UART_DEV\(1\) in the Makefile.board.dep file of the SUIT update example, and connected the router and the Nucleo board using UART. I am running USE_ETHOS=0 BOARD=nucleo-f767zi make flash term. I’ve double checked the connections and I’m sure the wiring is correct. But I cannot see the global ipv6 address on the Nucleo board running the SUIT application.

Secondly, I’m running a COAP fileserver on my Linux host and I connected my laptop to the same WiFi network as the ESP32 router. I would like to know how I can add a route from the ESP32 to my fileserver so that I can achieve an OTA firmware update.

Sorry for asking multiple questions at once, but I’m running a little low on time. Thanks in advance.

I assume Interface 5 is your SLIP interface? (you can check with ps). Can you do a link-local ping to ensure your wiring is correct?

ping ff02::1%5

Also you don’t want to do router advertisements on the downstream interface:

ifconfig 5 -rtr_adv

For reaching the Downstream network from your laptop, you have to manually add a route to the downstream network via the address of the upstream (WiFi) interface of the ESP32:

ip route add 2001:db8::/64 via fe80::a6cf:12ff:fe9a:2dc8 dev wlan0

(replace wlan0 with the real name of your WiFi interface)

You will also have to set your laptop as the default router on the RIOT side, for the border router application you can do so by setting IPV6_DEFAULT_ROUTER to the address of your laptop’s WiFi interface.

I’m assuming a link-local ping means running the ping command in the terminal of the Nucleo board running the SUIT update code. That did not work, 100% packet loss. I also tried the ps command and I could not find the SLIP interface. This is the output for those commands.

Also, I have another weird thing happening. As soon as I connect the ESP and the Nucleo boards together, the ESP starts resetting every few seconds. Even when I run the ping function, the ESP resets. This is how it looks.

I’m guessing this is because the ESP32 UART 1 pins are defined in the RIOT core as GPIO 9 and 10, which are SD3 and SD2 as per this pinout I found online, which are apparently connected to the flash memory of the board. Maybe using UART through these pins is causing that reset?

1 Like

You can set DEVELHELP=1 to enable thread names in ps. But looking at the ifconfig output you already chose the right interface.

Can you try other pins for UART? I don’t think all pins are possible to use for that, you better check the data sheet.

Yes, setting DEVELHELP=1 confirmed that interface 5 is SLIP. I’ve also tried with all possible combinations of UART connection on both devices. But I’m still not seeing a global address and ping ff02::1%5 still says 100% packet loss.

Can you try with FLASH_MODE=dio - this should make the flash use only two pins and free up GPIO9 and GPIO10 for UART

You can also try tests/periph/uart (and connect RX and TX on your board) to test if the UART is working in principle.

After taking a closer look at the devices running the router/SUIT example and trying out tests/periph_uart, I think I’ve understood a couple things. Firstly, according to the RIOT documentation there are two UARTs defined in the ESP, and UART_DEV(1) is the one connected to the flash pins while UART_DEV(0) is connecting the board to the terminal when I run term. I tried connecting the UART_DEV(0) to the Nucleo, and though I cannot use the terminal on the ESP32 while they are connected, I can see that when I run ping ff02::1%5 from the Nucleo, an LED on the ESP32 flashes 3 times. So I think from a hardware perspective, the UART connection is working which I also confirmed by running tests/periph_uart.

I think the SLIP connection could be the issue. Is there anything else I need to check or set in the Makefiles? The FLASH_MODE = dio also did not work and the ESP still resets when it receives something through the UART.

2 Likes

That’s great news! I only found this when reading the ESP32 SoC page in the documentation. Did you try a make BOARD=… clean? If you still can’t access the 2nd UART, @gschorcht should know more about that.

I think the UART_DEV(1) is technically working, but can only transmit. When I try the 'tests/periph_uart, I am able to send a test message from the ESP to the Nucleo. But when I try to send something back from the Nucleo, that’s when the ESP just resets. I tried with make clean with the same result.

I managed to solve the link-local ping issue. Turns out in my attempts to make the SLIP work, I initialised the UART in the main.c file, which I now removed. I am now able to ping ff02::1%5

I also have a global ipv6 address on the Nucleo board now.

But I had to manually enter ifconfig 5 -rtr_adv in the terminal, which I will not be able to do every time I power off and power on the board. Is there a way to do this in the Makefile?

Also, I would like to know how to reach this address from my Linux host. I have tried running this

but it just says RTNETLINK answers: File exists and I cannot ping it from my PC. Any ideas as to why this might be happening?

Yes - IMHO it’s a bug that this is on by default if there is no prefix configured on the interface, but I suppose opinions differ there. If you don’t need the deceive to be a router, you can just swap the gnrc_ipv6_router_default module for gnrc_ipv6_default and the node will no longer act as a router but try to solicit a router instead.

If you need routing, you’d need a way to get a prefix and those methods will all only enable router advertisements on the downstream interface.

Alternatively you can just set

CFLAGS += -DCONFIG_GNRC_IPV6_NIB_ADV_ROUTER=0

Huh that’s odd - is your wlan0 interface connected to a network?

Not really. I’ve been using my PC as a WiFi hotspot because I do not have a spare router currently. But the hotspot also uses the same wlan0 interface, doesn’t it?

You can find the name of your WiFi interface in ifconfig or ip a s.

Yes, I understand that. This is the ifconfig output.

I think this is the interface wlp0s20f3 as it is the only one with some activity in terms of Tx and Rx packets.

I tried routing to my ESP’s address like you suggested. It says RTNETLINK answers: File exists and the address is unreachable when I try to ping.

Does it make a difference if I’m using my PC as an Access Point (which I am doing right now) vs connecting it to a network?

Sorry, the ipv6 address I used in sudo ip route add 2001:db8::/64 via fe80::6411:da1d:befc:7eaf dev wlp0s20f3 is incorrect, it should be fe80::a6cf:12ff:fe9a:2dc8. Now when I added the route for the correct ipv6, File Exists did not show up but ping still doesn’t work.

I also added IPV6_DEFAULT_ROUTER = fe80::92b0:690f:c4d1:f8ef in the border router application.