Writing a Custom SNMP MIB
SNMP stands for Simple Network Management Protocol, which is an Internet-standard protocol for collecting and organizing information about managed devices on IP networks and for modifying that information to change device behavior. If you use SNMP in your organization, you probably have an SNMP collector to gather information on the status of devices in your network.
Since the NetBeez BeezKeeper is the central server for our network monitoring solution designed to provide an end-user experience view of your network, it would only make sense to be able to integrate it with your organization’s SNMP collector and receive any critical and performance alerts from your remote locations immediately, and be able to correlate them with other SNMP measurements/alerts.
Since NetBeez provides a new and unique view of your network, we had to create our own set of SNMP traps to accommodate our data model and the types of alerts generated by our product.
Writing Your Own 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 SNMP 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 shown in the diagram below (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, which are generated when a test on an agent is experiencing degraded performance or a failure. Both categories are grouped 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 }
Once all the entries and the sequence of entries (tables) are defined, we 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 }
This is the design we iteratively came up with. There may be some redundancies, or non-standard things in there, but this was all done by trial and error, and any feedback or discussion on this is always welcome.
Of course, SNMP works great if your organization is using SNMP as their primary way of looking into the status of network devices. Otherwise, you could also integrate the NetBeez BeezKeeper alerts using our Syslog integration.