diff --git a/third_party/axle_device/config.go b/third_party/axle_device/config.go index 50dcb7a..6d1c74f 100644 --- a/third_party/axle_device/config.go +++ b/third_party/axle_device/config.go @@ -3,18 +3,18 @@ package axle_device // RsspConfig CI系统与计轴设备的安全通信协议配置参数 // 计轴设备(管理一个集中站的所有计轴器)配置 type RsspConfig struct { - SrcAddr uint16 //16位源地址,本地地址 - DstAddr uint16 //16位目的地址,远程地址 - DataVer1 uint32 //通道1数据版本 - DataVer2 uint32 //通道2数据版本 - SID1 uint32 //通道1源标识 - SID2 uint32 //通道2源标识 - SINIT1 uint32 //通道1序列初始 - SINIT2 uint32 //通道2序列初始 - SendingPeriod uint32 //接收方每个安全通信会话对应的发送周期值,单位ms - SSRTimeout uint32 //等待SSR回应的定时器超时值,单位ms - Mtv uint32 //每个安全通信会话可容忍的最大时序偏差,即当前接收的RSD的序列号与上一次RSD的序列号最大允许差值 - Udl uint32 //每个安全通信会话RSD应用数据长度发送和接收的配置值(支持固定长度和可变长度);0-可变长度,大于0即固定长度 + SrcAddr uint16 //16位源地址,本地地址 + DstAddr uint16 //16位目的地址,远程地址 + DataVer1 uint32 //通道1数据版本 + DataVer2 uint32 //通道2数据版本 + SID1 uint32 //通道1源标识 + SID2 uint32 //通道2源标识 + SINIT1 uint32 //通道1序列初始 + SINIT2 uint32 //通道2序列初始 + SendingPeriod uint32 //接收方每个安全通信会话对应的发送周期值,单位ms + SsrRsspTimeout uint32 //等待SSR回应的定时器超时值,为RsspTimer时间,1=SendingPeriod + Mtv uint32 //每个安全通信会话可容忍的最大时序偏差,即当前接收的RSD的序列号与上一次RSD的序列号最大允许差值 + Udl uint32 //每个安全通信会话RSD应用数据长度发送和接收的配置值(支持固定长度和可变长度);0-可变长度,大于0即固定长度 } // CheckAddress 检测目标源地址目的地址是否在配置中 diff --git a/third_party/axle_device/rssp_server.go b/third_party/axle_device/rssp_server.go index 2a43110..c340ba2 100644 --- a/third_party/axle_device/rssp_server.go +++ b/third_party/axle_device/rssp_server.go @@ -7,8 +7,11 @@ import ( // RsspChannel 实现rssp通信 type RsspChannel struct { + //rssp安全通信配置 config *RsspConfig - //批次编号,发送序列号,周期计数器 + //rssp时钟 + rsspTimer *RsspTimer + //批次编号,发送序列号 sn *message.RsspSn //安全通道1时间戳 ch1Ts *message.RsspLFSR @@ -24,10 +27,42 @@ type RsspChannel struct { rcvCh2Ts uint32 //最近一次接收到的报文的序列号 rcvSn uint32 + //时序校验请求发送记录 + sendSseRecord *SseFireRecord } -// HandleRsspMsg 处理接收到的rssp报文 -func (s *RsspChannel) HandleRsspMsg(pack []byte) { +// RsspTimer rssp时钟,每一个tick周期为config.SendingPeriod +type RsspTimer struct { + t uint64 +} + +func (s *RsspTimer) tick() { + s.t++ +} +func (s *RsspTimer) now() uint64 { + return s.t +} + +// SseFireRecord 发送时序校验请求的记录 +type SseFireRecord struct { + send *message.RsspSse //已经发送的时序校验请求 + rsspTime uint64 //发送时序校验请求时的rssp时间 +} + +func (s *SseFireRecord) record(send *message.RsspSse, rsspTime uint64) { + s.send = send + s.rsspTime = rsspTime +} +func (s *SseFireRecord) clear() { + s.send = nil + s.rsspTime = 0 +} +func (s *SseFireRecord) hasRecord() bool { + return s.send != nil +} + +// 处理接收到的rssp报文 +func (s *RsspChannel) handleRsspMsg(pack []byte) { //报文头校验 head := &message.RsspHead{} if !head.Parse(pack) { //解析报文头失败 @@ -72,6 +107,10 @@ func (s *RsspChannel) HandleRsspMsg(pack []byte) { // 处理接收到的实时安全数据 func (s *RsspChannel) handleRsspRsd(rsd *message.RsspRsd) { + if rsd.Pic != message.PIC_MASTER { + slog.Debug("丢弃接收的RSSP-RSD报文:来自备系") + return + } //序列号校验 //接收的序列号小于最近一次有效序列号,则触发SSE时序校验 if rsd.Sn < s.rcvSn { @@ -79,18 +118,38 @@ func (s *RsspChannel) handleRsspRsd(rsd *message.RsspRsd) { s.fireSse(rsd) return } - if rsd.Sn-s.rcvSn > s.config.Mtv { + dSn := rsd.Sn - s.rcvSn + if dSn > s.config.Mtv { slog.Debug("丢弃接收的RSSP-RSD报文:当前接收RSD的序列号与最近一次接收的RSD的序列号差值过大,触发SSE") s.fireSse(rsd) return } //SVC校验 + c1Crc32 := message.RsspC1Crc32(rsd.Sad) + c1SidTs := c1Crc32 ^ rsd.Svc1 ^ message.SCW_C1 + // + c2Crc32 := message.RsspC2Crc32(rsd.Sad) + c2SidTs := c2Crc32 ^ rsd.Svc2 ^ message.SCW_C2 + //todo ... SVC校验待完善 + _ = c1SidTs + _ = c2SidTs + //校验通过 + //记录本次接收RSD的序列号和安全校验通道时间戳 + s.rcvSn = rsd.Sn + s.rcvCh1Ts = c1SidTs ^ s.config.SID1 + s.rcvCh2Ts = c2SidTs ^ s.config.SID2 + //通知应用层接收应用数据 + s.rcvUserData(rsd.Sad) +} + +// 从安全通道成功接收到应用层数据 +func (s *RsspChannel) rcvUserData(userData []byte) { } // 触发时序校正请求 func (s *RsspChannel) fireSse(rsd *message.RsspRsd) { - + s.sendSse() } // 接收到时序校正请求 @@ -99,8 +158,22 @@ func (s *RsspChannel) handleRsspSse(rsd *message.RsspSse) { } // 接收到时序校正应答 -func (s *RsspChannel) handleRsspSsr(rsd *message.RsspSsr) { - +func (s *RsspChannel) handleRsspSsr(ssr *message.RsspSsr) { + //SSR校验 + if !s.sendSseRecord.hasRecord() { + slog.Debug("丢弃接收的RSSP-SSR报文:未发起过SSE时序校正请求") + return + } + if s.rsspTimer.t-s.sendSseRecord.rsspTime > uint64(s.config.SsrRsspTimeout) { + slog.Debug("丢弃接收的RSSP-SSR报文:等待SSE响应超时") + return + } + if ssr.SeSn != s.sendSseRecord.send.Sn { + slog.Debug("丢弃接收的RSSP-SSR报文:SSR与SSE不对应") + return + } + //恢复时序 + //todo } // 将序列号和时间戳更新到下一个值