1
0
mirror of https://gitee.com/willfree/mlsr.git synced 2026-06-17 16:20:25 +08:00
Files
mlsr/route/NextHopList.go
T

229 lines
5.3 KiB
Go

// 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() {
// 注意,这里必须先删掉旧的,再加入新的;如果直接修改旧的nextHop,则可能导致该nextHop所属的另一个NextHopList属性被改变
l.RemoveNextHop(l.nextHops[index])
l.nextHops = append(l.nextHops, hop)
}
}
//
// AddNextHopBySmallerPriciple
// @Description: 在加入重合下一跳时,按照取较小开销的下一跳原则,进行更新
// @receiver l
// @param hop
//
func (l *NextHopList) AddNextHopBySmallerPriciple(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() {
// 注意,这里必须先删掉旧的,再加入新的;如果直接修改旧的nextHop,则可能导致该nextHop所属的另一个NextHopList属性被改变
l.RemoveNextHop(l.nextHops[index])
l.nextHops = append(l.nextHops, hop)
}
}
//
// 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
}