...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package sysfs
18
19 import (
20 "errors"
21 "fmt"
22 "os"
23 "path/filepath"
24
25 "github.com/prometheus/procfs/internal/util"
26 )
27
28 const fibrechannelClassPath = "class/fc_host"
29
30 type FibreChannelCounters struct {
31 DumpedFrames uint64
32 ErrorFrames uint64
33 InvalidCRCCount uint64
34 RXFrames uint64
35 RXWords uint64
36 TXFrames uint64
37 TXWords uint64
38 SecondsSinceLastReset uint64
39 InvalidTXWordCount uint64
40 LinkFailureCount uint64
41 LossOfSyncCount uint64
42 LossOfSignalCount uint64
43 NosCount uint64
44 FCPPacketAborts uint64
45 }
46
47 type FibreChannelHost struct {
48 Name string
49 Speed string
50 PortState string
51 PortType string
52 SymbolicName string
53 NodeName string
54 PortID string
55 PortName string
56 FabricName string
57 DevLossTMO string
58 SupportedClasses string
59 SupportedSpeeds string
60 Counters FibreChannelCounters
61 }
62
63 type FibreChannelClass map[string]FibreChannelHost
64
65
66 func (fs FS) FibreChannelClass() (FibreChannelClass, error) {
67 path := fs.sys.Path(fibrechannelClassPath)
68
69 dirs, err := os.ReadDir(path)
70 if err != nil {
71 return nil, err
72 }
73
74 fcc := make(FibreChannelClass, len(dirs))
75 for _, d := range dirs {
76 host, err := fs.parseFibreChannelHost(d.Name())
77 if err != nil {
78 return nil, err
79 }
80
81 fcc[host.Name] = *host
82 }
83
84 return fcc, nil
85 }
86
87
88 func (fs FS) parseFibreChannelHost(name string) (*FibreChannelHost, error) {
89 path := fs.sys.Path(fibrechannelClassPath, name)
90 host := FibreChannelHost{Name: name}
91
92 for _, f := range [...]string{"speed", "port_state", "port_type", "node_name", "port_id", "port_name", "fabric_name", "dev_loss_tmo", "symbolic_name", "supported_classes", "supported_speeds"} {
93 name := filepath.Join(path, f)
94 value, err := util.SysReadFile(name)
95 if err != nil {
96
97
98 if os.IsNotExist(err) {
99 continue
100 }
101 return nil, fmt.Errorf("failed to read file %q: %w", name, err)
102 }
103
104 switch f {
105 case "speed":
106 host.Speed = value
107 case "port_state":
108 host.PortState = value
109 case "port_type":
110 host.PortType = value
111 case "node_name":
112 if len(value) > 2 {
113 value = value[2:]
114 }
115 host.NodeName = value
116 case "port_id":
117 if len(value) > 2 {
118 value = value[2:]
119 }
120 host.PortID = value
121 case "port_name":
122 if len(value) > 2 {
123 value = value[2:]
124 }
125 host.PortName = value
126 case "fabric_name":
127 if len(value) > 2 {
128 value = value[2:]
129 }
130 host.FabricName = value
131 case "dev_loss_tmo":
132 host.DevLossTMO = value
133 case "supported_classes":
134 host.SupportedClasses = value
135 case "supported_speeds":
136 host.SupportedSpeeds = value
137 case "symbolic_name":
138 host.SymbolicName = value
139 }
140 }
141
142 counters, err := parseFibreChannelStatistics(path)
143 if err != nil {
144 return nil, err
145 }
146 host.Counters = *counters
147
148 return &host, nil
149 }
150
151
152 func parseFibreChannelStatistics(hostPath string) (*FibreChannelCounters, error) {
153 var counters FibreChannelCounters
154
155 path := filepath.Join(hostPath, "statistics")
156 files, err := os.ReadDir(path)
157 if err != nil {
158 return nil, err
159 }
160
161 for _, f := range files {
162 if !f.Type().IsRegular() || f.Name() == "reset_statistics" {
163 continue
164 }
165
166 name := filepath.Join(path, f.Name())
167 value, err := util.SysReadFile(name)
168 if err != nil {
169
170 if os.IsNotExist(err) || err.Error() == "operation not supported" || errors.Is(err, os.ErrInvalid) {
171 continue
172 }
173 return nil, fmt.Errorf("failed to read file %q: %w", name, err)
174 }
175
176 vp := util.NewValueParser(value)
177
178
179 switch f.Name() {
180 case "dumped_frames":
181 counters.DumpedFrames = *vp.PUInt64()
182 case "error_frames":
183 counters.ErrorFrames = *vp.PUInt64()
184
210 case "fcp_packet_aborts":
211 counters.FCPPacketAborts = *vp.PUInt64()
212
216 case "invalid_tx_word_count":
217 counters.InvalidTXWordCount = *vp.PUInt64()
218 case "invalid_crc_count":
219 counters.InvalidCRCCount = *vp.PUInt64()
220 case "link_failure_count":
221 counters.LinkFailureCount = *vp.PUInt64()
222
226 case "loss_of_signal_count":
227 counters.LossOfSignalCount = *vp.PUInt64()
228 case "loss_of_sync_count":
229 counters.LossOfSyncCount = *vp.PUInt64()
230 case "nos_count":
231 counters.NosCount = *vp.PUInt64()
232
236 case "rx_frames":
237 counters.RXFrames = *vp.PUInt64()
238 case "rx_words":
239 counters.RXWords = *vp.PUInt64()
240 case "seconds_since_last_reset":
241 counters.SecondsSinceLastReset = *vp.PUInt64()
242 case "tx_frames":
243 counters.TXFrames = *vp.PUInt64()
244 case "tx_words":
245 counters.TXWords = *vp.PUInt64()
246 }
247
248 if err := vp.Err(); err != nil {
249 return nil, err
250 }
251
252 }
253
254 return &counters, nil
255 }
256
View as plain text