Research-Stack/4-Infrastructure/docs/usbip-mesh-transport-design.md
2026-05-25 16:24:21 -05:00

5.6 KiB

USB/IP Mesh Transport Design

Status: design + capability probe. This document does not claim any exported USB device is live until a matching usbip attach receipt exists.

Decision

Use USB/IP as an optional transport surface over the existing Tailscale mesh. The local hardware probe showed that QFox and the laptop expose USB host controllers, not USB gadget/device-mode ports. USB/IP matches that reality: each node can keep acting as a USB host for physically attached devices while making selected USB devices reachable to another node over IP.

Transport Model

physical USB device
  -> exporting node xHCI host controller
  -> usbip-host + usbipd
  -> Tailscale/WiFi/Babel-routed IP path
  -> importing node vhci-hcd
  -> local kernel driver on importing node

USB/IP is not a replacement for USB-C host-to-host cabling. It is a remote bus projection: one machine owns the physical port, another machine imports a virtual host-controller slot.

Roles

Role Responsibility Required support
exporter owns physical USB device and offers it to the mesh usbip-host, usbipd, TCP 3240 on mesh-only address
importer consumes a remote USB device as if local vhci-hcd, usbip attach
controller decides which node should export/import Tailscale reachability, policy, receipts

Candidate Devices

Good candidates:

  • USB serial adapters for FPGA / microcontroller boards.
  • USB storage for short maintenance windows.
  • USB NICs or active bridge cables when a node has better physical placement.
  • Cameras, sensors, and test fixtures where single-owner access is acceptable.

Avoid or treat as experimental:

  • Keyboards/mice used for local recovery.
  • Bluetooth and WiFi controllers already needed by the exporting host.
  • Audio/video devices with tight latency expectations.
  • Security-sensitive devices unless the mesh ACL and exporter are trusted.

Security Boundary

USB/IP has a large trust boundary because the importing kernel parses remote USB traffic. Treat it as a privileged infrastructure path, not an open service.

Minimum policy:

  • Bind/listen only on Tailscale or a private mesh address.
  • Restrict TCP 3240 with host firewall and Tailscale ACLs.
  • Export only explicit bus IDs, never all USB devices.
  • Require an operator action or policy receipt before usbip bind.
  • Prefer one active importer per exported device.
  • Record attach/detach receipts with exporter, importer, bus ID, VID:PID, driver, and route metrics.

Integration With Mesh Routing

The USB/IP path should be a transport candidate in the same selector as WiFi and Tailscale:

Transport Purpose Cost notes
local USB direct attached device on current node lowest software latency
USB/IP over LAN/WiFi remote physical USB device in 5ft cluster depends on WiFi latency and loss
USB/IP over Tailscale non-local node device access encrypted, reliable, higher latency
native IP service prefer when device protocol already has an IP-native API avoids kernel USB remoting

For non-local nodes, USB/IP should ride over Tailscale first. If later we add Babel across WiFi Direct/AP links, the USB/IP controller can choose the lower cost route but should keep the service bound to a mesh-only interface.

Probe

Capability probe:

bash 4-Infrastructure/auto/nodes/usbip.sh

The probe emits JSON with:

  • tools.usbip and tools.usbipd
  • kernel module availability/load state for usbip_core, usbip_host, vhci_hcd
  • whether usbipd is active and TCP 3240 is listening
  • visible USB devices by bus ID, VID:PID, speed, product, and current driver

The probe is observe-only. It does not bind, export, attach, or detach devices.

Bring-Up Plan

  1. Install userland usbip tools on QFox, nixos-laptop, and any non-local node that may export/import devices.
    • QFox/CachyOS: sudo pacman -S usbip
    • NixOS: add pkgs.linuxPackages.usbip to environment.systemPackages for the active kernel package set.
  2. Load/persist modules:
    • exporters: usbip-core, usbip-host
    • importers: usbip-core, vhci-hcd
  3. Run the probe on each node and store receipts.
  4. Pick one low-risk test device, preferably a spare USB serial adapter.
  5. On exporter:
    • usbip list -l
    • usbip bind -b <busid>
    • start usbipd on a mesh-only address if supported by the installed daemon, otherwise firewall TCP 3240 to Tailscale peers only.
  6. On importer:
    • usbip list -r <exporter-tailscale-ip>
    • usbip attach -r <exporter-tailscale-ip> -b <busid>
    • verify the expected local device appears.
  7. Record attach receipt and detach cleanly:
    • usbip port
    • usbip detach -p <port>

Claim Boundaries

  • A capability probe proves only that tools/modules/devices are visible.
  • usbip bind proves only that an exporter made one bus ID available.
  • usbip attach plus local device enumeration proves a remote USB projection.
  • Device-specific success requires a higher-level receipt, such as UART bytes, block-device read, camera frame, or NIC link.

Initial Probe Result

Current QFox and nixos-laptop probes show:

  • Kernel modules are available and loaded on both nodes: usbip-core, usbip-host, vhci-hcd.
  • Userland tools are installed on both nodes:
    • QFox: /usr/bin/usbip, /usr/bin/usbipd
    • nixos-laptop: /run/current-system/sw/bin/usbip, /run/current-system/sw/bin/usbipd
  • No usbipd service was active and TCP 3240 was not listening.
  • Both nodes exposed candidate physical USB devices through sysfs.

This means the remaining bring-up is policy/service/device selection, not kernel or package availability.