Skip to content

Commit

Permalink
Merge c660e17 into 092eafb
Browse files Browse the repository at this point in the history
  • Loading branch information
genofire committed Mar 11, 2018
2 parents 092eafb + c660e17 commit 0afd82e
Show file tree
Hide file tree
Showing 40 changed files with 809 additions and 248 deletions.
6 changes: 5 additions & 1 deletion cmd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ func TestReadConfig(t *testing.T) {
assert.NotNil(config)

assert.True(config.Respondd.Enable)
assert.Equal([]string{"br-ffhb"}, config.Respondd.Interfaces)
assert.Equal("br-ffhb", config.Respondd.Interfaces[0].InterfaceName)
assert.Equal(time.Minute, config.Respondd.CollectInterval.Duration)
assert.Equal(time.Hour*24*7, config.Nodes.PruneAfter.Duration)
assert.Equal(time.Hour*24*7, config.Database.DeleteAfter.Duration)

assert.Len(config.Respondd.Sites, 1)
assert.Contains(config.Respondd.Sites, "ffhb")
assert.Contains(config.Respondd.Sites["ffhb"].Domains, "city")

// Test output plugins
assert.Len(config.Nodes.Output, 3)
outputs := config.Nodes.Output["meshviewer"].([]interface{})
Expand Down
8 changes: 5 additions & 3 deletions cmd/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import (

// importCmd represents the import command
var importCmd = &cobra.Command{
Use: "import <file.rrd> <site>",
Use: "import <file.rrd> <site> <domain>",
Short: "Imports global statistics from the given RRD files, requires InfluxDB",
Example: "yanic import --config /etc/yanic.toml olddata.rrd global",
Args: cobra.ExactArgs(2),
Example: "yanic import --config /etc/yanic.toml olddata.rrd global global",
Args: cobra.ExactArgs(3),
Run: func(cmd *cobra.Command, args []string) {
path := args[0]
site := args[1]
domain := args[2]
config := loadConfig()

err := allDatabase.Start(config.Database)
Expand All @@ -36,6 +37,7 @@ var importCmd = &cobra.Command{
},
ds.Time,
site,
domain,
)
}
},
Expand Down
43 changes: 36 additions & 7 deletions cmd/query.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,73 @@
package cmd

import (
"encoding/json"
"log"
"net"
"strings"
"time"

"github.com/FreifunkBremen/yanic/respond"
"github.com/FreifunkBremen/yanic/runtime"
"github.com/spf13/cobra"
)

var wait int
var (
wait int
port int
ipAddress string
)

// queryCmd represents the query command
var queryCmd = &cobra.Command{
Use: "query <interface> <destination>",
Use: "query <interfaces> <destination>",
Short: "Sends a query on the interface to the destination and waits for a response",
Example: `yanic query wlan0 "fe80::eade:27ff:dead:beef"`,
Example: `yanic query "eth0,wlan0" "fe80::eade:27ff:dead:beef"`,
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
iface := args[0]
ifaces := strings.Split(args[0], ",")
dstAddress := net.ParseIP(args[1])

log.Printf("Sending request address=%s iface=%s", dstAddress, iface)
log.Printf("Sending request address=%s ifaces=%s", dstAddress, ifaces)

var ifacesConfigs []respond.InterfaceConfig
for _, iface := range ifaces {
ifaceConfig := respond.InterfaceConfig{
InterfaceName: iface,
Port: port,
IPAddress: ipAddress,
}
ifacesConfigs = append(ifacesConfigs, ifaceConfig)
}

nodes := runtime.NewNodes(&runtime.NodesConfig{})

collector := respond.NewCollector(nil, nodes, []string{}, []string{iface}, 0)
sitesDomains := make(map[string][]string)
collector := respond.NewCollector(nil, nodes, sitesDomains, ifacesConfigs)
defer collector.Close()
collector.SendPacket(dstAddress)

time.Sleep(time.Second * time.Duration(wait))

for id, data := range nodes.List {
log.Printf("%s: %+v", id, data)
jq, err := json.Marshal(data)
if err != nil {
log.Printf("%s: %+v", id, data)
} else {
jqNeighbours, err := json.Marshal(data.Neighbours)
if err != nil {
log.Printf("%s: %s neighbours: %+v", id, string(jq), data.Neighbours)
} else {
log.Printf("%s: %s neighbours: %s", id, string(jq), string(jqNeighbours))
}
}
}
},
}

