Lorawan-stack: 根据网络服务器消息确认终端设备会话

创建于 2021-01-08  ·  8评论  ·  资料来源: TheThingsNetwork/lorawan-stack

概括

应用程序服务器应在以下事件中确认终端设备会话(即,将dev.PendingSession移入dev.Session ):

  • 上行消息(已经发生)
  • 下行确认
  • 下行链路
  • 下行链路失败(如果错误不是未知会话)
  • 下行队列失效

我们为什么需要这个?

目前,NS 可能会在 AS 不知道发生此切换的情况下“切换”会话。 @rvolosatovs使用以下顺序在v3.11复制了此内容。

  • 终端设备加入 - AS 知道此会话为dev.PendingSession
  • 终端设备发送 FPort=0 上行链路 - AS 不会收到此上行链路
  • 网络服务器调度 FPort=0 下行链路
  • 网络服务器向 AS 发送DownlinkQueueInvalidated事件
  • AS 拒绝此下行链路队列失效,因为它没有dev.Session

此时 AS 将永远无法在此会话中再次调度下行链路,除非 NS 在未来某个时间发送另一个无效,因为它基本上拒绝了 NS 发送 FPort=0 时发生的FCnt增加下行链路(现在 FCnt 总是太低)。

什么已经存在? 你现在看到了什么?

除非将来发生失效,否则会话不会恢复。

什么东西少了? 你要看什么?

  • SessionKeyIDDownlinkQueueInvalidation 。 如果队列为空,AS此时无法知道哪个队列失效了。
  • AS 应该更新正确会话的队列 + FCnt,而不是总是假设失效是关于dev.Session
  • AS 应该检查nacked消息来自哪个会话 - nacked消息可能来自挂起的会话(从 AS 的角度来看),因此 FCnt 更新应该在正确的会话。
  • 最后,当Summary提到的消息发生时,AS 应该在dev.PendingSessiondev.Session之间切换 as should session。

环境

v3.11

您建议如何实施?

  • 添加需要的proto字段,在NS端填写。
  • 检查我们在失效/nack 期间使用的会话,并确保在 AS 中更新该会话。
  • 将会话切换过程移出handleUplink并在所有适当的上行链路类型上进行。
  • (可选)以最低FCnt返回DownlinkQueue{Push|Replace}上的错误详细信息,并始终将LastAFCntDown更新为该值。 这将确保系统在任何时候由于某种原因在 AS 和 NS 之间不同步时收敛。

你打算如何测试这个?

尝试重现重现步骤中提到的序列。

你能自己做这个并提交一个拉取请求吗?

是的,但由于这是一个重要的更改,因此我要求首先将此问题标记为discussion - 我们要引入这些更改吗? 下行队列失效一个似乎是一个要求,但其他的有利于一致性。

抄送@rvolosatovs

bug application server network server in progress

最有用的评论

我已将优先级升级为prio/high因为它会影响v3.11.1部署。

更改应如下所示:

  • SessionKeyIDDownlinkQueueInvalidation 。 如果队列为空,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];
}
  • AS 应该更新正确会话的队列 + FCnt,而不是总是假设失效是关于dev.Session

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

不要总是使用dev.Session ,而是在SessionKeyID上进行切换以建立要使用的会话。 如果需要,更新当前的dev.Session

  • AS 应该检查nacked消息来自哪个会话 - nacked消息可能来自挂起的会话(从 AS 的角度来看),因此 FCnt 更新应该在正确的会话。

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

和以前一样,切换SessionKeyID以确定要使用的会话。 如果需要,更新当前的dev.Session

  • (可选)以最低FCnt返回DownlinkQueue{Push|Replace}上的错误详细信息,并始终将LastAFCntDown更新为该值。 这将确保系统在任何时候由于某种原因在 AS 和 NS 之间不同步时收敛。

应填写以下proto加法并将其作为错误详细信息添加到 NS 中的errFCntTooLow中:

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变化是不够的。 我不认为这种转换在一天结束时是错误的,但我们必须解决这些关于会话互模拟的怪癖。

抄送@johanstokking@rvolosatovs

所有8条评论

正如我们已经讨论过的那样,我赞成这一点。
Application Server 应该始终信任 Network Server,因为它始终拥有有关设备会话的最新数据。

  • 终端设备发送 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部署。

更改应如下所示:

  • SessionKeyIDDownlinkQueueInvalidation 。 如果队列为空,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];
}
  • AS 应该更新正确会话的队列 + FCnt,而不是总是假设失效是关于dev.Session

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

不要总是使用dev.Session ,而是在SessionKeyID上进行切换以建立要使用的会话。 如果需要,更新当前的dev.Session

  • AS 应该检查nacked消息来自哪个会话 - nacked消息可能来自挂起的会话(从 AS 的角度来看),因此 FCnt 更新应该在正确的会话。

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

和以前一样,切换SessionKeyID以确定要使用的会话。 如果需要,更新当前的dev.Session

  • (可选)以最低FCnt返回DownlinkQueue{Push|Replace}上的错误详细信息,并始终将LastAFCntDown更新为该值。 这将确保系统在任何时候由于某种原因在 AS 和 NS 之间不同步时收敛。

应填写以下proto加法并将其作为错误详细信息添加到 NS 中的errFCntTooLow中:

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变化是不够的。 我不认为这种转换在一天结束时是错误的,但我们必须解决这些关于会话互模拟的怪癖。

抄送@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 接收到的事件(作为队列的一部分)采取行动从根本上是不够的:

  • 消息可能是旧的,但我们想对队列进行修复_现在_
  • 消息可能会丢失 - 队列不是无限的
  • 消息可能会重新排序 - 它们被异步推送到队列中,并以可能重新排序的方式弹出

鉴于这些特点,有两种选择:

  • 将队列计算延迟到批处理结束(基本上如果你收到 10 个下行队列失效,你只在最后重新计算队列)。 由于以下原因,这还不够:

    • 当AS处理一批消息时,它仍然不知道他是_真的_在队列的末尾,还是在中间处理了某个批

    • 消息可能仍然会丢失,并且确定它们的顺序并非易事。

  • 只是_信任NS_。 我的意思是,推送/替换操作返回dev.Session.SessionKeyIDdev.PendingSession.SessionKeyIDLastAFCntDown ,作为错误详细信息的一部分。 然后我们使用错误详细信息在 AS 中重建会话。 从根本上说,这意味着当我们尝试使用过期数据(可能是过期会话,也可能是 FCnt 太低)进行下行队列操作时,我们最终会收敛到 NS 状态。 可能需要一、二、三次尝试,我会使其有界以避免无限旋转,但我们至少使用比上行消息队列中的信息新得多的信息进行操作。
  • 只是_信任NS_。 我的意思是,推送/替换操作返回dev.Session.SessionKeyIDdev.PendingSession.SessionKeyIDLastAFCntDown ,作为错误详细信息的一部分。 然后我们使用错误详细信息在 AS 中重建会话。 从根本上说,这意味着当我们尝试使用过期数据(可能是过期会话,也可能是 FCnt 太低)进行下行队列操作时,我们最终会收敛到 NS 状态。 可能需要一、二、三次尝试,我会使其有界以避免无限旋转,但我们至少使用比上行消息队列中的信息新得多的信息进行操作。

我认为这是最好的选择。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

ecities picture ecities  ·  5评论

htdvisser picture htdvisser  ·  4评论

johanstokking picture johanstokking  ·  8评论

w4tsn picture w4tsn  ·  6评论

rvolosatovs picture rvolosatovs  ·  9评论