You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

net_wireless.go 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // Copyright 2023 The Prometheus Authors
  2. // Licensed under the Apache License, Version 2.0 (the "License");
  3. // you may not use this file except in compliance with the License.
  4. // You may obtain a copy of the License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package procfs
  14. import (
  15. "bufio"
  16. "bytes"
  17. "fmt"
  18. "io"
  19. "strconv"
  20. "strings"
  21. "github.com/prometheus/procfs/internal/util"
  22. )
  23. // Wireless models the content of /proc/net/wireless.
  24. type Wireless struct {
  25. Name string
  26. // Status is the current 4-digit hex value status of the interface.
  27. Status uint64
  28. // QualityLink is the link quality.
  29. QualityLink int
  30. // QualityLevel is the signal gain (dBm).
  31. QualityLevel int
  32. // QualityNoise is the signal noise baseline (dBm).
  33. QualityNoise int
  34. // DiscardedNwid is the number of discarded packets with wrong nwid/essid.
  35. DiscardedNwid int
  36. // DiscardedCrypt is the number of discarded packets with wrong code/decode (WEP).
  37. DiscardedCrypt int
  38. // DiscardedFrag is the number of discarded packets that can't perform MAC reassembly.
  39. DiscardedFrag int
  40. // DiscardedRetry is the number of discarded packets that reached max MAC retries.
  41. DiscardedRetry int
  42. // DiscardedMisc is the number of discarded packets for other reasons.
  43. DiscardedMisc int
  44. // MissedBeacon is the number of missed beacons/superframe.
  45. MissedBeacon int
  46. }
  47. // Wireless returns kernel wireless statistics.
  48. func (fs FS) Wireless() ([]*Wireless, error) {
  49. b, err := util.ReadFileNoStat(fs.proc.Path("net/wireless"))
  50. if err != nil {
  51. return nil, err
  52. }
  53. m, err := parseWireless(bytes.NewReader(b))
  54. if err != nil {
  55. return nil, fmt.Errorf("%s: wireless: %w", ErrFileParse, err)
  56. }
  57. return m, nil
  58. }
  59. // parseWireless parses the contents of /proc/net/wireless.
  60. /*
  61. Inter-| sta-| Quality | Discarded packets | Missed | WE
  62. face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
  63. eth1: 0000 5. -256. -10. 0 1 0 3 0 0
  64. eth2: 0000 5. -256. -20. 0 2 0 4 0 0
  65. */
  66. func parseWireless(r io.Reader) ([]*Wireless, error) {
  67. var (
  68. interfaces []*Wireless
  69. scanner = bufio.NewScanner(r)
  70. )
  71. for n := 0; scanner.Scan(); n++ {
  72. // Skip the 2 header lines.
  73. if n < 2 {
  74. continue
  75. }
  76. line := scanner.Text()
  77. parts := strings.Split(line, ":")
  78. if len(parts) != 2 {
  79. return nil, fmt.Errorf("%w: expected 2 parts after splitting line by ':', got %d for line %q", ErrFileParse, len(parts), line)
  80. }
  81. name := strings.TrimSpace(parts[0])
  82. stats := strings.Fields(parts[1])
  83. if len(stats) < 10 {
  84. return nil, fmt.Errorf("%w: invalid number of fields in line %d, expected 10+, got %d: %q", ErrFileParse, n, len(stats), line)
  85. }
  86. status, err := strconv.ParseUint(stats[0], 16, 16)
  87. if err != nil {
  88. return nil, fmt.Errorf("%w: invalid status in line %d: %q", ErrFileParse, n, line)
  89. }
  90. qlink, err := strconv.Atoi(strings.TrimSuffix(stats[1], "."))
  91. if err != nil {
  92. return nil, fmt.Errorf("%s: parse Quality:link as integer %q: %w", ErrFileParse, qlink, err)
  93. }
  94. qlevel, err := strconv.Atoi(strings.TrimSuffix(stats[2], "."))
  95. if err != nil {
  96. return nil, fmt.Errorf("%s: Quality:level as integer %q: %w", ErrFileParse, qlevel, err)
  97. }
  98. qnoise, err := strconv.Atoi(strings.TrimSuffix(stats[3], "."))
  99. if err != nil {
  100. return nil, fmt.Errorf("%s: Quality:noise as integer %q: %w", ErrFileParse, qnoise, err)
  101. }
  102. dnwid, err := strconv.Atoi(stats[4])
  103. if err != nil {
  104. return nil, fmt.Errorf("%s: Discarded:nwid as integer %q: %w", ErrFileParse, dnwid, err)
  105. }
  106. dcrypt, err := strconv.Atoi(stats[5])
  107. if err != nil {
  108. return nil, fmt.Errorf("%s: Discarded:crypt as integer %q: %w", ErrFileParse, dcrypt, err)
  109. }
  110. dfrag, err := strconv.Atoi(stats[6])
  111. if err != nil {
  112. return nil, fmt.Errorf("%s: Discarded:frag as integer %q: %w", ErrFileParse, dfrag, err)
  113. }
  114. dretry, err := strconv.Atoi(stats[7])
  115. if err != nil {
  116. return nil, fmt.Errorf("%s: Discarded:retry as integer %q: %w", ErrFileParse, dretry, err)
  117. }
  118. dmisc, err := strconv.Atoi(stats[8])
  119. if err != nil {
  120. return nil, fmt.Errorf("%s: Discarded:misc as integer %q: %w", ErrFileParse, dmisc, err)
  121. }
  122. mbeacon, err := strconv.Atoi(stats[9])
  123. if err != nil {
  124. return nil, fmt.Errorf("%s: Missed:beacon as integer %q: %w", ErrFileParse, mbeacon, err)
  125. }
  126. w := &Wireless{
  127. Name: name,
  128. Status: status,
  129. QualityLink: qlink,
  130. QualityLevel: qlevel,
  131. QualityNoise: qnoise,
  132. DiscardedNwid: dnwid,
  133. DiscardedCrypt: dcrypt,
  134. DiscardedFrag: dfrag,
  135. DiscardedRetry: dretry,
  136. DiscardedMisc: dmisc,
  137. MissedBeacon: mbeacon,
  138. }
  139. interfaces = append(interfaces, w)
  140. }
  141. if err := scanner.Err(); err != nil {
  142. return nil, fmt.Errorf("%s: Failed to scan /proc/net/wireless: %w", ErrFileRead, err)
  143. }
  144. return interfaces, nil
  145. }