mirror of
https://gitee.com/willfree/mlsr.git
synced 2026-06-09 19:09:35 +08:00
264 lines
6.6 KiB
Go
264 lines
6.6 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 {
|
||
// 安排指定时间之后执行一个路由计算
|
||
err := t.ScheduleRoutingTableCalculation()
|
||
if err != nil {
|
||
common2.LogFatal("Calculate error,Schedule RoutingTableCalculation error, ", err)
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// AddNextHop
|
||
// @Description: 向路由表条目添加下一个跃点。
|
||
// @receiver t
|
||
// @param destRouter 要修改其RTE的目标路由器。
|
||
// @param hop 要添加到RTE的下一个跃点。
|
||
//
|
||
func (t *RoutingTable) AddNextHop(destRouter *component.Identifier, hop *NextHop) {
|
||
common2.LogInfo("Adding " + hop.LogicFaceUri() + " for destination " + destRouter.ToUri())
|
||
|
||
// 查找路由表项
|
||
rte := t.FindRoutingTableEntry(destRouter)
|
||
// 如果没有这条表项,则构建并加入
|
||
if rte == nil {
|
||
rte = new(RoutingTableEntry)
|
||
rte.AddNextHop(hop)
|
||
t.rTable = append(t.rTable, rte)
|
||
} else {
|
||
// 如果有,则直接编辑该条目,增加一个下一跳.
|
||
// todo: 这块需要测试,是否在go中可以直接根据引用进行表项的修改
|
||
rte.AddNextHop(hop)
|
||
}
|
||
}
|
||
|
||
//
|
||
// FindRoutingTableEntry
|
||
// @Description: 根据某个目的路由器,查找对应的路由表项
|
||
// @receiver t
|
||
// @param destRouter
|
||
// @return *RoutingTableEntry
|
||
//
|
||
func (t *RoutingTable) FindRoutingTableEntry(destRouter *component.Identifier) *RoutingTableEntry {
|
||
uri := destRouter.ToUri()
|
||
for i := 0; i < len(t.rTable); i++ {
|
||
if t.rTable[i].GetDestination().ToUri() == uri {
|
||
return t.rTable[i]
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
//
|
||
// ScheduleRoutingTableCalculation
|
||
// @Description: 仅当尚未计划计算事件时,才在事件计划程序中计划计算事件。
|
||
// @receiver t
|
||
//
|
||
func (t *RoutingTable) ScheduleRoutingTableCalculation() error {
|
||
if !t.m_isRouteCalculationScheduled {
|
||
common2.LogInfo("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() {
|
||
t.rTable = []*RoutingTableEntry{}
|
||
}
|
||
|
||
//
|
||
// 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
|
||
}
|