前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LoRaWAN 帧计数机制及典型问题分析

LoRaWAN 帧计数机制及典型问题分析

作者头像
twowinter
发布2021-12-07 14:12:07
8200
发布2021-12-07 14:12:07
举报
文章被收录于专栏:twowinter

这篇笔记对 LoRaWAN 常见的 ABP 设备帧计数问题进行了追踪分析,介绍了帧计数禁用的调试办法,以及一个不大常见却又隐蔽的细节问题。希望帮助 LoRaWAN 初学者系统性地了解 LoRaWAN 的帧计数机制。

背景

最近一周接连遇到了两个朋友关于 LoRaWAN 帧计数的问题咨询,特别是一个问题隐藏地比较深,好不容易排查了出来,因此做了笔记记录下。

一个是朋友A发来的,他的问题很典型,很多初学者都会遇到,就是 LoRaWAN 设备莫名其妙就不上报数据了,提示帧计数异常。

我们先从这个问题来说起。

协议介绍

这段协议英文还是比较拗口,中间有一句太长都不好断句,翻出了之前啃过的这段翻译(https://github.com/twowinter/LoRaWAN-Specification_ZH_CN),这段中的 provided 是假如的意思,以前没翻译出来,于是重新整理了下翻译。

代码语言:javascript
复制
终端入网成功后,终端和服务端的上下行帧计数同时置0。 每次发送消息后,发送端与之对应的 FCntUp 或 FCntDown 就会加1。
如果收到的帧计数相比当前计数有增长,同时两者相差小于 MAX_FCNT_GAP(考虑了计数翻转),接收方就按接收的帧计数更新对应值。
如果两者相差大于 MAX_FCNY_GAP 就说明中间丢失了很多数据,这条数据包就被丢掉。

所以我们可以小结下,一个合理的FCnt必须满足两个点: 1.FCnt 必须是增长的; 2.FCnt 的变化值必须小于 MAX_FCNT_GAP;

MAX_FCNT_GAP 是多少呢?在 LoRaWAN 区域参数规范里有介绍,咱们CN470中这个数值是 16384。

ABP设备帧计数问题分析

回到开头的问题上。

OTAA设备一般很少遇到FCnt的问题,因为每次设备重启可能都会进行Join,这样FCnt直接都置为0了。 而ABP设备没有Join操作,很多设备没做FCnt的保存,一旦重启,设备FCnt归0,而NS还是之前的旧值,那接下来的数据都会被丢弃,一直得等 FCnt 递增超过之前的大小。

同学可能会问,为什么一定要等 FCnt 超过缓存值才能正常通信呢?

因为设备上报的FCnt如果是一个旧的历史值,那说明这是一个收到过的数据,旧的数据就没必要处理了。如果不这样设计的话,那极端情况下,可能会被重放攻击。比如一个水表场景,我可以录下水表过去的一包数据,表明水表的度数,等要交水费重放这一个数据包,这样就不用交水费了。

禁用帧计数校验

那一些朋友可能手头就只有一个不完善的ABP设备,一旦重启设备FCnt重置就无法通信了,那该怎么办?

简单的办法是这样,每次重启了就手动在 NS 后台重置下这个 FCnt,让NS的缓存计数也清零。

这样每次重启都要操作NS,还有更简单的办法吗?

开源协议栈 chirpStack 为了方便开发者调试,提供了一个选项 Disable frame-counter validation,可以禁用掉对帧计数的校验。

正常情况下,FCnt 正常,那数据传输也正常,比如下面这两种情况,只要FCnt是增加的,且GAP不超过限值,那都OK

代码语言:javascript
复制
 DeviceFCntUp 80 SessionFCntUp 0
 DeviceFCntUp 10080 SessionFCntUp 0

禁用了帧计数校验后,就很潇洒了,即使FCnt乱来也都能正常进行数据传输。比如下面的两种情况,一个是设备FCnt重置了,一个是设备FCnt与平台的FCnt差值超过了限值,即使是这样的情况,NS也能正常传输这些设备数据。

代码语言:javascript
复制
 DeviceFCntUp 0 SessionFCntUp 249 // FCnt 回滚
 DeviceFCntUp 30080 SessionFCntUp 249 // FCnt 超过 MAX_FCNT_GAP

典型问题:禁用帧计数校验也不灵

问题描述

照理来说这个帧计数校验挺好用的,至少小能手使用起来还挺方便。

但最近一个伙伴在进行NS迁移(将一些设备从旧的NS迁到新的NS)时就遇到了一个问题, 明明在新的NS上禁用掉了帧计数校验,设备数据也从网关上报到了NS,但NS却拦截了这个设备的数据,迟迟无法正常传输。

开源 NS 处理逻辑

于是找到了 NS 的代码研究起来,伪代码如下,/internal/storage/device_session.go。

代码语言:javascript
复制
func GetDeviceSessionForPHYPayload() {
    ...
    fullFCnt, ok := ValidateAndGetFullFCntUp(s, macPL.FHDR.FCnt)
    if !ok {
        // If RelaxFCnt is turned on, just trust the uplink FCnt
        // this is insecure, but has been requested by many people for
        // debugging purposes.
        // Note that we do not reset the FCntDown as this would reset the
        // downlink frame-counter on a re-transmit, which is not what we
        // want.
        if s.SkipFCntValidation {
            fullFCnt = macPL.FHDR.FCnt
            s.FCntUp = macPL.FHDR.FCnt
            s.UplinkHistory = []UplinkHistory{}

            // validate if the mic is valid given the FCnt reset
            // note that we can always set the ConfFCnt as the validation
            // function will only use it when the ACK bit is set
            micOK, err := phy.ValidateUplinkDataMIC(s.GetMACVersion(), s.ConfFCnt, uint8(txDR), uint8(txCh), s.FNwkSIntKey, s.SNwkSIntKey)
            if err != nil {
                return DeviceSession{}, errors.Wrap(err, "validate mic error")
            }
        }
    }
    ...
}

func ValidateAndGetFullFCntUp(s DeviceSession, fCntUp uint32) (uint32, bool) {
	// we need to compare the difference of the 16 LSB
	gap := uint32(uint16(fCntUp) - uint16(s.FCntUp%65536))
	if gap < band.Band().GetDefaults().MaxFCntGap {
		return s.FCntUp + gap, true
	}
	return 0, false
}

原因分析

从日志来看,DeviceFCntUp 已经达到了 105007,因此超过了 MAX_FCNT_GAP,代码逻辑进入到了 SkipFCntValidation 的条件处理中,在这里返回了 MIC 校验出错的结果。

小能手于是用模拟器做了一些测试,最终定位到 FCnt 上,在 SessionFCntUp 为 0 的情况下,DeviceFCntUp 如果小于 65535 则没问题,超过 65535 则会 MIC 报错。

代码语言:javascript
复制
DeviceFCntUp 57921 SessionFCntUp 0 // mic OK
 DeviceFCntUp 123456 SessionFCntUp 0 // mic err

于是推断出来原因应该是这样,FCnt 在空中(LoRaMAC)只能传输16bit,因此 NS 无法知道设备 FCnt 是否大于65535,只能按照低16bit来处理。

解决办法

所以在这种情况下,FCnt 的同步就成问题了,只能手动告诉 NS 当前 FCnt,这时候 NS 上的 SessionFCntUp 只要低于 DeviceFCntUp,且差值不超 MAX_FCNT_GAP 就可以了。

DeviceFCntUp 是 105007,我在 NS 后台配了个 100007,过一会儿设备便正常上报了。问题解决。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/10/16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 协议介绍
  • ABP设备帧计数问题分析
  • 禁用帧计数校验
  • 典型问题:禁用帧计数校验也不灵
    • 问题描述
      • 开源 NS 处理逻辑
        • 原因分析
          • 解决办法
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档