mirror of
https://gitee.com/willfree/mlsr.git
synced 2026-06-03 15:56:13 +08:00
534 lines
16 KiB
Go
534 lines
16 KiB
Go
// Package lsdb
|
|
// @Author: Wang Feng
|
|
// @Description:
|
|
// @Version: 0.1.0
|
|
// @Date: 2022/3/24 11:41
|
|
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
|
//
|
|
|
|
package lsdb
|
|
|
|
import (
|
|
"bytes"
|
|
common2 "minlib/common"
|
|
"minlib/component"
|
|
"minlib/logicface"
|
|
"minlib/packet"
|
|
"mlsr/common"
|
|
"mlsr/communication"
|
|
"mlsr/lsa"
|
|
"mlsr/lsdb/LsaContainer"
|
|
"time"
|
|
)
|
|
|
|
// Lsdb更新状态
|
|
const (
|
|
INSTALLED = 0 // 已安装
|
|
UPDATED = 1 // 已更新
|
|
REMOVED = -1 // 已移除
|
|
)
|
|
|
|
const GRACE_PERIOD = 10 * time.Second // 超期宽限期。LSA比设定时间晚几秒钟被删除,以避免信息过早失效。
|
|
|
|
type Lsdb struct {
|
|
// 配置参数
|
|
mlsrConfig *common.MlsrConfig
|
|
|
|
// 同步协议配置项
|
|
sync *communication.SyncLogicHandler
|
|
|
|
// LSA容器
|
|
LsaContainer.LsaContainer
|
|
|
|
lsaRefreshTime time.Duration // lsa刷新时间
|
|
adjLsaBuildInterval time.Duration // 邻接LSA构建间隔
|
|
thisRouterPrefix *component.Identifier // 当前路由器的标识
|
|
|
|
// 任务调度器
|
|
scheduler *MlsrScheduler
|
|
// LogicFace接口
|
|
face *logicface.LogicFace
|
|
|
|
// 将LSA的名称从sync映射到其已知的最高序列号;
|
|
// 用于阻止MLSR尝试获取过时的LSA
|
|
highestSeqNo map[*component.Identifier]uint64
|
|
|
|
// 不同类型lsa的序列号管理器
|
|
sequencingManager *SequencingManager
|
|
|
|
isBuildAdjLsaScheduled bool // 是否安排构建邻接LSA
|
|
adjBuildCount uint64 // 邻接LSA的构建的统计数目
|
|
}
|
|
|
|
func (l *Lsdb) Init(mc *common.MlsrConfig, ms *MlsrScheduler,
|
|
_face *logicface.LogicFace) {
|
|
// 配置项
|
|
l.mlsrConfig = mc
|
|
// 调度器
|
|
l.scheduler = ms
|
|
// 逻辑face
|
|
l.face = _face
|
|
// 序列号管理器
|
|
l.sequencingManager = GetInstance()
|
|
// 存储器
|
|
err := l.LsaContainer.Init()
|
|
if err != nil {
|
|
common2.LogFatal("lsdb.LsaContainer init error, ", err.Error())
|
|
}
|
|
|
|
// todo 构造sync
|
|
|
|
// lsa刷新时间
|
|
l.lsaRefreshTime = l.mlsrConfig.GetLsaRefreshTime()
|
|
// 邻接lsa构建间隔
|
|
l.adjLsaBuildInterval = l.mlsrConfig.GetAdjLsaBuildInterval()
|
|
// 本机路由前缀
|
|
l.thisRouterPrefix = l.mlsrConfig.GetRouterPrefix()
|
|
|
|
// 是否已经安排邻接LSA的构建
|
|
l.isBuildAdjLsaScheduled = false
|
|
// 邻接LSA构建次数统计
|
|
l.adjBuildCount = 0
|
|
|
|
// 在LSDB初始化之前,对配置文件中的本机路由器进行拉式前缀注册(即监听该前缀)
|
|
// todo: 为了在Windows上单独测试,暂时注释掉face注册前缀这一步骤
|
|
//lsaPrefix := l.mlsrConfig.GetLsaPrefix()
|
|
//err := l.face.RegisterPullIdentifier(lsaPrefix, 2000)
|
|
//if err != nil {
|
|
// common2.LogFatal("Lsdb Init error, because of face register, ", err.Error())
|
|
//}
|
|
|
|
// 构建并安装自己的名称LSA
|
|
// todo 先测试其它项
|
|
//l.BuildAndInstallOwnNameLsa()
|
|
}
|
|
|
|
//
|
|
// DoesLsaExist
|
|
// @Description: 返回LSDB是否存在某个LSA的查询结果
|
|
// @receiver l
|
|
// @param routerIdentifier
|
|
// @param lsaType
|
|
// @return bool
|
|
//
|
|
func (l *Lsdb) DoesLsaNameExist(routerIdentifier *component.Identifier, lsaType lsa.LsaType) bool {
|
|
return l.ExistsRouterNameAndType(routerIdentifier, lsaType)
|
|
}
|
|
|
|
//
|
|
// DoesLsaExist
|
|
// @Description: 返回LSDB是否存在某个LSA的查询结果
|
|
// @receiver l
|
|
// @param lsa
|
|
// @return bool
|
|
//
|
|
func (l *Lsdb) DoesLsaExist(lsa lsa.ILsa) bool {
|
|
return l.Exists(lsa)
|
|
}
|
|
|
|
//
|
|
// BuildAndInstallOwnNameLsa
|
|
// @Description: 构建一个属于本路由器的名称LSA,并安装它到LSDB。
|
|
// @receiver l
|
|
//
|
|
func (l *Lsdb) BuildAndInstallOwnNameLsa() {
|
|
// 根据配置文件,构造本机的名称LSA
|
|
nlsa := new(lsa.NameLsa)
|
|
nlsa.SetOriginRouter(l.thisRouterPrefix) // 源路由
|
|
nlsa.SetSeqNo(l.sequencingManager.GetNameLsaSeq() + 1) // 序列号
|
|
nlsa.SetLsaExpirationTime(l.getLsaExpirationTimePoint()) // 超期时间
|
|
nlsa.NameLsaNamePrefixList.InsertNamePrefixList(l.mlsrConfig.GetNamePrefixList()) // 名称前缀列表
|
|
// 刷新序列号管理器中的名称LSA序列号
|
|
l.sequencingManager.IncreaseNameLsaSeq()
|
|
|
|
// todo: 使用sync通知路由更新
|
|
// m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
|
|
|
|
// 安装lsa到LSDB
|
|
l.InstallLsa(nlsa)
|
|
}
|
|
|
|
//
|
|
// BuildAndInstallOwnCoordinateLsa
|
|
// @Description: 构建一个属于本路由器的坐标LSA,并安装它到LSDB
|
|
// @receiver l
|
|
//
|
|
func (l *Lsdb) BuildAndInstallOwnCoordinateLsa() {
|
|
// todo:坐标计算预留接口
|
|
}
|
|
|
|
//
|
|
// ScheduleAdjLsaBuild
|
|
// @Description: 安排LSA的构建
|
|
// @receiver l
|
|
//
|
|
func (l *Lsdb) ScheduleAdjLsaBuild() {
|
|
// 计数
|
|
l.adjBuildCount++
|
|
// 日志记录
|
|
if l.isBuildAdjLsaScheduled {
|
|
common2.LogInfo("Rescheduling Adjacency LSA build in ", l.adjLsaBuildInterval)
|
|
} else {
|
|
common2.LogInfo("Scheduling Adjacency LSA build in ", l.adjLsaBuildInterval)
|
|
l.isBuildAdjLsaScheduled = true
|
|
}
|
|
// 安排构造邻接LSA
|
|
job, err := l.scheduler.ScheduleTaskAfterDuration(l.adjLsaBuildInterval, 1).Do(l.BuildAdjLsa)
|
|
job.LimitRunsTo(1)
|
|
l.scheduler.StartAsync()
|
|
if err != nil {
|
|
common2.LogError("Scheduling Adjacency LSA build error, ", err.Error())
|
|
}
|
|
}
|
|
|
|
//
|
|
// ProcessInterest
|
|
// @Description:收到一个兴趣包,根据兴趣包名称,查找LSA并返回。
|
|
// 处理兴趣包。类似NDN的拉式传输。
|
|
// 在NLSR的设计中,由于对兴趣包进行了进一步的分段,因此有以下两种兴趣包:
|
|
//* 1) 需要从segment fetcher中查找的兴趣包:
|
|
//* /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>
|
|
//* 2) 已经包含segment number的兴趣包:
|
|
//* /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>/<version>/<segmentNo>
|
|
// @receiver l
|
|
// @param interest
|
|
//
|
|
func (l *Lsdb) ProcessInterest(interest *packet.Interest) {
|
|
}
|
|
|
|
func (l *Lsdb) processInterestForLsa(interest *packet.Interest,
|
|
originRouterIdentifier *component.Identifier, lsaType lsa.LsaType, seqNo uint64) {
|
|
}
|
|
|
|
func (l *Lsdb) ProcessGPPkt(pkt *packet.GPPkt) {
|
|
}
|
|
|
|
//
|
|
// GetIsBuildAdjLsaScheduled
|
|
// @Description: 判断是否已经安排了邻接LSA的构建
|
|
// @receiver l
|
|
// @return bool
|
|
//
|
|
func (l *Lsdb) GetIsBuildAdjLsaScheduled() bool {
|
|
return l.isBuildAdjLsaScheduled
|
|
}
|
|
|
|
//
|
|
// GetSync
|
|
// @Description: 获取Sync协议逻辑处理器
|
|
// @receiver l
|
|
// @return communication.SyncLogicHandler
|
|
//
|
|
func (l *Lsdb) GetSync() *communication.SyncLogicHandler {
|
|
return l.sync
|
|
}
|
|
|
|
//
|
|
// FindLsa
|
|
// @Description: 根据LSA类型及所属路由器,获取LSA
|
|
// @receiver l*
|
|
// @param routerIdentifier
|
|
// @param lsaType
|
|
// @return lsa.ILsa
|
|
//
|
|
func (l *Lsdb) FindLsa(routerIdentifier *component.Identifier,
|
|
lsaType lsa.LsaType) lsa.ILsa {
|
|
lsaGet, err := l.GetLSAByNameAndType(routerIdentifier, lsaType)
|
|
if err != nil {
|
|
lsaGet = nil
|
|
}
|
|
return lsaGet
|
|
}
|
|
|
|
//
|
|
// isLsaNew
|
|
// @Description: 返回来自某个路由器的seq是否表示新的LSA。
|
|
// @receiver l
|
|
// @param routerIdentifier
|
|
// @param lsaType
|
|
// @param seqNo
|
|
// @return bool
|
|
//
|
|
func (l *Lsdb) isLsaNew(routerIdentifier *component.Identifier,
|
|
lsaType lsa.LsaType, seqNo uint64) bool {
|
|
iLsa := l.FindLsa(routerIdentifier, lsaType)
|
|
// 没找到,说明是最新的
|
|
if iLsa == nil {
|
|
return true
|
|
}
|
|
// 找到了,且LSDB中的该lsa序列号小于要查的lsa,说明是最新的
|
|
if iLsa.GetSeqNo() < seqNo {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
//
|
|
// IsLsaNew
|
|
// @Description: 返回来自某个路由器的seq是否表示新的LSA。
|
|
// @receiver l
|
|
// @param fLsa
|
|
// @return bool
|
|
//
|
|
func (l *Lsdb) IsLsaNew(fLsa lsa.ILsa) bool {
|
|
return l.isLsaNew(fLsa.GetOriginRouter(), fLsa.GetType(), fLsa.GetSeqNo())
|
|
}
|
|
|
|
//
|
|
// InstallLsa
|
|
// @Description: 将LSA安装到lsdb中
|
|
// @receiver l
|
|
// @param lsa
|
|
//
|
|
func (l *Lsdb) InstallLsa(lsa lsa.ILsa) {
|
|
timeToExpire := l.lsaRefreshTime
|
|
|
|
// 判断不是本机LSA时,调整超期时间
|
|
if lsa.GetOriginRouter().ToUri() != l.thisRouterPrefix.ToUri() {
|
|
// 如果该其他路由器发来的LSA还没超时,则将超时时间间隔设置为该LSA剩余存活时间
|
|
if l.uintToTime(lsa.GetExpirationTime()).After(time.Now()) {
|
|
timeToExpire = l.uintToTime(lsa.GetExpirationTime()).Sub(time.Now())
|
|
}
|
|
}
|
|
|
|
// 查看数据库中是否已有该LSA源路由器所发出的LSA
|
|
lsaInDb := l.FindLsa(lsa.GetOriginRouter(), lsa.GetType())
|
|
if lsaInDb == nil {
|
|
// 如果没有:
|
|
common2.LogDebug("Adding Lsa ", lsa.ToString())
|
|
// 1. 就插入该LSA
|
|
err := l.Emplace(lsa)
|
|
if err != nil {
|
|
common2.LogError("Add Lsa error", lsa.ToString())
|
|
return
|
|
}
|
|
// 2. 触发LSDB安装LSA的动作信号
|
|
// todo: onLsdbModified(lsa, LsdbUpdate::INSTALLED, {}, {});
|
|
// 3. 设置LSA超期时间事件
|
|
l.ScheduleLsaExpiration(lsa, timeToExpire)
|
|
} else if lsaInDb.GetSeqNo() < lsa.GetSeqNo() {
|
|
// 如果查到了,而且传入的这个LSA比数据库中的更新,我们将更新数据库
|
|
common2.LogDebug("Updating Lsa ", lsaInDb.ToString())
|
|
// 1. 就插入该LSA
|
|
err := l.Emplace(lsa)
|
|
if err != nil {
|
|
common2.LogError("Add Lsa error", lsa.ToString())
|
|
return
|
|
}
|
|
// 2. 触发LSDB更新LSA的动作信号
|
|
// todo: onLsdbModified(lsa, LsdbUpdate::UPDATED, namesToAdd, namesToRemove);
|
|
// 3. 设置LSA超期时间事件
|
|
l.ScheduleLsaExpiration(lsa, timeToExpire)
|
|
common2.LogDebug("Updated Lsa ", lsa.ToString())
|
|
}
|
|
}
|
|
|
|
//
|
|
// RemoveLsa
|
|
// @Description: 从LSDB中删除LSA
|
|
// @receiver l
|
|
// @param lsa
|
|
//
|
|
func (l *Lsdb) RemoveLsa(lsa lsa.ILsa) {
|
|
err := l.LsaContainer.EraseLsa(lsa)
|
|
if err != nil {
|
|
common2.LogError("")
|
|
return
|
|
}
|
|
common2.LogDebug("Removed LSA: ", lsa.ToString())
|
|
}
|
|
|
|
//
|
|
// RemoveLsaByNameAndType
|
|
// @Description: 删除lsa
|
|
// @receiver l
|
|
// @param routerIdentifier
|
|
// @param lsaType
|
|
//
|
|
func (l *Lsdb) RemoveLsaByNameAndType(routerIdentifier *component.Identifier,
|
|
lsaType lsa.LsaType) {
|
|
err := l.LsaContainer.EraseLsaByNameAndType(routerIdentifier, lsaType)
|
|
if err != nil {
|
|
common2.LogError("")
|
|
return
|
|
}
|
|
common2.LogDebug("Removed LSA: ", routerIdentifier.ToUri())
|
|
}
|
|
|
|
//
|
|
// BuildAdjLsa
|
|
// @Description: 构建一个邻接LSA
|
|
// 只有当路由器的所有邻居状态是已知的时,才可以构建它的邻接LSA。
|
|
// @receiver l
|
|
//
|
|
func (l *Lsdb) BuildAdjLsa() {
|
|
common2.LogDebug("buildAdjLsa called")
|
|
|
|
// 构建邻接lsa的任务启动,那么安排构建就变为false
|
|
l.isBuildAdjLsaScheduled = false
|
|
|
|
// 根据配置文件中邻接表的状态,执行不同的动作
|
|
if l.mlsrConfig.GetAdjacencys().IsAdjLsaBuildable(uint32(l.mlsrConfig.GetHelloRetries())) {
|
|
// 只有在有计划的情况下才执行adjLsa构建
|
|
adjBuildCountCache := l.adjBuildCount
|
|
if adjBuildCountCache > 0 {
|
|
// 只有有安排时,构建邻接lsa
|
|
if l.mlsrConfig.GetAdjacencys().GetNumOfActiveNeighbor() > 0 {
|
|
// 有激活状态的邻居,则安装邻接LSA
|
|
common2.LogDebug("Building and installing own Adj LSA")
|
|
l.BuildAndInstallOwnAdjLsa()
|
|
} else {
|
|
// 我们没有活跃的邻居,这意味着没有人可以穿过我们。
|
|
// 因此,请删除LSDB中的条目。这会阻止此路由器刷新LSA,最终导致其他路由器也将其删除。
|
|
common2.LogDebug("Removing own Adj LSA; no ACTIVE neighbors")
|
|
l.RemoveLsaByNameAndType(l.thisRouterPrefix, lsa.LsaADJACENCYType)
|
|
}
|
|
// 如果在构建adj LSA的过程中,FIB必须等待兴趣响应,
|
|
// 那么计划的adj LSA构建的数量可能会发生变化,因此我们不应该只将其设置为0。
|
|
l.adjBuildCount = l.adjBuildCount - adjBuildCountCache
|
|
}
|
|
} else {
|
|
// 我们仍在等待了解某个邻居的邻接状态,因此请安排稍后的构建(当有望完成时)
|
|
l.isBuildAdjLsaScheduled = true
|
|
scheTime := l.mlsrConfig.GetHelloTimeout() * time.Duration(l.mlsrConfig.GetHelloRetries())
|
|
job, err := l.scheduler.ScheduleTaskAfterDuration(scheTime, 1).Do(l.BuildAdjLsa)
|
|
job.LimitRunsTo(1)
|
|
l.scheduler.StartAsync()
|
|
if err != nil {
|
|
common2.LogError("Scheduling BuildAdjLsa error, ", err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// BuildAndInstallOwnAdjLsa
|
|
// @Description: 为当前路由器构建并安装一个邻接LSA
|
|
// @receiver l
|
|
//
|
|
func (l *Lsdb) BuildAndInstallOwnAdjLsa() {
|
|
// 根据配置文件,构造本机的名称LSA
|
|
adjLsa := new(lsa.AdjLsa)
|
|
adjLsa.SetOriginRouter(l.thisRouterPrefix)
|
|
adjLsa.SetSeqNo(l.sequencingManager.GetAdjLsaSeq() + 1) // 序列号
|
|
adjLsa.SetLsaExpirationTime(l.getLsaExpirationTimePoint()) // 超期时间
|
|
adjLsa.AdjLsaAdjacenctList.InsertAdjacenctList(l.mlsrConfig.GetAdjacencyList()) // 名称前缀列表
|
|
// 刷新序列号管理器中的名称LSA序列号
|
|
l.sequencingManager.IncreaseAdjLsaSeq()
|
|
|
|
// todo: 使用sync通知路由更新
|
|
// m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
|
|
|
|
// 安装lsa到LSDB
|
|
l.InstallLsa(adjLsa)
|
|
}
|
|
|
|
//
|
|
// ScheduleLsaExpiration
|
|
// @Description: 在调度器中安排一个刷新或过期事件
|
|
// @receiver l
|
|
//
|
|
func (l *Lsdb) ScheduleLsaExpiration(lsa lsa.ILsa, duration time.Duration) {
|
|
// 在指定间隔的几秒后触发刷新或过期事件
|
|
duration = duration + GRACE_PERIOD
|
|
// 安排LSA在指定时间间隔后进行删除
|
|
job, err := l.scheduler.ScheduleTaskAfterDuration(duration, 1).Do(l.ExpireOrRefreshLsa, lsa)
|
|
job.LimitRunsTo(1)
|
|
l.scheduler.StartAsync()
|
|
if err != nil {
|
|
common2.LogError("Scheduling Lsa Expiration error, ", err.Error())
|
|
}
|
|
}
|
|
|
|
//
|
|
// ExpireOrRefreshLsa
|
|
// @Description: LSA过期时间触发后,执行该函数
|
|
// @receiver l
|
|
// @param lsa
|
|
//
|
|
func (l *Lsdb) ExpireOrRefreshLsa(lsa lsa.ILsa) {
|
|
common2.LogDebug("ExpireOrRefreshLsa called for ", lsa.ToString())
|
|
|
|
lsaInDb := l.FindLsa(lsa.GetOriginRouter(), lsa.GetType())
|
|
if lsaInDb != nil {
|
|
common2.LogDebug("LSA Exists with seq no: ", lsaInDb.GetSeqNo())
|
|
// 只有DB中LSA序列号依然是传入调度器的LSA序列号时,才执行删除或更新动作。否则,该LSA已是新的,则不应修改它。
|
|
if lsaInDb.GetSeqNo() == lsa.GetSeqNo() {
|
|
if lsaInDb.GetOriginRouter().ToUri() == l.thisRouterPrefix.ToUri() {
|
|
// 如果是本机LSA,由于它不能被删除,因此我们只继续更新它
|
|
// 1. 更新
|
|
common2.LogDebug("Own lsa refreshing, ", lsaInDb.ToString())
|
|
lsaInDb.SetSeqNo(lsaInDb.GetSeqNo() + 1)
|
|
l.sequencingManager.SetLsaSeq(lsaInDb.GetSeqNo()+1, lsaInDb.GetType())
|
|
lsaInDb.SetExpirationTime(l.getLsaExpirationTimePoint())
|
|
err := l.Emplace(lsaInDb)
|
|
if err != nil {
|
|
common2.LogError("Own lsa refresh error, ", err.Error())
|
|
return
|
|
}
|
|
common2.LogDebug("Own lsa refreshed, ", lsaInDb.ToString())
|
|
// 2. 安排新的超期事件
|
|
l.ScheduleLsaExpiration(lsaInDb, l.lsaRefreshTime)
|
|
// 3. todo: 将lsa更新通知给sync
|
|
// m_sync.publishRoutingUpdate(lsaPtr->getType(), m_sequencingManager.getLsaSeq(lsaPtr->getType()));
|
|
} else {
|
|
// 如果是其他路由器的LSA,我们将删除它。
|
|
// 更新其他路由器的LSA是通过min-sync实现的,而不是超期触发。
|
|
common2.LogDebug("Other's LSA, so removing from LSDB, lsa is ", lsa.ToString())
|
|
l.RemoveLsa(lsaInDb)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// ExpressInterest
|
|
// @Description: 发送请求其它路由器LSA的兴趣包
|
|
// @receiver l
|
|
// @param interestName
|
|
// @param timeOut
|
|
// @param deadline
|
|
//
|
|
func (l *Lsdb) ExpressInterest(interestName *component.Identifier,
|
|
timeOut uint32, deadline *time.Time) {
|
|
}
|
|
|
|
//
|
|
// OnFetchLsaError
|
|
// @Description: 在发生所有错误的情况下,将尝试重新获取LSA,直到deadline到达。
|
|
// @receiver l
|
|
// @param errorCode
|
|
// @param msg
|
|
// @param interestName
|
|
// @param retransmitNo
|
|
// @param deadline
|
|
// @param lsaName
|
|
// @param seqNo
|
|
//
|
|
func (l *Lsdb) onFetchLsaError(errorCode uint32, msg string,
|
|
interestName *component.Identifier, retransmitNo uint32,
|
|
deadline *time.Time, lsaName *component.Identifier, seqNo uint64) {
|
|
}
|
|
|
|
//
|
|
// AfterFetchLsa
|
|
// @Description: 当SegmentFetcher返回一个有效LSA之后的成功回调
|
|
// 在NLSR的设计中,一个获取LSA的基础兴趣包格式为:
|
|
// /<network>/NLSR/LSA/<site>/%C1.Router/<router>/<lsa-type>/<seqNo>
|
|
// @receiver l
|
|
// @param buffer
|
|
// @param interestName
|
|
//
|
|
func (l *Lsdb) afterFetchLsa(buffer bytes.Buffer, interestName *component.Identifier) {
|
|
}
|
|
|
|
func (l *Lsdb) getLsaExpirationTimePoint() uint64 {
|
|
timeExpire := time.Now()
|
|
timeExpire = timeExpire.Add(l.mlsrConfig.GetRouterDeadInterval())
|
|
|
|
return uint64(timeExpire.UnixMilli())
|
|
}
|
|
|
|
func (l *Lsdb) uintToTime(uintTime uint64) time.Time {
|
|
return time.UnixMilli(int64(uintTime))
|
|
}
|