1
0
mirror of https://gitee.com/willfree/mlsr.git synced 2026-06-10 19:59:35 +08:00
Files
mlsr/route/RoutingTable.go
T

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
}