mirror of
https://gitee.com/willfree/mlsr.git
synced 2026-06-15 20:04:48 +08:00
372 lines
11 KiB
Go
372 lines
11 KiB
Go
// Package mir
|
||
// @Author: Wang Feng
|
||
// @Description: 其他模块可以调用本结构体,来完成对mir中fib的修改
|
||
// 最终形态应支持对mir中推式/拉式的fib表的修改。可暂时仅支持拉式。
|
||
// 注:基于wzq代码修改而来:https://gitea.qjm253.cn/PKUSZ-future-network-lab/ospf-min/src/branch/master/mir/fibcontroller.go
|
||
// @Version: 0.1.0
|
||
// @Date: 2022/7/21 15:13
|
||
// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||
//
|
||
|
||
package mir
|
||
|
||
import (
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
common2 "minlib/common"
|
||
"minlib/component"
|
||
"minlib/logicface"
|
||
"minlib/mgmt"
|
||
"minlib/security"
|
||
)
|
||
|
||
// 一些关于MIR的默认信息。todo 后期应完善到配置文件中,从配置文件中进行读取。
|
||
const (
|
||
MirUnixPath = "/tmp/mir.sock"
|
||
MirIdentityDBPath = "/usr/local/.mir/identity/"
|
||
MirDefaultId = "/min/mlsrDeamon"
|
||
MirDefaultPasswd = "pkusz"
|
||
MirTopPrefix = "/min-mir/mgmt/localhost"
|
||
)
|
||
|
||
// MirNextHopInfo
|
||
// @Description: 下一跳信息【可用于ListFib函数返回值的反序列化】
|
||
//
|
||
type MirNextHopInfo struct {
|
||
LogicFaceId uint64
|
||
Cost uint64
|
||
}
|
||
|
||
// MirFibInfo
|
||
// @Description: 每个FIB条目中,一个前缀可对应多个下一跳【可用于ListFib函数返回值的反序列化】
|
||
//
|
||
type MirFibInfo struct {
|
||
Identifier string
|
||
NextHopsInfo []MirNextHopInfo
|
||
}
|
||
|
||
// MirFaceInfo
|
||
// @Description: 用于从MIR获取所有face信息时的反序列化
|
||
//
|
||
type MirFaceInfo struct {
|
||
LogicFaceId uint64
|
||
RemoteUri string
|
||
LocalUri string
|
||
Mtu uint64
|
||
RateLimit int64
|
||
}
|
||
|
||
// FibCodeCaller
|
||
// @Description: 实现MIR中fib表项信息更改的结构体
|
||
//
|
||
type FibCodeCaller struct {
|
||
mirController *mgmt.MIRController
|
||
keyChain *security.KeyChain
|
||
}
|
||
|
||
//
|
||
// NewDefaultKeychain
|
||
// @Description: 传入mir身份密码,获取路由器的KeyChain
|
||
// @param passwd
|
||
// @return *security.KeyChain
|
||
//
|
||
func (c *FibCodeCaller) newDefaultKeychain(passwd string) *security.KeyChain {
|
||
keyChain := new(security.KeyChain)
|
||
if err := keyChain.InitialKeyChainByPath(MirIdentityDBPath); err != nil {
|
||
common2.LogFatal(err)
|
||
}
|
||
if identity := keyChain.GetIdentityByName(MirDefaultId); identity == nil {
|
||
common2.LogFatal("Identity => "+MirDefaultId, " not exists")
|
||
} else {
|
||
if err := keyChain.SetCurrentIdentity(identity, passwd); err != nil {
|
||
common2.LogFatal(err)
|
||
}
|
||
}
|
||
return keyChain
|
||
}
|
||
|
||
//
|
||
// NewController
|
||
// @Description: 传入密钥链,构建MirController(内置于MIR做进程间通信的unix-logicface)
|
||
// @param keyChain
|
||
// @return *mgmt.MIRController
|
||
//
|
||
func (c *FibCodeCaller) newController(keyChain *security.KeyChain) *mgmt.MIRController {
|
||
_controller := mgmt.CreateMIRController(func() (mgmt.IMgmtLogicFace, error) {
|
||
face := new(logicface.LogicFace)
|
||
/* unix connection */
|
||
if err := face.InitWithUnixSocket(MirUnixPath); err != nil {
|
||
return nil, err
|
||
}
|
||
return face, nil
|
||
}, true, keyChain)
|
||
return _controller
|
||
}
|
||
|
||
//
|
||
// Init
|
||
// @Description: 传入mir密钥
|
||
// @receiver c
|
||
// @param password
|
||
//
|
||
func (c *FibCodeCaller) Init(password string) {
|
||
c.keyChain = c.newDefaultKeychain(password)
|
||
c.mirController = c.newController(c.keyChain)
|
||
}
|
||
|
||
func (c *FibCodeCaller) Init2(password string, chain *security.KeyChain) {
|
||
c.keyChain = chain
|
||
c.mirController = c.newController(c.keyChain)
|
||
}
|
||
|
||
//
|
||
// newReadControlParameters
|
||
// @Description: 用于只读的参数,如ListFib
|
||
// @receiver c
|
||
// @return *component.ControlParameters
|
||
// @return error
|
||
//
|
||
func (c *FibCodeCaller) newReadControlParameters() (*component.ControlParameters, error) {
|
||
semantics := "pull"
|
||
parameters := &component.ControlParameters{}
|
||
parameters.SetSemantics(component.GetSemanticsEnumByString(semantics))
|
||
if !component.CheckSemanticsSupport(parameters.Semantics()) {
|
||
/* Not Support for this semantics */
|
||
return nil, errors.New("not support semantics: pull")
|
||
}
|
||
return parameters, nil
|
||
}
|
||
|
||
//
|
||
// newModifyControlParameters
|
||
// @Description: 用于修改的参数,如DelFib、AddFib
|
||
// @receiver c
|
||
// @param prefix 名称前缀
|
||
// @param nexthop 该名称前缀的网络出口,本函数将据此获取其对应的logicFaceId,并作为参数放入返回值中
|
||
// @param cost 本条目的开销
|
||
// @return *component.ControlParameters
|
||
// @return error
|
||
//
|
||
func (c *FibCodeCaller) newModifyControlParameters(prefix, nexthop string, cost uint64) (*component.ControlParameters, error) {
|
||
/* Attributes that fib needs */
|
||
semantics := "pull"
|
||
parameters := &component.ControlParameters{}
|
||
identifier, err := component.CreateIdentifierByString(prefix)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
logicFaceId, err := c.nexthop2LfId(nexthop)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
/* Control parameters setting */
|
||
parameters.SetPrefix(identifier)
|
||
parameters.SetLogicFaceId(logicFaceId)
|
||
parameters.SetCost(cost)
|
||
parameters.SetSemantics(component.GetSemanticsEnumByString(semantics)) /* push or pull semantic */
|
||
if !component.CheckSemanticsSupport(parameters.Semantics()) {
|
||
/* Not Support for this semantics */
|
||
return nil, errors.New("not support semantics: pull")
|
||
}
|
||
return parameters, nil
|
||
}
|
||
|
||
//
|
||
// newFibAddCommandExecutor
|
||
// @Description: 获取命令执行器,用于AddFib
|
||
// @receiver c
|
||
// @param parameters
|
||
// @return *mgmt.CommandExecutor
|
||
// @return error
|
||
//
|
||
func (c *FibCodeCaller) newFibAddCommandExecutor(parameters *component.ControlParameters) (*mgmt.CommandExecutor, error) {
|
||
/* Command executor factory method */
|
||
/* CreateFibxxxCommand needs more abstraction */
|
||
commandExecutor, err := c.mirController.PrepareCommandExecutor(mgmt.CreateFibAddCommand(MirTopPrefix, parameters))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
commandExecutor.SetAutoShutdown(true)
|
||
return commandExecutor, nil
|
||
}
|
||
|
||
//
|
||
// newFibDeleteCommandExecutor
|
||
// @Description: 获取命令执行器,用于DelFib
|
||
// @receiver c
|
||
// @param parameters
|
||
// @return *mgmt.CommandExecutor
|
||
// @return error
|
||
//
|
||
func (c *FibCodeCaller) newFibDeleteCommandExecutor(parameters *component.ControlParameters) (*mgmt.CommandExecutor, error) {
|
||
/* Command executor factory method */
|
||
/* CreateFibxxxCommand needs more abstraction */
|
||
commandExecutor, err := c.mirController.PrepareCommandExecutor(mgmt.CreateFibDeleteCommand(MirTopPrefix, parameters))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
commandExecutor.SetAutoShutdown(true)
|
||
return commandExecutor, nil
|
||
}
|
||
|
||
//
|
||
// newFibListCommandExecutor
|
||
// @Description: 获取命令执行器,用于ListFib
|
||
// @receiver c
|
||
// @param parameters
|
||
// @return *mgmt.CommandExecutor
|
||
// @return error
|
||
//
|
||
func (c *FibCodeCaller) newFibListCommandExecutor(parameters *component.ControlParameters) (*mgmt.CommandExecutor, error) {
|
||
/* Command executor factory method */
|
||
/* CreateFibxxxCommand needs more abstraction (return value should be interface) */
|
||
commandExecutor, err := c.mirController.PrepareCommandExecutor(mgmt.CreateFibListCommand(MirTopPrefix, parameters))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
commandExecutor.SetAutoShutdown(true)
|
||
return commandExecutor, nil
|
||
}
|
||
|
||
//
|
||
// addFib
|
||
// @Description: 增加某个fib表项
|
||
// @receiver c
|
||
// @param prefix
|
||
// @param nexthop
|
||
// @param cost
|
||
// @return error
|
||
//
|
||
func (c *FibCodeCaller) addFib(prefix string, nexthop string, cost uint64) error {
|
||
/* Create Control Parameters */
|
||
parameters, err := c.newModifyControlParameters(prefix, nexthop, cost)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
/* Create Command Executor*/
|
||
commandExecutor, err := c.newFibAddCommandExecutor(parameters)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
/* execute command */
|
||
response, err := commandExecutor.Start()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
/* success */
|
||
if response.Code != mgmt.ControlResponseCodeSuccess {
|
||
/* failure */
|
||
return errors.New(fmt.Sprintf("Add next hop for %s => %s failed! errMsg: %s", prefix, nexthop, response.Msg))
|
||
}
|
||
return nil
|
||
}
|
||
|
||
//
|
||
// DelFib
|
||
// @Description: 删除某个fib表项
|
||
// @receiver c
|
||
// @param prefix
|
||
// @param nexthop
|
||
// @param cost
|
||
// @return error
|
||
//
|
||
func (c *FibCodeCaller) delFib(prefix string, nexthop string, cost uint64) error {
|
||
/* Create Control Parameters */
|
||
parameters, err := c.newModifyControlParameters(prefix, nexthop, cost)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
/* Create Command Executor*/
|
||
commandExecutor, err := c.newFibDeleteCommandExecutor(parameters)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
/* execute command */
|
||
response, err := commandExecutor.Start()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
/* success */
|
||
if response.Code != mgmt.ControlResponseCodeSuccess {
|
||
/* failure */
|
||
return errors.New(fmt.Sprintf("Delete next hop for %s => %s failed! errMsg: %s", prefix, nexthop, response.Msg))
|
||
}
|
||
return nil
|
||
}
|
||
|
||
//
|
||
// ListFib
|
||
// @Description: 获取fib表项(默认拉式)
|
||
// @receiver c
|
||
// @return string
|
||
//
|
||
func (c *FibCodeCaller) listFib() (string, error) {
|
||
/* Create Control Parameters */
|
||
parameters, err := NewReadControlParameters()
|
||
if err != nil {
|
||
return err.Error(), err
|
||
}
|
||
/* Create Command Executor*/
|
||
commandExecutor, err := c.newFibListCommandExecutor(parameters)
|
||
if err != nil {
|
||
return err.Error(), err
|
||
}
|
||
/* execute command */
|
||
response, err := commandExecutor.Start()
|
||
if err != nil {
|
||
return err.Error(), err
|
||
}
|
||
/* success */
|
||
if response.Code != mgmt.ControlResponseCodeSuccess {
|
||
/* failure */
|
||
return errors.New(fmt.Sprintf("List fibs failed! errMsg: %s", response.Msg)).Error(), err
|
||
}
|
||
return response.GetString(), nil
|
||
}
|
||
|
||
//
|
||
// nexthop2LfId
|
||
// @Description: 根据NextHop获取其对应的logicfaceID,以填充到用于修改的参数中去。
|
||
// 获取过程:先通过与MIR进程通信,获取所有LogicFace信息;
|
||
// 再通过将face的远端uri与传入的nexthop进行对比,找到匹配的那个logicFace;
|
||
// 最后将该logicface的id进行返回。
|
||
// @receiver c
|
||
// @param nexthop 形式如”tcp://192.168.0.1:2333“的对端uri
|
||
// @return uint64 LogicFaceId
|
||
// @return error
|
||
//
|
||
func (c *FibCodeCaller) nexthop2LfId(nexthop string) (uint64, error) {
|
||
commandExecutor, err := c.mirController.PrepareCommandExecutor(mgmt.CreateLogicFaceListCommand(MirTopPrefix))
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
commandExecutor.SetAutoShutdown(true)
|
||
/* execute command */
|
||
response, err := commandExecutor.Start()
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
var faceInfoList []MirFaceInfo
|
||
/* unmarshal response */
|
||
err = json.Unmarshal(response.GetBytes(), &faceInfoList)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
/* function: get logic face id in logic face list */
|
||
getId := func(ifAddr string) int {
|
||
for _, v := range faceInfoList {
|
||
if v.RemoteUri == ifAddr {
|
||
return int(v.LogicFaceId)
|
||
}
|
||
}
|
||
return -1
|
||
}
|
||
res := -1
|
||
res = getId(nexthop)
|
||
if res != -1 {
|
||
return uint64(res), nil
|
||
}
|
||
return 0, errors.New(fmt.Sprintf("Cannot get logicface of : %s", nexthop))
|
||
}
|