Skip to content

build(docker): Add remote radio support in docker#201

Draft
Lakshmi97-velampati wants to merge 18 commits into
mainfrom
mvelam850/dev/threadRadionInDockerCompose
Draft

build(docker): Add remote radio support in docker#201
Lakshmi97-velampati wants to merge 18 commits into
mainfrom
mvelam850/dev/threadRadionInDockerCompose

Conversation

@Lakshmi97-velampati
Copy link
Copy Markdown
Contributor

Add an optional otbr-radio Docker container that connects a Silicon Labs BRD2703 xG24 Explorer Kit to the Barton devcontainer via D-Bus, enabling Thread integration testing with real hardware.

  • Dockerfile.otbr-radio: builds image with cpcd and otbr-agent compiled for CPC transport; uses the URL spinel+cpc://cpcd_0?iid=1&iid-list=0 to handle both unicast and broadcast Spinel frames
  • compose.otbr-radio.yaml: compose overlay that shares a D-Bus socket volume with the barton service and maps RADIO_DEVICE at the same path on both the host and container sides
  • otbr-radio-entrypoint.sh: writes a fresh cpcd config on every start (uart_device_file, uart_hardflow: true), waits for "Daemon startup was successful" before launching otbr-agent, and auto-detects BACKBONE_IF from the host default route at runtime
  • setupDockerEnv.sh: auto-detects the backbone interface via ip route and writes it to docker/.env;

Refs: BARTON-359

Add an optional otbr-radio Docker container that connects a Silicon
Labs BRD2703 xG24 Explorer Kit to the Barton devcontainer via D-Bus,
enabling Thread integration testing with real hardware.

- Dockerfile.otbr-radio: builds image with cpcd and otbr-agent
  compiled for CPC transport; uses the URL
  spinel+cpc://cpcd_0?iid=1&iid-list=0 to handle both unicast and
  broadcast Spinel frames
- compose.otbr-radio.yaml: compose overlay that shares a D-Bus socket
  volume with the barton service and maps RADIO_DEVICE at the same
  path on both the host and container sides
- otbr-radio-entrypoint.sh: writes a fresh cpcd config on every start
  (uart_device_file, uart_hardflow: true), waits for "Daemon startup
  was successful" before launching otbr-agent, and auto-detects
  BACKBONE_IF from the host default route at runtime
- setupDockerEnv.sh: auto-detects the backbone interface via ip route
  and writes it to docker/.env;

Refs: BARTON-359

Signed-off-by: mvelam850 <munilakshmi_velampati@comcast.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional “real USB radio” Thread Border Router path for Barton’s Docker-based dev environment by introducing an otbr-radio sidecar container (cpcd + otbr-agent) that shares a D-Bus socket volume with the main barton container, enabling Thread integration testing against real BRD2703 hardware.

