Lorawan-stack: Bestätigen Sie die Endgerätesitzung basierend auf Netzwerkservernachrichten

Erstellt am 8. Jan. 2021  ·  8Kommentare  ·  Quelle: TheThingsNetwork/lorawan-stack

Zusammenfassung

Der Anwendungsserver sollte die Endgerätesitzung dev.Session folgenden Ereignissen bestätigen (dh dev.PendingSession in dev.Session ):

  • Uplink-Nachricht (passiert bereits)
  • Downlink-Bestätigung
  • Downlink-Nack
  • Downlink fehlgeschlagen (wenn der Fehler keine unbekannte Sitzung ist)
  • Downlink-Warteschlange ungültig gemacht

Warum brauchen wir das?

Derzeit ist es möglich, dass der NS die Sitzung „umschaltet“, ohne dass der AS weiß, dass dieser Wechsel stattgefunden hat. @rvolosatovs hat dies in v3.11 mit der folgenden Sequenz reproduziert.

  • Endgerät tritt bei – AS kennt diese Sitzung als dev.PendingSession
  • Endgerät sendet FPort=0 Uplink - AS empfängt diesen Uplink nicht
  • Der Netzwerkserver plant einen FPort=0-Downlink
  • Netzwerkserver sendet ein DownlinkQueueInvalidated Ereignis an die AS
  • AS lehnt diese Ungültigkeitserklärung der Downlink-Warteschlange ab, da es kein dev.Session

An diesem Punkt kann der AS in dieser Sitzung nie wieder Downlinks planen, es sei denn, der NS sendet irgendwann in der Zukunft eine weitere Ungültigkeitserklärung, da er im Grunde die FCnt Erhöhung zurückgewiesen hat, die stattfand, als der NS einen FPort=0 sendete downlink (und jetzt ist die FCnt immer zu niedrig).

Was ist schon da? Was siehst du jetzt?

Die Sitzung wird nicht wiederhergestellt, es sei denn, es tritt in Zukunft eine Invalidierung ein.

Was fehlt? Was willst du sehen?

  • Füge SessionKeyID zu DownlinkQueueInvalidation . Wenn die Warteschlange leer ist, kann das AS in diesem Moment nicht wissen, welche Warteschlange ungültig gemacht wurde.
  • Der AS sollte die Warteschlange + FCnt der richtigen Sitzung aktualisieren, anstatt immer davon auszugehen, dass die Invalidierung ungefähr dev.Session .
  • Der AS sollte prüfen, von welcher Sitzung eine nacked Nachricht stammt - es ist möglich, dass die nacked Nachricht von einer ausstehenden Sitzung stammt (aus Sicht des AS) und daher sollte die FCnt-Aktualisierung am die richtige Sitzung.
  • Schließlich sollte der AS die As-soll-Sitzung zwischen dev.PendingSession und dev.Session umschalten, wenn die in Summary erwähnten Meldungen auftreten.

Umgebung

v3.11

Wie wollen Sie dies umsetzen?

  • Fügen Sie das erforderliche Proto-Feld hinzu und füllen Sie es auf der NS-Seite aus.
  • Überprüfen Sie, welche Sitzung wir während der Invalidierung/Nack verwenden, und stellen Sie sicher, dass Sie diese im AS aktualisieren.
  • Verschieben Sie das Sitzungswechselverfahren aus dem handleUplink und führen Sie es auf allen entsprechenden Uplink-Typen durch.
  • (Optional) Geben Sie Fehlerdetails für DownlinkQueue{Push|Replace} mit dem Minimum von FCnt und aktualisieren Sie LastAFCntDown auf diesen Wert. Dies würde sicherstellen, dass das System konvergiert, wenn wir aus irgendeinem Grund zwischen AS und NS nicht synchron sind.

Wie schlagen Sie vor, dies zu testen?

Versuchen Sie, die in den Reproduktionsschritten erwähnte Sequenz zu reproduzieren.

Können Sie dies selbst tun und einen Pull Request senden?

Ja, aber da dies eine nicht triviale Änderung ist, bitte ich, dieses Problem zuerst als discussion markieren - wollen wir diese Änderungen einführen? Die Ungültigkeitserklärung der Downlink-Warteschlange scheint eine Voraussetzung zu sein, aber die anderen sind gut für die Konsistenz.

cc @rvolosatovs

bug application server network server in progress

Hilfreichster Kommentar

Ich habe die Priorität auf prio/high aktualisiert, da sie sich auf Bereitstellungen von v3.11.1 auswirkt.

Die Änderungen sollten die folgenden sein:

  • Füge SessionKeyID zu DownlinkQueueInvalidation . Wenn die Warteschlange leer ist, kann das AS in diesem Moment nicht wissen, welche Warteschlange ungültig gemacht wurde.

Der folgende Zusatz proto (Feld 3 ) sollte genügen.

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];
}
  • Der AS sollte die Warteschlange + FCnt der richtigen Sitzung aktualisieren, anstatt immer davon auszugehen, dass die Invalidierung ungefähr dev.Session .

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

