Skip to content

Cancel pending requests when a device leave or rejoins - #92

Merged
puddly merged 24 commits into
devfrom
puddly/forget-node-state-on-rejoin
Nov 12, 2026
Merged

puddly merged 24 commits into
devfrom
puddly/forget-node-state-on-rejoin

Conversation

@puddly

@puddly puddly commented Nov 10, 2026

Copy link
Copy Markdown
Member

When a device rejoins, pending route requests to it will not be answered and all pending requests to it should be invalidated.

Should address #88 alongside #89.

@zigpy-review-bot zigpy-review-bot added the bugfix This PR fixes a bug label Nov 11, 2026
@puddly
puddly marked this pull request as ready for review November 11, 2026 19:46
Copilot AI balanced review requested due to automatic review settings November 11, 2026 19:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Active issues leave stale route-discovery entries after discovery removal and allow queued Leave requests to survive a rejoin, potentially forcing a freshly rejoined device to leave again.

2 open issues
What changed in this PR

This PR clears stale per-device state on joins, rejoins, and departures, complementing #89’s routing changes to address the pairing delays in #88.

Changes:

  • Remove routes, route records, and related discovery entries for a device.
  • Clear APS duplicate tracking and fail pending unrouted sends when its session resets.
  • Preserve session state when learning address mappings from ordinary traffic.
File Description
crates/​ziggurat-zigbee/​src/​nwk/​routing.rs Adds per-device routing-state cleanup.
crates/​ziggurat-driver/​src/​zigbee_stack/​nwk.rs Adds session cleanup while preserving state during ordinary address learning.
crates/​ziggurat-driver/​src/​zigbee_stack/​joining.rs Invokes cleanup when devices leave.

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Rejoin cleanup leaves stale sends and old-address state active and accepts outdated leave reports, allowing prior-session traffic or events to disrupt the new session.

4 open issues
2 resolved since last review

Review effort: Balanced

@puddly puddly changed the title Forget node state on rejoin Cancel pending requests when a device leave or rejoins Nov 11, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Incomplete leave/rejoin cleanup leaves stale routing state and pending unicasts active, allowing old-session retries—including leave requests—to disrupt rejoined devices.

No open issues 🎉

3 previously missed issues

In code that hasn't changed since last review

Medium severity Preserve old-address route state until rejoin invalidation

crates/​ziggurat-driver/​src/​zigbee_stack/​nwk.rs:185

For a secured rejoin under a different short address, this overwrites the old mapping before handle_rejoin_request calls update_nwk_eui64_mapping. That helper then sees the new address as previous_nwk, leaving the old address's cached routes, pending discoveries, and route-request broadcasts intact. Skip this cache update for RejoinRequest frames so the rejoin handler can invalidate the previous address before replacing its mapping.

Medium severity Reset route discoveries originated by the rejoining device

crates/​ziggurat-zigbee/​src/​nwk/​routing.rs:297

This retains discoveries originated by the rejoining device, even though its route-request identifier can restart with the new session. A new request reusing an old identifier is then compared against the previous session's forward_cost in accept_route_request and is rejected if its new path costs more; relayed replies can also be rejected against the stale residual_cost. Reset discovery state originating at the rejoining nwk, not only our discoveries targeting it, while keeping any necessary late-copy suppression separate.

Medium severity Prevent failed in-flight indirect sends from requeueing after rejoin

crates/​ziggurat-zigbee/​src/​sends/​unicasts.rs:364

An indirect frame already transmitting when the device rejoins is skipped here, but it can still be retried afterward: on a failed radio report, transmitted returns it to AwaitingPoll while its persistence deadline remains live. If that frame is the stale-child leave request, the rejoined device receives it on its next poll and is told to leave again. Although the current copy cannot be recalled, mark the in-flight record as cancelled so its report settles it rather than requeueing it.

4 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Rejoin handling leaves pending sends and route-request broadcasts active for the previous address and can drop valid replies for retained relayed discoveries, causing router timeouts.

2 open issues

Review effort: Balanced

@puddly
puddly merged commit 8acaa19 into dev Nov 12, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix This PR fixes a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants