アプリケーションサーバーは、次のイベントでデバイスセッションの終了を確認する必要があります(つまり、 dev.PendingSession
をdev.Session
に移動します)。
現在、ASがこの切り替えが発生したことを認識せずに、NSがセッションを「切り替える」可能性があります。 @rvolosatovsは、次のシーケンスを使用してこれをv3.11
再現しました。
dev.PendingSession
として認識しますDownlinkQueueInvalidated
イベントをASに送信しますdev.Session
がないため、このダウンリンクキューの無効化を拒否しますこの時点で、NSがFPort = 0を送信したときに発生したFCnt
増加を基本的に拒否したため、NSが将来別の無効化を送信しない限り、ASはこのセッションでダウンリンクを再度スケジュールすることはできません。ダウンリンク(そして今、FCntは常に低すぎます)。
将来無効化が発生しない限り、セッションは回復しません。
SessionKeyID
をDownlinkQueueInvalidation
追加します。 キューが空の場合、ASは現時点でどのキューが無効にされたかを知ることができません。dev.Session
であると常に想定するのではなく、正しいセッションのキュー+ FCntを更新する必要があります。nacked
メッセージがどのセッションからのものかを確認する必要があります- nacked
メッセージが(ASの観点から)保留中のセッションからのものである可能性があるため、FCntの更新は正しいセッション。Summary
記載されているメッセージが発生したときに、as shouldセッションをdev.PendingSession
とdev.Session
間で切り替える必要があります。v3.11
handleUplink
から移動し、適切なすべてのアップリンクタイプで実行します。FCnt
でDownlinkQueue{Push|Replace}
エラーの詳細を返し、常にLastAFCntDown
をこの値に更新します。 これにより、何らかの理由でASとNSの間で同期がとれていない場合に、システムが確実に収束します。再現手順に記載されているシーケンスを再現してみてください。
はい。ただし、これは重要な変更であるため、最初にこの問題にdiscussion
タグを付けるようにお願いしています。これらの変更を導入しますか? ダウンリンクキューの無効化の1つは要件のようですが、他の無効化は一貫性に優れています。
cc @rvolosatovs
すでに説明したように、私はこれに賛成です。
アプリケーションサーバーは、デバイスセッションに関する最新のデータを常に保持しているため、常にネットワークサーバーを信頼する必要があります。
- エンドデバイスはFPort = 0アップリンクを送信します-ASはこのアップリンクを受信しません
NSがこれを送信するようにこれを変更する必要がありますが、ペイロードが空でFPort 0を使用して、アップストリームに送信されないようにしますか?
- エンドデバイスはFPort = 0アップリンクを送信します-ASはこのアップリンクを受信しません
NSがこれを送信するようにこれを変更する必要がありますが、ペイロードが空でFPort 0を使用して、アップストリームに送信されないようにしますか?
NS-> ASメッセージングは非同期であるため、セッションを確認するためにFPort==0
アップリンクがASに送信される前にキューの無効化が到着する可能性があるため、冗長です。とにかくこれを行う必要があります。 NSへのFPort==0
アップリンクに応答してASにアップリンクを送信する唯一の理由は、ASにセッション変更ができるだけ早く通知されるようにするためですが、そのような必要はありません。 それでも、NSがFPort 0アップリンクの代わりにASに送信するSessionSwitch
メッセージを導入する方が理にかなっています。
v3.11.1
展開に影響しているため、優先度をprio/high
アップグレードしました。
変更は次のようになります。
SessionKeyID
をDownlinkQueueInvalidation
追加します。 キューが空の場合、ASは現時点でどのキューが無効にされたかを知ることができません。次のproto
追加(フィールド3
)で十分です。
message ApplicationInvalidatedDownlinks {
repeated ApplicationDownlink downlinks = 1;
uint32 last_f_cnt_down = 2;
bytes session_key_id = 3 [(gogoproto.customname) = "SessionKeyID", (validate.rules).bytes.max_len = 2048];
}
dev.Session
であると常に想定するのではなく、正しいセッションのキュー+ FCntを更新する必要があります。常にdev.Session
を使用する代わりに、使用するセッションを確立するためにSessionKeyID
をオンにします。 必要に応じて、現在のdev.Session
更新します。
nacked
メッセージがどのセッションからのものかを確認する必要があります- nacked
メッセージが保留中のセッションからのものである可能性があるため(ASの観点から)、FCntの更新は正しいセッション。前と同じように、使用するセッションを決定するためにSessionKeyID
をオンにします。 必要に応じて、現在のdev.Session
更新します。
FCnt
でDownlinkQueue{Push|Replace}
エラーの詳細を返し、常にLastAFCntDown
をこの値に更新します。 これにより、何らかの理由でASとNSの間で同期がとれていない場合に、システムが確実に収束します。次のproto
追加を入力し、エラーの詳細としてNSのerrFCntTooLow
に追加する必要があります。
message UpdateDownlinkQueueErrorDetails {
bytes session_key_id = 1 [(gogoproto.customname) = "SessionKeyID", (validate.rules).bytes.max_len = 2048];
uint32 last_f_cnt_down = 2;
}
ASはこれらの詳細を取得し、現在のセッションを更新できます。
変更には下位互換性があり、NS側では最小限であることが望まれます。 魔神はすでにボトルから出ています-ASとNSの間のプロトコル全体がゆっくりと非同期になり、 FPort=0
変更を元に戻すだけでは十分ではありません。 結局のところ、この変換が間違っていたとは思いませんが、セッションの双模倣に関するこれらの癖を修正する必要があります。
cc @ johanstokking 、 @ rvolosatovs
私にはいいですね!
ここでできることはありますか? もしそうなら、私を再割り当てして、私に何を知らせてください。
ここでできることはありますか? もしそうなら、私を再割り当てして、私に何を知らせてください。
私はすでにこれに取り組んでおり、次の点に非常に重点を置いています。
* (Optional) return error details on `DownlinkQueue{Push|Replace}` with the minimum `FCnt` and always update the `LastAFCntDown` to this value. This would ensure that the system converges if at any point we're for some reason out of sync between AS and NS.
これは、キューの一部としてNSから受信したイベントに基づいてアクションを実行するだけでは、基本的に十分ではないためです。
これらの特性を考えると、2つのオプションがあります。
dev.Session.SessionKeyID
、 dev.PendingSession.SessionKeyID
、およびLastAFCntDown
返すということです。 次に、エラーの詳細を使用して、ASでセッションを再構築します。 基本的に、これは、古いデータ(おそらく古いセッション、おそらくFCntが低すぎる)を使用してダウンリンクキュー操作を実行しようとすると、最終的にNS状態に収束することを意味します。 1、2、3回の試行が必要になる場合があります。無限に回転するのを避けるために制限を設けますが、少なくともアップリンクメッセージキューからの情報よりも大幅に新しい情報で動作しています。
- ただ_NSを信頼する_。 これが意味するのは、プッシュ/置換操作は、エラーの詳細の一部として、
dev.Session.SessionKeyID
、dev.PendingSession.SessionKeyID
、およびLastAFCntDown
返すということです。 次に、エラーの詳細を使用して、ASでセッションを再構築します。 基本的に、これは、古いデータ(おそらく古いセッション、おそらくFCntが低すぎる)を使用してダウンリンクキュー操作を実行しようとすると、最終的にNS状態に収束することを意味します。 1、2、3回の試行が必要になる場合があります。無限に回転するのを避けるために制限を設けますが、少なくともアップリンクメッセージキューからの情報よりも大幅に新しい情報で動作しています。
これが最良の選択肢だと思います。
最も参考になるコメント
v3.11.1
展開に影響しているため、優先度をprio/high
アップグレードしました。変更は次のようになります。
SessionKeyID
をDownlinkQueueInvalidation
追加します。 キューが空の場合、ASは現時点でどのキューが無効にされたかを知ることができません。次の
proto
追加(フィールド3
)で十分です。dev.Session
であると常に想定するのではなく、正しいセッションのキュー+ FCntを更新する必要があります。https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1020 -L1038
常に
dev.Session
を使用する代わりに、使用するセッションを確立するためにSessionKeyID
をオンにします。 必要に応じて、現在のdev.Session
更新します。nacked
メッセージがどのセッションからのものかを確認する必要があります-nacked
メッセージが保留中のセッションからのものである可能性があるため(ASの観点から)、FCntの更新は正しいセッション。https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1060 -L1073
前と同じように、使用するセッションを決定するために
SessionKeyID
をオンにします。 必要に応じて、現在のdev.Session
更新します。FCnt
でDownlinkQueue{Push|Replace}
エラーの詳細を返し、常にLastAFCntDown
をこの値に更新します。 これにより、何らかの理由でASとNSの間で同期がとれていない場合に、システムが確実に収束します。次の
proto
追加を入力し、エラーの詳細としてNSのerrFCntTooLow
に追加する必要があります。ASはこれらの詳細を取得し、現在のセッションを更新できます。
変更には下位互換性があり、NS側では最小限であることが望まれます。 魔神はすでにボトルから出ています-ASとNSの間のプロトコル全体がゆっくりと非同期になり、
FPort=0
変更を元に戻すだけでは十分ではありません。 結局のところ、この変換が間違っていたとは思いませんが、セッションの双模倣に関するこれらの癖を修正する必要があります。cc @ johanstokking 、 @ rvolosatovs