package main import ( "os" "strconv" "strings" ) // Everything the driver counts against a frame the link failed to carry, split // by direction of travel so each counter belongs to exactly one direction: the // transmitting interface owns the tx fields and the receiving interface the rx // ones. Reading both sets off both interfaces would report every drop twice. var ( nicTxFields = []string{ "tx_errors", "tx_dropped", "tx_fifo_errors", "tx_carrier_errors", "tx_aborted_errors", "tx_window_errors", "collisions", } nicRxFields = []string{ "rx_errors", "rx_dropped", "rx_crc_errors", "rx_missed_errors", "rx_length_errors", "rx_over_errors", "rx_frame_errors", "rx_fifo_errors", } ) type nicCounters struct { tx uint64 rx uint64 carrierDown uint64 } func readUint(path string) (uint64, bool) { b, err := os.ReadFile(path) if err != nil { return 0, false } v, err := strconv.ParseUint(strings.TrimSpace(string(b)), 10, 64) if err != nil { return 0, false } return v, true } func sumFields(base string, fields []string) uint64 { var total uint64 for _, f := range fields { if v, ok := readUint(base + "/statistics/" + f); ok { total += v } } return total } func readNIC(ifname string) nicCounters { base := "/sys/class/net/" + ifname c := nicCounters{ tx: sumFields(base, nicTxFields), rx: sumFields(base, nicRxFields), } c.carrierDown, _ = readUint(base + "/carrier_down_count") return c }