func init() {
RootCmd.AddCommand(queryCmd)
queryCmd.Flags().IntVar(&wait, "wait", 1, "Seconds to wait for a response")
queryCmd.Flags().IntVar(&port, "port", 0, "define a port to listen (if not set or set to 0 the kernel will use a random free port at its own)")
queryCmd.Flags().StringVar(&ipAddress, "ip", "", "ip address which is used for sending (optional - without definition used the link-local address)")
}
2 changes: 1 addition & 1 deletion cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ var serveCmd = &cobra.Command{
time.Sleep(delay)
}

collector = respond.NewCollector(allDatabase.Conn, nodes, config.Respondd.Sites, config.Respondd.Interfaces, config.Respondd.Port)
collector = respond.NewCollector(allDatabase.Conn, nodes, config.Respondd.SitesDomains(), config.Respondd.Interfaces)
collector.Start(config.Respondd.CollectInterval.Duration)
defer collector.Close()
}
Expand Down
30 changes: 26 additions & 4 deletions config_example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,29 @@ enable = true
synchronize = "1m"
# how often request per multicast
collect_interval = "1m"

# table of a site to save stats for (not exists for global only)
#[respondd.sites.example]
## list of domains on this site to save stats for (empty for global only)
#domains = []
## example
[respondd.sites.ffhb]
domains = ["city"]

# interface that has an IP in your mesh network
interfaces = ["br-ffhb"]
# list of sites to save stats for (empty for global only)
sites = []
[[respondd.interfaces]]
# name of interface on which this collector is running
ifname = "br-ffhb"
# ip address which is used for sending
# (optional - without definition used a address of ifname)
ip_address = "fd2f:5119:f2d::5"
# multicast address to destination of respondd
# (optional - without definition used batman default ff02::2:1001)
multicast_address = "ff05::2:1001"
# define a port to listen
# if not set or set to 0 the kernel will use a random free port at its own
#port = 10001


