Skip to content

Nzyme Util

The nzyme-util command is made to help you with common Nzyme tasks and especially to manage Nzyme hardware and peripherals.

Installation

Download the latest version of nzyme-util for your operating system and install it like this:

sudo dpkg -i nzyme-util_xxx-xxx-xxx-x.x.x.deb

You can now execute nzyme-util. Run the --help command to make sure it works:

$ nzyme-util --help

Nzyme CLI Utility

Usage: nzyme-util [COMMAND]

Commands:
  firmware
  devices
  help      Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

udev Rules

You can install the following udev rule to avoid having to be root to interact with Nzyme devices. It allows non-root users to use all USB devices with the Nzyme vendor ID 0x390C.

Write the following file to /etc/udev/rules.d/99-nzyme-usb.rules:

SUBSYSTEM=="usb", ATTR{idVendor}=="390c", MODE="0666"

Then reload the udev rules:

sudo udevadm control --reload-rules
sudo udevadm trigger

Confirm that the rule took effect:

$ udevadm cat | grep 390c
SUBSYSTEM=="usb", ATTR{idVendor}=="390c", MODE="0666"

You can decide not to install this udev rule, but you will have to be root or use sudo to run nzyme-util when interacting with Nzyme devices via USB.

Commands

List All Connected Nzyme Devices

You can list all connected Nzyme devices like this:

nzyme-util devices list

This will show you relevant information for each connected Nzyme device:

Device:
├─ Product:          Limina
├─ Manufacturer:     Nzyme LLC
├─ Serial:           207C309A3645
├─ Firmware Version: v0.0
├─ VID:PID:          390C:0200
├─ Bus / Address:    1 / 5
└─ ACM Port:         /dev/ttyACM0

Device:
├─ Product:          Sona (802.11/WiFi)
├─ Manufacturer:     Nzyme LLC
├─ Serial:           7C9085C8E6BDAAD1
├─ Firmware Version: v0.5
├─ VID:PID:          390C:0100
├─ Bus / Address:    1 / 51
└─ ACM Port:         /dev/ttyACM2

Device:
├─ Product:          Sona (802.11/WiFi)
├─ Manufacturer:     Nzyme LLC
├─ Serial:           8B7B63E05F374C94
├─ Firmware Version: v0.5
├─ VID:PID:          390C:0100
├─ Bus / Address:    1 / 50
└─ ACM Port:         /dev/ttyACM1

Device:
├─ Product:          Sona (802.11/WiFi)
├─ Manufacturer:     Nzyme LLC
├─ Serial:           B47277283036FD2F
├─ Firmware Version: v0.5
├─ VID:PID:          390C:0100
├─ Bus / Address:    1 / 55
└─ ACM Port:         /dev/ttyACM4

Device:
├─ Product:          Sona (802.11/WiFi)
├─ Manufacturer:     Nzyme LLC
├─ Serial:           1ABAE79791F91419
├─ Firmware Version: v0.5
├─ VID:PID:          390C:0100
├─ Bus / Address:    1 / 52
└─ ACM Port:         /dev/ttyACM3

Generate Sona Configuration

You can automatically generate an optimized Sona configuration snippet for your nzyme-tap configuration file.

nzyme-util sona generate-config

This will generate a configuration snippet that makes use of all connected Sona boards, splitting channels evenly.

==> Sona Configuration Generator
    Generating configuration for all connected Sona devices.

[>] Detecting connected Sona devices...
[*] Found 1 Sona (4 interfaces).

Detected Interfaces:
    [1] sona-7C9085C8E6BDAAD1
    [2] sona-8B7B63E05F374C94
    [3] sona-B47277283036FD2F
    [4] sona-1ABAE79791F91419

==> Generated Configuration
    Copy the block between the markers below into your nzyme tap
    configuration file. Channels are split evenly across all interfaces.

---------- BEGIN CONFIGURATION ----------

