2014-06-14 09:31:12 +08:00
|
|
|
package network
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type NetworkStats struct {
|
2014-07-24 05:31:37 +08:00
|
|
|
RxBytes uint64 `json:"rx_bytes"`
|
|
|
|
RxPackets uint64 `json:"rx_packets"`
|
|
|
|
RxErrors uint64 `json:"rx_errors"`
|
|
|
|
RxDropped uint64 `json:"rx_dropped"`
|
|
|
|
TxBytes uint64 `json:"tx_bytes"`
|
|
|
|
TxPackets uint64 `json:"tx_packets"`
|
|
|
|
TxErrors uint64 `json:"tx_errors"`
|
|
|
|
TxDropped uint64 `json:"tx_dropped"`
|
2014-06-14 09:31:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo.
|
2014-07-24 05:18:58 +08:00
|
|
|
func GetStats(networkState *NetworkState) (*NetworkStats, error) {
|
2014-06-14 09:31:12 +08:00
|
|
|
// This can happen if the network runtime information is missing - possible if the container was created by an old version of libcontainer.
|
2014-06-25 07:43:00 +08:00
|
|
|
if networkState.VethHost == "" {
|
2014-07-24 05:31:37 +08:00
|
|
|
return &NetworkStats{}, nil
|
2014-06-14 09:31:12 +08:00
|
|
|
}
|
2014-06-25 07:43:00 +08:00
|
|
|
data, err := readSysfsNetworkStats(networkState.VethHost)
|
2014-06-14 09:31:12 +08:00
|
|
|
if err != nil {
|
2014-07-24 05:18:58 +08:00
|
|
|
return nil, err
|
2014-06-14 09:31:12 +08:00
|
|
|
}
|
|
|
|
|
2014-07-24 08:26:13 +08:00
|
|
|
// Ingress for host veth is from the container. Hence tx_bytes stat on the host veth is actually number of bytes received by the container.
|
2014-07-24 05:18:58 +08:00
|
|
|
return &NetworkStats{
|
2014-07-24 08:26:13 +08:00
|
|
|
RxBytes: data["tx_bytes"],
|
|
|
|
RxPackets: data["tx_packets"],
|
|
|
|
RxErrors: data["tx_errors"],
|
|
|
|
RxDropped: data["tx_dropped"],
|
|
|
|
TxBytes: data["rx_bytes"],
|
|
|
|
TxPackets: data["rx_packets"],
|
|
|
|
TxErrors: data["rx_errors"],
|
|
|
|
TxDropped: data["rx_dropped"],
|
2014-06-27 04:49:02 +08:00
|
|
|
}, nil
|
2014-06-14 09:31:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reads all the statistics available under /sys/class/net/<EthInterface>/statistics as a map with file name as key and data as integers.
|
|
|
|
func readSysfsNetworkStats(ethInterface string) (map[string]uint64, error) {
|
|
|
|
out := make(map[string]uint64)
|
|
|
|
|
2014-06-26 13:40:58 +08:00
|
|
|
fullPath := filepath.Join("/sys/class/net", ethInterface, "statistics/")
|
|
|
|
err := filepath.Walk(fullPath, func(path string, _ os.FileInfo, _ error) error {
|
2014-06-14 09:31:12 +08:00
|
|
|
// skip fullPath.
|
|
|
|
if path == fullPath {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
base := filepath.Base(path)
|
|
|
|
data, err := ioutil.ReadFile(path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
value, err := strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
out[base] = value
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return out, err
|
|
|
|
}
|