SNMP Get from IONIX ASL

The IONIX management domains use SNMP extensively for discovery and polling - using highly optimised intelligent mechanisms that result in polls being performed "as required" and bundled into the smallest number of packets possible. Hooking into these mechanisms is really quite complex, but there are simplified interfaces that allow you to use SNMP "get" logic in an ASL script. My target for this posting is to introduce this latter, simplified SNMP interface.

The basics

The first step is to create an instance of the ACT_SNMP class. The name of the class (the first argument in the "create()" call) is a fixed string, but the object name (the second argument) can be any name you like provided it doesnt clash with the name of anything else (including systems) in the repository. Generally it's an accepted convention to prepend the class name (or a derivative of it) to the front of the name. Here's a possible example..

snmp = create( "ACT_SNMP", "ACT_SNMP-my-snmp");

If you are planning to use SNMP gets from multiple threads (maybe: during discovery), then make sure that you give each thread it's own instance of the ACT_SNMP class. You can use the "thread()" function to salt the object name, like this..

snmp = create( "ACT_SNMP", "ACT_SNMP-my-snmp-".thread());

Once created, the object's internal thread has to be started. The convention normally used in the standard ASL scripts that come with the product is to attempt a "stop" before trying a "start", but to ignore any errors that the stop attempt may throw. The code looks something like this..

timeout = 2000;  // in milli-seconds
retries = 3;
snmp->stop()?IGNORE;
snmp->start(timeout, retries);

A possibly more efficient way of achieving the same thing (though the as-delivered ASLs dont use this) would be to call "start" only if the object's thread isnt already started. The disadvantage of this approach is that the timeout and retries arent modified if the object was already started.

if (!snmp->started) { snmp->start(timeout, retries); }

Now the object is ready for use, and we can start to retrieve SNMP data using it. In order to do this, we need ..

  • a reference to the topology manager object
  • an object reference to the SNMPAgent for the system we are going to query.
  • the OID of the MIB variable we want to collect.

Here's a simple example that collects the value for the "sysUpTime" OID in the MIB, using the ACT_SNMP object handle stored in "snmp" - as created above..

system = object( "Router", "gw1");
agent = system->getSNMPAgent();
oid = ".1.3.6.1.2.1.1.3.0";
tm = object("ICF-TopologyManager");
result = tm->snmpActGet(snmp, agent, oid);
print(result);

What this example will show is that the result is returned as an array of three values, and the output of out script looks something like this when run..

{ .1.3.6.1.2.1.1.3.0, smiTimeTicks, 3930575776 }

The first field in the list is the OID of the returned data (which is the same as the one we requested), the second one identifies the type of the returned value, and the third field is the value itself. So you could access the value like this..

print("sysUpTime = ".result[2]);

Possible values for the type (result[1]) are..

smiBitString, smiCounter32,   smiCounter64
smiGauge32,   smiInteger32,   smiIpAddress
smiNull,      smiOctetString, smiOid
smiOpaque,    smiTimeTicks,   smiUnsigned32

Error handling

if the OID we are trying to get isnt populated in the device's MIB, then the "snmpActGet" call will throw an error, and the script will stop at that point, so we need some way to ensure that the error is trapped and identified in a more intellegent way. The suggested approach is as follows..

result = list( "", "error", "" );
result = tm->snmpActGet(snmp, agent, oid)?IGNORE;
if (result[1] == "error") {
    print( "Attempt to get ".oid." failed");
}

The reason that this logic works is that the "?IGNORE" flag at the end of the second line means that the entire line is skipped if the attempt to execute it fails. No error is report in the logs, and the value previously placed in "result" is unchanged. Sadly, it isnt possible to know why the call failed.

Using getNext instead

The opertion "snmpActGetNext" provides a potentially useful variation on the "snmpActGet" operation. Rather than returning the specified oid value, it returns the next oid in the MIB - the one immediately after the one requested. The first field of the return now contains the actual OID returned.

Addendum - working with SAM or OI

The above approach works for IP AM/PM.

Please see "SNMP Get from ASL in OI or SAM" for a slightly different approach that works in SAM or OI.

Scroll to Top