Anstatt immer dev.Session , schalten Sie SessionKeyID ein, um festzulegen, welche Sitzung verwendet werden soll. Aktualisieren Sie dev.Session Bedarf das aktuelle

  • Der AS sollte prüfen, von welcher Sitzung eine nacked Nachricht stammt - es ist möglich, dass die nacked Nachricht von einer ausstehenden Sitzung stammt (aus Sicht des AS) und daher sollte die FCnt-Aktualisierung am durchgeführt werden die richtige Sitzung.

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

Schalten Sie wie zuvor SessionKeyID ein, um zu bestimmen, welche Sitzung verwendet werden soll. Aktualisieren Sie dev.Session Bedarf das aktuelle

  • (Optional) geben Sie Fehlerdetails für DownlinkQueue{Push|Replace} mit dem Minimum von FCnt und aktualisieren Sie LastAFCntDown auf diesen Wert. Dies würde sicherstellen, dass das System konvergiert, wenn wir aus irgendeinem Grund zwischen AS und NS nicht synchron sind.

Der folgende Zusatz proto sollte ausgefüllt und als Fehlerdetails zu den errFCntTooLow im NS hinzugefügt werden:

message UpdateDownlinkQueueErrorDetails {
  bytes session_key_id = 1 [(gogoproto.customname) = "SessionKeyID", (validate.rules).bytes.max_len = 2048];
  uint32 last_f_cnt_down = 2;
}

Der AS kann dann diese Details übernehmen und die aktuelle Sitzung aktualisieren.

Die Änderungen sind abwärtskompatibel und auf der NS-Seite hoffentlich minimal. Der Geist ist bereits aus der Flasche - das gesamte Protokoll zwischen AS und NS wurde langsam asynchron, und es reicht nicht aus, die Änderung von FPort=0 einfach rückgängig zu machen. Ich denke nicht, dass diese Transformation am Ende des Tages falsch war, aber wir müssen diese Macken in Bezug auf die Sitzungsbisimulation beheben.

cc @johanstokking , @rvolosatovs

Alle 8 Kommentare

Ich bin dafür, wie wir bereits besprochen haben.
Der Anwendungsserver sollte dem Netzwerkserver immer vertrauen, da er immer über die aktuellsten Daten zur Gerätesitzung verfügt.

  • Endgerät sendet FPort=0 Uplink - AS empfängt diesen Uplink nicht

Sollten wir dies nicht so ändern, dass NS dies sendet, aber mit leerer Nutzlast und FPort 0, damit es nicht in den Upstream gesendet wird?

  • Endgerät sendet FPort=0 Uplink - AS empfängt diesen Uplink nicht

Sollten wir dies nicht so ändern, dass NS dies sendet, aber mit leerer Nutzlast und FPort 0, damit es nicht in den Upstream gesendet wird?

Es ist überflüssig, da NS->AS-Messaging asynchron ist, kann die Warteschlangen-Invalidierung eintreffen, bevor der FPort==0 Uplink an AS gesendet wird, um die Sitzung zu bestätigen, also müssen wir dies trotzdem tun. Der einzige Grund, einen Uplink an AS als Antwort auf einen FPort==0 Uplink an NS zu senden, wäre sicherzustellen, dass AS so schnell wie möglich über eine Sitzungsänderung benachrichtigt wird, aber wir haben keine solche Notwendigkeit. Selbst dann wäre es viel sinnvoller, eine SessionSwitch Nachricht einzuführen, die NS anstelle des FPort 0-Uplinks an AS senden würde.

Ich habe die Priorität auf prio/high aktualisiert, da sie sich auf Bereitstellungen von v3.11.1 auswirkt.

Die Änderungen sollten die folgenden sein:

  • Füge SessionKeyID zu DownlinkQueueInvalidation . Wenn die Warteschlange leer ist, kann das AS in diesem Moment nicht wissen, welche Warteschlange ungültig gemacht wurde.

Der folgende Zusatz proto (Feld 3 ) sollte genügen.

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];
}
  • Der AS sollte die Warteschlange + FCnt der richtigen Sitzung aktualisieren, anstatt immer davon auszugehen, dass die Invalidierung ungefähr dev.Session .

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

Anstatt immer dev.Session , schalten Sie SessionKeyID ein, um festzulegen, welche Sitzung verwendet werden soll. Aktualisieren Sie dev.Session Bedarf das aktuelle

  • Der AS sollte prüfen, von welcher Sitzung eine nacked Nachricht stammt - es ist möglich, dass die nacked Nachricht von einer ausstehenden Sitzung stammt (aus Sicht des AS) und daher sollte die FCnt-Aktualisierung am durchgeführt werden die richtige Sitzung.

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

Schalten Sie wie zuvor SessionKeyID ein, um zu bestimmen, welche Sitzung verwendet werden soll. Aktualisieren Sie dev.Session Bedarf das aktuelle

  • (Optional) geben Sie Fehlerdetails für DownlinkQueue{Push|Replace} mit dem Minimum von FCnt und aktualisieren Sie LastAFCntDown auf diesen Wert. Dies würde sicherstellen, dass das System konvergiert, wenn wir aus irgendeinem Grund zwischen AS und NS nicht synchron sind.

