Search code examples
javasnmpsnmp4j

Sending table index in SNMP trap


I have implemented an SNMP agent using snmp4j, and am running into a bit of a snag with how to properly report SNMPv3 traps/notifications to an SNMP manager. The implementation is set up to manage a table of values indexed by instanceId. When you query the agent you receive the OIDs of the various fields suffixed by ".1", ".2", ".3", etc. based on the particular link instance associated with the OID value. So querying results in:

-----------------------------------------
| Entity  | OID          | Value        |
-----------------------------------------
| Link1   | linkAlias.1  | Link 1       |
| Link2   | linkAlias.2  | Link 2       |
| Link1   | linkState.1  | 1            |
| Link2   | linkState.2  | 3            |
| Link1   | linkText.1   | UP           |
| Link2   | linkText.2   | INITIALIZING |
-----------------------------------------

That works great. However, I need to be able to send traps in a similar way so that the index of the table is sent with the trap. That way alarms triggered from SNMP queries can be cleared when the link status changes I tried simply adding the instanceId as a varbind as seen below in my code block, but the entity is always reported as the generic "Link". Has anyone encountered this that could help me solve this? Anything is appreciated greatly.

public static void updateLinkStatus(int instanceId, LinkState status) 
{   
    boolean varChanged = false;

    Variable[] currentManagedObject = currentManagedObjects.get(instanceId);
    if(currentManagedObject != null)
    {
        // If we are managing this object
        if(((Integer32)currentManagedObject[1]).toInt() != status.value)
            varChanged = true;

        // Update the managed object Status Integer and Status Text
        currentManagedObject[1] = new Integer32(status.value);
        currentManagedObject[2] = new OctetString(status.getLinkStateText());
    }
    else 
    {
        varChanged = true; // No previous record to check against
    }

    // Send trap now if not equal to previous value
    if(varChanged)
    {
        OID trapOid = null;
        int linkState = LinkState.UNKNOWN.value; // Will be overridden
        String linkStateText = null;

        if(status == LinkState.DOWN)
        {
            trapOid = oidLinkDown;
            linkState = LinkState.DOWN.value;
            linkStateText = LnkState.DOWN.getLinkStateText();
        }
        else if(status == LinkState.MISCONFIGURED)
        {
            trapOid = oidLinkMisconfigured;
            linkState = LinkState.MISCONFIGURED.value;
            linkStateText = LinkState.MISCONFIGURED.getLinkStateText();
        }
        else if(status == LinkState.UP)
        {
            trapOid = oidLinkUp;
            linkState = LinkState.UP.value;
            linkStateText = LinkState.UP.getLinkStateText();
        }
        else if(status == LinkState.INITIALIZING)
        {
            trapOid = oidLinkInitializing;
            linkState = LinkState.INITIALIZING.value;
            linkStateText = LinkState.INITIALIZING.getLinkStateText();
        }
        else
        {
            // Theoretically, should never change to LinkState.UNKNOWN - no trap available for it
            linkState = LinkState.UNKNOWN.value;
            linkStateText = LinkState.UNKNOWN.getLinkStateText();
        }

        // Create variable bindings for V3 trap
        if(trapOid != null)
        {
            List<VariableBinding> variableBindings = new ArrayList<VariableBinding>();
            variableBindings.add(new VariableBinding(oidLinkState, new Integer32(linkState)));
            variableBindings.add(new VariableBinding(oidLinkText, new OctetString(linkStateText)));
            variableBindings.add(new VariableBinding(oidLinkInstanceID, new Integer32(instanceId)));
            //I've tried the below varbind too and it also doesn't work
            //variableBindings.add(new VariableBinding(new OID(oidLinkInstanceID.toIntArray(), instanceId)));
            agent.sendTrap_Version3(trapOid, variableBindings);
        }
    }
}

Edit:

Note: The links are dynamically configurable so I cannot simply define each link with a separate OID; I define the base OID in the MIB and need to add the index dynamically.


Solution

  • I discovered the solution. I attempted to simply add the instance index to the OID and send a NULLOBJ as the value in the varbind like so:

    variableBindings.add(new VariableBinding(new OID(oidLinkInstanceID.toIntArray(), instanceId)));
    

    But the manager rejected the message. So I added the instance index to the OID as well as the varbind value like so:

    variableBindings.add(new VariableBinding(new OID(oidLinkInstanceID.toIntArray(), instanceId), new Integer32(instanceId)));
    

    And the manager reports the entity as Link1, Link2, etc. consistent with the SNMP table.