diff --git a/common/MlsrConfig.go b/common/MlsrConfig.go index 3b08da7..e0591c8 100644 --- a/common/MlsrConfig.go +++ b/common/MlsrConfig.go @@ -125,6 +125,10 @@ type GeneralConfig struct { LsaRefreshTime uint32 `ini:"LsaRefreshTime"` // LSA刷新时间【单位:毫秒】 + // 路由器死亡后,本机NameLsa和AdjLsa将超期失效,从而被LSDB清除 + // 路由器死亡时间是本机LSA构建时的超期时间,但它在本机进行刷新时,是不按照死亡时间进行刷新的,而是按照LSA刷新时间做刷新的触发 + // 路由器死亡时间是给其他路由器的LSA超期时间,例如路由器B在死亡时间间隔后会将路由器A的LSA删除,但路由器A其实在LSA刷新时间就已经 + // 刷新该LSA,并通知给路由器B,因而保证了路由器B一直有路由器A的LSA。 RouterDeadInterval uint32 `ini:"RouterDeadInterval"` // 路由器判断死亡的时间间隔(必须大于LSA刷新时间)【单位:毫秒】 LsaInterestLifetime int `ini:"LsaInterestLifetime"` // LSA兴趣包生存周期。当使用推式包时,此值无效【单位:毫秒】 diff --git a/lsdb/Lsdb.go b/lsdb/Lsdb.go index 0d696ab..995799c 100644 --- a/lsdb/Lsdb.go +++ b/lsdb/Lsdb.go @@ -28,6 +28,8 @@ const ( REMOVED = -1 // 已移除 ) +const GRACE_PERIOD = 10 * time.Second // 超期宽限期。LSA比设定时间晚几秒钟被删除,以避免信息过早失效。 + type Lsdb struct { // 配置参数 mlsrConfig *common.MlsrConfig @@ -117,7 +119,7 @@ func (l *Lsdb) BuildAndInstallOwnNameLsa() { nlsa := new(lsa.NameLsa) nlsa.SetOriginRouter(l.thisRouterPrefix) // 源路由 nlsa.SetSeqNo(l.sequencingManager.GetNameLsaSeq() + 1) // 序列号 - nlsa.SetLsaExpirationTime(uint64(l.getLsaExpirationTimePoint().UnixMilli())) // 超期时间 + nlsa.SetLsaExpirationTime(l.getLsaExpirationTimePoint()) // 超期时间 nlsa.NameLsaNamePrefixList.InsertNamePrefixList(l.mlsrConfig.GetNamePrefixList()) // 名称前缀列表 // 刷新序列号管理器中的名称LSA序列号 l.sequencingManager.IncreaseNameLsaSeq() @@ -231,6 +233,46 @@ func (l *Lsdb) IsLsaNew(routerIdentifier *component.Identifier, } 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 lsa == 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()) + } } func (l *Lsdb) RemoveLsa(routerIdentifier *component.Identifier, @@ -262,11 +304,55 @@ func (l *Lsdb) BuildAndInstallOwnAdjLsa() { // @Description: 在调度器中安排一个刷新或过期事件 // @receiver l // -func (l *Lsdb) ScheduleLsaExpiration(lsa lsa.ILsa, duration *time.Duration) { - +func (l *Lsdb) ScheduleLsaExpiration(lsa lsa.ILsa, duration time.Duration) { + // 安排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.GetOriginRouter(), lsaInDb.GetType()) + } + } + } } func (l *Lsdb) ProcessInterestForLsa(interest *packet.Interest, @@ -306,9 +392,13 @@ func (l *Lsdb) OnFetchLsaError(errorCode uint32, msg string, func (l *Lsdb) AfterFetchLsa(buffer bytes.Buffer, interestName *component.Identifier) { } -func (l *Lsdb) getLsaExpirationTimePoint() time.Time { +func (l *Lsdb) getLsaExpirationTimePoint() uint64 { timeExpire := time.Now() - timeExpire.Add(l.mlsrConfig.GetRouterDeadInterval()) + timeExpire = timeExpire.Add(l.mlsrConfig.GetRouterDeadInterval()) - return timeExpire + return uint64(timeExpire.UnixMilli()) +} + +func (l *Lsdb) uintToTime(uintTime uint64) time.Time { + return time.UnixMilli(int64(uintTime)) } diff --git a/lsdb/Lsdb_test.go b/lsdb/Lsdb_test.go index 2a0d916..50186c9 100644 --- a/lsdb/Lsdb_test.go +++ b/lsdb/Lsdb_test.go @@ -17,6 +17,11 @@ import ( const testConfigPath = "D:\\" + common.DefaultConfFileName +// +// TestLsdb_Init +// @Description: 测试LSDB初始化 +// @param t +// func TestLsdb_Init(t *testing.T) { // 配置文件初始化 mlsrConfig, err := common.ParseConfig(testConfigPath) @@ -32,3 +37,30 @@ func TestLsdb_Init(t *testing.T) { lsdb := new(Lsdb) lsdb.Init(mlsrConfig, sche, face) } + +// +// TestUnixTime +// @Description: 测试时间与时间戳的转换。将用于LSA中过期时间的保存,非常重要。 +// @param t +// +func TestUnixTime(t *testing.T) { + // 配置文件初始化 + mlsrConfig, err := common.ParseConfig(testConfigPath) + if err != nil { + fmt.Println("配置文件解析错误") + } + // 调度器初始化 + sche := new(MlsrScheduler) + sche.Init() + // LogicFace初始化(假设初始化,暂时用不到) + face := new(logicface.LogicFace) + // LSDB初始化 + lsdb := new(Lsdb) + lsdb.Init(mlsrConfig, sche, face) + + // 获取过期时间的时间戳 + timeExpire := lsdb.getLsaExpirationTimePoint() + // 时间戳转回过期时间 + timeTemplate := "2006-01-02 15:04:05" // 时间戳常规类型 + fmt.Println(lsdb.uintToTime(timeExpire).Format(timeTemplate)) +}