diff --git a/cmd/yanic-query/main.go b/cmd/yanic-query/main.go index f981c25..69cc74e 100644 --- a/cmd/yanic-query/main.go +++ b/cmd/yanic-query/main.go @@ -19,8 +19,11 @@ func main() { nodes := runtime.NewNodes(&runtime.Config{}) - collector := respond.NewCollector(nil, nodes, iface, 0) - collector.SendPacket(net.ParseIP(dstAddress)) + collector := respond.NewCollector(nil, nodes, iface, iface, iface, 0) + collector.SendPacket(net.UDPAddr{ + IP: net.ParseIP(dstAddress), + Zone: iface, + }) time.Sleep(time.Second) diff --git a/cmd/yanic/main.go b/cmd/yanic/main.go index 1d27404..5f1339a 100644 --- a/cmd/yanic/main.go +++ b/cmd/yanic/main.go @@ -43,6 +43,12 @@ func main() { if err != nil { panic(err) } + if config.Respondd.InterfaceSendUnicast == "" { + config.Respondd.InterfaceSendUnicast = config.Respondd.InterfaceListen + } + if config.Respondd.InterfaceSendMulticast == "" { + config.Respondd.InterfaceSendMulticast = config.Respondd.InterfaceListen + } connections, err = allDB.Connect(config.Database.Connection) if err != nil { @@ -82,7 +88,7 @@ func main() { time.Sleep(delay) } - collector = respond.NewCollector(connections, nodes, config.Respondd.Interface, config.Respondd.Port) + collector = respond.NewCollector(connections, nodes, config.Respondd.InterfaceListen, config.Respondd.InterfaceSendMulticast, config.Respondd.InterfaceSendUnicast, config.Respondd.Port) collector.Start(config.Respondd.CollectInterval.Duration) defer collector.Close() } diff --git a/config_example.toml b/config_example.toml index c5dd8ae..9e67378 100644 --- a/config_example.toml +++ b/config_example.toml @@ -5,8 +5,13 @@ enable = true synchronize = "1m" # how oftern request per multicast collect_interval = "1m" -# on which interface +# on which interface to listen interface = "eth0" +# send unicast request (default: see interface) +## interface_send_unicast = "eth0" +# send multicast request (default: see interface) +# interface_send_multicast = "eth1" + # define a port to listen # (no or 0 would choose at port at his own) #port = 10001 diff --git a/data/neighbours.go b/data/neighbours.go index 08fd0d2..24d7f18 100644 --- a/data/neighbours.go +++ b/data/neighbours.go @@ -2,10 +2,11 @@ package data // Neighbours struct type Neighbours struct { - Batadv map[string]BatadvNeighbours `json:"batadv"` - LLDP map[string]LLDPNeighbours `json:"lldp"` - //WifiNeighbours map[string]WifiNeighbours `json:"wifi"` - NodeID string `json:"node_id"` + Batadv map[string]BatadvNeighbours `json:"batadv"` + LLDP map[string]LLDPNeighbours `json:"lldp"` + Babel map[string]BabelNeighbours `json:"babel"` + WifiNeighbours map[string]WifiNeighbours `json:"wifi"` + NodeID string `json:"node_id"` } // WifiLink struct @@ -21,6 +22,11 @@ type BatmanLink struct { Tq int `json:"tq"` } +// BabelLink struct +type BabelLink struct { + Address string `json:"address"` +} + // LLDPLink struct type LLDPLink struct { Name string `json:"name"` @@ -32,6 +38,9 @@ type BatadvNeighbours struct { Neighbours map[string]BatmanLink `json:"neighbours"` } +// BabelNeighbours struct +type BabelNeighbours []BabelLink + // WifiNeighbours struct type WifiNeighbours struct { Neighbours map[string]WifiLink `json:"neighbours"` diff --git a/database/graphite/node.go b/database/graphite/node.go index 2b04e9a..1ca52a8 100644 --- a/database/graphite/node.go +++ b/database/graphite/node.go @@ -50,6 +50,13 @@ func (c *Connection) InsertNode(node *runtime.Node) { } addField("neighbours.batadv", batadv) + // protocol: Babel + babel := 0 + for _, babelNeighbours := range neighbours.Babel { + babel += len(babelNeighbours) + } + addField("neighbours.babel", babel) + // protocol: LLDP lldp := 0 for _, lldpNeighbours := range neighbours.LLDP { diff --git a/database/influxdb/node.go b/database/influxdb/node.go index 5f23368..21a23e4 100644 --- a/database/influxdb/node.go +++ b/database/influxdb/node.go @@ -80,6 +80,13 @@ func buildNodeStats(node *runtime.Node) (tags models.Tags, fields models.Fields) } fields["neighbours.batadv"] = batadv + // protocol: Babel + babel := 0 + for _, babelNeighbours := range neighbours.Babel { + babel += len(babelNeighbours) + } + fields["neighbours.babel"] = babel + // protocol: LLDP lldp := 0 for _, lldpNeighbours := range neighbours.LLDP { diff --git a/output/meshviewer/graph.go b/output/meshviewer/graph.go index dda0d3a..3386cd3 100644 --- a/output/meshviewer/graph.go +++ b/output/meshviewer/graph.go @@ -80,6 +80,7 @@ func (builder *graphBuilder) readNodes(nodes map[string]*runtime.Node) { builder.macToID[sourceAddress] = sourceID } } + } // Iterate over local MAC addresses from LLDP @@ -102,6 +103,22 @@ func (builder *graphBuilder) readNodes(nodes map[string]*runtime.Node) { } } } + // Wifi neighbours + for _, wifiNeighbours := range neighbours.WifiNeighbours { + for targetAddress, link := range wifiNeighbours.Neighbours { + if targetID, found := builder.macToID[targetAddress]; found { + builder.addLink(targetID, sourceID, link.Noise/link.Signal) + } + } + } + // Babel neighbours + for _, babelNeighbours := range neighbours.Babel { + for _, link := range babelNeighbours { + if targetID, found := builder.macToID[link.Address]; found { + builder.addLink(targetID, sourceID, 1) + } + } + } // LLDP for _, neighbours := range neighbours.LLDP { for targetAddress := range neighbours { diff --git a/respond/collector.go b/respond/collector.go index b5406c1..46c807e 100644 --- a/respond/collector.go +++ b/respond/collector.go @@ -17,18 +17,19 @@ import ( // Collector for a specificle respond messages type Collector struct { - connection *net.UDPConn // UDP socket - queue chan *Response // received responses - iface string - db database.Connection - nodes *runtime.Nodes - interval time.Duration // Interval for multicast packets - stop chan interface{} + connection *net.UDPConn // UDP socket + queue chan *Response // received responses + ifaceSendUnicast string + ifaceSendMulticast string + db database.Connection + nodes *runtime.Nodes + interval time.Duration // Interval for multicast packets + stop chan interface{} } // NewCollector creates a Collector struct -func NewCollector(db database.Connection, nodes *runtime.Nodes, iface string, port int) *Collector { - linkLocalAddr, err := getLinkLocalAddr(iface) +func NewCollector(db database.Connection, nodes *runtime.Nodes, ifaceListen string, ifaceSendUnicast string, ifaceSendMulticast string, port int) *Collector { + linkLocalAddr, err := getLinkLocalAddr(ifaceListen) if err != nil { log.Panic(err) } @@ -37,7 +38,7 @@ func NewCollector(db database.Connection, nodes *runtime.Nodes, iface string, po conn, err := net.ListenUDP("udp", &net.UDPAddr{ IP: linkLocalAddr, Port: port, - Zone: iface, + Zone: ifaceListen, }) if err != nil { log.Panic(err) @@ -45,12 +46,13 @@ func NewCollector(db database.Connection, nodes *runtime.Nodes, iface string, po conn.SetReadBuffer(maxDataGramSize) collector := &Collector{ - connection: conn, - db: db, - nodes: nodes, - iface: iface, - queue: make(chan *Response, 400), - stop: make(chan interface{}), + connection: conn, + db: db, + nodes: nodes, + ifaceSendUnicast: ifaceSendUnicast, + ifaceSendMulticast: ifaceSendMulticast, + queue: make(chan *Response, 400), + stop: make(chan interface{}), } go collector.receiver() @@ -117,7 +119,10 @@ func (coll *Collector) sendOnce() { func (coll *Collector) sendMulticast() { log.Println("sending multicast") - coll.SendPacket(net.ParseIP(multiCastGroup)) + coll.SendPacket(net.UDPAddr{ + IP: net.ParseIP(multiCastGroup), + Zone: coll.ifaceSendMulticast, + }) } // Send unicast packets to nodes that did not answer the multicast @@ -132,19 +137,17 @@ func (coll *Collector) sendUnicasts(seenBefore jsontime.Time) { // Send unicast packets log.Printf("sending unicast to %d nodes", len(nodes)) for _, node := range nodes { - coll.SendPacket(node.Address) + coll.SendPacket(net.UDPAddr{ + IP: node.Address, + Zone: coll.ifaceSendUnicast, + }) time.Sleep(10 * time.Millisecond) } } // SendPacket sends a UDP request to the given unicast or multicast address -func (coll *Collector) SendPacket(address net.IP) { - addr := net.UDPAddr{ - IP: address, - Port: port, - Zone: coll.iface, - } - +func (coll *Collector) SendPacket(addr net.UDPAddr) { + addr.Port = port if _, err := coll.connection.WriteToUDP([]byte("GET nodeinfo statistics neighbours"), &addr); err != nil { log.Println("WriteToUDP failed:", err) } diff --git a/runtime/config.go b/runtime/config.go index a14933f..66382a4 100644 --- a/runtime/config.go +++ b/runtime/config.go @@ -9,11 +9,13 @@ import ( //Config the config File of this daemon type Config struct { Respondd struct { - Enable bool `toml:"enable"` - Synchronize Duration `toml:"synchronize"` - Interface string `toml:"interface"` - Port int `toml:"port"` - CollectInterval Duration `toml:"collect_interval"` + Enable bool `toml:"enable"` + Synchronize Duration `toml:"synchronize"` + InterfaceListen string `toml:"interface"` + InterfaceSendMulticast string `toml:"interface_send_multicast"` + InterfaceSendUnicast string `toml:"interface_send_unicast"` + Port int `toml:"port"` + CollectInterval Duration `toml:"collect_interval"` } Webserver struct { Enable bool `toml:"enable"` diff --git a/runtime/config_test.go b/runtime/config_test.go index 0b248fb..a23999d 100644 --- a/runtime/config_test.go +++ b/runtime/config_test.go @@ -15,7 +15,7 @@ func TestReadConfig(t *testing.T) { assert.NotNil(config) assert.True(config.Respondd.Enable) - assert.Equal("eth0", config.Respondd.Interface) + assert.Equal("eth0", config.Respondd.InterfaceListen) assert.Equal(time.Minute, config.Respondd.CollectInterval.Duration) assert.Equal(time.Hour*24*7, config.Nodes.PruneAfter.Duration)