[wifi_interfaces.sona-7C9085C8E6BDAAD1]
active = true
channels_2g = [1, 2, 3, 4, 5, 6, 7]
channels_5g = []

[wifi_interfaces.sona-8B7B63E05F374C94]
active = true
channels_2g = [8, 9, 10, 11, 12, 13, 14]
channels_5g = []

[wifi_interfaces.sona-B47277283036FD2F]
active = true
channels_2g = []
channels_5g = [36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120]

[wifi_interfaces.sona-1ABAE79791F91419]
active = true
channels_2g = []
channels_5g = [124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177]

----------- END CONFIGURATION -----------

[*] Configuration generated for 4 interfaces.

Watching a Tap in Real Time

nzyme-util tap top is a live, top-like terminal dashboard of a running nzyme-tap process. It shows what the tap is doing right now, ten times a second: which message bus channels are receiving data, how full their buffers are, whether packets are being dropped, how much CPU and memory the tap uses, whether reports reach the Nzyme node, and what the tap is logging. It is the quickest way to get a feeling for a tap under load, and to see a problem the moment it happens instead of waiting for the next status report.

Enabling the Telemetry Feed

The dashboard reads from a telemetry feed that nzyme-tap serves on a local TCP socket. The feed is disabled by default. Enable it in your nzyme-tap.conf and restart the tap:

[telemetry]
enabled = true
listen = "127.0.0.1:22910"
tick_ms = 100
Variable Description
enabled Serve the feed. Default: false.
listen Address and port to listen on. Must be a loopback address. Default: 127.0.0.1:22910.
tick_ms How often channel and capture counters are sampled, in milliseconds. Between 20 and 5000. Default: 100.

Warning

The feed is unauthenticated and includes tap log lines. This is why nzyme-tap refuses any listen address that is not a loopback address. To watch a remote tap, forward the port over SSH as described below.

The feed costs the tap nothing while nobody is connected. While a dashboard is connected, the tap samples its counters once per tick and streams them; this adds no work to the packet processing path.

Running the Dashboard

On the tap host, run:

nzyme-util tap top

Use --address if the feed listens on a different port. The dashboard connects, shows ● LINK in the header and starts drawing. If the tap is not reachable it keeps retrying and tells you so, and it reconnects automatically if the tap restarts.

To watch a tap on another host, forward the port over SSH and connect to the local end of the tunnel:

ssh -L 22910:127.0.0.1:22910 tap-host
nzyme-util tap top

What You See

The dashboard has four pages. Switch with Tab or the number keys.

Overview (1)

  • Pulse: a scrolling graph of the bytes per second the tap processes, with the current rate, the peak and the total.
  • System: host CPU with a per-core strip, memory, the tap's own CPU, resident memory, thread and file descriptor counts, load average and, on a Raspberry Pi, the CPU temperature. The LOCK line shows how long the feed had to wait for the tap's central metrics lock, which is a direct measurement of lock contention inside the tap. LAG shows how late the sample fired. LEAD summarizes the leader link: ok and failed submissions, the last round-trip time and the duration of the last report cycle.
  • Captures: one row per capture interface with an activity LED, received packets or frames per second, a small history graph, and drop counters that flash when new drops occur. A capture that stopped running is marked in red.
  • WiFi // Hopper: one row per WiFi adapter with the frequency and channel it is currently tuned to, the channel width, the hop rate, and a strip of all assigned channels with the current one highlighted.
  • Bus // Channels: one row per message bus channel, grouped by bus. The LED flashes white when messages arrived in the last tick and fades through orange and red as the channel goes quiet. The row shows messages and bytes per second, the watermark (how many messages are queued, against the channel's capacity) and the total number of submit errors, which are messages dropped because the channel was full. New errors flash the row. A watermark above 80 % blinks. The activity graph on the right shows the message rate over the last minute.
  • Leader Link // Submissions: one row per report path sent to the Nzyme node (tcp/sessions, dns/summary, status, and so on) with an LED on the last submission, ok and failed counts, the last HTTP status, the last and slowest round-trip time, the payload size, a round-trip trend and the last error. 403 off means the subsystem is disabled on the node.
  • Report Cycle: every ten seconds the tap walks its state tables, builds each report, uploads it and clears the table. Each table's row shows how long that step took, its share of the whole cycle, and the slowest it has been. A table holds its lock during this step, so a slow row here means the processors writing to that table were waiting.
  • Table Sizes: the sizes of the state tables between reports, each with a bar against its own peak and a trend.
  • Log: the tap log as it happens, colored by level, with error and warning counts in the title.

