1
2
3
4
5
6
7
8
9
10
11
12
13
14 package procfs
15
16 import (
17 "bufio"
18 "bytes"
19 "fmt"
20 "strconv"
21 "strings"
22
23 "github.com/prometheus/procfs/internal/util"
24 )
25
26
27 type NetProtocolStats map[string]NetProtocolStatLine
28
29
30
31
32 type NetProtocolStatLine struct {
33 Name string
34 Size uint64
35 Sockets int64
36 Memory int64
37 Pressure int
38 MaxHeader uint64
39 Slab bool
40 ModuleName string
41 Capabilities NetProtocolCapabilities
42 }
43
44
45 type NetProtocolCapabilities struct {
46 Close bool
47 Connect bool
48 Disconnect bool
49 Accept bool
50 IoCtl bool
51 Init bool
52 Destroy bool
53 Shutdown bool
54 SetSockOpt bool
55 GetSockOpt bool
56 SendMsg bool
57 RecvMsg bool
58 SendPage bool
59 Bind bool
60 BacklogRcv bool
61 Hash bool
62 UnHash bool
63 GetPort bool
64 EnterMemoryPressure bool
65 }
66
67
68
69
70
71
72
73 func (fs FS) NetProtocols() (NetProtocolStats, error) {
74 data, err := util.ReadFileNoStat(fs.proc.Path("net/protocols"))
75 if err != nil {
76 return NetProtocolStats{}, err
77 }
78 return parseNetProtocols(bufio.NewScanner(bytes.NewReader(data)))
79 }
80
81 func parseNetProtocols(s *bufio.Scanner) (NetProtocolStats, error) {
82 nps := NetProtocolStats{}
83
84
85 s.Scan()
86
87 for s.Scan() {
88 line, err := nps.parseLine(s.Text())
89 if err != nil {
90 return NetProtocolStats{}, err
91 }
92
93 nps[line.Name] = *line
94 }
95 return nps, nil
96 }
97
98 func (ps NetProtocolStats) parseLine(rawLine string) (*NetProtocolStatLine, error) {
99 line := &NetProtocolStatLine{Capabilities: NetProtocolCapabilities{}}
100 var err error
101 const enabled = "yes"
102 const disabled = "no"
103
104 fields := strings.Fields(rawLine)
105 line.Name = fields[0]
106 line.Size, err = strconv.ParseUint(fields[1], 10, 64)
107 if err != nil {
108 return nil, err
109 }
110 line.Sockets, err = strconv.ParseInt(fields[2], 10, 64)
111 if err != nil {
112 return nil, err
113 }
114 line.Memory, err = strconv.ParseInt(fields[3], 10, 64)
115 if err != nil {
116 return nil, err
117 }
118 if fields[4] == enabled {
119 line.Pressure = 1
120 } else if fields[4] == disabled {
121 line.Pressure = 0
122 } else {
123 line.Pressure = -1
124 }
125 line.MaxHeader, err = strconv.ParseUint(fields[5], 10, 64)
126 if err != nil {
127 return nil, err
128 }
129 if fields[6] == enabled {
130 line.Slab = true
131 } else if fields[6] == disabled {
132 line.Slab = false
133 } else {
134 return nil, fmt.Errorf("%w: capability for protocol: %s", ErrFileParse, line.Name)
135 }
136 line.ModuleName = fields[7]
137
138 err = line.Capabilities.parseCapabilities(fields[8:])
139 if err != nil {
140 return nil, err
141 }
142
143 return line, nil
144 }
145
146 func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) error {
147
148 capabilityFields := [...]*bool{
149 &pc.Close,
150 &pc.Connect,
151 &pc.Disconnect,
152 &pc.Accept,
153 &pc.IoCtl,
154 &pc.Init,
155 &pc.Destroy,
156 &pc.Shutdown,
157 &pc.SetSockOpt,
158 &pc.GetSockOpt,
159 &pc.SendMsg,
160 &pc.RecvMsg,
161 &pc.SendPage,
162 &pc.Bind,
163 &pc.BacklogRcv,
164 &pc.Hash,
165 &pc.UnHash,
166 &pc.GetPort,
167 &pc.EnterMemoryPressure,
168 }
169
170 for i := 0; i < len(capabilities); i++ {
171 if capabilities[i] == "y" {
172 *capabilityFields[i] = true
173 } else if capabilities[i] == "n" {
174 *capabilityFields[i] = false
175 } else {
176 return fmt.Errorf("%w: capability block for protocol: position %d", ErrFileParse, i)
177 }
178 }
179 return nil
180 }
181
View as plain text