Skip to content

End Device Initiator flag remains set when forwarding remote group commands #65

Closed

Description

@ChristophKaser

One caveat at the beginning: this whole investigation was done using an AI agent, I am not that knowledgeable in the zigbee stack.

Ziggurat currently forwards group commands (e.g. from a remote) with the NWK End Device Initiator flag still set. A bound light does not respond, although Ziggurat receives and retransmits the commands successfully.

Zigbee specification 05-3474-23, §3.3.1.1.8, requires the parent to clear this flag when relaying a message from an end-device child. Under §3.6.2.2, other routers must reject an initiator-marked message if the source is not an end device in their neighbor table.

Zigbee specification

Details

  • Tested revision: 392d4c7fe5c497d553977492bc02cb305573b7fc.
  • Remote: IKEA TRADFRI remote control.
  • Light: IKEA TRADFRI bulb E27 WW 806lm.
  • The remote’s On/Off and Level Control bindings point to group 3; the bulb’s queried membership includes group 3.

The raw capture shows the remote sending a MAC unicast to the coordinator with NWK destination 0xFFFD. Ziggurat broadcasts three copies, all with successful radio TX results. The NWK frame control remains 0x2248, retaining End Device Initiator. The source and sequence are preserved, and the radius decreases from 12 to 11.

In crates/ziggurat-driver/src/zigbee_stack/nwk.rs, maybe_relay_broadcast() clones the frame without clearing end_device_initiator. The unicast relay path also retains it.

I applied a local fix that clears the flag before forwarding, including broadcast retries and indirect copies. After deployment, toggle and brightness controls worked.

Activity

  1. TheJulianJES commented on Oct 14, 2026

    @TheJulianJES

    @zigpy-review-bot Investigate. Possibly also open PR(s). Do up to 6 review rounds for both code and PR description.

  2. zigpy-review-bot commented on Oct 14, 2026

    @zigpy-review-bot
    Contributor

    Thanks for the detailed analysis, it checks out. The Zigbee R23.2 spec (§3.3.1.1.8) requires a router parent to clear the End Device Initiator bit when relaying a frame from one of its end device children, and ziggurat never did, so routers that don't have the remote as their own child drop the relayed group command (§3.6.2.2).

    Fix: #66. It clears the bit for frames whose NWK source is one of our end device children, in both the broadcast relay (the relayed copy, its retransmits, and the copies queued for sleepy children) and the unicast relay (sender retries and the indirect queue). That matches the paths your local fix covered.

    Details
    • Spec §3.3.1.1.8: "After validating the source (see section 3.6.2.2), a router parent device SHALL clear this field when relaying a message sent by one of its end device children."
    • Spec §3.6.2.2: a receiver searches its neighbor table for an end device with the frame's source address and drops the frame if there is none; an end device receiver drops any frame with the bit set.
    • In crates/ziggurat-driver/src/zigbee_stack/nwk.rs, maybe_relay_broadcast, the sleepy-child fan-out and relay_unicast_nwk_frame all forwarded the frame with the bit unchanged.
    • Not part of Clear End Device Initiator when relaying an end device child's frame #66: ziggurat also doesn't enforce the receive-side check of §3.6.2.2 (dropping such frames from non-children and sending a Leave with Rejoin). That's noted as an open item on the PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    None yet

    Size

    None yet

    Area

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions