El servidor de aplicaciones debe confirmar la sesión del dispositivo final (es decir, mover dev.PendingSession
a dev.Session
) en los siguientes eventos:
Actualmente, es posible que el NS 'cambie' la sesión sin que el AS sepa que este cambio ocurrió. @rvolosatovs reprodujo esto en v3.11
usando la siguiente secuencia.
dev.PendingSession
DownlinkQueueInvalidated
al ASdev.Session
En este punto, el AS nunca podrá programar enlaces descendentes nuevamente en esta sesión a menos que el NS envíe otra invalidación en el futuro, porque básicamente rechazó el aumento de FCnt
que ocurrió cuando el NS envió un FPort = 0 enlace descendente (y ahora el FCnt siempre es demasiado bajo).
La sesión no se recuperará a menos que ocurra una invalidación en el futuro.
SessionKeyID
a DownlinkQueueInvalidation
. Si la cola está vacía, el AS no puede saber en este momento qué cola fue invalidada.dev.Session
.nacked
; es posible que el mensaje nacked
sea de una sesión pendiente (desde la perspectiva del AS) y, como tal, la actualización de FCnt debe realizarse en la sesión correcta.dev.PendingSession
y dev.Session
cuando se produzcan los mensajes mencionados en Summary
.v3.11
handleUplink
y hágalo en todos los tipos de enlace ascendente apropiados.DownlinkQueue{Push|Replace}
con el mínimo de FCnt
y actualice siempre LastAFCntDown
a este valor. Esto aseguraría que el sistema converge si en algún momento no estamos sincronizados entre AS y NS por alguna razón.Intente reproducir la secuencia mencionada en los pasos de reproducción.
Sí, pero como se trata de un cambio no trivial, solicito que se etiquete este problema primero como discussion
: ¿queremos introducir estos cambios? La invalidación de la cola de enlace descendente parece un requisito, pero las otras son buenas para la coherencia.
cc @rvolosatovs
Estoy a favor de esto, como ya hemos comentado.
El servidor de aplicaciones siempre debe confiar en el servidor de red, porque siempre tiene los datos más actualizados sobre la sesión del dispositivo.
- El dispositivo final envía FPort = 0 uplink - AS no recibirá este uplink
¿No deberíamos cambiar esto para que NS envíe esto, pero con una carga útil vacía y FPort 0, para que no se envíe en sentido ascendente?
- El dispositivo final envía FPort = 0 uplink - AS no recibirá este uplink
¿No deberíamos cambiar esto para que NS envíe esto, pero con una carga útil vacía y FPort 0, para que no se envíe en sentido ascendente?
Es redundante, dado que la mensajería NS-> AS es asíncrona, la invalidación de la cola puede llegar antes de que se envíe el enlace ascendente FPort==0
a AS para confirmar la sesión, por lo que tenemos que hacer esto de todos modos. La única razón para enviar un enlace ascendente a AS en respuesta a FPort==0
enlace ascendente a NS, sería garantizar que AS sea notificado del cambio de sesión lo antes posible, pero no tenemos esa necesidad. Incluso entonces, tendría mucho más sentido introducir un mensaje SessionSwitch
, que NS enviaría a AS en lugar del enlace ascendente FPort 0.
He actualizado la prioridad a prio/high
ya que está afectando las implementaciones de v3.11.1
.
Los cambios deben ser los siguientes:
SessionKeyID
a DownlinkQueueInvalidation
. Si la cola está vacía, el AS no puede saber en este momento qué cola fue invalidada.La siguiente adición proto
(campo 3
) debería ser suficiente.
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
.En lugar de usar dev.Session
siempre, cambie SessionKeyID
para establecer qué sesión usar. Si es necesario, actualice el dev.Session
actual.
nacked
; es posible que el mensaje nacked
sea de una sesión pendiente (desde la perspectiva del AS) y, como tal, la actualización de FCnt debe realizarse en la sesión correcta.Como antes, cambie SessionKeyID
para determinar qué sesión usar. Si es necesario, actualice el dev.Session
actual.
DownlinkQueue{Push|Replace}
con el mínimo FCnt
y siempre actualice LastAFCntDown
a este valor. Esto aseguraría que el sistema converge si en algún momento no estamos sincronizados entre AS y NS por alguna razón.La siguiente adición proto
debe completarse y agregarse como detalles de error al errFCntTooLow
en el NS:
message UpdateDownlinkQueueErrorDetails {
bytes session_key_id = 1 [(gogoproto.customname) = "SessionKeyID", (validate.rules).bytes.max_len = 2048];
uint32 last_f_cnt_down = 2;
}
El AS puede tomar estos detalles y actualizar la sesión actual.
Los cambios son compatibles con versiones anteriores y, con suerte, mínimos en el lado NS. El genio ya salió de la botella: todo el protocolo entre AS y NS se volvió asincrónico lentamente, y simplemente revertir el cambio FPort=0
no será suficiente. No creo que esta transformación esté mal al final del día, pero debemos corregir estas peculiaridades con respecto a la bisimulación de la sesión.
cc @johanstokking , @rvolosatovs
¡Suena bien para mí!
¿Algo que pueda hacer aquí? Si es así, vuelva a asignarme y déjeme saber qué.
¿Algo que pueda hacer aquí? Si es así, vuelva a asignarme y déjeme saber qué.
Ya estoy trabajando en esto, con un gran énfasis en el siguiente punto:
* (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.
La razón de esto es que tomar acciones basadas en los eventos recibidos de la NS, como parte de la cola, no es fundamentalmente suficiente:
Dadas estas características, existen dos opciones:
dev.Session.SessionKeyID
, dev.PendingSession.SessionKeyID
y LastAFCntDown
, como parte de los detalles del error. Luego usamos los detalles del error para reconstruir la sesión en el AS. Básicamente, esto significa que cuando intentamos hacer una operación de cola de enlace descendente, utilizando datos desactualizados (quizás una sesión desactualizada, quizás un FCnt demasiado bajo), eventualmente convergemos al estado NS. Puede tomar uno, dos, tres intentos, lo haré acotado para evitar un giro infinito, pero al menos estamos operando con información que es significativamente más nueva que la de la cola de mensajes de enlace ascendente.
- Solo confíe en el NS. Lo que quiero decir con esto es que las operaciones de empujar / reemplazar devuelven
dev.Session.SessionKeyID
,dev.PendingSession.SessionKeyID
yLastAFCntDown
, como parte de los detalles del error. Luego usamos los detalles del error para reconstruir la sesión en el AS. Básicamente, esto significa que cuando intentamos hacer una operación de cola de enlace descendente, utilizando datos desactualizados (quizás una sesión desactualizada, quizás un FCnt demasiado bajo), eventualmente convergemos al estado NS. Puede tomar uno, dos, tres intentos, lo haré acotado para evitar un giro infinito, pero al menos estamos operando con información que es significativamente más nueva que la de la cola de mensajes de enlace ascendente.
Creo que esta es la mejor opción.
Comentario más útil
He actualizado la prioridad a
prio/high
ya que está afectando las implementaciones dev3.11.1
.Los cambios deben ser los siguientes:
SessionKeyID
aDownlinkQueueInvalidation
. Si la cola está vacía, el AS no puede saber en este momento qué cola fue invalidada.La siguiente adición
proto
(campo3
) debería ser suficiente.dev.Session
.https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1020 -L1038
En lugar de usar
dev.Session
siempre, cambieSessionKeyID
para establecer qué sesión usar. Si es necesario, actualice eldev.Session
actual.nacked
; es posible que el mensajenacked
sea de una sesión pendiente (desde la perspectiva del AS) y, como tal, la actualización de FCnt debe realizarse en la sesión correcta.https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1060 -L1073
Como antes, cambie
SessionKeyID
para determinar qué sesión usar. Si es necesario, actualice eldev.Session
actual.DownlinkQueue{Push|Replace}
con el mínimoFCnt
y siempre actualiceLastAFCntDown
a este valor. Esto aseguraría que el sistema converge si en algún momento no estamos sincronizados entre AS y NS por alguna razón.La siguiente adición
proto
debe completarse y agregarse como detalles de error alerrFCntTooLow
en el NS:El AS puede tomar estos detalles y actualizar la sesión actual.
Los cambios son compatibles con versiones anteriores y, con suerte, mínimos en el lado NS. El genio ya salió de la botella: todo el protocolo entre AS y NS se volvió asincrónico lentamente, y simplemente revertir el cambio
FPort=0
no será suficiente. No creo que esta transformación esté mal al final del día, pero debemos corregir estas peculiaridades con respecto a la bisimulación de la sesión.cc @johanstokking , @rvolosatovs