banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

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.

  • network
  • snmp
  • if-mib
  • interface
  • switch
  • router

by banshee1 installation2 versions

Keen 1.0.0 · 109 lines
// 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', 'Missing interface', '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);
        }
    }
}