mirror of
https://gitee.com/willfree/mlsr.git
synced 2026-10-04 19:42:02 +08:00
269 lines
8.9 KiB
Go
269 lines
8.9 KiB
Go
// Package communication
|
|
// @Author: Wang Feng / zhengqi Wu
|
|
// @Description:
|
|
// @Version: 0.1.0
|
|
// @Date: 2022/4/1 16:07
|
|
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
|
//
|
|
|
|
package communication
|
|
|
|
import (
|
|
"errors"
|
|
common2 "minlib/common"
|
|
"minlib/component"
|
|
"minlib/logicface"
|
|
mutil "minlib/utils"
|
|
"mlsr/common"
|
|
"mlsr/lsa"
|
|
"mlsr/utils"
|
|
"strconv"
|
|
)
|
|
|
|
// IsLsaNew 用于判断新的LSA是否到来
|
|
//
|
|
// 参数说明:
|
|
//
|
|
// identifier LSA的标识
|
|
//
|
|
// lsaType LSA的类型
|
|
//
|
|
// seq LSA的序列号
|
|
//
|
|
// incomingLogicFaceId LSA到来的LogicFaceId
|
|
//
|
|
type IsLsaNew = func(identifier *component.Identifier, lsaType lsa.LsaType, seq uint64, incomingLogicFaceId uint64) bool
|
|
|
|
// SyncLogicHandler MLSR-to-MINSync 中间层
|
|
//
|
|
// 本结构体为MLSR提供MINSync同步协议的一种抽象
|
|
//
|
|
// MLSR与MINSync之间并不存在强关联关系,只是因为当前只实现了MINSync这一版本的同步协议,因此后续有其余的同步协议也可以通过该中间层向
|
|
// MLSR提供同步协议的抽象
|
|
//
|
|
type SyncLogicHandler struct {
|
|
/////////////// 私有属性 /////////////
|
|
// syncFace 用于同步数据的LogicFace
|
|
syncFace *logicface.DummyClientLogicFace
|
|
// isLsaNew 用于判断LSA是否更新的自定义函数
|
|
isLsaNew IsLsaNew
|
|
// confParam MLSR配置参数
|
|
confParam *common.MlsrConfigParameters
|
|
// nlsrComponent NLSR字符串
|
|
mlsrComponent string
|
|
// lsaComponent LSA字符串
|
|
lsaComponent string
|
|
/////////////// 公有属性 /////////////
|
|
// OnNewLsa 当新LSA到来时的所触发的信号
|
|
OnNewLsa *mutil.Signal
|
|
// NameLsaUserPrefix NameLsa前缀
|
|
NameLsaUserPrefix *component.Identifier
|
|
// AdjLsaUserPrefix AdjLsa前缀
|
|
AdjLsaUserPrefix *component.Identifier
|
|
// CoorLsa 双曲路由Lsa前缀
|
|
CoorLsaUserPrefix *component.Identifier
|
|
// SyncLogic 同步数据逻辑(目前仅支持MINSync)
|
|
SyncLogic *SyncProtocolAdapter
|
|
}
|
|
|
|
// ProcessUpdate 处理到达该路由节点的新同步数据
|
|
//
|
|
// 参数说明:
|
|
//
|
|
// updateName: 更新的数据前缀
|
|
//
|
|
// highSeq: 更新的数据版本
|
|
//
|
|
// incomingFaceId: 该同步数据到达的LogicFaceId
|
|
//
|
|
func (s *SyncLogicHandler) ProcessUpdate(updateName *component.Identifier, highSeq, incomingFaceId uint64) {
|
|
common2.LogInfo("Update Name: ", updateName.ToUri(), " Seq no: ", highSeq)
|
|
|
|
// nlsrPosition 从同步数据的标识中获取子字符串'nlsr'的位置
|
|
mlsrPosition := utils.GetNameComponentPosition(updateName, s.mlsrComponent)
|
|
// lsaPosition 从同步数据的标识中获取子字符串'lsa'的位置
|
|
lsaPosition := utils.GetNameComponentPosition(updateName, s.lsaComponent)
|
|
|
|
if mlsrPosition < 0 || lsaPosition < 0 {
|
|
common2.LogWarn("收到了不合法的同步更新数据")
|
|
return
|
|
}
|
|
|
|
// networkName 用于表示源MLSR节点网络标识
|
|
networkName, err := updateName.GetSubIdentifier(1, mlsrPosition-1)
|
|
if err != nil {
|
|
common2.LogError("解析源MLSR节点网络标识出错", err.Error())
|
|
return
|
|
}
|
|
networkNameBlock, err := networkName.SelfWireEncode(networkName)
|
|
|
|
// routerName 用于表示源MLSR节点路由器标识
|
|
// NLSR源代码:updateName.getSubName(lsaPosition + 1).getPrefix(-1);
|
|
// 意味着取updateName的第[lsaPosition+1, updateName.Size()-2]个组件组成标识
|
|
// 等价于从第lsaPosition+1开始取updateName.Size()-lsaPosition-2个
|
|
routerName, err := updateName.GetSubIdentifier(lsaPosition+1, updateName.Size()-lsaPosition-2)
|
|
if err != nil {
|
|
common2.LogError("解析源MLSR节点路由器标识出错", err.Error())
|
|
return
|
|
}
|
|
|
|
routerNameBlock, err := routerName.SelfWireEncode(routerName)
|
|
if err != nil {
|
|
common2.LogError(err.Error())
|
|
return
|
|
}
|
|
routerNameCopy, err := component.NewIdentifierByBlock(routerNameBlock)
|
|
if err != nil {
|
|
common2.LogError(err.Error())
|
|
return
|
|
}
|
|
|
|
// 将networkName和routerName组合成originRouterName
|
|
originRouterName, err := component.NewIdentifierByBlock(networkNameBlock)
|
|
if err != nil {
|
|
common2.LogError(err.Error())
|
|
return
|
|
}
|
|
for _, comp := range routerNameCopy.GetComponents() {
|
|
originRouterName.Append(comp)
|
|
}
|
|
|
|
s.ProcessUpdateFromSync(originRouterName, updateName, highSeq, incomingFaceId)
|
|
}
|
|
|
|
// ProcessUpdateFromSync 处理更新的回调函数
|
|
//
|
|
// 主要用来确定更新的LSA类型并拉取它的载荷
|
|
//
|
|
// 首先检查收到的更新是否是我们自身发布的,这是可能发生的,
|
|
// 原因可以查看MINSync全同步逻辑中的TestMultipleNodesSimultaneousPublish测试用例
|
|
//
|
|
// 随后检查更新的类型,确定该更新信息用于更新哪类LSA
|
|
//
|
|
// 最后转发兴趣包拉取该LSA对应的载荷
|
|
//
|
|
func (s *SyncLogicHandler) ProcessUpdateFromSync(originRouter, updateName *component.Identifier, seqNo, incomingFaceId uint64) {
|
|
common2.LogDebug("Origin Router of update: ", originRouter.ToUri())
|
|
|
|
// 先校验该LSA更新是否由本地路由器发布,一个路由器不应该拉取自己发布的LSA
|
|
if originRouter.ToUri() != s.confParam.GetRouterPrefix().ToUri() {
|
|
// 校验LSA类型
|
|
var lsaType lsa.LsaType
|
|
lsaTypeComp, err := updateName.Get(-1)
|
|
if err != nil {
|
|
common2.LogError(err.Error())
|
|
return
|
|
}
|
|
// 将lsaTypeComp字符串转换为LSAType
|
|
// 先转为int,再转为LSAType
|
|
lsaTypeInt, err := strconv.Atoi(lsaTypeComp.ToUri())
|
|
if err != nil {
|
|
common2.LogError(err.Error())
|
|
return
|
|
}
|
|
lsaType = lsa.LsaType(lsaTypeInt)
|
|
|
|
// 判断是否Lsa更新
|
|
if s.isLsaNew(originRouter, lsaType, seqNo, incomingFaceId) {
|
|
// 双曲路由特性未实现,这里先不判断
|
|
//if lsaType == lsa.LsaADJACENCYType && seqNo != 0 {
|
|
// common2.LogError()
|
|
// return
|
|
//}
|
|
//if (lsaType == Lsa::Type::COORDINATE && seqNo != 0 &&
|
|
// m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) {
|
|
// NLSR_LOG_ERROR("Got an update for coordinate LSA when link-state " <<
|
|
// "is enabled. Not going to fetch.");
|
|
// return;
|
|
//}
|
|
// 触发OnNewLsa信号,通知MLSR新的LSA到来
|
|
s.OnNewLsa.Emit(updateName, seqNo, originRouter, incomingFaceId)
|
|
}
|
|
}
|
|
}
|
|
|
|
// PublishRoutingUpdate 通知MINSync向其它节点发布更新
|
|
//
|
|
// 序列号seqNo取决于调用该方法时sequencing manager的状态
|
|
//
|
|
// 发布更新时会这样做可以满足其他路由器的Sync兴趣包,让它们知道有同步更新可用
|
|
//
|
|
func (s *SyncLogicHandler) PublishRoutingUpdate(t lsa.LsaType, seqNo uint64) {
|
|
switch t {
|
|
case lsa.LsaADJACENCYType:
|
|
s.SyncLogic.PublishUpdate(s.AdjLsaUserPrefix, seqNo)
|
|
case lsa.LsaCOORDINATEType:
|
|
s.SyncLogic.PublishUpdate(s.CoorLsaUserPrefix, seqNo)
|
|
case lsa.LsaNAMEType:
|
|
s.SyncLogic.PublishUpdate(s.NameLsaUserPrefix, seqNo)
|
|
}
|
|
}
|
|
|
|
// NewSyncLogicHandler SyncLogicHandler的工厂方法
|
|
//
|
|
func NewSyncLogicHandler(face *logicface.DummyClientLogicFace, isLsaNew IsLsaNew, conf *common.MlsrConfigParameters) (*SyncLogicHandler, error) {
|
|
if face == nil || isLsaNew == nil || conf == nil {
|
|
return nil, errors.New("无效的输入参数")
|
|
}
|
|
|
|
// 基础参数
|
|
syncLogicHandler := new(SyncLogicHandler)
|
|
syncLogicHandler.OnNewLsa = mutil.NewSignal()
|
|
syncLogicHandler.syncFace = face
|
|
syncLogicHandler.isLsaNew = isLsaNew
|
|
syncLogicHandler.confParam = conf
|
|
|
|
// 标识组件构造
|
|
syncLogicHandler.mlsrComponent = "mlsr"
|
|
syncLogicHandler.lsaComponent = "LSA"
|
|
// NLSR的源码中使用了字符串类型的标识组件, 而不是非负数类型
|
|
nameComponent := component.CreateIdentifierComponentByString(strconv.Itoa(int(lsa.LsaNAMEType)))
|
|
adjComponent := component.CreateIdentifierComponentByString(strconv.Itoa(int(lsa.LsaADJACENCYType)))
|
|
coorComponent := component.CreateIdentifierComponentByString(strconv.Itoa(int(lsa.LsaCOORDINATEType)))
|
|
|
|
// Bug: 复制标识SyncPrefix
|
|
// Fix: 复制标识SyncUserPrefix
|
|
syncUserPrefix := conf.GetSyncUserPrefix()
|
|
if syncUserPrefix == nil {
|
|
return nil, errors.New("无效同步标识")
|
|
}
|
|
syncUserPrefixBlock, err := syncUserPrefix.SelfWireEncode(syncUserPrefix)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// NameLsaUserPrefix 构建
|
|
syncLogicHandler.NameLsaUserPrefix, err = component.NewIdentifierByBlock(syncUserPrefixBlock)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
syncLogicHandler.NameLsaUserPrefix.Append(nameComponent)
|
|
// AdjLsaUserPrefix 构建
|
|
syncLogicHandler.AdjLsaUserPrefix, err = component.NewIdentifierByBlock(syncUserPrefixBlock)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
syncLogicHandler.AdjLsaUserPrefix.Append(adjComponent)
|
|
// CoorLsaUserPrefix 构建
|
|
syncLogicHandler.CoorLsaUserPrefix, err = component.NewIdentifierByBlock(syncUserPrefixBlock)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
syncLogicHandler.CoorLsaUserPrefix.Append(coorComponent)
|
|
|
|
// 双曲路由特性暂未支持
|
|
// if conf.GetHyperbolicState()
|
|
|
|
// 同步逻辑实例
|
|
syncLogicHandler.SyncLogic, err = NewSyncProtocolAdapter(face,
|
|
// 公共的SyncPrefix
|
|
conf.GetSyncPrefix(),
|
|
// userPrefix
|
|
syncLogicHandler.NameLsaUserPrefix,
|
|
// syncInterestLifetime
|
|
conf.GetSyncInterestLifetime(),
|
|
// 处理更新同步数据的回调函数
|
|
syncLogicHandler.ProcessUpdate)
|
|
|
|
return syncLogicHandler, nil
|
|
}
|