Network
banshee/network-collection/network/snmp/
interface-traffic
The traffic of each interface of a switch, a router or a firewall by SNMP: throughput, usage, packets, errors and drops.
par banshee1 installation2 versions
v2Dernière
Publiée le 28 octobre 2026. One naming convention across collections; documentation completed.
// The traffic of the network interfaces of a switch, a router or a firewall, by SNMP (IF-MIB): the
// throughput of each interface, its usage of the negotiated speed, its packets, errors and drops, from the
// 64-bit counters between two runs. The state of the links is read by network/snmp/interfaces.
// Loopback and null interfaces are left out by the default selection.
need('protocol:snmp');
per('interface', 'Interfaces', array('ignore' => array('lo', 'lo0*', 'Lo*', 'Nu*', 'Null*')));
output('alias', 'text', array('label' => 'Description', 'per' => 'interface'));
output('traffic-in', 'number', array('label' => 'Inbound traffic', 'unit' => 'bit/s', 'per' => 'interface'));
output('traffic-out', 'number', array('label' => 'Outbound traffic', 'unit' => 'bit/s', 'per' => 'interface'));
output('traffic', 'number', array('label' => 'Total traffic', 'unit' => 'bit/s', 'per' => 'interface'));
output('in-percent', 'number', array('label' => 'Inbound usage', 'unit' => '%', 'per' => 'interface'));
output('out-percent', 'number', array('label' => 'Outbound usage', 'unit' => '%', 'per' => 'interface'));
output('packets', 'number', array('label' => 'Packets', 'unit' => 'packets/s', 'per' => 'interface'));
output('errors', 'number', array('label' => 'Errors', 'unit' => 'errors/s', 'per' => 'interface'));
output('drops', 'number', array('label' => 'Drops', 'unit' => 'packets/s', 'per' => 'interface'));
output('drop-percent', 'number', array('label' => 'Share of packets dropped', 'unit' => '%', 'per' => 'interface'));
watch.above('saturation-in', 'Inbound saturation', 'in-percent', array('warning' => 70, 'critical' => 90, 'for' => '5 min'));
watch.above('saturation-out', 'Outbound saturation', 'out-percent', array('warning' => 70, 'critical' => 90, 'for' => '5 min'));
watch.custom('errors', 'Errors', array(
'help' => 'Warning beyond a number of errors per minute; critical beyond a share of the traffic.',
'settings' => array(
'per-minute' => array('label' => 'Warning beyond', 'form' => 'number', 'unit' => 'errors/min', 'default' => 1),
'share' => array('label' => 'Critical beyond', 'form' => 'number', 'unit' => '% of traffic', 'default' => 0.1),
),
));
watch.above('drops', 'Packets dropped', 'drop-percent', array('warning' => 0.5, 'critical' => 2));
watch.habit('traffic-unusual', 'Unusual traffic', 'traffic', array('floor' => 10000000, 'enabled' => false));
watch.silence('mute', 'Silent interface', 'packets', array('warning' => '10 min', 'enabled' => false));
// By ifIndex. IF-MIB, ifTable: ifInDiscards, ifInErrors, ifOutDiscards, ifOutErrors. ifXTable: ifName,
// ifAlias (the description the administrator gives the port), ifHighSpeed (in Mbit/s) and the 64-bit
// counters, octets and unicast, multicast and broadcast packets, in each direction.
$interfaces = snmp.table(array(
'name' => '1.3.6.1.2.1.31.1.1.1.1',
'alias' => '1.3.6.1.2.1.31.1.1.1.18',
'in-discards' => '1.3.6.1.2.1.2.2.1.13',
'in-errors' => '1.3.6.1.2.1.2.2.1.14',
'out-discards' => '1.3.6.1.2.1.2.2.1.19',
'out-errors' => '1.3.6.1.2.1.2.2.1.20',
'in-octets' => '1.3.6.1.2.1.31.1.1.1.6',
'in-ucast' => '1.3.6.1.2.1.31.1.1.1.7',
'in-mcast' => '1.3.6.1.2.1.31.1.1.1.8',
'in-bcast' => '1.3.6.1.2.1.31.1.1.1.9',
'out-octets' => '1.3.6.1.2.1.31.1.1.1.10',
'out-ucast' => '1.3.6.1.2.1.31.1.1.1.11',
'out-mcast' => '1.3.6.1.2.1.31.1.1.1.12',
'out-bcast' => '1.3.6.1.2.1.31.1.1.1.13',
'speed' => '1.3.6.1.2.1.31.1.1.1.15',
));
$errors_per_minute = watch.setting('errors', 'per-minute');
$errors_share = watch.setting('errors', 'share');
$seen = array();
foreach ($interfaces as $index => $row) {
if (!list.has($row, 'name')) {
continue;
}
// Two interfaces of the same name each keep their own: the second carries its ifIndex, as in
// network/snmp/interfaces.
$name = $row['name'];
if (list.has($seen, $name)) {
$name = $name . ' #' . $index;
}
$seen[$name] = true;
if (list.get($row, 'alias', '') != '') {
value('alias', $row['alias'], $name);
}
// Rates, from the counters of this run and the previous one; nothing on the first run, after the device
// restarts, nor for an interface without 64-bit counters.
if (!list.has($row, 'in-octets') || !list.has($row, 'out-octets')) {
continue;
}
$in_packets = list.get($row, 'in-ucast', 0) + list.get($row, 'in-mcast', 0) + list.get($row, 'in-bcast', 0);
$out_packets = list.get($row, 'out-ucast', 0) + list.get($row, 'out-mcast', 0) + list.get($row, 'out-bcast', 0);
$in = counter.rate('in', $row['in-octets'] * 8, $name);
$out = counter.rate('out', $row['out-octets'] * 8, $name);
$packets = counter.rate('packets', $in_packets + $out_packets, $name);
$errors = counter.rate('errors', list.get($row, 'in-errors', 0) + list.get($row, 'out-errors', 0), $name);
$drops = counter.rate('drops', list.get($row, 'in-discards', 0) + list.get($row, 'out-discards', 0), $name);
if ($in == '' || $out == '' || $packets == '' || $errors == '' || $drops == '') {
continue;
}
value('traffic-in', number.round($in), $name);
value('traffic-out', number.round($out), $name);
value('traffic', number.round($in + $out), $name);
value('packets', number.round($packets, 2), $name);
value('errors', number.round($errors, 3), $name);
value('drops', number.round($drops, 3), $name);
if ($packets + $drops > 0) {
value('drop-percent', number.round(100 * $drops / ($packets + $drops), 2), $name);
}
// The negotiated speed is in Mbit/s: one percent is 10,000 bit/s. A link that is down, or a virtual
// interface, has none (0).
$speed = list.get($row, 'speed', 0);
if ($speed > 0) {
value('in-percent', number.round($in / ($speed * 10000), 1), $name);
value('out-percent', number.round($out / ($speed * 10000), 1), $name);
}
// Errors: per minute for the warning, as a share of the traffic for the critical.
if ($errors_per_minute != '' && $errors * 60 > $errors_per_minute) {
watch.raise('errors', 'warning', $name . ': ' . number.round($errors * 60, 1) . ' errors per minute', $name);
}
if ($errors_share != '' && $packets + $errors > 0) {
$share = 100 * $errors / ($packets + $errors);
if ($share > $errors_share) {
watch.raise('errors', 'critical', $name . ': ' . number.round($share, 2) . ' % of traffic in error', $name);
}
}
}