Der Anwendungsserver sollte die Endgerätesitzung dev.Session
folgenden Ereignissen bestätigen (dh dev.PendingSession
in dev.Session
):
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.
dev.PendingSession
DownlinkQueueInvalidated
Ereignis an die ASdev.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).
Die Sitzung wird nicht wiederhergestellt, es sei denn, es tritt in Zukunft eine Invalidierung ein.
SessionKeyID
zu DownlinkQueueInvalidation
. Wenn die Warteschlange leer ist, kann das AS in diesem Moment nicht wissen, welche Warteschlange ungültig gemacht wurde.dev.Session
.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.dev.PendingSession
und dev.Session
umschalten, wenn die in Summary
erwähnten Meldungen auftreten.v3.11
handleUplink
und führen Sie es auf allen entsprechenden Uplink-Typen durch.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.Versuchen Sie, die in den Reproduktionsschritten erwähnte Sequenz zu reproduzieren.
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
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:
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];
}
dev.Session
.Anstatt immer dev.Session
, schalten Sie SessionKeyID
ein, um festzulegen, welche Sitzung verwendet werden soll. Aktualisieren Sie dev.Session
Bedarf das aktuelle
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.Schalten Sie wie zuvor SessionKeyID
ein, um zu bestimmen, welche Sitzung verwendet werden soll. Aktualisieren Sie dev.Session
Bedarf das aktuelle
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:
Angesichts dieser Eigenschaften gibt es zwei Möglichkeiten:
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
undLastAFCntDown
. 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.
Hilfreichster Kommentar
Ich habe die Priorität auf
prio/high
aktualisiert, da sie sich auf Bereitstellungen vonv3.11.1
auswirkt.Die Änderungen sollten die folgenden sein:
SessionKeyID
zuDownlinkQueueInvalidation
. Wenn die Warteschlange leer ist, kann das AS in diesem Moment nicht wissen, welche Warteschlange ungültig gemacht wurde.Der folgende Zusatz
proto
(Feld3
) sollte genügen.dev.Session
.https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1020 -L1038
Anstatt immer
dev.Session
, schalten SieSessionKeyID
ein, um festzulegen, welche Sitzung verwendet werden soll. Aktualisieren Siedev.Session
Bedarf das aktuellenacked
Nachricht stammt - es ist möglich, dass dienacked
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 Siedev.Session
Bedarf das aktuelleDownlinkQueue{Push|Replace}
mit dem Minimum vonFCnt
und aktualisieren SieLastAFCntDown
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 denerrFCntTooLow
im NS hinzugefügt werden: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