From 11765f0af634c281d48a7f49e3078e9b2818fcda Mon Sep 17 00:00:00 2001 From: Patrick Fairbank Date: Tue, 11 Jun 2024 20:04:30 -0700 Subject: [PATCH] Add parsing of Rx/Tx bytes from ifconfig. --- README.md | 4 ++++ radio/radio_ap.go | 10 ++++++++++ radio/radio_ap_test.go | 13 ++++++++++++- radio/station_status.go | 23 ++++++++++++++++++++++- radio/station_status_test.go | 17 +++++++++++++++++ 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e9083be..85ee798 100644 --- a/README.md +++ b/README.md @@ -66,8 +66,10 @@ $ curl http://10.0.100.2:8081/status "signalNoiseRatio": 0, "rxRateMbps": 0, "rxPackets": 0, + "rxBytes": 0, "txRateMbps": 0, "txPackets": 0, + "txBytes": 0, "bandwidthUsedMbps": 0 }, "blue3": null, @@ -82,8 +84,10 @@ $ curl http://10.0.100.2:8081/status "signalNoiseRatio": 40, "rxRateMbps": 860.3, "rxPackets": 4095, + "rxBytes": 5177, "txRateMbps": 6, "txPackets": 5246, + "txBytes": 11830, "bandwidthUsedMbps": 4.102 }, "red2": null, diff --git a/radio/radio_ap.go b/radio/radio_ap.go index fe61e10..20267fb 100644 --- a/radio/radio_ap.go +++ b/radio/radio_ap.go @@ -272,5 +272,15 @@ func (radio *Radio) updateMonitoring() { } else { stationStatus.parseAssocList(output) } + + // Update the number of bytes received and transmitted. + output, err = shell.runCommand("ifconfig", stationInterface) + if err != nil { + log.Printf("Error running 'ifconfig %s': %v", stationInterface, err) + stationStatus.RxBytes = monitoringErrorCode + stationStatus.TxBytes = monitoringErrorCode + } else { + stationStatus.parseIfconfig(output) + } } } diff --git a/radio/radio_ap_test.go b/radio/radio_ap_test.go index 7dcb50b..b588ac8 100644 --- a/radio/radio_ap_test.go +++ b/radio/radio_ap_test.go @@ -379,6 +379,8 @@ func TestRadio_updateStationMonitoring(t *testing.T) { "\tRX: 550.6 MBit/s 4095 Pkts.\n" + "\tTX: 254.0 MBit/s 0 Pkts.\n" + "\texpected throughput: unknown" + fakeShell.commandOutput["ifconfig wlan0"] = "wlan0\tLink encap:Ethernet HWaddr 00:00:00:00:00:00\n" + + "\tRX bytes:12345 (12.3 KiB) TX bytes:98765 (98.7 KiB)" fakeShell.commandOutput["luci-bwc -i wlan0-2"] = "[ 1687496917, 26097, 177, 70454, 846 ],\n" + "[ 1687496919, 26097, 177, 70454, 846 ],\n" + "[ 1687496920, 26097, 177, 70518, 847 ],\n" + @@ -387,12 +389,16 @@ func TestRadio_updateStationMonitoring(t *testing.T) { "[ 1687496922, 26097, 177, 70582, 848 ],\n" + "[ 1687496923, 2609700, 177, 7064600, 849 ]" fakeShell.commandOutput["iwinfo wlan0-2 assoclist"] = "" + fakeShell.commandOutput["ifconfig wlan0-2"] = "" fakeShell.commandOutput["luci-bwc -i wlan0-4"] = "" fakeShell.commandErrors["iwinfo wlan0-4 assoclist"] = errors.New("oops") + fakeShell.commandErrors["ifconfig wlan0-4"] = errors.New("oops") radio.updateMonitoring() assert.True(t, radio.StationStatuses["red1"].IsRobotRadioLinked) assert.Equal(t, 550.6, radio.StationStatuses["red1"].RxRateMbps) assert.Equal(t, -999.0, radio.StationStatuses["red1"].BandwidthUsedMbps) + assert.Equal(t, 12345, radio.StationStatuses["red1"].RxBytes) + assert.Equal(t, 98765, radio.StationStatuses["red1"].TxBytes) assert.Equal( t, StationStatus{ @@ -405,17 +411,22 @@ func TestRadio_updateStationMonitoring(t *testing.T) { StationStatus{ IsRobotRadioLinked: false, RxRateMbps: -999, + RxBytes: -999, TxRateMbps: -999, + TxBytes: -999, SignalNoiseRatio: -999, BandwidthUsedMbps: 0, }, *radio.StationStatuses["blue2"], ) - assert.Equal(t, 6, len(fakeShell.commandsRun)) + assert.Equal(t, 9, len(fakeShell.commandsRun)) assert.Contains(t, fakeShell.commandsRun, "luci-bwc -i wlan0") assert.Contains(t, fakeShell.commandsRun, "iwinfo wlan0 assoclist") + assert.Contains(t, fakeShell.commandsRun, "ifconfig wlan0") assert.Contains(t, fakeShell.commandsRun, "luci-bwc -i wlan0-2") assert.Contains(t, fakeShell.commandsRun, "iwinfo wlan0-2 assoclist") + assert.Contains(t, fakeShell.commandsRun, "ifconfig wlan0-2") assert.Contains(t, fakeShell.commandsRun, "luci-bwc -i wlan0-4") assert.Contains(t, fakeShell.commandsRun, "iwinfo wlan0-4 assoclist") + assert.Contains(t, fakeShell.commandsRun, "ifconfig wlan0-4") } diff --git a/radio/station_status.go b/radio/station_status.go index 65aec58..4447084 100644 --- a/radio/station_status.go +++ b/radio/station_status.go @@ -44,12 +44,18 @@ type StationStatus struct { // Number of packets received from the robot radio. RxPackets int `json:"rxPackets"` + // Number of bytes received from the robot radio. + RxBytes int `json:"rxBytes"` + // Upper-bound link transmit rate (from the access point to the robot radio) in megabits per second. TxRateMbps float64 `json:"txRateMbps"` // Number of packets transmitted to the robot radio. TxPackets int `json:"txPackets"` + // Number of bytes transmitted to the robot radio. + TxBytes int `json:"txBytes"` + // Current five-second average total (rx + tx) bandwidth in megabits per second. BandwidthUsedMbps float64 `json:"bandwidthUsedMbps"` } @@ -71,7 +77,8 @@ func (status *StationStatus) parseBandwidthUsed(response string) { } } -// Parses the given data from the access point's association list and updates the status structure with the result. +// parseAssocList parses the given data from the access point's association list and updates the status structure with +// the result. func (status *StationStatus) parseAssocList(response string) { line1Re := regexp.MustCompile( "((?:[0-9A-F]{2}:){5}(?:[0-9A-F]{2}))\\s+(-\\d+) dBm / (-\\d+) dBm \\(SNR (\\d+)\\)\\s+(\\d+) ms ago", @@ -111,3 +118,17 @@ func (status *StationStatus) parseAssocList(response string) { } } } + +// parseIfconfig parses the given output from the access point's ifconfig command and updates the status structure with +// the result. +func (status *StationStatus) parseIfconfig(response string) { + bytesRe := regexp.MustCompile("RX bytes:(\\d+) .* TX bytes:(\\d+) ") + + status.RxBytes = 0 + status.TxBytes = 0 + bytesMatch := bytesRe.FindStringSubmatch(response) + if len(bytesMatch) > 0 { + status.RxBytes, _ = strconv.Atoi(bytesMatch[1]) + status.TxBytes, _ = strconv.Atoi(bytesMatch[2]) + } +} diff --git a/radio/station_status_test.go b/radio/station_status_test.go index 01cd83e..de0b82c 100644 --- a/radio/station_status_test.go +++ b/radio/station_status_test.go @@ -99,3 +99,20 @@ func TestStationStatus_ParseAssocList(t *testing.T) { status.parseAssocList(response) assert.Equal(t, StationStatus{}, status) } + +func TestStationStatus_ParseIfconfig(t *testing.T) { + var status StationStatus + + status.parseIfconfig("") + assert.Equal(t, StationStatus{}, status) + + response := "ath15\tLink encap:Ethernet HWaddr 4A:DA:35:B0:00:2C\n" + + "\tinet6 addr: fe80::48da:35ff:feb0:2c/64 Scope:Link\n" + + "\tUP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1\n" + + "\tRX packets:690 errors:0 dropped:0 overruns:0 frame:0\n" + + "\tTX packets:727 errors:0 dropped:0 overruns:0 carrier:0\n " + + "\tcollisions:0 txqueuelen:0\n" + + "\tRX bytes:45311 (44.2 KiB) TX bytes:48699 (47.5 KiB)\n" + status.parseIfconfig(response) + assert.Equal(t, StationStatus{RxBytes: 45311, TxBytes: 48699}, status) +}