github.com/bigcommerce/nomad@v0.9.3-bc/client/fingerprint/network_linux.go (about) 1 package fingerprint 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os/exec" 7 "regexp" 8 "strconv" 9 "strings" 10 ) 11 12 // linkSpeedSys parses link speed in Mb/s from /sys. 13 func (f *NetworkFingerprint) linkSpeedSys(device string) int { 14 path := fmt.Sprintf("/sys/class/net/%s/speed", device) 15 16 // Read contents of the device/speed file 17 content, err := ioutil.ReadFile(path) 18 if err != nil { 19 f.logger.Debug("unable to read link speed", "path", path) 20 return 0 21 } 22 23 lines := strings.Split(string(content), "\n") 24 mbs, err := strconv.Atoi(lines[0]) 25 if err != nil || mbs <= 0 { 26 f.logger.Debug("unable to parse link speed", "path", path) 27 return 0 28 } 29 30 return mbs 31 } 32 33 // linkSpeed returns link speed in Mb/s, or 0 when unable to determine it. 34 func (f *NetworkFingerprint) linkSpeed(device string) int { 35 // Use LookPath to find the ethtool in the systems $PATH 36 // If it's not found or otherwise errors, LookPath returns and empty string 37 // and an error we can ignore for our purposes 38 ethtoolPath, _ := exec.LookPath("ethtool") 39 if ethtoolPath != "" { 40 if speed := f.linkSpeedEthtool(ethtoolPath, device); speed > 0 { 41 return speed 42 } 43 } 44 45 // Fall back on checking a system file for link speed. 46 return f.linkSpeedSys(device) 47 } 48 49 // linkSpeedEthtool determines link speed in Mb/s with 'ethtool'. 50 func (f *NetworkFingerprint) linkSpeedEthtool(path, device string) int { 51 outBytes, err := exec.Command(path, device).Output() 52 if err != nil { 53 f.logger.Warn("error calling ethtool", "error", err, "path", path, "device", device) 54 return 0 55 } 56 57 output := strings.TrimSpace(string(outBytes)) 58 re := regexp.MustCompile("Speed: [0-9]+[a-zA-Z]+/s") 59 m := re.FindString(output) 60 if m == "" { 61 // no matches found, output may be in a different format 62 f.logger.Warn("unable to parse speed", "path", path, "device", device) 63 return 0 64 } 65 66 // Split and trim the Mb/s unit from the string output 67 args := strings.Split(m, ": ") 68 raw := strings.TrimSuffix(args[1], "Mb/s") 69 70 // convert to Mb/s 71 mbs, err := strconv.Atoi(raw) 72 if err != nil || mbs <= 0 { 73 f.logger.Warn("unable to parse Mb/s", "path", path, "device", device) 74 return 0 75 } 76 77 return mbs 78 }