diff --git a/INSTALL.md b/INSTALL.md index 8d890e1..d52e741 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -25,6 +25,12 @@ As root: go get -v -u github.com/FreifunkBremen/yanic ``` +### allow to ping +only needed if config has `nodes.ping_count` > 0 +```sh +sudo setcap cap_net_raw=+ep /opt/go/bin/yanic +``` + #### Work with other databases If you like to use another database solution than influxdb, Pull Requests are welcome. Just fork this project and create another subpackage within the folder diff --git a/docs/docs_install.md b/docs/docs_install.md index 388eade..54a9b56 100644 --- a/docs/docs_install.md +++ b/docs/docs_install.md @@ -26,6 +26,12 @@ As root: go get -v -u github.com/FreifunkBremen/yanic ``` +### allow to ping +only needed if config has `nodes.ping_count` > 0 +```sh +sudo setcap cap_net_raw=+ep /opt/go/bin/yanic +``` + ### Install ```sh diff --git a/runtime/node.go b/runtime/node.go index cff23e3..c689fa9 100644 --- a/runtime/node.go +++ b/runtime/node.go @@ -13,7 +13,7 @@ type Node struct { Firstseen jsontime.Time `json:"firstseen"` Lastseen jsontime.Time `json:"lastseen"` Online bool `json:"online"` - NoRespondd bool `json:"-"` + NoRespondd bool `json:"no_respondd"` Statistics *data.Statistics `json:"statistics"` Nodeinfo *data.Nodeinfo `json:"nodeinfo"` Neighbours *data.Neighbours `json:"-"` diff --git a/runtime/nodes.go b/runtime/nodes.go index 8e19d2a..7e25eb5 100644 --- a/runtime/nodes.go +++ b/runtime/nodes.go @@ -80,9 +80,10 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) *Node { // Update fields node.Lastseen = now node.Online = true - node.Neighbours = res.Neighbours node.Nodeinfo = res.Nodeinfo node.Statistics = res.Statistics + node.Neighbours = res.Neighbours + node.NoRespondd = res.Statistics == nil && res.Neighbours == nil return node } @@ -170,24 +171,32 @@ func (nodes *Nodes) expire() { nodes.Lock() defer nodes.Unlock() + wg := sync.WaitGroup{} + for id, node := range nodes.List { if node.Lastseen.Before(pruneAfter) { // expire delete(nodes.List, id) } else if node.Lastseen.Before(offlineAfter) { // set to offline - if nodes.config.PingCount > 0 && nodes.ping(node) { - node.Online = true - node.NoRespondd = true + wg.Add(1) + go func(node *Node) { + defer wg.Done() + if nodes.config.PingCount > 0 && nodes.ping(node) { + node.Online = true + node.NoRespondd = true - node.Statistics = nil - node.Neighbours = nil - } else { - node.Online = false - node.NoRespondd = false - } + node.Statistics = nil + node.Neighbours = nil + } else { + node.Online = false + node.NoRespondd = false + } + }(node) } } + wg.Wait() + log.WithField("nodes", "expire").Debug("end") } // adds the nodes interface addresses to the internal map @@ -249,6 +258,7 @@ func (nodes *Nodes) save() { // serialize nodes SaveJSON(nodes, nodes.config.StatePath) + log.WithField("nodes", "save").Debug("end") } // SaveJSON to path diff --git a/runtime/nodes_ping.go b/runtime/nodes_ping.go index d5f7e53..9198178 100644 --- a/runtime/nodes_ping.go +++ b/runtime/nodes_ping.go @@ -10,13 +10,21 @@ func (nodes *Nodes) ping(node *Node) bool { if node.Nodeinfo != nil { logNode = logNode.WithField("node_id", node.Nodeinfo.NodeID) } - if node.Address == nil { + var addr string + if node.Address != nil { + addr = node.Address.IP.String() + if node.Address.IP.IsLinkLocalUnicast() { + addr += "%" + node.Address.Zone + } + } else { logNode.Debug("error no address found") - return false - } - addr := node.Address.IP.String() - if node.Address.IP.IsLinkLocalUnicast() { - addr += "%" + node.Address.Zone + if node.Nodeinfo != nil { + for _, addrMaybe := range node.Nodeinfo.Network.Addresses { + if len(addrMaybe) >= 5 && addrMaybe[:5] != "fe80:" { + addr = addrMaybe + } + } + } } logAddr := logNode.WithField("addr", addr) @@ -26,9 +34,10 @@ func (nodes *Nodes) ping(node *Node) bool { logAddr.Debugf("error during ping: %s", err) return false } - //pinger.SetPrivileged(true) + pinger.SetPrivileged(true) pinger.Count = nodes.config.PingCount pinger.Timeout = nodes.config.PingTimeout.Duration + pinger.Interval = pinger.Timeout / pinger.Count pinger.Run() // blocks until finished stats := pinger.Statistics() logAddr.WithFields(map[string]interface{}{ diff --git a/runtime/nodes_ping_test.go b/runtime/nodes_ping_test.go index 170f4d1..23f43a2 100644 --- a/runtime/nodes_ping_test.go +++ b/runtime/nodes_ping_test.go @@ -27,7 +27,13 @@ func TestPing(t *testing.T) { ifaceToNodeID: make(map[string]string), } - node := nodes.Update("expire", &data.ResponseData{NodeInfo: &data.NodeInfo{NodeID: "nodeID-Lola"}}) + node := nodes.Update("expire", &data.ResponseData{NodeInfo: &data.NodeInfo{ + NodeID: "nodeID-Lola", + Network: data.Network{Addresses: []string{"fe80::1", "fd2f::1"}}, + }}) + // get fallback + assert.False(nodes.ping(node)) + node.Address = &net.UDPAddr{Zone: "bat0"} // error during ping assert.False(nodes.ping(node))