Skip to content

Commit

Permalink
Merge pull request #1408 from shanemadden/ciscobgp
Browse files Browse the repository at this point in the history
Add ciscobgp snmp collector
  • Loading branch information
shanemadden committed Oct 22, 2015
2 parents 2d2ba70 + 0ac6bbe commit 89a91ec
Show file tree
Hide file tree
Showing 2 changed files with 226 additions and 1 deletion.
2 changes: 1 addition & 1 deletion cmd/scollector/collectors/snmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"bosun.org/opentsdb"
)

var builtInSNMPs = map[string]func(cfg conf.SNMP){"ifaces": SNMPIfaces, "cisco": SNMPCisco, "bridge": SNMPBridge, "ips": SNMPIPAddresses}
var builtInSNMPs = map[string]func(cfg conf.SNMP){"ifaces": SNMPIfaces, "cisco": SNMPCisco, "bridge": SNMPBridge, "ips": SNMPIPAddresses, "ciscobgp": SNMPCiscoBGP}

func SNMP(cfg conf.SNMP, mibs map[string]conf.MIB) error {
if cfg.Host == "" {
Expand Down
225 changes: 225 additions & 0 deletions cmd/scollector/collectors/snmp_ciscobgp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package collectors

import (
"fmt"
"io"
"strings"
"time"

"bosun.org/_third_party/github.com/mjibson/snmp"
"bosun.org/cmd/scollector/conf"
"bosun.org/metadata"
"bosun.org/opentsdb"
)

func SNMPCiscoBGP(cfg conf.SNMP) {
collectors = append(collectors, &IntervalCollector{
F: func() (opentsdb.MultiDataPoint, error) {
return c_snmp_ciscobgp(cfg.Community, cfg.Host)
},
Interval: time.Second * 30,
name: fmt.Sprintf("snmp-ciscobgp-%s", cfg.Host),
})
}

func c_snmp_ciscobgp(community, host string) (opentsdb.MultiDataPoint, error) {
const (
state = ".1.3.6.1.4.1.9.9.187.1.2.5.1.3.1.4"
adminStatus = ".1.3.6.1.4.1.9.9.187.1.2.5.1.4.1.4"
localAS = ".1.3.6.1.4.1.9.9.187.1.2.5.1.8.1.4"
localIdentifier = ".1.3.6.1.4.1.9.9.187.1.2.5.1.9.1.4"
remoteAS = ".1.3.6.1.4.1.9.9.187.1.2.5.1.11.1.4"
remoteIdentifier = ".1.3.6.1.4.1.9.9.187.1.2.5.1.12.1.4"
inUpdates = ".1.3.6.1.4.1.9.9.187.1.2.5.1.13.1.4"
outUpdates = ".1.3.6.1.4.1.9.9.187.1.2.5.1.14.1.4"
inTotalMessages = ".1.3.6.1.4.1.9.9.187.1.2.5.1.15.1.4"
outTotalMessages = ".1.3.6.1.4.1.9.9.187.1.2.5.1.16.1.4"
inUpdateElapsedTime = ".1.3.6.1.4.1.9.9.187.1.2.5.1.27.1.4"
acceptedPrefixes = ".1.3.6.1.4.1.9.9.187.1.2.8.1.1.1.4"
deniedPrefixes = ".1.3.6.1.4.1.9.9.187.1.2.8.1.2.1.4"
advertisedPrefixes = ".1.3.6.1.4.1.9.9.187.1.2.8.1.6.1.4"
suppressedPrefixes = ".1.3.6.1.4.1.9.9.187.1.2.8.1.7.1.4"
withdrawnPrefixes = ".1.3.6.1.4.1.9.9.187.1.2.8.1.8.1.4"

bgpPeerState = "bgp.peer.state"
bgpPeerAdminStatus = "bgp.peer.admin_status"
bgpPeerInUpdates = "bgp.peer.updates.in"
bgpPeerOutUpdates = "bgp.peer.updates.out"
bgpPeerInTotalMessages = "bgp.peer.messages.in"
bgpPeerOutTotalMessages = "bgp.peer.messages.out"
bgpPeerInUpdateElapsedTime = "bgp.peer.update_elapsed.in"
bgpPeerAcceptedPrefixes = "bgp.peer.prefixes.accepted"
bgpPeerDeniedPrefixes = "bgp.peer.prefixes.denied"
bgpPeerAdvertisedPrefixes = "bgp.peer.prefixes.advertised"
bgpPeerSuppressedPrefixes = "bgp.peer.prefixes.suppressed"
bgpPeerWithdrawnPrefixes = "bgp.peer.prefixes.withdrawn"

bgpPeerStateDesc = "The state of the peer. 1:idle 2:connect 3:active 4:opensent 5:openconfirm 6:established"
bgpPeerAdminStatusDesc = "The admin status of the peer connection 1:stop 2:start"
bgpPeerInUpdatesDesc = "The number of updates received from the peer in the current session"
bgpPeerOutUpdatesDesc = "The number of updates sent to the peer in the current session"
bgpPeerInTotalMessagesDesc = "The number of total messages received from the peer in the current session"
bgpPeerOutTotalMessagesDesc = "The number of total messages sent to the peer in the current session"
bgpPeerInUpdateElapsedTimeDesc = "The amount of time since the last update from the peer"
bgpPeerAcceptedPrefixesDesc = "The number of prefixes accepted from the peer"
bgpPeerDeniedPrefixesDesc = "The number of prefixes from the peer that were denied this session"
bgpPeerAdvertisedPrefixesDesc = "The number of prefixes that have been advertised to the peer this session"
bgpPeerSuppressedPrefixesDesc = "The number of prefixes that have been suppressed from sending to the peer this session"
bgpPeerWithdrawnPrefixesDesc = "The number of prefixes that the local node has withdrawn from the peer this session"
)
// Tag: local_as
localASesRaw, err := snmp_ip_tree(host, community, localAS)
if err != nil {
return nil, err
}
localASes := make(map[string]string, len(localASesRaw))
for k, v := range localASesRaw {
s := fmt.Sprint(v)
localASes[k] = s
}

// Tag: local_id
localIdentifiersRaw, err := snmp_ip_tree(host, community, localIdentifier)
if err != nil {
return nil, err
}
localIdentifiers := make(map[string]string, len(localIdentifiersRaw))
for k, v := range localIdentifiersRaw {
if uv, ok := v.([]uint8); ok {
localIdentifiers[k] = snmp_combine_ip_uint8(uv)
} else {
return nil, fmt.Errorf("Bad IP address data in local identifier for peer %q on host %q", k, host)
}
}

// Tag: remote_as
remoteASesRaw, err := snmp_ip_tree(host, community, remoteAS)
if err != nil {
return nil, err
}
remoteASes := make(map[string]string, len(remoteASesRaw))
for k, v := range remoteASesRaw {
s := fmt.Sprint(v)
remoteASes[k] = s
}

// Tag: remote_id
remoteIdentifiersRaw, err := snmp_ip_tree(host, community, remoteIdentifier)
if err != nil {
return nil, err
}
remoteIdentifiers := make(map[string]string, len(remoteIdentifiersRaw))
for k, v := range remoteIdentifiersRaw {
if uv, ok := v.([]uint8); ok {
remoteIdentifiers[k] = snmp_combine_ip_uint8(uv)
} else {
return nil, fmt.Errorf("Bad IP address data in remote identifier for peer %q on host %q", k, host)
}
}

var md opentsdb.MultiDataPoint

type bgpAdd struct {
oid string
metric string
rate metadata.RateType
unit metadata.Unit
desc string
}

// Function to harvest all metrics with the tag groups above
add := func(bA bgpAdd) error {
m, err := snmp_ip_tree(host, community, bA.oid)
if err != nil {
return err
}
for k, v := range m {
_, localASok := localASes[k]
_, localIdentifierok := localIdentifiers[k]
_, remoteASok := remoteASes[k]
_, remoteIdentifierok := remoteIdentifiers[k]
if localASok && localIdentifierok && remoteASok && remoteIdentifierok {
tags := opentsdb.TagSet{
"host": host,
"peer": k,
"local_as": localASes[k],
"local_id": localIdentifiers[k],
"remote_as": remoteASes[k],
"remote_id": remoteIdentifiers[k],
}
Add(&md, bA.metric, v, tags, bA.rate, bA.unit, bA.desc)
} else {
return fmt.Errorf("Missing tag data for peer %q on host %q", k, host)
}
}
return nil
}
// oid, metric, rate, unit, description
oids := []bgpAdd{
{state, bgpPeerState, metadata.Gauge, metadata.StatusCode, bgpPeerStateDesc},
{adminStatus, bgpPeerAdminStatus, metadata.Gauge, metadata.StatusCode, bgpPeerAdminStatusDesc},
{inUpdates, bgpPeerInUpdates, metadata.Counter, metadata.Packet, bgpPeerInUpdatesDesc},
{outUpdates, bgpPeerOutUpdates, metadata.Counter, metadata.Packet, bgpPeerOutUpdatesDesc},
{inTotalMessages, bgpPeerInTotalMessages, metadata.Counter, metadata.Packet, bgpPeerInTotalMessagesDesc},
{outTotalMessages, bgpPeerOutTotalMessages, metadata.Counter, metadata.Packet, bgpPeerOutTotalMessagesDesc},
{inUpdateElapsedTime, bgpPeerInUpdateElapsedTime, metadata.Gauge, metadata.Second, bgpPeerInUpdateElapsedTimeDesc},
{acceptedPrefixes, bgpPeerAcceptedPrefixes, metadata.Gauge, metadata.Count, bgpPeerAcceptedPrefixesDesc},
{deniedPrefixes, bgpPeerDeniedPrefixes, metadata.Counter, metadata.Count, bgpPeerDeniedPrefixesDesc},
{advertisedPrefixes, bgpPeerAdvertisedPrefixes, metadata.Counter, metadata.Count, bgpPeerAdvertisedPrefixesDesc},
{suppressedPrefixes, bgpPeerSuppressedPrefixes, metadata.Counter, metadata.Count, bgpPeerSuppressedPrefixesDesc},
{withdrawnPrefixes, bgpPeerWithdrawnPrefixes, metadata.Counter, metadata.Count, bgpPeerWithdrawnPrefixesDesc},
}
for _, bA := range oids {
if err := add(bA); err != nil {
return nil, err
}
}
return md, nil
}

func snmp_ip_tree(host, community, oid string) (map[string]interface{}, error) {
rows, err := snmp.Walk(host, community, oid)
if err != nil {
return nil, err
}
m := make(map[string]interface{})
for rows.Next() {
key := ""
var a interface{}
id, err := rows.Scan(&a)
if err != nil {
return nil, err
}
switch t := id.(type) {
case []int:
key = snmp_combine_ip_int(t)
default:
return nil, fmt.Errorf("Got wrong type from OID check")
}
m[key] = a
}
if err := rows.Err(); err != nil && err != io.EOF {
return nil, err
}
return m, nil
}

func snmp_combine_ip_uint8(path []uint8) string {
s := make([]string, len(path))
for i := range path {
s[i] = fmt.Sprint(path[i])
}
// In some cases there's a .1.1 after the IP (because SNMP is awesome), drop it:
s = s[:4]
return strings.Join(s, ".")
}

func snmp_combine_ip_int(path []int) string {
s := make([]string, len(path))
for i := range path {
s[i] = fmt.Sprint(path[i])
}
// In some cases there's a .1.1 after the IP (because SNMP is awesome), drop it:
s = s[:4]
return strings.Join(s, ".")
}

0 comments on commit 89a91ec

Please sign in to comment.