实现LSDB中功能点:LSA安装、安排LSA超期任务、LSA超期刷新或删除

This commit is contained in:
free will committed 2022-06-03 17:22:32 +08:00
1 parent 4846c362ea
commit 6a43efb6d5
3 files changed
+132 -6

No files matched your search

+4
View File
@@ -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兴趣包生存周期。当使用推式包时,此值无效【单位:毫秒】
+96 -6
View File
@@ -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))
}
+32
View File
@@ -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))
}