2018-12-03 04:39:13 +08:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Copyright (C) Microsoft. All rights reserved.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
// See LICENSE.txt file in the project root for full license information.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sort"
|
|
|
|
"time"
|
|
|
|
|
2019-07-23 11:08:04 +08:00
|
|
|
"github.com/pkg/errors"
|
2018-12-03 04:39:13 +08:00
|
|
|
|
2019-07-23 11:08:04 +08:00
|
|
|
"github.com/microsoft/ethr/internal/stats"
|
|
|
|
)
|
2018-12-03 04:39:13 +08:00
|
|
|
|
2019-07-23 11:08:04 +08:00
|
|
|
func getNetworkStats() (stats.EthrNetStats, error) {
|
|
|
|
osStats := stats.GetOSStats()
|
|
|
|
devStats, err := osStats.GetNetDevStats()
|
|
|
|
if err != nil {
|
|
|
|
return stats.EthrNetStats{}, errors.Wrap(err, "getNetworkStats: could not get net device stats")
|
|
|
|
}
|
|
|
|
sort.SliceStable(devStats, func(i, j int) bool {
|
|
|
|
return devStats[i].InterfaceName < devStats[j].InterfaceName
|
2018-12-03 04:39:13 +08:00
|
|
|
})
|
|
|
|
|
2019-07-23 11:08:04 +08:00
|
|
|
tcpStats, err := osStats.GetTCPStats()
|
|
|
|
if err != nil {
|
|
|
|
return stats.EthrNetStats{}, errors.Wrap(err, "getNetworkStats: could not get net TCP stats")
|
|
|
|
}
|
|
|
|
|
|
|
|
return stats.EthrNetStats{NetDevStats: devStats, TCPStats: tcpStats}, nil
|
2018-12-03 04:39:13 +08:00
|
|
|
}
|
|
|
|
|
2019-07-23 11:08:04 +08:00
|
|
|
func getNetDevStatDiff(curStats stats.EthrNetDevStat, prevNetStats stats.EthrNetStats, seconds uint64) stats.EthrNetDevStat {
|
|
|
|
for _, prevStats := range prevNetStats.NetDevStats {
|
|
|
|
if prevStats.InterfaceName != curStats.InterfaceName {
|
2018-12-03 04:39:13 +08:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2019-07-23 11:08:04 +08:00
|
|
|
if curStats.RxBytes >= prevStats.RxBytes {
|
|
|
|
curStats.RxBytes -= prevStats.RxBytes
|
2018-12-03 04:39:13 +08:00
|
|
|
} else {
|
2019-07-23 11:08:04 +08:00
|
|
|
curStats.RxBytes += (^uint64(0) - prevStats.RxBytes)
|
2018-12-03 04:39:13 +08:00
|
|
|
}
|
|
|
|
|
2019-07-23 11:08:04 +08:00
|
|
|
if curStats.TxBytes >= prevStats.TxBytes {
|
|
|
|
curStats.TxBytes -= prevStats.TxBytes
|
2018-12-03 04:39:13 +08:00
|
|
|
} else {
|
2019-07-23 11:08:04 +08:00
|
|
|
curStats.TxBytes += (^uint64(0) - prevStats.TxBytes)
|
2018-12-03 04:39:13 +08:00
|
|
|
}
|
|
|
|
|
2019-07-23 11:08:04 +08:00
|
|
|
if curStats.RxPkts >= prevStats.RxPkts {
|
|
|
|
curStats.RxPkts -= prevStats.RxPkts
|
2018-12-03 04:39:13 +08:00
|
|
|
} else {
|
2019-07-23 11:08:04 +08:00
|
|
|
curStats.RxPkts += (^uint64(0) - prevStats.RxPkts)
|
2018-12-03 04:39:13 +08:00
|
|
|
}
|
|
|
|
|
2019-07-23 11:08:04 +08:00
|
|
|
if curStats.TxPkts >= prevStats.TxPkts {
|
|
|
|
curStats.TxPkts -= prevStats.TxPkts
|
2018-12-03 04:39:13 +08:00
|
|
|
} else {
|
2019-07-23 11:08:04 +08:00
|
|
|
curStats.TxPkts += (^uint64(0) - prevStats.TxPkts)
|
2018-12-03 04:39:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
break
|
|
|
|
}
|
2019-07-23 11:08:04 +08:00
|
|
|
curStats.RxBytes /= seconds
|
|
|
|
curStats.TxBytes /= seconds
|
|
|
|
curStats.RxPkts /= seconds
|
|
|
|
curStats.TxPkts /= seconds
|
2018-12-03 04:39:13 +08:00
|
|
|
return curStats
|
|
|
|
}
|
|
|
|
|
|
|
|
var statsEnabled bool
|
|
|
|
|
|
|
|
func startStatsTimer() {
|
|
|
|
if statsEnabled {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
ticker := time.NewTicker(time.Second)
|
|
|
|
statsEnabled = true
|
|
|
|
go func() {
|
|
|
|
for statsEnabled {
|
|
|
|
select {
|
|
|
|
case <-ticker.C:
|
|
|
|
emitStats()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ticker.Stop()
|
|
|
|
return
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
|
|
|
func stopStatsTimer() {
|
|
|
|
statsEnabled = false
|
|
|
|
}
|
|
|
|
|
2019-01-21 01:13:47 +08:00
|
|
|
var lastStatsTime time.Time = time.Now()
|
|
|
|
|
|
|
|
func timeToNextTick() time.Duration {
|
|
|
|
nextTick := lastStatsTime.Add(time.Second)
|
|
|
|
return time.Until(nextTick)
|
|
|
|
}
|
|
|
|
|
2018-12-03 04:39:13 +08:00
|
|
|
func emitStats() {
|
2019-01-21 01:13:47 +08:00
|
|
|
d := time.Since(lastStatsTime)
|
|
|
|
lastStatsTime = time.Now()
|
|
|
|
seconds := int64(d.Seconds())
|
|
|
|
if seconds < 1 {
|
|
|
|
seconds = 1
|
|
|
|
}
|
2018-12-03 04:39:13 +08:00
|
|
|
ui.emitTestResultBegin()
|
2019-01-21 01:13:47 +08:00
|
|
|
emitTestResults(uint64(seconds))
|
2018-12-03 04:39:13 +08:00
|
|
|
ui.emitTestResultEnd()
|
2019-07-23 11:08:04 +08:00
|
|
|
stats, err := getNetworkStats()
|
|
|
|
if err != nil {
|
2019-09-30 20:43:51 +08:00
|
|
|
ui.printErr("emitStats: could not get network stats: %v", err)
|
2019-07-23 11:08:04 +08:00
|
|
|
}
|
|
|
|
ui.emitStats(stats)
|
2019-01-21 01:13:47 +08:00
|
|
|
ui.paint(uint64(seconds))
|
2018-12-03 04:39:13 +08:00
|
|
|
}
|
|
|
|
|
2019-01-21 01:13:47 +08:00
|
|
|
func emitTestResults(s uint64) {
|
2018-12-03 04:39:13 +08:00
|
|
|
gSessionLock.RLock()
|
|
|
|
defer gSessionLock.RUnlock()
|
|
|
|
for _, k := range gSessionKeys {
|
|
|
|
v := gSessions[k]
|
2019-01-21 01:13:47 +08:00
|
|
|
ui.emitTestResult(v, TCP, s)
|
|
|
|
ui.emitTestResult(v, UDP, s)
|
|
|
|
ui.emitTestResult(v, HTTP, s)
|
|
|
|
ui.emitTestResult(v, HTTPS, s)
|
|
|
|
ui.emitTestResult(v, ICMP, s)
|
2018-12-03 04:39:13 +08:00
|
|
|
}
|
|
|
|
}
|