Leader // State (2) shows the submissions, report cycle and table size panels with more room, plus the sizes of the context and ARP state.

Gauges // Timers (3) lists every gauge the tap reports with a trend, and every timer with its mean and 99th percentile in microseconds over the last minute.

Log (4) is the full-screen log, scrollable.

The header shows the tap version, host name and uptime. ▲ STALL appears when the tap stopped sending ticks while the connection is still up, which usually means the tap is blocked on a lock. ▲ LINK LOST appears when the connection dropped; the dashboard keeps showing the last data and reconnects on its own.

Keys

Key Action
Tab, 1 to 4 Switch pages.
↑ / ↓, PgUp / PgDn Scroll the lists on the current page.
l Cycle the size of the log panel on the overview: small, large, hidden.
z Hide channels that have been idle for ten seconds.
p or Space Freeze the screen. Data that arrives while frozen is discarded.
q Quit.

Recording and Playback

Everything the dashboard receives can be written to a file:

nzyme-util tap top --record tap-session.ndjson

The header shows a blinking ● REC while recording. The file contains one JSON line per frame, is flushed every second and grows by roughly 10 KB per second at the default tick. Quit with q to close it cleanly.

Play a recording back in the same dashboard, paced exactly as it was recorded:

nzyme-util tap top --replay tap-session.ndjson

Every frame carries the time the tap produced it, so pauses, bursts and stalls replay as they happened. During playback the header shows the position and a progress bar, and these keys are available in addition to the ones above:

Key Action
Space Pause and resume.
+ / - Change the speed between 0.25× and 16×.
← / → Seek 10 seconds back or forward. With Shift, 60 seconds.
r Restart from the beginning.

--speed sets the initial playback speed. Recordings are a good way to share what a tap was doing with the Nzyme team.

Upgrading Firmware of a Nzyme Device

You need the following to upgrade the firmware of a Nzyme device:

  • The target Nzyme device connected via USB
  • The serial number of the target Nzyme device (see nzyme-util devices list above)
  • The firmware file to flash
  • Optionally: The SHA256 sum of the Nzyme public key to verifiy firmware and nzyme-util authenticity

You can upgrade the firmware like this:

nzyme-util firmware flash --firmware-file firmware.bin --serial 1ABAE79791F91419

The output will look something like this:

==> Nzyme Firmware Upgrade
    Device Serial : 1ABAE79791F91419
    Firmware File : firmware.bin

Device Information:
    Product        : Sona (802.11/WiFi)
    Manufacturer   : Nzyme LLC
    Serial Number  : 1ABAE79791F91419
    Bootloader     : Sona
    Firmware       : v0.5
    USB VID:PID    : 0x390C:0x0100
    ACM Port       : /dev/ttyACM1

==> Loading Firmware

==> Entering Bootloader Mode
[>] Sending bootloader command over /dev/ttyACM1...
[>] Waiting for bootloader enumeration (0x390C:0x0002)...
[*] Bootloader mode detected.

==> Flashing Firmware
[>] Writing firmware image...
[*] All bytes written. Device is validating and rebooting.

==> Waiting for Device Reboot
[>] Expecting device as 0x390C:0x0100...
[*] Device reconnected.

==> Verifying Firmware Version
[*] New firmware version: v0.5

==> Process complete.

Verifying Authenticity

