Lorawan-stack: ネットワークサーバーメッセージに基づいてエンドデバイスセッションを確認します

作成日 2021年01月08日  ·  8コメント  ·  ソース: TheThingsNetwork/lorawan-stack

概要

アプリケーションサーバーは、次のイベントでデバイスセッションの終了を確認する必要があります(つまり、 dev.PendingSessiondev.Sessionに移動します)。

  • アップリンクメッセージ(すでに発生しています)
  • ダウンリンクack
  • ダウンリンクナック
  • ダウンリンクに失敗しました(エラーが不明なセッションでない場合)
  • ダウンリンクキューが無効になりました

なぜ私たちはこれが必要なのですか?

現在、ASがこの切り替えが発生したことを認識せずに、NSがセッションを「切り替える」可能性があります。 @rvolosatovsは、次のシーケンスを使用してこれをv3.11再現しました。

  • エンドデバイスが参加します-ASはこのセッションをdev.PendingSessionとして認識します
  • エンドデバイスはFPort = 0アップリンクを送信します-ASはこのアップリンクを受信しません
  • ネットワークサーバーはFPort = 0ダウンリンクをスケジュールします
  • ネットワークサーバーはDownlinkQueueInvalidatedイベントをASに送信します
  • ASにはdev.Sessionがないため、このダウンリンクキューの無効化を拒否します

この時点で、NSがFPort = 0を送信したときに発生したFCnt増加を基本的に拒否したため、NSが将来別の無効化を送信しない限り、ASはこのセッションでダウンリンクを再度スケジュールすることはできません。ダウンリンク(そして今、FCntは常に低すぎます)。

すでに何がありますか? あなたは今何を見ていますか?

将来無効化が発生しない限り、セッションは回復しません。

何が欠けている? あなたは何が見たいですか?

  • SessionKeyIDDownlinkQueueInvalidation追加します。 キューが空の場合、ASは現時点でどのキューが無効にされたかを知ることができません。
  • ASは、無効化が約dev.Sessionであると常に想定するのではなく、正しいセッションのキュー+ FCntを更新する必要があります。
  • ASは、 nackedメッセージがどのセッションからのものかを確認する必要があります- nackedメッセージが(ASの観点から)保留中のセッションからのものである可能性があるため、FCntの更新は正しいセッション。
  • 最後に、ASは、 Summary記載されているメッセージが発生したときに、as shouldセッションをdev.PendingSessiondev.Session間で切り替える必要があります。

環境

v3.11

これをどのように実装することを提案しますか?

  • 必要なプロトフィールドを追加し、NS側に入力します。
  • 無効化/ナック中に使用しているセッションを確認し、ASでそのセッションを更新してください。
  • セッション切り替え手順をhandleUplinkから移動し、適切なすべてのアップリンクタイプで実行します。
  • (オプション)最小FCntDownlinkQueue{Push|Replace}エラーの詳細を返し、常にLastAFCntDownをこの値に更新します。 これにより、何らかの理由でASとNSの間で同期がとれていない場合に、システムが確実に収束します。

これをどのようにテストすることを提案しますか?

再現手順に記載されているシーケンスを再現してみてください。

これを自分で行い、プルリクエストを送信できますか?

はい。ただし、これは重要な変更であるため、最初にこの問題にdiscussionタグを付けるようにお願いしています。これらの変更を導入しますか? ダウンリンクキューの無効化の1つは要件のようですが、他の無効化は一貫性に優れています。

cc @rvolosatovs

bug application server network server in progress

最も参考になるコメント

v3.11.1展開に影響しているため、優先度をprio/highアップグレードしました。

変更は次のようになります。

  • SessionKeyIDDownlinkQueueInvalidation追加します。 キューが空の場合、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];
}
  • ASは、無効化が約dev.Sessionであると常に想定するのではなく、正しいセッションのキュー+ FCntを更新する必要があります。

https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1020 -L1038