# A little build-in webserver, which statically serves a directory.
# This is useful for testing purposes or for a little standalone installation.
[webserver]
Expand Down Expand Up @@ -56,6 +70,14 @@ offline_after = "10m"
# List of site_codes of nodes that should be included in the output
#sites = ["ffhb"]
#
# replace the site_code with the domain_code in this output
# e.g. site_code='ffhb',domain_code='city' => site_code='city', domain_code=''
#domain_as_site = true
#
# append on the site_code the domain_code with a '.' in this output
# e.g. site_code='ffhb',domain_code='city' => site_code='ffhb.city', domain_code=''
#domain_append_site = true
#
# set has_location to true if you want to include only nodes that have geo-coordinates set
# (setting this to false has no sensible effect, unless you'd want to hide nodes that have coordinates)
#has_location = true
Expand Down
17 changes: 17 additions & 0 deletions data/neighbours.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package data
// Neighbours struct
type Neighbours struct {
Batadv map[string]BatadvNeighbours `json:"batadv"`
Babel map[string]BabelNeighbours `json:"babel"`
LLDP map[string]LLDPNeighbours `json:"lldp"`
//WifiNeighbours map[string]WifiNeighbours `json:"wifi"`
NodeID string `json:"node_id"`
Expand All @@ -27,11 +28,27 @@ type LLDPLink struct {
Description string `json:"descr"`
}

// BabelLink struct
type BabelLink struct {
// How need this:
RXCost int `json:"rxcost"`
TXCost int `json:"txcost"`
Cost int `json:"cost"`
Reachability int `json:"reachability"`
}

// BatadvNeighbours struct
type BatadvNeighbours struct {
Neighbours map[string]BatmanLink `json:"neighbours"`
}

// BabelNeighbours struct
type BabelNeighbours struct {
Protocol string `json:"protocol"`
LinkLocalAddress string `json:"ll-addr"`
Neighbours map[string]BabelLink `json:"neighbours"`
}

// WifiNeighbours struct
type WifiNeighbours struct {
Neighbours map[string]WifiLink `json:"neighbours"`
Expand Down
21 changes: 13 additions & 8 deletions data/nodeinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ type NodeInfo struct {
Wireless *Wireless `json:"wireless,omitempty"`
}

// BatInterface struct
type BatInterface struct {
// NetworkInterface struct
type NetworkInterface struct {
Interfaces struct {
Wireless []string `json:"wireless,omitempty"`
Other []string `json:"other,omitempty"`
Expand All @@ -24,16 +24,17 @@ type BatInterface struct {
}

// Addresses returns a flat list of all MAC addresses
func (iface *BatInterface) Addresses() []string {
func (iface *NetworkInterface) Addresses() []string {
return append(append(iface.Interfaces.Other, iface.Interfaces.Tunnel...), iface.Interfaces.Wireless...)
}

// Network struct
type Network struct {
Mac string `json:"mac"`
Addresses []string `json:"addresses"`
Mesh map[string]*BatInterface `json:"mesh"`
MeshInterfaces []string `json:"mesh_interfaces"`
Mac string `json:"mac"`
Addresses []string `json:"addresses"`
Mesh map[string]*NetworkInterface `json:"mesh"`
// still used in gluon?
MeshInterfaces []string `json:"mesh_interfaces"`
}

// Owner struct
Expand All @@ -43,7 +44,8 @@ type Owner struct {

// System struct
type System struct {
SiteCode string `json:"site_code,omitempty"`
SiteCode string `json:"site_code,omitempty"`
DomainCode string `json:"domain_code,omitempty"`
}

// Location struct
Expand All @@ -63,6 +65,9 @@ type Software struct {
Version string `json:"version,omitempty"`
Compat int `json:"compat,omitempty"`
} `json:"batman-adv,omitempty"`
Babeld struct {
Version string `json:"version,omitempty"`
} `json:"babeld,omitempty"`
Fastd struct {
Enabled bool `json:"enabled,omitempty"`
Version string `json:"version,omitempty"`
Expand Down
4 changes: 2 additions & 2 deletions data/nodeinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

func TestNodeinfoBatAddresses(t *testing.T) {
assert := assert.New(t)
batIface := &BatInterface{
iface := &NetworkInterface{
Interfaces: struct {
Wireless []string `json:"wireless,omitempty"`
Other []string `json:"other,omitempty"`
Expand All @@ -20,7 +20,7 @@ func TestNodeinfoBatAddresses(t *testing.T) {
},
}

addr := batIface.Addresses()
addr := iface.Addresses()
assert.NotNil(addr)
assert.Equal([]string{"aa:aa:aa:aa:aa", "aa:aa:aa:aa:ab"}, addr)
}
4 changes: 2 additions & 2 deletions database/all/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ func (conn *Connection) InsertLink(link *runtime.Link, time time.Time) {
}
}

func (conn *Connection) InsertGlobals(stats *runtime.GlobalStats, time time.Time, site string) {
func (conn *Connection) InsertGlobals(stats *runtime.GlobalStats, time time.Time, site string, domain string) {
for _, item := range conn.list {
item.InsertGlobals(stats, time, site)
item.InsertGlobals(stats, time, site, domain)
}
}

Expand Down
2 changes: 1 addition & 1 deletion database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Connection interface {
InsertLink(*runtime.Link, time.Time)

// InsertGlobals stores global statistics
InsertGlobals(*runtime.GlobalStats, time.Time, string)
InsertGlobals(*runtime.GlobalStats, time.Time, string, string)

// PruneNodes prunes historical per-node data
PruneNodes(deleteAfter time.Duration)
Expand Down
9 changes: 8 additions & 1 deletion database/graphite/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/fgrosse/graphigo"
)

func (c *Connection) InsertGlobals(stats *runtime.GlobalStats, time time.Time, site string) {
func (c *Connection) InsertGlobals(stats *runtime.GlobalStats, time time.Time, site string, domain string) {
measurementGlobal := MeasurementGlobal
counterMeasurementModel := CounterMeasurementModel
counterMeasurementFirmware := CounterMeasurementFirmware
Expand All @@ -20,6 +20,13 @@ func (c *Connection) InsertGlobals(stats *runtime.GlobalStats, time time.Time, s
counterMeasurementAutoupdater += "_" + site
}

if domain != runtime.GLOBAL_DOMAIN {
measurementGlobal += "_" + domain
counterMeasurementModel += "_" + domain
counterMeasurementFirmware += "_" + domain
counterMeasurementAutoupdater += "_" + domain
}

c.addPoint(GlobalStatsFields(measurementGlobal, stats))
c.addCounterMap(counterMeasurementModel, stats.Models, time)
c.addCounterMap(counterMeasurementFirmware, stats.Firmwares, time)
Expand Down
25 changes: 16 additions & 9 deletions database/influxdb/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,35 @@ import (
)

// InsertGlobals implementation of database
func (conn *Connection) InsertGlobals(stats *runtime.GlobalStats, time time.Time, site string) {
var tags models.Tags
func (conn *Connection) InsertGlobals(stats *runtime.GlobalStats, time time.Time, site string, domain string) {
tags := models.Tags{}

measurementGlobal := MeasurementGlobal
counterMeasurementModel := CounterMeasurementModel
counterMeasurementFirmware := CounterMeasurementFirmware
counterMeasurementAutoupdater := CounterMeasurementAutoupdater

if site != runtime.GLOBAL_SITE {
tags = models.Tags{
models.Tag{Key: []byte("site"), Value: []byte(site)},
}
tags.Set([]byte("site"), []byte(site))

measurementGlobal += "_site"
counterMeasurementModel += "_site"
counterMeasurementFirmware += "_site"
counterMeasurementAutoupdater += "_site"
}
if domain != runtime.GLOBAL_DOMAIN {
tags.Set([]byte("domain"), []byte(domain))

measurementGlobal += "_domain"
counterMeasurementModel += "_domain"
counterMeasurementFirmware += "_domain"
counterMeasurementAutoupdater += "_domain"
}

conn.addPoint(measurementGlobal, tags, GlobalStatsFields(stats), time)
conn.addCounterMap(counterMeasurementModel, stats.Models, time, site)
conn.addCounterMap(counterMeasurementFirmware, stats.Firmwares, time, site)
conn.addCounterMap(counterMeasurementAutoupdater, stats.Autoupdater, time, site)
conn.addCounterMap(counterMeasurementModel, stats.Models, time, site, domain)
conn.addCounterMap(counterMeasurementFirmware, stats.Firmwares, time, site, domain)
conn.addCounterMap(counterMeasurementAutoupdater, stats.Autoupdater, time, site, domain)
}

// GlobalStatsFields returns fields for InfluxDB
Expand All @@ -48,13 +54,14 @@ func GlobalStatsFields(stats *runtime.GlobalStats) map[string]interface{} {
// Saves the values of a CounterMap in the database.
// The key are used as 'value' tag.
// The value is used as 'counter' field.
func (conn *Connection) addCounterMap(name string, m runtime.CounterMap, t time.Time, site string) {
func (conn *Connection) addCounterMap(name string, m runtime.CounterMap, t time.Time, site string, domain string) {
for key, count := range m {
conn.addPoint(
name,
models.Tags{
models.Tag{Key: []byte("value"), Value: []byte(key)},
models.Tag{Key: []byte("site"), Value: []byte(site)},
models.Tag{Key: []byte("domain"), Value: []byte(domain)},
},
models.Fields{"count": count},
t,
Expand Down
Loading

0 comments on commit 0afd82e

Please sign in to comment.