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"`
|
Buffers uint32 `json:"buffers"`
|
||||||
Free uint32 `json:"free"`
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes.Update(nodeId, res)
|
node := nodes.Update(nodeId, res)
|
||||||
|
|
||||||
if val := res.Statistics; val != nil && statsDb != nil {
|
if statsDb != nil && node.Statistics != nil {
|
||||||
statsDb.Add(val, res.NodeInfo)
|
statsDb.Add(nodeId, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func NewNodes(config *Config) *Nodes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update a Node
|
// 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()
|
now := jsontime.Now()
|
||||||
|
|
||||||
nodes.Lock()
|
nodes.Lock()
|
||||||
@ -86,8 +86,16 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) {
|
|||||||
|
|
||||||
// Update statistics
|
// Update statistics
|
||||||
if val := res.Statistics; val != nil {
|
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
|
node.Statistics = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNodesMini get meshviewer valide JSON
|
// GetNodesMini get meshviewer valide JSON
|
||||||
|
42
stats_db.go
42
stats_db.go
@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/FreifunkBremen/respond-collector/data"
|
"github.com/FreifunkBremen/respond-collector/data"
|
||||||
|
"github.com/FreifunkBremen/respond-collector/models"
|
||||||
"github.com/influxdata/influxdb/client/v2"
|
"github.com/influxdata/influxdb/client/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,14 +45,19 @@ func NewStatsDb() *StatsDb {
|
|||||||
return db
|
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{
|
tags := map[string]string{
|
||||||
"nodeid": stats.NodeId,
|
"nodeid": nodeId,
|
||||||
}
|
}
|
||||||
// Maybe a If
|
|
||||||
if owner := node.Owner; owner != nil {
|
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
||||||
tags["owner"] = owner.Contact
|
if owner := nodeinfo.Owner; owner != nil {
|
||||||
|
tags["owner"] = owner.Contact
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := map[string]interface{}{
|
fields := map[string]interface{}{
|
||||||
"load": stats.LoadAverage,
|
"load": stats.LoadAverage,
|
||||||
"idletime": int64(stats.Idletime),
|
"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
|
fields["traffic.mgmt_tx.packets"] = t.Packets
|
||||||
}
|
}
|
||||||
if w := stats.Wireless; w != nil {
|
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 {
|
if time := w.Airtime24; time != nil {
|
||||||
fields["airtime24.active"] = time.Active
|
addAirtime("24", w.Airtime24)
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
if time := w.Airtime5; time != nil {
|
if time := w.Airtime5; time != nil {
|
||||||
fields["airtime5.active"] = time.Active
|
addAirtime("5", w.Airtime5)
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user