mirror of
https://gitee.com/willfree/mlsr.git
synced 2026-06-10 19:59:35 +08:00
236 lines
5.7 KiB
Go
236 lines
5.7 KiB
Go
// Package route
|
|
// @Author: Wang Feng
|
|
// @Description:
|
|
// @Version: 0.1.0
|
|
// @Date: 2022/5/9 16:53
|
|
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
|
//
|
|
|
|
package route
|
|
|
|
import (
|
|
"errors"
|
|
common2 "minlib/common"
|
|
"minlib/component"
|
|
"minlib/encoding"
|
|
"mlsr/common"
|
|
"mlsr/extensions"
|
|
"mlsr/lsa"
|
|
"mlsr/lsdb"
|
|
"mlsr/route/Calculator"
|
|
"time"
|
|
)
|
|
|
|
type RoutingTable struct {
|
|
// lsa存储库
|
|
lsdb *lsdb.Lsdb
|
|
// 配置参数
|
|
mlsrConfig *common.MlsrConfig
|
|
// 任务调度器
|
|
scheduler *lsdb.MlsrScheduler
|
|
|
|
// 路由条目列表
|
|
rTable []*RoutingTableEntry
|
|
// 路由计算间隔时间
|
|
m_routingCalcInterval time.Duration
|
|
// 路由表是否正在计算
|
|
m_isRoutingTableCalculating bool
|
|
// 是否已经安排了路由计算
|
|
m_isRouteCalculationScheduled bool
|
|
// 当前路由器的邻接LSA是否存在
|
|
m_ownAdjLsaExist bool
|
|
|
|
// 双曲坐标状态 => 暂时用不到
|
|
m_hyperbolicState uint32
|
|
}
|
|
|
|
func (t *RoutingTable) Init() {
|
|
// 初始化任务调度器
|
|
t.scheduler = new(lsdb.MlsrScheduler)
|
|
t.scheduler.Init()
|
|
}
|
|
|
|
//
|
|
// Calculate
|
|
// @Description: 计算网络中每个路由器的下一个跃点列表。
|
|
// @receiver t
|
|
//
|
|
func (t *RoutingTable) Calculate() {
|
|
if !t.m_isRoutingTableCalculating {
|
|
// 先将状态改为正在做路由计算
|
|
t.m_isRoutingTableCalculating = true
|
|
|
|
// 做邻接路由计算
|
|
t.calculateLsRoutingTable()
|
|
|
|
// 恢复计算状态
|
|
t.m_isRouteCalculationScheduled = false
|
|
t.m_isRoutingTableCalculating = false
|
|
} else {
|
|
// 安排指定时间之后执行一个路由计算
|
|
t.ScheduleRoutingTableCalculation()
|
|
}
|
|
}
|
|
|
|
//
|
|
// AddNextHop
|
|
// @Description: 向路由表条目添加下一个跃点。
|
|
// @receiver t
|
|
// @param destRouter 要修改其RTE的目标路由器。
|
|
// @param hop 要添加到RTE的下一个跃点。
|
|
//
|
|
func (t *RoutingTable) AddNextHop(destRouter *component.Identifier, hop *NextHop) {
|
|
|
|
}
|
|
|
|
func (t *RoutingTable) FindRoutingTableEntry(destRouter *component.Identifier) *RoutingTableEntry {
|
|
//todo
|
|
return nil
|
|
}
|
|
|
|
//
|
|
// ScheduleRoutingTableCalculation
|
|
// @Description: 仅当尚未计划计算事件时,才在事件计划程序中计划计算事件。
|
|
// @receiver t
|
|
//
|
|
func (t *RoutingTable) ScheduleRoutingTableCalculation() error {
|
|
if !t.m_isRouteCalculationScheduled {
|
|
common2.LogFatal("Scheduling routing table calculation in ", t.m_routingCalcInterval)
|
|
err := t.scheduler.ScheduleTaskAfterDuration(t.m_routingCalcInterval, t.Calculate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
t.m_isRouteCalculationScheduled = true
|
|
}
|
|
return nil
|
|
}
|
|
|
|
//
|
|
// calculateLsRoutingTable
|
|
// @Description: 计算链路状态路由表。
|
|
// @receiver t
|
|
//
|
|
func (t *RoutingTable) calculateLsRoutingTable() {
|
|
if t.lsdb.GetIsBuildAdjLsaScheduled() {
|
|
common2.LogFatal("Adjacency build is scheduled, routing table can not be calculated :(")
|
|
return
|
|
}
|
|
|
|
// 我们只在LS中检查这一点,因为我们从不移除自己的坐标LSA。而如果没有任何邻居,则移除自己的邻接LSA
|
|
if !t.m_ownAdjLsaExist {
|
|
return
|
|
}
|
|
|
|
t.clearRoutingTable()
|
|
|
|
// 构造路由映射表
|
|
lsas, err := t.lsdb.GetLSAsByType(lsa.LsaADJACENCYType)
|
|
if err != nil {
|
|
common2.LogFatal("Get Lsa in calculateLsRoutingTable error, ", err)
|
|
}
|
|
rMap := new(Calculator.RouterMap)
|
|
rMap.Init()
|
|
err = rMap.CreateFromAdjLsdb(lsas)
|
|
if err != nil {
|
|
common2.LogFatal("create RouterMap from lsdb error in calculateLsRoutingTable error, ", err)
|
|
}
|
|
|
|
nRouters := rMap.GetMapSize()
|
|
|
|
// 构造路由计算器
|
|
calculator := new(Calculator.LinkStateRoutingTableCalculator)
|
|
calculator.SetRouterNum(nRouters)
|
|
// 使用计算器去计算路由
|
|
err = calculator.CalculatePath(rMap, t, t.mlsrConfig, t.lsdb)
|
|
if err != nil {
|
|
common2.LogFatal("CalculatePath in calculateLsRoutingTable error, ", err)
|
|
}
|
|
|
|
// todo: 开始根据新计算的路由去更新NPT表
|
|
common2.LogInfo("Calling Update NPT With new Route")
|
|
//todo
|
|
}
|
|
|
|
//
|
|
// clearRoutingTable
|
|
// @Description: 清空路由表
|
|
// @receiver t
|
|
//
|
|
func (t *RoutingTable) clearRoutingTable() {
|
|
|
|
}
|
|
|
|
//
|
|
// WireEncode
|
|
// @Description: 线速编码
|
|
// @receiver l
|
|
// @param encoder
|
|
// @return int
|
|
// @return error
|
|
//
|
|
func (t *RoutingTable) WireEncode(encoder *encoding.Encoder) (int, error) {
|
|
// 判断列表长度,为0则抛出错误
|
|
if len(t.rTable) == 0 {
|
|
return 0, errors.New("Invalid RoutingTable, expect at least one RoutingTableEntry!")
|
|
}
|
|
totalLength := 0
|
|
// 编码 TLV-VALUE
|
|
// 反向遍历,可以保证解码的时候正向输出
|
|
for i := len(t.rTable) - 1; i >= 0; i-- {
|
|
if t.rTable[i] == nil {
|
|
continue
|
|
}
|
|
tmpLen, err := t.rTable[i].WireEncode(encoder)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
totalLength += tmpLen
|
|
}
|
|
|
|
// 编码 TLV-LENGTH
|
|
tmpLen, err := encoder.PrependVarNumber(encoding.VlInt(totalLength))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
totalLength += tmpLen
|
|
|
|
// 编码 TLV-TYPE
|
|
tmpLen, err = encoder.PrependVarNumber(extensions.TlvMlsrRoutingTable)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
totalLength += tmpLen
|
|
|
|
return totalLength, nil
|
|
}
|
|
|
|
//
|
|
// WireDecode
|
|
// @Description: 线速解码
|
|
// @receiver l
|
|
// @param block
|
|
// @return error
|
|
//
|
|
func (t *RoutingTable) WireDecode(block *encoding.Block) error {
|
|
// 检查 TLV-TYPE 是否正确
|
|
if err := encoding.ExpectType(block.GetType(), extensions.TlvMlsrRoutingTable); err != nil {
|
|
return err
|
|
}
|
|
|
|
// 解析子 TLV
|
|
if err := block.ParseSubElements(); err != nil {
|
|
return err
|
|
}
|
|
tableEntries := make([]*RoutingTableEntry, len(block.GetSubElements()))
|
|
for index, element := range block.GetSubElements() {
|
|
var tableEntry RoutingTableEntry
|
|
err := tableEntry.WireDecode(element)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tableEntries[index] = &tableEntry
|
|
}
|
|
t.rTable = tableEntries
|
|
return nil
|
|
}
|