From 87a4af784164899c921abf4462acab13682d226a Mon Sep 17 00:00:00 2001 From: Arceliar Date: Sun, 21 Jan 2018 14:58:54 -0600 Subject: [PATCH] update admin dot to better handle missing nodes and to direct links towards parent, based on neilalexander's work --- misc/sim/treesim.go | 24 ++++++++++++++++ src/yggdrasil/admin.go | 62 +++++++++++++++++++++++++++++++++--------- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/misc/sim/treesim.go b/misc/sim/treesim.go index 8d4d3f7..afb681e 100644 --- a/misc/sim/treesim.go +++ b/misc/sim/treesim.go @@ -377,6 +377,14 @@ func dumpDHTSize(store map[[32]byte]*Node) { fmt.Printf("DHT min %d / avg %f / max %d\n", min, avg, max) } +func (n *Node) startUDP(listen string) { + n.core.DEBUG_setupAndStartGlobalUDPInterface(listen) +} + +func (n *Node) connectUDP(remoteAddr string) { + n.core.DEBUG_maybeSendUDPKeys(remoteAddr) +} + //////////////////////////////////////////////////////////////////////////////// var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") @@ -416,6 +424,22 @@ func main() { } */ startNetwork(kstore) + if true { + for _, node := range kstore { + node.startUDP("localhost:0") + node.connectUDP("localhost:12345") + break // just 1 + } + for _, node := range kstore { + go func() { + // Just dump any packets sent to this node + for range node.recv { + } + }() + } + var block chan struct{} + <-block + } //time.Sleep(10*time.Second) // Note that testPaths only works if pressure is turend off // Otherwise congestion can lead to routing loops? diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index eec1d71..3cf2cd2 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -111,24 +111,60 @@ func (a *admin) handleRequest(conn net.Conn) { } a.core.router.doAdmin(getSessions) - // Now print it all out - conn.Write([]byte(fmt.Sprintf("graph {\n"))) - for k := range m { - var mask [mDepth]switchPort - copy(mask[:mDepth], k[:]) - for mk := range mask { - mask[len(mask)-1-mk] = 0 - if len(m[k]) == 0 { - m[k] = fmt.Sprintf("%+v (missing)", k) + // Start building a tree from all known nodes + type nodeInfo struct { + name string + key [mDepth]switchPort + parent [mDepth]switchPort + } + infos := make(map[[mDepth]switchPort]nodeInfo) + // First fill the tree with all known nodes, no parents + for k, n := range m { + infos[k] = nodeInfo{ + name: n, + key: k, + } + } + // Now go through and create placeholders for any missing nodes + for _, info := range infos { + for idx, port := range info.key { + if port == 0 { + break } - if len(m[mask]) == 0 { - m[mask] = fmt.Sprintf("%+v (missing)", mask) + var key [mDepth]switchPort + copy(key[:idx], info.key[:]) + newInfo, isIn := infos[key] + if isIn { + continue } - if len(m[mask]) > 0 && m[mask] != m[k] { - conn.Write([]byte(fmt.Sprintf(" \"%+v\" -- \"%+v\";\n", m[k], m[mask]))) + newInfo.name = "missing" + newInfo.key = key + infos[key] = newInfo + } + } + // Now go through and attach parents + for _, info := range infos { + info.parent = info.key + for idx := len(info.parent) - 1; idx >= 0; idx-- { + if info.parent[idx] != 0 { + info.parent[idx] = 0 break } } + infos[info.key] = info + } + // Now print it all out + conn.Write([]byte(fmt.Sprintf("digraph {\n"))) + // First set the labels + for _, info := range infos { + conn.Write([]byte(fmt.Sprintf("\"%v\" [ label = \"%v\" ];\n", info.key, info.name))) + } + // Then print the tree structure + for _, info := range infos { + if info.key == info.parent { + continue + } // happens for the root, skip it + conn.Write([]byte(fmt.Sprintf(" \"%+v\" -> \"%+v\";\n", info.key, info.parent))) } conn.Write([]byte(fmt.Sprintf("}\n"))) break