SNMP and MIB
SNMP (Simple Network Management Protocol) is an Internet-standard protocol used to:
- collect and organize information about managed devices on IP networks,
- modify that information,
- 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.
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):
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!