SSH access to DUTs¶
How ssh dut-X reaches each DUT through its isolated VLAN, and how to connect manually when a DUT is on mesh VLAN 200.
Static ProxyCommand¶
Each DUT SSH alias in ~/.ssh/config uses labgrid-dut-proxy, which queries the switch PVID then execs labgrid-bound-connect on vlan<PVID>. Template: configs/templates/ssh_config_fcefyn.
Host dut-belkin-1
User root
ProxyCommand sudo labgrid-dut-proxy belkin-1 192.168.1.1 22
labgrid-bound-connect uses socat with SO_BINDTODEVICE. Isolated DUTs all use 192.168.1.1; the interface is what distinguishes them. The proxy must not block on /tmp/switch.lock: Switch SSH lock.
VLAN lifecycle during tests¶
sequenceDiagram
participant Test as pytest
participant Switch as TP-Link switch
participant DUT as DUT
Note over DUT: Default: isolated VLAN (100-108)
Test->>Switch: set_port_vlan(dut, 200)
Note over DUT: Mesh VLAN 200
Test->>DUT: run tests via SSHProxy(vlan200)
Test->>Switch: restore_port_vlan(dut)
Note over DUT: Back to isolated VLAN
- openwrt-tests: VLANs never change. DUTs always on isolated VLANs.
- libremesh-tests:
conftest_vlan.pymoves ports to VLAN 200 at test start and restores on teardown. A cancelled CI job skips teardown; runswitch-vlan --restore-allon the host. - Tests use their own SSH path (
SSHProxywith hardcodedvlan200), not the~/.ssh/configaliases. - SSH transport retry:
SSHProxyautomatically retries up to 3 times on exit code 255 (TCP/SSH transport errors). These are common during batman-adv/babeld convergence right after boot. - IP watchdog: After boot, a background script on each DUT re-applies the fixed mesh SSH IP every 3 seconds for 300 seconds, targeting
br-lanwhen UP. This survives network restarts triggered by OpenWrt init scripts or batman-adv configuration.
VLAN switching: local vs remote¶
Only the lab host owns the switch credentials (SNMP access, switch-vlan CLI, dut-config.yaml). The developer machine does not.
conftest_vlan.py handles both scenarios transparently:
| Execution | LG_PROXY |
How switch-vlan runs |
|---|---|---|
| From lab host (CI, local dev) | Not set | subprocess.run(["switch-vlan", "dut", "200"]) |
| From remote developer machine | labgrid-fcefyn |
subprocess.run(["ssh", "labgrid-fcefyn", "switch-vlan dut 200"]) |
flowchart LR
subgraph Remote["Developer machine"]
pytest["pytest"]
end
subgraph Host["Lab host"]
switch_vlan["switch-vlan"]
switch["TP-Link switch<br/>(SNMP)"]
end
pytest -->|"ssh labgrid-fcefyn<br/>switch-vlan dut 200"| switch_vlan
switch_vlan -->|SNMP| switch
Result: Developers do not need to install switch-vlan, configure switch credentials, or have dut-config.yaml locally. VLAN operations are delegated to the host via SSH.
Manual access to mesh VLAN 200¶
If a test crashes before VLAN teardown, a DUT may be stuck on VLAN 200. From the lab host (where vlan200 and sudo NOPASSWD for labgrid-bound-connect exist):
sudo labgrid-bound-connect vlan200 <mesh_ssh_ip> 22
There are three addresses worth distinguishing during mesh tests:
192.168.1.1: the default OpenWrt LAN IP. This is what isolated single-node access uses throughvlan100-vlan108.10.13.200.x: the per-DUT mesh SSH/control IP. It is a stable secondary address added onbr-lanso the host can reach each DUT uniquely while multiple nodes share VLAN 200.10.13.x.xexcluding10.13.200.x: the real LibreMesh address onbr-lan. This is the address mesh assertions should use for ping, ARP, and routing checks.
Remote developer (LG_PROXY)¶
From a developer machine, the vlan200 interface lives on the lab host, not on the developer machine. The bound-connect must therefore run on the host via SSH. The test suite handles this automatically (see SSHProxy._build_ssh_cmd in conftest_mesh.py); for manual SSH from a machine:
ssh -o ProxyCommand="ssh ${LG_PROXY:-labgrid-fcefyn} sudo /usr/local/sbin/labgrid-bound-connect vlan200 <mesh_ssh_ip> 22" \
root@<mesh_ssh_ip>
sequenceDiagram
participant Machine as Dev machine
participant Host as Lab host (LG_PROXY)
participant DUT as DUT mesh (10.13.200.x)
Machine->>Host: ssh (LG_PROXY)
Host->>Host: sudo labgrid-bound-connect vlan200 IP 22
Host->>DUT: TCP socket bound to vlan200
Machine->>DUT: SSH session through nested ProxyCommand
Pre-requisites on the host (already in place for labgrid-dev per host-config 3.4): SSH user must have sudo NOPASSWD for /usr/local/sbin/labgrid-bound-connect. No local dut-config.yaml nor labgrid-switch-abstraction install is required on the developer machine.
Per-DUT isolated VLAN and mesh SSH IP table: Rack cheatsheets - all DUTs.
To restore all ports to isolated VLANs after a crash:
switch-vlan --restore-all