# Test a three-floor RPL network design

Test router and leaf roles, parent Rank and root-held routes before accepting a downward path to a floor-two actuator.

## Run on Linux x86-64 with Docker and X11

The image, Java, compiler and simulator ran on this host under Apptainer.
Docker is unavailable here: the laptop Docker invocation is syntax-reviewed,
not claimed as laptop-tested. Windows, macOS and ARM display setup is outside
this recipe. No paid service or account is required.

Download `lab-files.tar.gz` from this lab page. In a terminal:

```bash
mkdir cooja-lab
cd cooja-lab
tar -xzf ~/Downloads/lab-files.tar.gz
git clone --depth 1 --branch release/v4.9 https://github.com/contiki-ng/contiki-ng.git contiki-ng
test "$(git -C contiki-ng rev-parse HEAD)" = c20b12cd2db707d6c07918f8b26cfeb52cf298ca
git -C contiki-ng submodule update --init --depth 1 tools/cooja
test "$(git -C contiki-ng/tools/cooja rev-parse HEAD)" = 33d41ae9f8acd6075fb903b0bcd5b4122bad8d8f
mkdir -p jdk17 home/contiki-ng
curl -fL 'https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.20.1%2B1/OpenJDK17U-jdk_x64_linux_hotspot_17.0.20.1_1.tar.gz' -o jdk17.tar.gz
echo '3808d1d15e3ec6bd5b84057fb5d84c33d8a1536a258146bcea2e603fc726e08e  jdk17.tar.gz' | sha256sum -c -
tar -xzf jdk17.tar.gz --strip-components=1 -C jdk17
xhost +si:localuser:$(id -un)
bash cooja-rpl-network-design/docker-launch.sh
# After closing Cooja:
xhost -si:localuser:$(id -un)
```

The launcher binds the packet at `/lab`. Cooja loads `/lab/cooja-rpl-network-design.csc`
and compiles the included unmodified upstream C files. The project header enables
logging and any explicitly documented parameter changes. The supplied Makefiles
expect the recipe's `/home/user/contiki-ng` mount. The first Gradle build requires
Internet. To use your own native Java 17 installation, set CONTIKI in the supplied
Makefiles to your checkout and open the CSC with that release's Cooja.

The script starts automatically and stops at `TEST OK` or `TEST FAILED`. The GUI
stays open. Use **Mote output → Filter** to show the rows named in the steps;
clear the filter to inspect other messages. **File → Open simulation → Browse...**
loads another CSC. Reopen the original CSC for a fresh seed-1 run.
Times are simulated times, not wall-clock times. `expected-output.txt` is the
unaltered headless serial/test log, including actual measurements and the test result.

For headless Docker execution, replace `--gui --autostart` in the launcher with
`--no-gui --logdir=/lab/run-output` and remove the display requirement/mount.
Cooja writes `COOJA.testlog` under that writable output directory.

## Building scenario and roles

The original scenario has one root, two mains-powered router candidates per
floor, battery-role leaves and a floor-two actuator group. The small simulation
represents one leaf per floor, with mote 9 representing that actuator group:

| Role | IDs | Coordinates (m) |
|---|---|---|
| Root | 1 | (0,0) |
| Floor 3 routers | 2,3 | (-20,30), (20,30) |
| Floor 2 routers | 4,5 | (-20,60), (20,60) |
| Floor 1 routers | 6,7 | (-20,90), (20,90) |
| Floor 3 / floor 2 actuator / floor 1 leaves | 8,9,10 | (40,30), (40,65), (40,100) |

These are design-role assumptions: Cooja does not model mains supply, real
battery discharge, walls or actual floor elevations here. UDGM is 50/100 m,
seed 1, success ratios 1. The `leaves/project-conf.h` sets
RPL_CONF_DEFAULT_LEAF_ONLY=1; the router firmware leaves that mode disabled.
All application C is upstream rpl-udp. Leaf 9 sends telemetry like the other
clients and receives replies; the root also initiates a ping to its address.

## Measured design record

Root status at 130.065 s identifies instance 0, DODAG fd00::201:1:1:1,
MRHOF and Non-storing. Its route dump at 131.065 s includes root-held paths
for leaves 8→3, 9→3 and 10→5. At 134.065 s, router 4 lists candidate
2: Rank 256, metric 135, candidate 391. It also hears other routers; the
complete log retains the rejected candidates and freshness flags.

The root-to-9 ping at 140.065 s receives a reply 75 ms later. All nine clients
send telemetry successfully: 130 requests reach the root, with replies observed
at every client by 180 s. Packet replies and DAO/root route knowledge provide
separate proofs. “Non-storing” alone is not a downward-delivery measurement.
The final parent graph has 2→1, 3→1, 4→2, 5→3, 6→4, 7→5,
8→3, 9→3 and 10→5. In particular, a physical floor label does not force a
parent on the next floor: the radio model permits leaf 9 to hear router 3.

## Original candidate-Rank worksheet and tie

This is a deliberately simplified paper model, not a second measured Rank dump:
F2-A hears F3-A Rank 256 with local increase 256, and F3-B Rank 384 with
local increase 128. Both candidates give 512. Do not invent a winner.
Record both candidates and request current-link, freshness, hysteresis or policy
evidence. For a leaf, repeat all five fields: two candidates, advertised Rank,
local increase, resulting Rank, chosen parent and the confirming observation.
Compare that model with router 4's actual measured 256+135=391 decision.

## Mode decision and validation checklist

Write a one-page record with roles, DODAG hypothesis, parent evidence, traffic
inventory, mode choice and validation. Upward telemetry dominates; occasional
root-to-actuator packets require downward reachability. Peer traffic is rare
and is not tested. Non-storing keeps downward path knowledge at the root;
this candidate is supported by the observed root links and root-initiated ping.
Storing is a justified alternative only if local downward/peer requirements and
intermediate-router memory are measured. This lab does not run Storing firmware
or measure RAM consumption; record those as pending alternative-design tests.

List the expected DIO evidence for discovery/Rank, DAO evidence for downward
knowledge, one telemetry packet and one independently initiated downward packet.
Separate simulator packet proof from actual actuator action, security policy,
installed RF reliability, battery lifetime and external border routing.
The lab root has no external interface. Retest after a root, parent, firmware,
objective function, route mode, traffic mix or link-quality change. Use the
parent-switch lab for a measured relay-failure window before claiming repair.


## Tested version

Contiki-NG release/v4.9 c20b12cd, Cooja 4.8 (2022071901), Temurin 17.0.20.1, image sha256:b14d5afb0a2a852d9e72bbed607ead03f6ccc5f4d4dee44f0799110be2f4b609
