Matter 06 · 探索とメッセージング — DNS-SD と MRP

Chapter 06

探索とメッセージング — DNS-SD と MRP

この章がなぜ必要なのか——「見つからない」と「届かない」を分けて考える.

Matter の通信は 2 段階である。 まず 相手を見つける(DNS-SD)。次に 確実に届ける(MRP)。

トラブルの大半はこのどちらかで、症状は似ているが原因はまったく違う。 「見つからない」ならマルチキャストと mDNS を疑い、 「見つかるが応答しない」ならセッションと MRP を疑う。

この章は 21 章のデバッグの土台になる。

この章で使う既出の用語(定義は各リンク先). Matter(01 章 3 節)、コミッショニング(01 章 3 節)、セキュリティ(01 章 2 節)、ネットワーク(01 章 3 節)、ACL(02 章 4 節)、IPv6(02 章 1 節)、Node(02 章 2 節)、メッセージング(02 章 1 節)、マルチキャスト(03 章 3 節)、Channel(04 章 4 節)、Router(04 章 2 節)、Wi-Fi(04 章 9 節)、必要(05 章 5 節)

1. DNS-SD による探索

Matter は DNS-SD(DNS Service Discovery)でノードを見つける。 ローカルネットワークでは mDNS(マルチキャスト DNS、_5353/udp)を使う。

3 つのサービスタイプ

サービス用途いつ広告されるか
_matterc._udpコミッショニング可能な機器まだ Fabric に入っていない、または Commissioning Window が開いている
_matter._tcp運用中のノードFabric に参加済み
_matterd._udpコミッショナ(ユーザー主導のコミッショニング用)コミッショナ側が広告

_matter._tcp なのに UDP で通信する. 紛らわしいが、これは DNS-SD のサービス名の慣習によるもので、 実際のトランスポートは主に UDP(ポート 5540)である。 「なぜ _tcp なのか」を仕様上の意味で追う必要はない。そういうものだと覚える。

運用サービスのインスタンス名

<Compressed Fabric ID>-<Node ID>._matter._tcp.local.
      16 桁 16 進          16 桁 16 進

例:

DEDEDEDE00010001-0000000000000042._matter._tcp.local.
部分内容
Compressed Fabric IDRoot Public Key と Fabric ID から HKDF で導出した 64 bit(02 章)
Node IDその Fabric における Node ID(64 bit)

これがマルチアドミンの見え方である. 1 台の機器が 3 つの Fabric に所属していれば、 3 つの _matter._tcp インスタンスを広告する。 Fabric ごとに Compressed Fabric ID も Node ID も違うので、名前も違う。

dns-sd -B _matter._tcp で同じ機器が 3 行出てきても、それは正常である。

コミッショニング用サービスとサブタイプ

_matterc._udp にはサブタイプが付き、絞り込み検索ができる。

サブタイプ意味例
_S<n>Short Discriminator(上位 4 bit)_S15
_L<n>Long Discriminator(12 bit 全体)_L3840
_V<n>Vendor ID_V65521
_T<n>Device Type_T257
_CMCommissioning Mode_CM
# 特定の Discriminator の機器だけを探す
dns-sd -B _matterc._udp,_L3840

手動ペアリングコード(13 章)には Short Discriminator しか入らない. だから _S<n> サブタイプが用意されている。 QR コードなら Long Discriminator が入るので _L<n> で正確に絞れる。

TXT レコード

サービスには TXT レコードが付き、通信パラメータが入る。

共通(運用・コミッショニング両方)

キー意味単位
SIISession Idle Intervalms
SAISession Active Intervalms
SATSession Active Thresholdms
TTCP サポートのビットマップ—
ICD長時間アイドル運用(LIT)かどうか0/1

コミッショニング時のみ

キー意味
DDiscriminator(12 bit)
VP<VendorID>+<ProductID>(10 進)
CMCommissioning Mode(0=不可, 1=標準, 2=カスタム)
DTDevice Type
DNDevice Name(ユーザー向け表示名)
RIRotating Device Identifier
PH / PIPairing Hint / Pairing Instruction

SII / SAI が電池機器では決定的である. これはコントローラに「私は寝ているので、再送はこの間隔で待ってくれ」と伝える値である。 ここが正しく広告されていないと、コントローラが短い間隔で再送を繰り返し、 機器の電池を無駄に消耗させる(次節の MRP)。

RI(Rotating Device Identifier)は、 追跡を防ぎつつ機器を識別するための、定期的に変わる値である。 常に同じ ID を広告すると、通りすがりの第三者に機器の存在を追跡されうる。

2. Thread での探索の特殊事情

Thread デバイスは mDNS のマルチキャストを常時受信できない(04 章)。 そこで SRP(Service Registration Protocol)で Border Router に登録し、 Border Router が代理で mDNS を広告する。

[Thread 機器] ──SRP(ユニキャスト)──> [Border Router] ──mDNS──> [Wi-Fi 側]
確認コマンド見るもの
ot-ctl srp client state機器側の登録状態
ot-ctl srp server serviceBorder Router に登録されているサービス
dns-sd -B _matter._tcpWi-Fi 側から見えているか

この 3 段階のどこで切れているかを特定するのが、Thread のデバッグの基本である。

3. MRP — メッセージ信頼性プロトコル

Matter は主に UDP を使う。UDP には再送も順序保証もない。 そこで Matter 自身が信頼性を担保する仕組みを持つ。それが MRP である。

仕組み

要素内容
Message Counterメッセージごとの通し番号。重複検出と再送検出に使う
Reliability フラグ「このメッセージは ACK が必要」を示す
Standalone ACK応答すべきデータがないときの単独 ACK
Piggyback ACK応答メッセージに ACK を相乗りさせる
再送ACK が来なければバックオフして再送

