Calculate channel utilization
This commit is contained in:
parent
8a99cb2bd7
commit
92aac7b7ca
51
data/airtime.go
Normal file
51
data/airtime.go
Normal file
@ -0,0 +1,51 @@
|
||||
package data
|
||||
|
||||
type Wireless struct {
|
||||
TxPower24 uint32 `json:"txpower24,omitempty"`
|
||||
Channel24 uint32 `json:"channel24,omitempty"`
|
||||
TxPower5 uint32 `json:"txpower5,omitempty"`
|
||||
Channel5 uint32 `json:"channel5,omitempty"`
|
||||
}
|
||||
|
||||
type WirelessStatistics struct {
|
||||
Airtime24 *WirelessAirtime `json:"airtime24,omitempty"`
|
||||
Airtime5 *WirelessAirtime `json:"airtime5,omitempty"`
|
||||
}
|
||||
|
||||
type WirelessAirtime struct {
|
||||
ChanUtil float32 // Channel utilization
|
||||
RxUtil float32 // Receive utilization
|
||||
TxUtil float32 // Transmit utilization
|
||||
|
||||
Active_time uint64 `json:"active"`
|
||||
Busy_time uint64 `json:"busy"`
|
||||
Rx_time uint64 `json:"rx"`
|
||||
Tx_time uint64 `json:"tx"`
|
||||
Noise uint32 `json:"noise"`
|
||||
Frequency uint32 `json:"frequency"`
|
||||
}
|
||||
|
||||
// Calculates the utilization values in regard to the previous values
|
||||
func (cur *WirelessStatistics) SetUtilization(prev *WirelessStatistics) {
|
||||
cur.Airtime24.SetUtilization(prev.Airtime24)
|
||||
cur.Airtime5.SetUtilization(prev.Airtime5)
|
||||
}
|
||||
|
||||
// Calculates the utilization values in regard to the previous values
|
||||
func (cur *WirelessAirtime) SetUtilization(prev *WirelessAirtime) {
|
||||
if prev == nil || cur.Active_time <= prev.Active_time {
|
||||
return
|
||||
}
|
||||
|
||||
active := float32(cur.Active_time) - float32(prev.Active_time)
|
||||
busy := float32(cur.Busy_time) - float32(prev.Busy_time)
|
||||
rx := float32(cur.Tx_time) - float32(prev.Tx_time)
|
||||
tx := float32(cur.Rx_time) - float32(prev.Rx_time)
|
||||
|
||||
// Calculate utilizations
|
||||
if active > 0 {
|
||||
cur.ChanUtil = (busy + rx + tx) / active
|
||||
cur.RxUtil = rx / active
|
||||
cur.TxUtil = tx / active
|
||||
}
|
||||
}
|
46
data/airtime_test.go
Normal file
46
data/airtime_test.go
Normal file
@ -0,0 +1,46 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUtilization(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
t1 := &WirelessAirtime{
|
||||
Active_time: 20,
|
||||
Busy_time: 0,
|
||||
Tx_time: 5,
|
||||
Rx_time: 0,
|
||||
}
|
||||
t2 := &WirelessAirtime{
|
||||
Active_time: 120,
|
||||
Busy_time: 10,
|
||||
Tx_time: 25,
|
||||
Rx_time: 15,
|
||||
}
|
||||
t3 := &WirelessAirtime{
|
||||
Active_time: 200,
|
||||
Busy_time: 40,
|
||||
Tx_time: 35,
|
||||
Rx_time: 15,
|
||||
}
|
||||
|
||||
t1.SetUtilization(t2)
|
||||
assert.Zero(t1.ChanUtil)
|
||||
assert.Zero(t1.TxUtil)
|
||||
assert.Zero(t1.RxUtil)
|
||||
|
||||
t2.SetUtilization(t1)
|
||||
assert.NotZero(t2.ChanUtil)
|
||||
assert.EqualValues(0.45, t2.ChanUtil)
|
||||
assert.EqualValues(0.2, t2.RxUtil)
|
||||
assert.EqualValues(0.15, t2.TxUtil)
|
||||
|
||||
t3.SetUtilization(t2)
|
||||
assert.EqualValues(0.5, t3.ChanUtil)
|
||||
assert.EqualValues(0.125, t3.RxUtil)
|
||||
assert.EqualValues(0, t3.TxUtil)
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package data
|
||||
|
||||
type Wireless struct {
|
||||
TxPower24 uint32 `json:"txpower24,omitempty"`
|
||||
Channel24 uint32 `json:"channel24,omitempty"`
|
||||
TxPower5 uint32 `json:"txpower5,omitempty"`
|
||||
Channel5 uint32 `json:"channel5,omitempty"`
|
||||
}
|
||||
type SwitchPort struct {
|
||||
Speed uint32 `json:"speed"`
|
||||
}
|
||||
|
||||
type WirelessStatistics struct {
|
||||
Airtime24 *WirelessAirtime `json:"airtime24,omitempty"`
|
||||
Airtime5 *WirelessAirtime `json:"airtime5,omitempty"`
|
||||
}
|
||||
|
||||
type WirelessAirtime struct {
|
||||
Active uint64 `json:"active"`
|
||||
Busy uint64 `json:"busy"`
|
||||
Rx uint64 `json:"rx"`
|
||||
Tx uint64 `json:"tx"`
|
||||
Noise uint32 `json:"noise"`
|
||||
Frequency uint32 `json:"frequency"`
|
||||
}
|
@ -62,3 +62,7 @@ type Memory struct {
|
||||
Buffers uint32 `json:"buffers"`
|
||||
Free uint32 `json:"free"`
|
||||
}
|
||||
|
||||
type SwitchPort struct {
|
||||
Speed uint32 `json:"speed"`
|
||||
}
|
||||
|
6
main.go
6
main.go
@ -94,9 +94,9 @@ func onReceive(addr net.UDPAddr, res *data.ResponseData) {
|
||||
return
|
||||
}
|
||||
|
||||
nodes.Update(nodeId, res)
|
||||
node := nodes.Update(nodeId, res)
|
||||
|
||||
if val := res.Statistics; val != nil && statsDb != nil {
|
||||
statsDb.Add(val, res.NodeInfo)
|
||||
if statsDb != nil && node.Statistics != nil {
|
||||
statsDb.Add(nodeId, node)
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func NewNodes(config *Config) *Nodes {
|
||||
}
|
||||
|
||||
// Update a Node
|
||||
func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) {
|
||||
func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) *Node {
|
||||
now := jsontime.Now()
|
||||
|
||||
nodes.Lock()
|
||||
@ -86,8 +86,16 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) {
|
||||
|
||||
// Update statistics
|
||||
if val := res.Statistics; val != nil {
|
||||
|
||||
// Update channel utilization if previous statistics are present
|
||||
if node.Statistics != nil && node.Statistics.Wireless != nil && val.Wireless != nil {
|
||||
val.Wireless.SetUtilization(node.Statistics.Wireless)
|
||||
}
|
||||
|
||||
node.Statistics = val
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
// GetNodesMini get meshviewer valide JSON
|
||||
|
42
stats_db.go
42
stats_db.go
@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/FreifunkBremen/respond-collector/data"
|
||||
"github.com/FreifunkBremen/respond-collector/models"
|
||||
"github.com/influxdata/influxdb/client/v2"
|
||||
)
|
||||
|
||||
@ -44,14 +45,19 @@ func NewStatsDb() *StatsDb {
|
||||
return db
|
||||
}
|
||||
|
||||
func (c *StatsDb) Add(stats *data.Statistics, node *data.NodeInfo) {
|
||||
func (c *StatsDb) Add(nodeId string, node *models.Node) {
|
||||
stats := node.Statistics
|
||||
|
||||
tags := map[string]string{
|
||||
"nodeid": stats.NodeId,
|
||||
"nodeid": nodeId,
|
||||
}
|
||||
// Maybe a If
|
||||
if owner := node.Owner; owner != nil {
|
||||
tags["owner"] = owner.Contact
|
||||
|
||||
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
||||
if owner := nodeinfo.Owner; owner != nil {
|
||||
tags["owner"] = owner.Contact
|
||||
}
|
||||
}
|
||||
|
||||
fields := map[string]interface{}{
|
||||
"load": stats.LoadAverage,
|
||||
"idletime": int64(stats.Idletime),
|
||||
@ -89,23 +95,21 @@ func (c *StatsDb) Add(stats *data.Statistics, node *data.NodeInfo) {
|
||||
fields["traffic.mgmt_tx.packets"] = t.Packets
|
||||
}
|
||||
if w := stats.Wireless; w != nil {
|
||||
addAirtime := func(suffix string, time *data.WirelessAirtime) {
|
||||
fields["airtime"+suffix+".chan_util"] = time.ChanUtil
|
||||
fields["airtime"+suffix+".rx_util"] = time.RxUtil
|
||||
fields["airtime"+suffix+".tx_util"] = time.TxUtil
|
||||
fields["airtime"+suffix+".noise"] = time.Noise
|
||||
fields["airtime"+suffix+".frequency"] = time.Frequency
|
||||
tags["frequency"+suffix+""] = strconv.Itoa(int(time.Frequency))
|
||||
}
|
||||
|
||||
if time := w.Airtime24; time != nil {
|
||||
fields["airtime24.active"] = time.Active
|
||||
fields["airtime24.busy"] = time.Busy
|
||||
fields["airtime24.tx"] = time.Tx
|
||||
fields["airtime24.rx"] = time.Rx
|
||||
fields["airtime24.noise"] = time.Noise
|
||||
fields["airtime24.frequency"] = time.Frequency
|
||||
tags["frequency24"] = strconv.Itoa(int(time.Frequency))
|
||||
addAirtime("24", w.Airtime24)
|
||||
|
||||
}
|
||||
if time := w.Airtime5; time != nil {
|
||||
fields["airtime5.active"] = time.Active
|
||||
fields["airtime5.busy"] = time.Busy
|
||||
fields["airtime5.tx"] = time.Tx
|
||||
fields["airtime5.rx"] = time.Rx
|
||||
fields["airtime5.noise"] = time.Noise
|
||||
fields["airtime5.frequency"] = time.Frequency
|
||||
tags["frequency5"] = strconv.Itoa(int(time.Frequency))
|
||||
addAirtime("5", w.Airtime5)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user