Creating Software to Ease the Management Task
Using Java DMK, we can create software that both listens for events and proactively reads the device status. Here I focus on the latter, just to illustrate the principles.
To begin with, I’ll write a simple program that looks at a specific network link and tries to determine if it’s prone to congestion. We do this by sampling and averaging some SNMP counters on an interface at one end of this link. These are standard objects that are maintained by the SNMP entity running on the device. Sometimes, the SNMP entity is not running by default—in this case, I’ll assume the network manager (i.e., your predecessor!) has chosen to run SNMP on all of those devices where it is available. Let’s now describe the simple requirements for the code.
Our Selected Set of Management Requirements
We want to create some software that fulfils the following simple requirements:
- Return the operational status of a specified interface.
- Calculate the traffic level for a specified interface.
- Determine if a specified link is approaching a state of congestion.
An interface usually has an administrative state and an operational state. The administrative state is the one desired by the network manager—"I want this interface to be up." The operational state is the actual state of the interface. Try to think about the operational state as the network’s response to the requested state. If the administrative state is up and the operational state is down, then we know there’s a problem.
The interface type I’ll be using is Ethernet, specifically 10Mbps (or 10,000,000 bps). I’ll be retrieving a snapshot of the count of incoming bits received at an interface at one end of Link 1 in Figure 1. This will give us an instantaneous picture of the inward traffic level at that interface. Then, we’ll wait a bit and retrieve the same counter value. The difference between these two values gives us the required utilization value. Let’s have a look at some source code now.
The Source Code
The Java class I use is called RequestData. It contains a main() method and makes use of the following Java DMK resources (among others):
import com.sun.management.snmp.SnmpDefinitions; import com.sun.management.snmp.SnmpOid; import com.sun.management.snmp.SnmpVarBindList; import com.sun.management.snmp.manager.SnmpPeer;
To begin with, I initialize the SNMP Manager API. This allows us to access the generated table mentioned in the introduction.
final SnmpOidTableSupport oidTable = new RFC1213_MIBOidTable(); SnmpOid.setSnmpOidTable(oidTable);
Next, I create an SnmpPeer object. This represents the entity with which we will communicate. Note that this uses the port passed in as a command-line parameter.
final SnmpPeer agent = new SnmpPeer(host, Integer.parseInt(port));
We must now create a communications session with the remote entity. This requires us to specify SNMP community strings. These data elements are then associated with the agent.
final SnmpParameters params = new SnmpParameters("public", "private"); agent.setParams(params);
We’re nearly there! We now have to build the session to manage the data request and then we’re ready to create the data request list (or variable binding list):
final SnmpSession session = new SnmpSession("SyncManager session"); session.setDefaultPeer(agent); final SnmpVarBindList list = new SnmpVarBindList( "SyncManager varbind list");
The program is a single Java DMK class that builds an SNMP request message. This message specifies four objects of interest, using the following code:
// A description of the host device list.addVarBind("sysDescr.0"); // The operational state of interface 1 list.addVarBind("ifOperStatus.1"); // The number of incoming octets on interface 1 list.addVarBind("ifInOctets.1"); // The speed of interface 1 list.addVarBind("ifSpeed.1");
Our four required objects are packed into an SNMP getRequest message and sent to the receiving entity as follows:
SnmpRequest request = session.snmpGetRequest(null, list);
We now retrieve the same set of objects twice; the difference in time between the samples is found using this Java code:
// Calculate the time between messages long oldTime = date1.getTime(); long newTime = new Date().getTime(); long elapsed = (newTime - oldTime) / MS_DIVIDEND; println("Elapsed time in seconds " + elapsed);
In this section, we get the most recent time and subtract a time value recorded just before the first retrieval. This gives us a rough estimate of the elapsed time between the data samples.
When the returned data is displayed, we see the following major elements:
Value : 25625, Object ID : 220.127.116.11.18.104.22.168.1.5.1 (Syntax : Gauge32) Value : 10000000 >> Press Enter to resend the request. Elapsed time in seconds 16 Value : 26005, Object ID : 22.214.171.124.126.96.36.199.1.5.1 (Syntax : Gauge32) Value : 10000000
The three bold data items above represent the two values of the ifInOctets object taken at an interval of 16 seconds. The selected interface (which supports a speed of 10,000,000 bps) has received 25,625 octets (or bytes) at the time T1 and 26,005 octets at the time T2. To determine the incoming link utilization, we apply the following formula:
Incoming Link % Utilization = ((T2 octets - T1 octets) * 8 * 100) / (ifSpeed * Sample speed)
Plugging in the values above gives us a utilization of (26005 - 25625) * 8 * 100/(10,000,000 * 16), or 0.0019 percent.
Clearly, the interface is very lightly loaded on the incoming side! A similar measurement can be made for the outgoing direction (using the ifOutOctets object instead). Then, both values can be summed to determine the overall loading. Obviously, care is required in drawing any conclusions from the figures (they are instantaneous snapshots of data that can change rapidly), but they do provide some minimal level of understanding of the loading on the interface.
Plying this program with diligence and observing loading trends over a period of a day might lead us to understand why the outgoing network manager made the comment concerning Link 1. In any case, it means that you are beginning to learn about the secrets that the network holds in store! Extending this approach to other regions of the network should help in acquiring a broader understanding again.
Running the Example
To run the example program, you’ll need to install Java DMK. Free evaluation copies can be downloaded from Sun Microsystems, though these copies expire after 90 days. So don’t be too leisurely about running this code! Alternatively, if you win a couple of lotteries, you might be tempted to purchase Java DMK.
In either case, just follow the instructions in the examples\current\Snmp\Manager\ReadMe file, and the example should compile and run successfully. I used Java DMK version 5.1. Also, there’s detail and further Java examples in my book, Network Management, MIBs & MPLS: Principles, Design, & Implementation—no lottery win required!
Remember: Use Patterns
I strongly encourage using the adapter pattern to hide the complexity of the Java DMK API. Really, Java DMK isn’t complex per se, but it is proprietary. For this reason, it’s important to not litter your application code with calls into such an API. The adapter provides a useful model for achieving this noble design aim.
The adapter serves to insulate the application code from the details of the Java DMK (or other) technology. Your code then calls into the adapter, rather than directly using the Java DMK interface. So, if you later decide to change from Java DMK and use another technology, any required changes to your code will have been minimized ahead of time.
Further details on the adapter pattern and its applications can be found in design pattern books, such as O’Reilly’s Head First Design Patterns.