常にdev.Sessionを使用する代わりに、使用するセッションを確立するためにSessionKeyIDをオンにします。 必要に応じて、現在のdev.Session更新します。

  • ASは、 nackedメッセージがどのセッションからのものかを確認する必要があります- nackedメッセージが保留中のセッションからのものである可能性があるため(ASの観点から)、FCntの更新は正しいセッション。

https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1060 -L1073

前と同じように、使用するセッションを決定するためにSessionKeyIDをオンにします。 必要に応じて、現在のdev.Session更新します。

  • (オプション)最小FCntDownlinkQueue{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

全てのコメント8件

すでに説明したように、私はこれに賛成です。
アプリケーションサーバーは、デバイスセッションに関する最新のデータを常に保持しているため、常にネットワークサーバーを信頼する必要があります。

  • エンドデバイスは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アップグレードしました。

変更は次のようになります。

  • SessionKeyIDDownlinkQueueInvalidation追加します。 キューが空の場合、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];
}
  • ASは、無効化が約dev.Sessionであると常に想定するのではなく、正しいセッションのキュー+ FCntを更新する必要があります。

https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1020 -L1038

常にdev.Sessionを使用する代わりに、使用するセッションを確立するためにSessionKeyIDをオンにします。 必要に応じて、現在のdev.Session更新します。

  • ASは、 nackedメッセージがどのセッションからのものかを確認する必要があります- nackedメッセージが保留中のセッションからのものである可能性があるため(ASの観点から)、FCntの更新は正しいセッション。

https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1060 -L1073

前と同じように、使用するセッションを決定するためにSessionKeyIDをオンにします。 必要に応じて、現在のdev.Session更新します。

  • (オプション)最小FCntDownlinkQueue{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から受信したイベントに基づいてアクションを実行するだけでは、基本的に十分ではないためです。

  • メッセージは古い可能性がありますが、キューを修正したいと思います_now_
  • メッセージが失われる可能性があります-キューは無限ではありません
  • メッセージは並べ替えられる場合があります-メッセージは非同期でキューにプッシュされ、並べ替えられる可能性のある方法でポップされます

これらの特性を考えると、2つのオプションがあります。

  • キューの計算をバッチ処理の最後まで遅らせます(基本的に、10個のダウンリンクキューの無効化を受け取った場合は、最後にのみキューを再計算します)。 次の理由により、これでは不十分です。

    • ASがメッセージのバッチを処理するとき、キューの最後にいるのか、途中でバッチを処理しているのかはまだわかりません。

    • メッセージは依然として失われる可能性があり、メッセージの順序を決定することは簡単ではありません。

  • ただ_NSを信頼する_。 これが意味するのは、プッシュ/置換操作は、エラーの詳細の一部として、 dev.Session.SessionKeyIDdev.PendingSession.SessionKeyID 、およびLastAFCntDown返すということです。 次に、エラーの詳細を使用して、ASでセッションを再構築します。 基本的に、これは、古いデータ(おそらく古いセッション、おそらくFCntが低すぎる)を使用してダウンリンクキュー操作を実行しようとすると、最終的にNS状態に収束することを意味します。 1、2、3回の試行が必要になる場合があります。無限に回転するのを避けるために制限を設けますが、少なくともアップリンクメッセージキューからの情報よりも大幅に新しい情報で動作しています。
  • ただ_NSを信頼する_。 これが意味するのは、プッシュ/置換操作は、エラーの詳細の一部として、 dev.Session.SessionKeyIDdev.PendingSession.SessionKeyID 、およびLastAFCntDown返すということです。 次に、エラーの詳細を使用して、ASでセッションを再構築します。 基本的に、これは、古いデータ(おそらく古いセッション、おそらくFCntが低すぎる)を使用してダウンリンクキュー操作を実行しようとすると、最終的にNS状態に収束することを意味します。 1、2、3回の試行が必要になる場合があります。無限に回転するのを避けるために制限を設けますが、少なくともアップリンクメッセージキューからの情報よりも大幅に新しい情報で動作しています。

これが最良の選択肢だと思います。

このページは役に立ちましたか?
0 / 5 - 0 評価