Сервер приложений должен подтвердить сеанс конечного устройства (т.е. переместить dev.PendingSession
в dev.Session
) при следующих событиях:
В настоящее время возможно, что NS «переключает» сеанс, а AS не знает, что это переключение произошло. @rvolosatovs воспроизвел это в v3.11
используя следующую последовательность.
dev.PendingSession
DownlinkQueueInvalidated
dev.Session
На этом этапе AS никогда не сможет снова запланировать нисходящие каналы в этом сеансе, если NS не отправит другое объявление недействительности когда-нибудь в будущем, потому что он в основном отклонил увеличение FCnt
которое произошло, когда NS отправил FPort = 0 нисходящий канал (и теперь FCnt всегда слишком низкий).
Сеанс не будет восстановлен, если в будущем не произойдет аннулирование.
SessionKeyID
к DownlinkQueueInvalidation
. Если очередь пуста, AS не может в данный момент узнать, какая очередь была признана недействительной.dev.Session
.nacked
- возможно, что сообщение nacked
получено из ожидающего сеанса (с точки зрения AS), и поэтому обновление FCnt должно быть выполнено на правильный сеанс.dev.PendingSession
и dev.Session
при появлении сообщений, упомянутых в Summary
.v3.11
handleUplink
и сделайте это для всех подходящих типов восходящих каналов.DownlinkQueue{Push|Replace}
с минимальным значением FCnt
и всегда обновлять LastAFCntDown
до этого значения. Это обеспечит сходимость системы, если в какой-то момент мы по какой-то причине рассинхронизируем AS и NS.Попробуйте воспроизвести последовательность, указанную в шагах воспроизведения.
Да, но поскольку это нетривиальное изменение, я прошу сначала пометить эту проблему как discussion
- хотим ли мы внести эти изменения? Обнуление очереди нисходящей линии связи кажется обязательным, но другие хороши для согласованности.
cc @rvolosatovs
Я за это, о чем мы уже говорили.
Сервер приложений всегда должен доверять сетевому серверу, потому что он всегда имеет самые свежие данные о сеансе устройства.
- Конечное устройство отправляет FPort = 0 восходящий канал - AS не получит этот восходящий канал
Разве мы не должны изменить это так, чтобы NS отправлял это, но с пустой полезной нагрузкой и FPort 0, чтобы он не отправлялся в восходящем направлении?
- Конечное устройство отправляет FPort = 0 восходящий канал - AS не получит этот восходящий канал
Разве мы не должны изменить это так, чтобы NS отправлял это, но с пустой полезной нагрузкой и FPort 0, чтобы он не отправлялся в восходящем направлении?
Это избыточно, поскольку обмен сообщениями NS-> AS является асинхронным, аннулирование очереди может произойти до того, как восходящий канал FPort==0
будет отправлен в AS для подтверждения сеанса, поэтому мы должны сделать это в любом случае. Единственная причина для отправки восходящего канала на AS в ответ на восходящий канал FPort==0
на NS - это обеспечить уведомление AS об изменении сеанса как можно скорее, но у нас нет такой необходимости. Даже тогда было бы разумнее ввести сообщение SessionSwitch
, которое NS будет отправлять в AS вместо восходящего канала FPort 0.
Я повысил приоритет до prio/high
как он влияет v3.11.1
развертывания
Изменения должны быть следующими:
SessionKeyID
к DownlinkQueueInvalidation
. Если очередь пуста, 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];
}
dev.Session
.Вместо того, чтобы всегда использовать dev.Session
, включите SessionKeyID
, чтобы определить, какой сеанс использовать. При необходимости обновите текущий dev.Session
.
nacked
- возможно, что сообщение nacked
получено из ожидающего сеанса (с точки зрения AS), и поэтому обновление FCnt должно быть выполнено на правильный сеанс.Как и раньше, включите SessionKeyID
, чтобы определить, какой сеанс использовать. При необходимости обновите текущий dev.Session
.
DownlinkQueue{Push|Replace}
с минимальным значением FCnt
и всегда обновлять LastAFCntDown
до этого значения. Это обеспечит сходимость системы, если в какой-то момент мы по какой-то причине рассинхронизируем AS и NS.Следующее дополнение proto
должно быть заполнено и добавлено в качестве сведений об ошибке к errFCntTooLow
в NS:
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, как части очереди, в принципе недостаточно:
Учитывая эти характеристики, есть два варианта:
dev.Session.SessionKeyID
, dev.PendingSession.SessionKeyID
и LastAFCntDown
как часть сведений об ошибке. Затем мы используем сведения об ошибке для восстановления сеанса в AS. По сути, это означает, что, когда мы пытаемся выполнить операцию очереди нисходящего канала, используя устаревшие данные (возможно, устаревший сеанс, возможно, слишком низкий FCnt), мы в конечном итоге переходим к состоянию NS. Это может занять одну, две, три попытки, я сделаю это ограниченным, чтобы избежать бесконечного вращения, но мы, по крайней мере, работаем с информацией, которая значительно новее, чем информация из очереди сообщений восходящего канала.
- Просто доверяйте NS_. Я имею в виду, что операции вставки / замены возвращают
dev.Session.SessionKeyID
,dev.PendingSession.SessionKeyID
иLastAFCntDown
как часть сведений об ошибке. Затем мы используем сведения об ошибке для восстановления сеанса в AS. По сути, это означает, что, когда мы пытаемся выполнить операцию очереди нисходящего канала, используя устаревшие данные (возможно, устаревший сеанс, возможно, слишком низкий FCnt), мы в конечном итоге переходим к состоянию NS. Это может занять одну, две, три попытки, я сделаю это ограниченным, чтобы избежать бесконечного вращения, но мы, по крайней мере, работаем с информацией, которая значительно новее, чем информация из очереди сообщений восходящего канала.
Думаю, это лучший вариант.
Самый полезный комментарий
Я повысил приоритет до
prio/high
как он влияетv3.11.1
развертыванияИзменения должны быть следующими:
SessionKeyID
кDownlinkQueueInvalidation
. Если очередь пуста, AS не может в данный момент узнать, какая очередь была признана недействительной.Следующего добавления
proto
(поле3
) должно хватить.dev.Session
.https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1020 -L1038
Вместо того, чтобы всегда использовать
dev.Session
, включитеSessionKeyID
, чтобы определить, какой сеанс использовать. При необходимости обновите текущийdev.Session
.nacked
- возможно, что сообщениеnacked
получено из ожидающего сеанса (с точки зрения AS), и поэтому обновление FCnt должно быть выполнено на правильный сеанс.https://github.com/TheThingsNetwork/lorawan-stack/blob/e2fa6c085eaaf1a0b70939020244875bd01e5857/pkg/applicationserver/applicationserver.go#L1060 -L1073
Как и раньше, включите
SessionKeyID
, чтобы определить, какой сеанс использовать. При необходимости обновите текущийdev.Session
.DownlinkQueue{Push|Replace}
с минимальным значениемFCnt
и всегда обновлятьLastAFCntDown
до этого значения. Это обеспечит сходимость системы, если в какой-то момент мы по какой-то причине рассинхронизируем AS и NS.Следующее дополнение
proto
должно быть заполнено и добавлено в качестве сведений об ошибке кerrFCntTooLow
в NS:Затем AS может использовать эти данные и обновить текущий сеанс.
Изменения обратно совместимы и, надеюсь, минимальны на стороне NS. Джин уже вышел из бутылки - весь протокол между AS и NS постепенно стал асинхронным, и простого возврата изменения
FPort=0
будет недостаточно. Я не думаю, что это преобразование было неправильным в конце концов, но мы должны исправить эти причуды, касающиеся бисимуляции сеанса.cc @johanstokking , @rvolosatovs