Le serveur d'applications doit confirmer la session de l'appareil final (c'est-à-dire déplacer dev.PendingSession
dans dev.Session
) sur les événements suivants :
Actuellement, il est possible que le NS « bascule » la session sans que l'AS sache que ce basculement s'est produit. @rvolosatovs a reproduit cela dans v3.11
utilisant la séquence suivante.
dev.PendingSession
DownlinkQueueInvalidated
à l'ASdev.Session
À ce stade, l'AS ne pourra plus jamais planifier de liaisons descendantes dans cette session à moins que le NS n'envoie une autre invalidation dans le futur, car il a essentiellement rejeté l' FCnt
qui s'est produite lorsque le NS a envoyé un FPort=0 liaison descendante (et maintenant le FCnt est toujours trop bas).
La session ne sera pas récupérée à moins qu'une invalidation ne se produise à l'avenir.
SessionKeyID
à DownlinkQueueInvalidation
. Si la file d'attente est vide, l'AS ne peut pas savoir à ce moment quelle file d'attente a été invalidée.dev.Session
.nacked
- il est possible que le message nacked
provienne d'une session en attente (du point de vue de l'AS) et en tant que tel, la mise à jour FCnt doit être effectuée le la bonne séance.dev.PendingSession
et dev.Session
lorsque les messages mentionnés dans Summary
se produisent.v3.11
handleUplink
et effectuez-la sur tous les types de liaison montante appropriés.DownlinkQueue{Push|Replace}
avec le minimum FCnt
et mettez toujours à jour le LastAFCntDown
avec cette valeur. Cela garantirait que le système converge si, pour une raison quelconque, nous sommes désynchronisés entre AS et NS.Essayez de reproduire la séquence mentionnée dans les étapes de reproduction.
Oui, mais comme il s'agit d'un changement non trivial, je demande de marquer d'abord ce problème comme discussion
- voulons-nous introduire ces changements ? L'invalidation de file d'attente de liaison descendante semble une exigence, mais les autres sont bonnes pour la cohérence.
cc @rvolosatovs
Je suis en faveur de cela, comme nous en avons déjà discuté.
Le serveur d'applications doit toujours faire confiance à Network Server, car il dispose toujours des données les plus récentes sur la session du périphérique.
- Le périphérique final envoie la liaison montante FPort=0 - AS ne recevra pas cette liaison montante
Ne devrions-nous pas changer cela pour que NS envoie cela, mais avec une charge utile vide et FPort 0, afin qu'il ne soit pas envoyé en amont ?
- Le périphérique final envoie la liaison montante FPort=0 - AS ne recevra pas cette liaison montante
Ne devrions-nous pas changer cela pour que NS envoie cela, mais avec une charge utile vide et FPort 0, afin qu'il ne soit pas envoyé en amont ?
C'est redondant, puisque la messagerie NS->AS est asynchrone, l'invalidation de la file d'attente peut arriver avant que la liaison montante FPort==0
soit envoyée à AS pour confirmer la session, nous devons donc le faire de toute façon. La seule raison d'envoyer une liaison montante à AS en réponse à une liaison montante FPort==0
vers NS serait de s'assurer que AS est informé du changement de session dès que possible, mais nous n'en avons pas besoin. Même dans ce cas, il serait beaucoup plus logique d'introduire un message SessionSwitch
, que NS enverrait à AS au lieu de la liaison montante FPort 0.
J'ai mis à niveau la priorité à prio/high
car cela affecte les déploiements de v3.11.1
.
Les changements devraient être les suivants :
SessionKeyID
à DownlinkQueueInvalidation
. Si la file d'attente est vide, l'AS ne peut pas savoir à ce moment quelle file d'attente a été invalidée.L'addition suivante de proto
(champ 3
) devrait suffire.
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
.Au lieu d'utiliser toujours le dev.Session
, faites un basculement sur SessionKeyID
afin d'établir quelle session utiliser. Si nécessaire, mettez à jour le dev.Session
actuel.
nacked
- il est possible que le message nacked
provienne d'une session en attente (du point de vue de l'AS) et en tant que tel, la mise à jour FCnt doit être effectuée le la bonne séance.Comme précédemment, faites un switch sur le SessionKeyID
afin de déterminer quelle session utiliser. Si nécessaire, mettez à jour le dev.Session
actuel.
DownlinkQueue{Push|Replace}
avec le minimum FCnt
et mettez toujours à jour le LastAFCntDown
avec cette valeur. Cela garantirait que le système converge si, pour une raison quelconque, nous sommes désynchronisés entre AS et NS.L'ajout suivant de proto
doit être rempli et ajouté en tant que détails d'erreur au errFCntTooLow
dans la NS :
message UpdateDownlinkQueueErrorDetails {
bytes session_key_id = 1 [(gogoproto.customname) = "SessionKeyID", (validate.rules).bytes.max_len = 2048];
uint32 last_f_cnt_down = 2;
}
L'AS peut alors prendre ces détails et mettre à jour la session en cours.
Les modifications sont rétrocompatibles et, espérons-le, minimes du côté NS. Le génie est déjà sorti de la bouteille - l'ensemble du protocole entre AS et NS est lentement devenu asynchrone, et simplement annuler le changement FPort=0
ne suffira pas. Je ne pense pas que cette transformation était erronée en fin de compte, mais nous devons corriger ces bizarreries concernant la bisimulation de session.
cc @johanstokking , @rvolosatovs
Cela me semble bon !
Tout ce que je peux faire ici ? Si c'est le cas, veuillez me réaffecter et dites-moi quoi.
Tout ce que je peux faire ici ? Si c'est le cas, veuillez me réaffecter et dites-moi quoi.
Je travaille déjà là-dessus, avec un gros accent sur le point suivant :
* (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 raison en est que prendre des mesures basées sur les événements reçus du NS, dans le cadre de la file d'attente, n'est fondamentalement pas vraiment suffisant :
Compte tenu de ces caractéristiques, deux options s'offrent à vous :
dev.Session.SessionKeyID
, dev.PendingSession.SessionKeyID
et le LastAFCntDown
, dans le cadre des détails de l'erreur. Nous utilisons ensuite les détails de l'erreur pour reconstruire la session dans l'AS. Fondamentalement, cela signifie que lorsque nous essayons de faire une opération de file d'attente de liaison descendante, en utilisant des données obsolètes (peut-être une session obsolète, peut-être un FCnt trop bas), nous convergeons finalement vers l'état NS. Cela peut prendre un, deux, trois essais, je vais le limiter afin d'éviter de tourner à l'infini, mais nous fonctionnons au moins avec des informations nettement plus récentes que celles de la file d'attente des messages de liaison montante.
- Juste _faites confiance au NS_. Ce que je veux dire par là, c'est que les opérations push/replace renvoient le
dev.Session.SessionKeyID
,dev.PendingSession.SessionKeyID
et leLastAFCntDown
, dans le cadre des détails de l'erreur. Nous utilisons ensuite les détails de l'erreur pour reconstruire la session dans l'AS. Fondamentalement, cela signifie que lorsque nous essayons de faire une opération de file d'attente de liaison descendante, en utilisant des données obsolètes (peut-être une session obsolète, peut-être un FCnt trop bas), nous convergeons finalement vers l'état NS. Cela peut prendre un, deux, trois essais, je vais le limiter afin d'éviter de tourner à l'infini, mais nous fonctionnons au moins avec des informations nettement plus récentes que celles de la file d'attente des messages de liaison montante.
Je pense que c'est la meilleure option.
Commentaire le plus utile
J'ai mis à niveau la priorité à
prio/high
car cela affecte les déploiements dev3.11.1
.Les changements devraient être les suivants :
SessionKeyID
àDownlinkQueueInvalidation
. Si la file d'attente est vide, l'AS ne peut pas savoir à ce moment quelle file d'attente a été invalidée.L'addition suivante de
proto
(champ3
) devrait suffire.dev.Session
.https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1020 -L1038
Au lieu d'utiliser toujours le
dev.Session
, faites un basculement surSessionKeyID
afin d'établir quelle session utiliser. Si nécessaire, mettez à jour ledev.Session
actuel.nacked
- il est possible que le messagenacked
provienne d'une session en attente (du point de vue de l'AS) et en tant que tel, la mise à jour FCnt doit être effectuée le la bonne séance.https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1060 -L1073
Comme précédemment, faites un switch sur le
SessionKeyID
afin de déterminer quelle session utiliser. Si nécessaire, mettez à jour ledev.Session
actuel.DownlinkQueue{Push|Replace}
avec le minimumFCnt
et mettez toujours à jour leLastAFCntDown
avec cette valeur. Cela garantirait que le système converge si, pour une raison quelconque, nous sommes désynchronisés entre AS et NS.L'ajout suivant de
proto
doit être rempli et ajouté en tant que détails d'erreur auerrFCntTooLow
dans la NS :L'AS peut alors prendre ces détails et mettre à jour la session en cours.
Les modifications sont rétrocompatibles et, espérons-le, minimes du côté NS. Le génie est déjà sorti de la bouteille - l'ensemble du protocole entre AS et NS est lentement devenu asynchrone, et simplement annuler le changement
FPort=0
ne suffira pas. Je ne pense pas que cette transformation était erronée en fin de compte, mais nous devons corriger ces bizarreries concernant la bisimulation de session.cc @johanstokking , @rvolosatovs