[SNMP4J] SNMP Timeout seems to be incorrect

=??b?wfi9wrn8?= steve at nextdata.co.kr
Fri Dec 1 10:30:26 CET 2006


Hi
I have found that it seed to be incoorect when testing a very short timeout value.

Please test following code.
--------------------------------------------------------------------------------------------------

package snmpTest;

import org.snmp4j.*;
import org.snmp4j.smi.*;
import org.snmp4j.mp.*;
import org.snmp4j.event.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import java.util.Date;
import java.util.Vector;
import java.text.SimpleDateFormat;
import java.util.Hashtable;

/**
 * <p>Title: SNMP4J Test</p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2006</p>
 *
 * <p>Company: NEXT DATA SYSTEMS</p>
 *
 * @author Steve
 * @version 1.0
 */
public class ClassMain
{
  String agentIP;
  int    snmpVersion;

  public static void main(String args[])
  {
    try
    {
      ClassMain obj = new ClassMain(args[0]);

      if(args[1].equals("set"))
        obj.snmpSet(new String[]{args[2]}, Long.parseLong(args[3]));
      else if(args[1].equals("get"))
        obj.snmpGet(args[2], Long.parseLong(args[3]));
      else if(args[1].equals("getNext"))
        obj.snmpGetNext(args[2], Long.parseLong(args[3]));
      else if(args[2].equals("getBulk"))
        obj.snmpGetBulk(args[2], Long.parseLong(args[3]));
      else
        System.out.println("Cannot recognize command.");
    }
    catch(Exception e)
    {
      e.printStackTrace();
      System.out.println("ClassMain SNMPVersion:agentIP command description");
    }
  }

  public ClassMain(String uri) throws Exception
  {
    System.out.println("URI:"+uri);
    
    String[] nURI = uri.split(":");

    if(nURI[0].equals("SNMPv1"))
      snmpVersion = SnmpConstants.version1;
    else if(nURI[0].equals("SNMPv2c"))
      snmpVersion = SnmpConstants.version2c;
    else if(nURI[0].equals("SNMPv3"))
      snmpVersion = SnmpConstants.version3;
    else
      throw new IllegalArgumentException("URI parsing error");

    agentIP = nURI[1];
    System.out.println("SNMP version:"+snmpVersion);
  }

  public void doTraceLog(String log)
  {
      try
      {
          SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");

          System.out.print("[" + format.format(new Date()) + "]");
          System.out.println(log);
      }
      catch(Exception e)
      {
      }

  }
  