Changes:

  • Add an otbr-radio Docker image + entrypoint that brings up D-Bus, Avahi, cpcd, then otbr-agent over CPC (spinel+cpc://).
  • Add a Compose overlay to run otbr-radio with host networking/privileges and share /var/run/dbus with barton.
  • Extend tooling/docs: dockerw -T flag, .env variables (RADIO_DEVICE, BACKBONE_IF), and setup instructions.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
docs/THREAD_BORDER_ROUTER_SUPPORT.md Adds end-to-end documentation for simulated vs real-radio Thread setup, including USB-IP guidance.
dockerw Adds -T flag to include the OTBR radio compose overlay and start the otbr-radio service.
docker/setupDockerEnv.sh Writes optional RADIO_DEVICE and BACKBONE_IF into docker/.env, with backbone IF auto-detection.
docker/README.md Documents the new compose overlay and the -T flag.
docker/otbr-radio-entrypoint.sh New entrypoint that orchestrates D-Bus, Avahi, cpcd, and otbr-agent startup for CPC-based RCP.
docker/Dockerfile.otbr-radio New build for cpcd + otbr-agent (Silabs GSDK transport/CPC) and D-Bus policy.
docker/compose.otbr-radio.yaml New compose overlay that runs otbr-radio privileged with host networking and shares D-Bus socket volume with barton.

Comment thread docker/otbr-radio-entrypoint.sh Outdated
Comment thread docker/otbr-radio-entrypoint.sh Outdated
Comment thread docker/setupDockerEnv.sh Outdated
Comment thread dockerw Outdated
Copy link
Copy Markdown
Contributor

@kfundecmcsa kfundecmcsa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a couple open questions, but requesting changes for the title. This effort should fall into the build commit type, not feat

Comment thread docs/THREAD_BORDER_ROUTER_SUPPORT.md Outdated
Comment thread docs/THREAD_BORDER_ROUTER_SUPPORT.md Outdated
@Lakshmi97-velampati Lakshmi97-velampati changed the title feat(docker): Add thread radio support in docker build(docker): Add thread radio support in docker Apr 13, 2026
@Lakshmi97-velampati
Copy link
Copy Markdown
Contributor Author

I have a couple open questions, but requesting changes for the title. This effort should fall into the build commit type, not feat

Updated

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comment thread docker/Dockerfile.otbr-radio
Comment thread docker/compose.otbr-radio.yaml Outdated
Comment thread docker/compose.otbr-radio.yaml Outdated
Comment thread docker/compose.otbr-radio.yaml Outdated
Comment thread docker/otbr-radio-entrypoint.sh Outdated
Comment thread docker/otbr-radio-entrypoint.sh Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Comment thread docker/otbr-radio-entrypoint.sh Outdated
Comment thread docker/compose.otbr-radio.yaml Outdated
Comment thread docker/compose.otbr-radio.yaml Outdated
Comment thread docker/compose.otbr-radio.yaml Outdated
Comment thread .devcontainer/devcontainer.json
@Lakshmi97-velampati Lakshmi97-velampati marked this pull request as draft April 17, 2026 02:10
@tleacmcsa
Copy link
Copy Markdown
Contributor

Be sure to take this PR out of draft when you are ready for re-review.

@Lakshmi97-velampati Lakshmi97-velampati marked this pull request as ready for review April 17, 2026 16:03
Copilot AI review requested due to automatic review settings April 17, 2026 16:03
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Comment thread docs/THREAD_BORDER_ROUTER_SUPPORT.md Outdated
Comment thread docker/compose.otbr-radio.yaml Outdated
Comment thread dockerw Outdated
Comment thread dockerw Outdated
@Lakshmi97-velampati
Copy link
Copy Markdown
Contributor Author

This generally worked with the exception that I had to change the DBUS_SYSTEM_BUS_ADDRESS value set in compose.otbr-radio.yaml to point to the otbr-dbus path.

Thread subsystem worked, but I could not commission a Matter+Thread device since there is no bluez/Bluetooth support. We need to add bluez in the same container as otbr-agent since they both can use the same radio for Thread and bluetooth. Its fine with me if the bluetooth/bluez part comes in a follow-up PR though.

To confirm, were you able to commission a Matter+Thread device in this configuration? How did you decide it was successful, the Thread subsystem showing ready?

Thanks for testing this and for adding the BLE support.

Apologies, I haven’t validated the commissioning flow yet. My checks were limited to confirming that the otbr-agent is running in the new container.

I’ll verify the commissioning flow now with the BLE changes you’ve added and confirm the results.

@tleacmcsa tleacmcsa changed the title build(docker): Add thread radio support in docker build(docker): Add remote radio support in docker May 11, 2026
@Lakshmi97-velampati Lakshmi97-velampati marked this pull request as ready for review May 19, 2026 06:12
Copilot AI review requested due to automatic review settings May 19, 2026 06:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

# AF_BLUETOOTH (e.g. bluetoothctl) can run via nsenter.
- /proc/1/ns/net:/run/host-netns:ro
environment:
- DBUS_SYSTEM_BUS_ADDRESS=${DBUS_SYSTEM_BUS_ADDRESS:-unix:path=/var/run/otbr-dbus/system_bus_socket}
2. If using Matter, configure and build your Matter SDK as described in [MATTER_SUPPORT.md]().
3. If using Zigbee, see [ZIGBEE_SUPPORT.md]().
4. If using OpenThread's Border Router, see [THREAD_BORDER_ROUTER_SUPPORT.md]().
4. If using OpenThread's Border Router, see [REMOTE_RADIO_FOR_DEVELOPMENT.md]().
Comment thread scripts/remote-radio/usbip-validate.sh Outdated
Comment on lines +227 to +230
if echo "${HCI_DEVICES}" | grep -q "hci${BLE_ADAPTER_ID}"; then
pass "hci${BLE_ADAPTER_ID} is present in host network namespace"

HCI_STATUS=$(echo "${HCI_DEVICES}" | grep -A2 "hci${BLE_ADAPTER_ID}:" || true)
Comment thread docker/otbr-radio-entrypoint.sh Outdated
echo "[otbr-radio] Starting cpcd (instance: cpcd_0, device: ${RADIO_DEVICE})..."
CPCD_LOG="/tmp/cpcd.log"
: > "${CPCD_LOG}"
cpcd --conf "${CPCD_CONF}" > >(tee "${CPCD_LOG}") 2>&1 &
Lakshmi97-velampati and others added 2 commits May 19, 2026 11:05
hcitool uses the legacy HCI socket interface which permanently conflicts
with bluetoothd's MGMT socket. Starting an LE scan via hcitool and
killing it leaves the kernel MGMT layer stuck, causing all subsequent
StartDiscovery calls to fail with InProgress.

Changes:
- Rewrite ble_verify_scan() to use hciconfig instead of hcitool lescan
- Make ble_health_check() passive (read D-Bus properties only, no
  StartDiscovery/StopDiscovery) to avoid conflicts with Matter SDK scans
- Remove hciconfig down and hcitool cmd HCI_Reset from init sequence;
  simplify to hciconfig up with down/up recovery cycle
- Update usbip-validate.sh checks for revised BLE stack behavior
Copilot AI review requested due to automatic review settings May 20, 2026 19:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 6 comments.

# AF_BLUETOOTH (e.g. bluetoothctl) can run via nsenter.
- /proc/1/ns/net:/run/host-netns:ro
environment:
- DBUS_SYSTEM_BUS_ADDRESS=${DBUS_SYSTEM_BUS_ADDRESS:-unix:path=/var/run/otbr-dbus/system_bus_socket}
Comment thread docker/otbr-radio-entrypoint.sh Outdated
Comment on lines +86 to +104
echo "[otbr-radio] Starting private D-Bus system bus at ${DBUS_SYSTEM_BUS_ADDRESS}..."
mkdir -p "${DBUS_DIR}"
if [ -S "${DBUS_SOCKET_PATH}" ]; then
echo "[otbr-radio] Removing stale D-Bus socket ${DBUS_SOCKET_PATH}..."
rm -f "${DBUS_SOCKET_PATH}"
fi
dbus-daemon --config-file=/etc/otbr-dbus.conf --fork --nopidfile
echo "[otbr-radio] Private D-Bus started."

###############################################################################
# 2. Validate the USB radio device
###############################################################################
if [ -z "${RADIO_DEVICE}" ]; then
echo "[otbr-radio] ERROR: RADIO_DEVICE is not set." >&2
echo "[otbr-radio] Set it in docker/.env or export before starting:" >&2
echo "[otbr-radio] export RADIO_DEVICE=/dev/ttyACM0" >&2
echo "[otbr-radio] See docs/REMOTE_RADIO_FOR_DEVELOPMENT.md for setup instructions." >&2
exit 1
fi
Comment thread docker/otbr-agent.conf
Comment on lines +4 to +13
<listen>unix:path=/var/run/otbr-dbus/system_bus_socket</listen>
<auth>ANONYMOUS</auth>
<allow_anonymous/>
<policy context="default">
<allow own="io.openthread.BorderRouter.wpan0"/>
<allow send_destination="io.openthread.BorderRouter.wpan0"/>
<allow send_interface="*"/>
<allow user="*"/>
<allow own="*"/>
<allow send_type="*"/>
<allow receive_sender="*"/>
<allow send_destination="*"/>
<allow receive_type="*"/>
<allow receive_sender="*"/>
Comment thread scripts/remote-radio/usbip-validate.sh Outdated
Comment on lines +278 to +279
# Use timeout because bluetoothctl blocks if bluetoothd is not running.
BT_LIST=$(timeout 5 sudo nsenter --net="${HOST_NETNS}" bluetoothctl list 2>/dev/null || true)
Comment on lines +41 to +45
# scripts/usbip-attach-local.sh user@remote-server
# scripts/usbip-attach-local.sh remote-server # uses current username
#
# Leave the terminal open while you work. Press Ctrl-C to close the tunnel.
# Run scripts/usbip-detach-local.sh to clean up.
Comment on lines +308 to +314
char *endPtr = nullptr;
unsigned long val = strtoul(env, &endPtr, 10);

if (endPtr != env && *endPtr == '\0')
{
adapterId = static_cast<uint32_t>(val);
icInfo("Using BLE adapter hci%u from %s", adapterId, BLE_CONTROLLER_ADAPTER_ID_ENV);
@Lakshmi97-velampati Lakshmi97-velampati marked this pull request as draft May 26, 2026 14:03
Add infrastructure for running the otbr-radio container against a
remote cpcd instance over TCP, and work around two Silicon Labs CPC
BLE firmware bugs that prevent BLE scanning and connections from
working through the CPC radio.

Remote CPC mode
===============
When CPC_REMOTE_HOST is set, the entrypoint starts CPC socket proxy
clients instead of running cpcd locally.  The proxy tunnels CPC
SEQPACKET Unix sockets over TCP connections to a remote host running
cpc_remote_access.sh in server mode.  Six proxy instances are started:
ctrl, reset, and data+event for both the Bluetooth RCP (endpoint 14)
and Thread/Spinel (endpoint 12) endpoints.

New files:
- scripts/remote-radio/cpc_socket_proxy.py:
  Bidirectional SEQPACKET-over-TCP proxy with self-healing reconnect,
  TCP keepalive for fast stale-session detection, and automatic session
  eviction in server mode (CPC endpoints allow only one client).

- scripts/remote-radio/cpc_remote_access.sh:
  Server-side watcher that starts and monitors proxy server instances
  on the remote host where cpcd runs.

CPC BLE firmware workarounds (hci_pty_proxy.py)
===============================================
The Silicon Labs BRD2703 xG24 CPC BLE firmware has two HCI
compatibility bugs that prevent BLE from working with the Linux
kernel (tested on 6.8.0 / BlueZ 5.72):

Bug 1: Extended Scan Disable wrong opcode
  The firmware advertises LE Extended Advertising support in its
  feature set, but when the kernel sends LE Set Extended Scan Enable
  (opcode 0x2042) to disable scanning, the firmware responds with the
  wrong opcode (legacy 0x200c instead of 0x2042).  The kernel discards
  this unexpected response and the 0x2042 command times out.  Because
  scanning cannot be stopped, all subsequent LE Create Connection
  commands are rejected with "Command Disallowed" (HCI status 0x0c).

  Fix: The proxy intercepts the LE Read Local Supported Features
  response during controller init and clears the Extended Advertising
  feature bit (byte 1, bit 4 = 0x10).  This forces the kernel to use
  legacy BLE scan commands (0x200b/0x200c) which the firmware handles
  correctly.

Bug 2: Enhanced Connection Complete v2 event
  After clearing Extended Advertising support, the kernel only
  registers a handler for the legacy LE Connection Complete event
  (subevent 0x01).  However, the firmware sends LE Enhanced Connection
  Complete v2 (subevent 0x29, a BT 5.2+ event) when a connection is
  established.  The kernel silently discards this unknown subevent,
  the connection times out (HCI status 0x08), and the firmware is left
  with a phantom connection that generates periodic "ACL packet for
  unknown connection handle" errors in dmesg.

  Fix: The proxy translates Enhanced Connection Complete events
  (subevent 0x29 for v2, 0x0A for v1) into the legacy format
  (subevent 0x01) by stripping the Resolvable Private Address fields
  (12 bytes), Advertising_Handle (1 byte), and Sync_Handle (2 bytes),
  and rewriting the parameter length accordingly.

New file:
- scripts/remote-radio/hci_pty_proxy.py:
  HCI UART (H4) PTY proxy that sits between bt_host_cpc_hci_bridge
  and btattach.  Supports optional debug logging via HCI_PROXY_DEBUG
  env var for troubleshooting HCI event flow.

Entrypoint changes (otbr-radio-entrypoint.sh)
=============================================
- Add remote CPC mode: when CPC_REMOTE_HOST is set, start CPC socket
  proxy clients and skip local cpcd startup.
- Integrate HCI PTY proxy between bt_host_cpc_hci_bridge and btattach
  (section 5b).  Falls back gracefully if the proxy script is not
  mounted.
- Remove stale pts_hci symlink before starting bt_host_cpc_hci_bridge
  to prevent the PTY wait loop from seeing a stale file from a
  previous run.
- Simplify BLE init sequence: replace ble_verify_scan() and
  ble_health_check() with a deterministic down/up/HCI-Reset cycle
  followed by bluetoothd start.  The previous approach used hcitool
  lescan for verification which poisoned the MGMT layer.
- Simplify ble_monitor(): remove D-Bus health checks and bridge
  restart logic; just watch btattach and restart the BLE chain when
  it exits.

Compose changes (compose.otbr-radio.yaml)
==========================================
- Bind-mount cpc_socket_proxy.py, hci_pty_proxy.py, and the
  entrypoint script into the container.
- Add CPC_REMOTE_HOST, CPC_REMOTE_PORT, CPC_INSTANCE env vars.

Other changes
=============
- CommissioningOrchestrator.cpp: Close BLE connection after
  ThreadNetworkEnable completes to free the CPC radio for Thread
  traffic.  BLE and Thread share the single CPC radio and cannot
  operate simultaneously.
- devcontainer.json: Set DEBUGINFOD_URLS="" to prevent GDB from
  hanging on symbol downloads from the Ubuntu debuginfod server.
@github-actions
Copy link
Copy Markdown

Missing or incorrect copyright headers in the following files:
scripts/remote-radio/cpc_remote_access.sh
scripts/remote-radio/cpc_socket_proxy.py

Comment thread scripts/remote-radio/cpc_socket_proxy.py Fixed
@github-actions
Copy link
Copy Markdown

Missing or incorrect copyright headers in the following files:
scripts/remote-radio/cpc_remote_access.sh
scripts/remote-radio/cpc_socket_proxy.py

…ote radio stack

Remove CloseBleConnection() after ThreadNetworkEnable
------------------------------------------------------
CPC multiplexes BLE and Thread independently via separate endpoints
(ep14 for Bluetooth RCP, ep12 for 802.15.4/Spinel), so closing the
BLE connection after Thread network enable is unnecessary. Worse, it
prevents the Matter SDK from extending the commissioning failsafe
over BLE during CASE-over-Thread retries, causing commissioning to
fail when the first CASE attempt doesn't succeed immediately.

HCI PTY proxy: intercept Read Local Name (0x0C14)
--------------------------------------------------
The CPC firmware does NOT support HCI Read Local Name. It returns a
1-byte "Unknown HCI Command" error instead of the expected 249-byte
response. The kernel logs "unexpected cc 0x0c14 length: 1 < 249" and
mishandles the command completion — this corrupts the HCI command
queue, causes background scan-stop timeouts (-ETIMEDOUT), and leaves
bluetoothd in a permanently stuck state where StartDiscovery()
returns "InProgress" even though no scan is active.

The proxy now intercepts outgoing Read Local Name commands and returns
a synthetic success response with a placeholder name so the
unsupported command never reaches the CPC firmware. Also adds
Extended Advertising command interception (bytes 36-37 opcode
stripping) and LE feature bit stripping.

CPC socket proxy: support concurrent clients with retry
--------------------------------------------------------
Previously the proxy evicted stale sessions on new connections. Now
multiple TCP clients can connect concurrently (e.g. both the HCI
bridge and otbr-agent need their own ctrl session). Each TCP client
gets its own independent Unix socket connection to cpcd. Added retry
logic with backoff for endpoint sockets that cpcd creates on-demand
after the remote client opens them via the control socket.

otbr-radio entrypoint: resilient BLE bridge lifecycle
------------------------------------------------------
- Increase bt_host_cpc_hci_bridge wait timeout from 15s to 30s for
  remote CPC connections
- Convert bridge startup failures from fatal errors to warnings;
  the BLE monitor loop will retry
- Add BLE monitor loop that detects bridge/proxy crashes and restarts
  the full BLE stack (bridge -> proxy -> btattach -> bluetoothd)
- Add process reaping for zombie children
- Use python3 -u for unbuffered proxy output

CPC remote access: pre-start well-known endpoint proxies
---------------------------------------------------------
Pre-start TCP listeners for well-known CPC endpoints (ep12 for
802.15.4, ep14 for Bluetooth) before any remote client connects.
The proxy retries the local Unix socket connection with backoff,
giving cpcd time to create endpoint sockets on-demand. Added health
check loop to restart well-known proxies if they die.

setupDockerEnv.sh: persist CPC remote radio settings
-----------------------------------------------------
Preserve CPC_REMOTE_HOST, CPC_REMOTE_PORT, and CPC_INSTANCE in
docker/.env across setupDockerEnv.sh invocations, matching the
existing behavior for RADIO_DEVICE and BACKBONE_IF.

compose.otbr-radio.yaml: mount cpc_validate.sh
-----------------------------------------------
Bind-mount the CPC validation/diagnostic script into the otbr-radio
container at /opt/cpc-proxy/cpc_validate.sh.

Add cpc_validate.sh diagnostic script
--------------------------------------
Comprehensive validation script for the full CPC + BLE + Thread
stack in the otbr-radio container. Checks CPC connectivity, BLE
bridge, HCI proxy, BlueZ stack, BLE scanning, Thread interface,
and multi-user container detection safety.
@github-actions
Copy link
Copy Markdown

Missing or incorrect copyright headers in the following files:
scripts/remote-radio/cpc_remote_access.sh
scripts/remote-radio/cpc_socket_proxy.py
scripts/remote-radio/cpc_validate.sh

Comment thread scripts/remote-radio/cpc_socket_proxy.py Fixed
Replace the USB-IP and CPC socket proxy remote radio approach with a
simpler remote serial tunnel architecture.  The new design uses a single
Python script on the workstation that relays serial bytes over an SSH
reverse tunnel, eliminating the need for USB-IP kernel modules, multiple
helper scripts, and complex CPC socket proxying.

New files:
- scripts/remote-radio/remote-serial.py: Workstation-side relay that
  opens the local Silicon Labs radio serial port, starts a TCP server,
  and establishes an SSH reverse tunnel to the dev server.  Features
  auto-detection of radio ports, per-user port isolation (base 20000 +
  UID), persistent serial port across TCP reconnects, stale tunnel
  cleanup, and auto-reconnect for both serial and SSH.
- scripts/remote-radio/validate.sh: Comprehensive 8-section validation
  script covering container environment, D-Bus, radio connection, CPC,
  BLE chain, HCI, otbr-agent, and known pitfalls.  Auto-detects and
  re-execs into the otbr-radio container via Docker CLI or Docker Engine
  API (for environments without the docker command).
- docker/setup-thread-routes.sh: Configures IPv6 routing in the barton
  container so it can reach Thread mesh devices via the otbr-radio
  container.  Adds a fd00::/8 ULA catch-all route through otbr-radio's
  bridge address.  Runs as postStartCommand in the devcontainer.

Modified files:
- docker/otbr-radio-entrypoint.sh:
  - Add remote serial tunnel mode: when RADIO_HOST/RADIO_PORT are set,
    use socat to bridge TCP to a PTY instead of a local USB device
  - Resolve host.docker.internal to IPv4 (SSH tunnel binds IPv4 only)
  - Remove wait-slave from socat (prevents TCP lifecycle coupling to
    PTY slave state during cpcd init retries)
  - Use no-data TCP probe (: >/dev/tcp/) instead of echo to avoid
    sending garbage bytes to the radio during connectivity checks
  - Always set uart_hardflow: true (radio firmware requires it; cpcd
    exits with FATAL on mismatch even though CRTSCTS is a no-op on PTY)
  - Add stdbuf -oL for cpcd output buffering (ensures grep detects
    the ready message promptly)
  - Set accept_ra=2 on backbone interface (kernel drops RAs when
    forwarding=1 without this)
- docker/compose.otbr-radio.yaml:
  - Add sysctls for IPv6 forwarding and NDP proxy on otbr-radio
  - Add RADIO_PORT/RADIO_HOST environment variables
  - Add extra_hosts for host.docker.internal resolution
- docker/setupDockerEnv.sh:
  - Replace CPC_REMOTE_HOST/PORT/INSTANCE with RADIO_PORT/RADIO_HOST
- .devcontainer/devcontainer.json:
  - Add postStartCommand for Thread IPv6 route setup
- docs/REMOTE_RADIO_FOR_DEVELOPMENT.md:
  - Complete rewrite covering both local USB and remote serial tunnel

Deleted files (replaced by remote-serial.py + validate.sh):
- scripts/remote-radio/cpc_remote_access.sh
- scripts/remote-radio/cpc_socket_proxy.py
- scripts/remote-radio/cpc_validate.sh
- scripts/remote-radio/usbip-attach-local.sh
- scripts/remote-radio/usbip-attach-remote.sh
- scripts/remote-radio/usbip-detach-local.sh
- scripts/remote-radio/usbip-detach-remote.sh
- scripts/remote-radio/usbip-validate.sh
self._server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._server_sock.settimeout(2.0)
self._server_sock.bind(("127.0.0.1", self.listen_port))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants