diff --git a/runtime/nodes.go b/runtime/nodes.go index 7e25eb5..448c372 100644 --- a/runtime/nodes.go +++ b/runtime/nodes.go @@ -7,6 +7,7 @@ import ( "time" "github.com/bdlm/log" + ping "github.com/digineo/go-ping" "github.com/FreifunkBremen/yanic/data" "github.com/FreifunkBremen/yanic/lib/jsontime" @@ -17,6 +18,7 @@ type Nodes struct { List map[string]*Node `json:"nodes"` // the current nodemap, indexed by node ID ifaceToNodeID map[string]string // mapping from MAC address to NodeID config *NodesConfig + pinger *ping.Pinger sync.RWMutex } @@ -27,6 +29,11 @@ func NewNodes(config *NodesConfig) *Nodes { ifaceToNodeID: make(map[string]string), config: config, } + p, err := ping.New("", "::") + if err != nil { + log.Warnf("ping bind failed: %s", err) + } + nodes.pinger = p if config.StatePath != "" { nodes.load() @@ -83,7 +90,7 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) *Node { node.Nodeinfo = res.Nodeinfo node.Statistics = res.Statistics node.Neighbours = res.Neighbours - node.NoRespondd = res.Statistics == nil && res.Neighbours == nil + node.NoRespondd = false return node } @@ -185,9 +192,6 @@ func (nodes *Nodes) expire() { 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 @@ -196,7 +200,7 @@ func (nodes *Nodes) expire() { } } wg.Wait() - log.WithField("nodes", "expire").Debug("end") + log.WithField("nodes", "expire").Info("end") } // adds the nodes interface addresses to the internal map @@ -258,7 +262,7 @@ func (nodes *Nodes) save() { // serialize nodes SaveJSON(nodes, nodes.config.StatePath) - log.WithField("nodes", "save").Debug("end") + log.WithField("nodes", "save").Info("end") } // SaveJSON to path diff --git a/runtime/nodes_ping.go b/runtime/nodes_ping.go index 9198178..e76aa58 100644 --- a/runtime/nodes_ping.go +++ b/runtime/nodes_ping.go @@ -1,8 +1,9 @@ package runtime import ( + "net" + "github.com/bdlm/log" - "github.com/sparrc/go-ping" ) func (nodes *Nodes) ping(node *Node) bool { @@ -10,38 +11,29 @@ func (nodes *Nodes) ping(node *Node) bool { if node.Nodeinfo != nil { logNode = logNode.WithField("node_id", node.Nodeinfo.NodeID) } - var addr string + var addr *net.IPAddr if node.Address != nil { - addr = node.Address.IP.String() - if node.Address.IP.IsLinkLocalUnicast() { - addr += "%" + node.Address.Zone - } + addr = &net.IPAddr{IP:node.Address.IP, Zone: node.Address.Zone} } else { logNode.Debug("error no address found") if node.Nodeinfo != nil { - for _, addrMaybe := range node.Nodeinfo.Network.Addresses { - if len(addrMaybe) >= 5 && addrMaybe[:5] != "fe80:" { - addr = addrMaybe + for _, addrMaybeString := range node.Nodeinfo.Network.Addresses { + if len(addrMaybeString) >= 5 && addrMaybeString[:5] != "fe80:" { + addrMaybe, err := net.ResolveIPAddr("ip6", addrMaybeString) + if err == nil { + addr = addrMaybe + } } } } } - logAddr := logNode.WithField("addr", addr) + logAddr := logNode.WithField("addr", addr.String()) + + _, err := nodes.pinger.PingAttempts(addr, nodes.config.PingTimeout.Duration, nodes.config.PingCount) - pinger, err := ping.NewPinger(addr) - if err != nil { - logAddr.Debugf("error during ping: %s", err) - return false - } - 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{}{ - "pkg_lost": stats.PacketLoss, + "success": err == nil, }).Debug("pong") - return stats.PacketLoss < 100 + return err == nil } diff --git a/runtime/nodes_ping_test.go b/runtime/nodes_ping_test.go index 23f43a2..ba212f7 100644 --- a/runtime/nodes_ping_test.go +++ b/runtime/nodes_ping_test.go @@ -27,7 +27,7 @@ func TestPing(t *testing.T) { ifaceToNodeID: make(map[string]string), } - node := nodes.Update("expire", &data.ResponseData{NodeInfo: &data.NodeInfo{ + node := nodes.Update("expire", &data.ResponseData{Nodeinfo: &data.Nodeinfo{ NodeID: "nodeID-Lola", Network: data.Network{Addresses: []string{"fe80::1", "fd2f::1"}}, }})