Der folgende Zusatz proto sollte ausgefüllt und als Fehlerdetails zu den errFCntTooLow im NS hinzugefügt werden:

message UpdateDownlinkQueueErrorDetails {
  bytes session_key_id = 1 [(gogoproto.customname) = "SessionKeyID", (validate.rules).bytes.max_len = 2048];
  uint32 last_f_cnt_down = 2;
}

Der AS kann dann diese Details übernehmen und die aktuelle Sitzung aktualisieren.

Die Änderungen sind abwärtskompatibel und auf der NS-Seite hoffentlich minimal. Der Geist ist bereits aus der Flasche - das gesamte Protokoll zwischen AS und NS wurde langsam asynchron, und es reicht nicht aus, die Änderung von FPort=0 einfach rückgängig zu machen. Ich denke nicht, dass diese Transformation am Ende des Tages falsch war, aber wir müssen diese Macken in Bezug auf die Sitzungsbisimulation beheben.

cc @johanstokking , @rvolosatovs

Klingt gut für mich!

Kann ich hier irgendwas machen? Wenn ja, weisen Sie mich bitte neu zu und teilen Sie mir mit, was.

Kann ich hier irgendwas machen? Wenn ja, weisen Sie mich bitte neu zu und teilen Sie mir mit, was.

Daran arbeite ich bereits, mit großem Schwerpunkt auf folgendem Punkt:

* (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.

Der Grund dafür ist, dass es im Grunde nicht ausreicht, auf Grundlage der vom NS empfangenen Ereignisse als Teil der Warteschlange Maßnahmen zu ergreifen:

  • Nachrichten mögen alt sein, aber wir wollen die Warteschlange _jetzt_ korrigieren.
  • Nachrichten können verloren gehen - die Warteschlange ist nicht unendlich
  • Nachrichten können neu geordnet werden – sie werden asynchron in die Warteschlange eingeschoben und möglicherweise neu geordnet angezeigt

Angesichts dieser Eigenschaften gibt es zwei Möglichkeiten:

  • Verzögern Sie die Warteschlangenberechnung bis zum Ende der Stapelverarbeitung (im Allgemeinen wird die Warteschlange erst am Ende neu berechnet, wenn Sie 10 Ungültigkeiten der Downlink-Warteschlange erhalten). Dies ist aus folgenden Gründen nicht ausreichend:

    • Wenn der AS einen Stapel Nachrichten verarbeitet, weiß er immer noch nicht, ob er _wirklich_ am Ende der Warteschlange steht oder einen Stapel in der Mitte verarbeitet

    • Nachrichten können dennoch verloren gehen, und die Bestimmung ihrer Reihenfolge ist nicht trivial.

  • Vertraue einfach dem NS_. Was ich damit meine ist, dass Push/Replace-Operationen als Teil der Fehlerdetails dev.Session.SessionKeyID , dev.PendingSession.SessionKeyID und LastAFCntDown . Wir verwenden dann die Fehlerdetails, um die Sitzung im AS neu aufzubauen. Im Grunde bedeutet dies, dass wir, wenn wir versuchen, eine Downlink-Warteschlangenoperation durchzuführen, unter Verwendung veralteter Daten (vielleicht eine veraltete Sitzung, vielleicht eine zu niedrige FCnt) schließlich zum NS-Zustand konvergieren. Es kann ein, zwei, drei Versuche dauern, ich mache es begrenzt, um ein unendliches Drehen zu vermeiden, aber wir arbeiten zumindest mit Informationen, die wesentlich neuer sind als die aus der Uplink-Nachrichtenwarteschlange.
  • Vertraue einfach dem NS_. Was ich damit meine ist, dass Push/Replace-Operationen als Teil der Fehlerdetails dev.Session.SessionKeyID , dev.PendingSession.SessionKeyID und LastAFCntDown . Wir verwenden dann die Fehlerdetails, um die Sitzung im AS neu aufzubauen. Im Grunde bedeutet dies, dass wir, wenn wir versuchen, eine Downlink-Warteschlangenoperation durchzuführen, unter Verwendung veralteter Daten (vielleicht eine veraltete Sitzung, vielleicht eine zu niedrige FCnt) schließlich zum NS-Zustand konvergieren. Es kann ein, zwei, drei Versuche dauern, ich mache es begrenzt, um ein unendliches Drehen zu vermeiden, aber wir arbeiten zumindest mit Informationen, die wesentlich neuer sind als die aus der Uplink-Nachrichtenwarteschlange.

Ich denke, dies ist die beste Option.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

kschiffer picture kschiffer  ·  6Kommentare

johanstokking picture johanstokking  ·  3Kommentare

adriansmares picture adriansmares  ·  9Kommentare

johanstokking picture johanstokking  ·  8Kommentare

ecities picture ecities  ·  5Kommentare