How We Wrote Our Own SNMP MIB for BeezKeeper

SNMP and MIB

SNMP (Simple Network Management Protocol) is an Internet-standard protocol used to:

  1. collect and organize information about managed devices on IP networks,
  2. modify that information,
  3. change device behavior.

If your organization has a network monitoring tools, chances are that it’s an SNMP collector. The collector gathers information on the status and performance of network devices. That information is organized and defined via an SNMP MIB. A MIB (Management Information Base) is like a dictionary file that catalogs available information records.

SNMP

An example with the NetBeez MIB

NetBeez is a network monitoring solution designed to provide an end-user experience view of an enterprise network. As a network monitoring tool, NetBeez generates alerts. These alerts can be encoded in SNMP format so NetBeez users can integrate the tool with other SNMP collectors, such as SolarWinds.  The integration with other SNMP collectors enables correlating events from multiple tools to find the root cause.

Since NetBeez provides a new and unique view of your network, we had to create our own MIB. This MIB defines the actual SNMP traps that are generated by our product. The MIB definition file needs to be imported in the SNMP collector that will process the NetBeez traps. You can download and view the NetBeez MIB if you wish to.

Writing Your Own SNMP MIB: Procedure

The first step in writing our own SNMP MIB was to get our Private Enterprise Number (PEN). This number represents the root OID of an organization. For NetBeez, this is 1.3.6.1.4.1.44523, which translates to:

iso.org.dod.internet.private.enterprises.netbeez

And it should be the first declaration in our MIB:

netbeez MODULE-IDENTITY
     LAST-UPDATED "201704200000Z"
     ORGANIZATION "NetBeez, Inc."
     CONTACT-INFO
        "NetBeez, Inc.
        netbeez.net

        Postal: NetBeez, Inc.
        5124B Penn Avenue
        Pittsburgh, PA 15224
        USA

        Phone: +1 844-NET-BEEZ
        EMail: support@netbeez.net"

     DESCRIPTION
        "This MIB contains definition of the SNMP Traps
        associated to alerts sent by the NetBeez BeezKeeper"

     REVISION
        "201704200000Z"

     DESCRIPTION
        "First revision that includes only the alerts subtree"

  ::= { enterprises 44523 }


The next step was to create a hierarchy of the objects that made sense to include in our MIB. First, we decided to create a child object right under the enterprise OID for the specific product: BeezKeeper.

beezKeeperMIB   OBJECT IDENTIFIER ::= { netbeez 1 }

Everything else is rooted under this OID as you can see in the below diagram (generated using MIB Browser):

OID diagram


Since we wanted to include all the alerts generated by our system, we split them in two categories. The first one is agent device alerts to represent alerts such as reachability and wireless interface up/down alerts. The second one is test alerts. Network monitoring agents trigger alerts when a test experiencing degraded performance or a failure. Both categories are present under the nbAlerts group:

nbAlerts       OBJECT IDENTIFIER ::= { beezKeeperMIB 1 }

beezAlerts  OBJECT IDENTIFIER ::= { nbAlerts 1 }
testAlerts OBJECT IDENTIFIER ::= { nbAlerts 2 }

We then decided to include two table objects that will hold a SEQUENCE of the alert records for the two alert types: beezStatusAlerts and the testStatusAlerts. Doing it at this layer of the hierarchy gives us the ability to add more alert types if we need them in the future.

Here is the beezAlertsTable object:

beezStatusAlertTable    OBJECT-TYPE
  SYNTAX    SEQUENCE OF BeezStatusAlertEntry
  MAX-ACCESS not-accessible
  STATUS    current
  DESCRIPTION
    "This is the data structure associated to
    alerts triggered by the NetBeez BeezKeeper."
  ::= { beezAlerts 1 }

Then for each of the tables, you have to define the entries that go in that table. Here is the beezStatusAlertEntry which is of type BeezStatusAlertEntry:

beezStatusAlertEntry    OBJECT-TYPE
  SYNTAX    BeezStatusAlertEntry
  MAX-ACCESS not-accessible
  STATUS    current
  DESCRIPTION
    "This is the data structure associated to
    alerts triggered by the NetBeez BeezKeeper."
  INDEX  { beezAlertID }
  ::= { beezStatusAlertTable 1 }

BeezStatusAlertEntry   ::= SEQUENCE   {
  beezAlertID       Integer32,
  beezAlertType     INTEGER,
  beezAlertSeverity INTEGER,
  beezSourceAlertID  INTEGER,
  beezAlertTimestamp OCTET STRING,
  beezName      OCTET STRING,
  beezID       INTEGER,
  beezAlertMessage   OCTET STRING
  }

Then for each sequence, we had to define each of the objects that comprise it. Here’s just the first two for the BeezStatusAlertEntry:

beezAlertID OBJECT-TYPE
  SYNTAX    Integer32(0..127)
  MAX-ACCESS read-only
  STATUS    current
  DESCRIPTION
    "The alert ID of the alert being sent; this
    number can be used to correlate cleared alerts
    with raised ones."
  ::= { beezStatusAlertEntry 1 }

beezAlertType  OBJECT-TYPE
  SYNTAX    INTEGER {
     beezReachabilityAlert (1),
     beez80211 (2)
  }
  MAX-ACCESS read-only
  STATUS    current
  DESCRIPTION
    "The alert ID of the alert being sent; this
    number can be used to correlate cleared alerts
    with raised ones."
  ::= { beezStatusAlertEntry 2 }

MIB Notifications

We first defined all the entries and the sequence of entries (tables). We the defined the notifications, which represent the messages sent from the NetBeez server to your trap collector. You have to group them under a separate notifications group:

nbAlertNotifications    OBJECT IDENTIFIER ::= { beezKeeperMIB 0 }

nbAlertNotificationsGroup NOTIFICATION-GROUP
   NOTIFICATIONS { beezAlertNotification, testAlertNotification }
   STATUS        current
   DESCRIPTION
      "The basic notifications implemented by an SNMP entity
       supporting command responder applications."
   ::= { nbGroups 3 }

Inside this group, you can describe the NOTIFICATION-TYPE messages. These messages are also sequences of attribute objects, referencing the attributes we defined earlier:

-- Notification types:

beezAlertNotification NOTIFICATION-TYPE
     OBJECTS { beezAlertID, beezAlertType, beezSourceAlertID, beezAlertTimestamp, beezName, beezID, beezAlertMessage, beezAlertSeverity }
     STATUS       current
     DESCRIPTION
         "A notification about a change in the alert status of a beez agent."
     ::= { nbAlertNotifications 1 }

testAlertNotification NOTIFICATION-TYPE
     OBJECTS { testAlertID, testType, testAlertSeverity, testSourceAlertID, testAlertTimestamp, testBeezName, testBeezID, testTargetName, testAlertMessage, testTargetDisplayName }
     STATUS       current
     DESCRIPTION
         "A notification about a change in the alert status of a monitoring test."
     ::= { nbAlertNotifications 2 }

Conclusion

I have to admit that writing our own MIB was not a simple task. However, with trial and some errors, we were able to build a MIB. If you are currently only using an SNMP poller for monitoring the network status, consider integrating NetBeez to gather the end-user perspective. After all, there’s a NetBeez MIB for integrating them!

decoration image

Get your free trial now

Monitor your network from the user perspective

You can share

Twitter Linkedin Facebook

Let's keep in touch

decoration image