diff --git a/info/machine.go b/info/machine.go index 998340c0..5591f3d2 100644 --- a/info/machine.go +++ b/info/machine.go @@ -95,6 +95,20 @@ type DiskInfo struct { Size uint64 `json:"size"` } +type NetInfo struct { + // Device name + Name string `json:"name"` + + // Mac Address + MacAddress string `json:"mac_address"` + + // Speed in MBits/s + Speed uint64 `json:"speed"` + + // Maximum Transmission Unit + Mtu uint64 `json:"mtu"` +} + type MachineInfo struct { // The number of cores in this machine. NumCores int `json:"num_cores"` @@ -111,6 +125,9 @@ type MachineInfo struct { // Disk map DiskMap map[string]DiskInfo `json:"disk_map"` + // Network devices + NetworkDevices []NetInfo `json:"network_devices"` + // Machine Topology // Describes cpu layout and hierarchy. TODO(rjnagal): Add Memory hierarchy. Topology []Node `json:"topology"` diff --git a/manager/machine.go b/manager/machine.go index baeda0b1..906311a3 100644 --- a/manager/machine.go +++ b/manager/machine.go @@ -235,6 +235,11 @@ func getMachineInfo(sysFs sysfs.SysFs) (*info.MachineInfo, error) { return nil, err } + netDevices, err := sysfs.GetNetworkDevices(sysFs) + if err != nil { + return nil, err + } + topology, numCores, err := getTopology(sysFs, string(cpuinfo)) if err != nil { return nil, err @@ -245,6 +250,7 @@ func getMachineInfo(sysFs sysfs.SysFs) (*info.MachineInfo, error) { CpuFrequency: clockSpeed, MemoryCapacity: memoryCapacity, DiskMap: diskMap, + NetworkDevices: netDevices, Topology: topology, } diff --git a/utils/sysfs/fakesysfs/fake.go b/utils/sysfs/fakesysfs/fake.go index 55ab4a19..e6e530d8 100644 --- a/utils/sysfs/fakesysfs/fake.go +++ b/utils/sysfs/fakesysfs/fake.go @@ -68,6 +68,23 @@ func (self *FakeSysFs) GetBlockDeviceNumbers(name string) (string, error) { return "8:0\n", nil } +func (self *FakeSysFs) GetNetworkDevices() ([]os.FileInfo, error) { + self.info.EntryName = "eth0" + return []os.FileInfo{&self.info}, nil +} + +func (self *FakeSysFs) GetNetworkAddress(name string) (string, error) { + return "42:01:02:03:04:f4\n", nil +} + +func (self *FakeSysFs) GetNetworkMtu(name string) (string, error) { + return "1024\n", nil +} + +func (self *FakeSysFs) GetNetworkSpeed(name string) (string, error) { + return "1000\n", nil +} + func (self *FakeSysFs) GetCaches(id int) ([]os.FileInfo, error) { self.info.EntryName = "index0" return []os.FileInfo{&self.info}, nil diff --git a/utils/sysfs/sysfs.go b/utils/sysfs/sysfs.go index d5043ab0..a56e97bc 100644 --- a/utils/sysfs/sysfs.go +++ b/utils/sysfs/sysfs.go @@ -28,6 +28,7 @@ import ( const ( blockDir = "/sys/block" cacheDir = "/sys/devices/system/cpu/cpu" + netDir = "/sys/class/net" ) // Abstracts the lowest level calls to sysfs. @@ -39,6 +40,11 @@ type SysFs interface { // Get device major:minor number string. GetBlockDeviceNumbers(string) (string, error) + GetNetworkDevices() ([]os.FileInfo, error) + GetNetworkAddress(string) (string, error) + GetNetworkMtu(string) (string, error) + GetNetworkSpeed(string) (string, error) + // Get directory information for available caches accessible to given cpu. GetCaches(id int) ([]os.FileInfo, error) // Get information for a cache accessible from the given cpu. @@ -71,6 +77,34 @@ func (self *realSysFs) GetBlockDeviceSize(name string) (string, error) { return string(size), nil } +func (self *realSysFs) GetNetworkDevices() ([]os.FileInfo, error) { + return ioutil.ReadDir(netDir) +} + +func (self *realSysFs) GetNetworkAddress(name string) (string, error) { + address, err := ioutil.ReadFile(path.Join(netDir, name, "/address")) + if err != nil { + return "", err + } + return string(address), nil +} + +func (self *realSysFs) GetNetworkMtu(name string) (string, error) { + mtu, err := ioutil.ReadFile(path.Join(netDir, name, "/mtu")) + if err != nil { + return "", err + } + return string(mtu), nil +} + +func (self *realSysFs) GetNetworkSpeed(name string) (string, error) { + speed, err := ioutil.ReadFile(path.Join(netDir, name, "/speed")) + if err != nil { + return "", err + } + return string(speed), nil +} + func (self *realSysFs) GetCaches(id int) ([]os.FileInfo, error) { cpuPath := fmt.Sprintf("%s%d/cache", cacheDir, id) return ioutil.ReadDir(cpuPath) @@ -161,6 +195,52 @@ func GetBlockDeviceInfo(sysfs SysFs) (map[string]info.DiskInfo, error) { return diskMap, nil } +// Get information about network devices present on the system. +func GetNetworkDevices(sysfs SysFs) ([]info.NetInfo, error) { + devs, err := sysfs.GetNetworkDevices() + if err != nil { + return nil, err + } + netDevices := []info.NetInfo{} + for _, dev := range devs { + name := dev.Name() + // Only consider ethernet devices for now. + if !strings.HasPrefix(name, "eth") { + continue + } + address, err := sysfs.GetNetworkAddress(name) + if err != nil { + return nil, err + } + mtuStr, err := sysfs.GetNetworkMtu(name) + if err != nil { + return nil, err + } + var mtu uint64 + n, err := fmt.Sscanf(mtuStr, "%d", &mtu) + if err != nil || n != 1 { + return nil, fmt.Errorf("could not parse mtu from %s for device %s", mtuStr, name) + } + netInfo := info.NetInfo{ + Name: name, + MacAddress: strings.TrimSpace(address), + Mtu: mtu, + } + speed, err := sysfs.GetNetworkSpeed(name) + // Some devices don't set speed. + if err == nil { + var s uint64 + n, err := fmt.Sscanf(speed, "%d", &s) + if err != nil || n != 1 { + return nil, fmt.Errorf("could not parse speed from %s for device %s", speed, name) + } + netInfo.Speed = s + } + netDevices = append(netDevices, netInfo) + } + return netDevices, nil +} + type CacheInfo struct { // size in bytes Size uint64