]> git.ipfire.org Git - collecty.git/blame - src/collecty/plugins/conntrack.py
conntrack: Show protocol in object representation
[collecty.git] / src / collecty / plugins / conntrack.py
CommitLineData
0ec1854a
MT
1#!/usr/bin/python
2###############################################################################
3# #
4# collecty - A system statistics collection daemon for IPFire #
5# Copyright (C) 2015 IPFire development team #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
21
22import os
23
24import base
25
26CONNTRACK_FILE = "/proc/net/nf_conntrack"
27
28class ConntrackTable(object):
29 _layer3_protocols = (
30 "ipv6",
31 "ipv4",
32 "other",
33 )
34
35 _layer4_protocols = (
36 "dccp",
37 "icmp",
38 "igmp",
39 "sctp",
40 "tcp",
41 "udp",
42 "udplite",
43 "other",
44 )
45
46 _stateful_layer4_protocols = {
47 "dccp" : (
48 "CLOSEREQ",
49 "CLOSING",
50 "IGNORE",
51 "INVALID",
52 "NONE",
53 "OPEN",
54 "PARTOPEN",
55 "REQUEST",
56 "RESPOND",
57 "TIME_WAIT",
58 ),
59 "sctp" : (
60 "CLOSED",
61 "COOKIE_ECHOED",
62 "COOKIE_WAIT",
63 "ESTABLISHED",
64 "NONE",
65 "SHUTDOWN_ACK_SENT",
66 "SHUTDOWN_RECD",
67 "SHUTDOWN_SENT",
68 ),
69 "tcp" : (
70 "CLOSE",
71 "CLOSE_WAIT",
72 "ESTABLISHED",
73 "FIN_WAIT",
74 "LAST_ACK",
75 "NONE",
76 "SYN_RECV",
77 "SYN_SENT",
78 "SYN_SENT2",
79 "TIME_WAIT",
80 ),
81 }
82
83 def __init__(self, filename):
84 with open(filename) as f:
85 self.layer3_protocols = {}
86 for proto in self._layer3_protocols:
87 self.layer3_protocols[proto] = 0
88
89 self.layer4_protocols = {}
90 for proto in self._layer4_protocols:
91 self.layer4_protocols[proto] = 0
92
93 self.protocol_states = {}
94 for proto, states in self._stateful_layer4_protocols.items():
95 self.protocol_states[proto] = dict((state, 0) for state in states)
96
97 for line in f.readlines():
98 line = line.split()
99
100 # Layer 3 protocol
101 layer3_protocol = line[0]
102
103 try:
104 self.layer3_protocols[layer3_protocol] += 1
105 except KeyError:
106 self.layer3_protocols["other"] += 1
107
108 # Layer 4 protocol
109 layer4_protocol = line[2]
110
111 try:
112 self.layer4_protocols[layer4_protocol] += 1
113 except KeyError:
114 self.layer4_protocols["other"] += 1
115 layer4_protocol = "other"
116
117 # Count connection states
118 if self.protocol_states.has_key(layer4_protocol):
119 state = line[5]
120
121 try:
122 self.protocol_states[layer4_protocol][state] += 1
123 except KeyError:
124 pass
125
126
127class ConntrackObject(base.Object):
128 protocol = None
129
130 def init(self, conntrack_table):
131 self.conntrack_table = conntrack_table
132
133 @property
134 def id(self):
135 return self.protocol
136
137
138class ConntrackLayer3ProtocolsObject(ConntrackObject):
139 protocols = ConntrackTable._layer3_protocols
140
141 rrd_schema = [
142 "DS:%s:GAUGE:0:U" % p for p in protocols
143 ]
144
145 @property
146 def id(self):
147 return "layer3-protocols"
148
149 def collect(self):
150 results = []
151
152 for proto in self.protocols:
153 r = self.conntrack_table.layer3_protocols.get(proto, 0)
154 results.append("%s" % r)
155
156 return ":".join(results)
157
158
159class ConntrackLayer4ProtocolsObject(ConntrackObject):
160 protocols = ConntrackTable._layer4_protocols
161
162 rrd_schema = [
163 "DS:%s:GAUGE:0:U" % p for p in protocols
164 ]
165
166 @property
167 def id(self):
168 return "layer4-protocols"
169
170 def collect(self):
171 results = []
172
173 for proto in self.protocols:
174 r = self.conntrack_table.layer4_protocols.get(proto, 0)
175 results.append("%s" % r)
176
177 return ":".join(results)
178
179
180class ConntrackProtocolWithStatesObject(ConntrackObject):
181 def init(self, conntrack_table, protocol):
182 ConntrackObject.init(self, conntrack_table)
183 self.protocol = protocol
184
b54c3e02
MT
185 def __repr__(self):
186 return "<%s %s>" % (self.__class__.__name__, self.protocol)
187
0ec1854a
MT
188 @property
189 def states(self):
190 return ConntrackTable._stateful_layer4_protocols.get(self.protocol)
191
192 @property
193 def rrd_schema(self):
194 return ["DS:%s:GAUGE:0:U" % state for state in self.states]
195
196 def get_states(self):
197 results = []
198
199 for state in self.states:
200 r = self.conntrack_table.protocol_states[self.protocol].get(state, 0)
201 results.append("%s" % r)
202
203 return results
204
205 def collect(self):
206 return ":".join(self.get_states())
207
208
209class ConntrackPlugin(base.Plugin):
210 name = "conntrack"
211 description = "Conntrack Plugin"
212
213 templates = []
214
215 @property
216 def objects(self):
217 ct = self.get_conntrack_table()
218
219 if ct:
220 yield ConntrackLayer3ProtocolsObject(self, ct)
221 yield ConntrackLayer4ProtocolsObject(self, ct)
222
223 for protocol in ConntrackTable._stateful_layer4_protocols:
224 yield ConntrackProtocolWithStatesObject(self, ct, protocol)
225
226 def get_conntrack_table(self):
227 if not os.path.exists(CONNTRACK_FILE):
228 return
229
230 return ConntrackTable(CONNTRACK_FILE)