1
0
mirror of https://gitee.com/willfree/mlsr.git synced 2026-06-18 05:50:25 +08:00
Files
mlsr/hello/HelloProtocol.go
2022-08-25 06:54:06 -07:00

307 lines
11 KiB
Go

// Package hello
// @Author: Pei Xinyuan
// @Description:
// @Version: 0.1.0
// @Date: 2022/7/14 14:49
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package hello
import (
common2 "minlib/common"
"minlib/component"
"minlib/logicface"
"minlib/packet"
"minlib/security"
"mlsr/common"
"mlsr/lsa"
"mlsr/lsdb"
"mlsr/route"
"mlsr/utils"
"time"
)
// 用于hello兴趣包的名称的组件
const INFO_COMPONENT = "INFO"
const MLSR_COMPONENT = "mlsr"
type HelloProtocol struct {
m_face *logicface.DummyClientLogicFace
m_scheduler *lsdb.MlsrScheduler
m_keychain *security.KeyChain
mlsrConfig *common.MlsrConfig
m_routingTable *route.RoutingTable
m_lsdb *lsdb.Lsdb
m_adjacencyList *lsa.AdjLsaAdjacenctList
// 协议状态
state bool // 程序生成状态, true 为正常运行, false 为关闭状态
// 接收到hello响应数据包后的信号量触发
OnInitialHelloDataValidated *utils.Signal
}
//
// Init
// @Description: Hello协议-初始化
// @receiver hp
// @param face
// @param scheduler
// @param keychain
// @param mlsrConfig
// @param routingTable
// @param mlsdb
//
func (hp *HelloProtocol) Init(face *logicface.DummyClientLogicFace,
scheduler *lsdb.MlsrScheduler,
keychain *security.KeyChain, mlsrConfig *common.MlsrConfig,
routingTable *route.RoutingTable, mlsdb *lsdb.Lsdb) {
// 信号量初始化
hp.OnInitialHelloDataValidated = utils.NewSignal()
// 其它数据结构
hp.m_face = face
hp.m_scheduler = scheduler
hp.m_keychain = keychain
hp.mlsrConfig = mlsrConfig
hp.m_routingTable = routingTable
hp.m_lsdb = mlsdb
hp.m_adjacencyList = mlsrConfig.GetAdjacencys()
// logicface相关
// 构造接收hello兴趣包的监听前缀
name, err := component.CreateIdentifierByString(
hp.mlsrConfig.GetRouterPrefix().ToUri() + "/" + MLSR_COMPONENT + "/" + INFO_COMPONENT)
if err != nil {
common2.LogFatal("HelloProtocol Setting interest filter for Hello interest error, interest generate wrong.", err)
return
}
// 协议状态
hp.state = true
// 直接使用registerPrefix来进行前缀监听
onRegisterFailF := func(*component.Identifier) {
common2.LogFatal("HelloProtocol onRegisterFailF backcall")
}
onRegisterSuccessF := func(*component.Identifier) {
common2.LogDebug("HelloProtocol onRegisterSuccess backcall")
}
onInterestF := func(interest *packet.Interest) {
common2.LogDebug("HelloProtocol onInterest backcall")
err = hp.dealWithRecvPkt(interest)
if err != nil {
common2.LogDebug("HelloProtocol dealWithRecvPkt error, ", err.Error())
}
}
hp.m_face.RegisterPrefix(name, 3000, onInterestF, onRegisterFailF, onRegisterSuccessF)
// 启动收包协程
go hp.m_face.ProcessEvent()
}
//
// expressInterest
// @Description: 根据传入的兴趣包名称和兴趣包过期时间,构建兴趣包,并发出去
// @receiver hp
// @param interestName
// @param _millseconds
//
func (hp *HelloProtocol) expressInterest(interestName *component.Identifier, _millseconds uint32) {
common2.LogDebug("HelloProtocol Expressing Interest: " + interestName.ToUri())
interest := packet.NewInterest()
interest.SetName(interestName)
interest.SetInterestLifeTime(uint64(_millseconds))
// 将兴趣包通过face发出,并对超时、nack、正常应答三种情况进行处理
err := hp.m_face.ExpressInterest(interest, hp.onContent, hp.processInterestTimedOut, hp.processInterestNack)
if err != nil {
common2.LogDebug("HelloProtocol express interest error, maybe the icn logic face doesn't work.", err)
return
}
}
//
// SendHelloInterest
// @Description: 向指定邻居路由器发送hello探测包
// @receiver hp
// @param neighbor
//
func (hp *HelloProtocol) SendHelloInterest(neighbor *component.Identifier) {
// 查找关于某个邻居路由器的邻接信息
adjInfo := hp.m_adjacencyList.FindAdjacencyByRouterIdentifier(neighbor)
// 如果没有找到,则不做处理
if adjInfo == nil {
return
}
// 如果找到了,且有对应的faceID,则发送一个hello探测包
if adjInfo.LogicFaceId() != 0 {
// interest name: /<neighbor>/NLSR/INFO/<router>
name, err := component.CreateIdentifierByString(adjInfo.GetNeighborRouterIdentifier().ToUri() +
"/" + MLSR_COMPONENT + "/" + INFO_COMPONENT +
"/" + GetSinglePrefixForHelloProtocol(hp.mlsrConfig.GetRouterPrefix()))
if err != nil {
common2.LogDebug("HelloProtocol SendHelloInterest error, hello name create wrong.", err)
return
}
// 将data发出去
hp.expressInterest(name, hp.mlsrConfig.GetInterestResendTime())
common2.LogDebug("HelloProtocol Sending HELLO interest: " + name.ToUri())
}
// 安排按照配置文件中的时间,若干秒后【默认一分钟】发送下一个hello兴趣包
job, err := hp.m_scheduler.ScheduleTaskAfterDuration(hp.mlsrConfig.GetInfoInterestInterval(), 1).
Do(hp.SendHelloInterest, neighbor)
job.LimitRunsTo(1)
hp.m_scheduler.StartAsync()
if err != nil {
common2.LogError("HelloProtocol ScheduleTask to send hello interest error. ", err.Error())
}
}
//
// processInterestNack
// @Description: 发送兴趣包给邻居路由器,当收到nack时,执行本函数
// @receiver hp
// @param interest
// @param nack
//
func (hp *HelloProtocol) processInterestNack(interest *packet.Interest, nack *packet.Nack) {
common2.LogDebug("HelloProtocol receive nack for interest: "+interest.GetName().ToUri()+
", the nack reason is: ", nack.GetNackReason(), "will treat as time out in 2s later.")
job, err := hp.m_scheduler.ScheduleTaskAfterDuration(2*time.Second, 1).
Do(hp.processInterestTimedOut, interest)
job.LimitRunsTo(1)
hp.m_scheduler.StartAsync()
if err != nil {
common2.LogError("HelloProtocol ScheduleTask to processInterestTimedOut error. ", err.Error())
}
}
//
// processInterestTimedOut
// @Description: 发送兴趣包给邻居路由器,当超时时,执行本函数
// @receiver hp
// @param interest
//
func (hp *HelloProtocol) processInterestTimedOut(interest *packet.Interest) {
common2.LogDebug("HelloProtocol time out for interest: " + interest.GetName().ToUri())
// interest name: /<neighbor>/NLSR/INFO/<router>
interestName := interest.GetName()
// 取出兴趣包倒数第二个组件,对其进行校验
infoComponent, err := interestName.Get(-2)
if err != nil {
common2.LogDebug("HelloProtocol processInterestTimedOut error, get(-2) err ", err)
return
}
if infoComponent.ToUri() != INFO_COMPONENT {
common2.LogDebug("HelloProtocol processInterestTimedOut error, INFO_COMPONENT not found in interestName ", err)
return
}
// 取"/NLSR"之前的所有组件组成的前缀,也即邻居路由器的前缀
neighborIdentifier, err := interestName.GetPrefix(-3)
if err != nil {
common2.LogDebug("HelloProtocol processInterestTimedOut error, interestName.GetPrefix error.", err)
return
}
// 将本机邻居列表中该邻居的超时次数增加1
err = hp.m_adjacencyList.IncrementTimedOutInterestCount(neighborIdentifier)
if err != nil {
common2.LogDebug("HelloProtocol processInterestTimedOut error, IncrementTimedOutInterestCount error.", err)
return
}
// 查找该邻居的状态
status, err := hp.m_adjacencyList.GetStatusOfNeighbor(neighborIdentifier)
if err != nil {
common2.LogDebug("HelloProtocol processInterestTimedOut error, GetStatusOfNeighbor error.", err)
return
}
// 查找该邻居的超时次数
infoIntTimedOutCount, err := hp.m_adjacencyList.GetTimedOutInterestCount(neighborIdentifier)
if err != nil {
common2.LogDebug("HelloProtocol processInterestTimedOut error, GetTimedOutInterestCount error.", err)
return
}
common2.LogDebug("HelloProtocol processInterestTimedOut Status: ", status)
common2.LogDebug("HelloProtocol processInterestTimedOut TimeoutCount: ", infoIntTimedOutCount)
// 如果超时次数小于阈值。则继续探测
if infoIntTimedOutCount < hp.mlsrConfig.GetInterestResendTime() {
name, err := component.CreateIdentifierByString(neighborIdentifier.ToUri() +
"/" + MLSR_COMPONENT + "/" + INFO_COMPONENT +
"/" + GetSinglePrefixForHelloProtocol(hp.mlsrConfig.GetRouterPrefix()))
if err != nil {
common2.LogDebug("HelloProtocol processInterestTimedOut error, hello name create wrong.")
return
}
common2.LogDebug("HelloProtocol processInterestTimedOut Resending interest: " + interestName.ToUri())
// 将兴趣包再次发出去
hp.expressInterest(name, hp.mlsrConfig.GetInterestResendTime())
} else if status == lsa.STATUS_ACTIVE {
// 如果重传次数达到阈值,且该路由器旧状态为激活状态,则将其修改为未激活
err = hp.m_adjacencyList.SetStatusOfNeighbor(neighborIdentifier, lsa.STATUS_INACTIVE)
if err != nil {
common2.LogDebug("HelloProtocol processInterestTimedOut error, set status error. ", err)
}
common2.LogDebug("HelloProtocol processInterestTimedOut, change status of " +
neighborIdentifier.ToUri() + " to IN-ACTIVE")
// 安排lsdb的邻接lsa重新构建
hp.m_lsdb.ScheduleAdjLsaBuild()
}
}
//
// onContent
// @Description: 发送兴趣包给邻居路由器,当收到data包时,执行本函数
// @receiver hp
// @param data
//
func (hp *HelloProtocol) onContent(interest *packet.Interest, data *packet.Data) {
common2.LogDebug("HelloProtocol Received data for INFO(name): " + data.GetName().ToUri())
// todo 这里先跳过签名验证,执行验证通过后的处理
// 取出数据包名称的倒数第三个组件,对其进行校验
infoComponent, err := data.GetName().Get(-3)
if err != nil {
common2.LogDebug("HelloProtocol onContent error, get(-3) err ", err)
return
}
if infoComponent.ToUri() != INFO_COMPONENT {
common2.LogDebug("HelloProtocol onContent error, INFO_COMPONENT not found in dataName ", err)
return
}
// 取"/NLSR"之前的所有组件组成的前缀,也即邻居路由器的前缀
neighborIdentifier, err := data.GetName().GetPrefix(-4)
if err != nil {
common2.LogDebug("HelloProtocol onContent error, dataName.GetPrefix error.", err)
return
}
// 查找该邻居的状态
oldStatus, err := hp.m_adjacencyList.GetStatusOfNeighbor(neighborIdentifier)
if err != nil {
common2.LogDebug("HelloProtocol onContent error, get old status error.", err)
return
}
// 设置该路由器的状态及超时次数
err = hp.m_adjacencyList.SetStatusOfNeighbor(neighborIdentifier, lsa.STATUS_ACTIVE)
if err != nil {
common2.LogDebug("HelloProtocol onContent error, set status error.", err)
return
}
err = hp.m_adjacencyList.SetTimedOutInterestCount(neighborIdentifier, 0)
if err != nil {
common2.LogDebug("HelloProtocol onContent error, set timeout count error.", err)
return
}
// 查找该邻居的新状态
newStatus, err := hp.m_adjacencyList.GetStatusOfNeighbor(neighborIdentifier)
if err != nil {
common2.LogDebug("HelloProtocol onContent error, get new status error.", err)
return
}
common2.LogDebug("HelloProtocol onContent, neighbor: ", neighborIdentifier.ToUri(),
", old status: ", oldStatus, ", new status: ", newStatus)
// 如果状态发生了更改,则安排邻接Lsa进行重新构建,并发射信号给fib,使其更新mir中的该face状态
if newStatus != oldStatus {
hp.m_lsdb.ScheduleAdjLsaBuild()
hp.OnInitialHelloDataValidated.Emit(neighborIdentifier)
}
}