Carry mDNS interface scope_id for link-local IPv6 sends#13
Open
vbondarevsky wants to merge 1 commit into
Open
Conversation
Matter devices commonly advertise only a link-local IPv6 operational address (fe80::/10). Sending UDP to such an address requires the interface zone (scope_id); without it sendto fails with EINVAL (IPv4 socket) or No route to host (IPv6 socket), so commissioning/operation never completes. Capture the interface index on which each device's mDNS reply was received (ll_scope map in MdnsService), expose it as MatterDeviceInfo::scope_id, encode it into the address as [fe80::..%idx]:port (discover::addr_string), and apply it as the scope_id when sending (transport split_scope + Connection::scope_id). Incoming datagrams are matched zone-insensitively (scopeless_key).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Devices that advertise only a link-local IPv6 operational address (fe80::…) can't be reached: every UDP send fails with EINVAL (IPv4 socket) or No route to host (IPv6 socket), so CASE/commissioning never completes.
Cause
A link-local address needs the interface zone (scope_id) to be sendable — fe80::/64 exists on every interface. The address was taken from mDNS without a zone, so scope_id was 0.
Fix
Carry the scope from where it's known to where it's needed:
mdns2 records the interface each link-local AAAA reply arrived on (MdnsService::scope_for).
MatterDeviceInfo::scope_id is set from it; discover::addr_string encodes [fe80::…%idx]:port.
transport parses the zone (split_scope), stores it on Connection, and applies it as scope_id on send; inbound datagrams are matched zone-insensitively.
The scope comes from the actual receive interface, so it's correct on multi-interface hosts (no guessing). Non-link-local and IPv4 paths are unchanged.
Test
Verified end-to-end against a real accessory (Shelly Presence, Wi-Fi) on macOS: BLE commissioning → CASE → CommissioningComplete, and operational attribute reads