Netmodule Routers with AI Features

Goal

This wiki shows how to enable an AI Core DX-M1 chip in the router and use it within an LXC container. It also explains how to set up additional utilities within the container.

The background to this project

Enable the router to run its own AI modules locally, directly on the router, without having to use a hyperscaler. Your own data can be used to train the AI modules because it is not shared with third parties. The entire value chain remains under your control and can be flexibly developed further. Applications include intelligent energy management systems, dynamic traffic control systems, and production management. The AI modules can be trained and fine-tuned for their core tasks to achieve optimal results.


Modules in the router


Prerequisites

  • NetModule NB2800/NB2810 Wireless Router with wireless connection
  • NetModule Software with AI Core DX-M1 Chip Support for NB2800 NB2800 Password for the download: “ai-chip”
  • NetModule Software with AI Core DX-M1 Chip Support for NB2810 NB2810 Password for the download: “ai-chip”
  • Not available for legacy products NB1600, NB2700, NB3700, NB3710

The wiki was tested with router software nrsw-image-2800-0.0.0.0.img and the LXC container with debina 13 armhf (trixie)


1. Installing the Module into the Router Hardware

An adapter is required for the Deepx DX-M1 AI chip to be used with the router. The PCI Express interfaces are implemented as Mini PCIe on the router board. The DX-M1 chip requires a Mini PCIe to M.2 M-key adapter.

The NB2800's circuit board features a DC/DC converter that supplies 3.3 volts to the two Mini-PCIe slots. The maximum output current is 6 amps. A maximum of 12 watts is available for the Mini-PCIe modules. The DX-M1 chip has a maximum power consumption of less than 5 watts.

The module can be installed in slot 1 or 2 on the NB2800.

The DX-M1 chip was inserted into the first slot

To ensure communication between the chip and the router, the module must be configured as Wi-Fi in the BD.

USER
=== BDINFO === bd/0/pd_module0: slot=0,caps=wlan-main:wlan-aux bd/0/pd_module1: slot=1,caps=wlan-main:wlan-aux bd/0/pd_module2: slot=2,caps=wwan-main:wwan-aux:gnss-active:voice bd/0/pd_module3: slot=3,caps=wwan-main:wwan-aux:voice

You can check whether the module is present via the router's console.

USER
lspci 02:00.0 Class 1200: 1ff4:0000

The module was detected in the router: “02:00.0” (PCI address of the device: Bus 02, Device 00, Function 0).

The device class of the module was correctly identified as “Class 1200” (processing accelerator), i.e., an NPU or AI accelerator

The last entry is generated generically because the name of the hardware is not stored in the lspci/pci.ids database.


2. Setting Up the Router Software on the Router

The first step is to download the software that includes driver support for the DX-M1 chip. To do this, click the link NB2800 or NB2810 to download the appropriate software for the two respective routers.

The password for access is “ai-chip”

Save the downloaded router software to the “/tmp” subdirectory on the router, and then connect to the router via the console using SSH or the Windows program PuTTY.

USER
BusyBox v1.35.0 () built-in shell (ash)

~ $ cd /tmp/ /tmp $ swupdate -fr nrsw-image-2800-0.0.0.0.img This is swupdate (version 3.0) speaking

Will force things root0 is currently our root partition ========== system info ================== Model NB2800 Profile: NETBOLT ROOTFS: 0.0.0.0 (20260806194249) UBOOT: 5.0.0.100 LOGIC: 5.0.0.100 (1 file) PATCH: none Forcing installation of an unsigned image.

You can install this image on the router using the command swupdate -fr nrsw-image-2800-0.0.0.0.img.

Next, set up a mobile (WWAN) connection on the router

In this example, I've set it up for a Telekom SIM card.

You can use a ping test to check whether the router can establish an Internet connection via the WWAN connection.

USER
~ $ ping quad9.net PING quad9.net (195.176.255.138): 56 data bytes 64 bytes from 195.176.255.138: seq=0 ttl=52 time=25.844 ms 64 bytes from 195.176.255.138: seq=1 ttl=52 time=39.836 ms 64 bytes from 195.176.255.138: seq=2 ttl=52 time=53.615 ms


3. Set up the LXC Contianer

Activate the LXC container on the router

In the second step, the image of the LXC container in this case, a Debina 13 (trixie).

The easiest way to do this is to install the whole thing over the Internet. However, the router requires a mobile connection to the Internet.

From a Jenkins server you get the current image for the container

* Jenkins Server Page image-debian / Link

Here you can download a Debian image for various systems and versions.

The armhf tab is important here, and trixie

The image is the “rootfs.tar.xz” which is required. With a right click you can copy the link.

It would be structured like this:

https://jenkins.linuxcontainers.org/view/Images/job/image-debian/architecture=armhf,release=trixie,variant=default/4118/artifact/rootfs.tar.xz

When the “Apply” button is pressed, Debian will be installed.

Set up the LXC container further. A network interface is enabled here.

The container has now also been assigned an IP address.

USER
~ $ lxc-info guest0 Name: guest0 State: RUNNING PID: 2255 IP: 192.168.1.149 CPU use: 1.57 seconds BlkIO use: 4.00 KiB Memory use: 6.29 MiB KMem use: 1.18 MiB Link: virt0 TX bytes: 2.28 KiB RX bytes: 853 bytes Total bytes: 3.11 KiB ~ $

Always assign a fixed IP address for the LXC container via the DHCP server. The MAC address of the LXC container is 00:FF:AA:00:44:00.

Log in to the LXC container and test whether it can access the Internet.

USER
~ $ lxc-attach guest0 root@LXCNAME:~# ping quad9.net PING quad9.net (195.176.255.138) 56(84) bytes of data. 64 bytes from 195.176.255.138 (195.176.255.138): icmp_seq=1 ttl=51 time=37.0 ms 64 bytes from 195.176.255.138 (195.176.255.138): icmp_seq=2 ttl=51 time=40.9 ms

— quad9.net ping statistics — 2 packets transmitted, 2 received, 0% packet loss, time 3006ms rtt min/avg/max/mdev = 28.823/36.685/40.937/4.768 ms root@LXCNAME:~#

The container is installed and set up. Now you can set up further tools on the container.


Adjust the LXC config so that the USB port can be used in the container

Enable USB administration on the router

When the USB device is plugged in, it is mounted by the router and stored in the system as device part “/dev/sda1“.

USER
Feb 12 09:13:38.515 NB2800 kern.info kernel: sda: sda1 Feb 12 09:13:38.515 NB2800 kern.notice kernel: sd 2:0:0:0: [sda] Attached SCSI removable disk Feb 12 09:13:38.585 NB2800 local1.notice NB2800: add event for usb device /dev/sda Feb 12 09:13:38.596 NB2800 user.notice event-manager[1831]: received event 'USB storage device has been added' Feb 12 09:13:38.667 NB2800 local1.notice NB2800: add event for usb device /dev/sda1 Feb 12 09:13:38.671 NB2800 local1.notice NB2800: device add - device = /dev/sda1 Feb 12 09:13:38.675 NB2800 local1.notice NB2800: device add - type = usb Feb 12 09:13:38.678 NB2800 local1.notice NB2800: device add - uid = 855A-2532 Feb 12 09:13:38.690 NB2800 user.debug : Add-event for (type=usb, device=/dev/sda1, id=855A-2532) Feb 12 09:13:38.692 NB2800 user.debug : storage-add: device (path=/dev/sda1, uid=855A-2532) appeared

In order to release the device in the container, I need to know what kind of device it is: “b” is a block device, major number “8” and minor number “1”.

With this information, we can adjust the LXC configuration so that we have access to the device from within the container.

This change is made directly in the router software. When updating the router software, this entry must be made again because it is not part of the official software.

Add these entries to the end of the config file.

~ $ vi /etc/lxc/guest0/config
                                                           
# Setting up a USB flash drive in the LXC container                                      
lxc.cgroup.devices.allow = b 8:1 rwm                                
lxc.mount.entry = /dev/sda1 /dev/sda1 none bind,optional,create=file            

Simply add these four entries to the LXC configuration file. Please ensure that you fill them in with your own parameters. Restart the router for these changes to take effect.

Now the USB device can be connected to the container and used. The “mkdir” command is used to set up an area in the file system for access.In the second step, change the permissions of the file.

USER
~ $ lxc-attach guest0

$ mkdir -p /mnt/home/data

$ chgrp -R users /mnt/home/ $ chmod -R 770 /mnt/home/

Check whether the rights have been set.

USER
/mnt/home $ ls -l total 4 drwxrwx— 2 root users 4096 Aug 11 14:19 data /mnt/home $


Integrating external storage into the container system

The whole thing is integrated via a cron job, so that it is always available when the router is restarted.

Queries with which file system the external storage was formatted.

USER
root@LXCNAME:~# mknod /dev/sda1 b 8 1 root@LXCNAME:~# blkid /dev/sda1 /dev/sda1: UUID=“6fdf5877-289d-4b3f-a2f0-d6bce5554c6a” BLOCK_SIZE=“4096” TYPE=“ext4” root@LXCNAME:~# root@LXCNAME:~# mount /dev/sda1 /mnt/home/data

First, we create a script file called vi usb_stick.sh

