Network
banshee/network-collection/network/snmp/
interfaces
The state of each interface of a switch, a router or a firewall by SNMP: link, speed, duplex, MTU, time in its state, IPv4 addresses.
by banshee1 installation2 versions
v2Latest
Published on October 28, 2026. One naming convention across collections; documentation completed.
// The state of the network interfaces of a switch, a router or a firewall, by SNMP (IF-MIB, EtherLike-MIB,
// IP-MIB): the link of each interface, its negotiated speed and duplex, its MTU, how long it has kept its
// state, and its IPv4 addresses. The traffic, errors and drops are read by network/snmp/interface-traffic;
// the name and uptime of the device by network/snmp/system.
// 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('link', 'text', array('label' => 'Link state', 'per' => 'interface'));
output('speed', 'number', array('label' => 'Negotiated speed', 'unit' => 'Mbit/s', 'per' => 'interface'));
output('duplex', 'text', array('label' => 'Duplex', 'per' => 'interface'));
output('mtu', 'number', array('label' => 'MTU', 'per' => 'interface'));
output('stable-for', 'number', array('label' => 'Time in its state', 'unit' => 'min', 'per' => 'interface'));
output('addresses', 'number', array('label' => 'IPv4 addresses', 'per' => 'interface'));
// Not checked by default: on an access switch, every port without a cable is a link down. Check it once
// the selection keeps the links that count.
watch.state('link-down', 'Link down', 'link', array('critical' => array('down', 'lowerlayerdown'), 'enabled' => false));
watch.below('link-changed', 'Link changed recently', 'stable-for', array('warning' => 15, 'enabled' => false));
watch.custom('speed-degraded', 'Negotiated speed degraded', array(
'help' => 'Warning when the negotiated speed is below the expected speed.',
'settings' => array(
'expected' => array('label' => 'Expected speed', 'form' => 'number', 'unit' => 'Mbit/s', 'default' => 1000),
),
'enabled' => false,
));
watch.state('half-duplex', 'Half duplex', 'duplex', array('warning' => array('half')));
watch.missing('missing', 'Interface missing', 'link', array('enabled' => false));
watch.expect('mtu', 'Unexpected MTU', 'mtu', array('warning' => array(1500), 'enabled' => false));
watch.below('no-address', 'No IPv4 address left', 'addresses', array('critical' => 1, 'enabled' => false));
// By ifIndex. IF-MIB, ifTable: ifMtu, ifAdminStatus, ifOperStatus and ifLastChange (the sysUpTime of the
// last change of state). ifXTable: ifName ("Gi1/0/1", "ether1", "ge-0/0/0"), ifHighSpeed (in Mbit/s) and
// ifAlias, the description the administrator gives the port. EtherLike-MIB: dot3StatsDuplexStatus, whose
// index is the ifIndex.
$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',
'mtu' => '1.3.6.1.2.1.2.2.1.4',
'admin' => '1.3.6.1.2.1.2.2.1.7',
'status' => '1.3.6.1.2.1.2.2.1.8',
'last-change' => '1.3.6.1.2.1.2.2.1.9',
'speed' => '1.3.6.1.2.1.31.1.1.1.15',
'duplex' => '1.3.6.1.2.1.10.7.2.1.19',
));
// IP-MIB, ipAddrTable, by address: ipAdEntIfIndex tells the interface that carries it.
$addresses = snmp.table(array('ifindex' => '1.3.6.1.2.1.4.20.1.2'));
// SNMPv2-MIB, sysUpTime: the time since the agent started, in hundredths of a second, the clock of
// ifLastChange.
$uptime = snmp.get('1.3.6.1.2.1.1.3.0');
$address_count = array();
foreach ($addresses as $entry) {
$address_count[$entry['ifindex']] = list.get($address_count, $entry['ifindex'], 0) + 1;
}
// ifOperStatus and dot3StatsDuplexStatus in words; an interface disabled by the administrator
// (ifAdminStatus 2) reads "disabled", so that it does not pass for a link down.
$states = array(1 => 'up', 2 => 'down', 3 => 'testing', 4 => 'unknown', 5 => 'dormant', 6 => 'notpresent', 7 => 'lowerlayerdown');
$duplexes = array(1 => 'unknown', 2 => 'half', 3 => 'full');
$expected_speed = watch.setting('speed-degraded', 'expected');
$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.
$name = $row['name'];
if (list.has($seen, $name)) {
$name = $name . ' #' . $index;
}
$seen[$name] = true;
$link = list.get($states, list.get($row, 'status', 4), 'unknown');
if (list.get($row, 'admin', 1) == 2) {
$link = 'disabled';
}
value('link', $link, $name);
if (list.get($row, 'alias', '') != '') {
value('alias', $row['alias'], $name);
}
value('addresses', list.get($address_count, $index, 0), $name);
if (list.has($row, 'mtu')) {
value('mtu', $row['mtu'], $name);
}
// ifLastChange above sysUpTime means sysUpTime wrapped (after 497 days): the time is not known.
if (list.has($row, 'last-change') && $row['last-change'] <= $uptime) {
value('stable-for', number.round(($uptime - $row['last-change']) / 6000, 1), $name);
}
// The speed and duplex of a link that is not up mean nothing.
if ($link != 'up') {
continue;
}
if (list.has($row, 'duplex')) {
value('duplex', list.get($duplexes, $row['duplex'], 'unknown'), $name);
}
$speed = list.get($row, 'speed', 0);
if ($speed > 0) {
value('speed', $speed, $name);
if ($expected_speed != '' && $speed < $expected_speed) {
watch.raise('speed-degraded', 'warning', $name . ' negotiated at ' . $speed . ' Mbit/s', $name);
}
}
}