  public void snmpSet(String pdus[], long timeout)
  {
    try
    {
      MessageDispatcherImpl mdi = new MessageDispatcherImpl();
      
      mdi.addMessageProcessingModel(new MPv2c());
      Snmp snmp = new Snmp(mdi);
      CommunityTarget target = new CommunityTarget();
      IpAddress targetAddr = new IpAddress(agentIP);

      targetAddr.setValue(agentIP);

      target.setAddress(targetAddr);
      target.setRetries(2);
      target.setTimeout(timeout);
      target.setVersion(snmpVersion);

      PDU pdu = new PDU();
      pdu.setType(PDU.SET);

      for (int i = 0; i < pdus.length; i++) 
      {
        String          pduData[] = pdus[i].split(":"); 
        VariantVariable var = new VariantVariable(Variable.createFromSyntax(
            Integer.parseInt(pduData[1])));

        var.setValue(pduData[2]);
        pdu.add(new VariableBinding(new OID(pduData[0]), var));
      }

      ResponseEvent response = snmp.send(pdu, target);
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

  public void snmpGet(String oid, long timeout)
  {
    try
    {
      //MessageDispatcherImpl mdi = new MessageDispatcherImpl();

      //mdi.addMessageProcessingModel(new MPv2c());
      //Snmp snmp = new Snmp(mdi);
      TransportMapping transport = new DefaultUdpTransportMapping();
      
      transport.listen();
      
      Snmp snmp = new Snmp(transport);
      //Snmp snmp = new Snmp();
      
      snmp.setTimeoutModel(new AdvancedTimeoutModel(timeout));
      CommunityTarget target = new CommunityTarget();
      Address  targetAddress = GenericAddress.parse("udp:"+agentIP+"/161");
      target.setAddress(targetAddress);
      target.setRetries(0);
      target.setTimeout(timeout);
      target.setVersion(snmpVersion);
      target.setCommunity(new OctetString("public"));

      PDU pdu = new PDU();
      pdu.setType(PDU.GET);
      pdu.add(new VariableBinding(new OID(oid)));

      doTraceLog("SNMP GET Request: "+oid+", timeout:"+timeout);
      
      ResponseEvent response = snmp.send(pdu, target);
      
      doTraceLog("SNMP GET Response:"+response.getResponse());
    }
    catch(Exception e)
    {
      doTraceLog("Exception: "+e.getMessage());
      //e.printStackTrace();
    }
  }

  public void snmpGetNext(String oid, long timeout)
  {
    try
    {
      Snmp snmp = new Snmp();
      CommunityTarget target = new CommunityTarget();
      IpAddress targetAddr = new IpAddress(agentIP);
      
      targetAddr.setValue(agentIP);

      target.setAddress(targetAddr);
      target.setRetries(2);
      target.setTimeout(timeout);
      target.setVersion(snmpVersion);

      PDU pdu = new PDU();
      pdu.setType(PDU.GETNEXT);
      pdu.add(new VariableBinding(new OID(oid)));

      ResponseEvent response = snmp.send(pdu, target);
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

  public void snmpGetBulk(String desc, long timeout)
  {
    try
    {
      String snmpDesc[] = desc.split(":");
      String oid        = snmpDesc[0];
      int    maxRp      = Integer.parseInt(snmpDesc[1]);
      
      Snmp snmp = new Snmp();
      CommunityTarget target = new CommunityTarget();
      IpAddress targetAddr = new IpAddress(agentIP);

      targetAddr.setValue(agentIP);

      target.setAddress(targetAddr);
      target.setRetries(2);
      target.setTimeout(timeout);
      target.setVersion(snmpVersion);
      
      PDU pdu = new PDU();
      pdu.setType(PDU.GETNEXT);
      pdu.add(new VariableBinding(new OID(oid)));
      pdu.setMaxRepetitions(maxRp);

      ResponseEvent response = snmp.send(pdu, target);
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }
  
  private class AdvancedTimeoutModel implements TimeoutModel
  {
    private long retryTimeout;
    
    AdvancedTimeoutModel(long ioTimeout)
    {
      retryTimeout = ioTimeout;
    }
    
    public long getRequestTimeout(int nRetries, long timeout)
    {
      doTraceLog("get request timeout...");
      return retryTimeout;
    }
    
    public long getRetryTimeout(int nRetries, int totalRetries, long timeout)
    {
      doTraceLog("get retry timeout...");
      return 1;
    }
  }
}
------------------------------------------------------------------

test logs



D:\prj\SNMPTest>java -cp SNMPTest.jar;snmp4j.jar snmpTest.ClassMain SNMPv1:220.90.132.94 get 1.3.6.1.2.1.1.1.0 1
URI:SNMPv1:220.90.132.94
SNMP version:0
[2006/12/01 17:47:07.020]SNMP GET Request: 1.3.6.1.2.1.1.1.0, timeout:1
[2006/12/01 17:47:07.040]get retry timeout...
[2006/12/01 17:47:07.040]SNMP GET Response:RESPONSE[requestID=1669627258, errorStatus=Success(0), errorIndex=0, VBS[1.3.
6.1.2.1.1.1.0 = Foundry Networks, Inc. Router, IronWare Version 07.8.00aT53 Compiled on Oct 04 2004 at 16:42:07 labeled
as B2R07800a]]
------------------------------------------------------------------
I think this result caused by folling code of SNMP4j
------------------------------------------------------------------
    synchronized (syncResponse) {
      PduHandle handle;
      PendingRequest request;
      synchronized (sync) {
        handle = sendMessage(pdu, target, transport);
        request =
            new PendingRequest(handle, syncResponse, target, pdu, target,
                               transport);
        if (logger.isDebugEnabled()) {
          logger.debug("New pending request with handle " + handle);
        }
        pendingRequests.put(handle, request);
        long delay = timeoutModel.getRetryTimeout(0, target.getRetries(),
                                                  target.getTimeout());
        timer.schedule(request, delay);
      }
      try {
        syncResponse.wait();
        PendingRequest retryRequest =
            (PendingRequest) pendingRequests.remove(handle);
        if (retryRequest != null) {
          retryRequest.setFinished();
          retryRequest.cancel();
        }
        if (logger.isDebugEnabled()) {
          logger.debug("Removed pending request with handle: "+handle);
        }
        request.setFinished();
        request.cancel();
      }
      catch (InterruptedException iex) {
        logger.warn(iex);
        // ignore
      }
    }
--------------------------------------------------------------------
1. First of all it seemed to try send the SNMP pdu to the target synchronously.
2. And then run the code stuffs related to timer.

So during the first step the timeout will never happens.
Is this result intended to follow SNMP protocol specification?

If anyone have interests, please reply.

Thanks. 





More information about the SNMP4J mailing list