EtherGuard-VPN/path/path.go

590 lines
14 KiB
Go
Raw Normal View History

2021-08-16 20:58:15 +02:00
package path
import (
2021-10-12 10:05:23 +02:00
"errors"
2021-08-16 20:58:15 +02:00
"fmt"
2021-08-25 15:21:26 +02:00
"io/ioutil"
2021-08-16 20:58:15 +02:00
"math"
2021-08-25 15:21:26 +02:00
"strings"
2021-08-21 16:54:24 +02:00
"sync"
2021-08-16 20:58:15 +02:00
"time"
2021-12-02 18:13:48 +01:00
"github.com/KusakabeSi/EtherGuard-VPN/mtypes"
orderedmap "github.com/KusakabeSi/EtherGuard-VPN/orderdmap"
2021-08-16 20:58:15 +02:00
yaml "gopkg.in/yaml.v2"
)
2021-08-20 19:32:50 +02:00
func (g *IG) GetCurrentTime() time.Time {
2021-08-25 13:54:13 +02:00
return time.Now().Add(g.ntp_offset).Round(0)
2021-08-20 19:32:50 +02:00
}
2021-08-16 20:58:15 +02:00
type Latency struct {
2021-10-27 03:02:44 +02:00
ping float64
ping_old float64
additionalCost float64
2021-12-02 18:13:48 +01:00
validUntil time.Time
2021-08-16 20:58:15 +02:00
}
type Fullroute struct {
2021-12-02 18:13:48 +01:00
Next mtypes.NextHopTable `yaml:"NextHopTable"`
Dist mtypes.DistTable `yaml:"DistanceTable"`
2021-08-16 20:58:15 +02:00
}
// IG is a graph of integers that satisfies the Graph interface.
type IG struct {
2021-12-09 08:46:15 +01:00
Vert map[mtypes.Vertex]bool
edges map[mtypes.Vertex]map[mtypes.Vertex]*Latency
edgelock *sync.RWMutex
gsetting mtypes.GraphRecalculateSetting
SuperNodeInfoTimeout time.Duration
RecalculateCoolDown time.Duration
TimeoutCheckInterval time.Duration
recalculateTime time.Time
dlTable mtypes.DistTable
nhTable mtypes.NextHopTable
changed bool
NhTableExpire time.Time
IsSuperMode bool
loglevel mtypes.LoggerInfo
2021-08-25 13:54:13 +02:00
ntp_wg sync.WaitGroup
2021-12-04 15:46:36 +01:00
ntp_info mtypes.NTPInfo
2021-08-25 13:54:13 +02:00
ntp_offset time.Duration
ntp_servers orderedmap.OrderedMap // serverurl:lentancy
2021-08-20 19:32:50 +02:00
}
2021-12-09 08:46:15 +01:00
func NewGraph(num_node int, IsSuperMode bool, theconfig mtypes.GraphRecalculateSetting, ntpinfo mtypes.NTPInfo, loglevel mtypes.LoggerInfo) (*IG, error) {
2021-08-20 19:32:50 +02:00
g := IG{
2021-12-09 08:46:15 +01:00
edgelock: &sync.RWMutex{},
gsetting: theconfig,
RecalculateCoolDown: mtypes.S2TD(theconfig.RecalculateCoolDown),
TimeoutCheckInterval: mtypes.S2TD(theconfig.TimeoutCheckInterval),
ntp_info: ntpinfo,
2021-08-20 19:32:50 +02:00
}
2021-12-02 18:13:48 +01:00
g.Vert = make(map[mtypes.Vertex]bool, num_node)
g.edges = make(map[mtypes.Vertex]map[mtypes.Vertex]*Latency, num_node)
2021-08-20 19:32:50 +02:00
g.IsSuperMode = IsSuperMode
2021-10-12 10:05:23 +02:00
g.loglevel = loglevel
2021-08-25 13:54:13 +02:00
g.InitNTP()
2021-12-09 08:46:15 +01:00
return &g, nil
2021-08-16 20:58:15 +02:00
}
2021-08-24 10:43:55 +02:00
func (g *IG) GetWeightType(x float64) (y float64) {
2021-08-20 19:32:50 +02:00
x = math.Abs(x)
2021-08-24 10:43:55 +02:00
y = x
2021-12-09 08:46:15 +01:00
if g.gsetting.JitterTolerance > 0.001 && g.gsetting.JitterToleranceMultiplier > 1 {
t := g.gsetting.JitterTolerance
r := g.gsetting.JitterToleranceMultiplier
2021-08-24 10:43:55 +02:00
y = math.Pow(math.Ceil(math.Pow(x/t, 1/r)), r) * t
2021-08-20 19:32:50 +02:00
}
return y
}
2021-12-09 08:46:15 +01:00
func (g *IG) ShouldUpdate(oldval float64, newval float64, withCooldown bool) bool {
if (oldval >= mtypes.Infinity) != (newval >= mtypes.Infinity) {
return true
}
if withCooldown {
if g.recalculateTime.Add(g.RecalculateCoolDown).After(time.Now()) {
return false
}
}
2021-12-07 21:39:19 +01:00
oldval = math.Abs(oldval * 1000)
2021-08-24 10:43:55 +02:00
newval = math.Abs(newval * 1000)
2021-08-20 19:32:50 +02:00
if g.IsSuperMode {
2021-12-09 08:46:15 +01:00
if g.gsetting.JitterTolerance > 0.001 && g.gsetting.JitterToleranceMultiplier >= 1 {
2021-08-24 10:43:55 +02:00
diff := math.Abs(newval - oldval)
x := math.Max(oldval, newval)
2021-12-09 08:46:15 +01:00
t := g.gsetting.JitterTolerance
r := g.gsetting.JitterToleranceMultiplier
2021-08-24 10:43:55 +02:00
return diff > t+x*(r-1) // https://www.desmos.com/calculator/raoti16r5n
}
return oldval == newval
2021-08-20 19:32:50 +02:00
} else {
2021-08-25 15:21:26 +02:00
return g.GetWeightType(oldval) != g.GetWeightType(newval)
2021-08-20 19:32:50 +02:00
}
}
2021-12-09 08:46:15 +01:00
func (g *IG) CheckAnyShouldUpdate(withCooldown bool) bool {
2021-10-14 12:37:09 +02:00
vert := g.Vertices()
2021-12-09 08:46:15 +01:00
for u := range vert {
for v := range vert {
2021-10-27 03:02:44 +02:00
if u != v {
newVal := g.Weight(u, v, false)
2021-12-07 21:39:19 +01:00
oldVal := g.OldWeight(u, v, false)
2021-12-09 08:46:15 +01:00
if g.ShouldUpdate(oldVal, newVal, withCooldown) {
2021-10-27 03:02:44 +02:00
return true
}
2021-10-14 12:37:09 +02:00
}
}
}
return false
}
2021-08-20 19:32:50 +02:00
func (g *IG) RecalculateNhTable(checkchange bool) (changed bool) {
2021-12-09 08:46:15 +01:00
if g.gsetting.StaticMode {
2021-12-04 03:32:59 +01:00
if g.changed {
changed = checkchange
}
return
}
2021-12-09 08:46:15 +01:00
if !g.CheckAnyShouldUpdate(true) {
2021-10-12 10:05:23 +02:00
return
}
2021-12-09 08:46:15 +01:00
dist, next, _ := g.FloydWarshall(false)
changed = false
if checkchange {
CheckLoop:
for src, dsts := range next {
for dst, old_next := range dsts {
nexthop := g.Next(src, dst)
if old_next != nexthop {
changed = true
break CheckLoop
2021-08-20 19:32:50 +02:00
}
}
}
2021-09-21 22:03:11 +02:00
}
2021-12-09 08:46:15 +01:00
g.dlTable, g.nhTable = dist, next
g.recalculateTime = time.Now()
2021-09-21 22:03:11 +02:00
return
}
2021-12-02 18:13:48 +01:00
func (g *IG) RemoveVirt(v mtypes.Vertex, recalculate bool, checkchange bool) (changed bool) { //Waiting for test
2021-09-21 22:03:11 +02:00
g.edgelock.Lock()
2021-10-12 10:05:23 +02:00
delete(g.Vert, v)
delete(g.edges, v)
2021-12-09 08:46:15 +01:00
for u := range g.edges {
2021-10-12 10:05:23 +02:00
delete(g.edges[u], v)
2021-09-21 22:03:11 +02:00
}
g.edgelock.Unlock()
2021-12-04 03:32:59 +01:00
g.changed = true
2021-09-21 22:03:11 +02:00
if recalculate {
changed = g.RecalculateNhTable(checkchange)
2021-08-20 19:32:50 +02:00
}
return
}
2021-12-02 18:13:48 +01:00
func (g *IG) UpdateLatency(src mtypes.Vertex, dst mtypes.Vertex, val float64, TimeToAlive float64, SuperAdditionalCost float64, recalculate bool, checkchange bool) (changed bool) {
return g.UpdateLatencyMulti([]mtypes.PongMsg{{
Src_nodeID: src,
Dst_nodeID: dst,
Timediff: val,
AdditionalCost: SuperAdditionalCost,
TimeToAlive: TimeToAlive,
}}, recalculate, checkchange)
}
func (g *IG) UpdateLatencyMulti(pong_info []mtypes.PongMsg, recalculate bool, checkchange bool) (changed bool) {
2021-08-26 21:06:15 +02:00
g.edgelock.Lock()
2021-12-02 18:13:48 +01:00
should_update := false
for _, pong_msg := range pong_info {
u := pong_msg.Src_nodeID
v := pong_msg.Dst_nodeID
2021-12-09 08:46:15 +01:00
newval := pong_msg.Timediff
2021-12-28 10:45:35 +01:00
if dst_latency, ok := g.gsetting.ManualLatency[mtypes.NodeID_Broadcast]; ok {
if _, ok := dst_latency[mtypes.NodeID_Broadcast]; ok {
newval = dst_latency[mtypes.NodeID_Broadcast] / 1000 // s to ms
}
if _, ok := dst_latency[v]; ok {
newval = dst_latency[v] / 1000 // s to ms
}
}
if dst_latency, ok := g.gsetting.ManualLatency[u]; ok {
if _, ok := dst_latency[mtypes.NodeID_Broadcast]; ok {
newval = dst_latency[mtypes.NodeID_Broadcast] / 1000 // s to ms
}
if _, ok := dst_latency[v]; ok {
newval = dst_latency[v] / 1000 // s to ms
2021-12-09 08:46:15 +01:00
}
}
w := newval
2021-12-02 18:13:48 +01:00
additionalCost := pong_msg.AdditionalCost
if additionalCost < 0 {
additionalCost = 0
}
g.Vert[u] = true
g.Vert[v] = true
if _, ok := g.edges[u]; !ok {
g.recalculateTime = time.Time{}
g.edges[u] = make(map[mtypes.Vertex]*Latency)
}
g.edgelock.Unlock()
2021-12-07 21:39:19 +01:00
oldval := g.OldWeight(u, v, false)
2021-12-02 18:13:48 +01:00
g.edgelock.Lock()
2021-12-09 08:46:15 +01:00
should_update = should_update || g.ShouldUpdate(oldval, w, false)
2021-12-02 18:13:48 +01:00
if _, ok := g.edges[u][v]; ok {
g.edges[u][v].ping = w
g.edges[u][v].validUntil = time.Now().Add(mtypes.S2TD(pong_msg.TimeToAlive))
g.edges[u][v].additionalCost = additionalCost / 1000
} else {
g.edges[u][v] = &Latency{
ping: w,
2021-12-09 08:46:15 +01:00
ping_old: mtypes.Infinity,
2021-12-02 18:13:48 +01:00
validUntil: time.Now().Add(mtypes.S2TD(pong_msg.TimeToAlive)),
additionalCost: additionalCost / 1000,
}
2021-10-12 10:05:23 +02:00
}
2021-08-16 20:58:15 +02:00
}
2021-08-21 16:54:24 +02:00
g.edgelock.Unlock()
2021-08-26 21:06:15 +02:00
if should_update && recalculate {
changed = g.RecalculateNhTable(checkchange)
}
2021-08-20 19:32:50 +02:00
return
}
2021-12-02 18:13:48 +01:00
func (g *IG) Vertices() map[mtypes.Vertex]bool {
vr := make(map[mtypes.Vertex]bool)
2021-08-23 19:45:09 +02:00
g.edgelock.RLock()
defer g.edgelock.RUnlock()
2021-08-23 18:39:04 +02:00
for k, v := range g.Vert { //copy a new list
vr[k] = v
}
return vr
2021-08-16 20:58:15 +02:00
}
2021-12-09 08:46:15 +01:00
func (g *IG) Neighbors(v mtypes.Vertex) (vs []mtypes.Vertex) {
2021-08-23 18:39:04 +02:00
g.edgelock.RLock()
defer g.edgelock.RUnlock()
for k := range g.edges[v] { //copy a new list
2021-08-16 20:58:15 +02:00
vs = append(vs, k)
}
return vs
}
2021-08-20 19:32:50 +02:00
2021-12-09 08:46:15 +01:00
func (g *IG) Next(u, v mtypes.Vertex) mtypes.Vertex {
if _, ok := g.nhTable[u]; !ok {
2021-12-09 08:46:15 +01:00
return mtypes.NodeID_Invalid
2021-08-20 19:32:50 +02:00
}
if _, ok := g.nhTable[u][v]; !ok {
2021-12-09 08:46:15 +01:00
return mtypes.NodeID_Invalid
2021-08-20 19:32:50 +02:00
}
return g.nhTable[u][v]
2021-08-20 19:32:50 +02:00
}
2021-12-02 18:13:48 +01:00
func (g *IG) Weight(u, v mtypes.Vertex, withAC bool) (ret float64) {
2021-08-23 18:39:04 +02:00
g.edgelock.RLock()
defer g.edgelock.RUnlock()
2021-10-12 10:05:23 +02:00
//defer func() { fmt.Println(u, v, ret) }()
if u == v {
return 0
}
2021-08-21 16:54:24 +02:00
if _, ok := g.edges[u]; !ok {
2021-12-09 08:46:15 +01:00
return mtypes.Infinity
2021-08-20 19:32:50 +02:00
}
2021-08-21 16:54:24 +02:00
if _, ok := g.edges[u][v]; !ok {
2021-12-09 08:46:15 +01:00
return mtypes.Infinity
2021-08-20 19:32:50 +02:00
}
2021-12-02 18:13:48 +01:00
if time.Now().After(g.edges[u][v].validUntil) {
2021-12-09 08:46:15 +01:00
return mtypes.Infinity
2021-08-16 20:58:15 +02:00
}
2021-10-27 03:53:01 +02:00
ret = g.edges[u][v].ping
2021-10-27 03:02:44 +02:00
if withAC {
2021-10-27 03:53:01 +02:00
ret += g.edges[u][v].additionalCost
2021-10-27 03:02:44 +02:00
}
2021-12-09 08:46:15 +01:00
if ret >= mtypes.Infinity {
return mtypes.Infinity
2021-10-27 03:02:44 +02:00
}
return
2021-08-16 20:58:15 +02:00
}
2021-12-02 18:13:48 +01:00
func (g *IG) OldWeight(u, v mtypes.Vertex, withAC bool) (ret float64) {
2021-10-12 10:05:23 +02:00
g.edgelock.RLock()
defer g.edgelock.RUnlock()
if u == v {
return 0
}
if _, ok := g.edges[u]; !ok {
2021-12-09 08:46:15 +01:00
return mtypes.Infinity
2021-10-12 10:05:23 +02:00
}
if _, ok := g.edges[u][v]; !ok {
2021-12-09 08:46:15 +01:00
return mtypes.Infinity
2021-10-12 10:05:23 +02:00
}
2021-10-27 03:53:01 +02:00
ret = g.edges[u][v].ping_old
2021-10-27 03:02:44 +02:00
if withAC {
2021-10-27 03:53:01 +02:00
ret += g.edges[u][v].additionalCost
2021-10-12 10:05:23 +02:00
}
2021-12-09 08:46:15 +01:00
if ret >= mtypes.Infinity {
return mtypes.Infinity
2021-10-27 03:02:44 +02:00
}
return
2021-10-12 10:05:23 +02:00
}
2021-12-02 18:13:48 +01:00
func (g *IG) SetWeight(u, v mtypes.Vertex, weight float64) {
2021-10-12 10:05:23 +02:00
g.edgelock.Lock()
defer g.edgelock.Unlock()
if _, ok := g.edges[u]; !ok {
return
}
if _, ok := g.edges[u][v]; !ok {
return
}
g.edges[u][v].ping = weight
}
2021-12-02 18:13:48 +01:00
func (g *IG) SetOldWeight(u, v mtypes.Vertex, weight float64) {
2021-10-12 10:05:23 +02:00
g.edgelock.Lock()
defer g.edgelock.Unlock()
if _, ok := g.edges[u]; !ok {
return
}
if _, ok := g.edges[u][v]; !ok {
return
}
g.edges[u][v].ping_old = weight
}
func (g *IG) RemoveAllNegativeValue() {
vert := g.Vertices()
2021-12-09 08:46:15 +01:00
for u := range vert {
for v := range vert {
2021-10-27 03:02:44 +02:00
if g.Weight(u, v, true) < 0 {
2021-10-12 10:05:23 +02:00
if g.loglevel.LogInternal {
fmt.Printf("Internal: Remove negative value : edge[%v][%v] = 0\n", u, v)
}
g.SetWeight(u, v, 0)
}
}
}
}
2021-12-02 18:13:48 +01:00
func (g *IG) FloydWarshall(again bool) (dist mtypes.DistTable, next mtypes.NextHopTable, err error) {
2021-10-12 10:05:23 +02:00
if g.loglevel.LogInternal {
if !again {
fmt.Println("Internal: Start Floyd Warshall algorithm")
} else {
fmt.Println("Internal: Start Floyd Warshall algorithm again")
}
}
2021-08-16 20:58:15 +02:00
vert := g.Vertices()
2021-12-02 18:13:48 +01:00
dist = make(mtypes.DistTable)
next = make(mtypes.NextHopTable)
2021-12-09 08:46:15 +01:00
for u := range vert {
2021-12-02 18:13:48 +01:00
dist[u] = make(map[mtypes.Vertex]float64)
2021-12-09 08:46:15 +01:00
next[u] = make(map[mtypes.Vertex]mtypes.Vertex)
for v := range vert {
dist[u][v] = mtypes.Infinity
2021-08-16 20:58:15 +02:00
}
dist[u][u] = 0
for _, v := range g.Neighbors(u) {
2021-10-27 03:02:44 +02:00
w := g.Weight(u, v, true)
wo := g.Weight(u, v, false)
2021-12-09 08:46:15 +01:00
if w < mtypes.Infinity {
2021-08-16 20:58:15 +02:00
v := v
dist[u][v] = w
2021-12-09 08:46:15 +01:00
next[u][v] = v
2021-08-16 20:58:15 +02:00
}
2021-10-27 03:02:44 +02:00
g.SetOldWeight(u, v, wo)
2021-08-16 20:58:15 +02:00
}
}
2021-12-09 08:46:15 +01:00
for k := range vert {
for i := range vert {
for j := range vert {
if dist[i][k] < mtypes.Infinity && dist[k][j] < mtypes.Infinity {
2021-08-16 20:58:15 +02:00
if dist[i][j] > dist[i][k]+dist[k][j] {
dist[i][j] = dist[i][k] + dist[k][j]
next[i][j] = next[i][k]
}
}
}
}
}
2021-10-12 10:05:23 +02:00
for i := range dist {
if dist[i][i] < 0 {
if !again {
if g.loglevel.LogInternal {
fmt.Println("Internal: Error: Negative cycle detected")
}
g.RemoveAllNegativeValue()
err = errors.New("negative cycle detected")
dist, next, _ = g.FloydWarshall(true)
return
} else {
2021-12-02 18:13:48 +01:00
dist = make(mtypes.DistTable)
next = make(mtypes.NextHopTable)
2021-12-09 08:46:15 +01:00
err = errors.New("negative cycle detected again")
2021-10-12 10:05:23 +02:00
if g.loglevel.LogInternal {
fmt.Println("Internal: Error: Negative cycle detected again")
}
return
}
}
}
return
2021-08-16 20:58:15 +02:00
}
2021-12-09 08:46:15 +01:00
func (g *IG) Path(u, v mtypes.Vertex) (path []mtypes.Vertex, err error) {
g.edgelock.RLock()
defer g.edgelock.RUnlock()
footprint := make(map[mtypes.Vertex]bool)
2021-08-16 20:58:15 +02:00
for u != v {
2021-12-09 08:46:15 +01:00
if _, has := footprint[u]; has {
return path, fmt.Errorf("cycle detected in nhTable, s:%v e:%v path:%v", u, v, path)
}
if _, ok := g.nhTable[u]; !ok {
return path, fmt.Errorf("nhTable[%v] not exist", u)
}
if _, ok := g.nhTable[u][v]; !ok {
return path, fmt.Errorf("nhTable[%v][%v] not exist", u, v)
}
2021-08-16 20:58:15 +02:00
path = append(path, u)
2021-12-09 08:46:15 +01:00
footprint[u] = true
u = g.nhTable[u][v]
2021-08-16 20:58:15 +02:00
}
2021-12-09 08:46:15 +01:00
path = append(path, u)
return path, nil
2021-08-16 20:58:15 +02:00
}
2021-12-04 03:32:59 +01:00
func (g *IG) SetNHTable(nh mtypes.NextHopTable) { // set nhTable from supernode
2021-12-07 21:39:19 +01:00
g.edgelock.Lock()
2021-12-09 08:46:15 +01:00
defer g.edgelock.Unlock()
g.nhTable = nh
2021-12-04 03:32:59 +01:00
g.changed = true
2021-08-24 20:16:21 +02:00
g.NhTableExpire = time.Now().Add(g.SuperNodeInfoTimeout)
2021-08-20 19:32:50 +02:00
}
2021-12-02 18:13:48 +01:00
func (g *IG) GetNHTable(recalculate bool) mtypes.NextHopTable {
2021-10-12 10:05:23 +02:00
if recalculate && time.Now().After(g.NhTableExpire) {
2021-09-21 22:03:11 +02:00
g.RecalculateNhTable(false)
2021-08-20 19:32:50 +02:00
}
return g.nhTable
2021-08-20 19:32:50 +02:00
}
2021-12-02 18:13:48 +01:00
func (g *IG) GetDtst() mtypes.DistTable {
2021-08-24 20:16:21 +02:00
return g.dlTable
}
2021-12-02 18:13:48 +01:00
func (g *IG) GetEdges(isOld bool, withAC bool) (edges map[mtypes.Vertex]map[mtypes.Vertex]float64) {
2021-08-24 20:16:21 +02:00
vert := g.Vertices()
2021-12-02 18:13:48 +01:00
edges = make(map[mtypes.Vertex]map[mtypes.Vertex]float64, len(vert))
2021-12-09 08:46:15 +01:00
for src := range vert {
2021-12-02 18:13:48 +01:00
edges[src] = make(map[mtypes.Vertex]float64, len(vert))
2021-12-09 08:46:15 +01:00
for dst := range vert {
2021-08-25 10:13:53 +02:00
if src != dst {
2021-10-12 10:05:23 +02:00
if isOld {
2021-10-27 03:02:44 +02:00
edges[src][dst] = g.OldWeight(src, dst, withAC)
2021-10-12 10:05:23 +02:00
} else {
2021-10-27 03:02:44 +02:00
edges[src][dst] = g.Weight(src, dst, withAC)
2021-10-12 10:05:23 +02:00
}
2021-08-25 10:13:53 +02:00
}
2021-08-24 20:16:21 +02:00
}
}
return
}
2021-12-02 18:13:48 +01:00
func (g *IG) GetBoardcastList(id mtypes.Vertex) (tosend map[mtypes.Vertex]bool) {
tosend = make(map[mtypes.Vertex]bool)
for _, element := range g.nhTable[id] {
2021-12-09 08:46:15 +01:00
tosend[element] = true
2021-08-16 20:58:15 +02:00
}
return
}
2021-12-09 08:46:15 +01:00
func (g *IG) GetBoardcastThroughList(self_id mtypes.Vertex, in_id mtypes.Vertex, src_id mtypes.Vertex) (tosend map[mtypes.Vertex]bool, errs []error) {
2021-12-02 18:13:48 +01:00
tosend = make(map[mtypes.Vertex]bool)
2021-12-09 08:46:15 +01:00
for check_id := range g.GetBoardcastList(self_id) {
path, err := g.Path(src_id, check_id)
if err != nil {
errs = append(errs, err)
continue
}
for _, path_node := range path {
2021-08-20 19:32:50 +02:00
if path_node == self_id && check_id != in_id {
2021-08-16 20:58:15 +02:00
tosend[check_id] = true
continue
}
}
}
return
}
2021-08-25 15:21:26 +02:00
func printExample() {
fmt.Println(`X 1 2 3 4 5 6
1 0 0.5 Inf Inf Inf Inf
2 0.5 0 0.5 0.5 Inf Inf
3 Inf 0.5 0 0.5 0.5 Inf
4 Inf 0.5 0.5 0 Inf 0.5
5 Inf Inf 0.5 Inf 0 Inf
6 Inf Inf Inf 0.5 Inf 0`)
}
2021-12-09 08:46:15 +01:00
func ParseDistanceMatrix(input string) ([]mtypes.PongMsg, error) {
lines := strings.Split(input, "\n")
verts := strings.Fields(lines[0])
ret := make([]mtypes.PongMsg, 0, len(verts)*len(verts))
for li, line := range lines[1:] {
element := strings.Fields(line)
src, err := mtypes.String2NodeID(element[0])
if err != nil {
return ret, err
}
if len(element) != len(verts) {
return ret, fmt.Errorf("parse error at line %v: element number mismatch to node id number", li)
}
for ei, sval := range element[1:] {
val, err := mtypes.String2Float64(sval)
if err != nil {
return ret, err
}
dst, err := mtypes.String2NodeID(verts[ei+1])
if err != nil {
return ret, err
}
if src != dst && val != mtypes.Infinity {
ret = append(ret, mtypes.PongMsg{
Src_nodeID: src,
Dst_nodeID: dst,
Timediff: val,
TimeToAlive: 999999,
})
}
}
2021-08-25 15:21:26 +02:00
}
2021-12-09 08:46:15 +01:00
return ret, nil
2021-08-25 15:21:26 +02:00
}
func Solve(filePath string, pe bool) error {
if pe {
printExample()
return nil
}
2021-12-09 08:46:15 +01:00
g, _ := NewGraph(3, false, mtypes.GraphRecalculateSetting{}, mtypes.NTPInfo{}, mtypes.LoggerInfo{LogInternal: false})
2021-08-25 15:21:26 +02:00
inputb, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
input := string(inputb)
2021-12-09 08:46:15 +01:00
all_edge, _ := ParseDistanceMatrix(input)
g.UpdateLatencyMulti(all_edge, false, false)
2021-10-12 10:05:23 +02:00
dist, next, err := g.FloydWarshall(false)
if err != nil {
fmt.Println("Error:", err)
}
2021-08-25 15:21:26 +02:00
2021-08-16 20:58:15 +02:00
rr, _ := yaml.Marshal(Fullroute{
Dist: dist,
Next: next,
})
fmt.Print(string(rr))
2021-08-25 15:21:26 +02:00
fmt.Println("\nHuman readable:")
fmt.Println("src\tdist\t\tpath")
2021-12-09 08:46:15 +01:00
all_vert := g.Vertices()
for u := range all_vert {
for v := range all_vert {
2021-08-25 15:21:26 +02:00
if u != v {
2021-12-09 08:46:15 +01:00
path, err := g.Path(u, v)
pathstr := fmt.Sprint(path)
if err != nil {
pathstr = fmt.Sprint(path)
}
fmt.Printf("%d -> %d\t%3f\t%s\n", u, v, dist[u][v], pathstr)
2021-08-25 15:21:26 +02:00
}
}
}
return nil
2021-08-16 20:58:15 +02:00
}