package netflow
import (
"fmt"
"log"
"node/global"
"os"
"regexp"
"strconv"
"strings"
"time"
)
var gVar *global.Global
func Start(g *global.Global) {
gVar = g
log.Println("netflow start")
gVar.Lock.RLock()
ifname := gVar.Str["ifname"]
gVar.Lock.RUnlock()
for {
var interval int64 = 5
go secondNetFlow(ifname, interval)
time.Sleep(time.Duration(interval) * time.Second)
}
}
// 每秒流量, 统计完成后完成后发送到接口
func secondNetFlow(ifname string, sleep int64) {
sleep1 := time.Now().Unix()
tx1, rx1 := netflowTxRx(ifname)
time.Sleep(time.Duration(sleep) * time.Second)
tx2, rx2 := netflowTxRx(ifname)
sleep2 := time.Now().Unix() - sleep1
// tx3 := (tx2 - tx1) / sleep2 * 8
// rx3 := (rx2 - rx1) / sleep2 * 8
tx3 := (tx2 - tx1) / sleep2 * 8 / 1000000 //mbps
rx3 := (rx2 - rx1) / sleep2 * 8 / 1000000
// log.Printf("tx=%v rx=%v", tx3, rx3)
gVar.Lock.Lock()
gVar.NetLineInfo.TxRealtime = tx3
if gVar.NetLineInfo.TxLastMax < tx3 {
gVar.NetLineInfo.TxLastMax = tx3
}
gVar.NetLineInfo.RxRealtime = rx3
if gVar.NetLineInfo.RxLastMax < rx3 {
gVar.NetLineInfo.RxLastMax = rx3
}
gVar.Lock.Unlock()
}
// 取得某个接口在 /proc/net/dev 中的数据
func getInterfaceNetFlow(ifName, procNetDev string) (tx, rx int64) {
regexpStr := fmt.Sprintf(`[\s^]%s:.*`, ifName) // 拼接正则表达式
match1 := regexp.MustCompile(regexpStr).FindString(procNetDev) // 匹配所在行
match2 := regexp.MustCompile(`\S+?(:|\b)`).FindAllString(strings.TrimSpace(match1), 11) // 正则匹配为数组
// 如果匹配成功, 那么数组 len 肯定是 11, 则赋值返回
if len(match2) == 11 {
tx, _ = strconv.ParseInt(match2[9], 10, 64)
rx, _ = strconv.ParseInt(match2[1], 10, 64)
}
return
}
// 取得指定接口流量
func netflowTxRx(ifname string) (tx, rx int64) {
// 取得流量文件数据
vNetDev, err := os.ReadFile("/proc/net/dev")
if err != nil {
return
}
tx, rx = getInterfaceNetFlow(ifname, string(vNetDev))
return
}
type LineInfo struct {
Code int64 `doc:"1表示数据正常"`
TxLastMax int64 `doc:"线路拨号以来的最大值"`
TxConfMax int64 `doc:"运营商标识的线路最大值"`
TxRealtime int64 `doc:"实时速度"`
RxLastMax int64 `doc:"线路拨号以来的最大值"`
RxConfMax int64 `doc:"运营商标识的线路最大值"`
RxRealtime int64 `doc:"实时速度"`
Mac string
}
func NewLineInfo() (obj *LineInfo) {
obj = &LineInfo{}
obj.Code = 1
v1, err1 := strconv.ParseInt(os.Getenv("MAX_TX"), 10, 64)
if err1 == nil {
obj.TxConfMax = v1
obj.TxLastMax = v1
}
v2, err2 := strconv.ParseInt(os.Getenv("MAX_RX"), 10, 64)
if err2 == nil {
obj.RxConfMax = v2
obj.RxLastMax = v2
}
obj.Mac = os.Getenv("MAC")
return
}