# Measure a parent-switch recovery window

Remove the selected RPL relay, measure target-node packet loss and recovery, then restore the link and test the return path again.

## 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-parent-switch/docker-launch.sh
# After closing Cooja:
xhost -si:localuser:$(id -un)
```

The launcher binds the packet at `/lab`. Cooja loads `/lab/cooja-rpl-parent-switch.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.

## Reproducible intervention and measured window

Root 1 is (0,0); 2 (-30,25), 3 (30,25), 4 (-60,55), target 5 (0,55),
6 (60,55). UDGM transmit/interference 50/100 m, success ratios 1, seed 1.
All application C is unchanged rpl-udp, with shell/logging enabled. MRHOF and
Non-storing are reported by the running stack. Script events are scheduled
relative to the first mote log at 0.065 s; the final timeout is at 300 s.

Headless runs proceed through all phases automatically. The same CSC pauses
only in GUI mode at about 89.065 s and 150.065 s so you can inspect before
and changed states. Click **Start/Pause** once at each pause to continue.
At 90.065 s the script reads target 5's actual parent (3), saves its position,
and moves that relay to (300,300). At 210.065 s it restores the saved position.

| Evidence | Observed simulated time/state |
|---|---|
| Baseline target state | 85.065 s: parent 3, Rank 422 |
| Relay removal | 90.065 s |
| First target parent change | 100.760728 s: parent 2 |
| First recovered target request at root | 110.644856 s |
| First recovered target reply | 110.711112 s |
| Changed state snapshot | 140.065 s: parent 2, Rank 420 |
| Root-to-target ping | 145.136 s reply, 71 ms delay, ttl 63 |
| Relay restored | 210.065 s |
| Restored-link target snapshot | 260.065 s: parent 2, Rank 395 |
| Second root-to-target ping | 270.166 s reply, 101 ms delay, ttl 63 |

Parent selection changed after 10.695728 s. The first successful target uplink
and reply came 20.579856 s and 20.646112 s after the fault. These are the
first observed successes, not continuous millisecond-by-millisecond outage
measurements. The target sent 12 requests between removal and restoration:
10 reached the root and all 10 replies reached the target, so two transmitted
requests lacked root reception. The complete serial log preserves sequence
numbers and all intermediate route changes. Whole-network totals are 98 sent
and 91 received, which include other affected clients; do not mix them with
the target-only 10/12 result.

The final annotation map has active parents only for 2→1, 4→2 and 5→2.
Restoring relay 3 does not demonstrate complete recovery of its subtree by
300 s. Accept the target path, not a claim of global repair. A later run with
a longer observation window would be required for the remaining nodes.

## Preserve the original forwarding-harness worksheet

Use connected `192.168.1.0/24 dev radio`, static `10.0.0.0/8 via A`, more
specific `10.2.4.0/24 via B`, and default `0.0.0.0/0 via C` as paper inputs.
These IPv4 entries are not installed in the simulated IPv6 network.

| Packet case | Selected row / action | Evidence still needed |
|---|---|---|
| destination 192.168.1.50 | connected /24, local-link forward | neighbor resolution |
| destination 10.2.4.77, counter 64 | /24 via B; reject broader /8 even with lower metric; counter becomes 63 | next-hop and packet reply |
| destination 198.51.100.20 | default via C | gateway and return route |
| same remote packet, counter 1 | select route then drop expired at forwarding router | expiry log/ICMP policy |
| return packet with no matching/default route | drop no route | separate return-table snapshot |

For each row write packet ID/direction, source/destination, counter before/after,
all matching prefixes, source of route, selected prefix, next hop/interface,
action and supporting record. This is the original deterministic forwarding
worksheet, not a claim that the RPL simulation installed those IPv4 routes or
captured a deliberate Hop Limit=1 fault. The live ping replies provide actual
IPv6 ttl=63 observations over the two-hop target path.

## Recovery and metric conclusion

Finish six records: baseline, trigger, transient state, stable target state,
packet/return proof, limitation. Name the exact parent replaced, the two missing
target requests, first successful uplink/reply times, and the lack of original
parent return by the deadline. No loop diagnosis is inferred merely from a
missed packet. Record the owner and retest trigger as well as pass/fail.

For the original metric-choice exercise compare a short lossy path with a longer
steady path using the objective-functions lab's actual neighbor metrics and
retransmission records. Hop count alone can hide loss; extra hops alone do not
prove resilience. State which metric and eligible candidate set support a
choice. Neither this target recovery nor a better ETX score proves external
border-router routing, security policy, application retries or installed RF.
Retest after topology, objective function, firmware, root or traffic changes.


## Tested version

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