Piggyback ACK が重要である. 「電球を点けろ」に対して「点けました」という応答を返すなら、 その応答が ACK を兼ねる。パケット数が半分になる—— 電池機器と 802.15.4 の狭い帯域では、これが効く。

再送のバックオフ

\(n\) 回目の再送までの待ち時間は、次の式で決まる。

\[ t(n) = i \cdot \text{MARGIN} \cdot \text{BASE}^{\max(0,\ n - \text{THRESHOLD})} \cdot \left(1 + U \cdot \text{JITTER}\right) \]
記号意味仕様上の値
\(i\)基準間隔。相手が Idle なら SII、Active なら SAI相手が広告する値
MARGINMRP_BACKOFF_MARGIN1.1
BASEMRP_BACKOFF_BASE1.6
THRESHOLDMRP_BACKOFF_THRESHOLD1
JITTERMRP_BACKOFF_JITTER0.25
\(U\)0〜1 の一様乱数—
—MRP_MAX_TRANSMISSIONS5

式の読み方.

決定的なのは \(i\)(SII / SAI)である。 相手が眠っている機器(SII が 5 秒など)なら、待ち時間も秒オーダーになる。 DNS-SD の TXT でこれを正しく広告していないと、 コントローラが数百 ms 間隔で再送を繰り返し、機器が受け取れないまま 5 回で諦めて失敗——という事故が起きる。

Active と Idle

状態使う間隔
直近の通信から SESSION_ACTIVE_THRESHOLD 以内SAI(短い)
それ以上経過SII(長い)

「さっきまで話していた相手なら、まだ起きているだろう」という前提である。

4. セッションの種類

Matter のメッセージは必ず何らかのセッションで保護される。

セッション確立方法いつ使う
Unsecuredなしセッション確立のハンドシェイクそのもの
PASEパスコード(SPAKE2+)コミッショニング時のみ(13 章)
CASE証明書(SIGMA)運用時(14 章)
Group事前共有のグループ鍵マルチキャストによる一斉制御

PASE と CASE の使い分けは明確である.

PASE で確立したセッションはコミッショニングが終われば破棄される。 以降はすべて CASE である。

5. メッセージの構造(概略)

┌──────────────────────────────────────────────┐
│ Message Header(平文)                        │
│  Session ID / Message Counter / Source Node…  │
├──────────────────────────────────────────────┤
│ ↓ ここから暗号化・認証(AES-CCM)              │
│ Protocol Header                               │
│  Exchange ID / Protocol ID / Opcode           │
├──────────────────────────────────────────────┤
│ Application Payload(TLV)                    │
├──────────────────────────────────────────────┤
│ Message Integrity Check(MIC, 16 bytes)      │
└──────────────────────────────────────────────┘
概念意味
Session暗号化の単位。鍵が紐づく
Exchange1 往復のやりとりの単位。要求と応答を対応づける
Protocol IDSecure Channel / Interaction Model / BDX / User Directed Commissioning
Message Counter単調増加。リプレイ攻撃を防ぐ

ヘッダの一部が平文であることに注意. Session ID や Message Counter は、復号する前に必要なので平文である。 ただし認証はされている(MIC の計算対象に含まれる)ので、改竄はできない。

一方、Source/Destination Node ID がヘッダに露出しうる点は、 プライバシー上の考慮事項になる。仕様にはこれを難読化する仕組み (Privacy 拡張)も定義されている。

6. デバッグの手順

「見つからない」とき

1. dns-sd -B _matterc._udp(または avahi-browse)でサービスが見えるか
       ↓ 見えない
2. ping6 ff02::1 で機器が IPv6 レベルで見えるか
       ↓ 見えない → ネットワークの問題([03 章](03_IPv6の基礎.md#切り分けの順序))
       ↓ 見える  → mDNS の問題(マルチキャスト遮断、Thread なら SRP)
3. Thread なら ot-ctl srp server service で登録を確認

「見つかるが応答しない」とき

1. サービスの TXT レコードを確認(dns-sd -L で詳細)
       → SII / SAI が異常に大きくないか
2. 機器のログでセッション確立まで進んでいるか
       ↓ PASE/CASE が失敗 → 証明書・パスコードの問題([12 章](12_デバイス認証と証明書.md)〜[14 章](14_運用時のセキュリティ.md))
       ↓ 成立している    → ACL の問題([14 章](14_運用時のセキュリティ.md))or 未実装のコマンド
3. MRP の再送ログを見る(何回再送して諦めたか)
# サービスの詳細(TXT レコードとポート)を見る
dns-sd -L <instance-name> _matter._tcp local.
avahi-browse -r _matter._tcp

# 実際に解決してみる
dns-sd -G v6 <hostname>.local.

7. 落とし穴

落とし穴内容
SII/SAI を広告しないコントローラが短周期で再送し、電池機器が応答できない
コミッショニング後も _matterc._udp を出し続けるセキュリティ上・混乱の元
mDNS の再登録漏れIP が変わったのにレコードを更新せず、到達不能になる
Compressed Fabric ID の誤計算名前が合わず発見されない
SRP のリース切れ一定時間後に消える。定期更新が必要
Exchange ID の使い回し応答の対応づけが壊れる
メッセージカウンタの巻き戻しリプレイ検出に引っかかり拒否される(不揮発に保存すること)

メッセージカウンタの永続化は見落とされやすい. 再起動でカウンタが 0 に戻ると、相手は「古いメッセージだ」と判断して破棄する。 仕様に沿った初期化・保存が必要である。SDK は対応しているが、 独自にストレージ層を実装した場合は要注意である。

8. まとめ