Public Key Verification

It is critical that you have an authentic copy of the Nzyme public key before verifying releases. You can download the public key from the Nzyme downloads page.

To prevent an attacker from substituting a malicious release and supplying their own key alongside it, always verify your downloaded public key's SHA256 hash against one or more of our trusted, independent sources.

This is the SHA256 hash of the current Nzyme public key:

Key SHA256
ALPHA 19165ba3a5c92ee306cafcca41e79044cbdafb9daae2dce38838ba0915dead4c

Info

The ALPHA key is used to sign all current Nzyme releases. Additional keys may be introduced in future release channels.

We publish the SHA256 hash of our public keys in the following independent locations:

Depending on your security requirements, verify the hash against as many of these sources as needed. The more sources you check, the higher your assurance that the key has not been tampered with.

Verifying on Linux

After downloading the public key, run sha256sum against it and compare the output to the expected hash above and to the DNS TXT record:

sha256sum nzyme-alpha.pub

The hash printed by sha256sum must exactly match both the value in the table above and the DNS TXT record. If there is any discrepancy, do not use the key, discard the downloaded file and contact the Nzyme team.

Verifying Authenticity of nzyme-util

We will use nzyme-util to verify authenticity of Nzyme firmware files and software releases. This means that we must ensure that nzyme-util itself is authentic. Using nzyme-util for verification is easy because it can automate the process. However, the initial verification of nzyme-util itself requires openssl.

Step 1: Verify the Public Key

For this verification, we will use the nzyme-alpha.pub.pem key format instead of the standard nzyme-alpha.pub binary distribution.

Confirm that the key sha256sum matches the published hash as described above, using as many factors as your threat model calls for:

$ openssl pkey -pubin -in nzyme-alpha.pub.pem -pubout -outform DER | tail -c 32 | sha256sum

Step 2: Verify nzyme-util Using openssl

With the public key confirmed as authentic, use openssl to verify the signature of the nzyme-util binary before running it for the first time:

openssl pkeyutl -verify -pubin -inkey nzyme-alpha.pub.pem -rawin -in nzyme-util.deb -sigfile nzyme-util.deb.sig

openssl will print Signature Verified Successfully if the signature is valid. Any other output means the binary has been tampered with or the wrong key was used.

Verifying Authenticity of Software Releases

You can find the required signature file together with the release file on the Nzyme downloads page.

nzyme-util release verify --public-key-file nzyme-alpha.pub --signature-file release.deb.sig --release-file release.deb 

Output for an authentic release will look like this:

==> Nzyme Release Signature Verification
    Release File  : release.deb
    Signature File: release.deb.sig
    Public Key    : nzyme-alpha.pub
    File Size     : 61664376 bytes

[✓] Signature VALID — release is authentic and unmodified.

[!!] Verify supplied public key against trusted source:

    19165ba3 a5c92ee3 06cafcca 41e79044
    cbdafb9d aae2dce3 8838ba09 15dead4c

[!!] Additionally, always verify authenticity of this executable as documented.

Verifying Authenticity of Firmware Files

Nzyme firmware files have the signature baked into the release file, and you can run nzyme-util without specifying a separate signature:

nzyme-util firmware verify --public-key-file nzyme-alpha.pub --firmware-file firmware.bin 

Output for an authentic release will look like this:

==> Nzyme Firmware Signature Verification
    Firmware File : firmware.bin
    Public Key    : nzyme-alpha.pub
    File Size     : 240860 bytes
    FW Length     : 240776 bytes
    USB VID:PID   : 0x390C:0x0100
    FW Version    : 0.5
    Signing KeyID : 1

[✓] Signature VALID — firmware is authentic and unmodified.

[!!] Verify supplied public key against trusted source:

    19165ba3 a5c92ee3 06cafcca 41e79044
    cbdafb9d aae2dce3 8838ba09 15dead4c

[!!] Additionally, always verify authenticity of this executable as documented.