root / plugins / network / netstat_s_ @ b0b39b01
Historique | Voir | Annoter | Télécharger (19,4 ko)
| 1 | 85419c53 | Artem Sheremet | #!/usr/bin/env ruby |
|---|---|---|---|
| 2 | |||
| 3 | b0b39b01 | Lars Kruse | =begin |
| 4 | |||
| 5 | netstat_s revision 6 (Nov 2013) |
||
| 6 | |||
| 7 | This plugin shows various statistics from 'netstat -s' |
||
| 8 | |||
| 9 | Required privileges: none |
||
| 10 | |||
| 11 | OS: |
||
| 12 | Supposed: BSD, Linux (only a few items, see netstat_multi for more) |
||
| 13 | Tested: FreeBSD: 8.2, 8.3, 9.1 |
||
| 14 | Linux : Debian 6 (kernel 2.6.32), Arch (kernel 3.11.6), CentOS 6 |
||
| 15 | |||
| 16 | Author: Artem Sheremet <dot.doom@gmail.com> |
||
| 17 | |||
| 18 | 85419c53 | Artem Sheremet | |
| 19 | #%# family=auto |
||
| 20 | #%# capabilities=autoconf suggest |
||
| 21 | |||
| 22 | b0b39b01 | Lars Kruse | =end |
| 23 | |||
| 24 | 85419c53 | Artem Sheremet | # original filename |
| 25 | 302641b0 | Artem Sheremet | PLUGIN_NAME = 'netstat_s_' |
| 26 | 85419c53 | Artem Sheremet | |
| 27 | 302641b0 | Artem Sheremet | $os = `uname -s`.strip.downcase.to_sym |
| 28 | 85419c53 | Artem Sheremet | $debug_mode = ARGV.first == 'debug' |
| 29 | |||
| 30 | class String |
||
| 31 | b0b39b01 | Lars Kruse | def escape |
| 32 | self.gsub /[^\w]/, '_' |
||
| 33 | end |
||
| 34 | |||
| 35 | unless method_defined? :start_with? |
||
| 36 | def start_with?(str) |
||
| 37 | self[0...str.size] == str |
||
| 38 | end |
||
| 39 | end |
||
| 40 | |||
| 41 | unless method_defined? :lines |
||
| 42 | def lines |
||
| 43 | self.split($/).to_enum |
||
| 44 | end |
||
| 45 | end |
||
| 46 | 85419c53 | Artem Sheremet | end |
| 47 | |||
| 48 | class Graph |
||
| 49 | b0b39b01 | Lars Kruse | def initialize(name, protocol, parse_expr) |
| 50 | @name, @protocol, @parse_expr = name, protocol, parse_expr |
||
| 51 | end |
||
| 52 | |||
| 53 | def config |
||
| 54 | config_options = [] |
||
| 55 | |||
| 56 | # first, build a list of multigraphs (one graph per unit) |
||
| 57 | # Hash key is unit, and the value is array of labels |
||
| 58 | multigraphs = {}
|
||
| 59 | @parse_expr.each { |expr, descr|
|
||
| 60 | next unless descr # no label - skip this entry |
||
| 61 | |||
| 62 | descr.each { |entry|
|
||
| 63 | labels_array = (multigraphs[entry[0]] ||= []) |
||
| 64 | labels_array.push [entry[1], entry[2]] |
||
| 65 | } |
||
| 66 | } |
||
| 67 | |||
| 68 | multigraphs.each_pair { |unit, labels_and_negatives|
|
||
| 69 | # now just add options to the config |
||
| 70 | |||
| 71 | config_options.concat [ |
||
| 72 | "multigraph #{name(unit)}",
|
||
| 73 | "graph_title Netstat: #{@protocol}: #{@name}#{" (#{unit})" if multigraphs.size > 1}",
|
||
| 74 | "graph_category network", |
||
| 75 | "graph_order #{labels_and_negatives.map { |label, _negative| label.escape }.join(' ')}"
|
||
| 76 | ] |
||
| 77 | |||
| 78 | config_options.push "graph_args --base 1024" if unit == :bytes |
||
| 79 | has_negatives = false |
||
| 80 | |||
| 81 | labels_and_negatives.each { |label, negative|
|
||
| 82 | label_esc = label.escape |
||
| 83 | has_negatives = true unless negative == nil |
||
| 84 | |||
| 85 | if negative == true |
||
| 86 | # the value has no opposite and is negative |
||
| 87 | config_options.concat [ |
||
| 88 | "#{label_esc}.graph no",
|
||
| 89 | "#{label_esc}_neg.type DERIVE",
|
||
| 90 | "#{label_esc}_neg.min 0",
|
||
| 91 | "#{label_esc}_neg.draw LINE",
|
||
| 92 | "#{label_esc}_neg.label #{label}",
|
||
| 93 | "#{label_esc}_neg.negative #{label_esc}"
|
||
| 94 | ] |
||
| 95 | else |
||
| 96 | config_options.concat [ |
||
| 97 | "#{label_esc}.type DERIVE",
|
||
| 98 | "#{label_esc}.min 0",
|
||
| 99 | "#{label_esc}.draw LINE",
|
||
| 100 | "#{label_esc}.label #{label}"
|
||
| 101 | ] |
||
| 102 | end |
||
| 103 | |||
| 104 | if negative == false |
||
| 105 | # the value has no opposite and is positive |
||
| 106 | config_options.concat [ |
||
| 107 | "#{label_esc}_neg.graph off",
|
||
| 108 | "#{label_esc}.negative #{label_esc}_neg"
|
||
| 109 | ] |
||
| 110 | elsif negative |
||
| 111 | negative_esc = negative.escape |
||
| 112 | config_options.concat [ |
||
| 113 | "#{label_esc}.negative #{negative_esc}",
|
||
| 114 | "#{negative_esc}.graph no"
|
||
| 115 | ] |
||
| 116 | end |
||
| 117 | } |
||
| 118 | |||
| 119 | config_options.push "graph_vlabel per second#{" in (-) / out (+)" if has_negatives}"
|
||
| 120 | } |
||
| 121 | |||
| 122 | config_options |
||
| 123 | end |
||
| 124 | |||
| 125 | def fetch(data) |
||
| 126 | output_data = [] |
||
| 127 | |||
| 128 | # first build a set of multigraphs, one per unit. |
||
| 129 | # Hash key is unit, and the value is a hash of 'escaped label' => 'value' |
||
| 130 | multigraphs = {}
|
||
| 131 | @parse_expr.each { |expr, descr|
|
||
| 132 | next unless descr # no label - skip this entry |
||
| 133 | |||
| 134 | index = data.index { |line| line =~ expr }
|
||
| 135 | if index |
||
| 136 | data.delete_at index |
||
| 137 | $~[1..-1].zip(descr).each { |value, info|
|
||
| 138 | unit, label = info |
||
| 139 | (multigraphs[unit] ||= {})[label.escape] = value
|
||
| 140 | } |
||
| 141 | else |
||
| 142 | warn "no line found for #{expr}, #{descr}" if $debug_mode
|
||
| 143 | end |
||
| 144 | } |
||
| 145 | |||
| 146 | multigraphs.each_pair { |unit, values|
|
||
| 147 | output_data.push "multigraph #{name(unit)}"
|
||
| 148 | output_data += values.map { |label, value| "#{label}.value #{value}" }
|
||
| 149 | } |
||
| 150 | |||
| 151 | output_data |
||
| 152 | end |
||
| 153 | |||
| 154 | def name(unit) |
||
| 155 | "#{PLUGIN_NAME}#{@protocol}_#{@name.escape}_#{unit}"
|
||
| 156 | end |
||
| 157 | 85419c53 | Artem Sheremet | end |
| 158 | |||
| 159 | def graphs_for(protocol) |
||
| 160 | b0b39b01 | Lars Kruse | case protocol |
| 161 | # Order of the graps in each section is important for parsing. |
||
| 162 | # At the same time, it is not important for munin, so we are OK placing it in parsing order here. |
||
| 163 | when 'tcp' |
||
| 164 | $os == :linux ? [ |
||
| 165 | Graph.new('sent', protocol, [
|
||
| 166 | # Description of the elements of arrays below: |
||
| 167 | # 0: regexp to parse the line |
||
| 168 | # 1: Array<Array[3]> for each matching group in the regular expression. |
||
| 169 | # 0: unit name |
||
| 170 | # 1: label |
||
| 171 | # 2 (optional): negative label |
||
| 172 | # It could be reasonable to add more elements as warning and critical values. |
||
| 173 | |||
| 174 | [/(\d+) segments send out$/, [[:segments, 'total']]], |
||
| 175 | [/(\d+) segments retransmitted$/, [[:segments, 'retransmitted']]] |
||
| 176 | ]), |
||
| 177 | |||
| 178 | Graph.new('received', protocol, [
|
||
| 179 | [/(\d+) segments received$/, [[:segments, 'total']]], |
||
| 180 | [/(\d+) bad segments received.$/, [[:segments, 'bad']]] |
||
| 181 | ]), |
||
| 182 | |||
| 183 | Graph.new('connections', protocol, [
|
||
| 184 | [/(\d+) active connections openings$/, [[:connections, 'active openings']]], |
||
| 185 | [/(\d+) passive connection openings$/, [[:connections, 'passive openings']]], |
||
| 186 | [/(\d+) failed connection attempts$/, [[:connections, 'failed attempts']]], |
||
| 187 | [/(\d+) connection resets received$/, [[:connections, 'RST received']]], |
||
| 188 | [/(\d+) connections established$/, [[:connections, 'established']]], |
||
| 189 | [/(\d+) resets sent$/, [[:connections, 'RST sent']]] |
||
| 190 | ]), |
||
| 191 | |||
| 192 | Graph.new('timeouts', protocol, [
|
||
| 193 | [/(\d+) timeouts after SACK recovery$/, [[:segments, 'after SACK recovery']]], |
||
| 194 | [/(\d+) other TCP timeouts$/, [[:segments, 'other TCP']]], |
||
| 195 | [/(\d+) timeouts in loss state$/, [[:segments, 'in a loss state']]] |
||
| 196 | ]) |
||
| 197 | ] : [ |
||
| 198 | Graph.new('sent', protocol, [
|
||
| 199 | [/(\d+) packets sent$/, [[:packets, 'total']]], |
||
| 200 | [/(\d+) data packets \((\d+) bytes\)$/, [[:packets, 'data'], [:bytes, 'data']]], |
||
| 201 | [/(\d+) data packets \((\d+) bytes\) retransmitted$/, [[:packets, 'retransmitted'], [:bytes, 'retransmitted']]], |
||
| 202 | [/(\d+) data packets unnecessarily retransmitted$/, [[:packets, 'unnecessarily retransmitted']]], |
||
| 203 | [/(\d+) resends initiated by MTU discovery$/, [[:packets, 'resends initiated by MTU discovery']]], |
||
| 204 | [/(\d+) ack-only packets \((\d+) delayed\)$/, [[:packets, 'ack-only'], [:packets, 'ack-only delayed']]], |
||
| 205 | [/(\d+) URG only packets$/, [[:packets, 'URG only']]], |
||
| 206 | [/(\d+) window probe packets$/, [[:packets, 'window probe']]], |
||
| 207 | [/(\d+) window update packets$/, [[:packets, 'window update']]], |
||
| 208 | [/(\d+) control packets$/, [[:packets, 'control']]] |
||
| 209 | ]), |
||
| 210 | |||
| 211 | Graph.new('received', protocol, [
|
||
| 212 | [/(\d+) packets received$/, [[:packets, 'total']]], |
||
| 213 | [/(\d+) acks \(for (\d+) bytes\)$/, [[:packets, 'acks'], [:bytes, 'acks']]], |
||
| 214 | [/(\d+) duplicate acks$/, [[:packets, 'duplicate acks']]], |
||
| 215 | [/(\d+) acks for unsent data$/, [[:packets, 'acks for unsent data']]], |
||
| 216 | [/(\d+) packets \((\d+) bytes\) received in-sequence$/, [[:packets, 'in-sequence'], [:bytes, 'in-sequence']]], |
||
| 217 | [/(\d+) completely duplicate packets \((\d+) bytes\)$/, [[:packets, 'completely duplicate'], [:bytes, 'completely duplicate']]], |
||
| 218 | [/(\d+) old duplicate packets$/, [[:packets, 'old duplicate']]], |
||
| 219 | [/(\d+) packets with some dup\. data \((\d+) bytes duped\)$/, [[:packets, 'some dup. data'], [:bytes, 'partial dups']]], |
||
| 220 | [/(\d+) out-of-order packets \((\d+) bytes\)$/, [[:packets, 'out-of-order'], [:bytes, 'out-of-order']]], |
||
| 221 | [/(\d+) packets \((\d+) bytes\) of data after window$/, [[:packets, 'data after window'], [:bytes, 'data after window']]], |
||
| 222 | [/(\d+) window probes$/, [[:packets, 'window probes']]], |
||
| 223 | [/(\d+) window update packets$/, [[:packets, 'window update']]], |
||
| 224 | [/(\d+) packets received after close$/, [[:packets, 'after close']]], |
||
| 225 | [/(\d+) discarded for bad checksums$/, [[:packets, 'bad checksums']]], |
||
| 226 | [/(\d+) discarded for bad header offset fields?$/, [[:packets, 'bad header offset flds']]], |
||
| 227 | [/(\d+) discarded because packet too short$/, [[:packets, 'too short']]], |
||
| 228 | [/(\d+) discarded due to memory problems$/, [[:packets, 'discarded: memory problems']]], |
||
| 229 | [/(\d+) ignored RSTs in the windows$/, [[:packets, 'ignored RSTs in windows']]], |
||
| 230 | [/(\d+) segments updated rtt \(of (\d+) attempts\)$/, [[:packets, 'RTT: updated'], [:packets, 'RTT: attempts to update']]] |
||
| 231 | ]), |
||
| 232 | |||
| 233 | Graph.new('connections', protocol, [
|
||
| 234 | [/(\d+) connection requests$/, [[:connections, 'requests']]], |
||
| 235 | [/(\d+) connection accepts$/, [[:connections, 'accepts']]], |
||
| 236 | [/(\d+) bad connection attempts$/, [[:connections, 'bad attempts']]], |
||
| 237 | [/(\d+) listen queue overflows$/, [[:connections, 'listen queue overflows']]], |
||
| 238 | [/(\d+) connections established \(including accepts\)$/, [[:connections, 'established']]], |
||
| 239 | [/(\d+) connections closed \(including (\d+) drops\)$/, [[:connections, 'closed'], [:connections, 'dropped']]], |
||
| 240 | [/(\d+) connections updated cached RTT on close$/, [[:connections, 'closed & upd cached RTT']]], |
||
| 241 | [/(\d+) connections updated cached RTT variance on close$/, [[:connections, 'closed & upd cached RTT variance']]], |
||
| 242 | [/(\d+) connections updated cached ssthresh on close$/, [[:connections, 'closed & upd cached ssthresh']]], |
||
| 243 | [/(\d+) embryonic connections dropped$/, [[:connections, 'embryonic dropped']]] |
||
| 244 | ]), |
||
| 245 | |||
| 246 | Graph.new('timeouts', protocol, [
|
||
| 247 | [/(\d+) retransmit timeouts$/, [[:connections, 'retransmit']]], |
||
| 248 | [/(\d+) connections dropped by rexmit timeout$/, [[:connections, 'retransmit: dropped']]], |
||
| 249 | [/(\d+) persist timeouts$/, [[:connections, 'persist']]], |
||
| 250 | [/(\d+) connections dropped by persist timeout$/, [[:connections, 'persist: dropped']]], |
||
| 251 | [/(\d+) Connections \(fin_wait_2\) dropped because of timeout$/, [[:connections, 'fin_wait_2: dropped']]], |
||
| 252 | [/(\d+) keepalive timeouts$/, [[:connections, 'keepalive']]], |
||
| 253 | [/(\d+) keepalive probes sent$/, [[:connections, 'keepalive: probes sent']]], |
||
| 254 | [/(\d+) connections dropped by keepalive$/, [[:connections, 'keepalive: dropped']]] |
||
| 255 | ]), |
||
| 256 | |||
| 257 | Graph.new('correct predictions', protocol, [
|
||
| 258 | [/(\d+) correct ACK header predictions$/, [[:predictions, 'ACK header']]], |
||
| 259 | [/(\d+) correct data packet header predictions$/, [[:predictions, 'data packet header']]] |
||
| 260 | ]), |
||
| 261 | |||
| 262 | Graph.new('SYN', protocol, [
|
||
| 263 | [/(\d+) syncache entries added$/, [[:entries, 'cache added']]], |
||
| 264 | [/(\d+) cookies sent$/, [[:entries, 'cookies sent']]], |
||
| 265 | [/(\d+) cookies received$/, [[:entries, 'cookies received']]], |
||
| 266 | [/(\d+) retransmitted$/, [[:entries, 'retransmitted']]], |
||
| 267 | [/(\d+) dupsyn$/, [[:entries, 'duplicates']]], |
||
| 268 | [/(\d+) dropped$/, [[:entries, 'dropped']]], |
||
| 269 | [/(\d+) completed$/, [[:entries, 'completed']]], |
||
| 270 | [/(\d+) bucket overflow$/, [[:entries, 'bucket overflow']]], |
||
| 271 | [/(\d+) cache overflow$/, [[:entries, 'cache overflow']]], |
||
| 272 | [/(\d+) reset$/, [[:entries, 'reset']]], |
||
| 273 | [/(\d+) stale$/, [[:entries, 'stale']]], |
||
| 274 | [/(\d+) aborted$/, [[:entries, 'aborted']]], |
||
| 275 | [/(\d+) badack$/, [[:entries, 'bad ACK']]], |
||
| 276 | [/(\d+) unreach$/, [[:entries, 'unreachable']]], |
||
| 277 | [/(\d+) zone failures$/, [[:entries, 'zone failures']]], |
||
| 278 | [/(\d+) hostcache entries added$/, [[:entries, 'hostcache added']]], |
||
| 279 | [/(\d+) bucket overflow$/, [[:entries, 'hostcache overflow']]] |
||
| 280 | ]), |
||
| 281 | |||
| 282 | Graph.new('SACK', protocol, [
|
||
| 283 | [/(\d+) SACK recovery episodes$/, [[:packets, 'recovery episodes']]], |
||
| 284 | [/(\d+) segment rexmits in SACK recovery episodes$/, [[:packets, 'segment rexmits']]], |
||
| 285 | [/(\d+) byte rexmits in SACK recovery episodes$/, [[:bytes, 'bytes rexmitted']]], |
||
| 286 | [/(\d+) SACK options \(SACK blocks\) received$/, [[:packets, 'options blocks rcvd']]], |
||
| 287 | [/(\d+) SACK options \(SACK blocks\) sent$/, [[:packets, 'options blocks sent']]], |
||
| 288 | [/(\d+) SACK scoreboard overflow$/, [[:packets, 'scoreboard overflow']]] |
||
| 289 | ]), |
||
| 290 | |||
| 291 | Graph.new('ECN', protocol, [
|
||
| 292 | [/(\d+) packets with ECN CE bit set$/, [[:packets, 'CE bit']]], |
||
| 293 | [/(\d+) packets with ECN ECT\(0\) bit set$/, [[:packets, 'ECT(0) bit']]], |
||
| 294 | [/(\d+) packets with ECN ECT\(1\) bit set$/, [[:packets, 'ECT(1) bit']]], |
||
| 295 | [/(\d+) successful ECN handshakes$/, [[:packets, 'successful handshakes']]], |
||
| 296 | [/(\d+) times ECN reduced the congestion window$/, [[:packets, 'congestion window reduced']]] |
||
| 297 | ]) |
||
| 298 | ] |
||
| 299 | when 'udp' |
||
| 300 | $os == :linux ? [] : [ |
||
| 301 | Graph.new('received', protocol, [
|
||
| 302 | [/(\d+) datagrams received$/, [[:packets, 'total']]], |
||
| 303 | [/(\d+) with incomplete header$/, [[:packets, 'incomplete header']]], |
||
| 304 | [/(\d+) with bad data length field$/, [[:packets, 'bad data length field']]], |
||
| 305 | [/(\d+) with bad checksum$/, [[:packets, 'bad checksum']]], |
||
| 306 | [/(\d+) with no checksum$/, [[:packets, 'no checksum']]], |
||
| 307 | [/(\d+) dropped due to no socket$/, [[:packets, 'dropped: no socket']]], |
||
| 308 | [/(\d+) broadcast\/multicast datagrams undelivered$/, [[:packets, '*cast undelivered']]], |
||
| 309 | [/(\d+) dropped due to full socket buffers$/, [[:packets, 'dropped: no buffers']]], |
||
| 310 | [/(\d+) not for hashed pcb$/, [[:packets, 'not for hashed pcb']]], |
||
| 311 | [/(\d+) delivered$/, [[:packets, 'delivered']]] |
||
| 312 | ]), |
||
| 313 | |||
| 314 | Graph.new('sent', protocol, [
|
||
| 315 | [/(\d+) datagrams output$/, [[:packets, 'total']]], |
||
| 316 | [/(\d+) times multicast source filter matched$/, [[:packets, 'multicast src filter match']]] |
||
| 317 | ]) |
||
| 318 | ] |
||
| 319 | when 'ip' |
||
| 320 | $os == :linux ? [] : [ |
||
| 321 | Graph.new('received', protocol, [
|
||
| 322 | [/(\d+) total packets received$/, [[:packets, 'total']]], |
||
| 323 | [/(\d+) bad header checksums$/, [[:packets, 'bad header checksum']]], |
||
| 324 | [/(\d+) with size smaller than minimum$/, [[:packets, 'size smaller than min']]], |
||
| 325 | [/(\d+) with data size < data length$/, [[:packets, 'data size < data length']]], |
||
| 326 | [/(\d+) with ip length > max ip packet size$/, [[:packets, 'ip length > max ip packet sz']]], |
||
| 327 | [/(\d+) with header length < data size$/, [[:packets, 'header length < data size']]], |
||
| 328 | [/(\d+) with data length < header length$/, [[:packets, 'data length < header length']]], |
||
| 329 | [/(\d+) with bad options$/, [[:packets, 'bad options']]], |
||
| 330 | [/(\d+) with incorrect version number$/, [[:packets, 'incorrect version']]], |
||
| 331 | [/(\d+) fragments? received$/, [[:packets, 'fragments']]], |
||
| 332 | [/(\d+) fragments? dropped \(dup or out of space\)$/, [[:packets, 'frags dropped: dup/out of spc']]], |
||
| 333 | [/(\d+) fragments? dropped after timeout$/, [[:packets, 'frags dropped: timeout']]], |
||
| 334 | [/(\d+) packets? reassembled ok$/, [[:packets, 'reassembled ok']]], |
||
| 335 | [/(\d+) packets? for this host$/, [[:packets, 'for this host']]], |
||
| 336 | [/(\d+) packets? for unknown\/unsupported protocol$/, [[:packets, 'for unknown/unsup protocol']]], |
||
| 337 | [/(\d+) packets? forwarded \((\d+) packets fast forwarded\)$/, [[:packets, 'forwarded'], [:packets, 'fast forwarded']]], |
||
| 338 | [/(\d+) packets? not forwardable$/, [[:packets, 'not forwardable']]], |
||
| 339 | [/(\d+) packets? received for unknown multicast group$/, [[:packets, 'unknown multicast grp']]] |
||
| 340 | ]), |
||
| 341 | |||
| 342 | Graph.new('sent', protocol, [
|
||
| 343 | [/(\d+) packets? sent from this host$/, [[:packets, 'total']]], |
||
| 344 | [/(\d+) redirects? sent$/, [[:packets, 'redirect']]], |
||
| 345 | [/(\d+) packets? sent with fabricated ip header$/, [[:packets, 'fabricated IP head']]], |
||
| 346 | [/(\d+) output packets? dropped due to no bufs, etc\.$/, [[:packets, 'dropped: no bufs, etc']]], |
||
| 347 | [/(\d+) output packets? discarded due to no route$/, [[:packets, 'discarded: no route']]], |
||
| 348 | [/(\d+) output datagrams? fragmented$/, [[:packets, 'fragmented']]], |
||
| 349 | [/(\d+) fragments? created$/, [[:packets, 'fragments created']]], |
||
| 350 | [/(\d+) datagrams? that can't be fragmented$/, [[:packets, "can't be fragmented"]]], |
||
| 351 | [/(\d+) tunneling packets? that can't find gif$/, [[:packets, 'tunneling, gif not found']]], |
||
| 352 | [/(\d+) datagrams? with bad address in header$/, [[:packets, 'bad address in header']]] |
||
| 353 | ]) |
||
| 354 | ] |
||
| 355 | when 'arp' |
||
| 356 | $os == :linux ? [] : [ |
||
| 357 | Graph.new('packets', protocol, [
|
||
| 358 | # This is just a total, so ignore the value but keep regexp to avoid 'not parsed' warning. |
||
| 359 | [/(\d+) ARP packets? received$/], |
||
| 360 | [/(\d+) ARP requests? received$/, [[:packets, 'requests received']]], |
||
| 361 | [/(\d+) ARP repl(?:y|ies) received$/, [[:packets, 'replies received']]], |
||
| 362 | [/(\d+) ARP requests? sent$/, [[:packets, 'requests', 'requests received']]], |
||
| 363 | [/(\d+) ARP repl(?:y|ies) sent$/, [[:packets, 'replies', 'replies received']]], |
||
| 364 | [/(\d+) total packets? dropped due to no ARP entry$/, [[:packets, 'no entry']]] |
||
| 365 | ]), |
||
| 366 | |||
| 367 | Graph.new('entries', protocol, [
|
||
| 368 | [/(\d+) ARP entrys? timed out$/, [[:entries, 'timed out']]], |
||
| 369 | [/(\d+) Duplicate IPs seen$/, [[:entries, 'duplicate IPs seen']]] |
||
| 370 | ]) |
||
| 371 | ] |
||
| 372 | end |
||
| 373 | 85419c53 | Artem Sheremet | end |
| 374 | |||
| 375 | proto_name = File.basename($0, '.*').escape |
||
| 376 | proto_name.slice! 0, PLUGIN_NAME.size if proto_name.start_with? PLUGIN_NAME |
||
| 377 | |||
| 378 | proto_name = 'tcp' if proto_name.empty? |
||
| 379 | |||
| 380 | def netstat_s(protocol) |
||
| 381 | b0b39b01 | Lars Kruse | if $os == :linux |
| 382 | %w(tcp udp).include?(protocol) ? |
||
| 383 | `netstat -s --#{protocol}` :
|
||
| 384 | `netstat -s --raw` |
||
| 385 | else |
||
| 386 | `netstat -sp #{protocol}`
|
||
| 387 | end.lines.reject { |line| line =~ /^\w+:/ }
|
||
| 388 | 85419c53 | Artem Sheremet | end |
| 389 | |||
| 390 | case ARGV.first |
||
| 391 | when 'autoconf' |
||
| 392 | b0b39b01 | Lars Kruse | puts [:linux, :freebsd].include?($os) ? 'yes' : 'no' |
| 393 | 85419c53 | Artem Sheremet | when 'suggest' |
| 394 | b0b39b01 | Lars Kruse | puts $os == :linux ? %w(tcp) : %w(tcp udp ip arp) |
| 395 | 85419c53 | Artem Sheremet | when 'config' |
| 396 | b0b39b01 | Lars Kruse | graphs_for(proto_name).each { |graph|
|
| 397 | puts graph.config.join $/ |
||
| 398 | } |
||
| 399 | 85419c53 | Artem Sheremet | else |
| 400 | b0b39b01 | Lars Kruse | data = netstat_s(proto_name) |
| 401 | graphs_for(proto_name).each { |graph|
|
||
| 402 | puts graph.fetch(data).join $/ |
||
| 403 | } |
||
| 404 | 85419c53 | Artem Sheremet | |
| 405 | b0b39b01 | Lars Kruse | warn "not parsed:\n#{data.join}" unless data.empty? if $debug_mode
|
| 406 | 85419c53 | Artem Sheremet | end |
| 407 | 302641b0 | Artem Sheremet | |
| 408 | # awful performance when scrolling through those regexps above |
||
| 409 | # vim: syntax=none |
