Merge remote-tracking branch 'origin/master'

This commit is contained in:
pxy committed 2022-06-24 11:21:04 +08:00
commit 37900a8367
57 files changed
+7561 -496

No files matched your search

+43
View File
@@ -0,0 +1,43 @@
# MLSR
## 介绍
MLSR(MIN Link State Routing Protocol,多标识网络链路状态路由协议)是MIN(Mutil-Identifier Network,多标识网络)中的基本路由协议。
MLSR支持推式传输和拉式传输下的路由寻址。
## 功能模块简述
### LSA模块
### LSDB模块
### 路由表模块
### NPT模块
## 开发规范
### 注释规范
* 源代码文件抬头注明开发者、时间、版本、组织等信息,请参考较早提交的代码文件。
* 结构体及函数需注明其作用,请参考较早提交的代码文件。
### 代码规范
* 函数之间留有确定行数的空行。
* 复杂函数内部可根据逻辑关系,用空行分割为若干块,并加入注释予以解释。
## 开发环境及依赖
### 开发环境
| 环境项 | 信息 |
| :----: | :----: |
| Golang | go 1.18 |
| IDE推荐 | GoLand |
### 软件依赖
minlib
注:请将minlib放置在与mlsr同目录下,注意,不是mlsr目录之下,是平行关系。
## 联系我们
MIN-Group
国家重大科技基础设施——未来网络北大实验室
深圳市信息论与未来网络重点实验室
开发者邮箱:wefree@stu.pku.edu.cn
+186 -64
View File
@@ -11,6 +11,8 @@ package common
import (
"encoding/json"
"gopkg.in/ini.v1"
common2 "minlib/common"
"strconv"
)
const DefaultConfFileName = "mlsrConf.ini"
@@ -20,58 +22,154 @@ const DefaultConfFileName = "mlsrConf.ini"
// @Description: MLSR 配置文件的配置。与mlsrConf.ini一一对应
//
type MlsrConfig struct {
GeneralConfig `ini:"General"`
NeighborsConfig `ini:"Neighbors"`
HyperbolicConfig `ini:"Hyperbolic"`
FibConfig `ini:"Fib"`
AdvertisingConfig `ini:"Advertising"`
SecurityConfig `ini:"Security"`
GeneralConfig `ini:"General"`
LogConfig `ini:"Log"`
NeighborsConfig `ini:"Neighbors"`
HyperbolicConfig `ini:"Hyperbolic"`
FibConfig `ini:"Fib"`
AdvertisingConfig `ini:"Advertising"`
SecurityConfig `ini:"Security"`
mlsrConfigPath string // 配置文件所在路径
neighbors []NeighborConfig // NeighborsConfig中的信息
// 获取值的接口
MlsrConfigParameters
mlsrConfigPath string // 配置文件所在路径
neighbors []NeighborConfig // NeighborsConfig中的信息
}
//
// ToString
// @Description:
// @receiver c
//
func (c *MlsrConfig) ToString() string {
var str string
str += "----------------------- MlsrConfig -------------------------\n"
str += "Config File Path: " + c.mlsrConfigPath + "\n"
str += "----------------- 1. GeneralConfig -------------------------\n"
bytes, err := json.Marshal(c.GeneralConfig)
if err == nil {
str += string(bytes) + "\n"
}
str += "----------------- 2. LogConfig -----------------------------\n"
bytes, err = json.Marshal(c.LogConfig)
if err == nil {
str += string(bytes) + "\n"
}
str += "----------------- 3. NeighborsConfig -----------------------\n"
bytes, err = json.Marshal(c.NeighborsConfig)
if err == nil {
str += string(bytes) + "\n"
}
str += "----------------- 4. HyperbolicConfig ----------------------\n"
bytes, err = json.Marshal(c.HyperbolicConfig)
if err == nil {
str += string(bytes) + "\n"
}
str += "----------------- 5. FibConfig -----------------------------\n"
bytes, err = json.Marshal(c.FibConfig)
if err == nil {
str += string(bytes) + "\n"
}
str += "----------------- 6. AdvertisingConfig ---------------------\n"
bytes, err = json.Marshal(c.AdvertisingConfig)
if err == nil {
str += string(bytes) + "\n"
}
str += "----------------- 7. SecurityConfig ------------------------\n"
bytes, err = json.Marshal(c.SecurityConfig)
if err == nil {
str += string(bytes) + "\n"
}
str += "\n"
return str
}
func (c *MlsrConfig) ParametersToString() string {
var str string
str += "----------------------- MlsrConfigParameters -------------------------\n"
str += "----------------------- 1. 标识符 -------------------------------------\n"
str += "路由器定位符:" + c.MlsrConfigParameters.m_routerName.ToUri() + "\n"
str += "网域定位符:" + c.MlsrConfigParameters.m_siteName.ToUri() + "\n"
str += "网络定位符:" + c.MlsrConfigParameters.m_network.ToUri() + "\n"
str += "路由器前缀:" + c.MlsrConfigParameters.m_routerPrefix.ToUri() + "\n"
str += "同步用户前缀:" + c.MlsrConfigParameters.m_syncUserPrefix.ToUri() + "\n"
str += "同步前缀:" + c.MlsrConfigParameters.m_syncPrefix.ToUri() + "\n"
str += "LSA前缀:" + c.MlsrConfigParameters.m_lsaPrefix.ToUri() + "\n"
str += "----------------------- 2. 时间 ---------------------------------------\n"
str += "LSA刷新时间:" + strconv.Itoa(int(c.MlsrConfigParameters.m_lsaRefreshTime.Seconds())) + " " +
"秒 = " + strconv.Itoa(int(c.MlsrConfigParameters.m_lsaRefreshTime.Seconds())/60) + "分钟\n"
str += "LSA兴趣包生命周期:" + strconv.Itoa(int(c.MlsrConfigParameters.m_lsaInterestLifetime.Seconds())) + " 秒" + "\n"
str += "路由器死亡间隔:" + strconv.Itoa(int(c.MlsrConfigParameters.m_routerDeadInterval.Seconds())) + " " +
"秒 = " + strconv.Itoa(int(c.MlsrConfigParameters.m_routerDeadInterval.Seconds())/60) + "分钟\n"
str += "同步兴趣包生命周期:" + strconv.Itoa(int(c.MlsrConfigParameters.m_syncInterestLifetime.Seconds())) + " 秒" + "\n"
str += "hello超时时间:" + strconv.Itoa(int(c.MlsrConfigParameters.m_helloTimeout.Seconds())) + " 秒" + "\n"
str += "hello发送间隔:" + strconv.Itoa(int(c.MlsrConfigParameters.m_helloInterval.Seconds())) + " 秒" + "\n"
str += "邻接LSA构建间隔:" + strconv.Itoa(int(c.MlsrConfigParameters.m_adjLsaBuildInterval.Seconds())) + " 秒" + "\n"
str += "LogicFace数据集请求间隔:" + strconv.Itoa(int(c.MlsrConfigParameters.m_faceDatasetFetchInterval.Seconds())) + " " +
"秒 = " + strconv.Itoa(int(c.MlsrConfigParameters.m_faceDatasetFetchInterval.Seconds())/60) + "分钟\n"
str += "路由计算间隔:" + strconv.Itoa(int(c.MlsrConfigParameters.m_RoutingCalcInterval.Seconds())) + " 秒" + "\n"
str += "\n"
return str
}
//
// GeneralConfig
// @Description: 最基础配置信息:LSA、同步协议
// @Description: 一、最基础配置信息:LSA、同步协议
//
type GeneralConfig struct {
Network string `ini:"Network"` // 所属网络
Site string `ini:"Site"` // 所属站点
Router string `ini:"Router"` // 所属路由器
Network string `ini:"Network"` // 所属网络
Site string `ini:"Site"` // 所属站点
Router string `ini:"Router"` // 所属路由器
LsaRefreshTime uint32 `ini:"LsaRefreshTime"` // LSA刷新时间
LsaRefreshTime uint32 `ini:"LsaRefreshTime"` // LSA刷新时间【单位:毫秒】
RouterDeadInterval uint32 `ini:"RouterDeadInterval"` // 路由器判断死亡的时间间隔(必须大于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兴趣包生存周期。当使用推式包时,此值无效
LsaInterestLifetime int `ini:"LsaInterestLifetime"` // LSA兴趣包生存周期。当使用推式包时,此值无效【单位:毫秒】
SyncProtocol string `ini:"SyncProtocol"` // 同步协议
SyncInterestLifetime uint32 `ini:"SyncInterestLifetime"` // 同步协议兴趣包生命周期
SyncProtocol string `ini:"SyncProtocol"` // 同步协议
SyncInterestLifetime uint32 `ini:"SyncInterestLifetime"` // 同步协议兴趣包生命周期【单位:毫秒】
}
//
// LogConfig
// @Description: 二、日志模块
//
type LogConfig struct {
LogLevel string `ini:"LogLevel"` // 日志等级
ReportCaller bool `ini:"ReportCaller"` // 日志输出时是否添加文件名和函数名
LogFormat string `ini:"LogFormat"` // 输出日志的格式 "json" | "text"
LogFilePath string `ini:"LogFilePath"` // 日志输出文件路径,为空则输出至控制台
}
//
// NeighborsConfig
// @Description: 邻居路由器相关配置
// @Description: 三、邻居路由器相关配置
//
type NeighborsConfig struct {
HelloRetries int `ini:"HelloRetries"` // hello协议探测最大次数
HelloTimeout uint32 `ini:"HelloTimeout"` // hello协议中的超时时间
HelloInterval uint32 `ini:"HelloInterval"` // 两个hello包之间的间隔时间
HelloRetries int `ini:"HelloRetries"` // hello协议探测最大次数【单位:毫秒】
HelloTimeout uint32 `ini:"HelloTimeout"` // hello协议中的超时时间【单位:毫秒】
HelloInterval uint32 `ini:"HelloInterval"` // 两个hello包之间的间隔时间【单位:毫秒】
AdjLsaBuildInterval uint32 `ini:"AdjLsaBuildInterval"` // 邻接LSA构建的时间间隔
LogicFaceDatasetFetchRetries uint32 `ini:"LogicFaceDatasetFetchRetries"` // 获取FaceStatus数据集的重试次数
LogicFaceDatasetFetchInterval uint32 `ini:"LogicFaceDatasetFetchInterval"` // FaceStatus数据集获取尝试之间的间隔
NeighborsInfo NeighborsJsonString `ini:"NeighborsInfo"` // 邻居路由器链路信息
AdjLsaBuildInterval uint32 `ini:"AdjLsaBuildInterval"` // 邻接LSA构建的时间间隔【单位:毫秒】
LogicFaceDatasetFetchRetries uint32 `ini:"LogicFaceDatasetFetchRetries"` // 获取FaceStatus数据集的重试次数
LogicFaceDatasetFetchInterval uint32 `ini:"LogicFaceDatasetFetchInterval"` // FaceStatus数据集获取尝试之间的间隔【单位:毫秒】
NeighborsInfo NeighborsJsonString `ini:"NeighborsInfo"` // 邻居路由器链路信息
}
type NeighborsJsonString string
type NeighborConfig struct {
NeighborName string `ini:"NeighborName"` // 邻居路由器的名称前缀
LogicFaceUri string `ini:"LogicFaceUri"` // 连接该邻居路由器的LogicFace的URI
LinkCost uint64 `ini:"LinkCost"` // 链路开销(用uint64还是double待决)
NeighborName string `ini:"NeighborName"` // 邻居路由器的名称前缀
LogicFaceUri string `ini:"LogicFaceUri"` // 连接该邻居路由器的LogicFace的URI
LinkCost uint64 `ini:"LinkCost"` // 链路开销(用uint64还是double待决)
}
//
@@ -81,10 +179,10 @@ type NeighborConfig struct {
// @return NeighborsJsonString
// @return error
//
func parseNeighborConfigToJsonString(neighbors []NeighborConfig) (NeighborsJsonString,error) {
bytes,err := json.Marshal(neighbors)
if err!= nil{
return "",err
func parseNeighborConfigToJsonString(neighbors []NeighborConfig) (NeighborsJsonString, error) {
bytes, err := json.Marshal(neighbors)
if err != nil {
return "", err
}
return NeighborsJsonString(bytes), nil
}
@@ -97,35 +195,43 @@ func parseNeighborConfigToJsonString(neighbors []NeighborConfig) (NeighborsJsonS
// @return []NeighborConfig
// @return error
//
func parseJsonStringToNeighbors(jsonString NeighborsJsonString) ([]NeighborConfig,error) {
func parseJsonStringToNeighbors(jsonString NeighborsJsonString) ([]NeighborConfig, error) {
var neighbors []NeighborConfig
err := json.Unmarshal([]byte(jsonString), &neighbors)
if err!= nil{
return nil,err
if err != nil {
return nil, err
}
return neighbors, nil
}
//
// HyperbolicConfig
// @Description: 预留双曲坐标的接口
// @Description: 四、预留双曲坐标的配置
//
type HyperbolicConfig struct {
}
//
// FibConfig
// @Description: 路由计算相关配置
// @Description: 五、路由计算与FIB更新相关配置
//
type FibConfig struct {
MaxLogicFacesPerPrefix int `ini:"MaxLogicFacesPerPrefix"` // 每个前缀对应的下一跳face列表的最大数目
RoutingCalcInterval uint32 `ini:"RoutingCalcInterval"` // 两次路由计算的时间间隔
MaxLogicFacesPerPrefix int `ini:"MaxLogicFacesPerPrefix"` // 每个前缀对应的下一跳face列表的最大数目
RoutingCalcInterval uint32 `ini:"RoutingCalcInterval"` // 两次路由计算的时间间隔【单位:毫秒】
}
//
// AdvertisingConfig
// @Description: 六、需要通告给其它路由器的前缀
//
type AdvertisingConfig struct {
Prefixs []string `ini:"Prefixs"` // 需要广告给其他路由器的本机前缀
Prefixs []string `ini:"Prefixs"` // 需要广告给其他路由器的本机前缀
}
//
// SecurityConfig
// @Description: 七、预留安全相关的配置
//
type SecurityConfig struct {
}
@@ -134,24 +240,32 @@ type SecurityConfig struct {
// @Description: 初始化配置,给所有的配置设置默认值
// @receiver c
//
func (c *MlsrConfig) Init() {
// 通用配置参数
func (c *MlsrConfig) Init() {
// 1. 通用配置参数
c.GeneralConfig.Network = "/min"
c.GeneralConfig.Site = "/pkusz"
c.GeneralConfig.Router = "/routerA"
c.GeneralConfig.LsaRefreshTime = 1800 // 240-7200
c.GeneralConfig.RouterDeadInterval = 2*c.GeneralConfig.LsaRefreshTime
c.GeneralConfig.LsaInterestLifetime = 4 // 4-60
c.GeneralConfig.LsaRefreshTime = 30 * 60 * 1000 // 60*4-60*120,范围是4分钟-2小时。默认半小时
c.GeneralConfig.RouterDeadInterval = 2 * c.GeneralConfig.LsaRefreshTime // 默认一小时
c.GeneralConfig.LsaInterestLifetime = 4 * 1000 // 4-60,范围是4秒钟到1分钟。默认4秒钟
c.GeneralConfig.SyncProtocol = "min-sync"
c.GeneralConfig.SyncInterestLifetime = 60000 // 1000-120000
c.GeneralConfig.SyncInterestLifetime = 60 * 1000 // 1000-120*1000,范围是1秒到2分钟。默认1分钟
// 邻居路由器配置参数
c.NeighborsConfig.HelloRetries = 3 // 1-15
c.NeighborsConfig.HelloTimeout = 1 // 1-15
c.NeighborsConfig.HelloInterval = 60 // 30-90
c.NeighborsConfig.AdjLsaBuildInterval = 10 // 5-30
c.NeighborsConfig.LogicFaceDatasetFetchRetries = 3 // 1-10
c.NeighborsConfig.LogicFaceDatasetFetchInterval = 3600 // 1800-5400
// 2. Log
c.LogConfig.LogLevel = "ALL"
c.LogConfig.ReportCaller = true
c.LogConfig.LogFormat = "text"
c.LogConfig.LogFilePath = ""
// 3. 邻居路由器配置参数
c.NeighborsConfig.HelloRetries = 3 // 1-15,次数
c.NeighborsConfig.HelloTimeout = 1 * 1000 // 1-15,超时时间,范围1秒-15秒。默认1秒钟
c.NeighborsConfig.HelloInterval = 60 * 1000 // 30-90,间隔时间,范围30秒到1分钟。默认1分钟
c.NeighborsConfig.AdjLsaBuildInterval = 10 * 1000 // 5-30,构建间隔,范围5秒到30秒。默认10秒钟
c.NeighborsConfig.LogicFaceDatasetFetchRetries = 3 // 1-10,次数
c.NeighborsConfig.LogicFaceDatasetFetchInterval = 60 * 60 * 1000 // 30*60-90*60,半小时到一个半小时。默认1小时
// 邻接链路信息
c.neighbors = []NeighborConfig{}
// 将邻居链路信息存储到配置文件中 todo:用于测试
neighborConfig1 := NeighborConfig{
NeighborName: "/routerB",
@@ -166,14 +280,16 @@ func (c *MlsrConfig) Init() {
//neighborsJsonString, _ := parseNeighborConfigToJsonString(
// []NeighborConfig{neighborConfig1,neighborConfig2})
//c.NeighborsConfig.NeighborsInfo=neighborsJsonString
c.neighbors=[]NeighborConfig{neighborConfig1,neighborConfig2}
c.neighbors = append(c.neighbors, neighborConfig1)
c.neighbors = append(c.neighbors, neighborConfig2)
// 路由计算配置参数
c.FibConfig.MaxLogicFacesPerPrefix = 0 // 0-60 todo:为啥默认是0呢
c.FibConfig.RoutingCalcInterval = 15 // 0-15
// 5. FIB更新配置参数
c.FibConfig.MaxLogicFacesPerPrefix = 0 // 0-60,个数,最多有多少个下一跳。置0表示保留所有计算出的下一跳
c.FibConfig.RoutingCalcInterval = 15 * 1000 // 0-15,路由计算间隔。默认15秒计算一次
// 广播本地前缀配置参数
c.AdvertisingConfig.Prefixs=[]string{"/videos","/files","voices"} // todo:用于测试
// 6. 广播本地前缀配置参数
// c.AdvertisingConfig.Prefixs = []string{} // 非测试状态
c.AdvertisingConfig.Prefixs = []string{"/videos", "/files", "/voices"} // todo:用于测试
}
//
@@ -184,10 +300,10 @@ func (c *MlsrConfig) Init() {
//
func (c *MlsrConfig) Save() error {
cfg := ini.Empty()
if len(c.neighbors)>0 {
if len(c.neighbors) > 0 {
c.NeighborsInfo, _ = parseNeighborConfigToJsonString(c.neighbors)
}
if err:= ini.ReflectFrom(cfg,c); err!= nil{
if err := ini.ReflectFrom(cfg, c); err != nil {
return err
}
return cfg.SaveTo(c.mlsrConfigPath)
@@ -204,18 +320,24 @@ func (c *MlsrConfig) Save() error {
func ParseConfig(configPath string) (*MlsrConfig, error) {
cfg, err := ini.Load(configPath)
if err != nil {
common2.LogFatal("ParseConfig error, load error, path is ", configPath, err.Error())
return nil, err
}
mlsrConfig := new(MlsrConfig)
mlsrConfig.mlsrConfigPath = configPath
// 初始化配置,给所有的配置项设置默认值
mlsrConfig.Init()
// 加载配置文件中的配置
// 加载配置文件中的配置:如果有,则理应覆盖Init中设置的默认配置
if err = cfg.MapTo(&mlsrConfig); err != nil {
common2.LogFatal("ParseConfig error, mapTo error, path is ", configPath, err.Error())
return nil, err
}
if mlsrConfig.NeighborsInfo!="" {
if mlsrConfig.NeighborsInfo != "" {
mlsrConfig.neighbors, _ = parseJsonStringToNeighbors(mlsrConfig.NeighborsInfo)
}
// 将配置中的参数进行初始化,以支持直接获取结构体形式的参数
mlsrConfig.MlsrConfigParameters.Init(mlsrConfig)
// 按照配置文件中的参数,对日志模块进行初始化。不做这一步,则日志模块的配置失效
InitLogger(mlsrConfig)
return mlsrConfig, nil
}
+460
View File
@@ -0,0 +1,460 @@
// Package common
// @Author: Wang Feng
// @Description: MlsrConfig的辅助类。MlsrConf中主要实现读写配置文件的操作,
// 本类则负责将配置参数转化为实际的结构体。
// @Version: 0.1.0
// @Date: 2022/5/12 15:29
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package common
import (
common2 "minlib/common"
"minlib/component"
"mlsr/lsa"
"strconv"
"time"
)
// 同步协议版本号
const SYNC_VERSION = 1
type MlsrConfigParameters struct {
// 元数据从配置文件中来
mlsrconf *MlsrConfig
// 名称前缀/名称标识
m_routerName *component.Identifier
m_siteName *component.Identifier
m_network *component.Identifier
m_routerPrefix *component.Identifier
m_syncUserPrefix *component.Identifier
m_syncPrefix *component.Identifier
m_lsaPrefix *component.Identifier
// 时间:通用配置
m_lsaRefreshTime time.Duration
m_lsaInterestLifetime time.Duration
m_routerDeadInterval time.Duration // 路由器死亡时间(经过了该时间,NameLsa将触发超时)
m_syncInterestLifetime time.Duration
// 时间:邻居路由器
m_helloTimeout time.Duration
m_helloInterval time.Duration
m_adjLsaBuildInterval time.Duration
m_faceDatasetFetchInterval time.Duration
// 时间:FIB更新
m_RoutingCalcInterval time.Duration
// 邻接信息列表
m_adjl *lsa.AdjLsaAdjacenctList
// 命名前缀列表
m_npl *lsa.NameLsaNamePrefixList
}
// MlsrConfig初始化
func (mcp *MlsrConfigParameters) Init(config *MlsrConfig) {
mcp.setMetaData(config)
// 依次构建各个名称前缀/名称标识
_ = mcp.build3Prefix()
_ = mcp.buildSyncAndLsaPrefix()
_ = mcp.buildRouterAndSyncUserPrefix()
// 构建时间间隔
mcp.genDurations()
// 构建邻接表和名称前缀表
mcp.InitAdjacencyList()
mcp.InitNamePrefixList()
}
//
// setMetaData
// @Description: 设置mlsrconfig
// @receiver mcp
// @param config
//
func (mcp *MlsrConfigParameters) setMetaData(config *MlsrConfig) {
mcp.mlsrconf = config
}
//
// genDurations
// @Description: 生成时间相关配置信息
// @receiver mcp
//
func (mcp *MlsrConfigParameters) genDurations() {
mcp.m_lsaRefreshTime =
time.Duration(mcp.mlsrconf.LsaRefreshTime) * time.Millisecond
mcp.m_lsaInterestLifetime =
time.Duration(mcp.mlsrconf.LsaInterestLifetime) * time.Millisecond
mcp.m_routerDeadInterval =
time.Duration(mcp.mlsrconf.RouterDeadInterval) * time.Millisecond
mcp.m_syncInterestLifetime =
time.Duration(mcp.mlsrconf.SyncInterestLifetime) * time.Millisecond
mcp.m_helloTimeout =
time.Duration(mcp.mlsrconf.HelloTimeout) * time.Millisecond
mcp.m_helloInterval =
time.Duration(mcp.mlsrconf.HelloInterval) * time.Millisecond
mcp.m_adjLsaBuildInterval =
time.Duration(mcp.mlsrconf.AdjLsaBuildInterval) * time.Millisecond
mcp.m_faceDatasetFetchInterval =
time.Duration(mcp.mlsrconf.LogicFaceDatasetFetchInterval) * time.Millisecond
mcp.m_RoutingCalcInterval =
time.Duration(mcp.mlsrconf.RoutingCalcInterval) * time.Millisecond
}
//
// build3Prefix
// @Description: 构建了三个必要的名称组件,网络、网域/网站、路由器
// @receiver mcp
// @return error
//
func (mcp *MlsrConfigParameters) build3Prefix() error {
var err error
mcp.m_network, err = component.CreateIdentifierByString(mcp.mlsrconf.Network)
if err != nil {
return err
}
mcp.m_siteName, err = component.CreateIdentifierByString(mcp.mlsrconf.Site)
if err != nil {
return err
}
mcp.m_routerName, err = component.CreateIdentifierByString(mcp.mlsrconf.Router)
if err != nil {
return err
}
return nil
}
func (mcp *MlsrConfigParameters) buildSyncAndLsaPrefix() error {
// 同步前缀 = "/localhop" + 网络字段 + "/mlsr/sync" + SYNC版本号
syncPrefix := "/localhop" + mcp.mlsrconf.Network + "/mlsr/sync" + "/" + strconv.Itoa(SYNC_VERSION)
var err error
mcp.m_syncPrefix, err = component.CreateIdentifierByString(syncPrefix)
if err != nil {
return err
}
// Lsa前缀 = "/localhop" + 网络字段 + "/sync/LSA"
lsaPrefix := "/localhop" + mcp.mlsrconf.Network + "/sync/LSA"
mcp.m_lsaPrefix, err = component.CreateIdentifierByString(lsaPrefix)
if err != nil {
return err
}
return nil
}
func (mcp *MlsrConfigParameters) buildRouterAndSyncUserPrefix() error {
// 路由器前缀 = 网络字段 + 网域字段 + 路由器字段
prefix := mcp.mlsrconf.Network + mcp.mlsrconf.Site + mcp.mlsrconf.Router
var err error
mcp.m_routerPrefix, err = component.CreateIdentifierByString(prefix)
if err != nil {
return err
}
// 同步用户前缀 = Lsa前缀 + 网域字段 + 路由器字段
syncUserPrefix := mcp.m_lsaPrefix.ToUri() + mcp.mlsrconf.Site + mcp.mlsrconf.Router
mcp.m_syncUserPrefix, err = component.CreateIdentifierByString(syncUserPrefix)
if err != nil {
return err
}
return nil
}
//
// GetNetwork
// @Description: 网络定位符
// @receiver mcp
// @return *component.Identifier
//
func (mcp *MlsrConfigParameters) GetNetwork() *component.Identifier {
return mcp.m_network
}
//
// GetSiteName
// @Description:网域定位符
// @receiver mcp
// @return *component.Identifier
//
func (mcp *MlsrConfigParameters) GetSiteName() *component.Identifier {
return mcp.m_siteName
}
//
// GetRouterName
// @Description: 路由器定位符
// @receiver mcp
// @return *component.Identifier
//
func (mcp *MlsrConfigParameters) GetRouterName() *component.Identifier {
return mcp.m_routerName
}
//
// GetRouterPrefix
// @Description: 路由器前缀
// @receiver mcp
// @return *component.Identifier
//
func (mcp *MlsrConfigParameters) GetRouterPrefix() *component.Identifier {
return mcp.m_routerPrefix
}
//
// GetSyncUserPrefix
// @Description: 同步用户前缀
// @receiver mcp
// @return *component.Identifier
//
func (mcp *MlsrConfigParameters) GetSyncUserPrefix() *component.Identifier {
return mcp.m_syncUserPrefix
}
//
// GetSyncPrefix
// @Description: 同步前缀
// @receiver mcp
// @return *component.Identifier
//
func (mcp *MlsrConfigParameters) GetSyncPrefix() *component.Identifier {
return mcp.m_syncPrefix
}
//
// GetLsaPrefix
// @Description: LSA前缀
// @receiver mcp
// @return *component.Identifier
//
func (mcp *MlsrConfigParameters) GetLsaPrefix() *component.Identifier {
return mcp.m_lsaPrefix
}
func (mcp *MlsrConfigParameters) GetSyncProtocol() {
// todo
}
//
// GetLsaRefreshTime
// @Description: LSA刷新时间
// @receiver mcp
// @return time.Duration
//
func (mcp *MlsrConfigParameters) GetLsaRefreshTime() time.Duration {
return mcp.m_lsaRefreshTime
}
//
// GetLsaInterestLifetime
// @Description: LSA兴趣包生命周期
// @receiver mcp
// @return time.Duration
//
func (mcp *MlsrConfigParameters) GetLsaInterestLifetime() time.Duration {
return mcp.m_lsaInterestLifetime
}
//
// GetRouterDeadInterval
// @Description: 路由器死亡间隔
// @receiver mcp
// @return time.Duration
//
func (mcp *MlsrConfigParameters) GetRouterDeadInterval() time.Duration {
return mcp.m_routerDeadInterval
}
//
// GetSyncInterestLifetime
// @Description: 同步兴趣包生命周期
// @receiver mcp
// @return time.Duration
//
func (mcp *MlsrConfigParameters) GetSyncInterestLifetime() time.Duration {
return mcp.m_syncInterestLifetime
}
//
// GetAdjLsaBuildInterval
// @Description: 邻接LSA构建间隔
// @receiver mcp
// @return time.Duration
//
func (mcp *MlsrConfigParameters) GetAdjLsaBuildInterval() time.Duration {
return mcp.m_adjLsaBuildInterval
}
//
// GetFaceDatasetFetchInterval
// @Description: LogicFace数据集请求间隔
// @receiver mcp
// @return time.Duration
//
func (mcp *MlsrConfigParameters) GetFaceDatasetFetchInterval() time.Duration {
return mcp.m_faceDatasetFetchInterval
}
//
// GetRoutingCalcInterval
// @Description: 路由计算间隔
// @receiver mcp
// @return time.Duration
//
func (mcp *MlsrConfigParameters) GetRoutingCalcInterval() time.Duration {
return mcp.m_RoutingCalcInterval
}
//
// GetFaceDatasetFetchTries
// @Description: LogicFace数据集请求次数
// @receiver mcp
// @return int
//
func (mcp *MlsrConfigParameters) GetFaceDatasetFetchTries() uint32 {
return mcp.mlsrconf.LogicFaceDatasetFetchRetries
}
//
// GetHelloRetries
// @Description: hello兴趣包重传次数
// @receiver mcp
// @return int
//
func (mcp MlsrConfigParameters) GetHelloRetries() int {
return mcp.mlsrconf.HelloRetries
}
//
// GetHelloTimeout
// @Description: Hello超时时间
// @receiver mcp
// @return time.Duration
//
func (mcp *MlsrConfigParameters) GetHelloTimeout() time.Duration {
return mcp.m_helloTimeout
}
//
// GetHelloInterval
// @Description: Hello重传间隔
// @receiver mcp
// @return time.Duration
//
func (mcp *MlsrConfigParameters) GetHelloInterval() time.Duration {
return mcp.m_helloInterval
}
func (mcp *MlsrConfigParameters) GetInterestRetryNumber() {
// todo
}
func (mcp *MlsrConfigParameters) GetInterestResendTime() {
// todo
}
func (mcp *MlsrConfigParameters) GetInfoInterestInterval() {
// todo
}
func (mcp *MlsrConfigParameters) GetMaxFacesPerPrefix() int {
return mcp.mlsrconf.MaxLogicFacesPerPrefix
}
//
// InitAdjacencyList
// @Description: 从配置文件中初始化邻接信息列表
// @receiver mcp
//
func (mcp *MlsrConfigParameters) InitAdjacencyList() {
mcp.m_adjl = new(lsa.AdjLsaAdjacenctList)
neighborConfigs := mcp.mlsrconf.neighbors
for i := 0; i < len(neighborConfigs); i++ {
// 根据配置文件构造每条邻接链路信息
// 链路开销、URI及定位符均按照配置进行构造,
// FaceId缺省为0,兴趣包超时次数缺省为0,状态缺省为未激活
linkCost := lsa.AdjLsaLinkCost{}
linkCost.SetLinkCost(neighborConfigs[i].LinkCost)
faceUri := lsa.AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri(neighborConfigs[i].LogicFaceUri)
iden, err := component.CreateIdentifierByString(neighborConfigs[i].NeighborName)
if err != nil {
common2.LogError("MlsrCOnfig GetAdjacencyList error, beacuse ", err.Error())
continue
}
faceId := lsa.AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(0)
adjInfo := lsa.NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 0, lsa.STATUS_INACTIVE)
// 加入信息列表
mcp.m_adjl.Insert(adjInfo)
}
}
func (mcp *MlsrConfigParameters) InitNamePrefixList() {
mcp.m_npl = new(lsa.NameLsaNamePrefixList)
// 从配置文件读取广播前缀
adverPrefixs := mcp.mlsrconf.AdvertisingConfig.Prefixs
for i := 0; i < len(adverPrefixs); i++ {
// 为每个广播前缀构建一条名称前缀信息,其source为缺省的""
namePrefixInfo := new(lsa.NameLsaNamePrefixInfo)
iden, err := component.CreateIdentifierByString(adverPrefixs[i])
if err != nil {
common2.LogError("MlsrCOnfig GetNamePrefixList error, beacuse ", err.Error())
continue
}
namePrefixInfo.NamePrefix = iden
namePrefixInfo.InsertSource("")
// 将该名称前缀信息加入列表
mcp.m_npl.InsertNamePrefixInfo(namePrefixInfo)
}
}
//
// GetAdjacencyList
// @Description: 从配置文件中获取邻接信息列表
// @receiver mcp
// @return []*lsa.AdjLsaAdjacencyInfo
//
func (mcp *MlsrConfigParameters) GetAdjacencyList() []*lsa.AdjLsaAdjacencyInfo {
return mcp.m_adjl.GetAdjList()
}
//
// GetAdjacencys
// @Description: 获取整体的邻接信息
// @receiver mcp
// @return *lsa.AdjLsaAdjacenctList
//
func (mcp *MlsrConfigParameters) GetAdjacencys() *lsa.AdjLsaAdjacenctList {
return mcp.m_adjl
}
//
// GetNamePrefixList
// @Description: 从配置文件中获取名称前缀信息列表
// @receiver mcp
// @return []*lsa.NameLsaNamePrefixInfo
//
func (mcp *MlsrConfigParameters) GetNamePrefixList() []*lsa.NameLsaNamePrefixInfo {
return mcp.m_npl.GetNamePrefixList()
}
//
// GetNamePrefixs
// @Description: 获取整体的名称前缀信息
// @receiver mcp
// @return *lsa.NameLsaNamePrefixList
//
func (mcp *MlsrConfigParameters) GetNamePrefixs() *lsa.NameLsaNamePrefixList {
return mcp.m_npl
}
func (mcp *MlsrConfigParameters) GetKeyChain() {
// todo
}
+57 -5
View File
@@ -25,6 +25,55 @@ func getCurrentDirectory() string {
return dir
}
const testConfigPath = "D:\\" + DefaultConfFileName
//
// TestCreatConfigFile
// @Description: 测试生成mlsrConfig文件
// @param t
//
func TestCreatConfigFile(t *testing.T) {
testPath := "D:"
testPath += "\\"
testPath += DefaultConfFileName
mlsrConfig := new(MlsrConfig)
mlsrConfig.mlsrConfigPath = testPath
mlsrConfig.Init()
mlsrConfig.MlsrConfigParameters.Init(mlsrConfig)
_ = mlsrConfig.Save()
}
//
// TestMlsrConfigParameters
// @Description: 测试配置项所有参数
// @param t
//
func TestMlsrConfigParameters(t *testing.T) {
// 1、从指定目录解析配置文件
mlsrConfig, err := ParseConfig(testConfigPath)
if err != nil {
fmt.Println("配置文件解析错误")
}
// 2、打印配置中的普通字符串信息
fmt.Println(mlsrConfig.ToString())
// 3、打印配置中的特殊参数信息
fmt.Println(mlsrConfig.ParametersToString())
fmt.Println("!!!", mlsrConfig.MlsrConfigParameters.GetSyncUserPrefix().ToUri()+"00000")
fmt.Println("end")
// 打印邻接列表
adjs := mlsrConfig.GetAdjacencyList()
for i := 0; i < len(adjs); i++ {
fmt.Println(adjs[i].ToString())
}
fmt.Println("#########################################################")
// 打印名称前缀表
prefixs := mlsrConfig.GetNamePrefixList()
for i := 0; i < len(prefixs); i++ {
fmt.Println(prefixs[i].ToString())
}
}
//
// TestMlsrConfig_ParseConfigAndSave
// @Description: 测试配置文件解析和存储
@@ -34,15 +83,18 @@ func TestMlsrConfig_ParseConfigAndSave(t *testing.T) {
testPath := "D:"
testPath += "\\"
testPath += DefaultConfFileName
fmt.Println("test mlsr conf path: "+testPath)
mlsrConfig,_ := ParseConfig(testPath)
fmt.Println("test mlsr conf path: " + testPath)
mlsrConfig, err := ParseConfig(testPath)
if err != nil {
fmt.Println("配置文件加载错误")
}
// 存储
fmt.Println(mlsrConfig)
_ = mlsrConfig.Save()
// 取出
mlsrConfig2,_ := ParseConfig(testPath)
mlsrConfig2, _ := ParseConfig(testPath)
fmt.Println(mlsrConfig2)
// 解析neighbors
@@ -50,11 +102,11 @@ func TestMlsrConfig_ParseConfigAndSave(t *testing.T) {
fmt.Println(neighbors)
// 修改再存
ss:=NeighborConfig{
ss := NeighborConfig{
NeighborName: "nei",
LogicFaceUri: "uri",
LinkCost: 0,
}
mlsrConfig2.neighbors = append(mlsrConfig2.neighbors,ss)
mlsrConfig2.neighbors = append(mlsrConfig2.neighbors, ss)
_ = mlsrConfig2.Save()
}
+25
View File
@@ -0,0 +1,25 @@
// Package common
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/16 17:03
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package common
import "minlib/common"
// InitLogger 日志模块初始化
//
// @Description:
// @param config 配置文件
//
func InitLogger(config *MlsrConfig) {
common.InitLogger(&common.LoggerParameters{
ReportCaller: config.LogConfig.ReportCaller,
LogLevel: config.LogConfig.LogLevel,
LogFormat: config.LogConfig.LogFormat,
LogFilePath: config.LogConfig.LogFilePath,
})
}
+22 -15
View File
@@ -12,25 +12,32 @@ package extensions
const (
// Lsa for MLSR
TlvMlsrLsaAdjacency = 401 // 表示MIR之间邻接关系信息的LSA
TlvMlsrLsaNamePrefix = 402 // 表示名称前缀(内容标识、身份标识等以前缀形式命名的标识)信息的LSA
TlvMlsrLsaCoordinate = 403 // 表示坐标信息的LSA
TlvMlsrLsaAdjacency = 401 // 表示MIR之间邻接关系信息的LSA
TlvMlsrLsaName = 402 // 表示名称前缀(内容标识、身份标识等以前缀形式命名的标识)信息的LSA
TlvMlsrLsaCoordinate = 403 // 表示坐标信息的LSA
// 所有类型Lsa的必需部分
TlvMlsrLsaBase = 410 // 表示LSA最基本信息:源MIR、序列号、过期时间
TlvMlsrLsaExpirationTime = 420 // LSA过期时间
TlvMlsrLsaSequenceNumber = 421 // LSA序列号
TlvMlsrLsaBase = 410 // 表示LSA最基本信息:源MIR、序列号、过期时间
TlvMlsrLsaExpirationTime = 420 // LSA过期时间
TlvMlsrLsaSequenceNumber = 421 // LSA序列号
// AdjLsa的组件
TlvMlsrAdjLsaLogicFaceId = 422 // logicface Id
TlvMlsrAdjLsaLinkCost = 423 // 链路开销
TlvMlsrAdjLsaLogicFaceUri = 424 // LogicFace前缀
TlvMlsrAdjLsaAdjacencyInfo = 425 // 单条邻接信息
TlvMlsrAdjLsaAdjacencyList = 426 // 一个邻接LSA包含的所有邻接信息
TlvMlsrAdjLsaLogicFaceId = 422 // logicface Id
TlvMlsrAdjLsaLinkCost = 423 // 链路开销
TlvMlsrAdjLsaLogicFaceUri = 424 // LogicFace前缀
TlvMlsrAdjLsaAdjacencyInfo = 425 // 单条邻接信息
TlvMlsrAdjLsaAdjacencyList = 426 // 一个邻接LSA包含的所有邻接信息
// NameLsa的组件
TlvMlsrNameLsaNamePrefixSource = 427 // 名称前缀的来源
TlvMlsrNameLsaNamePrefixInfo = 428 // 单条名称前缀信息
TlvMlsrNameLsaNamePrefixList = 429 // 一个名称LSA包含的所有名称前缀信息
)
TlvMlsrNameLsaNamePrefixSource = 427 // 名称前缀的来源
TlvMlsrNameLsaNamePrefixInfo = 428 // 单条名称前缀信息
TlvMlsrNameLsaNamePrefixList = 429 // 一个名称LSA包含的所有名称前缀信息
// route模块涉及到的组件
TlvMlsrConnectingLogicFaceUri = 441
TlvMlsrRouteCost = 442
TlvMlsrNextHop = 443
TlvMlsrNextHopList = 444
TlvMlsrRoutingTableEntry = 445
TlvMlsrRoutingTable = 446
)
+1 -1
View File
@@ -5,12 +5,12 @@ go 1.16
require (
//github.com/rakanalh/scheduler v0.1
github.com/go-co-op/gocron v1.13.0
github.com/liyue201/gostl v1.0.1
github.com/smartystreets/goconvey v1.7.2 // indirect
github.com/tidwall/btree v1.2.1 // indirect
github.com/tidwall/buntdb v1.2.9
github.com/tidwall/gjson v1.14.0 // indirect
gopkg.in/ini.v1 v1.62.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
minlib v0.0.0
)
+4
View File
@@ -13,6 +13,8 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/liyue201/gostl v1.0.1 h1:VQdvogZ90WpCb5WdG9UxS6r5ulnYEp8VfEMEZXVtpIs=
github.com/liyue201/gostl v1.0.1/go.mod h1:rgK+T1a0sQ1+CsAonfuD1J8C4iuGfOU9VAt9mmR/m10=
github.com/mutecomm/go-sqlcipher/v4 v4.4.2 h1:eM10bFtI4UvibIsKr10/QT7Yfz+NADfjZYh0GKrXUNc=
github.com/mutecomm/go-sqlcipher/v4 v4.4.2/go.mod h1:mF2UmIpBnzFeBdu/ypTDb/LdbS0nk0dfSN1WUsWTjMA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -30,6 +32,7 @@ github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/assert v0.1.0 h1:aWcKyRBUAdLoVebxo95N7+YZVTFF/ASTr7BN4sLP6XI=
@@ -71,6 +74,7 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+150 -23
View File
@@ -9,30 +9,152 @@
package lsa
import (
"encoding/json"
"minlib/component"
"minlib/encoding"
"mlsr/extensions"
)
//
// AdjLsa
// @Description: 邻接LSA
//
type AdjLsa struct {
encoding.SelfEncodingBase
LsaBase
AdjLsaAdjacenctList
}
//
// innerAdjLsa
// @Description: 内置结构体之:邻接LSA
//
type innerAdjLsa struct {
LsaTypeInt int
LsaOriginRouter string
LsaSequenceNumber uint64
LsaExpirationTime uint64
AdjacencyInfoList []innerAdjacencyInfo
}
//
// innerAdjacencyInfo
// @Description: 内置结构体之:邻接信息
//
type innerAdjacencyInfo struct {
LinkCost uint64
LogicFaceUri string
LogicFaceId uint64
NeighborRouter string
InterestTimedOutNo uint32
Status int
}
//
// parseAdjLsaToInner
// @Description: 邻接LSA转内置结构体
// @param aLsa
// @return innerAdjLsa
// @return error
//
func parseAdjLsaToInner(aLsa *AdjLsa) (innerAdjLsa, error) {
innerALSA := innerAdjLsa{}
innerALSA.LsaTypeInt = int(aLsa.GetType())
innerALSA.LsaOriginRouter = aLsa.LsaOriginRouterIdentifier.ToUri()
innerALSA.LsaSequenceNumber = aLsa.GetSeqNo()
innerALSA.LsaExpirationTime = aLsa.GetExpirationTime()
for i := 0; i < len(aLsa.lsaAdjacencys); i++ {
info := innerAdjacencyInfo{}
info.LinkCost = aLsa.lsaAdjacencys[i].LinkCost()
info.LogicFaceUri = aLsa.lsaAdjacencys[i].LogicFaceUri()
info.LogicFaceId = aLsa.lsaAdjacencys[i].LogicFaceId()
info.NeighborRouter = aLsa.lsaAdjacencys[i].lsaNeighborRouterIdentifier.ToUri()
info.InterestTimedOutNo = aLsa.lsaAdjacencys[i].InterestTimedOutNo
info.Status = aLsa.lsaAdjacencys[i].Status
innerALSA.AdjacencyInfoList = append(innerALSA.AdjacencyInfoList, info)
}
return innerALSA, nil
}
//
// parseInnerToAdjLsa
// @Description: 内置结构体转邻接LSA
// @param inner
// @param alsa
// @return error
//
func parseInnerToAdjLsa(inner *innerAdjLsa, alsa *AdjLsa) error {
routerIdent, err := component.CreateIdentifierByString(inner.LsaOriginRouter)
if err != nil {
return err
}
alsa.SetOriginRouter(routerIdent)
alsa.SetSeqNo(inner.LsaSequenceNumber)
alsa.SetExpirationTime(inner.LsaExpirationTime)
for i := 0; i < len(inner.AdjacencyInfoList); i++ {
realInfo := new(AdjLsaAdjacencyInfo)
realInfo.SetLinkCost(inner.AdjacencyInfoList[i].LinkCost)
realInfo.SetLogicFaceUri(inner.AdjacencyInfoList[i].LogicFaceUri)
realInfo.SetLogicFaceId(inner.AdjacencyInfoList[i].LogicFaceId)
iden, err2 := component.CreateIdentifierByString(
inner.AdjacencyInfoList[i].NeighborRouter)
if err2 != nil {
return err2
}
realInfo.SetNeighborRouterIdentifier(iden)
realInfo.InterestTimedOutNo = inner.AdjacencyInfoList[i].InterestTimedOutNo
realInfo.Status = inner.AdjacencyInfoList[i].Status
alsa.lsaAdjacencys = append(alsa.lsaAdjacencys, realInfo)
}
return nil
}
//
// LoadFromJsonString
// @Description: 从json字符串中加载AdjLsa
// @receiver a
// @param jsonBytes
// @return error
//
func (a *AdjLsa) LoadFromJsonString(jsonBytes []byte) error {
// 转中间结构体
inner := innerAdjLsa{}
err := json.Unmarshal(jsonBytes, &inner)
if err != nil {
return err
}
// 转实际结构体
err = parseInnerToAdjLsa(&inner, a)
if err != nil {
return err
}
return nil
}
//
// GetJsonString
// @Description: AdjLsa转json
// @receiver a
// @return []byte
// @return error
//
func (a *AdjLsa) GetJsonString() ([]byte, error) {
innerAdjLsa, err := parseAdjLsaToInner(a)
if err != nil {
return nil, err
}
b, err := json.Marshal(innerAdjLsa)
if err != nil {
return nil, err
}
return b, nil
}
func (a *AdjLsa) GetType() LsaType {
return LsaADJACENCYType
}
func (a *AdjLsa) GetJsonString() ([]byte,error) {
// todo
return nil,nil
}
func (a *AdjLsa) LoadFromJsonString(jsonBytes []byte) error{
//todo
return nil
}
//
// GetAdjList
// @Description: 获取邻接信息表
@@ -72,8 +194,13 @@ func (a *AdjLsa) IsEqualContent(aLsa *AdjLsa) bool {
// @return string
//
func (a *AdjLsa) ToString() string {
// todo
return ""
var res = ""
res += "{ "
res += a.LsaBase.ToString()
res += ", "
res += a.AdjLsaAdjacenctList.ToString()
res += " }"
return res
}
//
@@ -84,22 +211,22 @@ func (a *AdjLsa) ToString() string {
// @return int
// @return error
//
func (a *AdjLsa) WireEncode(encoder *encoding.Encoder) (int,error) {
func (a *AdjLsa) WireEncode(encoder *encoding.Encoder) (int, error) {
totalLength := 0
// TLV-Value
tmpLen,err := a.AdjLsaAdjacenctList.WireEncode(encoder)
tmpLen, err := a.AdjLsaAdjacenctList.WireEncode(encoder)
if err != nil {
return 0, err
}
totalLength+=tmpLen
tmpLen,err = a.LsaBase.WireEncode(encoder)
totalLength += tmpLen
tmpLen, err = a.LsaBase.WireEncode(encoder)
if err != nil {
return 0, err
}
totalLength+=tmpLen
totalLength += tmpLen
// TLV-Length
tmpLen,err = encoder.PrependVarNumber(encoding.VlInt(totalLength))
tmpLen, err = encoder.PrependVarNumber(encoding.VlInt(totalLength))
if err != nil {
return 0, err
}
@@ -112,7 +239,7 @@ func (a *AdjLsa) WireEncode(encoder *encoding.Encoder) (int,error) {
}
totalLength += tmpLen
return totalLength,nil
return totalLength, nil
}
//
@@ -134,17 +261,17 @@ func (a *AdjLsa) WireDecode(block *encoding.Block) error {
}
// 提取参数
for _, parameter := range block.GetSubElements(){
for _, parameter := range block.GetSubElements() {
switch parameter.GetType() {
case extensions.TlvMlsrLsaBase:
if err:= a.LsaBase.WireDecode(parameter); err != nil {
if err := a.LsaBase.WireDecode(parameter); err != nil {
return err
}
case extensions.TlvMlsrAdjLsaAdjacencyList:
if err:= a.AdjLsaAdjacenctList.WireDecode(parameter); err != nil {
if err := a.AdjLsaAdjacenctList.WireDecode(parameter); err != nil {
return err
}
}
}
return nil
}
}
+82 -32
View File
@@ -12,22 +12,23 @@ import (
"minlib/component"
"minlib/encoding"
"mlsr/extensions"
"strconv"
)
const (
STATUS_UNKNOWN = -1
STATUS_UNKNOWN = -1
STATUS_INACTIVE = 0
STATUS_ACTIVE = 1
STATUS_ACTIVE = 1
)
type AdjLsaAdjacencyInfo struct {
AdjLsaLinkCost // 两个路由器之间的链路成本
AdjLsaLogicFaceUri // MIR层级对LogicFace的字符串描述,如udp://1.0.0.2,或ether:aa.aa.aa.aa...
AdjLsaLogicFaceId // MIR给LogicFace分配的uint64类型的id,如182828,nlsr可通过该id定位到哪个logicface负责传该链路数据
AdjLsaLinkCost // 两个路由器之间的链路成本
AdjLsaLogicFaceUri // MIR层级对LogicFace的字符串描述,如udp://1.0.0.2,或ether:aa.aa.aa.aa...
AdjLsaLogicFaceId // MIR给LogicFace分配的uint64类型的id,如182828,nlsr可通过该id定位到哪个logicface负责传该链路数据
lsaNeighborRouterIdentifier *component.Identifier // NLSR已配置的邻居路由器标识符,如/min/pkusz/group1/router1
InterestTimedOutNo uint32 // 自从收到最后一个回复之后,记录已经失败的hello兴趣包的数目
Status int // 表示邻居路由器的状态:未知-1、未激活0、激活1
InterestTimedOutNo uint32 // 自从收到最后一个回复之后,记录已经失败的hello兴趣包的数目
Status int // 表示邻居路由器的状态:未知-1、未激活0、激活1
}
//
@@ -41,13 +42,37 @@ type AdjLsaAdjacencyInfo struct {
// @return *AdjLsaAdjacencyInfo
//
func NewAdjLsaAdjacencyInfo(adjLsaLinkCost AdjLsaLinkCost, adjLsaLogicFaceUri AdjLsaLogicFaceUri,
m_lsaNeighborRouterIdentifier *component.Identifier, m_interestTimedOutNo uint32,
m_status int) *AdjLsaAdjacencyInfo {
faceId AdjLsaLogicFaceId, m_lsaNeighborRouterIdentifier *component.Identifier,
m_interestTimedOutNo uint32, m_status int) *AdjLsaAdjacencyInfo {
return &AdjLsaAdjacencyInfo{AdjLsaLinkCost: adjLsaLinkCost, AdjLsaLogicFaceUri: adjLsaLogicFaceUri,
lsaNeighborRouterIdentifier: m_lsaNeighborRouterIdentifier,
AdjLsaLogicFaceId: faceId, lsaNeighborRouterIdentifier: m_lsaNeighborRouterIdentifier,
InterestTimedOutNo: m_interestTimedOutNo, Status: m_status}
}
//
// NewAdjLsaAdjacencyInfoByInstance
// @Description: 根据已有的结构体实例,创建邻接信息结构体
// @param adjLsaLinkCost
// @param adjLsaLogicFaceUri
// @param faceId
// @param m_lsaNeighborRouterIdentifier
// @param m_interestTimedOutNo
// @param m_status
// @return *AdjLsaAdjacencyInfo
//
func NewAdjLsaAdjacencyInfoByInstance(adjLsaLinkCost *AdjLsaLinkCost, adjLsaLogicFaceUri *AdjLsaLogicFaceUri,
faceId *AdjLsaLogicFaceId, m_lsaNeighborRouterIdentifier *component.Identifier,
m_interestTimedOutNo uint32, m_status int) *AdjLsaAdjacencyInfo {
adjRes := AdjLsaAdjacencyInfo{}
adjRes.SetLinkCost(adjLsaLinkCost.LinkCost())
adjRes.SetLogicFaceUri(adjLsaLogicFaceUri.LogicFaceUri())
adjRes.SetLogicFaceId(faceId.LogicFaceId())
adjRes.SetNeighborRouterIdentifier(m_lsaNeighborRouterIdentifier)
adjRes.InterestTimedOutNo = m_interestTimedOutNo
adjRes.Status = m_status
return &adjRes
}
//
// GetNeighborRouterIdentidier
// @Description: 获取相邻路由器的标识
@@ -66,7 +91,7 @@ func (l *AdjLsaAdjacencyInfo) GetNeighborRouterIdentifier() *component.Identifie
//
func (l *AdjLsaAdjacencyInfo) SetNeighborRouterIdentifier(routerIdentifier *component.Identifier) {
// todo: 验证identifier,如类型、字段是否为空等
l.lsaNeighborRouterIdentifier= routerIdentifier
l.lsaNeighborRouterIdentifier = routerIdentifier
}
//
@@ -78,7 +103,7 @@ func (l *AdjLsaAdjacencyInfo) SetNeighborRouterIdentifier(routerIdentifier *comp
//
func (l *AdjLsaAdjacencyInfo) Compare(routerIdentifier *component.Identifier) bool {
// todo: 验证identifier,如类型、字段是否为空等
if routerIdentifier.ToUri()==l.lsaNeighborRouterIdentifier.ToUri() {
if routerIdentifier.ToUri() == l.lsaNeighborRouterIdentifier.ToUri() {
return true
}
return false
@@ -92,7 +117,7 @@ func (l *AdjLsaAdjacencyInfo) Compare(routerIdentifier *component.Identifier) bo
// @return bool
//
func (l *AdjLsaAdjacencyInfo) CompareLogicFaceUri(faceUri *AdjLsaLogicFaceUri) bool {
if faceUri.LogicFaceUri()==l.LogicFaceUri(){
if faceUri.LogicFaceUri() == l.LogicFaceUri() {
return true
}
return false
@@ -106,7 +131,7 @@ func (l *AdjLsaAdjacencyInfo) CompareLogicFaceUri(faceUri *AdjLsaLogicFaceUri) b
// @return bool
//
func (l *AdjLsaAdjacencyInfo) CompareLogicFaceUriString(faceUriString string) bool {
if faceUriString==l.LogicFaceUri(){
if faceUriString == l.LogicFaceUri() {
return true
}
return false
@@ -120,12 +145,35 @@ func (l *AdjLsaAdjacencyInfo) CompareLogicFaceUriString(faceUriString string) bo
// @return bool
//
func (l *AdjLsaAdjacencyInfo) CompareLogicFaceId(faceId uint64) bool {
if faceId==l.LogicFaceId(){
if faceId == l.LogicFaceId() {
return true
}
return false
}
//
// ToString
// @Description: 转string
// @receiver l
//
func (l *AdjLsaAdjacencyInfo) ToString() string {
var resString string
resString += "{ LinkCost: "
resString += strconv.FormatUint(l.LinkCost(), 10)
resString += ", LogicFaceUri: "
resString += l.LogicFaceUri()
resString += ", LogicFaceId: "
resString += strconv.FormatUint(l.LogicFaceId(), 10)
resString += ", NeighborRouterIdentifier: "
resString += l.lsaNeighborRouterIdentifier.ToUri()
resString += ", InterestTimedOutNo: "
resString += strconv.Itoa(int(l.InterestTimedOutNo))
resString += ", Status: "
resString += strconv.Itoa(l.Status)
resString += " }"
return resString
}
//
// WireEncode
// @Description: 线速编码
@@ -134,41 +182,41 @@ func (l *AdjLsaAdjacencyInfo) CompareLogicFaceId(faceId uint64) bool {
// @return int
// @return error
//
func (l *AdjLsaAdjacencyInfo) WireEncode(encoder *encoding.Encoder) (int,error) {
func (l *AdjLsaAdjacencyInfo) WireEncode(encoder *encoding.Encoder) (int, error) {
totalLength := 0
// TLV-Value
if tmpLen,err := l.AdjLsaLinkCost.WireEncode(encoder); err!=nil{
if tmpLen, err := l.AdjLsaLinkCost.WireEncode(encoder); err != nil {
return 0, err
}else{
} else {
totalLength += tmpLen
}
if tmpLen,err := l.AdjLsaLogicFaceUri.WireEncode(encoder); err!=nil{
if tmpLen, err := l.AdjLsaLogicFaceUri.WireEncode(encoder); err != nil {
return 0, err
}else{
} else {
totalLength += tmpLen
}
if tmpLen,err := l.lsaNeighborRouterIdentifier.WireEncode(encoder); err!=nil{
if tmpLen, err := l.lsaNeighborRouterIdentifier.WireEncode(encoder); err != nil {
return 0, err
}else{
} else {
totalLength += tmpLen
}
// TLV-Length
if tmpLen,err := encoder.PrependVarNumber(encoding.VlInt(totalLength)); err!=nil{
if tmpLen, err := encoder.PrependVarNumber(encoding.VlInt(totalLength)); err != nil {
return 0, err
}else{
} else {
totalLength += tmpLen
}
// TLV-Type
if tmpLen,err := encoder.PrependVarNumber(extensions.TlvMlsrAdjLsaAdjacencyInfo); err!=nil{
if tmpLen, err := encoder.PrependVarNumber(extensions.TlvMlsrAdjLsaAdjacencyInfo); err != nil {
return 0, err
}else{
} else {
totalLength += tmpLen
}
return totalLength,nil
return totalLength, nil
}
//
@@ -190,21 +238,23 @@ func (l *AdjLsaAdjacencyInfo) WireDecode(block *encoding.Block) error {
}
// 提取参数
for _, parameter := range block.GetSubElements(){
for _, parameter := range block.GetSubElements() {
switch parameter.GetType() {
case encoding.TlvIdentifier:
if err:= l.lsaNeighborRouterIdentifier.WireDecode(parameter); err != nil {
iden := component.Identifier{}
if err := iden.WireDecode(parameter); err != nil {
return err
}
l.lsaNeighborRouterIdentifier = &iden
case extensions.TlvMlsrAdjLsaLogicFaceUri:
if err:= l.AdjLsaLogicFaceUri.WireDecode(parameter); err != nil {
if err := l.AdjLsaLogicFaceUri.WireDecode(parameter); err != nil {
return err
}
case extensions.TlvMlsrAdjLsaLinkCost:
if err:= l.AdjLsaLinkCost.WireDecode(parameter); err != nil {
if err := l.AdjLsaLinkCost.WireDecode(parameter); err != nil {
return err
}
}
}
return nil
}
}
+130
View File
@@ -0,0 +1,130 @@
// Package lsa
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/4/22 11:01
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package lsa
import (
"fmt"
"minlib/component"
"minlib/encoding"
"testing"
)
//
// TestNewAdjLsaAdjacencyInfo
// @Description: 测试构造一条邻接信息
// @param t
//
func TestNewAdjLsaAdjacencyInfo(t *testing.T) {
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
fmt.Println("cost: ", adjInfo.LinkCost())
fmt.Println("uri: ", adjInfo.LogicFaceUri())
fmt.Println("id: ", adjInfo.LogicFaceId())
fmt.Println("identifier: ", iden.ToUri())
fmt.Println(adjInfo.ToString())
}
//
// TestAdjLsaAdjacencyInfo_Compare
// @Description: 测试一些比较函数
// @param t
//
func TestAdjLsaAdjacencyInfo_Compare(t *testing.T) {
// 先构造
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
// 再测试:全部为true则pass
iden2, _ := component.CreateIdentifierByString("/pku/router")
fmt.Println(adjInfo.Compare(iden2))
fmt.Println(adjInfo.CompareLogicFaceId(77))
fmt.Println(adjInfo.CompareLogicFaceUriString("uri"))
fmt.Println(adjInfo.CompareLogicFaceUri(&faceUri))
}
//
// TestAdjLsaAdjacencyInfo_WireEncode
// @Description: 测试编码
// @param t
//
func TestAdjLsaAdjacencyInfo_WireEncode(t *testing.T) {
// 先构造
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
// 构造编码器
encoder := encoding.Encoder{}
err := encoder.EncoderReset(encoding.MaxPacketSize, 0)
if err != nil {
fmt.Println("encoder reset失败 ", err.Error())
return
}
// 编码并打印
cnt, err := adjInfo.WireEncode(&encoder)
if err != nil {
fmt.Println("AdjInfo 线速编码失败 ", err.Error())
return
}
res, err := encoder.GetBuffer()
if err != nil {
fmt.Println("获取编码结果失败 ", err.Error())
return
}
fmt.Println(cnt)
for i := 0; i < len(res); i++ {
fmt.Print(res[i], ", ")
}
fmt.Println()
// 241, 1, 169, 33, 101, 19, 100, 2, 0, 47, 100, 4, 0, 112, 107, 117, 100, 7, 0, 114, 111, 117, 116, 101, 114, 241, 1, 168, 3, 117, 114, 105, 241, 1, 167, 1, 100,
}
//
// TestAdjLsaAdjacencyInfo_WireDecode
// @Description: 测试线速解码
// 注意,编码解码目前只作用于三个信息项目:链路开销、faceuri、邻接路预期标识符三个信息项
// @param t
//
func TestAdjLsaAdjacencyInfo_WireDecode(t *testing.T) {
// 由数组构建block
var buf = [37]byte{241, 1, 169, 33, 101, 19, 100, 2, 0, 47, 100, 4, 0, 112, 107,
117, 100, 7, 0, 114, 111, 117, 116,
101, 114, 241, 1, 168, 3, 117, 114, 105, 241, 1, 167, 1, 100}
block, err := encoding.CreateBlockByBuffer(buf[:], true)
if err != nil {
fmt.Println("创建block失败 ", err.Error())
return
}
// 由Block构建结构体,并打印变量
adjInfo := new(AdjLsaAdjacencyInfo)
err = adjInfo.WireDecode(block)
if err != nil {
fmt.Println("线性解码失败 ", err.Error())
return
}
fmt.Println(adjInfo.ToString())
}
+121 -77
View File
@@ -37,6 +37,18 @@ func (l *AdjLsaAdjacenctList) Insert(info *AdjLsaAdjacencyInfo) {
l.lsaAdjacencys = append(l.lsaAdjacencys, info)
}
//
// InsertAdjacenctList
// @Description: 插入邻接列表
// @receiver l
// @param list
//
func (l *AdjLsaAdjacenctList) InsertAdjacenctList(list []*AdjLsaAdjacencyInfo) {
for i := 0; i < len(list); i++ {
l.Insert(list[i])
}
}
//
// getAdjList
// @Description: 获取包含所有邻接信息的邻接表
@@ -47,6 +59,25 @@ func (l *AdjLsaAdjacenctList) GetAdjList() []*AdjLsaAdjacencyInfo {
return l.lsaAdjacencys
}
//
// ToString
// @Description: 转string
// @receiver l
// @return string
//
func (l *AdjLsaAdjacenctList) ToString() string {
var resString string
resString += "[ "
for i := 0; i < l.Size(); i++ {
resString += l.GetAdjList()[i].ToString()
if i < (l.Size() - 1) {
resString += ", "
}
}
resString += " ]"
return resString
}
//
// isNeighbor
// @Description: 判断某个MIR标识符是否是邻居MIR
@@ -55,8 +86,8 @@ func (l *AdjLsaAdjacenctList) GetAdjList() []*AdjLsaAdjacencyInfo {
// @return bool
//
func (l *AdjLsaAdjacenctList) IsNeighbor(routerIdentifier *component.Identifier) bool {
for i:=0; i<len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].lsaNeighborRouterIdentifier.ToUri()==routerIdentifier.ToUri(){
for i := 0; i < len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].lsaNeighborRouterIdentifier.ToUri() == routerIdentifier.ToUri() {
return true
}
}
@@ -72,13 +103,13 @@ func (l *AdjLsaAdjacenctList) IsNeighbor(routerIdentifier *component.Identifier)
// @return int
// @return error
//
func (l *AdjLsaAdjacenctList) findIndexByRouterIdentifier(routerIdentifier *component.Identifier) (int,error) {
for i:=0; i<len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].lsaNeighborRouterIdentifier.ToUri()==routerIdentifier.ToUri(){
return i,nil
func (l *AdjLsaAdjacenctList) findIndexByRouterIdentifier(routerIdentifier *component.Identifier) (int, error) {
for i := 0; i < len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].lsaNeighborRouterIdentifier.ToUri() == routerIdentifier.ToUri() {
return i, nil
}
}
return -1,errors.New("no found the identifier")
return -1, errors.New("no found the identifier")
}
//
@@ -90,9 +121,9 @@ func (l *AdjLsaAdjacenctList) findIndexByRouterIdentifier(routerIdentifier *comp
// @return error
//
func (l *AdjLsaAdjacenctList) IncrementTimedOutInterestCount(routerIdentifier *component.Identifier) error {
if index,err:=l.findIndexByRouterIdentifier(routerIdentifier);err!=nil{
if index, err := l.findIndexByRouterIdentifier(routerIdentifier); err != nil {
return err
}else{
} else {
l.lsaAdjacencys[index].InterestTimedOutNo++
return nil
}
@@ -108,10 +139,10 @@ func (l *AdjLsaAdjacenctList) IncrementTimedOutInterestCount(routerIdentifier *c
// @return error
//
func (l *AdjLsaAdjacenctList) SetTimedOutInterestCount(routerIdentifier *component.Identifier, count uint32) error {
if index,err:=l.findIndexByRouterIdentifier(routerIdentifier);err!=nil{
if index, err := l.findIndexByRouterIdentifier(routerIdentifier); err != nil {
return err
}else{
l.lsaAdjacencys[index].InterestTimedOutNo=count
} else {
l.lsaAdjacencys[index].InterestTimedOutNo = count
return nil
}
}
@@ -124,11 +155,11 @@ func (l *AdjLsaAdjacenctList) SetTimedOutInterestCount(routerIdentifier *compone
// @return uint32
// @return error
//
func (l *AdjLsaAdjacenctList) GetTimedOutInterestCount(routerIdentifier *component.Identifier) (uint32,error) {
if index,err:=l.findIndexByRouterIdentifier(routerIdentifier);err!=nil{
return 0,err
}else{
return l.lsaAdjacencys[index].InterestTimedOutNo,nil
func (l *AdjLsaAdjacenctList) GetTimedOutInterestCount(routerIdentifier *component.Identifier) (uint32, error) {
if index, err := l.findIndexByRouterIdentifier(routerIdentifier); err != nil {
return 0, err
} else {
return l.lsaAdjacencys[index].InterestTimedOutNo, nil
}
}
@@ -140,11 +171,11 @@ func (l *AdjLsaAdjacenctList) GetTimedOutInterestCount(routerIdentifier *compone
// @return int
// @return error
//
func (l *AdjLsaAdjacenctList) GetStatusOfNeighbor(routerIdentifier *component.Identifier) (int,error) {
if index,err:=l.findIndexByRouterIdentifier(routerIdentifier);err!=nil{
return -2,err
}else{
return l.lsaAdjacencys[index].Status,nil
func (l *AdjLsaAdjacenctList) GetStatusOfNeighbor(routerIdentifier *component.Identifier) (int, error) {
if index, err := l.findIndexByRouterIdentifier(routerIdentifier); err != nil {
return -2, err
} else {
return l.lsaAdjacencys[index].Status, nil
}
}
@@ -156,35 +187,39 @@ func (l *AdjLsaAdjacenctList) GetStatusOfNeighbor(routerIdentifier *component.Id
// @param status
// @return error
//
func (l *AdjLsaAdjacenctList) SetStatusOfNeighbor(routerIdentifier *component.Identifier,status int) error {
if index,err:=l.findIndexByRouterIdentifier(routerIdentifier);err!=nil{
func (l *AdjLsaAdjacenctList) SetStatusOfNeighbor(routerIdentifier *component.Identifier, status int) error {
if index, err := l.findIndexByRouterIdentifier(routerIdentifier); err != nil {
return err
}else{
l.lsaAdjacencys[index].Status=status
} else {
l.lsaAdjacencys[index].Status = status
return nil
}
}
//
// isAdjLsaBuildable
// @Description: 当所有邻居的状态可知时,此表可用于构建邻接LSA。
// 当邻居状态是ACTIVE或INACTIVE时,就表示此邻居状态可知;
// 当一个邻居还在被联络,即在发送hello兴趣包给它时,则此邻居状态为UNKNOWN。
// 在Nlsr中,本函数的代码实现与代码注释不一致,后面可以进一步研究其原因,甚至可以提交issue给nlsr项目组。
// @Description: 判断邻接LSA是否要被再次构建
// @receiver l
// @param interestRetryNo 联系邻居的hello兴趣包的最大重传次数
// @return bool 此邻接表的实体对象是否能够用于构建一个邻接LSA
//
func (l *AdjLsaAdjacenctList) IsAdjLsaBuildable(interestRetryNo uint32) bool {
for i:=0; i<len(l.lsaAdjacencys); i++ {
switch l.lsaAdjacencys[i].Status{
case STATUS_UNKNOWN:
if l.lsaAdjacencys[i].InterestTimedOutNo<interestRetryNo{
return false
}
nTimedOutNeighbors := 0
for i := 0; i < len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].Status == STATUS_ACTIVE {
// 有已经知道在激活状态的邻居,则将其安装到LSDB
return true
} else if l.lsaAdjacencys[i].InterestTimedOutNo >= interestRetryNo {
// 如果邻居全部都没有激活,且兴趣包尝试次数超出最大值,就删掉本机的邻接LSA
nTimedOutNeighbors++
}
}
return true
if nTimedOutNeighbors == len(l.lsaAdjacencys) {
return true
} else {
// 既没有激活邻居,又还在尝试查看邻居情况,则继续安排构建邻接LSA
return false
}
}
//
@@ -195,11 +230,11 @@ func (l *AdjLsaAdjacenctList) IsAdjLsaBuildable(interestRetryNo uint32) bool {
// @return *AdjLsaAdjacencyInfo
// @return error
//
func (l *AdjLsaAdjacenctList) GetAdjacency(routerIdentifier *component.Identifier) (*AdjLsaAdjacencyInfo,error){
if index,err:=l.findIndexByRouterIdentifier(routerIdentifier);err!=nil{
return nil,err
}else{
return l.lsaAdjacencys[index],nil
func (l *AdjLsaAdjacenctList) GetAdjacency(routerIdentifier *component.Identifier) (*AdjLsaAdjacencyInfo, error) {
if index, err := l.findIndexByRouterIdentifier(routerIdentifier); err != nil {
return nil, err
} else {
return l.lsaAdjacencys[index], nil
}
}
@@ -210,9 +245,9 @@ func (l *AdjLsaAdjacenctList) GetAdjacency(routerIdentifier *component.Identifie
// @return int
//
func (l *AdjLsaAdjacenctList) GetNumOfActiveNeighbor() int {
numbers:=0
for i:=0; i<len(l.lsaAdjacencys); i++ {
switch l.lsaAdjacencys[i].Status{
numbers := 0
for i := 0; i < len(l.lsaAdjacencys); i++ {
switch l.lsaAdjacencys[i].Status {
case STATUS_ACTIVE:
numbers++
}
@@ -227,9 +262,9 @@ func (l *AdjLsaAdjacenctList) GetNumOfActiveNeighbor() int {
// @return int
//
func (l *AdjLsaAdjacenctList) GetNumOfINActiveNeighbor() int {
numbers:=0
for i:=0; i<len(l.lsaAdjacencys); i++ {
switch l.lsaAdjacencys[i].Status{
numbers := 0
for i := 0; i < len(l.lsaAdjacencys); i++ {
switch l.lsaAdjacencys[i].Status {
case STATUS_INACTIVE:
numbers++
}
@@ -244,9 +279,9 @@ func (l *AdjLsaAdjacenctList) GetNumOfINActiveNeighbor() int {
// @return int
//
func (l *AdjLsaAdjacenctList) GetNumOfUnknownNeighbor() int {
numbers:=0
for i:=0; i<len(l.lsaAdjacencys); i++ {
switch l.lsaAdjacencys[i].Status{
numbers := 0
for i := 0; i < len(l.lsaAdjacencys); i++ {
switch l.lsaAdjacencys[i].Status {
case STATUS_UNKNOWN:
numbers++
}
@@ -269,12 +304,12 @@ func (l *AdjLsaAdjacenctList) Size() int {
// @Description: 清空所有邻接信息
// @receiver l
//
func (l *AdjLsaAdjacenctList) Reset() {
l.lsaAdjacencys=[]*AdjLsaAdjacencyInfo{}
func (l *AdjLsaAdjacenctList) Reset() {
l.lsaAdjacencys = []*AdjLsaAdjacencyInfo{}
}
//
// FindAdjacencyByRouterIdentifier
// FindAdjacencysByRouterIdentifier
// @Description: 获取指定路由器标识的所有邻接信息条目。
// 这就表明一个邻接表中可能有包含同一个MIR标识的多个邻接信息条目,
// 前面的一些设置或获取操作均只对按序查到的第一个邻接信息条目进行操作。
@@ -283,16 +318,25 @@ func (l *AdjLsaAdjacenctList) Reset() {
// @param routerIdentifier
// @return []*AdjLsaAdjacencyInfo
//
func (l *AdjLsaAdjacenctList) FindAdjacencyByRouterIdentifier(routerIdentifier *component.Identifier) []*AdjLsaAdjacencyInfo {
func (l *AdjLsaAdjacenctList) FindAdjacencysByRouterIdentifier(routerIdentifier *component.Identifier) []*AdjLsaAdjacencyInfo {
var infos []*AdjLsaAdjacencyInfo
for i:=0; i<len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].lsaNeighborRouterIdentifier.ToUri()==routerIdentifier.ToUri(){
infos=append(infos,l.lsaAdjacencys[i])
for i := 0; i < len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].lsaNeighborRouterIdentifier.ToUri() == routerIdentifier.ToUri() {
infos = append(infos, l.lsaAdjacencys[i])
}
}
return infos
}
func (l *AdjLsaAdjacenctList) FindAdjacencyByRouterIdentifier(routerIdentifier *component.Identifier) *AdjLsaAdjacencyInfo {
for i := 0; i < len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].lsaNeighborRouterIdentifier.ToUri() == routerIdentifier.ToUri() {
return l.lsaAdjacencys[i]
}
}
return nil
}
//
// FindAdjacencyByLogicFaceId
// @Description: 获取指定LogicFaceId的所有邻接信息条目
@@ -302,9 +346,9 @@ func (l *AdjLsaAdjacenctList) FindAdjacencyByRouterIdentifier(routerIdentifier *
//
func (l *AdjLsaAdjacenctList) FindAdjacencyByLogicFaceId(id *AdjLsaLogicFaceId) []*AdjLsaAdjacencyInfo {
var infos []*AdjLsaAdjacencyInfo
for i:=0; i<len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].LogicFaceId()==id.Value(){
infos=append(infos,l.lsaAdjacencys[i])
for i := 0; i < len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].LogicFaceId() == id.Value() {
infos = append(infos, l.lsaAdjacencys[i])
}
}
return infos
@@ -319,21 +363,21 @@ func (l *AdjLsaAdjacenctList) FindAdjacencyByLogicFaceId(id *AdjLsaLogicFaceId)
//
func (l *AdjLsaAdjacenctList) FindAdjacencyByLogicFaceUri(uri *AdjLsaLogicFaceUri) []*AdjLsaAdjacencyInfo {
var infos []*AdjLsaAdjacencyInfo
for i:=0; i<len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].AdjLsaLogicFaceUri.Value()==uri.Value(){
infos=append(infos,l.lsaAdjacencys[i])
for i := 0; i < len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].AdjLsaLogicFaceUri.Value() == uri.Value() {
infos = append(infos, l.lsaAdjacencys[i])
}
}
return infos
}
func (l *AdjLsaAdjacenctList) getLogicFaceId(uri *AdjLsaLogicFaceUri) (uint64,error) {
for i:=0; i<len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].AdjLsaLogicFaceUri.Value()==uri.Value(){
return l.lsaAdjacencys[i].AdjLsaLogicFaceId.Value(),nil
func (l *AdjLsaAdjacenctList) getLogicFaceId(uri *AdjLsaLogicFaceUri) (uint64, error) {
for i := 0; i < len(l.lsaAdjacencys); i++ {
if l.lsaAdjacencys[i].AdjLsaLogicFaceUri.Value() == uri.Value() {
return l.lsaAdjacencys[i].AdjLsaLogicFaceId.Value(), nil
}
}
return 0,errors.New("not found the AdjLsaLogicFaceUri in the list")
return 0, errors.New("not found the AdjLsaLogicFaceUri in the list")
}
//
@@ -344,19 +388,19 @@ func (l *AdjLsaAdjacenctList) getLogicFaceId(uri *AdjLsaLogicFaceUri) (uint64,er
// @return int
// @return error
//
func (l *AdjLsaAdjacenctList) WireEncode(encoder *encoding.Encoder) (int,error) {
func (l *AdjLsaAdjacenctList) WireEncode(encoder *encoding.Encoder) (int, error) {
// 判断列表长度,为0则抛出错误
if len(l.lsaAdjacencys)==0 {
return 0,errors.New("Invalid AdjLsaAdjacencyList, expect at least one AdjLsaAdjacencyInfo!")
if len(l.lsaAdjacencys) == 0 {
return 0, errors.New("Invalid AdjLsaAdjacencyList, expect at least one AdjLsaAdjacencyInfo!")
}
totalLength := 0
// 编码 TLV-VALUE
// 反向遍历,可以保证解码的时候正向输出
for i:=len(l.lsaAdjacencys)-1; i>=0; i-- {
if l.lsaAdjacencys[i]==nil {
for i := len(l.lsaAdjacencys) - 1; i >= 0; i-- {
if l.lsaAdjacencys[i] == nil {
continue
}
tmpLen,err := l.lsaAdjacencys[i].WireEncode(encoder)
tmpLen, err := l.lsaAdjacencys[i].WireEncode(encoder)
if err != nil {
return 0, err
}
@@ -377,7 +421,7 @@ func (l *AdjLsaAdjacenctList) WireEncode(encoder *encoding.Encoder) (int,error)
}
totalLength += tmpLen
return totalLength,nil
return totalLength, nil
}
//
@@ -408,4 +452,4 @@ func (l *AdjLsaAdjacenctList) WireDecode(block *encoding.Block) error {
}
l.lsaAdjacencys = adjacencyContainer
return nil
}
}
+236
View File
@@ -0,0 +1,236 @@
// Package lsa
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/4/22 0:15
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package lsa
import (
"fmt"
"minlib/component"
"minlib/encoding"
"testing"
)
//
// TestAdjLsaAdjacenctList_GetAdjList
// @Description: 测试构造、打印
// @param t
//
func TestAdjLsaAdjacenctList_GetAdjList(t *testing.T) {
// 先构造一个info
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
// 构造Info列表
adjInfoList := new(AdjLsaAdjacenctList)
adjInfoList.Insert(adjInfo)
// 再加第二个info
iden2, _ := component.CreateIdentifierByString("/pku/router2")
adjInfo.SetNeighborRouterIdentifier(iden2)
adjInfoList.Insert(adjInfo)
// 测试输出
fmt.Println(adjInfoList.ToString())
}
//
// TestAdjLsaAdjacenctList_IsNeighbor
// @Description: 测试是否是邻居路由器
// @param t
//
func TestAdjLsaAdjacenctList_IsNeighbor(t *testing.T) {
// 先构造一个info
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
adjInfoList := new(AdjLsaAdjacenctList)
adjInfoList.Insert(adjInfo)
// 测试某路由器是否是邻居节点
fmt.Println(adjInfoList.IsNeighbor(iden))
iden2, _ := component.CreateIdentifierByString("/pku/router2")
fmt.Println(adjInfoList.IsNeighbor(iden2))
}
//
// TestAdjLsaAdjacenctList_IncrementTimedOutInterestCount
// @Description: 测试增加、设置、获取已经失败的hello兴趣包的数目
// @param t
//
func TestAdjLsaAdjacenctList_IncrementTimedOutInterestCount(t *testing.T) {
// 先构造一个info
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
adjInfoList := new(AdjLsaAdjacenctList)
adjInfoList.Insert(adjInfo)
// 测试增加已经失败的hello兴趣包的数目
_ = adjInfoList.IncrementTimedOutInterestCount(iden)
fmt.Println(adjInfoList.ToString())
// 测试设置
_ = adjInfoList.SetTimedOutInterestCount(iden, 10)
fmt.Println(adjInfoList.ToString())
// 测试获取
fmt.Println(adjInfoList.GetTimedOutInterestCount(iden))
}
//
// TestAdjLsaAdjacenctList_GetStatusOfNeighbor
// @Description: 测试操作邻居路由器的状态
// @param t
//
func TestAdjLsaAdjacenctList_GetStatusOfNeighbor(t *testing.T) {
// 先构造一个info
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
adjInfoList := new(AdjLsaAdjacenctList)
adjInfoList.Insert(adjInfo)
// 测试获取状态
fmt.Println(adjInfoList.GetStatusOfNeighbor(iden))
// 设置再获取
adjInfoList.SetStatusOfNeighbor(iden, 2)
fmt.Println(adjInfoList.GetStatusOfNeighbor(iden))
}
//
// TestAdjLsaAdjacenctList_FindAdjacencyByRouterIdentifier
// @Description: 测试获取邻接信息
// @param t
//
func TestAdjLsaAdjacenctList_FindAdjacencyByRouterIdentifier(t *testing.T) {
// 先构造一个info
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
adjInfoList := new(AdjLsaAdjacenctList)
adjInfoList.Insert(adjInfo)
// 获取
fmt.Println(adjInfoList.FindAdjacencysByRouterIdentifier(iden)[0].ToString())
//fmt.Println(adjInfoList.FindAdjacencyByRouterIdentifier(iden)[1].ToString())
fmt.Println(adjInfoList.FindAdjacencyByLogicFaceId(&faceId)[0].ToString())
fmt.Println(adjInfoList.FindAdjacencyByLogicFaceUri(&faceUri)[0].ToString())
}
//
// TestAdjLsaAdjacenctList_WireEncode
// @Description: 测试编码
// @param t
//
func TestAdjLsaAdjacenctList_WireEncode(t *testing.T) {
// 先构造一个info
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
// 构造Info列表
adjInfoList := new(AdjLsaAdjacenctList)
adjInfoList.Insert(adjInfo)
// 再加第二个info
iden2, _ := component.CreateIdentifierByString("/pku/router2")
adjInfo2 := AdjLsaAdjacencyInfo{
AdjLsaLinkCost: adjInfo.AdjLsaLinkCost,
AdjLsaLogicFaceUri: adjInfo.AdjLsaLogicFaceUri,
AdjLsaLogicFaceId: adjInfo.AdjLsaLogicFaceId,
lsaNeighborRouterIdentifier: iden2,
InterestTimedOutNo: 111,
Status: 0,
}
adjInfoList.Insert(&adjInfo2)
fmt.Println(adjInfoList.ToString())
// 构造编码器
encoder := encoding.Encoder{}
err := encoder.EncoderReset(encoding.MaxPacketSize, 0)
if err != nil {
fmt.Println("encoder reset失败 ", err.Error())
return
}
// 编码并打印
cnt, err := adjInfoList.WireEncode(&encoder)
if err != nil {
fmt.Println("LsaBase 线速编码失败 ", err.Error())
return
}
res, err := encoder.GetBuffer()
if err != nil {
fmt.Println("获取编码结果失败 ", err.Error())
return
}
fmt.Println(cnt)
for i := 0; i < len(res); i++ {
fmt.Print(res[i], ", ")
}
fmt.Println()
}
//
// TestAdjLsaAdjacenctList_WireDecode
// @Description: 测试解码
// @param t
//
func TestAdjLsaAdjacenctList_WireDecode(t *testing.T) {
// 由数组构建block
var buf = [80]byte{241, 1, 170, 76, 241, 1, 169, 34, 101, 20, 100, 2,
0, 47, 100, 4, 0, 112, 107, 117, 100, 8, 0, 114, 111, 117, 116,
101, 114, 49, 241, 1, 168, 3, 117, 114, 105, 241, 1, 167, 1, 100,
241, 1, 169, 34, 101, 20, 100, 2, 0, 47, 100, 4, 0, 112, 107, 117,
100, 8, 0, 114, 111, 117, 116, 101, 114, 50,
241, 1, 168, 3, 117, 114, 105, 241, 1, 167, 1, 100}
block, err := encoding.CreateBlockByBuffer(buf[:], true)
if err != nil {
fmt.Println("创建block失败 ", err.Error())
return
}
// 由Block构建结构体,并打印变量
base := new(AdjLsaAdjacenctList)
err = base.WireDecode(block)
if err != nil {
fmt.Println("线性解码失败 ", err.Error())
return
}
fmt.Println(base.ToString())
}
+4 -4
View File
@@ -33,12 +33,12 @@ func (l *AdjLsaLogicFaceUri) LogicFaceUri() string {
}
//
// setLogicFaceUri
// SetLogicFaceUri
// @Description: 设置LogicFaceUri
// @receiver l
// @param logicFaceUri
//
func (l *AdjLsaLogicFaceUri) setLogicFaceUri(logicFaceUri string) {
func (l *AdjLsaLogicFaceUri) SetLogicFaceUri(logicFaceUri string) {
l.CommonString.SetValue(logicFaceUri)
}
@@ -50,7 +50,7 @@ func (l *AdjLsaLogicFaceUri) setLogicFaceUri(logicFaceUri string) {
// @return int
// @return error
//
func (l *AdjLsaLogicFaceUri) WireEncode(encoder *encoding.Encoder) (int,error) {
func (l *AdjLsaLogicFaceUri) WireEncode(encoder *encoding.Encoder) (int, error) {
l.CommonString.SetTlvType(extensions.TlvMlsrAdjLsaLogicFaceUri)
return l.CommonString.WireEncode(encoder)
}
@@ -64,7 +64,7 @@ func (l *AdjLsaLogicFaceUri) WireEncode(encoder *encoding.Encoder) (int,error) {
//
func (l *AdjLsaLogicFaceUri) WireDecode(block *encoding.Block) error {
// 检查type是否正确
if err := encoding.ExpectType(block.GetType(),extensions.TlvMlsrAdjLsaLogicFaceUri); err!=nil {
if err := encoding.ExpectType(block.GetType(), extensions.TlvMlsrAdjLsaLogicFaceUri); err != nil {
return err
}
return l.CommonString.WireDecode(block)
+3 -3
View File
@@ -21,7 +21,7 @@ import (
//
func TestAdjLsaLogicFaceUri_LogicFaceUri(t *testing.T) {
testCPU := AdjLsaLogicFaceUri{}
testCPU.setLogicFaceUri("url")
testCPU.SetLogicFaceUri("url")
fmt.Println(testCPU.LogicFaceUri())
}
@@ -33,7 +33,7 @@ func TestAdjLsaLogicFaceUri_LogicFaceUri(t *testing.T) {
func TestAdjLsaLogicFaceUri_WireEncode(t *testing.T) {
testCPU := new(AdjLsaLogicFaceUri)
fmt.Println(testCPU.LogicFaceUri())
testCPU.setLogicFaceUri("url")
testCPU.SetLogicFaceUri("url")
fmt.Println(testCPU.LogicFaceUri())
//testCPC.SetTlvType(5)
fmt.Println(testCPU.Value())
@@ -72,7 +72,7 @@ func TestAdjLsaLogicFaceUri_WireDecode(t *testing.T) {
fmt.Println("interest", testCPU.Value())
//testCPC.SetTlvType(5)
fmt.Println(testCPU.TlvType())
testCPU.setLogicFaceUri("url")
testCPU.SetLogicFaceUri("url")
fmt.Println("interest", testCPU.Value())
fmt.Println("interest", testCPU.IsInitial())
var encoder encoding.Encoder
+198
View File
@@ -0,0 +1,198 @@
// Package lsa
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/4/22 11:01
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package lsa
import (
"encoding/json"
"fmt"
common2 "minlib/common"
"minlib/component"
"minlib/encoding"
"testing"
)
func TestAdjLsa_JsonConv(t *testing.T) {
// 构造基本部分
base := new(AdjLsa)
base.SetLsaExpirationTime(2000)
base.SetLsaSequenceNumber(1234)
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/pku")
// 构造邻接信息部分
// 先构造一个info
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
base.Insert(adjInfo)
// 再加第二个info
iden2, _ := component.CreateIdentifierByString("/pku/router2")
adjInfo2 := AdjLsaAdjacencyInfo{
AdjLsaLinkCost: adjInfo.AdjLsaLinkCost,
AdjLsaLogicFaceUri: adjInfo.AdjLsaLogicFaceUri,
AdjLsaLogicFaceId: adjInfo.AdjLsaLogicFaceId,
lsaNeighborRouterIdentifier: iden2,
InterestTimedOutNo: 111,
Status: 0,
}
base.Insert(&adjInfo2)
// 打印该adjlsa
common2.LogInfo(base.ToString())
// 转byte[]类型的json
jsonBytes, err := json.Marshal(&base)
if err != nil {
common2.LogInfo("邻接LSA json 转换失败")
}
common2.LogInfo("直接用Marshal将邻接LSA为Json: " + string(jsonBytes))
jsonBytes, err = base.GetJsonString()
common2.LogInfo("通过中间结构体将邻接LSA转为json: " + string(jsonBytes))
// 从Json转回来
newAdjLsa := new(AdjLsa)
err = newAdjLsa.LoadFromJsonString(jsonBytes)
if err != nil {
common2.LogInfo("邻接LSA json 转换失败")
}
common2.LogInfo("通过中间结构体将json转为邻接LSA: " + newAdjLsa.ToString())
}
//
// TestAdjLsa_New
// @Description: 构造
// @param t
//
func TestAdjLsa_New(t *testing.T) {
// 构造基本部分
base := new(AdjLsa)
base.SetLsaExpirationTime(2000)
base.SetLsaSequenceNumber(1234)
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/pku")
// 构造邻接信息部分
// 先构造一个info
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
base.Insert(adjInfo)
// 再加第二个info
iden2, _ := component.CreateIdentifierByString("/pku/router2")
adjInfo2 := AdjLsaAdjacencyInfo{
AdjLsaLinkCost: adjInfo.AdjLsaLinkCost,
AdjLsaLogicFaceUri: adjInfo.AdjLsaLogicFaceUri,
AdjLsaLogicFaceId: adjInfo.AdjLsaLogicFaceId,
lsaNeighborRouterIdentifier: iden2,
InterestTimedOutNo: 111,
Status: 0,
}
base.Insert(&adjInfo2)
// 打印该adjlsa
fmt.Println(base.ToString())
}
//
// TestAdjLsa_WireEncode
// @Description: 测试线速编码
// @param t
//
func TestAdjLsa_WireEncode(t *testing.T) {
// 构造LSA
base := new(AdjLsa)
base.SetLsaExpirationTime(2000)
base.SetLsaSequenceNumber(1234)
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/pku")
// 构造邻接信息部分
// 先构造一个info
linkCost := AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
base.Insert(adjInfo)
// 再加第二个info
iden2, _ := component.CreateIdentifierByString("/pku/router2")
adjInfo2 := AdjLsaAdjacencyInfo{
AdjLsaLinkCost: adjInfo.AdjLsaLinkCost,
AdjLsaLogicFaceUri: adjInfo.AdjLsaLogicFaceUri,
AdjLsaLogicFaceId: adjInfo.AdjLsaLogicFaceId,
lsaNeighborRouterIdentifier: iden2,
InterestTimedOutNo: 111,
Status: 0,
}
base.Insert(&adjInfo2)
// 构造编码器
encoder := encoding.Encoder{}
err := encoder.EncoderReset(encoding.MaxPacketSize, 0)
if err != nil {
fmt.Println("encoder reset失败 ", err.Error())
return
}
// 编码并打印
cnt, err := base.WireEncode(&encoder)
if err != nil {
fmt.Println("LsaBase 线速编码失败 ", err.Error())
return
}
res, err := encoder.GetBuffer()
if err != nil {
fmt.Println("获取编码结果失败 ", err.Error())
return
}
fmt.Println(cnt)
for i := 0; i < len(res); i++ {
fmt.Print(res[i], ", ")
}
fmt.Println()
}
//
// TestAdjLsa_WireDecode
// @Description: 测试线速解码
// @param t
//
func TestAdjLsa_WireDecode(t *testing.T) {
// 由数组构建block
var buf = [118]byte{241, 1, 145, 114, 241, 1, 154, 30, 101, 16, 100,
2, 0, 47, 100, 4, 0, 109, 105, 110, 100, 4, 0, 112, 107, 117,
241, 1, 165, 2, 4, 210, 241, 1, 164, 2, 7, 208, 241, 1, 170,
76, 241, 1, 169, 34, 101, 20, 100, 2, 0, 47, 100, 4, 0, 112,
107, 117, 100, 8, 0, 114, 111, 117, 116, 101, 114, 49, 241,
1, 168, 3, 117, 114, 105, 241, 1, 167, 1, 100, 241, 1, 169,
34, 101, 20, 100, 2, 0, 47, 100, 4, 0, 112, 107, 117, 100,
8, 0, 114, 111, 117, 116, 101, 114, 50,
241, 1, 168, 3, 117, 114, 105, 241, 1, 167, 1, 100}
block, err := encoding.CreateBlockByBuffer(buf[:], true)
if err != nil {
fmt.Println("创建block失败 ", err.Error())
return
}
// 由Block构建结构体,并打印变量
base := new(AdjLsa)
err = base.WireDecode(block)
if err != nil {
fmt.Println("线性解码失败 ", err.Error())
return
}
fmt.Println(base.ToString())
}
+55 -40
View File
@@ -15,6 +15,10 @@ import (
"mlsr/extensions"
)
//
// NameLsa
// @Description: 名称LSA
//
type NameLsa struct {
encoding.SelfEncodingBase
LsaBase
@@ -23,19 +27,23 @@ type NameLsa struct {
//
// innerNameLsa
// @Description: 转json所用的中间结构体
// @Description: 内置结构体之:名称LSA
//
type innerNameLsa struct {
LsaTypeInt int
LsaOriginRouter string
LsaTypeInt int
LsaOriginRouter string
LsaSequenceNumber uint64
LsaExpirationTime uint64
NamePrefixList []innerNamePrefixInfo
NamePrefixList []innerNamePrefixInfo
}
//
// innerNamePrefixInfo
// @Description: 内置结构体之:名称前缀信息
//
type innerNamePrefixInfo struct {
NamePrefix string
Sources []string
Sources []string
}
//
@@ -45,19 +53,19 @@ type innerNamePrefixInfo struct {
// @return innerNameLsa
// @return error
//
func parseNameLsaToInner(nLsa *NameLsa) (innerNameLsa,error) {
func parseNameLsaToInner(nLsa *NameLsa) (innerNameLsa, error) {
innerNLSA := innerNameLsa{}
innerNLSA.LsaTypeInt = int(nLsa.GetType())
innerNLSA.LsaOriginRouter = nLsa.LsaOriginRouterIdentifier.ToUri()
innerNLSA.LsaSequenceNumber = nLsa.GetSeqNo()
innerNLSA.LsaExpirationTime = nLsa.GetExpirationTime()
for i:=0;i<len(nLsa.lsaNamePrefixs);i++{
for i := 0; i < len(nLsa.lsaNamePrefixs); i++ {
info := innerNamePrefixInfo{}
info.Sources = nLsa.lsaNamePrefixs[i].Sources
info.NamePrefix = nLsa.lsaNamePrefixs[i].NamePrefix.ToUri()
innerNLSA.NamePrefixList = append(innerNLSA.NamePrefixList, info)
}
return innerNLSA,nil
return innerNLSA, nil
}
//
@@ -67,37 +75,44 @@ func parseNameLsaToInner(nLsa *NameLsa) (innerNameLsa,error) {
// @param nlsa
// @return error
//
func parseInnerToNameLsa(inner *innerNameLsa,nlsa *NameLsa) error {
routerIdent,err := component.CreateIdentifierByString(inner.LsaOriginRouter)
if err!=nil{
func parseInnerToNameLsa(inner *innerNameLsa, nlsa *NameLsa) error {
routerIdent, err := component.CreateIdentifierByString(inner.LsaOriginRouter)
if err != nil {
return err
}
nlsa.SetOriginRouter(routerIdent)
nlsa.SetSeqNo(inner.LsaSequenceNumber)
nlsa.SetExpirationTime(inner.LsaExpirationTime)
for i:=0;i<len(inner.NamePrefixList);i++{
for i := 0; i < len(inner.NamePrefixList); i++ {
realInfo := new(NameLsaNamePrefixInfo)
realInfo.Sources=inner.NamePrefixList[i].Sources
realInfo.NamePrefix,err = component.CreateIdentifierByString(
realInfo.Sources = inner.NamePrefixList[i].Sources
realInfo.NamePrefix, err = component.CreateIdentifierByString(
inner.NamePrefixList[i].NamePrefix)
if err!=nil{
if err != nil {
return err
}
nlsa.lsaNamePrefixs = append(nlsa.lsaNamePrefixs,realInfo)
nlsa.lsaNamePrefixs = append(nlsa.lsaNamePrefixs, realInfo)
}
return nil
}
//
// LoadFromJsonString
// @Description: 从Json字符串中加载名称LSA
// @receiver n
// @param jsonBytes
// @return error
//
func (n *NameLsa) LoadFromJsonString(jsonBytes []byte) error {
// 转中间结构体
inner := innerNameLsa{}
err := json.Unmarshal(jsonBytes,&inner)
if err!= nil{
err := json.Unmarshal(jsonBytes, &inner)
if err != nil {
return err
}
// 转实际结构体
err = parseInnerToNameLsa(&inner,n)
if err!= nil{
err = parseInnerToNameLsa(&inner, n)
if err != nil {
return err
}
@@ -111,16 +126,16 @@ func (n *NameLsa) LoadFromJsonString(jsonBytes []byte) error {
// @return []byte
// @return error
//
func (n *NameLsa) GetJsonString() ([]byte,error) {
innerNameLsa,err := parseNameLsaToInner(n)
if err!= nil {
func (n *NameLsa) GetJsonString() ([]byte, error) {
innerNameLsa, err := parseNameLsaToInner(n)
if err != nil {
return nil, err
}
b,err := json.Marshal(innerNameLsa)
if err!= nil {
b, err := json.Marshal(innerNameLsa)
if err != nil {
return nil, err
}
return b,nil
return b, nil
}
//
@@ -149,7 +164,7 @@ func (n *NameLsa) GetNamePrefixList() []*NameLsaNamePrefixInfo {
// @receiver n
// @param info
//
func (n *NameLsa) AddNamePrefixInfo(info *NameLsaNamePrefixInfo) {
func (n *NameLsa) AddNamePrefixInfo(info *NameLsaNamePrefixInfo) {
n.NameLsaNamePrefixList.InsertNamePrefixInfo(info)
}
@@ -176,35 +191,35 @@ func (n *NameLsa) ToString() string {
// @return int
// @return error
//
func (n *NameLsa) WireEncode(encoder *encoding.Encoder) (int,error) {
func (n *NameLsa) WireEncode(encoder *encoding.Encoder) (int, error) {
totalLength := 0
// TLV-Value
tmpLen,err := n.NameLsaNamePrefixList.WireEncode(encoder)
tmpLen, err := n.NameLsaNamePrefixList.WireEncode(encoder)
if err != nil {
return 0, err
}
totalLength+=tmpLen
tmpLen,err = n.LsaBase.WireEncode(encoder)
totalLength += tmpLen
tmpLen, err = n.LsaBase.WireEncode(encoder)
if err != nil {
return 0, err
}
totalLength+=tmpLen
totalLength += tmpLen
// TLV-Length
tmpLen,err = encoder.PrependVarNumber(encoding.VlInt(totalLength))
tmpLen, err = encoder.PrependVarNumber(encoding.VlInt(totalLength))
if err != nil {
return 0, err
}
totalLength += tmpLen
// TLV-Type
tmpLen, err = encoder.PrependVarNumber(extensions.TlvMlsrLsaNamePrefix)
tmpLen, err = encoder.PrependVarNumber(extensions.TlvMlsrLsaName)
if err != nil {
return 0, err
}
totalLength += tmpLen
return totalLength,nil
return totalLength, nil
}
//
@@ -216,7 +231,7 @@ func (n *NameLsa) WireEncode(encoder *encoding.Encoder) (int,error) {
//
func (n *NameLsa) WireDecode(block *encoding.Block) error {
// 检查 TLV-TYPE 是否正确
if err := encoding.ExpectType(block.GetType(), extensions.TlvMlsrLsaNamePrefix); err != nil {
if err := encoding.ExpectType(block.GetType(), extensions.TlvMlsrLsaName); err != nil {
return err
}
@@ -226,17 +241,17 @@ func (n *NameLsa) WireDecode(block *encoding.Block) error {
}
// 提取参数
for _, parameter := range block.GetSubElements(){
for _, parameter := range block.GetSubElements() {
switch parameter.GetType() {
case extensions.TlvMlsrLsaBase:
if err:= n.LsaBase.WireDecode(parameter); err != nil {
if err := n.LsaBase.WireDecode(parameter); err != nil {
return err
}
case extensions.TlvMlsrNameLsaNamePrefixList:
if err:= n.NameLsaNamePrefixList.WireDecode(parameter); err != nil {
if err := n.NameLsaNamePrefixList.WireDecode(parameter); err != nil {
return err
}
}
}
return nil
}
}
+36 -9
View File
@@ -22,6 +22,33 @@ type NameLsaNamePrefixList struct {
lsaNamePrefixs LsaNamePrefixContainer
}
//
// GetNamePrefixList
// @Description: 获取名称前缀列表
// @receiver l
// @return []*NameLsaNamePrefixInfo
//
func (l *NameLsaNamePrefixList) GetNamePrefixList() []*NameLsaNamePrefixInfo {
return l.lsaNamePrefixs
}
//
// InsertNamePrefixList
// @Description: 插入一张名称前缀信息列表
// @receiver l
// @param list
// @return bool 如果成功插入任何一条信息,即返回true
//
func (l *NameLsaNamePrefixList) InsertNamePrefixList(list []*NameLsaNamePrefixInfo) bool {
b := false
for i := 0; i < len(list); i++ {
if l.InsertNamePrefixInfo(list[i]) {
b = true
}
}
return b
}
//
// GetIndex
// @Description: 获取指定名称前缀在列表中的索引值
@@ -46,11 +73,11 @@ func (l *NameLsaNamePrefixList) GetIndex(namePrefix *component.Identifier) int {
// @return bool 只要能插入Info中的任何一个source,即返回true
//
func (l *NameLsaNamePrefixList) InsertNamePrefixInfo(info *NameLsaNamePrefixInfo) bool {
b:=false
for i:=0;i<len(info.Sources);i++{
tmpBool:=l.Insert(info.NamePrefix,info.Sources[i])
if tmpBool{
b=true
b := false
for i := 0; i < len(info.Sources); i++ {
tmpBool := l.Insert(info.NamePrefix, info.Sources[i])
if tmpBool {
b = true
}
}
return b
@@ -179,10 +206,10 @@ func (l *NameLsaNamePrefixList) IsEqualTo(list *NameLsaNamePrefixList) bool {
//
func (l *NameLsaNamePrefixList) ToString() string {
var res = "{ "
for i:=0;i<len(l.lsaNamePrefixs);i++{
res+=l.lsaNamePrefixs[i].ToString()
if i<(len(l.lsaNamePrefixs)-1){
res+="; "
for i := 0; i < len(l.lsaNamePrefixs); i++ {
res += l.lsaNamePrefixs[i].ToString()
if i < (len(l.lsaNamePrefixs) - 1) {
res += "; "
}
}
res += " }"
+3 -1
View File
@@ -8,6 +8,8 @@
package LsaContainer
import "mlsr/lsdb/LsaContainer/buntdb"
//
// LsaContainer
// @Description:
@@ -15,5 +17,5 @@ package LsaContainer
// 2. 其它索引键:Type()
//
type LsaContainer struct {
buntdb.LsaContainer_BuntDB
}
+141 -46
View File
@@ -1,9 +1,9 @@
// Package buntdb
// @Author: Wang Feng
// @Description:
// todo: 需要注意的是,根据对NLSR源代码的阅读,可以看出其通过originRouterName和lsaType可唯一确定一个LSA。
// todo 这就意味着,序列号只区分同一路由器同一类型LSA的新和旧,并不是如邻接LSA分成多个LSA进行传播。
// todo MLSR可参考其设计,也可通过originRouter和序列号来确定唯一LSA。
// 需要注意的是,根据对NLSR源代码的阅读,可以看出其通过originRouterName和lsaType可唯一确定一个LSA。
// 这就意味着,序列号只区分同一路由器同一类型LSA的新和旧,并不是分成多个LSA进行传播。
// MLSR参考其设计,同一路由器在另一路由器的LSDB中,仅保留最新序列号的两个LSA:邻接LSA、名称LSA。
// @Version: 0.1.0
// @Date: 2022/4/6 17:49
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
@@ -14,6 +14,7 @@ package buntdb
import (
"errors"
"github.com/tidwall/buntdb"
common2 "minlib/common"
"minlib/component"
"mlsr/lsa"
"strconv"
@@ -48,17 +49,24 @@ type LsaContainer_BuntDB struct {
// @return error 如果成功初始化,则返回nil
//
func (bdb *LsaContainer_BuntDB) Init() error {
// 打开db
// 1. 打开db
db, err := buntdb.Open(":memory:")
if err != nil {
common2.LogError("buntdb open error")
return err
}
bdb.db = db
// 建立基于LsaType的索引,便于根据type进行数据库快速检索
common2.LogInfo("buntdb open success")
// 2. 建立基于LsaType的索引,便于根据type进行数据库快速检索
err = db.CreateIndex("LsaType", "*", buntdb.IndexJSON("LsaTypeInt"))
if err != nil {
common2.LogError("buntdb create index error")
return err
}
common2.LogInfo("buntdb create index success")
// 3. 赋值
bdb.db = db
return nil
}
@@ -109,16 +117,71 @@ func getKeyFromNameAndType(routerIdentifier *component.Identifier,
// @return lsa.ILsa
// @return error
//
func newLsa(lsaType lsa.LsaType) (lsa.ILsa,error) {
func newLsa(lsaType lsa.LsaType) (lsa.ILsa, error) {
if lsaType == lsa.LsaADJACENCYType {
return new(lsa.AdjLsa),nil
}else if lsaType == lsa.LsaNAMEType{
return new(lsa.NameLsa),nil
}else {
return nil,errors.New("invalid lsa type")
return new(lsa.AdjLsa), nil
} else if lsaType == lsa.LsaNAMEType {
return new(lsa.NameLsa), nil
} else {
return nil, errors.New("invalid lsa type")
}
}
//
// Exists
// @Description: 判断某个lsa是否在内存数据库里
// @receiver bdb
// @param lsa
// @return bool
//
func (bdb *LsaContainer_BuntDB) Exists(lsa lsa.ILsa) bool {
errRes := bdb.db.View(func(tx *buntdb.Tx) error {
// 获取key
key := getKeyFromNameAndType(lsa.GetOriginRouter(), lsa.GetType())
// 获取value
_, err := tx.Get(key)
if err != nil {
common2.LogDebug("buntdb Exists get key no found, because of ", err.Error())
return err
}
return nil
})
if errRes == nil {
return true
}
return false
}
//
// ExistsRouterNameAndType
// @Description: 判断是否存在某个lsa
// @receiver bdb
// @param routerIdentifier
// @param lsaType
// @return bool
//
func (bdb *LsaContainer_BuntDB) ExistsRouterNameAndType(routerIdentifier *component.Identifier, lsaType lsa.LsaType) bool {
errRes := bdb.db.View(func(tx *buntdb.Tx) error {
// 获取key
key := getKeyFromNameAndType(routerIdentifier, lsaType)
// 获取value
_, err := tx.Get(key)
if err != nil {
common2.LogDebug("buntdb ExistsRouterNameAndType get key no found, because of ", err.Error())
return err
}
return nil
})
if errRes == nil {
return true
}
return false
}
//
// Emplace
// @Description: 安装一个lsa到LsaContainer
@@ -127,8 +190,9 @@ func newLsa(lsaType lsa.LsaType) (lsa.ILsa,error) {
//
func (bdb *LsaContainer_BuntDB) Emplace(lsa lsa.ILsa) error {
// 将lsa转为json字符串
jsonBytes,err := lsa.GetJsonString()
if err!= nil{
jsonBytes, err := lsa.GetJsonString()
if err != nil {
common2.LogError("buntdb emplace get json error, because of ", err.Error())
return err
}
@@ -137,14 +201,15 @@ func (bdb *LsaContainer_BuntDB) Emplace(lsa lsa.ILsa) error {
// 将转为的json存入键值对数据库
err = bdb.db.Update(func(tx *buntdb.Tx) error {
_, _, err := tx.Set(key, string(jsonBytes), nil)
if err != nil {
return err
_, _, err2 := tx.Set(key, string(jsonBytes), nil)
if err2 != nil {
common2.LogError("buntdb emplace set value error, because of ", err2.Error())
return err2
}
return nil
})
if err!= nil{
if err != nil {
return err
}
@@ -153,13 +218,35 @@ func (bdb *LsaContainer_BuntDB) Emplace(lsa lsa.ILsa) error {
//
// Erase
// @Description: 删除一个lsa:根据routerIdentifier和lsaType
// @Description: 删除一个lsa
// @receiver bdb
// @param lsa
//
func (bdb *LsaContainer_BuntDB) EraseLsa(lsa lsa.ILsa) error {
key := getKeyFromLsa(lsa)
return bdb.EraseLsaByKey(key)
err := bdb.EraseLsaByKey(key)
if err != nil {
common2.LogError("buntdb EraseLsa error, because of ", err.Error())
}
return err
}
//
// EraseLsaByNameAndType
// @Description: 删除一个lsa:根据routerIdentifier和lsaType
// @receiver bdb
// @param routerIdentifier
// @param lsaType
// @return error
//
func (bdb *LsaContainer_BuntDB) EraseLsaByNameAndType(routerIdentifier *component.Identifier,
lsaType lsa.LsaType) error {
key := getKeyFromNameAndType(routerIdentifier, lsaType)
err := bdb.EraseLsaByKey(key)
if err != nil {
common2.LogError("buntdb EraseLsa error, because of ", err.Error())
}
return err
}
//
@@ -172,8 +259,9 @@ func (bdb *LsaContainer_BuntDB) EraseLsa(lsa lsa.ILsa) error {
func (bdb *LsaContainer_BuntDB) EraseLsaByKey(key string) error {
errRes := bdb.db.Update(func(tx *buntdb.Tx) error {
_, err := tx.Delete(key)
//fmt.Println("删除的返回值是啥: ",ss) // 返回值是删除的value
// 返回值是删除的value
if err != nil {
common2.LogError("buntdb EraseLsaByKey delete error, because of ", err.Error())
return err
}
@@ -193,31 +281,34 @@ func (bdb *LsaContainer_BuntDB) EraseLsaByKey(key string) error {
// @return error
//
func (bdb *LsaContainer_BuntDB) GetLSAByNameAndType(routerIdentifier *component.Identifier,
lsaType lsa.LsaType) (lsa.ILsa,error) {
glsa,err := newLsa(lsaType) // 要查找的lsa
if err!= nil{
lsaType lsa.LsaType) (lsa.ILsa, error) {
glsa, err := newLsa(lsaType) // 要查找的lsa
if err != nil {
common2.LogError("buntdb GetLSAByNameAndType new lsa error, because of ", err.Error())
return nil, err
}
errRes := bdb.db.View(func(tx *buntdb.Tx) error {
// 获取key
key := getKeyFromNameAndType(routerIdentifier,lsaType)
key := getKeyFromNameAndType(routerIdentifier, lsaType)
// 获取value
value, err := tx.Get(key)
if err != nil {
return err
value, err2 := tx.Get(key)
if err2 != nil {
common2.LogError("buntdb GetLSAByNameAndType get key error, because of ", err2.Error())
return err2
}
// 将value转为lsa
err = glsa.LoadFromJsonString([]byte(value))
if err != nil {
return err
err2 = glsa.LoadFromJsonString([]byte(value))
if err2 != nil {
common2.LogError("buntdb GetLSAByNameAndType load from json error, because of ", err2.Error())
return err2
}
return nil
})
return glsa,errRes
return glsa, errRes
}
//
@@ -228,33 +319,36 @@ func (bdb *LsaContainer_BuntDB) GetLSAByNameAndType(routerIdentifier *component.
// @return []lsa.ILsa
// @return error
//
func (bdb *LsaContainer_BuntDB) GetLSAsByType(lsaType lsa.LsaType) ([]lsa.ILsa,error) {
func (bdb *LsaContainer_BuntDB) GetLSAsByType(lsaType lsa.LsaType) ([]lsa.ILsa, error) {
var lsas []lsa.ILsa
equalString := `{"LsaTypeInt":`+ strconv.Itoa(int(lsaType)) +`}` // 查找的类型
equalString := `{"LsaTypeInt":` + strconv.Itoa(int(lsaType)) + `}` // 查找的类型
errRes := bdb.db.View(func(tx *buntdb.Tx) error {
// 查找类型是lsaType的所有Lsa
err := tx.AscendEqual("LsaType", equalString, func(key, value string) bool {
// 构建一个Lsa
cacheLsa,err1 := newLsa(lsaType)
if err1!= nil{
cacheLsa, err1 := newLsa(lsaType)
if err1 != nil {
common2.LogError("buntdb GetLSAsByType new lsa error, because of ", err1.Error())
return false
}
// 将查找到的lsajson放入该lsa
err1 = cacheLsa.LoadFromJsonString([]byte(value))
if err1!= nil{
if err1 != nil {
common2.LogError("buntdb GetLSAsByType load from json error, because of ", err1.Error())
return false
}
// 将该lsa放入数组
lsas = append(lsas,cacheLsa)
lsas = append(lsas, cacheLsa)
return true
})
if err!=nil {
if err != nil {
common2.LogError("buntdb GetLSAsByType AscendEqual error, because of ", err.Error())
return err
}
return nil
})
return lsas,errRes
return lsas, errRes
}
//
@@ -265,21 +359,22 @@ func (bdb *LsaContainer_BuntDB) GetLSAsByType(lsaType lsa.LsaType) ([]lsa.ILsa,e
// @return []string
// @return error
//
func (bdb *LsaContainer_BuntDB) GetLSAKeysByType(lsaType lsa.LsaType) ([]string,error) {
func (bdb *LsaContainer_BuntDB) GetLSAKeysByType(lsaType lsa.LsaType) ([]string, error) {
var keys []string
equalString := `{"LsaTypeInt":`+ strconv.Itoa(int(lsaType)) +`}` // 查找的类型
equalString := `{"LsaTypeInt":` + strconv.Itoa(int(lsaType)) + `}` // 查找的类型
errRes := bdb.db.View(func(tx *buntdb.Tx) error {
// 查找类型是lsaType的所有Lsa
err := tx.AscendEqual("LsaType", equalString, func(key, value string) bool {
// 将该lsa放入数组
keys = append(keys,key)
keys = append(keys, key)
return true
})
if err!=nil {
if err != nil {
common2.LogError("buntdb GetLSAKeysByType AscendEqual error, because of ", err.Error())
return err
}
return nil
})
return keys,errRes
}
return keys, errRes
}
@@ -9,89 +9,286 @@
package buntdb
import (
"fmt"
"log"
common2 "minlib/common"
"minlib/component"
"mlsr/lsa"
"testing"
)
//
// TestLsaContainer_BuntDB_Emplace
// @Description:
// TestLsaContainer_BuntDB_Init
// @Description: 测试buntdb初始化
// @param t
//
func TestLsaContainer_BuntDB_Emplace_Get_Erase(t *testing.T) {
func TestLsaContainer_BuntDB_Init(t *testing.T) {
// 构造LsaContainer
lsaContainer := new(LsaContainer_BuntDB)
err := lsaContainer.Init()
if err != nil {
common2.LogInfo("lsaContainer创建失败:", err.Error())
}
}
//
// TestLsaContainer_BuntDB_Emplace
// @Description: 测试插入
// @param t
//
func TestLsaContainer_BuntDB_Emplace(t *testing.T) {
// 构造NameLsa
base := new(lsa.NameLsa)
base.SetLsaExpirationTime(2000)
base.SetLsaSequenceNumber(1234)
base.LsaOriginRouterIdentifier,_ = component.CreateIdentifierByString("/min/pku")
ident,_ := component.CreateIdentifierByString("/pku/routerfucker")
base.Insert(ident,"/bind")
base.Insert(ident,"/wechat")
ident,_ = component.CreateIdentifierByString("/pku/router")
base.Insert(ident,"/qq")
fmt.Println("ToString: "+base.ToString())
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/pku")
ident, _ := component.CreateIdentifierByString("/pku/routerfucker")
base.Insert(ident, "/bind")
base.Insert(ident, "/wechat")
ident, _ = component.CreateIdentifierByString("/pku/router")
base.Insert(ident, "/qq")
common2.LogInfo("ToString: " + base.ToString())
// 构造LsaContainer
lsaContainer := new(LsaContainer_BuntDB)
err := lsaContainer.Init()
if err!=nil{
log.Fatal("lsaContainer创建失败:",err.Error())
if err != nil {
common2.LogInfo("lsaContainer创建失败:", err.Error())
}
// 将NameLsa插入lsaContainer
err = lsaContainer.Emplace(base)
if err!=nil{
log.Fatal("lsaContainer存入lsa失败:",err.Error())
if err != nil {
common2.LogInfo("lsaContainer存入名称lsa失败:", err.Error())
}
fmt.Println("lsaContainer存入lsa成功")
common2.LogInfo("lsaContainer存入名称lsa成功")
}
// 获取lsa
origin,_ := component.CreateIdentifierByString("/min/pku")
lsa,err := lsaContainer.GetLSAByNameAndType(origin,2) // 2表示namelsa
if err!=nil{
log.Fatal("lsaContainer取出lsa失败:",err.Error())
//
// TestLsaContainer_BuntDB_FindLsa
// @Description: 测试查找lsa
// @param t
//
func TestLsaContainer_BuntDB_FindLsa(t *testing.T) {
// 构造NameLsa
base := new(lsa.NameLsa)
base.SetLsaExpirationTime(2000)
base.SetLsaSequenceNumber(1234)
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/pku")
ident, _ := component.CreateIdentifierByString("/pku/routerfucker")
base.Insert(ident, "/bind")
base.Insert(ident, "/wechat")
ident, _ = component.CreateIdentifierByString("/pku/router")
base.Insert(ident, "/qq")
common2.LogInfo("ToString: " + base.ToString())
// 构造LsaContainer
lsaContainer := new(LsaContainer_BuntDB)
err := lsaContainer.Init()
if err != nil {
common2.LogInfo("lsaContainer创建失败:", err.Error())
}
ss,_ := lsa.GetJsonString()
fmt.Println("lsa取出来:",string(ss))
// 再放入一个namelsa
base.LsaOriginRouterIdentifier,_ = component.CreateIdentifierByString("/min/pku111")
// 将NameLsa插入lsaContainer
err = lsaContainer.Emplace(base)
if err!=nil{
log.Fatal("lsaContainer存入lsa失败:",err.Error())
if err != nil {
common2.LogInfo("lsaContainer存入名称lsa失败:", err.Error())
}
fmt.Println("lsaContainer存入lsa成功")
common2.LogInfo("lsaContainer存入名称lsa成功")
// 查看某个lsa是否存在
b := lsaContainer.Exists(base)
common2.LogInfo("是否存在已插入的lsa:", b)
b = lsaContainer.ExistsRouterNameAndType(base.GetOriginRouter(), base.GetType())
common2.LogInfo("是否存在已插入的lsa:", b)
// 构造一个新Lsa
idenNew, _ := component.CreateIdentifierByString("/min/thu")
namelsa := new(lsa.NameLsa)
namelsa.SetOriginRouter(idenNew)
// 查看是否存在
b = lsaContainer.Exists(namelsa)
common2.LogInfo("是否存在尚未插入的lsa:", b)
b = lsaContainer.ExistsRouterNameAndType(idenNew, namelsa.GetType())
common2.LogInfo("是否存在尚未插入的lsa:", b)
}
//
// TestLsaContainer_BuntDB_Emplace_Get_Erase_Adj_Lsa
// @Description: 测试对邻接LSA进行增删改查
// @param t
//
func TestLsaContainer_BuntDB_Emplace_Get_Erase_Adj_Lsa(t *testing.T) {
// 构造AdjLsa
base := new(lsa.AdjLsa)
base.SetLsaExpirationTime(2000)
base.SetLsaSequenceNumber(1234)
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/pku")
// 构造邻接信息部分
// 先构造一个info
linkCost := lsa.AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := lsa.AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := lsa.AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := lsa.NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
base.Insert(adjInfo)
// 再加第二个info
iden2, _ := component.CreateIdentifierByString("/pku/router2")
adjInfo2 := lsa.NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden2, 111, 0)
base.Insert(adjInfo2)
// 构造LsaContainer
lsaContainer := new(LsaContainer_BuntDB)
err := lsaContainer.Init()
if err != nil {
common2.LogInfo("lsaContainer创建失败:", err.Error())
}
// 将AdjLsa插入lsaContainer
err = lsaContainer.Emplace(base)
if err != nil {
common2.LogInfo("lsaContainer存入邻接lsa失败:", err.Error())
}
common2.LogInfo("lsaContainer存入邻接lsa成功")
// 尝试获取lsa
origin, _ := component.CreateIdentifierByString("/min/pku")
lsa, err := lsaContainer.GetLSAByNameAndType(origin, 2) // 2表示namelsa
if err != nil {
common2.LogInfo("lsaContainer取出名称lsa失败:", err.Error())
} else {
ss, _ := lsa.GetJsonString()
common2.LogInfo("lsa取出来:", string(ss))
}
// 尝试获取邻接LSA
lsa, err = lsaContainer.GetLSAByNameAndType(origin, 1)
if err != nil {
common2.LogInfo("lsaContainer取出邻接lsa失败:", err.Error())
} else {
ss, _ := lsa.GetJsonString()
common2.LogInfo("lsa取出来:", string(ss))
}
// 再放入一个不同来源路由的邻接lsa
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/thu")
err = lsaContainer.Emplace(base)
if err != nil {
common2.LogInfo("lsaContainer存入邻接lsa失败:", err.Error())
}
common2.LogInfo("lsaContainer存入邻接lsa成功")
// 取出所有namelsa
lsas,_ := lsaContainer.GetLSAsByType(2)
fmt.Print("取出所有namelsa:")
for i:=0;i<len(lsas);i++ {
fmt.Println(lsas[i].ToString())
lsas, _ := lsaContainer.GetLSAsByType(2)
common2.LogInfo("取出所有namelsa:")
for i := 0; i < len(lsas); i++ {
common2.LogInfo(lsas[i].ToString())
}
fmt.Println("")
common2.LogInfo("")
lsas,_ = lsaContainer.GetLSAsByType(1)
fmt.Print("取出所有adjlsa:")
for i:=0;i<len(lsas);i++ {
fmt.Println(lsas[i].ToString())
// 取出所有邻接lsa
lsas, _ = lsaContainer.GetLSAsByType(1)
common2.LogInfo("取出所有adjlsa:")
for i := 0; i < len(lsas); i++ {
common2.LogInfo(lsas[i].ToString())
}
fmt.Println("")
common2.LogInfo("")
// 取出所有Namelsa的key
keys,_ := lsaContainer.GetLSAKeysByType(2)
fmt.Print("取出所有namelsa的key:",keys)
fmt.Println("")
keys, _ := lsaContainer.GetLSAKeysByType(2)
common2.LogInfo("取出所有namelsa的key:", keys)
common2.LogInfo("")
// 取出所有邻接lsa的key
keys, _ = lsaContainer.GetLSAKeysByType(1)
common2.LogInfo("取出所有邻接lsa的key:", keys)
common2.LogInfo("")
// 删除base2
_ = lsaContainer.EraseLsa(base)
lsas,_ = lsaContainer.GetLSAsByType(2)
fmt.Print("删除一个后,取出所有namelsa:")
for i:=0;i<len(lsas);i++ {
fmt.Println(lsas[i].ToString())
lsas, _ = lsaContainer.GetLSAsByType(1)
common2.LogInfo("删除一个后,取出所有邻接LSA:")
for i := 0; i < len(lsas); i++ {
common2.LogInfo(lsas[i].ToString())
}
fmt.Println("")
common2.LogInfo("")
}
//
// TestLsaContainer_BuntDB_Emplace
// @Description: 测试对名称LSA进行增删改查
// @param t
//
func TestLsaContainer_BuntDB_Emplace_Get_Erase_Name_Lsa(t *testing.T) {
// 构造NameLsa
base := new(lsa.NameLsa)
base.SetLsaExpirationTime(2000)
base.SetLsaSequenceNumber(1234)
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/pku")
ident, _ := component.CreateIdentifierByString("/pku/routerfucker")
base.Insert(ident, "/bind")
base.Insert(ident, "/wechat")
ident, _ = component.CreateIdentifierByString("/pku/router")
base.Insert(ident, "/qq")
common2.LogInfo("ToString: " + base.ToString())
// 构造LsaContainer
lsaContainer := new(LsaContainer_BuntDB)
err := lsaContainer.Init()
if err != nil {
common2.LogInfo("lsaContainer创建失败:", err.Error())
}
// 将NameLsa插入lsaContainer
err = lsaContainer.Emplace(base)
if err != nil {
common2.LogInfo("lsaContainer存入名称lsa失败:", err.Error())
}
common2.LogInfo("lsaContainer存入名称lsa成功")
// 获取lsa
origin, _ := component.CreateIdentifierByString("/min/pku")
lsa, err := lsaContainer.GetLSAByNameAndType(origin, 2) // 2表示namelsa
if err != nil {
common2.LogInfo("lsaContainer取出名称lsa失败:", err.Error())
}
ss, _ := lsa.GetJsonString()
common2.LogInfo("lsa取出来:", string(ss))
// 再放入一个namelsa
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/pku111")
err = lsaContainer.Emplace(base)
if err != nil {
common2.LogInfo("lsaContainer存入名称lsa失败:", err.Error())
}
common2.LogInfo("lsaContainer存入名称lsa成功")
// 取出所有namelsa
lsas, _ := lsaContainer.GetLSAsByType(2)
common2.LogInfo("取出所有namelsa:")
for i := 0; i < len(lsas); i++ {
common2.LogInfo(lsas[i].ToString())
}
common2.LogInfo("")
lsas, _ = lsaContainer.GetLSAsByType(1)
common2.LogInfo("取出所有adjlsa:")
for i := 0; i < len(lsas); i++ {
common2.LogInfo(lsas[i].ToString())
}
common2.LogInfo("")
// 取出所有Namelsa的key
keys, _ := lsaContainer.GetLSAKeysByType(2)
common2.LogInfo("取出所有namelsa的key:", keys)
common2.LogInfo("")
// 删除base2
_ = lsaContainer.EraseLsa(base)
lsas, _ = lsaContainer.GetLSAsByType(2)
common2.LogInfo("删除一个后,取出所有namelsa:")
for i := 0; i < len(lsas); i++ {
common2.LogInfo(lsas[i].ToString())
}
common2.LogInfo("")
}
+340 -49
View File
@@ -10,7 +10,9 @@ package lsdb
import (
"bytes"
common2 "minlib/common"
"minlib/component"
"minlib/logicface"
"minlib/packet"
"mlsr/common"
"mlsr/communication"
@@ -19,13 +21,17 @@ import (
"time"
)
type LsdbUpdate int
// Lsdb更新状态
const (
INSTALLED = 0 // 已安装
UPDATED = 1 // 已更新
REMOVED = -1 // 已移除
INSTALLED LsdbUpdate = 0 // 安装
UPDATED LsdbUpdate = 1 // 更新
REMOVED LsdbUpdate = -1 // 移除
)
const GRACE_PERIOD = 10 * time.Second // 超期宽限期。LSA比设定时间晚几秒钟被删除,以避免信息过早失效。
type Lsdb struct {
// 配置参数
mlsrConfig *common.MlsrConfig
@@ -34,36 +40,91 @@ type Lsdb struct {
sync *communication.SyncLogicHandler
// LSA容器
lsaContainer *LsaContainer.LsaContainer
LsaContainer.LsaContainer
lsaRefreshTime *time.Duration // lsa刷新时间
adjLsaBuildInterval *time.Duration // 邻接LSA构建间隔
thisRouterPrefix *component.Identifier // 当前路由器的标识
lsaRefreshTime time.Duration // lsa刷新时间
adjLsaBuildInterval time.Duration // 邻接LSA构建间隔
thisRouterPrefix *component.Identifier // 当前路由器的标识
// 任务调度器
scheduler *Scheduler
scheduler *MlsrScheduler
// LogicFace接口
face *logicface.LogicFace
// 将LSA的名称从sync映射到其已知的最高序列号;
// 用于阻止MLSR尝试获取过时的LSA
highestSeqNo map[*component.Identifier] uint64
highestSeqNo map[*component.Identifier]uint64
// 不同类型lsa的序列号管理器
sequencingManager *SequencingManager
isBuildAdjLsaScheduled bool // 是否安排构建邻接LSA
adjBuildCount uint64 // 邻接LSA的构建的统计数目
isBuildAdjLsaScheduled bool // 是否安排构建邻接LSA
adjBuildCount uint64 // 邻接LSA的构建的统计数目
}
func (l *Lsdb) Init(mc *common.MlsrConfig, ms *MlsrScheduler,
_face *logicface.LogicFace) {
// 配置项
l.mlsrConfig = mc
// 调度器
l.scheduler = ms
// 逻辑face
l.face = _face
// 序列号管理器
l.sequencingManager = GetInstance()
// 存储器
err := l.LsaContainer.Init()
if err != nil {
common2.LogFatal("lsdb.LsaContainer init error, ", err.Error())
}
// todo 构造sync
// lsa刷新时间
l.lsaRefreshTime = l.mlsrConfig.GetLsaRefreshTime()
// 邻接lsa构建间隔
l.adjLsaBuildInterval = l.mlsrConfig.GetAdjLsaBuildInterval()
// 本机路由前缀
l.thisRouterPrefix = l.mlsrConfig.GetRouterPrefix()
// 是否已经安排邻接LSA的构建
l.isBuildAdjLsaScheduled = false
// 邻接LSA构建次数统计
l.adjBuildCount = 0
// 在LSDB初始化之前,对配置文件中的本机路由器进行拉式前缀注册(即监听该前缀)
// todo: 为了在Windows上单独测试,暂时注释掉face注册前缀这一步骤
//lsaPrefix := l.mlsrConfig.GetLsaPrefix()
//err := l.face.RegisterPullIdentifier(lsaPrefix, 2000)
//if err != nil {
// common2.LogFatal("Lsdb Init error, because of face register, ", err.Error())
//}
// 构建并安装自己的名称LSA
l.BuildAndInstallOwnNameLsa()
}
//
// DoesLsaExist
// @Description: 返回LSDB是否存在某些LSA的查询结果
// @Description: 返回LSDB是否存在某个LSA的查询结果
// @receiver l
// @param routerIdentifier
// @param lsaType
// @return bool
//
func (l *Lsdb) DoesLsaExist(routerIdentifier *component.Identifier,lsaType int) bool {
panic("implement me")
func (l *Lsdb) DoesLsaNameExist(routerIdentifier *component.Identifier, lsaType lsa.LsaType) bool {
return l.ExistsRouterNameAndType(routerIdentifier, lsaType)
}
//
// DoesLsaExist
// @Description: 返回LSDB是否存在某个LSA的查询结果
// @receiver l
// @param lsa
// @return bool
//
func (l *Lsdb) DoesLsaExist(lsa lsa.ILsa) bool {
return l.Exists(lsa)
}
//
@@ -72,6 +133,20 @@ func (l *Lsdb) DoesLsaExist(routerIdentifier *component.Identifier,lsaType int)
// @receiver l
//
func (l *Lsdb) BuildAndInstallOwnNameLsa() {
// 根据配置文件,构造本机的名称LSA
nlsa := new(lsa.NameLsa)
nlsa.SetOriginRouter(l.thisRouterPrefix) // 源路由
nlsa.SetSeqNo(l.sequencingManager.GetNameLsaSeq() + 1) // 序列号
nlsa.SetLsaExpirationTime(l.getLsaExpirationTimePoint()) // 超期时间
nlsa.NameLsaNamePrefixList.InsertNamePrefixList(l.mlsrConfig.GetNamePrefixList()) // 名称前缀列表
// 刷新序列号管理器中的名称LSA序列号
l.sequencingManager.IncreaseNameLsaSeq()
// todo: 使用sync通知路由更新
// m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
// 安装lsa到LSDB
l.InstallLsa(nlsa)
}
//
@@ -80,7 +155,7 @@ func (l *Lsdb) BuildAndInstallOwnNameLsa() {
// @receiver l
//
func (l *Lsdb) BuildAndInstallOwnCoordinateLsa() {
// todo
// todo:坐标计算预留接口
}
//
@@ -88,12 +163,29 @@ func (l *Lsdb) BuildAndInstallOwnCoordinateLsa() {
// @Description: 安排LSA的构建
// @receiver l
//
func (l *Lsdb) ScheduleAdjLsaBuild() {
func (l *Lsdb) ScheduleAdjLsaBuild() {
// 计数
l.adjBuildCount++
// 日志记录
if l.isBuildAdjLsaScheduled {
common2.LogInfo("Rescheduling Adjacency LSA build in ", l.adjLsaBuildInterval)
} else {
common2.LogInfo("Scheduling Adjacency LSA build in ", l.adjLsaBuildInterval)
l.isBuildAdjLsaScheduled = true
}
// 安排构造邻接LSA
job, err := l.scheduler.ScheduleTaskAfterDuration(l.adjLsaBuildInterval, 1).Do(l.BuildAdjLsa)
job.LimitRunsTo(1)
l.scheduler.StartAsync()
if err != nil {
common2.LogError("Scheduling Adjacency LSA build error, ", err.Error())
}
}
//
// ProcessInterest
// @Description: 处理兴趣包。类似NDN的拉式传输。
// @Description:收到一个兴趣包,根据兴趣包名称,查找LSA并返回。
// 处理兴趣包。类似NDN的拉式传输。
// 在NLSR的设计中,由于对兴趣包进行了进一步的分段,因此有以下两种兴趣包:
//* 1) 需要从segment fetcher中查找的兴趣包:
//* /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>
@@ -102,10 +194,14 @@ func (l *Lsdb) ScheduleAdjLsaBuild() {
// @receiver l
// @param interest
//
func (l *Lsdb) ProcessInterest(interest *packet.Interest) {
func (l *Lsdb) ProcessInterest(interest *packet.Interest) {
}
func (l *Lsdb) ProcessGPPkt(pkt *packet.GPPkt) {
func (l *Lsdb) processInterestForLsa(interest *packet.Interest,
originRouterIdentifier *component.Identifier, lsaType lsa.LsaType, seqNo uint64) {
}
func (l *Lsdb) ProcessGPPkt(pkt *packet.GPPkt) {
}
//
@@ -138,12 +234,15 @@ func (l *Lsdb) GetSync() *communication.SyncLogicHandler {
//
func (l *Lsdb) FindLsa(routerIdentifier *component.Identifier,
lsaType lsa.LsaType) lsa.ILsa {
// todo
return &lsa.NameLsa{}
lsaGet, err := l.GetLSAByNameAndType(routerIdentifier, lsaType)
if err != nil {
lsaGet = nil
}
return lsaGet
}
//
// IsLsaNew
// isLsaNew
// @Description: 返回来自某个路由器的seq是否表示新的LSA。
// @receiver l
// @param routerIdentifier
@@ -151,23 +250,110 @@ func (l *Lsdb) FindLsa(routerIdentifier *component.Identifier,
// @param seqNo
// @return bool
//
func (l *Lsdb) IsLsaNew(routerIdentifier *component.Identifier,
lsaType lsa.LsaType,seqNo uint64) bool {
lsa := l.FindLsa(routerIdentifier,lsaType)
if lsa.GetSeqNo() >= seqNo{
return false
func (l *Lsdb) isLsaNew(routerIdentifier *component.Identifier,
lsaType lsa.LsaType, seqNo uint64) bool {
iLsa := l.FindLsa(routerIdentifier, lsaType)
// 没找到,说明是最新的
if iLsa == nil {
return true
}
return true
// 找到了,且LSDB中的该lsa序列号小于要查的lsa,说明是最新的
if iLsa.GetSeqNo() < seqNo {
return true
}
return false
}
func (l *Lsdb) InstallLsa(lsa lsa.ILsa) {
//
// IsLsaNew
// @Description: 返回来自某个路由器的seq是否表示新的LSA。
// @receiver l
// @param fLsa
// @return bool
//
func (l *Lsdb) IsLsaNew(fLsa lsa.ILsa) bool {
return l.isLsaNew(fLsa.GetOriginRouter(), fLsa.GetType(), fLsa.GetSeqNo())
}
func (l* Lsdb) RemoveLsa(routerIdentifier *component.Identifier,
//
// InstallLsa
// @Description: 将LSA安装到lsdb中
// @receiver l
// @param lsa
//
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 lsaInDb == 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())
}
}
//
// RemoveLsa
// @Description: 从LSDB中删除LSA
// @receiver l
// @param lsa
//
func (l *Lsdb) RemoveLsa(lsa lsa.ILsa) {
err := l.LsaContainer.EraseLsa(lsa)
if err != nil {
common2.LogError("")
return
}
common2.LogDebug("Removed LSA: ", lsa.ToString())
}
//
// RemoveLsaByNameAndType
// @Description: 删除lsa
// @receiver l
// @param routerIdentifier
// @param lsaType
//
func (l *Lsdb) RemoveLsaByNameAndType(routerIdentifier *component.Identifier,
lsaType lsa.LsaType) {
}
func (l* Lsdb) RemoveLsaByContainerIndex(index int) {
err := l.LsaContainer.EraseLsaByNameAndType(routerIdentifier, lsaType)
if err != nil {
common2.LogError("")
return
}
common2.LogDebug("Removed LSA: ", routerIdentifier.ToUri())
}
//
@@ -176,7 +362,43 @@ func (l* Lsdb) RemoveLsaByContainerIndex(index int) {
// 只有当路由器的所有邻居状态是已知的时,才可以构建它的邻接LSA。
// @receiver l
//
func (l *Lsdb) BuildAdjLsa() {
func (l *Lsdb) BuildAdjLsa() {
common2.LogDebug("buildAdjLsa called")
// 构建邻接lsa的任务启动,那么安排构建就变为false
l.isBuildAdjLsaScheduled = false
// 根据配置文件中邻接表的状态,执行不同的动作
if l.mlsrConfig.GetAdjacencys().IsAdjLsaBuildable(uint32(l.mlsrConfig.GetHelloRetries())) {
// 只有在有计划的情况下才执行adjLsa构建
adjBuildCountCache := l.adjBuildCount
if adjBuildCountCache > 0 {
// 只有有安排时,构建邻接lsa
if l.mlsrConfig.GetAdjacencys().GetNumOfActiveNeighbor() > 0 {
// 有激活状态的邻居,则安装邻接LSA
common2.LogDebug("Building and installing own Adj LSA")
l.BuildAndInstallOwnAdjLsa()
} else {
// 我们没有活跃的邻居,这意味着没有人可以穿过我们。
// 因此,请删除LSDB中的条目。这会阻止此路由器刷新LSA,最终导致其他路由器也将其删除。
common2.LogDebug("Removing own Adj LSA; no ACTIVE neighbors")
l.RemoveLsaByNameAndType(l.thisRouterPrefix, lsa.LsaADJACENCYType)
}
// 如果在构建adj LSA的过程中,FIB必须等待兴趣响应,
// 那么计划的adj LSA构建的数量可能会发生变化,因此我们不应该只将其设置为0。
l.adjBuildCount = l.adjBuildCount - adjBuildCountCache
}
} else {
// 我们仍在等待了解某个邻居的邻接状态,因此请安排稍后的构建(当有望完成时)
l.isBuildAdjLsaScheduled = true
scheTime := l.mlsrConfig.GetHelloTimeout() * time.Duration(l.mlsrConfig.GetHelloRetries())
job, err := l.scheduler.ScheduleTaskAfterDuration(scheTime, 1).Do(l.BuildAdjLsa)
job.LimitRunsTo(1)
l.scheduler.StartAsync()
if err != nil {
common2.LogError("Scheduling BuildAdjLsa error, ", err.Error())
}
}
}
//
@@ -184,7 +406,21 @@ func (l *Lsdb) BuildAdjLsa() {
// @Description: 为当前路由器构建并安装一个邻接LSA
// @receiver l
//
func (l *Lsdb) BuildAndInstallOwnAdjLsa() {
func (l *Lsdb) BuildAndInstallOwnAdjLsa() {
// 根据配置文件,构造本机的名称LSA
adjLsa := new(lsa.AdjLsa)
adjLsa.SetOriginRouter(l.thisRouterPrefix)
adjLsa.SetSeqNo(l.sequencingManager.GetAdjLsaSeq() + 1) // 序列号
adjLsa.SetLsaExpirationTime(l.getLsaExpirationTimePoint()) // 超期时间
adjLsa.AdjLsaAdjacenctList.InsertAdjacenctList(l.mlsrConfig.GetAdjacencyList()) // 名称前缀列表
// 刷新序列号管理器中的名称LSA序列号
l.sequencingManager.IncreaseAdjLsaSeq()
// todo: 使用sync通知路由更新
// m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
// 安装lsa到LSDB
l.InstallLsa(adjLsa)
}
//
@@ -192,19 +428,69 @@ 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) {
// 在指定间隔的几秒后触发刷新或过期事件
duration = duration + GRACE_PERIOD
// 安排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())
}
}
func (l* Lsdb) ExpireOrRefreshLsa(lsa lsa.ILsa) {
}
//
// ExpireOrRefreshLsa
// @Description: LSA过期时间触发后,执行该函数
// @receiver l
// @param lsa
//
func (l *Lsdb) ExpireOrRefreshLsa(lsa lsa.ILsa) {
common2.LogDebug("ExpireOrRefreshLsa called for ", lsa.ToString())
func (l *Lsdb) ProcessInterestForLsa(interest *packet.Interest,
originRouterIdentifier *component.Identifier,lsaType lsa.LsaType,seqNo uint64) {
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)
}
}
}
}
//
// ExpressInterest
// @Description: 发送请求其它路由器LSA的兴趣包
// @receiver l
// @param interestName
// @param timeOut
// @param deadline
//
func (l *Lsdb) ExpressInterest(interestName *component.Identifier,
timeOut uint32,deadline *time.Time) {
timeOut uint32, deadline *time.Time) {
}
//
@@ -219,9 +505,9 @@ func (l *Lsdb) ExpressInterest(interestName *component.Identifier,
// @param lsaName
// @param seqNo
//
func (l *Lsdb) OnFetchLsaError(errorCode uint32,msg string,
interestName *component.Identifier,retransmitNo uint32,
deadline *time.Time,lsaName *component.Identifier,seqNo uint64) {
func (l *Lsdb) onFetchLsaError(errorCode uint32, msg string,
interestName *component.Identifier, retransmitNo uint32,
deadline *time.Time, lsaName *component.Identifier, seqNo uint64) {
}
//
@@ -233,11 +519,16 @@ func (l *Lsdb) OnFetchLsaError(errorCode uint32,msg string,
// @param buffer
// @param interestName
//
func (l *Lsdb) AfterFetchLsa(buffer bytes.Buffer,interestName *component.Identifier) {
func (l *Lsdb) afterFetchLsa(buffer bytes.Buffer, interestName *component.Identifier) {
}
func (l *Lsdb) getLsaExpirationTimePoint() time.Time {
// todo
return time.Time{}
func (l *Lsdb) getLsaExpirationTimePoint() uint64 {
timeExpire := time.Now()
timeExpire = timeExpire.Add(l.mlsrConfig.GetRouterDeadInterval())
return uint64(timeExpire.UnixMilli())
}
func (l *Lsdb) uintToTime(uintTime uint64) time.Time {
return time.UnixMilli(int64(uintTime))
}
+254
View File
@@ -0,0 +1,254 @@
// Package lsdb
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/25 10:15
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package lsdb
import (
"fmt"
common2 "minlib/common"
"minlib/component"
"minlib/encoding"
"minlib/logicface"
"mlsr/common"
"mlsr/lsa"
"strconv"
"testing"
"time"
)
const testConfigPath = "D:\\" + common.DefaultConfFileName
//
// TestLsdb_Init
// @Description: 测试LSDB初始化
// @param t
//
func TestLsdb_Init(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)
}
//
// 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))
}
//
// TestLsdb_ScheduleLsaExpiration
// @Description: 测试安排LSA过期事件
// @param t
//
func TestLsdb_ScheduleLsaExpiration(t *testing.T) {
// 1. 初始化LSDB
// 配置文件初始化
mlsrConfig, err := common.ParseConfig(testConfigPath)
if err != nil {
common2.LogInfo("配置文件解析错误")
}
// 调度器初始化
sche := new(MlsrScheduler)
sche.Init()
// LogicFace初始化(假设初始化,暂时用不到)
face := new(logicface.LogicFace)
// LSDB初始化
lsdb := new(Lsdb)
lsdb.Init(mlsrConfig, sche, face)
// 2. 生成一个邻接Lsa
adjLsa := new(lsa.AdjLsa)
adjLsa.SetLsaExpirationTime(2000)
adjLsa.SetLsaSequenceNumber(1234)
adjLsa.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString("/min/pku")
// 构造邻接信息部分
// 先构造一个info
linkCost := lsa.AdjLsaLinkCost{}
linkCost.SetLinkCost(100)
faceUri := lsa.AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := lsa.AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString("/pku/router1")
adjInfo := lsa.NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
adjLsa.Insert(adjInfo)
// 3. 插入Lsdb
err = lsdb.Emplace(adjLsa)
if err != nil {
common2.LogInfo("插入错误")
}
common2.LogInfo("插入成功")
// 4. 设置自动删除任务【3s+10s=13s】
timeDur := 3 * time.Second
lsdb.ScheduleLsaExpiration(adjLsa, timeDur)
common2.LogInfo("???")
// 5. 不断循环查询lsdb中是否存在该lsa
i := 0
for true {
b := lsdb.DoesLsaExist(adjLsa)
common2.LogInfo("是否存在:" + strconv.FormatBool(b))
lsaCache := lsdb.FindLsa(adjLsa.GetOriginRouter(), adjLsa.GetType())
if lsaCache != nil {
common2.LogInfo(lsaCache.ToString())
}
time.Sleep(time.Second)
i++
}
}
//
// TestLsab_InstallLsa
// @Description: 测试安装lsa。安装lsa时会根据过期时间来设置多久后删除或更新该lsa
// @param t
//
func TestLsab_InstallLsa(t *testing.T) {
// 1. 初始化LSDB
// 配置文件初始化
mlsrConfig, err := common.ParseConfig(testConfigPath)
if err != nil {
common2.LogInfo("配置文件解析错误")
}
// 调度器初始化
sche := new(MlsrScheduler)
sche.Init()
// LogicFace初始化(假设初始化,暂时用不到)
face := new(logicface.LogicFace)
// LSDB初始化
lsdb := new(Lsdb)
lsdb.Init(mlsrConfig, sche, face)
// 2. 构建三秒后过期的时间戳,并将之设置到namelsa中
timeExpire := uint64(time.Now().Add(3 * time.Second).UnixMilli())
// 构造info
namePrefixInfo := new(lsa.NameLsaNamePrefixInfo)
namePrefixInfo.NamePrefix, _ = component.CreateIdentifierByString("/min/pku")
namePrefixInfo.InsertSource("/wechat")
namePrefixInfo.InsertSource("/qq")
// 构造nameLSA
nameLsa := new(lsa.NameLsa)
nameLsa.LsaBase = lsa.LsaBase{
SelfEncodingBase: encoding.SelfEncodingBase{},
LsaExpirationTime: lsa.LsaExpirationTime{},
LsaSequenceNumber: lsa.LsaSequenceNumber{},
LsaOriginRouterIdentifier: nil,
}
nameLsa.SetLsaSequenceNumber(111)
nameLsa.SetLsaExpirationTime(timeExpire)
routerIdent, _ := component.CreateIdentifierByString("/pku/router")
nameLsa.SetOriginRouter(routerIdent)
nameLsa.InsertNamePrefixInfo(namePrefixInfo)
// 3. 安装到lsdb
lsdb.InstallLsa(nameLsa)
// 4. 不断循环查询lsdb中是否存在该lsa
i := 0
for true {
b := lsdb.DoesLsaExist(nameLsa)
common2.LogInfo("是否存在:" + strconv.FormatBool(b))
lsaCache := lsdb.FindLsa(nameLsa.GetOriginRouter(), nameLsa.GetType())
if lsaCache != nil {
common2.LogInfo(lsaCache.ToString())
}
time.Sleep(time.Second)
i++
}
}
//
// TestName_BuildAndInstallAdjLsa
// @Description: 测试构建本机的adjlsa
// @param t
//
func TestName_BuildAndInstallAdjLsa(t *testing.T) {
// 1. 初始化LSDB
// 配置文件初始化
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)
// 2. 安装本机adjlsa
lsdb.BuildAndInstallOwnAdjLsa()
// 3. 打印lsdb中所有本机lsa
lsas, _ := lsdb.LsaContainer.GetLSAsByType(lsa.LsaADJACENCYType)
for i := 0; i < len(lsas); i++ {
common2.LogInfo(lsas[i].ToString())
}
lsas, _ = lsdb.LsaContainer.GetLSAsByType(lsa.LsaNAMEType)
for i := 0; i < len(lsas); i++ {
common2.LogInfo(lsas[i].ToString())
}
}
//
// TestLsdb_InstallLsa
// @Description: 测试安装lsa
// @param t
//
func TestLsdb_InstallLsa_ScheduleAdjLsaBuild(t *testing.T) {
// 1. 初始化LSDB
// 配置文件初始化
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)
// 2. todo 暂时不测,等linux机器上做实机测试
}
+68 -2
View File
@@ -8,10 +8,76 @@
package lsdb
import (
"github.com/go-co-op/gocron"
"time"
)
//
// Scheduler
// @Description: 调度器
// @Description: 封装了goCron的调度器
//
type Scheduler struct {
type MlsrScheduler struct {
sche *gocron.Scheduler
}
//
// Init
// @Description: 调度器初始化
// @receiver s
//
func (s *MlsrScheduler) Init() {
// UTC表示unix标准时间,与北京时区不同,但不影响任务执行
s.sche = gocron.NewScheduler(time.UTC)
}
//
// ScheduleTaskAfterDuration
// @Description: 安排任务在一定时间后触发,触发一次
// @receiver s
// @param dur 时间间隔
//
func (s *MlsrScheduler) ScheduleTaskAfterDuration(dur time.Duration, intervalSeconds int) *gocron.Scheduler {
timeRun := time.Now()
timeRun = timeRun.Add(dur)
return s.scheduleRecurringTaskAtTime(timeRun, intervalSeconds)
}
//
// ScheduleTaskAtTime
// @Description: 安排任务在某个时间执行一次
// @receiver s
// @param timeRun 执行时间
//
func (s *MlsrScheduler) ScheduleTaskAtTime(timeRun time.Time, intervalSeconds int) *gocron.Scheduler {
return s.scheduleRecurringTaskAtTime(timeRun, intervalSeconds)
}
//
// scheduleRecurringTaskAtTime
// @Description: 安排执行某次循环性任务
// @receiver s
// @param timeRun 首次执行时间
// @param intervalSeconds 执行间隔(单位:秒)
//
func (s *MlsrScheduler) scheduleRecurringTaskAtTime(timeRun time.Time, intervalSeconds int) *gocron.Scheduler {
// 判断调度器是否还在正常运行
if (s.sche == nil) || (!s.sche.IsRunning()) {
s.Init()
}
// 安排任务执行
return s.sche.Every(intervalSeconds).Seconds().StartAt(timeRun)
}
func (s *MlsrScheduler) StartAsync() {
s.sche.StartAsync()
}
//
// Close
// @Description: 关闭调度器
// @receiver s
//
func (s *MlsrScheduler) Close() {
s.sche.Clear()
}
+115
View File
@@ -0,0 +1,115 @@
// Package lsdb
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/30 11:19
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package lsdb
import (
"fmt"
"github.com/go-co-op/gocron"
common2 "minlib/common"
"testing"
"time"
)
func printHelloWithS(s string) {
fmt.Println("hello, ", s)
}
func printHello() {
fmt.Println("hello! ")
}
func testLuoTest() error {
timeRun := time.Now()
timeRun.Add(time.Second)
sche := gocron.NewScheduler(time.UTC)
job, err := sche.Every(3).Seconds().StartAt(timeRun).Do(printHelloWithS, "fuck")
if err != nil {
fmt.Println(err)
}
job.LimitRunsTo(3)
sche.StartAsync()
return nil
//for true {
// time.Sleep(time.Second)
//}
}
func testLuoTest2() error {
timeRun := time.Now()
timeRun.Add(time.Second)
sche := gocron.NewScheduler(time.UTC)
job, err := sche.Every(3).Seconds().StartAt(timeRun).Do(printHelloWithS, "fuck2")
if err != nil {
fmt.Println(err)
}
job.LimitRunsTo(3)
sche.StartAsync()
return nil
//for true {
// time.Sleep(time.Second)
//}
}
func TestMlsrScheduler_ScheduleTaskAfterDuration(t *testing.T) {
//_ = testLuoTest()
//_ = testLuoTest2()
//printHelloWithS("ddd")
//for true {
// time.Sleep(time.Second)
//}
// 构造
s := new(MlsrScheduler)
s.Init()
// 定时
timeNow := time.Now()
timeNow = timeNow.Add(3 * time.Second)
//调度任务
job, err := s.ScheduleTaskAfterDuration(time.Second, 3).Do(printHelloWithS, "sss")
job.LimitRunsTo(3)
s.StartAsync()
if err != nil {
fmt.Println("调度器调度任务测试失败, " + err.Error())
return
}
for true {
time.Sleep(time.Second)
}
//关闭调度器
s.Close()
}
//
// TestMlsrScheduler_ScheduleTaskAtTime
// @Description: 测试调度器在指定时间执行任务
// @param t
//
func TestMlsrScheduler_ScheduleTaskAtTime(t *testing.T) {
// 构造
s := new(MlsrScheduler)
s.Init()
// 定时
timeNow := time.Now()
timeNow = timeNow.Add(3 * time.Second)
// 调度任务
job, err := s.ScheduleTaskAtTime(timeNow, 1).Do(printHello)
job.LimitRunsTo(3)
s.StartAsync()
if err != nil {
common2.LogFatal("调度器调度任务测试失败, " + err.Error())
return
}
for true {
time.Sleep(time.Second)
}
// 关闭调度器
s.Close()
}
+102 -34
View File
@@ -10,21 +10,31 @@ package lsdb
import (
"errors"
"minlib/common"
common2 "minlib/common"
"mlsr/lsa"
"mlsr/utils"
"path"
"strconv"
"strings"
"sync"
)
var once sync.Once // 用以保证SequencingManager的使用是单例模式
var instance *SequencingManager // 单例模式的序列号管理器
var once sync.Once // 用以保证SequencingManager的使用是单例模式
var instance *SequencingManager // 单例模式的序列号管理器
var seqFileName string = "mlsrSeqNo.txt" // 保存序列号的文件名
var seqFileName string = ".mlsrSeqNo.txt" // 保存序列号的文件名
//
// SequencingManager
// @Description: 序列号管理器
//
type SequencingManager struct {
adjLsaSeq uint64
// 三种序列号
adjLsaSeq uint64
nameLsaSeq uint64
corLsaSeq uint64
corLsaSeq uint64
// 序列号保存到的文件路径
seqFileNameWithPath string
}
@@ -34,15 +44,19 @@ type SequencingManager struct {
// @param filePath 序列号同步到本地文件的文件位置
// @return *SequencingManager
//
func GetInstance(filePath string) *SequencingManager {
func GetInstance() *SequencingManager {
once.Do(func() {
homePath, err := common.Home()
homePath, err := common2.Home()
if err != nil {
common.LogFatal("Get current user home path failed!")
common2.LogError("Get current user home path failed!")
}
instance = &SequencingManager{0,0,0,
homePath+"/"+seqFileName}
_ = instance.SetSeqFileDirectory(filePath)
// 生成序列号管理器文件路径,并日志记录下来
filePath := path.Join(homePath, seqFileName)
common2.LogInfo("SequencingManager file path is " + filePath)
// 从文件中初始化该序列号管理器
instance = &SequencingManager{0, 0, 0,
filePath}
_ = instance.setSeqFileDirectory(filePath)
instance.InitiateSeqNoFromFile()
})
return instance
@@ -55,25 +69,65 @@ func GetInstance(filePath string) *SequencingManager {
// @receiver s
// @param filePath
//
func (s *SequencingManager) SetSeqFileDirectory(filePath string) error {
//todo
func (s *SequencingManager) setSeqFileDirectory(filePath string) error {
s.seqFileNameWithPath = filePath
return nil
}
//
// InitiateSeqNoFromFile
// @Description: todo:从文件中初始化各种类型lsa的seq
// @Description: 从文件中初始化各种类型lsa的seq
// @receiver s
//
func (s *SequencingManager) InitiateSeqNoFromFile() {
func (s *SequencingManager) InitiateSeqNoFromFile() {
// 先判断文件是否存在,不存在,则初始化文件
_, b := utils.IsExists(s.seqFileNameWithPath)
if !b {
common2.LogInfo("sequencingManager file not exists, fileinfo is " + s.seqFileNameWithPath)
homePath, err := common2.Home()
if err != nil {
common2.LogError("Get current user home path failed!")
}
// 生成序列号管理器文件,并将序列号写入文件
filePath := path.Join(homePath, seqFileName)
_ = s.setSeqFileDirectory(filePath)
utils.ClearAndWriteFile(filePath, "0 0 0") // 依次表示:邻接LSA序列号、名称LSA序列号、双曲LSA序列号
}
// 并读取数据
seqs, err := utils.ReadFromFile(s.seqFileNameWithPath)
common2.LogInfo("读取数据成功,序列号为: " + seqs)
if err != nil {
common2.LogFatal("read seqs from " + s.seqFileNameWithPath + " failed.")
return
}
// 读取邻接
seqsArray := strings.Fields(seqs)
s.adjLsaSeq, err = strconv.ParseUint(seqsArray[0], 10, 64)
if err != nil {
common2.LogFatal("read seqs from " + s.seqFileNameWithPath + " failed, reason is " + err.Error())
}
// 读取名称
s.nameLsaSeq, err = strconv.ParseUint(seqsArray[1], 10, 64)
if err != nil {
common2.LogFatal("read seqs from " + s.seqFileNameWithPath + " failed, reason is " + err.Error())
}
// 读取双曲
s.corLsaSeq, err = strconv.ParseUint(seqsArray[2], 10, 64)
if err != nil {
common2.LogFatal("read seqs from " + s.seqFileNameWithPath + " failed, reason is " + err.Error())
}
}
//
// WriteSeqNoToFile
// @Description: todo:将当前seq写入文件
// @Description: 将当前seq写入文件
// @receiver s
//
func (s SequencingManager) WriteSeqNoToFile() {
func (s *SequencingManager) writeSeqNoToFile() {
// 将序列号写入文件。依次表示:邻接LSA序列号、名称LSA序列号、双曲LSA序列号
utils.ClearAndWriteFile(s.seqFileNameWithPath, strconv.FormatUint(s.adjLsaSeq, 10)+" "+
strconv.FormatUint(s.nameLsaSeq, 10)+" "+
strconv.FormatUint(s.corLsaSeq, 10))
}
//
@@ -83,15 +137,17 @@ func (s SequencingManager) WriteSeqNoToFile() {
// @param seqNo
// @param lsaType
//
func (s *SequencingManager) SetLsaSeq(seqNo uint64,lsaType lsa.LsaType) {
func (s *SequencingManager) SetLsaSeq(seqNo uint64, lsaType lsa.LsaType) {
switch lsaType {
case lsa.LsaADJACENCYType:
s.adjLsaSeq=seqNo
s.adjLsaSeq = seqNo
case lsa.LsaNAMEType:
s.nameLsaSeq=seqNo
s.nameLsaSeq = seqNo
case lsa.LsaCOORDINATEType:
s.corLsaSeq=seqNo
s.corLsaSeq = seqNo
}
// 更新到文件
s.writeSeqNoToFile()
}
//
@@ -102,16 +158,16 @@ func (s *SequencingManager) SetLsaSeq(seqNo uint64,lsaType lsa.LsaType) {
// @return uint64
// @return error
//
func (s *SequencingManager) GetLsaSeq(lsaType lsa.LsaType) (uint64,error) {
func (s *SequencingManager) GetLsaSeq(lsaType lsa.LsaType) (uint64, error) {
switch lsaType {
case lsa.LsaADJACENCYType:
return s.adjLsaSeq,nil
return s.adjLsaSeq, nil
case lsa.LsaNAMEType:
return s.nameLsaSeq,nil
return s.nameLsaSeq, nil
case lsa.LsaCOORDINATEType:
return s.corLsaSeq,nil
return s.corLsaSeq, nil
}
return 0,errors.New("no found the lsaType: "+ strconv.Itoa(int(lsaType)))
return 0, errors.New("no found the lsaType: " + strconv.Itoa(int(lsaType)))
}
//
@@ -131,7 +187,9 @@ func (s *SequencingManager) GetAdjLsaSeq() uint64 {
// @param seq
//
func (s *SequencingManager) SetAdjLsaSeq(seq uint64) {
s.adjLsaSeq=seq
s.adjLsaSeq = seq
// 更新到文件
s.writeSeqNoToFile()
}
//
@@ -151,7 +209,9 @@ func (s *SequencingManager) GetNameLsaSeq() uint64 {
// @param seq
//
func (s *SequencingManager) SetNameLsaSeq(seq uint64) {
s.nameLsaSeq=seq
s.nameLsaSeq = seq
// 更新到文件
s.writeSeqNoToFile()
}
//
@@ -171,7 +231,9 @@ func (s *SequencingManager) GetCorLsaSeq() uint64 {
// @param seq
//
func (s *SequencingManager) SetCorLsaSeq(seq uint64) {
s.corLsaSeq=seq
s.corLsaSeq = seq
// 更新到文件
s.writeSeqNoToFile()
}
//
@@ -179,8 +241,10 @@ func (s *SequencingManager) SetCorLsaSeq(seq uint64) {
// @Description: 邻接LSA序列号加一
// @receiver s
//
func (s *SequencingManager) IncreaseAdjLsaSeq() {
func (s *SequencingManager) IncreaseAdjLsaSeq() {
s.adjLsaSeq++
// 更新到文件
s.writeSeqNoToFile()
}
//
@@ -188,8 +252,10 @@ func (s *SequencingManager) IncreaseAdjLsaSeq() {
// @Description: 名称LSA序列号加一
// @receiver s
//
func (s *SequencingManager) IncreaseNameLsaSeq() {
func (s *SequencingManager) IncreaseNameLsaSeq() {
s.nameLsaSeq++
// 更新到文件
s.writeSeqNoToFile()
}
//
@@ -197,6 +263,8 @@ func (s *SequencingManager) IncreaseNameLsaSeq() {
// @Description: 坐标LSA序列号加一
// @receiver s
//
func (s *SequencingManager) IncreaseCorLsaSeq() {
func (s *SequencingManager) IncreaseCorLsaSeq() {
s.corLsaSeq++
}
// 更新到文件
s.writeSeqNoToFile()
}
+32
View File
@@ -0,0 +1,32 @@
// Package lsdb
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/19 16:47
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package lsdb
import (
"fmt"
"mlsr/lsa"
"testing"
)
// 测试从文件读写序列号管理器
func TestSequencingManager_InitiateSeqNoFromFile(t *testing.T) {
// 构建序列号管理器
seqManager := GetInstance()
fmt.Println("path: ", seqManager.seqFileNameWithPath)
// 增加邻接序列号
seqManager.IncreaseAdjLsaSeq()
// 设置,获取指定lsa序列号
seqManager.SetLsaSeq(9999, lsa.LsaNAMEType)
seq1 := seqManager.GetNameLsaSeq()
seq2 := seqManager.GetAdjLsaSeq()
seq3, _ := seqManager.GetLsaSeq(lsa.LsaCOORDINATEType)
fmt.Println(seq1, seq2, seq3)
}
-31
View File
@@ -1,31 +0,0 @@
package main
import (
"fmt"
"github.com/tidwall/buntdb"
"minlib/logicface"
"mlsr/lsa"
)
func main() {
fmt.Println("abc")
s:=logicface.LogicFaceTypeEther
fmt.Println("def",s)
ss:=lsa.AdjLsaAdjacencyInfo{}
ss.Status=1
TestBuntDb()
}
func TestBuntDb() {
// https://github.com/tidwall/buntdb
db,err := buntdb.Open(":memory:")
if err!= nil{
fmt.Println("bunt db open err")
}
_ = db.Close()
fmt.Println("bunt db closed")
}
+38
View File
@@ -0,0 +1,38 @@
[General]
Network = /min
Site = /pkusz
Router = /routerA
LsaRefreshTime = 1800
RouterDeadInterval = 3600
LsaInterestLifetime = 4
SyncProtocol = min-sync
SyncInterestLifetime = 60000
[Log]
LogLevel = ALL
ReportCaller = true
LogFormat = text
LogFilePath =
[Neighbors]
HelloRetries = 3
HelloTimeout = 1
HelloInterval = 60
AdjLsaBuildInterval = 10
LogicFaceDatasetFetchRetries = 3
LogicFaceDatasetFetchInterval = 3600
NeighborsInfo = [{"NeighborName":"/routerB","LogicFaceUri":"tcp://1.1.1.1","LinkCost":10},{"NeighborName":"/routerC","LogicFaceUri":"tcp://1.1.1.0","LinkCost":10},{"NeighborName":"nei","LogicFaceUri":"uri","LinkCost":0}]
[Hyperbolic]
[Fib]
MaxLogicFacesPerPrefix = 0
RoutingCalcInterval = 15
[Advertising]
Prefixs = /videos,/files,voices
[Security]
[MlsrConfigParameters]
+26
View File
@@ -0,0 +1,26 @@
// Package mlsr
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/16 17:32
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package mlsr
import (
"fmt"
"mlsr/common"
)
func main() {
// 初始化配置文件
testPath := "D:"
testPath += "\\"
testPath += common.DefaultConfFileName
fmt.Println("test mlsr conf path: " + testPath)
mlsrConfig, _ := common.ParseConfig(testPath)
// 初始化日志模块
common.InitLogger(mlsrConfig)
}
+71
View File
@@ -0,0 +1,71 @@
// Package lsa
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/5 10:38
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"minlib/component"
"minlib/encoding"
"mlsr/extensions"
)
//
// ConnectingLogicFaceUri
// @Description: MIR层级对LogicFace的描述。例子:udp://1.0.0.2
//
type ConnectingLogicFaceUri struct {
component.CommonString
}
//
// LogicFaceUri
// @Description: 获取LogicFaceUri
// @receiver l
// @return string
//
func (l *ConnectingLogicFaceUri) LogicFaceUri() string {
return l.CommonString.Value()
}
//
// setLogicFaceUri
// @Description: 设置LogicFaceUri
// @receiver l
// @param logicFaceUri
//
func (l *ConnectingLogicFaceUri) SetLogicFaceUri(logicFaceUri string) {
l.CommonString.SetValue(logicFaceUri)
}
//
// WireEncode
// @Description: 线速编码
// @receiver l
// @param encoder
// @return int
// @return error
//
func (l *ConnectingLogicFaceUri) WireEncode(encoder *encoding.Encoder) (int,error) {
l.CommonString.SetTlvType(extensions.TlvMlsrConnectingLogicFaceUri)
return l.CommonString.WireEncode(encoder)
}
//
// WireDecode
// @Description: 线速解码
// @receiver l
// @param block
// @return error
//
func (l *ConnectingLogicFaceUri) WireDecode(block *encoding.Block) error {
// 检查type是否正确
if err := encoding.ExpectType(block.GetType(),extensions.TlvMlsrConnectingLogicFaceUri); err!=nil {
return err
}
return l.CommonString.WireDecode(block)
}
+109
View File
@@ -0,0 +1,109 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/26 10:39
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"fmt"
"minlib/encoding"
"testing"
)
//
// TestConnectingLogicFaceUri_LogicFaceUri
// @Description: 设置参数
// @param t
//
func TestConnectingLogicFaceUri_LogicFaceUri(t *testing.T) {
testCPU := ConnectingLogicFaceUri{}
testCPU.SetLogicFaceUri("url")
fmt.Println(testCPU.LogicFaceUri())
}
//
// TestConnectingLogicFaceUri_WireEncode
// @Description: 测试编码
// @param t
//
func TestConnectingLogicFaceUri_WireEncode(t *testing.T) {
testCPU := new(ConnectingLogicFaceUri)
fmt.Println(testCPU.LogicFaceUri())
testCPU.SetLogicFaceUri("url")
fmt.Println(testCPU.LogicFaceUri())
//testCPC.SetTlvType(5)
fmt.Println(testCPU.Value())
var encoder encoding.Encoder
err := encoder.EncoderReset(encoding.MaxPacketSize, 0)
if err != nil {
fmt.Println("encoder.EncoderReset() failed", err)
return
}
a, err := testCPU.WireEncode(&encoder)
if err != nil {
fmt.Println("ConnectingLogicFaceUri.WireEncode() failed", err)
return
}
fmt.Println(a)
buf, err := encoder.GetBuffer()
if err != nil {
fmt.Println("encoder.GetBuffer() failed", err)
return
}
fmt.Println("interest buf", buf)
block, err := encoding.CreateBlockByBuffer(buf[:], false)
if err != nil {
fmt.Println("encoding.CreateBlockByBuffer() failed", err)
}
fmt.Println("interest block", block)
}
//
// TestConnectingLogicFaceUri_WireDecode
// @Description: 测试解码
// @param t
//
func TestConnectingLogicFaceUri_WireDecode(t *testing.T) {
testCPU := new(ConnectingLogicFaceUri)
fmt.Println("interest", testCPU.Value())
//testCPC.SetTlvType(5)
fmt.Println(testCPU.TlvType())
testCPU.SetLogicFaceUri("url")
fmt.Println("interest", testCPU.Value())
fmt.Println("interest", testCPU.IsInitial())
var encoder encoding.Encoder
err := encoder.EncoderReset(encoding.MaxPacketSize, 0)
if err != nil {
fmt.Println("encoder.EncoderReset() failed", err)
return
}
a, err := testCPU.WireEncode(&encoder)
if err != nil {
fmt.Println("ConnectingLogicFaceUri.WireEncode() failed", err)
}
fmt.Println(a)
buf, err := encoder.GetBuffer()
if err != nil {
fmt.Println("encoder.GetBuffer() failed:", err)
return
}
fmt.Println("interest buf", buf)
block, err := encoding.CreateBlockByBuffer(buf[:], false)
if err != nil {
fmt.Println("encoding.CreateBlockByBuffer() failed:", err)
return
}
fmt.Println("interest block", block)
interest1 := new(ConnectingLogicFaceUri)
err = interest1.WireDecode(block)
if err != nil {
fmt.Println("interest1.WireDecode() failed", err)
return
}
fmt.Println("interest1.value: ", interest1.Value())
fmt.Println("interest1", interest1.IsInitial())
}
+346
View File
@@ -0,0 +1,346 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/9 17:31
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"errors"
"math"
"minlib/component"
"mlsr/common"
"mlsr/lsa"
"mlsr/lsdb"
"strconv"
)
//
// LinkStateRoutingTableCalculator
// @Description: 邻接状态路由表计算器。路由计算的核心部分
//
type LinkStateRoutingTableCalculator struct {
RoutingTableCalculator
// 私有变量区
// 表示源路由器想要到达某路由器,其最短路径上经过的上一个路由器。
m_parent []int
// 表示源路由器想要到达某路由器,其最短路径的距离
m_distance []uint64
}
//
// ToString
// @Description: 转string
// @receiver c
// @return string
//
func (c *LinkStateRoutingTableCalculator) ToString() string {
str := ""
str += "每个节点最佳路径的上一跳:["
for i := 0; i < len(c.m_parent); i++ {
str += "(" + strconv.Itoa(i)
str += ", "
str += strconv.Itoa(c.m_parent[i])
str += ")"
}
str += "\n"
str += "每个节点最佳路径的总开销:["
for i := 0; i < len(c.m_distance); i++ {
str += "(" + strconv.Itoa(i)
str += ", "
str += strconv.FormatUint(c.m_distance[i], 10)
str += ")"
}
str += "\n"
return str
}
// 一些在最短路径计算时会用到的常量
const (
EMPTY_PARENT = -12345 // 没有父节点 -12345
INF_DISTANCE = math.MaxUint64 // 无限距离 2147483647
NO_MAPPING_NUM = -1 // 没有映射的点 -1
// 公用常量
NO_NEXT_HOP = -12345 // 没有下一跳 -12345
)
//
// CalculatePath
// @Description: 计算可转发路径。路由计算里的唯一Public的接口
// @receiver c
// @param routerMap
// @param rTable
// @param mConfig
// @param lsdb
//
func (c *LinkStateRoutingTableCalculator) CalculatePath(routerMap *RouterMap,
mConfig *common.MlsrConfig,
lsdb *lsdb.Lsdb) ([]*component.Identifier, []*NextHop, error) {
// 设置路由器数目
c.SetRouterNum(routerMap.GetMapSize())
// 分配矩阵空间
c.allocateAdjMatrix()
// 初始化矩阵数值
c.initMatrix()
// 根据Lsdb邻接信息构造邻接矩阵
_ = c.makeAdjMatrix(lsdb, routerMap)
// 为路由计算中记录路径和距离的两个数组分配空间
c.allocateParent()
c.allocateDistance()
// 从配置文件中获取源路由器前缀,并根据routerMap获取其映射号
sourceRouter, b := routerMap.GetMappingNoByRouterName(mConfig.GetRouterPrefix())
if !b {
return nil, nil, errors.New("no found the source route in the router map, " +
"the source router prefix is: " + mConfig.GetRouterPrefix().ToUri())
}
// 初始化切片
routers := []*component.Identifier{} // 路由器标识
nexthops := []*NextHop{} // 下一跳
// 判断是单路径计算,还是多路径计算
if mConfig.GetMaxFacesPerPrefix() == 1 {
// 在单路径的情况下,我们可以简单地运行Dijkstra算法。
c.doDijkstraPathCalculation(sourceRouter)
// 将新的下一跳通知路由表。// 注意,当前版本中,本机的邻接信息是从配置文件中读取出来的。
rs, ns := c.addAllLsNextHopsToRoutingTable(mConfig.GetAdjacencys(), routerMap, sourceRouter)
return rs, ns, nil
} else {
// 多路径计算
// 1. 先确定源路由器的邻居路由器数目
c.setNoLink(c.getNumOfLinkfromAdjMatrix(sourceRouter))
c.allocateLinks()
c.allocateLinkCosts()
// 2. 获取用于路径计算的稀疏邻接列表。具体操作是填充:c.links,c.linkCosts
c.getLinksFromAdjMatrix(sourceRouter)
// 3. 遍历每个外接链路能够达到其它目的路由器的所有下一跳及其开销
for i := 0; i < c.vNoLink; i++ {
// 模拟只有当前邻居i可以访问的情形。即:砍掉除当前邻居路由器外的其他邻接链路
c.adjustAdMatrix(sourceRouter, c.links[i], c.linkCosts[i])
// 以当前邻居为起点,执行Dijkstra算法。
c.doDijkstraPathCalculation(sourceRouter)
// 用计算结果更新路由表。
rs, ns := c.addAllLsNextHopsToRoutingTable(mConfig.GetAdjacencys(), routerMap, sourceRouter)
routers = append(routers, rs...)
nexthops = append(nexthops, ns...)
}
c.freeLinks()
c.freeLinksCosts()
}
c.freeParent()
c.freeDistance()
c.freeAdjMatrix()
return routers, nexthops, nil
}
//
// doDijkstraPathCalculation
// @Description: 在邻接矩阵基础上,针对源路由器,做迪吉斯特拉计算
// 在注释中,“左集”表示已访问节点,“右集”表示未访问节点
// @receiver c
// @param sourceRouter
//
func (c *LinkStateRoutingTableCalculator) doDijkstraPathCalculation(sourceRouter int) {
// 尚未加入左集的最近元素(Q中右集最小元素)
var u int
// 每个单元代表具有该映射号的路由器。
// Q是queue首字母,它按升序存储所有路由器
Q := make([]int, c.m_nRouters)
// 尚未加入左集的最近元素在Q中的索引值
head := 0
// 初始化parent
for i := 0; i < c.m_nRouters; i++ {
// 每个点的最短路径上一点都初始化为空,即无法到达源路由器
c.m_parent[i] = EMPTY_PARENT
// 数组中第i个元素存储的是:源路由器到映射号为i的路由器之间的距离。初始化为无穷大
c.m_distance[i] = INF_DISTANCE
// 路由器队列初始化为按映射号排列
Q[i] = i
}
if sourceRouter != NO_MAPPING_NUM {
// 源路由器到其本身的距离为0
c.m_distance[sourceRouter] = 0
// 排序完毕,Q中第一个节点必然为源路由器
c.sortQueueByDistance(Q, c.m_distance, head, c.m_nRouters)
// 当我们没有访问完每一个节点时,执行循环
for head < c.m_nRouters {
// 将u设置为head当前指向的节点。“u,你就是天选之子!”
u = Q[head]
if c.m_distance[u] == INF_DISTANCE {
// 只有没有可访问的节点时,这里才会被执行。"天选之子是个废物,亡矣!"
break
}
// 对u的相邻节点进行迭代遍历。“朕要以你为衡,重设天下!”
for v := 0; v < c.m_nRouters; v++ {
// 如果u->v是可达的,
if c.adjMatrix[u][v] != NON_ADJACENT_COST {
// 而且我们还没有访问过v,即v属于右集,
if c.isNotExplored(Q, v, head+1, c.m_nRouters) {
// 如果到这个节点的距离+从这个节点到v的距离,
// 小于我们在构建adj LSA时得到的从源节点到v的距离,
// 就更新为新距离【算法中的松弛操作】
if c.m_distance[u]+c.adjMatrix[u][v] < c.m_distance[v] {
// 设置新距离
c.m_distance[v] = c.m_distance[u] + c.adjMatrix[u][v]
// 设置parent,即我们如何到达v的
c.m_parent[v] = u
}
}
}
}
// 右移head位置,从我们所在的位置按距离重新排序列表。"苍天已死,黄天当立!"
head++
c.sortQueueByDistance(Q, c.m_distance, head, c.m_nRouters)
}
}
}
//
// sortQueueByDistance
// @Description: 对切片中的元素进行交换排序
// 注意,切片是引用传递,因此这里实际修改了Q的值。
// @receiver c
// @param Q 要排序元素的切片
// @param dist 包含距离的数组
// @param start 列表中要排序的第一个元素
// @param element 列表元素数目
//
func (c *LinkStateRoutingTableCalculator) sortQueueByDistance(
Q []int, dist []uint64, start int, element int) {
for i := start; i < element; i++ {
for j := i + 1; j < element; j++ {
if dist[Q[j]] < dist[Q[i]] {
temp := Q[j]
Q[j] = Q[i]
Q[i] = temp
}
}
}
}
//
// isNotExplored
// @Description: 返回元素是否被访问
// @receiver c
// @param Q 要查看的元素列表
// @param u 要检查的元素
// @param start 要查看的列表的开头
// @param element 列表元素数
//
func (c *LinkStateRoutingTableCalculator) isNotExplored(
Q []int, u int, start int, element int) bool {
for i := start; i < element; i++ {
if Q[i] == u {
return true
}
}
return false
}
//
// addAllLsNextHopsToRoutingTable
// @Description: 将计算得到的所有路由器及其下一跳加入路由表
// @receiver c
// @param adjs
// @param rMap
// @param sourceRouter
// @return []*component.Identifier
// @return []*route.NextHop
//
func (c *LinkStateRoutingTableCalculator) addAllLsNextHopsToRoutingTable(
adjs *lsa.AdjLsaAdjacenctList, rMap *RouterMap,
sourceRouter int) ([]*component.Identifier, []*NextHop) {
// 初始化切片
routers := []*component.Identifier{} // 路由器标识
nexthops := []*NextHop{} // 下一跳
// 对于我们有的每个路由器
for i := 0; i < c.m_nRouters; i++ {
if i != sourceRouter {
// 获取算法确定的下一跳
nextHopRouter := c.getLsNextHop(i, sourceRouter)
// 需要该路由器不至于没有对应的下一跳
if nextHopRouter != NO_NEXT_HOP {
// 获取链路开销
routeCost := c.m_distance[i]
// 根据map获取该路由器的真实名称
nextHopRouterName, b := rMap.GetRouterNameByMappingNo(nextHopRouter)
if b {
// 根据本地邻接LSA列表,获取该下一跳路由器所对应的faceuri
nextHopFace := adjs.FindAdjacencyByRouterIdentifier(nextHopRouterName)
if nextHopFace == nil {
continue
}
// 将下一跳加入路由表
nextHop := new(NextHop)
nextHop.SetRouteCost(routeCost)
nextHop.SetLogicFaceUri(nextHopFace.AdjLsaLogicFaceUri.LogicFaceUri())
// 下面代码相当于:rt.addNextHop(*(pMap.getRouterNameByMappingNo(i)), nh);
name, bb := rMap.GetRouterNameByMappingNo(i)
if !bb {
continue
}
routers = append(routers, name)
nexthops = append(nexthops, nextHop)
}
}
}
}
return routers, nexthops
}
//
// getLsNextHop
// @Description: 决定到目的路由器的下一跳路由器
// @receiver c
// @param dest 想要确定的目的路由器
// @param source 源路由器
//
func (c *LinkStateRoutingTableCalculator) getLsNextHop(dest int, source int) int {
nextHop := NO_NEXT_HOP
// source的父节点是空节点,故遍历到source或某个断点,就停止循环
for c.m_parent[dest] != EMPTY_PARENT {
nextHop = dest
dest = c.m_parent[dest]
}
if dest != source {
nextHop = NO_NEXT_HOP
}
return nextHop
}
//
// allocateParent
// @Description: 分配内存
// @receiver c
//
func (c *LinkStateRoutingTableCalculator) allocateParent() {
c.m_parent = make([]int, c.m_nRouters)
}
//
// allocateDistance
// @Description: 分配内存
// @receiver c
//
func (c *LinkStateRoutingTableCalculator) allocateDistance() {
c.m_distance = make([]uint64, c.m_nRouters)
}
//
// freeParent
// @Description: 释放内存
// @receiver c
//
func (c *LinkStateRoutingTableCalculator) freeParent() {
c.m_parent = []int{}
}
//
// freeDistance
// @Description: 释放内存
// @receiver c
//
func (c *LinkStateRoutingTableCalculator) freeDistance() {
c.m_distance = []uint64{}
}
@@ -0,0 +1,293 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/30 10:57
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"fmt"
common2 "minlib/common"
"minlib/component"
"minlib/logicface"
"mlsr/common"
"mlsr/lsa"
"mlsr/lsdb"
"strconv"
"testing"
"time"
)
//
// testCreateAdjLsa
// @Description: 构造邻接lsa
// @param uri
// @return *lsa.AdjLsa
//
func testCreateAdjLsa(uri string) *lsa.AdjLsa {
base := new(lsa.AdjLsa)
timeExpire := time.Now()
timeExpire = timeExpire.Add(30 * time.Minute)
base.SetLsaExpirationTime(uint64(timeExpire.UnixMilli()))
base.SetLsaSequenceNumber(1234)
base.LsaOriginRouterIdentifier, _ = component.CreateIdentifierByString(uri)
return base
}
//
// testCreateAdjInfo
// @Description: 构造邻接信息
// @param cost
// @param uri
// @return *lsa.AdjLsaAdjacencyInfo
//
func testCreateAdjInfo(cost uint64, uri string) *lsa.AdjLsaAdjacencyInfo {
linkCost := lsa.AdjLsaLinkCost{}
linkCost.SetLinkCost(cost)
faceUri := lsa.AdjLsaLogicFaceUri{}
faceUri.SetLogicFaceUri("uri")
faceId := lsa.AdjLsaLogicFaceId{}
faceId.SetLogicFaceId(77)
iden, _ := component.CreateIdentifierByString(uri)
adjInfo := lsa.NewAdjLsaAdjacencyInfo(linkCost, faceUri, faceId, iden, 123, 1)
return adjInfo
}
//
// TestLinkStateRoutingTableCalculator_CalculateOnePath
// @Description: 测试普通的最短路径计算。测试已通过。
// @param t
//
func TestLinkStateRoutingTableCalculator_CalculateOnePath(t *testing.T) {
// 1. 构造邻接状态路由表计算器
rtc := new(LinkStateRoutingTableCalculator)
// 1.1 构造LSDB
// 配置文件初始化
mlsrConfig, err := common.ParseConfig(testConfigPath)
if err != nil {
fmt.Println("配置文件解析错误")
}
// 调度器初始化
sche := new(lsdb.MlsrScheduler)
sche.Init()
// LogicFace初始化(假设初始化,暂时用不到)
face := new(logicface.LogicFace)
// LSDB初始化
mlsdb := new(lsdb.Lsdb)
mlsdb.Init(mlsrConfig, sche, face)
// 安装本机adjlsa
mlsdb.BuildAndInstallOwnAdjLsa()
// 传入一些其它虚拟lsa,这些lsa与本机lsa共同形成一个小型路由拓扑
// 路由器B
adjLsaB := testCreateAdjLsa("/routerB")
adjInfoBA := testCreateAdjInfo(10, "/min/pkusz/routerA")
adjInfoBE := testCreateAdjInfo(50, "/routerE")
adjLsaB.Insert(adjInfoBA)
adjLsaB.Insert(adjInfoBE)
// 路由器C
adjLsaC := testCreateAdjLsa("/routerC")
adjInfoCA := testCreateAdjInfo(100, "/min/pkusz/routerA")
adjInfoCE := testCreateAdjInfo(10, "/routerE")
adjInfoCD := testCreateAdjInfo(60, "/routerD")
adjLsaC.Insert(adjInfoCA)
adjLsaC.Insert(adjInfoCD)
adjLsaC.Insert(adjInfoCE)
// 路由器E
adjLsaE := testCreateAdjLsa("/routerE")
adjInfoEB := testCreateAdjInfo(50, "/routerB")
adjInfoEC := testCreateAdjInfo(10, "/routerC")
adjInfoED := testCreateAdjInfo(20, "/routerD")
adjLsaE.Insert(adjInfoEB)
adjLsaE.Insert(adjInfoEC)
adjLsaE.Insert(adjInfoED)
// 路由器D
adjLsaD := testCreateAdjLsa("/routerD")
adjInfoDA := testCreateAdjInfo(30, "/min/pkusz/routerA")
adjInfoDC := testCreateAdjInfo(60, "/routerC")
adjInfoDE := testCreateAdjInfo(20, "/routerE")
adjLsaD.Insert(adjInfoDA)
adjLsaD.Insert(adjInfoDC)
adjLsaD.Insert(adjInfoDE)
mlsdb.InstallLsa(adjLsaB)
mlsdb.InstallLsa(adjLsaC)
mlsdb.InstallLsa(adjLsaD)
mlsdb.InstallLsa(adjLsaE)
// 1.2 构造RouterMap
lsas, err := mlsdb.GetLSAsByType(lsa.LsaADJACENCYType)
if err != nil {
common2.LogError("Get Lsa in calculateLsRoutingTable error, ", err)
}
common2.LogInfo("邻接lsa数目: ", len(lsas))
rMap := new(RouterMap)
rMap.Init()
err = rMap.CreateFromAdjLsdb(lsas)
// 打印rm
common2.LogInfo(rMap.ToString())
// 1.3 根据RouterMap,和lsdb中的adjlsa,构造邻接矩阵
// 设置路由器数目
rtc.SetRouterNum(rMap.GetMapSize())
// 分配矩阵空间
rtc.allocateAdjMatrix()
// 初始化矩阵值
rtc.initMatrix()
// 构造矩阵
err = rtc.makeAdjMatrix(mlsdb, rMap)
if err != nil {
common2.LogError("邻接矩阵构造失败")
}
// 1.4 打印输出路由表计算器
fmt.Println(rMap.ToString())
fmt.Println(rtc.ToString())
fmt.Println("源路由器的邻接数目:", rtc.getNumOfLinkfromAdjMatrix(0))
fmt.Println("另一个路由器的邻接数目:", rtc.getNumOfLinkfromAdjMatrix(1))
// 2. 执行单源最短路径算法
rtc.allocateParent()
rtc.allocateDistance()
rtc.doDijkstraPathCalculation(0)
// 查看执行结果
// 计算器中的上一跳路径,以及开销
fmt.Println(rtc.ToString())
// 计算器获取的针对每个目的路由器的下一跳,及开销。
names, nexthops := rtc.addAllLsNextHopsToRoutingTable(mlsrConfig.GetAdjacencys(), rMap, 0)
for i := 0; i < len(names); i++ {
fmt.Println(names[i].ToUri() + " ")
}
fmt.Println("")
for i := 0; i < len(nexthops); i++ {
fmt.Println(nexthops[i].LogicFaceUri() + "-" +
strconv.FormatUint(nexthops[i].RouteCost.RouteCost(), 10) + " ")
}
}
//
// TestLinkStateRoutingTableCalculator_CalculateMutilPath
// @Description: 测试多路径计算
// @param t
//
func TestLinkStateRoutingTableCalculator_CalculateMutilPath(t *testing.T) {
// 1. 构造邻接状态路由表计算器
rtc := new(LinkStateRoutingTableCalculator)
// 1.1 构造LSDB
// 配置文件初始化
mlsrConfig, err := common.ParseConfig(testConfigPath)
if err != nil {
fmt.Println("配置文件解析错误")
}
// 调度器初始化
sche := new(lsdb.MlsrScheduler)
sche.Init()
// LogicFace初始化(假设初始化,暂时用不到)
face := new(logicface.LogicFace)
// LSDB初始化
mlsdb := new(lsdb.Lsdb)
mlsdb.Init(mlsrConfig, sche, face)
// 安装本机adjlsa
mlsdb.BuildAndInstallOwnAdjLsa()
// 传入一些其它虚拟lsa,这些lsa与本机lsa共同形成一个小型路由拓扑
// 路由器B
adjLsaB := testCreateAdjLsa("/routerB")
adjInfoBA := testCreateAdjInfo(10, "/min/pkusz/routerA")
adjInfoBE := testCreateAdjInfo(50, "/routerE")
adjLsaB.Insert(adjInfoBA)
adjLsaB.Insert(adjInfoBE)
// 路由器C
adjLsaC := testCreateAdjLsa("/routerC")
adjInfoCA := testCreateAdjInfo(100, "/min/pkusz/routerA")
adjInfoCE := testCreateAdjInfo(10, "/routerE")
adjInfoCD := testCreateAdjInfo(60, "/routerD")
adjLsaC.Insert(adjInfoCA)
adjLsaC.Insert(adjInfoCD)
adjLsaC.Insert(adjInfoCE)
// 路由器E
adjLsaE := testCreateAdjLsa("/routerE")
adjInfoEB := testCreateAdjInfo(50, "/routerB")
adjInfoEC := testCreateAdjInfo(10, "/routerC")
adjInfoED := testCreateAdjInfo(20, "/routerD")
adjLsaE.Insert(adjInfoEB)
adjLsaE.Insert(adjInfoEC)
adjLsaE.Insert(adjInfoED)
// 路由器D
adjLsaD := testCreateAdjLsa("/routerD")
adjInfoDA := testCreateAdjInfo(30, "/min/pkusz/routerA")
adjInfoDC := testCreateAdjInfo(60, "/routerC")
adjInfoDE := testCreateAdjInfo(20, "/routerE")
adjLsaD.Insert(adjInfoDA)
adjLsaD.Insert(adjInfoDC)
adjLsaD.Insert(adjInfoDE)
mlsdb.InstallLsa(adjLsaB)
mlsdb.InstallLsa(adjLsaC)
mlsdb.InstallLsa(adjLsaD)
mlsdb.InstallLsa(adjLsaE)
// 1.2 构造RouterMap
lsas, err := mlsdb.GetLSAsByType(lsa.LsaADJACENCYType)
if err != nil {
common2.LogError("Get Lsa in calculateLsRoutingTable error, ", err)
}
common2.LogInfo("邻接lsa数目: ", len(lsas))
rMap := new(RouterMap)
rMap.Init()
err = rMap.CreateFromAdjLsdb(lsas)
// 打印rm
common2.LogInfo(rMap.ToString())
// 1.3 根据RouterMap,和lsdb中的adjlsa,构造邻接矩阵
// 设置路由器数目
rtc.SetRouterNum(rMap.GetMapSize())
// 分配矩阵空间
rtc.allocateAdjMatrix()
// 初始化矩阵值
rtc.initMatrix()
// 构造矩阵
err = rtc.makeAdjMatrix(mlsdb, rMap)
if err != nil {
common2.LogError("邻接矩阵构造失败")
}
// 1.4 打印输出路由表计算器
fmt.Println(rMap.ToString())
fmt.Println(rtc.ToString())
fmt.Println("源路由器的邻接数目:", rtc.getNumOfLinkfromAdjMatrix(0))
fmt.Println("另一个路由器的邻接数目:", rtc.getNumOfLinkfromAdjMatrix(1))
// 2. 执行多路径算法
rtc.allocateParent()
rtc.allocateDistance()
// 2.1. 先确定源路由器的邻居路由器数目
rtc.setNoLink(rtc.getNumOfLinkfromAdjMatrix(0))
rtc.allocateLinks()
rtc.allocateLinkCosts()
// 2.2. 获取用于路径计算的稀疏邻接列表。具体操作是填充:c.links,c.linkCosts
rtc.getLinksFromAdjMatrix(0)
//
routers := []*component.Identifier{} // 路由器标识
nexthops := []*NextHop{} // 下一跳
for i := 0; i < rtc.vNoLink; i++ {
// 模拟只有当前邻居i可以访问的情形。即:砍掉除当前邻居路由器外的其他邻接链路
rtc.adjustAdMatrix(0, rtc.links[i], rtc.linkCosts[i])
// 以当前邻居为起点,执行Dijkstra算法。
rtc.doDijkstraPathCalculation(0)
// 用计算结果更新路由表。
rs, ns := rtc.addAllLsNextHopsToRoutingTable(mlsrConfig.GetAdjacencys(), rMap, 0)
routers = append(routers, rs...)
nexthops = append(nexthops, ns...)
}
// 查看执行结果
// 计算器中的上一跳路径,以及开销
fmt.Println(rtc.ToString())
for i := 0; i < len(routers); i++ {
fmt.Println(routers[i].ToUri() + " ")
}
fmt.Println("")
for i := 0; i < len(nexthops); i++ {
fmt.Println(nexthops[i].LogicFaceUri() + "-" +
strconv.FormatUint(nexthops[i].RouteCost.RouteCost(), 10) + " ")
}
}
+373
View File
@@ -0,0 +1,373 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/6/10 11:16
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
common2 "minlib/common"
"minlib/component"
"mlsr/lsa"
"mlsr/lsdb"
)
//
// NamePrefixTable
// @Description: 名称前缀表
//
type NamePrefixTable struct {
// 路由表池:存储“目的路由器标识URI->RTPE”的映射
// 相当于存储了所有拥有前缀的路由表项,并包含每个路由表项对应的前缀列表信息,以及该前缀列表长度useCount
m_rtpool map[string]*RoutingTablePoolEntry
// 名称前缀表项列表
nptEntryList []*NamePrefixTableEntry
// 该名称前缀表所属的本机路由器标识
m_ownRouterName *component.Identifier
// 路由表。包含路由计算器计算出来的每个路由表标识及其对应的下一跳列表
m_routingTable *RoutingTable
// todo fib
}
//
// UpdateFromLsdb
// @Description: 根据lsdb的更新,对名称进行增加、更新或移除
// @receiver t
// @param lsa
// @param updateType
// @param namesToAdd
// @param namesToRemove
//
func (t *NamePrefixTable) UpdateFromLsdb(ilsa lsa.ILsa,
updateType lsdb.LsdbUpdate, namesToAdd []*component.Identifier,
namesToRemove []*component.Identifier) {
// 如果是本地Lsa的增删更操作,则不做响应
if ilsa.GetOriginRouter().ToUri() == t.m_ownRouterName.ToUri() {
return
}
common2.LogInfo("Got update from Lsdb for router: ", ilsa.GetOriginRouter().ToUri())
// lsa安装操作
if updateType == lsdb.INSTALLED {
// 先增加对该路由器标识的条目
t.AddEntry(ilsa.GetOriginRouter(), ilsa.GetOriginRouter())
// 只针对名称LSA进行更新
if ilsa.GetType() == lsa.LsaNAMEType {
// 获取该lsa中的名称前缀列表
nlsa := ilsa.(*lsa.NameLsa)
names := nlsa.GetNamePrefixes()
// 遍历所有名称前缀,将其添加到名称前缀表中
for i := 0; i < len(names); i++ {
if names[i].ToUri() != t.m_ownRouterName.ToUri() {
t.AddEntry(names[i], ilsa.GetOriginRouter())
}
}
}
} else if updateType == lsdb.UPDATED {
// lsa更新操作(增加、删除)
if ilsa.GetType() == lsa.LsaNAMEType {
// 增加
for i := 0; i < len(namesToAdd); i++ {
if namesToAdd[i].ToUri() != t.m_ownRouterName.ToUri() {
t.AddEntry(namesToAdd[i], ilsa.GetOriginRouter())
}
}
// 删除
for i := 0; i < len(namesToRemove); i++ {
if namesToRemove[i].ToUri() != t.m_ownRouterName.ToUri() {
t.RemoveEntry(namesToRemove[i], ilsa.GetOriginRouter())
}
}
}
} else {
// 既不是安装,又不是更新(增加或删除lsa的某些部分) => 那就是删除整个LSA
t.RemoveEntry(ilsa.GetOriginRouter(), ilsa.GetOriginRouter())
if ilsa.GetType() == lsa.LsaNAMEType {
// 获取该lsa中的名称前缀列表
nlsa := ilsa.(*lsa.NameLsa)
names := nlsa.GetNamePrefixes()
// 遍历所有名称前缀,将其添加到名称前缀表中
for i := 0; i < len(names); i++ {
if names[i].ToUri() != t.m_ownRouterName.ToUri() {
t.RemoveEntry(names[i], ilsa.GetOriginRouter())
}
}
}
}
}
//
// findNamePrefix
// @Description: 查找名称前缀
// @receiver t
// @param name
// @return int 返回-1时表示没有查找到
//
func (t *NamePrefixTable) findNamePrefix(name *component.Identifier) int {
for i := 0; i < len(t.nptEntryList); i++ {
if t.nptEntryList[i].GetNamePrefix().ToUri() == name.ToUri() {
return i
}
}
return -1
}
//
// deleteNamePrefix
// @Description: 根据名称前缀的索引坐标,删除指定名称前缀
// @receiver t
// @param nameIndex
//
func (t *NamePrefixTable) deleteNamePrefix(nameIndex int) {
var newList []*NamePrefixTableEntry
for i := 0; i < len(t.nptEntryList); i++ {
if i != nameIndex {
newList = append(newList, t.nptEntryList[i])
}
}
t.nptEntryList = newList
}
//
// AddEntry
// @Description: 此方法将路由器添加到名称前缀表条目中。如果名称前缀表条目不存在,则会创建它。
// 该方法将首先查看其缓存项的本地池,以找到destRouter的路由信息。
// 如果在那里找不到,它将构造一个,并用路由表中适当的RoutingTable条目中的信息填充它。
// 如果没有匹配项,它将实例化它,但没有下一跳。FIB也将收到NPT条目变更的通知。
// @receiver t
// @param name
// @param destRouter
//
func (t *NamePrefixTable) AddEntry(name *component.Identifier, destRouter *component.Identifier) {
// 检查播发的名称前缀是否已在表中。
nameIndex := t.findNamePrefix(name)
// 查找目的路由器标识是否在路由表项缓存池中
v, ok := t.m_rtpool[destRouter.ToUri()]
// 如果池中没有该目的路由器的路由表项,也即找不到去到name的路由路径,就加一个缓存池项
if !ok {
// 查看路由表,看是否有包含该目的路由器的条目
rte := t.m_routingTable.FindRoutingTableEntry(destRouter)
// 如果路由表里也没有,那我们在缓存里加一个新的条目(虽然没路径)
rtpe := new(RoutingTablePoolEntry)
if rte == nil {
rtpe.InitDest(destRouter, 0)
} else {
// 有的话,直接从路由器中取出该条目,放入缓存池
rtpe.InitRTE(rte, 0)
}
// 放入缓存池,并将v刷新为该缓存池项
v = t.AddRtpeToPool(rtpe)
}
// 更新npt项,并通知给fib
if nameIndex < 0 {
// 如果NPT中没有该name
common2.LogDebug("Adding origin: " + v.GetDestination().ToUri() +
" to a new name prefix: " + name.ToUri())
// 构造名称前缀表项,并添加之
npte := new(NamePrefixTableEntry)
npte.m_namePrefix = name
npte.AddRoutingTableEntry(v) // useCount在这个时候会+1
npte.GenerateNhlfromRteList()
t.nptEntryList = append(t.nptEntryList, npte)
nameIndex = t.findNamePrefix(name)
// 如果这个条目有下一跳,我们需要通知FIB
if len(npte.GetNextHops()) > 0 {
common2.LogDebug("Updating FIB with next hops for ", npte.GetNamePrefix().ToUri())
// todo 更新fib m_fib.update(name, npte->getNexthopList());
} else {
// 如果没有下一跳
// 路由表可以重新计算并添加一个没有下一跳的路由表条目,以替换现有的路由表条目。
// 在这种情况下,通过下一个跃点无法再访问名称前缀,应将其从FIB中删除。
// 但是,前缀应该保留在名称前缀表中,因为未来的路由表计算可能会添加下一跳。
common2.LogDebug(npte.GetNamePrefix().ToUri() + " has no next hops; removing from FIB")
// todo 更新fib m_fib.remove(name);
}
} else {
// 如果NPT有这个name
common2.LogDebug("Adding origin: " + v.GetDestination().ToUri() +
" to existing prefix: " + name.ToUri())
// 更新之
t.nptEntryList[nameIndex].AddRoutingTableEntry(v) // useCount在这个时候会+1
t.nptEntryList[nameIndex].GenerateNhlfromRteList()
// FIB通知
if len(t.nptEntryList[nameIndex].GetNextHops()) > 0 {
common2.LogDebug("Updating FIB with next hops for ",
t.nptEntryList[nameIndex].GetNamePrefix().ToUri())
// todo 更新fib m_fib.update(name, npte->getNexthopList());
} else {
common2.LogDebug(t.nptEntryList[nameIndex].GetNamePrefix().ToUri() +
" has no next hops; removing from FIB")
// todo 更新fib m_fib.remove(name);
}
}
// 将此NPT的引用添加到RTPE中。
v.NamePrefixTableEntries[t.nptEntryList[nameIndex].GetNamePrefix().ToUri()] = t.nptEntryList[nameIndex]
}
//
// RemoveEntry
// @Description: 此方法从条目中删除目标。如果传递了无效的“名称-目标”对,也不会失败。
// 删除后,如果RoutingTablePoolEntry的使用计数为0,则会将其从表中删除。
// 此外,如果名称前缀没有与之关联的路由表条目,则会将其从NPT中删除。
// 在任何情况下,FIB都会被告知这些变化。
// @receiver t
// @param name
// @param destRouter
//
func (t *NamePrefixTable) RemoveEntry(name *component.Identifier, destRouter *component.Identifier) {
common2.LogDebug("Removing origin: " + destRouter.ToUri() + " from " + name.ToUri())
// 根据目的路由器标识,获取其在路由条目缓存池中的条目
rtpe, ok := t.m_rtpool[destRouter.ToUri()]
if !ok {
// 如果没有找到,则不进行后续处理
common2.LogDebug("No entry for origin: " + destRouter.ToUri() +
" found, so it cannot be removed from prefix: " + name.ToUri())
return
}
// 查找名称前缀
nameIndex := t.findNamePrefix(name)
if nameIndex >= 0 {
common2.LogDebug("Removing origin: " + rtpe.GetDestination().ToUri() +
" from prefix: " + name.ToUri())
// 判断该缓存表项在被删除一个与某前缀的关联之后,其使用数是否为零,如果是,则删除该引用。
useCount := t.nptEntryList[nameIndex].RemoveRoutingTableEntry(rtpe)
if useCount == 0 {
t.DeleteRtpeFromPool(rtpe)
}
// 1 如果前缀是路由器前缀,并且没有任何其他路由表条目,则已从LSDB中删除与该原始路由器关联的邻接/坐标LSA,
// 因此应从名称前缀表中删除路由器前缀。
// 2 如果前缀是播发的名称前缀:如果另一个路由器播发此名称前缀,
// 则RteList应具有该路由器的另一个条目;下一个跃点应重新计算并安装在FIB中。
// 3 如果没有其他路由器播发此名称前缀,则RteList应为空,并且可以从名称前缀表中删除前缀。
// 一旦新名称LSA播发此前缀,将创建前缀的新条目。
if t.nptEntryList[nameIndex].GetRteListSize() == 0 {
common2.LogDebug(name.ToUri() + " has no routing table entries;" +
" removing from table and FIB")
t.deleteNamePrefix(nameIndex)
// todo 删除fib中的该name m_fib.remove(name);
} else {
common2.LogDebug(name.ToUri() + " has other routing table entries;" +
" updating FIB with next hops")
t.nptEntryList[nameIndex].GenerateNhlfromRteList()
// todo 更新fib m_fib.update(name, (*nameItr)->getNexthopList());
}
} else {
common2.LogDebug("Attempted to remove origin: " + rtpe.GetDestination().ToUri() +
" from non-existent prefix: " + name.ToUri())
}
}
//
// isNextHopsEqual
// @Description: 遍历查看两个下一跳列表是否完全一致
// @param hops1
// @param hops2
// @return bool
//
func isNextHopsEqual(hops1 []*NextHop, hops2 []*NextHop) bool {
// 长度不等,则false
if len(hops1) != len(hops2) {
return false
}
// 遍历,如果有一个不相等,则false
for i := 0; i < len(hops1); i++ {
if hops1[i].LogicFaceUri() != hops2[i].LogicFaceUri() ||
hops1[i].RouteCost.RouteCost() != hops2[i].RouteCost.RouteCost() {
return false
}
}
return true
}
//
// UpdateWithNewRoute
// @Description: 接收假定为详尽的条目列表,并使用条目中相应条目中包含的下一跳信息更新每个池条目。
// 如果找不到条目,则假定该池条目的目标不可访问,其下一跳信息将被删除。
// @receiver t
// @param entries
//
func (t *NamePrefixTable) UpdateWithNewRoute(entries []*RoutingTableEntry) {
common2.LogDebug("Updating table with newly calculated routes")
// 遍历名称前缀表中的路由表缓存池
for _, rtpe := range t.m_rtpool {
// 查看当前缓存表项的目的路由器,是否在传入的真路由表项里可以找到对应的
sameIndex := -1 // 默认没找到
for i := 0; i < len(entries); i++ {
if entries[i].GetDestination().ToUri() == rtpe.GetDestination().ToUri() {
sameIndex = i
}
}
// 根据缓存池与原路由表项的差异,将缓存池更新
if sameIndex >= 0 && !isNextHopsEqual(rtpe.GetNextHops(), entries[sameIndex].GetNextHops()) {
// 如果找到了对应条目,且两个路由表条目的下一跳列表不一致
common2.LogDebug("Routing entry: " + rtpe.GetDestination().ToUri() + " has changed next-hops.")
// 更新rtpe的下一跳列表
rtpe.SetNexthopList(entries[sameIndex].NextHopList)
// 更新rtpe的每个名称前缀表项
for _, nameEntry := range rtpe.NamePrefixTableEntries {
t.AddEntry(nameEntry.GetNamePrefix(), rtpe.GetDestination())
}
} else if sameIndex < 0 {
// 没有找到对应条目,说明到该路由器的路径已经无了无了无了~
common2.LogDebug("Routing entry: " + rtpe.GetDestination().ToUri() + " now has no next-hops.")
// 更新rtpe的下一跳列表:清空
rtpe.Clear()
// 更新rtpe的每个名称前缀表项
for _, nameEntry := range rtpe.NamePrefixTableEntries {
t.AddEntry(nameEntry.GetNamePrefix(), rtpe.GetDestination())
}
} else {
// 有找到对应条目,但是两个条目的下一跳列表完全一致
common2.LogDebug("No change in routing entry:" + rtpe.GetDestination().ToUri() +
", no action necessary.")
}
}
}
//
// AddRtpeToPool
// @Description: 将RoutingTablePoolEntry添加到NPT的本地池。
// 在C++版实现中,返回值将使用共享指针,因为它消除了处理生命周期问题的复杂hacks,并简化了内存管理。
// @receiver t
// @param rtpe
// @return *RoutingTablePoolEntry
//
func (t *NamePrefixTable) AddRtpeToPool(rtpe *RoutingTablePoolEntry) *RoutingTablePoolEntry {
t.m_rtpool[rtpe.GetDestination().ToUri()] = rtpe
return rtpe
}
//
// DeleteRtpeFromPool
// @Description: 从池中删除池项。
// @receiver t
// @param rtpe
//
func (t *NamePrefixTable) DeleteRtpeFromPool(rtpe *RoutingTablePoolEntry) {
// 查看是否有该条目
_, ok := t.m_rtpool[rtpe.GetDestination().ToUri()]
if !ok {
common2.LogDebug("Attempted to delete non-existent origin: " +
rtpe.GetDestination().ToUri() + " from NPT routing table entry storage pool.")
}
delete(t.m_rtpool, rtpe.GetDestination().ToUri())
}
+173
View File
@@ -0,0 +1,173 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/6/9 15:07
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
common2 "minlib/common"
"minlib/component"
)
//
// NamePrefixTableEntry
// @Description: 名称前缀表项
//
type NamePrefixTableEntry struct {
// 名称前缀
m_namePrefix *component.Identifier
// 保存路由表池项的切片。切片真好用。
// 这是因为,由于支持网内缓存,一个名称前缀可能对应多个路由器标识符。
// 名称前缀标项,和路由表项,是多对多的关系。
m_rteList []*RoutingTablePoolEntry
// 下一跳列表
NextHopList
}
//
// GetNamePrefix
// @Description: 获取所表示的名称前缀
// @receiver e
// @return *component.Identifier
//
func (e *NamePrefixTableEntry) GetNamePrefix() *component.Identifier {
return e.m_namePrefix
}
//
// GetRteList
// @Description: 获取与该名称前缀所关联的路由表池项
// @receiver e
// @return []*RoutingTablePoolEntry
//
func (e *NamePrefixTableEntry) GetRteList() []*RoutingTablePoolEntry {
return e.m_rteList
}
//
// ResetRteListNextHop
// @Description: 重置播发此名称前缀的所有路由表项的下一跳列表。
// @receiver e
//
func (e *NamePrefixTableEntry) ResetRteListNextHop() {
for i := 0; i < len(e.m_rteList); i++ {
e.m_rteList[i].Clear()
}
}
//
// GetRteListSize
// @Description: 返回所关联的路由表池项的数目。即当前名称前缀被哪些路由器所拥有。
// @receiver e
// @return int
//
func (e *NamePrefixTableEntry) GetRteListSize() int {
return len(e.m_rteList)
}
//
// GetNexthopList
// @Description: 获取本名称前缀所关联的下一跳列表。
// @receiver e
// @return []*NextHop
//
func (e *NamePrefixTableEntry) GetNexthopList() *NextHopList {
return &e.NextHopList
}
//
// GenerateNhlfromRteList
// @Description: 收集此条目的路由条目播发的所有下一个跃点。
// 其逻辑主要是将所有关联的路由表项的下一跳全部加进来。
// @receiver e
//
func (e *NamePrefixTableEntry) GenerateNhlfromRteList() {
// 清空旧的下一跳列表
e.NextHopList.Clear()
// 遍历关联的每个路由表条目
for i := 0; i < len(e.m_rteList); i++ {
// 遍历路由表条目的下一跳列表
for j := 0; j < e.m_rteList[i].NextHopList.Size(); j++ {
e.NextHopList.AddNextHop(e.m_rteList[i].nextHops[j])
}
}
}
//
// findRtpe
// @Description: 查找指定池条目
// @receiver e
// @param rtpePtr
// @return int 没找到时返回-1
//
func (e *NamePrefixTableEntry) findRtpe(rtpePtr *RoutingTablePoolEntry) int {
for i := 0; i < len(e.m_rteList); i++ {
if e.m_rteList[i].IsEqual(rtpePtr) {
return i
}
}
return -1
}
//
// deleteRtpe
// @Description: 删除指定索引位置的rtpe
// @receiver e
// @param index
//
func (e *NamePrefixTableEntry) deleteRtpe(index int) {
var tmpList []*RoutingTablePoolEntry
for i := 0; i < len(e.m_rteList); i++ {
if i != index {
tmpList = append(tmpList, e.m_rteList[i])
}
}
e.m_rteList = tmpList
}
//
// RemoveRoutingTableEntry
// @Description: 从该NPT条目中删除一个路由表条目
// @receiver e
// @param rtpePtr
// @return uint64 使用刚刚删除的路由条目的NPT数。
//
func (e *NamePrefixTableEntry) RemoveRoutingTableEntry(rtpePtr *RoutingTablePoolEntry) uint64 {
index := e.findRtpe(rtpePtr)
if index >= 0 {
// 该条目的使用数减一
e.m_rteList[index].DecrementUseCount()
// 删除该条目与本名称前缀的关联
// 1. 删掉:条目 -> 前缀
delete(e.m_rteList[index].NamePrefixTableEntries, e.GetNamePrefix().ToUri())
// 2. 删掉:前缀 -> 条目
e.deleteRtpe(index)
} else {
common2.LogError("Routing entry for: " + rtpePtr.GetDestination().ToUri() +
" not found in NPT entry: " + e.GetNamePrefix().ToUri())
}
return rtpePtr.m_useCount
}
//
// AddRoutingTableEntry
// @Description:将路由表池项添加到此NPT项的列表中
// (提醒:每个RTPE都有下一个跃点列表)。它们用于计算此条目的整体下一跳列表。
// @receiver e
// @param rtpePtr
//
func (e *NamePrefixTableEntry) AddRoutingTableEntry(rtpePtr *RoutingTablePoolEntry) {
index := e.findRtpe(rtpePtr)
// 先确定它是一个新的路由表条目
if index < 0 {
// 其使用数加一
rtpePtr.IncrementUseCount()
// 将其加入list
e.m_rteList = append(e.m_rteList, rtpePtr)
}
}
+115
View File
@@ -0,0 +1,115 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/5 20:45
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"minlib/encoding"
"mlsr/extensions"
)
//
// NextHop
// @Description: 下一跳
//
type NextHop struct {
encoding.SelfEncodingBase
ConnectingLogicFaceUri // 指示接口
RouteCost // 路由开销
IsHyperbolic bool // 是不是双曲路由(v0.1暂时用不到)
}
//
// NewNextHop
// @Description: 新建一个下一跳结构体
// @param uri
// @param cost
// @return *NextHop
// @return error
//
func NewNextHop(uri string, cost uint64) (*NextHop, error) {
// todo 检查传入的参数格式是否有效
nextHop := new(NextHop)
nextHop.IsHyperbolic = false
nextHop.SetLogicFaceUri(uri)
nextHop.SetRouteCost(cost)
return nextHop, nil
}
//
// WireEncode
// @Description: 线速编码
// @receiver l
// @param encoder
// @return int
// @return error
//
func (l *NextHop) WireEncode(encoder *encoding.Encoder) (int, error) {
totalLength := 0
// TLV-Value
tmpLen, err := l.ConnectingLogicFaceUri.WireEncode(encoder)
if err != nil {
return 0, err
}
totalLength += tmpLen
tmpLen, err = l.RouteCost.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.TlvMlsrNextHop)
if err != nil {
return 0, err
}
totalLength += tmpLen
return totalLength, nil
}
//
// WireDecode
// @Description: 线速解码
// @receiver l
// @param block
// @return error
//
func (l *NextHop) WireDecode(block *encoding.Block) error {
// 检查 TLV-TYPE 是否正确
if err := encoding.ExpectType(block.GetType(), extensions.TlvMlsrNextHop); err != nil {
return err
}
// 首先解析子Block
if err := block.ParseSubElements(); err != nil {
return err
}
// 提取参数
for _, parameter := range block.GetSubElements() {
switch parameter.GetType() {
case extensions.TlvMlsrConnectingLogicFaceUri:
if err := l.ConnectingLogicFaceUri.WireDecode(parameter); err != nil {
return err
}
case extensions.TlvMlsrRouteCost:
if err := l.RouteCost.WireDecode(parameter); err != nil {
return err
}
}
}
return nil
}
+209
View File
@@ -0,0 +1,209 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/5 20:44
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"errors"
"minlib/encoding"
"mlsr/extensions"
"strconv"
)
type NextHopContainer []*NextHop
//
// NextHopList
// @Description: 下一跳列表
//
type NextHopList struct {
encoding.SelfEncodingBase
nextHops NextHopContainer
}
//
// ToString
// @Description: 转string。用于测试
// @receiver l
// @return string
//
func (l *NextHopList) ToString() string {
res := "----------------\n"
for i := 0; i < len(l.nextHops); i++ {
res += l.nextHops[i].LogicFaceUri() + " "
res += strconv.FormatUint(l.nextHops[i].RouteCost.RouteCost(), 10) + " "
res += strconv.FormatBool(l.nextHops[i].IsHyperbolic) + " \n"
}
res += "----------------\n"
return res
}
//
// GetNextHops
// @Description: 获取下一跳列表
// @receiver l
// @return []*NextHop
//
func (l *NextHopList) GetNextHops() []*NextHop {
return l.nextHops
}
//
// findSameUriNextHop
// @Description: 找到uri一致的下一跳表项
// @receiver l
// @param hop
// @return int 找不到时,返回-1
//
func (l *NextHopList) findSameUriNextHop(hop *NextHop) int {
for i := 0; i < len(l.nextHops); i++ {
if l.nextHops[i].LogicFaceUri() == hop.LogicFaceUri() {
return i
}
}
return -1
}
//
// findSameNextHop
// @Description: 找到uri和cost都一致的下一跳表项
// @receiver l
// @param hop
// @return int 找不到,返回-1
//
func (l *NextHopList) findSameNextHop(hop *NextHop) int {
for i := 0; i < len(l.nextHops); i++ {
if (l.nextHops[i].LogicFaceUri() == hop.LogicFaceUri()) &&
(l.nextHops[i].RouteCost.RouteCost() == hop.RouteCost.RouteCost()) {
return i
}
}
return -1
}
//
// AddNextHop
// @Description: 增加一个下一跳表项。1. 如果不存在同uri,则插入;2. 如果存在,但cost不同,则更新它
// @receiver l
// @param hop
//
func (l *NextHopList) AddNextHop(hop *NextHop) {
index := l.findSameUriNextHop(hop)
if index < 0 {
l.nextHops = append(l.nextHops, hop)
} else if l.nextHops[index].RouteCost.RouteCost() != hop.RouteCost.RouteCost() {
l.nextHops[index].RouteCost.SetRouteCost(hop.RouteCost.RouteCost())
}
}
//
// RemoveNextHop
// @Description: 删除一个下一跳表项。
// @receiver l
// @param hop
//
func (l *NextHopList) RemoveNextHop(hop *NextHop) {
// 查找该条目索引
index := l.findSameUriNextHop(hop)
if index >= 0 {
l.nextHops = append(l.nextHops[:index], l.nextHops[index+1:]...)
}
}
//
// Size
// @Description: 返回表项数目
// @receiver l
// @return int
//
func (l *NextHopList) Size() int {
return len(l.nextHops)
}
//
// Clear
// @Description: 清空列表
// @receiver l
//
func (l *NextHopList) Clear() {
l.nextHops = []*NextHop{}
}
//
// WireEncode
// @Description: 线速编码
// @receiver l
// @param encoder
// @return int
// @return error
//
func (l *NextHopList) WireEncode(encoder *encoding.Encoder) (int, error) {
// 判断列表长度,为0则抛出错误
if len(l.nextHops) == 0 {
return 0, errors.New("Invalid NextHopList, expect at least one NextHop!")
}
totalLength := 0
// 编码 TLV-VALUE
// 反向遍历,可以保证解码的时候正向输出
for i := len(l.nextHops) - 1; i >= 0; i-- {
if l.nextHops[i] == nil {
continue
}
tmpLen, err := l.nextHops[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.TlvMlsrNextHopList)
if err != nil {
return 0, err
}
totalLength += tmpLen
return totalLength, nil
}
//
// WireDecode
// @Description: 线速解码
// @receiver l
// @param block
// @return error
//
func (l *NextHopList) WireDecode(block *encoding.Block) error {
// 检查 TLV-TYPE 是否正确
if err := encoding.ExpectType(block.GetType(), extensions.TlvMlsrNextHopList); err != nil {
return err
}
// 解析子 TLV
if err := block.ParseSubElements(); err != nil {
return err
}
hopContainer := make(NextHopContainer, len(block.GetSubElements()))
for index, element := range block.GetSubElements() {
var nextHop NextHop
err := nextHop.WireDecode(element)
if err != nil {
return err
}
hopContainer[index] = &nextHop
}
l.nextHops = hopContainer
return nil
}
+190
View File
@@ -0,0 +1,190 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/6/16 17:08
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"fmt"
"minlib/encoding"
"testing"
)
//
// TestNextHopList_AddNextHop
// @Description: 测试构造下一跳列表
// @param t
//
func TestNextHopList_AddNextHop(t *testing.T) {
// 构造三个下一跳
nthop1, _ := NewNextHop("/hop1", 10)
nthop2, _ := NewNextHop("/hop2", 20)
nthop3, _ := NewNextHop("/hop3", 30)
// 构造hoplist
hopList := new(NextHopList)
hopList.AddNextHop(nthop1)
hopList.AddNextHop(nthop2)
hopList.AddNextHop(nthop3)
// 打印长度
fmt.Println(hopList.Size())
// 打印所有下一跳
fmt.Println(hopList.ToString())
}
//
// TestNextHopList_find
// @Description: 测试查找
// @param t
//
func TestNextHopList_find(t *testing.T) {
// 构造三个下一跳
nthop1, _ := NewNextHop("/hop1", 10)
nthop2, _ := NewNextHop("/hop2", 20)
nthop3, _ := NewNextHop("/hop3", 30)
// 构造hoplist
hopList := new(NextHopList)
hopList.AddNextHop(nthop1)
hopList.AddNextHop(nthop2)
hopList.AddNextHop(nthop3)
// 测试查找相同Uri
ntTest, _ := NewNextHop("/hop2", 111)
i1 := hopList.findSameUriNextHop(ntTest)
fmt.Println("第二个下标:", i1)
ntTest, _ = NewNextHop("/hopTest", 111)
i2 := hopList.findSameUriNextHop(ntTest)
fmt.Println("没找到下标:", i2)
// 测试查找完全相同下一跳
ntTest, _ = NewNextHop("/hop2", 20)
i1 = hopList.findSameNextHop(ntTest)
fmt.Println("第二个下标:", i1)
ntTest.SetRouteCost(555)
i2 = hopList.findSameNextHop(ntTest)
fmt.Println("没找到下标:", i2)
}
//
// TestNextHopList_RemoveNextHop
// @Description: 测试删除
// @param t
//
func TestNextHopList_RemoveNextHop(t *testing.T) {
// 构造三个下一跳
nthop1, _ := NewNextHop("/hop1", 10)
nthop2, _ := NewNextHop("/hop2", 20)
nthop3, _ := NewNextHop("/hop3", 30)
// 构造hoplist
hopList := new(NextHopList)
hopList.AddNextHop(nthop1)
hopList.AddNextHop(nthop2)
hopList.AddNextHop(nthop3)
// 打印长度
fmt.Println(hopList.Size())
// 打印所有下一跳
fmt.Println(hopList.ToString())
// 删除
npTest, _ := NewNextHop("/hop1", 10)
hopList.RemoveNextHop(npTest)
// 打印长度
fmt.Println(hopList.Size())
// 打印所有下一跳
fmt.Println(hopList.ToString())
// 删除一个只有uri相同
npTest, _ = NewNextHop("/hop3", 100)
hopList.RemoveNextHop(npTest)
// 打印长度
fmt.Println(hopList.Size())
// 打印所有下一跳
fmt.Println(hopList.ToString())
// 删除一个uri不同
npTest, _ = NewNextHop("/hoppp", 100)
hopList.RemoveNextHop(npTest)
// 打印长度
fmt.Println(hopList.Size())
// 打印所有下一跳
fmt.Println(hopList.ToString())
}
//
// TestNextHopList_WireEncode
// @Description: 测试编码
// @param t
//
func TestNextHopList_WireEncode(t *testing.T) {
// 构造三个下一跳
nthop1, _ := NewNextHop("/hop1", 10)
nthop2, _ := NewNextHop("/hop2", 20)
nthop3, _ := NewNextHop("/hop3", 30)
// 构造hoplist
hopList := new(NextHopList)
hopList.AddNextHop(nthop1)
hopList.AddNextHop(nthop2)
hopList.AddNextHop(nthop3)
// 编码
encoder := encoding.Encoder{}
err := encoder.EncoderReset(encoding.MaxPacketSize, 0)
if err != nil {
fmt.Println("NextHopList编码报错,", err.Error())
return
}
length, err := hopList.WireEncode(&encoder)
if err != nil {
t.Fatal("NextHopList编码失败", err.Error())
}
// 获取编码
buf, err := encoder.GetBuffer()
if err != nil {
t.Fatal("NextHopList获取buffer结果失败", err.Error())
}
// 打印编码结果。如果可以正确解码,则说明编码成功
fmt.Println(length)
for i := 0; i < len(buf); i++ {
fmt.Print(buf[i], ", ")
}
fmt.Println()
}
//
// TestNextHopList_WireDecode
// @Description: 测试解码
// @param t
//
func TestNextHopList_WireDecode(t *testing.T) {
// 由数组构建block
var buf = [58]byte{241, 1, 188, 54, 241, 1, 187, 14, 241, 1, 186,
1, 10, 241, 1, 185, 5, 47, 104, 111, 112, 49, 241, 1, 187, 14,
241, 1, 186, 1, 20, 241, 1, 185, 5, 47, 104, 111, 112, 50, 241,
1, 187, 14,
241, 1, 186, 1, 30, 241, 1, 185, 5, 47, 104, 111, 112, 51}
block, err := encoding.CreateBlockByBuffer(buf[:], true)
if err != nil {
fmt.Println("创建block失败 ", err.Error())
return
}
// 由Block构建结构体,并打印变量
base := new(NextHopList)
err = base.WireDecode(block)
if err != nil {
fmt.Println("线性解码失败 ", err.Error())
return
}
fmt.Println(base.ToString())
}
+96
View File
@@ -0,0 +1,96 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/6/16 16:52
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"fmt"
"minlib/encoding"
"testing"
)
//
// TestNewNextHop
// @Description: 测试构造
// @param t
//
func TestNewNextHop(t *testing.T) {
nexthop, err := NewNextHop("/test", 543)
if err == nil {
fmt.Println(nexthop.IsHyperbolic)
fmt.Println(nexthop.RouteCost.RouteCost())
fmt.Println(nexthop.LogicFaceUri())
} else {
fmt.Println("测试NewNextHop报错,", err.Error())
}
}
//
// TestNextHop_WireEncode
// @Description: 测试编码
// @param t
//
func TestNextHop_WireEncode(t *testing.T) {
// 构造
nexthop, err := NewNextHop("/test", 543)
if err != nil {
fmt.Println("NewNextHop报错,", err.Error())
return
}
// 编码
encoder := encoding.Encoder{}
err = encoder.EncoderReset(encoding.MaxPacketSize, 0)
if err != nil {
fmt.Println("NextHop编码报错,", err.Error())
return
}
length, err := nexthop.WireEncode(&encoder)
if err != nil {
t.Fatal("NextHop编码失败", err.Error())
}
// 获取编码
buf, err := encoder.GetBuffer()
if err != nil {
t.Fatal("NextHop获取buffer结果失败", err.Error())
}
// 打印编码结果。如果可以正确解码,则说明编码成功
fmt.Println(length)
for i := 0; i < len(buf); i++ {
fmt.Print(buf[i], ", ")
}
fmt.Println()
}
//
// TestNextHop_WireDecode
// @Description: 测试解码
// @param t
//
func TestNextHop_WireDecode(t *testing.T) {
// 由数组构建block
var buf = [19]byte{241, 1, 187, 15, 241, 1, 186, 2, 2, 31, 241, 1, 185, 5, 47, 116, 101, 115, 116}
block, err := encoding.CreateBlockByBuffer(buf[:], true)
if err != nil {
fmt.Println("创建block失败 ", err.Error())
return
}
// 由Block构建结构体,并打印变量
base := new(NextHop)
err = base.WireDecode(block)
if err != nil {
fmt.Println("线性解码失败 ", err.Error())
return
}
fmt.Println(base.IsHyperbolic)
fmt.Println(base.RouteCost.RouteCost())
fmt.Println(base.LogicFaceUri())
}
+77
View File
@@ -0,0 +1,77 @@
// Package lsa
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/3/10 10:39
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"math"
"minlib/component"
"minlib/encoding"
"mlsr/extensions"
)
const (
DEFAULT_LINK_COST = 10
NON_ADJACENT_COST = math.MaxUint64
)
//
// RouteCost
// @Description: 链路开销
//
type RouteCost struct {
component.CommonUint64
}
//
// RouteCost
// @Description: 获取开销
// @receiver l
// @return uint64
//
func (l *RouteCost) RouteCost() uint64 {
return l.CommonUint64.Value()
}
//
// SetRouteCost
// @Description: 设置开销
// @receiver l
// @param linkCost
//
func (l *RouteCost) SetRouteCost(linkCost uint64) {
l.CommonUint64.SetValue(linkCost)
}
//
// WireEncode
// @Description: 线速编码
// @receiver l
// @param encoder
// @return int
// @return error
//
func (l *RouteCost) WireEncode(encoder *encoding.Encoder) (int, error) {
l.CommonUint64.SetTlvType(extensions.TlvMlsrRouteCost)
return l.CommonUint64.WireEncode(encoder)
}
//
// WireDecode
// @Description: 线速解码
// @receiver l
// @param block
// @return error
//
func (l *RouteCost) WireDecode(block *encoding.Block) error {
// 检查type是否正确
if err := encoding.ExpectType(block.GetType(),extensions.TlvMlsrRouteCost); err!=nil {
return err
}
return l.CommonUint64.WireDecode(block)
}
+81
View File
@@ -0,0 +1,81 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/26 12:02
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"bytes"
"fmt"
"minlib/encoding"
"testing"
)
//
// TestRouteCost_SetRouteCost
// @Description: 测试设置属性
// @param t
//
func TestRouteCost_SetRouteCost(t *testing.T) {
lsaSequenceNumber := RouteCost{}
lsaSequenceNumber.SetRouteCost(77)
if lsaSequenceNumber.RouteCost() != 77 {
t.Fatal("RouteCost设置失败")
}
}
//
// TestRouteCost_WireEncode
// @Description: 测试编码
// @param t
//
func TestRouteCost_WireEncode(t *testing.T) {
linkCost := RouteCost{}
linkCost.SetRouteCost(1234)
encoder := encoding.Encoder{}
encoder.EncoderReset(encoding.MaxPacketSize, 0)
length, err := linkCost.WireEncode(&encoder)
if err != nil {
t.Fatal("RouteCost编码失败", err.Error())
}
buf, err := encoder.GetBuffer()
if err != nil {
t.Fatal("RouteCost获取buffer结果失败", err.Error())
}
res := []byte{241, 1, 186, 2, 4, 210}
if length != 6 || !bytes.Equal(buf, res) {
fmt.Println("buf: ", buf)
fmt.Println("res: ", res)
t.Fatal("RouteCost编码内容错误", length, buf)
}
}
//
// TestRouteCost_WireDecode
// @Description: 测试解码
// @param t
//
func TestRouteCost_WireDecode(t *testing.T) {
var buf [6]byte = [6]byte{241, 1, 186, 2, 4, 210}
block, err := encoding.CreateBlockByBuffer(buf[:], true)
if err != nil {
t.Fatal("RouteCost创建Block失败", err.Error())
}
linkCost := RouteCost{}
err = linkCost.WireDecode(block)
if err != nil {
t.Fatal("RouteCost解码失败", err.Error())
}
if linkCost.RouteCost() != 1234 {
t.Fatal("RouteCost解码内容错误", linkCost.RouteCost())
}
}
+182
View File
@@ -0,0 +1,182 @@
// Package route
// @Author: Wang Feng
// @Description:
// 参考博文:https://www.zhaoyanchang.com/detail/31.html
// @Version: 0.1.0
// @Date: 2022/5/10 15:26
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"encoding/json"
"minlib/component"
"mlsr/lsa"
"strconv"
"sync"
)
//
// RouterMap
// @Description: 给每个路由器标识分配一个索引号
//
type RouterMap struct {
// 存储:路由器到索引值的映射
routerToNumberMap map[string]int
// 存储:索引值到路由器的映射
numberToRouterMap map[int]string
// 存储:路由器URI到其路由器标识的映射 => 相同URI的路由器标识被视为同一个路由器标识
uriToIdentifierMap map[string]*component.Identifier
// 初始值为0,每次加一递增
mappingIndex int
// 并发加锁
mapLock *sync.RWMutex
}
//
// ToString
// @Description: 转string,便于测试查看map的状态
// @receiver m
// @return string
//
func (m *RouterMap) ToString() string {
s := ""
s += "MappingIndex:" + strconv.Itoa(m.mappingIndex) + " "
// 第一个map
dataType, _ := json.Marshal(m.routerToNumberMap)
dataString := string(dataType)
s += dataString + " "
// 第二个map
dataType, _ = json.Marshal(m.numberToRouterMap)
dataString = string(dataType)
s += dataString + " "
return s
}
//
// Store
// @Description: 存入一个路由器标识
// @receiver m
// @param routerName
//
func (m *RouterMap) Store(routerName *component.Identifier) {
m.mapLock.Lock()
uri := routerName.ToUri()
_, ok := m.uriToIdentifierMap[uri]
if !ok {
// 如果不存在,则将其存入三张map
m.uriToIdentifierMap[uri] = routerName
m.routerToNumberMap[uri] = m.mappingIndex
m.numberToRouterMap[m.mappingIndex] = uri
m.mappingIndex++
}
m.mapLock.Unlock()
}
//
// CreateFromAdjLsdb
// @Description: 根据从LSDB中取出来的邻接LSA,进行RouterMap的生成
// @receiver m
// @param lsas
// @return error
//
func (m *RouterMap) CreateFromAdjLsdb(lsas []lsa.ILsa) error {
for i := 0; i < len(lsas); i++ {
// 1. 先将LSA解析为邻接LSA
adjLsa := (lsas[i]).(*lsa.AdjLsa)
// 2. 将每个邻接lsa的源路由,以及所有该源路由的邻接路由器,都加入到map中
m.Store(adjLsa.GetOriginRouter())
adjs := adjLsa.GetAdjList()
for j := 0; j < len(adjs); j++ {
m.Store(adjs[j].GetNeighborRouterIdentifier())
}
}
return nil
}
//
// Delete
// @Description: 删除一个路由器标识。在实际使用中用不到,故先小写其字母。
// @receiver m
// @param routerName
//
func (m *RouterMap) delete(routerName *component.Identifier) {
m.mapLock.Lock()
uri := routerName.ToUri()
value, ok := m.routerToNumberMap[uri]
if ok {
// 如果存在,则将其从三张map中删除
delete(m.uriToIdentifierMap, uri)
delete(m.routerToNumberMap, uri)
delete(m.numberToRouterMap, value)
}
m.mapLock.Unlock()
}
//
// GetRouterNameByMappingNo
// @Description: 根据索引获取路由器标识
// @receiver m
// @param index
// @return *component.Identifier
// @return bool
//
func (m *RouterMap) GetRouterNameByMappingNo(index int) (*component.Identifier, bool) {
m.mapLock.Lock()
defer m.mapLock.Unlock()
value, ok := m.numberToRouterMap[index]
if ok {
idenValue := m.uriToIdentifierMap[value]
return idenValue, true
}
return nil, false
}
//
// GetMappingNoByRouterName
// @Description: 根据标识获取索引
// @receiver m
// @param routerName
// @return int
// @return bool
//
func (m *RouterMap) GetMappingNoByRouterName(routerName *component.Identifier) (int, bool) {
m.mapLock.Lock()
defer m.mapLock.Unlock()
value, ok := m.routerToNumberMap[routerName.ToUri()]
return value, ok
}
//
// GetMapSize
// @Description: 获取路由器数目
// @receiver m
// @return int
//
func (m *RouterMap) GetMapSize() int {
m.Init()
return len(m.routerToNumberMap)
}
//
// Init
// @Description: 必须先执行该函数,以初始化RouterMap
// @receiver m*
//
func (m *RouterMap) Init() {
if m.uriToIdentifierMap == nil {
m.uriToIdentifierMap = make(map[string]*component.Identifier)
}
if m.routerToNumberMap == nil {
m.routerToNumberMap = make(map[string]int)
}
if m.numberToRouterMap == nil {
m.numberToRouterMap = make(map[int]string)
}
if m.mapLock == nil {
m.mapLock = new(sync.RWMutex)
}
}
+105
View File
@@ -0,0 +1,105 @@
// Package Calculator
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/10 16:53
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"fmt"
common2 "minlib/common"
"minlib/component"
"minlib/logicface"
"mlsr/common"
"mlsr/lsa"
"mlsr/lsdb"
"testing"
)
const testConfigPath = "D:\\" + common.DefaultConfFileName
func TestRouterMap_CreateFromAdjLsdb(t *testing.T) {
// 1. 构造LSDB
// 配置文件初始化
mlsrConfig, err := common.ParseConfig(testConfigPath)
if err != nil {
fmt.Println("配置文件解析错误")
}
// 调度器初始化
sche := new(lsdb.MlsrScheduler)
sche.Init()
// LogicFace初始化(假设初始化,暂时用不到)
face := new(logicface.LogicFace)
// LSDB初始化
lsdb := new(lsdb.Lsdb)
lsdb.Init(mlsrConfig, sche, face)
// 强行构建邻接lsa
lsdb.BuildAndInstallOwnAdjLsa()
// 2. 取出LSDB中的邻接LSA
lsas, err := lsdb.GetLSAsByType(lsa.LsaADJACENCYType)
if err != nil {
common2.LogError("Get Lsa in calculateLsRoutingTable error, ", err)
}
common2.LogInfo("邻接lsa数目: ", len(lsas))
// 3. 构造RouterMap
rMap := new(RouterMap)
rMap.Init()
err = rMap.CreateFromAdjLsdb(lsas)
// 4. 打印RouterMap状态
common2.LogInfo(rMap)
common2.LogInfo(rMap.ToString())
}
//
// TestRouterMap_Store
// @Description: 测试RouterMap
// @param t
//
func TestRouterMap_Store(t *testing.T) {
iden, _ := component.CreateIdentifierByString("/test/weforever")
iden1, _ := component.CreateIdentifierByString("/test/weforever1")
iden2, _ := component.CreateIdentifierByString("/test/weforever2")
// 存入
rmap := new(RouterMap)
rmap.Init()
rmap.Store(iden)
rmap.Store(iden1)
rmap.Store(iden2)
// 取出标识
index, b := rmap.GetMappingNoByRouterName(iden2)
fmt.Println(index, b)
// 取出一个同URI的标识
idenNew2, _ := component.CreateIdentifierByString("/test/weforever2")
index, b = rmap.GetMappingNoByRouterName(idenNew2)
fmt.Println(index, b)
// 取出Iden
idenCat, bb := rmap.GetRouterNameByMappingNo(0)
fmt.Println(idenCat.ToUri(), bb)
idenCat, bb = rmap.GetRouterNameByMappingNo(1)
fmt.Println(idenCat.ToUri(), bb)
idenCat, bb = rmap.GetRouterNameByMappingNo(2)
fmt.Println(idenCat.ToUri(), bb)
idenCat, bb = rmap.GetRouterNameByMappingNo(3)
fmt.Println(bb)
// 查看map大小
fmt.Println(rmap.GetMapSize())
// 删除后再查看
rmap.delete(iden)
rmap.delete(idenNew2)
fmt.Println(rmap.GetMapSize())
idenCat, bb = rmap.GetRouterNameByMappingNo(0)
fmt.Println(bb)
idenCat, bb = rmap.GetRouterNameByMappingNo(2)
fmt.Println(bb)
}
+297
View File
@@ -0,0 +1,297 @@
// 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"
"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
}
//
// Init
// @Description: 初始化
// @receiver t
// @param mc
// @param ms
// @param mlsdb
//
func (t *RoutingTable) Init(mc *common.MlsrConfig,
ms *lsdb.MlsrScheduler, mlsdb *lsdb.Lsdb) {
// 初始化任务调度器
t.scheduler = ms
// 初始化配置项
t.mlsrConfig = mc
// 初始化lsdb
t.lsdb = mlsdb
// 路由计算间隔时间
t.m_routingCalcInterval = mc.GetRoutingCalcInterval()
// 路由计算状态
t.m_isRoutingTableCalculating = false
t.m_isRouteCalculationScheduled = false
// todo 事件监听:如果监听到了传来的删除本地邻接LSA操作
// todo 事件监听:如果监听到了传来的安装本地邻接LSA操作
t.m_ownAdjLsaExist = true
// todo 事件监听:如果监听到了传来的安装或更新本地邻接LSA操作
//err := t.ScheduleRoutingTableCalculation()
//if err != nil {
// common2.LogError("RoutingTable.Init ScheduleRoutingTableCalculation error.")
//}
}
//
// 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.LogError("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)
job, err := t.scheduler.ScheduleTaskAfterDuration(t.m_routingCalcInterval, 1).Do(t.Calculate)
if err != nil {
return err
}
job.LimitRunsTo(1)
t.scheduler.StartAsync()
t.m_isRouteCalculationScheduled = true
}
return nil
}
//
// calculateLsRoutingTable
// @Description: 计算链路状态路由表。
// @receiver t
//
func (t *RoutingTable) calculateLsRoutingTable() {
if t.lsdb.GetIsBuildAdjLsaScheduled() {
common2.LogError("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.LogError("Get Lsa in calculateLsRoutingTable error, ", err)
}
rMap := new(RouterMap)
rMap.Init()
err = rMap.CreateFromAdjLsdb(lsas)
if err != nil {
common2.LogError("create RouterMap from lsdb error in calculateLsRoutingTable error, ", err)
}
nRouters := rMap.GetMapSize()
// 构造路由计算器
calculator := new(LinkStateRoutingTableCalculator)
calculator.SetRouterNum(nRouters)
// 使用计算器去计算路由
routers, nexthops, err := calculator.CalculatePath(rMap, t.mlsrConfig, t.lsdb)
if err != nil {
common2.LogError("CalculatePath in calculateLsRoutingTable error, ", err)
}
// 将路由计算结果依次加入路由表
for i := 0; i < len(routers); i++ {
t.AddNextHop(routers[i], nexthops[i])
}
// 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
}
+278
View File
@@ -0,0 +1,278 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/9 17:30
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"errors"
"mlsr/lsa"
"mlsr/lsdb"
"strconv"
"sync"
)
type RoutingTableCalculator struct {
// 邻接矩阵
adjMatrix [][]uint64
// 路由器数目
m_nRouters int
// 稀疏矩阵的形式存储本机路由器的邻接链路信息
vNoLink int // 链路数
links []int // 链路索引号
linkCosts []uint64 // 链路开销
}
//
// ToString
// @Description: 将路由表计算器的成员变量转为string。用于测试。
// @receiver c
// @return string
//
func (c *RoutingTableCalculator) ToString() string {
res := "\n"
res += "路由器数目:" + strconv.Itoa(c.m_nRouters) + "\n"
res += "邻接矩阵:\n"
for i := 0; i < len(c.adjMatrix); i++ {
for j := 0; j < len(c.adjMatrix[i]); j++ {
res += "["
res += strconv.Itoa(i)
res += ","
res += strconv.Itoa(j)
res += ","
res += strconv.FormatUint(c.adjMatrix[i][j], 10)
res += "] "
}
res += "\n"
}
res += "本机相邻链路数:" + strconv.Itoa(c.vNoLink) + "\n"
res += "本机相邻链路索引:"
res += "["
for i := 0; i < len(c.links); i++ {
res += strconv.Itoa(c.links[i])
if i < (len(c.links) - 1) {
res += ","
}
}
res += "]\n"
res += "本机相邻链路开销:"
res += "["
for i := 0; i < len(c.linkCosts); i++ {
res += strconv.Itoa(int(c.linkCosts[i]))
if i < (len(c.linkCosts) - 1) {
res += ","
}
}
res += "]\n"
return res
}
//
// SetRouterNum
// @Description: 设置路由器个数
// @receiver c
// @param n
//
func (c *RoutingTableCalculator) SetRouterNum(n int) {
c.m_nRouters = n
}
//
// allocateAdjMatrix
// @Description: 给邻接矩阵分配所需的空间
// @receiver c
//
func (c *RoutingTableCalculator) allocateAdjMatrix() {
c.adjMatrix = make([][]uint64, c.m_nRouters)
// 根据路由器的数目,确定邻接矩阵的长度
for i := 0; i < c.m_nRouters; i++ {
c.adjMatrix[i] = make([]uint64, c.m_nRouters)
}
}
//
// initMatrix
// @Description: 为矩阵的每个单元设置非邻接成本(NON_ADJACENT_COST,如-12345),以确保内存安全。
// @receiver c
//
func (c *RoutingTableCalculator) initMatrix() {
for i := 0; i < c.m_nRouters; i++ {
for j := 0; j < c.m_nRouters; j++ {
c.adjMatrix[i][j] = NON_ADJACENT_COST
}
}
}
//
// makeAdjMatrix
// @Description: 构建一个要去计算的邻接矩阵
// @receiver c
// @param lsdb
// @param p
//
func (c *RoutingTableCalculator) makeAdjMatrix(lsdb *lsdb.Lsdb,
rp *RouterMap) error {
// 1. 在Map中表示每个LSA
// 先从Lsdb中取出邻接LSA
lsas, err := lsdb.GetLSAsByType(lsa.LsaADJACENCYType)
if err != nil {
return errors.New("No Found adj lsa in LSDB. ")
}
// 2. 再对每个lsa进行操作
for i := 0; i < len(lsas); i++ {
// 2.1 取出源路由器,找其索引值,作为邻接矩阵的行号
row, b := rp.GetMappingNoByRouterName(lsas[i].GetOriginRouter())
if !b {
return errors.New("No Found origin router in routerMap. ")
}
// 2.2 依次取出该源路由器对应的所有邻接路由器标识,以及链路开销,来构建邻接矩阵
adjlsa, ok := (lsas[i]).(*lsa.AdjLsa)
if !ok {
return errors.New("Lsa from LSDB is not adjlsa. ")
}
adjs := adjlsa.GetAdjList()
for j := 0; j < len(adjs); j++ {
// 2.2.1 取列数
col, b := rp.GetMappingNoByRouterName(adjs[j].GetNeighborRouterIdentifier())
if !b {
return errors.New("No Found neighbor router in routerMap. ")
}
// 2.2.2 取开销
linkCost := adjs[j].AdjLsaLinkCost.LinkCost()
// 2.2.3 将开销放入邻接矩阵
if (row < c.m_nRouters) && (col < c.m_nRouters) {
c.adjMatrix[row][col] = linkCost
}
}
}
// todo 检查路由器A到路由器B的链路开销,若正向开销与反向开销不同,则两者均取较大值
return nil
}
//
// writeAdjMatrixLog
// @Description: 将格式化的邻接矩阵写入调试日志
// @receiver c 包含邻接矩阵数据的映射
// @param p
//
func (c *RoutingTableCalculator) writeAdjMatrixLog(p *sync.Map) {
// todo 输出调试信息,验证功能是否正常运行
}
//
// getNumOfLinkfromAdjMatrix
// @Description: 返回矩阵中一个路由器的邻接数(不包含其本身)
// @receiver c
// @param sRouter 计算邻接数的路由器
//
func (c *RoutingTableCalculator) getNumOfLinkfromAdjMatrix(sRouter int) int {
num := 0
for i := 0; i < c.m_nRouters; i++ {
if (c.adjMatrix[sRouter][i] != NON_ADJACENT_COST) && (i != sRouter) {
num++
}
}
return num
}
//
// freeAdjMatrix
// @Description: 释放内存
// @receiver c
//
func (c *RoutingTableCalculator) freeAdjMatrix() {
c.adjMatrix = [][]uint64{}
}
//
// adjustAdMatrix
// @Description: 在邻接矩阵中调整链路成本。除要更改的链路外,该源路由器的其它链路全部设置为不可达
// @receiver c
// @param source 要调整其邻接的源路由器
// @param link 要调整的源的邻接
// @param linkCost 更改为的成本。
//
func (c *RoutingTableCalculator) adjustAdMatrix(source int, link int, linkCost uint64) {
for i := 0; i < c.m_nRouters; i++ {
if i == link {
c.adjMatrix[source][i] = linkCost
} else {
c.adjMatrix[source][i] = NON_ADJACENT_COST
}
}
}
//
// getLinksFromAdjMatrix
// @Description: 用一些路由器的链路成本填充临时变量
// 获取一些路由器的邻接和链路开销的稀疏列表。
// 由于这是稀疏的,这意味着在生成这些数组时,如果矩阵中i处没有邻接,
// 这些临时变量将不会在i处包含非邻接代价(NON_ADJACENT_COST,-12345),而是包含下一个有效邻接的值。
// @receiver c
// @param links 链接映射号的一个整数数组
// @param linkCosts 存储链路开销的一个双指针数组
// @param source 被调整值的路由器
//
func (c *RoutingTableCalculator) getLinksFromAdjMatrix(source int) {
index := 0
for i := 0; i < c.m_nRouters; i++ {
if (c.adjMatrix[source][i] != NON_ADJACENT_COST) && (i != source) {
c.links[index] = i
c.linkCosts[index] = c.adjMatrix[source][i]
index++
}
}
}
//
// allocateLinks
// @Description: 分配一个足以容纳多路径计算临时值的数组
// @receiver c
//
func (c *RoutingTableCalculator) allocateLinks() {
c.links = make([]int, c.vNoLink)
}
//
// allocateLinkCosts
// @Description: 分配内存
// @receiver c
//
func (c *RoutingTableCalculator) allocateLinkCosts() {
c.linkCosts = make([]uint64, c.vNoLink)
}
//
// freeLinks
// @Description: 释放内存
// @receiver c
//
func (c *RoutingTableCalculator) freeLinks() {
c.links = []int{}
}
//
// freeLinksCosts
// @Description: 释放内存
// @receiver c
//
func (c *RoutingTableCalculator) freeLinksCosts() {
c.linkCosts = []uint64{}
}
//
// setNoLink
// @Description: 设置链路数,即多路径中的“多”所代指的个数
// @receiver c
// @param nl
//
func (c *RoutingTableCalculator) setNoLink(nl int) {
c.vNoLink = nl
}
+73
View File
@@ -0,0 +1,73 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/26 12:10
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"fmt"
common2 "minlib/common"
"minlib/logicface"
"mlsr/common"
"mlsr/lsa"
"mlsr/lsdb"
"testing"
)
func TestRoutingTableCalculator_Init(t *testing.T) {
// 构造路由计算器
rtc := new(RoutingTableCalculator)
// 1. 根据LSDB构造邻接矩阵
// 1.1 构造LSDB
// 配置文件初始化
mlsrConfig, err := common.ParseConfig(testConfigPath)
if err != nil {
fmt.Println("配置文件解析错误")
}
// 调度器初始化
sche := new(lsdb.MlsrScheduler)
sche.Init()
// LogicFace初始化(假设初始化,暂时用不到)
face := new(logicface.LogicFace)
// LSDB初始化
mlsdb := new(lsdb.Lsdb)
mlsdb.Init(mlsrConfig, sche, face)
// 安装本机adjlsa
mlsdb.BuildAndInstallOwnAdjLsa()
// todo 传入一些其它虚拟lsa,这些lsa与本机lsa共同形成一个小型路由拓扑
// 1.2 构造RouterMap
lsas, err := mlsdb.GetLSAsByType(lsa.LsaADJACENCYType)
if err != nil {
common2.LogError("Get Lsa in calculateLsRoutingTable error, ", err)
}
common2.LogInfo("邻接lsa数目: ", len(lsas))
rMap := new(RouterMap)
rMap.Init()
err = rMap.CreateFromAdjLsdb(lsas)
// 打印rm
common2.LogInfo(rMap.ToString())
// 1.3 根据RouterMap,和lsdb中的adjlsa,构造邻接矩阵
// 设置路由器数目
rtc.SetRouterNum(rMap.GetMapSize())
// 分配矩阵空间
rtc.allocateAdjMatrix()
// 初始化矩阵值
rtc.initMatrix()
// 构造矩阵
err = rtc.makeAdjMatrix(mlsdb, rMap)
if err != nil {
common2.LogError("邻接矩阵构造失败")
}
// 2. 打印输出路由表计算器
fmt.Println(rtc.ToString())
fmt.Println("源路由器的邻接数目:", rtc.getNumOfLinkfromAdjMatrix(0))
fmt.Println("另一个路由器的邻接数目:", rtc.getNumOfLinkfromAdjMatrix(1))
}
+146
View File
@@ -0,0 +1,146 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/5 20:41
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"minlib/component"
"minlib/encoding"
"mlsr/extensions"
)
//
// RoutingTableEntry
// @Description: 路由表条目
//
type RoutingTableEntry struct {
m_destination *component.Identifier
NextHopList
}
//
// ToString
// @Description: 转string。用于测试
// @receiver e
// @return string
//
func (e *RoutingTableEntry) ToString() string {
res := ""
res += "目的路由器: " + e.m_destination.ToUri() + "\n"
res += e.NextHopList.ToString()
return res
}
//
// NewRoutingTableEntry
// @Description: 新建一个路由表条目
// @param dest
// @return *RoutingTableEntry
// @return error
//
func NewRoutingTableEntry(dest *component.Identifier) (*RoutingTableEntry, error) {
// todo: 判断dest是否格式有效
rte := new(RoutingTableEntry)
rte.m_destination = dest
return rte, nil
}
//
// GetDestination
// @Description: 获取目的路由器
// @receiver e
// @return *component.Identifier
//
func (e *RoutingTableEntry) GetDestination() *component.Identifier {
return e.m_destination
}
//
// SetDestination
// @Description: 设置目的路由器
// @receiver e
// @param dest
//
func (e *RoutingTableEntry) SetDestination(dest *component.Identifier) {
e.m_destination = dest
}
//
// WireEncode
// @Description: 线速编码
// @receiver l
// @param encoder
// @return int
// @return error
//
func (e *RoutingTableEntry) WireEncode(encoder *encoding.Encoder) (int, error) {
totalLength := 0
// TLV-Value
tmpLen, err := e.NextHopList.WireEncode(encoder)
if err != nil {
return 0, err
}
totalLength += tmpLen
tmpLen, err = e.m_destination.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.TlvMlsrRoutingTableEntry)
if err != nil {
return 0, err
}
totalLength += tmpLen
return totalLength, nil
}
//
// WireDecode
// @Description: 线速解码
// @receiver l
// @param block
// @return error
//
func (e *RoutingTableEntry) WireDecode(block *encoding.Block) error {
// 检查 TLV-TYPE 是否正确
if err := encoding.ExpectType(block.GetType(), extensions.TlvMlsrRoutingTableEntry); err != nil {
return err
}
// 首先解析子Block
if err := block.ParseSubElements(); err != nil {
return err
}
// 提取参数
for _, parameter := range block.GetSubElements() {
switch parameter.GetType() {
case encoding.TlvIdentifier:
iden := component.Identifier{}
if err := iden.WireDecode(parameter); err != nil {
return err
}
e.m_destination = &iden
case extensions.TlvMlsrNextHopList:
if err := e.NextHopList.WireDecode(parameter); err != nil {
return err
}
}
}
return nil
}
+105
View File
@@ -0,0 +1,105 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/6/17 11:29
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"fmt"
"minlib/component"
"minlib/encoding"
"testing"
)
//
// TestNewRoutingTableEntry
// @Description: 测试构造路由表项
// @param t
//
func TestNewRoutingTableEntry(t *testing.T) {
// 构造
iden, _ := component.CreateIdentifierByString("/pku/abc")
rte, err := NewRoutingTableEntry(iden)
if err != nil {
fmt.Println("构造路由表项失败")
}
// 打印
fmt.Println(rte.GetDestination().ToUri())
}
//
// TestRoutingTableEntry_WireEncode
// @Description: 测试编码
// @param t
//
func TestRoutingTableEntry_WireEncode(t *testing.T) {
// 构造三个下一跳
nthop1, _ := NewNextHop("/hop1", 10)
nthop2, _ := NewNextHop("/hop2", 20)
nthop3, _ := NewNextHop("/hop3", 30)
// 构造路由表项
iden, _ := component.CreateIdentifierByString("/pku/run")
hopList, _ := NewRoutingTableEntry(iden)
hopList.AddNextHop(nthop1)
hopList.AddNextHop(nthop2)
hopList.AddNextHop(nthop3)
// 编码
encoder := encoding.Encoder{}
err := encoder.EncoderReset(encoding.MaxPacketSize, 0)
if err != nil {
fmt.Println("RoutingTableEntry编码报错,", err.Error())
return
}
length, err := hopList.WireEncode(&encoder)
if err != nil {
t.Fatal("RoutingTableEntry编码失败", err.Error())
}
// 获取编码
buf, err := encoder.GetBuffer()
if err != nil {
t.Fatal("RoutingTableEntry获取buffer结果失败", err.Error())
}
// 打印编码结果。如果可以正确解码,则说明编码成功
fmt.Println(length)
for i := 0; i < len(buf); i++ {
fmt.Print(buf[i], ", ")
}
fmt.Println()
}
//
// TestRoutingTableEntry_WireDecode
// @Description: 测试解码
// @param t
//
func TestRoutingTableEntry_WireDecode(t *testing.T) {
// 由数组构建block
var buf = [80]byte{241, 1, 189, 76, 101, 16, 100, 2, 0, 47,
100, 4, 0, 112, 107, 117, 100, 4, 0, 114, 117, 110, 241,
1, 188, 54, 241, 1, 187, 14, 241, 1, 186, 1, 10, 241, 1,
185, 5, 47, 104, 111, 112, 49, 241, 1, 187, 14, 241, 1,
186, 1, 20, 241, 1, 185, 5, 47, 104, 111, 112, 50, 241,
1, 187, 14,
241, 1, 186, 1, 30, 241, 1, 185, 5, 47, 104, 111, 112, 51}
block, err := encoding.CreateBlockByBuffer(buf[:], true)
if err != nil {
fmt.Println("创建block失败 ", err.Error())
return
}
// 由Block构建结构体,并打印变量
base := new(RoutingTableEntry)
err = base.WireDecode(block)
if err != nil {
fmt.Println("线性解码失败 ", err.Error())
return
}
fmt.Println(base.ToString())
}
+127
View File
@@ -0,0 +1,127 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/6/10 11:02
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
"minlib/component"
)
//
// RoutingTablePoolEntry
// @Description: 路由表池条目。
//
type RoutingTablePoolEntry struct {
RoutingTableEntry
// 记录使用本池条目的所有名称前缀 NamePrefix-名称前缀表项
NamePrefixTableEntries map[string]*NamePrefixTableEntry
m_useCount uint64 // 记录本条目被多少条名称前缀所使用
}
//
// Init
// @Description: 初始化目的路由器
// @receiver pe
// @param dest
//
func (pe *RoutingTablePoolEntry) Init(dest *component.Identifier) {
pe.m_destination = dest
pe.m_useCount = 1
}
//
// InitRTE
// @Description: 初始化路由表项和使用数
// @receiver pe
// @param rte
// @param useCount
//
func (pe *RoutingTablePoolEntry) InitRTE(rte *RoutingTableEntry, useCount uint64) {
pe.m_destination = rte.m_destination
pe.nextHops = rte.GetNextHops()
pe.m_useCount = useCount
}
//
// InitDest
// @Description: 初始化目的路由器和使用数
// @receiver pe
// @param dest
// @param useCount
//
func (pe *RoutingTablePoolEntry) InitDest(dest *component.Identifier, useCount uint64) {
pe.m_destination = dest
pe.m_useCount = useCount
}
//
// IsEqual
// @Description: 判断两个路由表池条目是否相等
// @receiver pe
// @param npe
// @return bool
//
func (pe *RoutingTablePoolEntry) IsEqual(npe *RoutingTablePoolEntry) bool {
if pe.GetDestination().ToUri() == npe.GetDestination().ToUri() &&
pe.NextHopList.Size() == pe.NextHopList.Size() {
b := true
for i := 0; i < pe.NextHopList.Size(); i++ {
if pe.GetNextHops()[i].LogicFaceUri() != npe.GetNextHops()[i].LogicFaceUri() ||
pe.GetNextHops()[i].RouteCost.RouteCost() != npe.GetNextHops()[i].RouteCost.RouteCost() {
b = false
}
}
return b
}
return false
}
//
// GetUseCount
// @Description: 获取使用数
// @receiver pe
// @return uint64
//
func (pe *RoutingTablePoolEntry) GetUseCount() uint64 {
return pe.m_useCount
}
//
// IncrementUseCount
// @Description: 使用数加一,并返回
// @receiver pe
// @return uint64
//
func (pe *RoutingTablePoolEntry) IncrementUseCount() uint64 {
pe.m_useCount++
return pe.m_useCount
}
//
// DecrementUseCount
// @Description: 使用数减一,并返回
// @receiver pe
// @return uint64
//
func (pe *RoutingTablePoolEntry) DecrementUseCount() uint64 {
if pe.m_useCount != 0 {
pe.m_useCount--
return pe.m_useCount
}
return 0
}
//
// SetNexthopList
// @Description: 设置下一跳列表
// @receiver pe
// @param list
//
func (pe *RoutingTablePoolEntry) SetNexthopList(list NextHopList) {
pe.NextHopList = list
}
+69
View File
@@ -0,0 +1,69 @@
// Package route
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/6/17 11:28
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package route
import (
common2 "minlib/common"
"minlib/logicface"
"mlsr/common"
"mlsr/lsdb"
"testing"
)
//
// TestRoutingTable_Init
// @Description: 测试初始化
// @param t
//
func TestRoutingTable_Init(t *testing.T) {
// 1. 组件初始化
// 配置文件初始化
mlsrConfig, err := common.ParseConfig(testConfigPath)
if err != nil {
common2.LogInfo("配置文件解析错误")
}
// 调度器初始化
sche := new(lsdb.MlsrScheduler)
sche.Init()
// LogicFace初始化(假设初始化,暂时用不到)
face := new(logicface.LogicFace)
// LSDB初始化
mlsdb := new(lsdb.Lsdb)
mlsdb.Init(mlsrConfig, sche, face)
// 2. 路由表初始化
rt := new(RoutingTable)
rt.Init(mlsrConfig, sche, mlsdb)
}
//
// TestRoutingTable_AddNextHop
// @Description: 测试构造路由表及其拓扑
// @param t
//
func TestRoutingTable_AddNextHop(t *testing.T) {
}
//
// TestRoutingTable_Calculate
// @Description: 测试计算
// @param t
//
func TestRoutingTable_Calculate(t *testing.T) {
}
//
// TestRoutingTable_ScheduleRoutingTableCalculation
// @Description: 测试安排路由计算
// @param t
//
func TestRoutingTable_ScheduleRoutingTableCalculation(t *testing.T) {
}
+65 -13
View File
@@ -16,7 +16,11 @@ import (
)
func printHHH() {
println("hello,gocron.",time.Now().String())
println("hello,gocron.", time.Now().String())
}
func printHHHWithPara(s string) {
println("hello,gocron.", time.Now().String(), s)
}
//
@@ -31,7 +35,7 @@ func Test_Loop(t *testing.T) {
s := gocron.NewScheduler(time.UTC)
// Job:只知道它提供的任务(task, go函数),因此只能执行与该任务相关的操作,例如防止自己超出需要很长时间的先前任务。
//j, _ := s.Every(10).Seconds().Do(func() { time.Sleep(2 * time.Second); printHHH()})
j, _ := s.Every(1).Seconds().Do(func() { printHHH()})
j, _ := s.Every(1).Seconds().Do(func() { printHHH() })
// Executor:顾名思义,executor 只负责调用Scheduler(调度程序)发送时,Job(作业)交给它的任务(go 函数)。
fmt.Println(j.IsRunning())
@@ -50,7 +54,7 @@ func Test_Loop(t *testing.T) {
func Test_IsRunning(t *testing.T) {
s := gocron.NewScheduler(time.UTC)
// Job:只知道它提供的任务(task, go函数),因此只能执行与该任务相关的操作,例如防止自己超出需要很长时间的先前任务。
j, _ := s.Every(10).Seconds().Do(func() { time.Sleep(2 * time.Second); printHHH()})
j, _ := s.Every(10).Seconds().Do(func() { time.Sleep(2 * time.Second); printHHH() })
// Executor:顾名思义,executor 只负责调用Scheduler(调度程序)发送时,Job(作业)交给它的任务(go 函数)。
fmt.Println(j.IsRunning())
@@ -67,10 +71,41 @@ func Test_IsRunning(t *testing.T) {
time.Sleep(1 * time.Second)
fmt.Println(j.IsRunning())
for true {
time.Sleep(1 * time.Second)
}
}
var task = func() {}
func Test_Run1Time(t *testing.T) {
// 触发时间设置到五秒后
timeRun := time.Now()
fmt.Println("run time: ", timeRun)
dur := 5 * time.Second
timeRun = timeRun.Add(dur)
fmt.Println("run time: ", timeRun)
// 设置触发事件
s := gocron.NewScheduler(time.UTC)
_, _ = s.At(timeRun).Do(printHHHWithPara, "xixixi")
//go func() {
// for {
// fmt.Println("Run count", job.RunCount())
// time.Sleep(time.Second)
// }
//}()
s.StartBlocking()
// 保活
//for true {
// time.Sleep(10 * time.Second)
//}
}
//
// Test_RunCount
// @Description: 测试job.RunCount()
@@ -78,14 +113,14 @@ var task = func() {}
//
func Test_RunCount(t *testing.T) {
s := gocron.NewScheduler(time.UTC)
job, _ := s.Every(1).Second().Do(task)
job, _ := s.Every(1).Second().Do(printHHHWithPara, "xxx")
go func() {
for {
fmt.Println("Run count", job.RunCount())
time.Sleep(time.Second)
}
}()
s.StartAsync()
s.StartBlocking()
// 保活
for true {
@@ -123,7 +158,7 @@ func Test_LastRun_NextRun(t *testing.T) {
func Test_LimitRunsTo(t *testing.T) {
s := gocron.NewScheduler(time.UTC)
job, _ := s.Every(1).Second().Do(printHHH)
job.LimitRunsTo(2)
job.LimitRunsTo(1)
s.StartAsync()
// 保活
@@ -135,24 +170,33 @@ func Test_LimitRunsTo(t *testing.T) {
//
// Test_ScheduleAtTimes
// @Description: 设置事件在指定时间节点被触发
// @Description: 设置事件在指定时间节点被触发 => 常见用法
// @param t
//
func Test_ScheduleAtTimes(t *testing.T) {
// 触发时间设定在五秒后
timeRun := time.Now()
fmt.Println("预定时间(假性):", timeRun)
dur := 4 * time.Second
timeRun = timeRun.Add(dur)
fmt.Println("预定时间:", timeRun)
// 设置一个触发时间
s := gocron.NewScheduler(time.UTC)
job, _ := s.Every(1).Day().At("20:02").Do(func() {printHHH()})
//job, _ := s.Every(100).Seconds().StartAt(timeRun).Do(printHHHWithPara, "heiheihei")
job, _ := s.Every(3).Seconds().StartAt(timeRun).Do(printHHH)
job.LimitRunsTo(3)
s.StartAsync()
fmt.Println(job.ScheduledAtTime())
fmt.Println("预定触发时间: ", job.ScheduledAtTime())
// 设置多个触发时间。当取时间时,返回最早的那个
job1, _ := s.Every(1).Day().At("10:30;08:00").Do(task)
fmt.Println(job1.ScheduledAtTime())
//job1, _ := s.Every(1).Day().At("10:30;08:00").Do(task)
//fmt.Println(job1.ScheduledAtTime())
// Output:
// 10:30
// 8:0
// 当取所有时间时,返回一个时间列表
fmt.Println(job1.ScheduledAtTimes())
//fmt.Println(job1.ScheduledAtTimes())
// Output:
// [8:0 10:30]
@@ -179,4 +223,12 @@ func Test_SingletonMode(t *testing.T) {
time.Sleep(3 * time.Second)
fmt.Println("Last run:", job.LastRun())
}
}
}
func Test_Running(t *testing.T) {
var s *gocron.Scheduler
if (s == nil) || (!s.IsRunning()) {
fmt.Println("hahhaha")
}
fmt.Println(s == nil)
}
+30
View File
@@ -0,0 +1,30 @@
package tests
import (
"fmt"
"github.com/tidwall/buntdb"
"minlib/logicface"
"mlsr/lsa"
"testing"
)
func TestName(t *testing.T) {
fmt.Println("abc")
s := logicface.LogicFaceTypeEther
fmt.Println("def", s)
ss := lsa.AdjLsaAdjacencyInfo{}
ss.Status = 1
TestBuntDb(t)
}
func TestBuntDb(t *testing.T) {
// https://github.com/tidwall/buntdb
db, err := buntdb.Open(":memory:")
if err != nil {
fmt.Println("bunt db open err")
}
_ = db.Close()
fmt.Println("bunt db closed")
}
+121
View File
@@ -0,0 +1,121 @@
// Package utils
// @Author: Jianming Que (阙建明)
// @Description:
// @Version: 1.0.0
// @Date: 2021/4/26 11:27 上午
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package utils
import (
"fmt"
"io/ioutil"
"minlib/common"
"os"
"strings"
)
func GetRelPath(path string) string {
if strings.HasPrefix(path, "~") {
homePath, err := common.Home()
if err != nil {
common.LogFatal("Get current user home path failed!")
}
return homePath + path[1:]
} else {
return path
}
}
func ReadFromFile(path string) (string, error) {
file, err := os.Open(path)
if err != nil {
return "", err
}
defer file.Close()
if content, err := ioutil.ReadAll(file); err != nil {
return "", err
} else {
return string(content), nil
}
}
// WriteFile 写入文件,文件不存在则创建,如在则重写内容
func ClearAndWriteFile(path string, str string) {
_, b := IsFile(path)
var f *os.File
var err error
if b {
//打开文件,
f, _ = os.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0666)
} else {
//新建文件
f, err = os.Create(path)
}
//使用完毕,需要关闭文件
defer func() {
err = f.Close()
if err != nil {
fmt.Println("err = ", err)
}
}()
if err != nil {
fmt.Println("err = ", err)
return
}
_, err = f.WriteString(str)
if err != nil {
fmt.Println("err = ", err)
}
}
// WriteFile 写入文件,文件不存在则创建,如在则追加内容
func WriteFile(path string, str string) {
_, b := IsFile(path)
var f *os.File
var err error
if b {
//打开文件,
f, _ = os.OpenFile(path, os.O_APPEND, 0666)
} else {
//新建文件
f, err = os.Create(path)
}
//使用完毕,需要关闭文件
defer func() {
err = f.Close()
if err != nil {
fmt.Println("err = ", err)
}
}()
if err != nil {
fmt.Println("err = ", err)
return
}
_, err = f.WriteString(str)
if err != nil {
fmt.Println("err = ", err)
}
}
// IsExists 判断路径是否存在
func IsExists(path string) (os.FileInfo, bool) {
f, err := os.Stat(path)
return f, err == nil || os.IsExist(err)
}
// IsDir 判断所给路径是否为文件夹
func IsDir(path string) (os.FileInfo, bool) {
f, flag := IsExists(path)
return f, flag && f.IsDir()
}
// IsFile 判断所给路径是否为文件
func IsFile(path string) (os.FileInfo, bool) {
f, flag := IsExists(path)
return f, flag && !f.IsDir()
}
+13
View File
@@ -0,0 +1,13 @@
// Package utils
// @Author: Wang Feng
// @Description:
// @Version: 0.1.0
// @Date: 2022/5/10 11:48
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
//
package utils
const (
)
+287
View File
@@ -0,0 +1,287 @@
/*
* Copyright (c) 2014-2022, Peking University Shenzhen Graduate School
*
* This file is part of MIN-Sync.
* See AUTHORS.md for complete list of MIN-Sync authors and contributors.
*
* MIN-Sync is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* MIN-Sync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* MIN-Sync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* The MIT License (MIT)
* Copyright (c) 2000 Arash Partow
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package utils
import (
"minlib/common"
"reflect"
"github.com/liyue201/gostl/ds/vector"
)
type DisconnectFunction = func()
/** \brief represents a connection to a signal
* \note This type is copyable. Any copy can be used to disconnect.
*/
type Connection struct {
disconnect DisconnectFunction
}
/** \brief disconnects from the signal
* \note If the connection is already disconnected, or if the Signal has been cleared,
* this operation has no effect.
* \warning During signal emission, attempting to disconnect a connection other than
* the executing handler's own connection results in undefined behavior.
*/
func (c *Connection) Disconnect() {
if c.IsConnected() {
c.disconnect()
}
}
/** \brief check if connected to the signal
*/
func (c *Connection) IsConnected() bool {
return c.disconnect != nil
}
/** \brief compare for equality
*
* Two connections are equal if they both point to the same connection that isn't disconnected,
* or they are both disconnected.
*/
func (c *Connection) Equals(other *Connection) bool {
return (!c.IsConnected() && !other.IsConnected()) || reflect.ValueOf(c.disconnect).Pointer() == reflect.ValueOf(other.disconnect).Pointer()
}
/* Factory Method for Connection */
func NewConnectionByDisconnectFunc(df DisconnectFunction) *Connection {
c := new(Connection)
c.disconnect = df
return c
}
/** \brief represents a function that can connect to the signal
*/
type Handler = func(...interface{})
/** \brief provides a lightweight signal / event system
*
* To declare a signal:
* factory method;
* To connect to a signal:
* owner.signalName.connect(f);
* Multiple functions can connect to the same signal.
* To emit a signal from owner:
* this->signalName.emit(arg1, arg2);
*
* \sa signal-emit.hpp allows owner's derived classes to emit signals
*/
type Signal struct {
slots SlotList
/** \brief is a signal handler executing?
*/
isExecuting bool
currentSlot SlotIterator
}
/** \brief connects a handler to the signal
* \note If invoked from a handler, the new handler won't receive the current emitted signal.
* \warning The handler is permitted to disconnect itself, but it must ensure its validity.
*/
func (s *Signal) Connect(handler Handler) *Connection {
slot := NewSlotByHandler(handler)
slotIterator := s.slots.Insert(s.slots.End(), slot)
/* disconnect management */
df := func() {
s.disconnect(slotIterator)
}
slot.Disconnect = df /* strong reference */
weakPtr := NewConnectionByDisconnectFunc(df) /* weak reference */
slot.Connection = weakPtr /* slot takes over connection */
return weakPtr
}
/** \brief connects a single-shot handler to the signal
*
* After the handler is executed once, it is automatically disconnected.
*/
func (s *Signal) ConnectSingleShot(handler Handler) *Connection {
slot := new(Slot)
slotIterator := s.slots.Insert(s.slots.End(), slot)
df := func() {
s.disconnect(slotIterator)
}
conn := NewConnectionByDisconnectFunc(df)
slot.Disconnect = df
slot.Connection = conn
slot.Handler = func(args ...interface{}) {
handler(args)
conn.Disconnect()
}
return conn
}
/** \retval true if there is no connection
*/
func (s *Signal) IsEmpty() bool {
return !s.isExecuting && s.slots.Empty()
}
/** \brief emits a signal
* \param args arguments passed to all handlers
* \warning Emitting the signal from a handler is undefined behavior.
* \note If a handler throws, the exception will be propagated to the caller
* who emits this signal, and some handlers may not be executed.
*/
func (s *Signal) Emit(args ...interface{}) {
if s.IsEmpty() {
return
}
defer func() {
s.isExecuting = false
}()
s.isExecuting = true
it := s.slots.Begin()
last := s.slots.Last()
isLast := false
for !isLast {
isLast = it.Equal(last)
s.currentSlot = it
s.currentSlot.Value().(*Slot).Handler(args...)
// disconnect while executing current slot
if s.currentSlot.Equal(s.slots.End()) {
it = s.slots.Erase(it)
} else {
it = it.Next().(SlotIterator)
}
}
}
/** \brief disconnects the handler in a slot
*/
func (s *Signal) disconnect(iterator SlotIterator) {
if s.isExecuting {
// during signal emission, only the currently executing handler can be disconnected
if !s.currentSlot.Equal(iterator) {
common.LogWarn("cannot disconnect another handler from a handler")
return
}
// this serves to indicate that the current slot needs to be erased from the list
// after it finishes executing; we cannot do it here because of bug #2333
s.currentSlot = s.slots.End()
// destruct
iterator.Value().(*Slot).Destruct()
} else {
iterator.Value().(*Slot).Destruct()
s.slots.Erase(iterator)
}
}
/* Clear
*/
func (s *Signal) Clear() {
/* \warn should only called when signal is not executing */
s.currentSlot = nil
/* clean all slots */
it := s.slots.Begin()
for !it.Equal(s.slots.End()) {
it.Value().(*Slot).Destruct()
it = it.Next().(*vector.VectorIterator)
}
/* clean slots container */
s.slots.Clear()
// s.slots = nil is not needed
}
/* factory method for Signal */
func NewSignal() *Signal {
s := new(Signal)
s.isExecuting = false
s.slots = vector.New()
return s
}
type SlotList = *vector.Vector
type SlotIterator = *vector.VectorIterator
type Slot struct {
/** \brief weak reference of disconnect function
connection's lifetime is taken over by slot
*/
*Connection
/** \brief the handler function who will receive emitted signals
*/
Handler Handler
/** \brief the disconnect function which will disconnect this handler
*
* In practice this is the Signal.Disconnect method bound to a ptr
* pointing at this slot.
*
* Connection also has a ptr which references the same function object.
* When the slot is erased or the signal is destructed, this function object is
* destructed, and the related Connections cannot disconnect this slot again.
*/
Disconnect DisconnectFunction
}
/* Clear
\warn cannot use the slot which has been already Destructed
*/
func (s *Slot) Destruct() {
s.Handler = nil
s.Disconnect = nil
s.Connection.disconnect = nil
s.Connection = nil
}
func NewSlotByHandler(handler Handler) *Slot {
s := new(Slot)
s.Handler = handler
return s
}
+354
View File
@@ -0,0 +1,354 @@
/*
* Copyright (c) 2014-2022, Peking University Shenzhen Graduate School
*
* This file is part of MIN-Sync.
* See AUTHORS.md for complete list of MIN-Sync authors and contributors.
*
* MIN-Sync is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* MIN-Sync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* MIN-Sync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* The MIT License (MIT)
* Copyright (c) 2000 Arash Partow
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package utils
import (
"testing"
)
func TestZeroSlot(t *testing.T) {
s := NewSignal()
s.Emit()
}
func TestTwoListener(t *testing.T) {
s := NewSignal()
hit1 := 0
hit2 := 0
func1 := func(...interface{}) {
hit1 += 1
}
func2 := func(...interface{}) {
hit2 += 1
}
s.Connect(func1)
s.Connect(func2)
s.Emit()
if hit1 != 1 || hit2 != 1 {
t.Fatalf("Two listener failed.")
}
}
func TestOneArgument(t *testing.T) {
s := NewSignal()
hit1 := 0
func1 := func(args ...interface{}) {
hit1 += 1
num := args[0].(int)
if num != 8106 {
panic("Test one argument failed.")
}
}
s.Connect(func1)
s.Emit(8106)
if hit1 != 1 {
t.Fatalf("Two listener failed.")
}
}
func TestTwoArguments(t *testing.T) {
s := NewSignal()
hit1 := 0
func1 := func(args ...interface{}) {
hit1 += 1
num := args[0].(int)
if num != 8106 {
panic("Test two arguments failed.")
}
num1 := args[1].(int)
if num1 != 8107 {
panic("Test two arguments failed.")
}
}
s.Connect(func1)
s.Emit(8106, 8107)
if hit1 != 1 {
t.Fatalf("Two listener failed.")
}
}
func TestManualDisconnect(t *testing.T) {
s := NewSignal()
hit1 := 0
func1 := func(args ...interface{}) {
hit1 += 1
}
conn := s.Connect(func1)
s.Emit()
if hit1 != 1 {
t.Fatalf("ManualDisconnect failed.")
}
if !conn.IsConnected() {
t.Fatalf("ManualDisconnect failed.")
}
conn.Disconnect()
if conn.IsConnected() {
t.Fatalf("ManualDisconnect failed.")
}
s.Emit()
if hit1 != 1 {
t.Fatalf("ManualDisconnect failed.")
}
conn.Disconnect()
}
func TestManualDisconnectDestructed(t *testing.T) {
s := NewSignal()
hit1 := 0
func1 := func(args ...interface{}) {
hit1 += 1
}
conn := s.Connect(func1)
s.Emit()
if hit1 != 1 {
t.Fatalf("ManualDisconnectDestructed failed.")
}
s.Clear()
if conn.IsConnected() {
t.Fatalf("ManualDisconnectDestructed failed.")
}
s.Clear()
s.Emit()
s.Clear()
s.Emit()
if hit1 != 1 {
t.Fatalf("ManualDisconnectDestructed failed.")
}
}
func TestConnectSingleSlot(t *testing.T) {
s := NewSignal()
hit1 := 0
func1 := func(args ...interface{}) {
hit1 += 1
}
conn := s.ConnectSingleShot(func1)
s.Emit()
if hit1 != 1 {
t.Fatalf("ConnectSingleSlot failed.")
}
if conn.IsConnected() {
t.Fatalf("ConnectSingleSlot failed.")
}
}
func TestConnectSingleShotDisconnected(t *testing.T) {
s := NewSignal()
hit1 := 0
func1 := func(args ...interface{}) {
hit1 += 1
}
conn := s.ConnectSingleShot(func1)
if !conn.IsConnected() {
t.Fatalf("ConnectSingleShotDisconnected failed.")
}
conn.Disconnect()
if conn.IsConnected() {
t.Fatalf("ConnectSingleShotDisconnected failed.")
}
s.Emit()
if hit1 != 0 {
t.Fatalf("ConnectSingleShotDisconnected failed.")
}
}
func TestConnectSingleShot1(t *testing.T) {
s := NewSignal()
hit1 := 0
func1 := func(args ...interface{}) {
hit1 += 1
}
conn := s.ConnectSingleShot(func1)
s.Emit()
if hit1 != 1 {
t.Fatalf("ConnectSingleShot1 failed.")
}
if conn.IsConnected() {
t.Fatalf("ConnectSingleShot1 failed.")
}
s.Emit()
if hit1 != 1 {
t.Fatalf("ConnectSingleShot1 failed.")
}
}
func TestConnectInHandler(t *testing.T) {
s := NewSignal()
hit1 := 0
hit2 := 0
hasHandler2 := false
func1 := func(args ...interface{}) {
hit1 += 1
if !hasHandler2 {
s.Connect(func(i ...interface{}) {
hit2 += 1
hasHandler2 = true
})
}
}
s.Connect(func1)
s.Emit()
if hit1 != 1 || hit2 != 0 {
t.Fatalf("ConnectInHandler failed.")
}
s.Emit()
if hit1 != 2 || hit2 != 1 {
t.Fatalf("ConnectInHandler failed.")
}
}
func TestDisconnectSelfInHandler(t *testing.T) {
s := NewSignal()
hit1 := 0
var conn *Connection
func1 := func(args ...interface{}) {
hit1 += 1
if !conn.IsConnected() {
t.Fatalf("DisconnectSelfInHandler failed.")
}
conn.Disconnect()
if conn.IsConnected() {
t.Fatalf("DisconnectSelfInHandler failed.")
}
if s.IsEmpty() {
t.Fatalf("DisconnectSelfInHandler failed.")
}
}
conn = s.Connect(func1)
s.Emit()
if hit1 != 1 {
t.Fatalf("DisconnectSelfInHandler failed.")
}
if conn.IsConnected() {
t.Fatalf("DisconnectSelfInHandler failed.")
}
if !s.IsEmpty() {
t.Fatalf("DisconnectSelfInHandler failed.")
}
s.Emit()
if hit1 != 1 {
t.Fatalf("DisconnectSelfInHandler failed.")
}
}
func TestThrowInHandler(t *testing.T) {
s := NewSignal()
hit1 := 0
func1 := func(args ...interface{}) {
hit1 += 1
panic("hello")
}
s.Connect(func1)
defer func() {
if r := recover(); r != nil {
if hit1 != 1 {
t.Fatalf("ThrowInHandler failed.")
}
}
}()
s.Emit()
}