#!/bin/bash
mknod /dev/sda1 b 8 1
sleep 1s
mount /dev/sda1 /mnt/home/data

To test it, you can now simply run this file. Now the whole thing has to be saved as a cron job. To do this, call up the command “crontab -e” and save this line there.

USER
root@LXCNAME:~# chmod a+x usb_stick.sh

root@LXCNAME:~# apt install cron

root@LXCNAME:~# crontab -e
@reboot /root/usb_stick.sh

4. Set up the AI Core DX-M1 chip

The driver must be loaded into the router using the “modprobe” command. This is done by typing “done”.

~ $ vi /etc/init.d/done

# The dxrt_driver.ko driver is being loaded
modprobe dxrt_driver 2>/dev/null || sudo insmod /lib/modules/$(uname -r)/extra/rt/dxrt_driver.ko

# LXC continaer restart
/etc/init.d/virt restart

Test this after rebooting the router to see if the interface is present in the router.

In the next step, the interface must be passed to the LXC container.

~ $ vi /etc/lxc/guest0/config

# Allow Access (Device 247)
lxc.cgroup.devices.allow = c 247:0 rwm

# Mount the DXRT device node in the container
lxc.mount.entry = /dev/dxrt0 dev/dxrt0 none bind,create=file 0 0

If the “dxrt0” interface under the LXC container is set to mode “(000),” you must check the settings in lxc config again to make sure they are correct.

USER
root@LXCNAME:~# ls -l /dev/ | grep dx* crw-rw-rw- 1 root root 247, 0 Aug 11 15:38 dxrt0


The next thing you'll need is the DX-RT runtime software

To do this, you'll need to clone the DX-ALL-SUITE repository using “git”.

The git tool is required for this. The DX-ALL-SUITE repository is then saved to the USB flash drive for further installation

USER
root@LXCNAME:~# apt install git

root@LXCNAME:~# cd /mnt/home/data/ root@LXCNAME:/mnt/home/data# export VERSION=v2.1.0 root@LXCNAME:/mnt/home/data# git clone -b ${VERSION} –recurse-submodules https://github.com/DEEPX-AI/dx-all-suite.git

Additional software is required for the installation

USER
root@LXCNAME:~# apt install cmake root@LXCNAME:~# apt install ninja-build root@LXCNAME:~# apt install g++-arm-linux-gnueabihf root@LXCNAME:~# apt install python3 python3-dev python3-venv python3-pip root@LXCNAME:~# apt install libncurses-dev root@LXCNAME:~# apt install libonnxruntime-dev

You can then proceed with the installation of the DX-RT (runtime software).

USER
root@LXCNAME:~# cd /mnt/home/data/dx-all-suite/dx-runtime/dx_rt

root@LXCNAME:~# cmake -S . -B build -DPython_EXECUTABLE=/usr/bin/python3 -Donnxruntime_INCLUDE_DIRS=/mnt/home/data/dx-all-suite/dx-runtime/dx_rt/extern/onnxruntime-win-x64-1.20.1/include -Donnxruntime_LIB_DIRS=/mnt/home/data/dx-all-suite/dx-runtime/dx_rt/extern/onnxruntime-win-x64-1.20.1/lib

root@LXCNAME:~# cmake –build build -j1

Once it has been successfully installed, you can test it.

USER
root@LXCNAME:~# cp -a /mnt/home/data/dx-all-suite/dx-runtime/dx_rt/build/bin/dxrt-cli /usr/local/bin/dxrt-cli root@LXCNAME:~# chmod 755 /usr/local/bin/dxrt-cli

Run the CLI command “dxrt-cli –status”

USER
root@LXCNAME:~# dxrt-cli -s DXRT v3.1.0 ======================================================= * Device 0: M1, Accelerator type ——————— Version ——————— * RT Driver version : v2.6.0 * PCIe Driver version : v2.5.0


* FW version : v2.1.5 ——————— Device Info ——————— * Memory : LPDDR5 5600 Mbps, 3.92GiB * Board : M.2, Rev 1.5 * Chip Offset : 0 * PCIe : Gen1 X1 [02:00:00]

NPU 0: voltage 750 mV, clock 1000 MHz, temperature 48'C NPU 1: voltage 750 mV, clock 1000 MHz, temperature 49'C NPU 2: voltage 750 mV, clock 1000 MHz, temperature 48'C ======================================================= root@LXCNAME:~#

Now, information from the three NPU cores on the AI chip is displayed.


5. Additional information

* Deepx DX-M1 AI-Chip Webpage DX-M1 Chip

* Deepx DX-M1 Documentation DX-M1 Documentation

* AI-Models for the Chip AI-Models

* Overview DX-M1 Chip Overview