[SNMP4J] Resent (full code now): Why is the USM a singleton ?

Sjoerd van Doorn sjoerdvandoorn at yahoo.com
Tue Mar 3 23:39:00 CET 2009



--- On Tue, 3/3/09, Sjoerd van Doorn <sjoerdvandoorn at yahoo.com> wrote:

From: Sjoerd van Doorn <sjoerdvandoorn at yahoo.com>
Subject: Why is the USM a singleton ?
To: "SNMP4j" <snmp4j at agentpp.org>
Date: Tuesday, March 3, 2009, 10:35 PM







Hello all,
 
I'm working on an issue and I suspect the fact that the USM is a singleton, is part of the reasons I'm having problems.
Can someone explain why not have an instance of the USM for every MPv3 instance ?
 
My problem is having timeouts, usmStatsNotInTime, usmUnknownEngineId and MessageException (1404) every now and then.
I'm in a network with 200+ elements and I already have seen that the autoritiveEngineId of the elements is not unique, however I cannot have them changed for my purpose (I am aware that this is against RFC 3414)
The issues show when in parallel (multithreaded) querying appr. 15 devices.(I'll post a snipped at the end of my mail.
 
I suspect the internal administration of the USM is broken due to the fact that the engineID is non-unique and that this is causing my errors.
 
After analysing the code for a couple of days and going through the previous posts, I can see more people are having these kind of problems, however I could not find any solution.
I'm thinking that a modification of the USM from a singleton to a instance per MPv3 could solve the problem, but I can't realy oversee why it is designed as a singleton from the beginning. 
 
Here is my code (executed by 15 threads in parallel in synchronous mode.
 
private final Snmp4jAgent _agent; 

private final String _requestType; 

protected SnmpCommand(Snmp4jAgent agent, String requestType){ 
  _agent = agent; 
_requestType = requestType; 
initSecurityModels(createUSM()); 
} 

protected void initSecurityModels( USM usm ){ 
SecurityModels.getInstance().addSecurityModel(usm); 
} 

protected USM createUSM(){ 
return new USM(SecurityProtocols.getInstance(), 
new OctetString(MPv3.createLocalEngineID()), 
0); 
} 

protected PDU createRequest(){ 
final PDU request = new ScopedPDU(); 
request.setType(PDU.getTypeFromString(_requestType)); 
request.setMaxRepetitions(15); 
request.setNonRepeaters(0); 
return request; 
} 

protected Target createTarget(){ 
final UserTarget target = new UserTarget(); 
target.setSecurityLevel(_agent.securityLevel); 
target.setSecurityName(_agent.securityName); 
target.setVersion(_agent.version); 
target.setAddress(_agent.udpAddress); 
target.setRetries(_agent.retries); 
target.setTimeout(_agent.timeoutInSeconds * 1000); 
return target; 
} 

protected Snmp createSnmp() throws IOException{ 
Snmp snmp = new Snmp(new DefaultUdpTransportMapping()); 
UsmUser user = new UsmUser(_agent.securityName, 
_agent.authProtocol, 
_agent.authPassphrase, 
_agent.privProtocol, 
_agent.privPassphrase); 
snmp.getUSM().addUser(_agent.securityName, user); 
return snmp; 
} 

public PDU execute() throws IOException{
Snmp snmp = null;

try{
snmp = createSnmp();
final List<VariableBinding> results = new ArrayList<VariableBinding>();
snmp.listen();
final PDU request = createRequest();
request.add(new VariableBinding(_oid));
final Target target = createTarget();
ResponseEvent responseEvent = snmp.send(request, target);
if (responseEvent.getPeerAddress() == null){
throw new IOException("No response received");
}
PDU response = responseEvent.getResponse();
if (response == null){
log.error("SNMP GetNextCommand :: response==null");
return null;
}
_agent.check(response);
VariableBinding binding = response.get(0);
OID checker = binding.getOid();
while (binding.getOid().leftMostCompare(_oid.size(), _oid) == 0){
results.add(binding);

request.set(0, new VariableBinding(binding.getOid()));
responseEvent = snmp.send(request, target);
response = responseEvent.getResponse();
if (response == null){
throw new IOException("Timeout occured");
}
binding = response.get(0);
// check oid duplicated ( last one ...
if (checker.equals(binding.getOid())){
// if there is only one remove the last one ... bogus
if (results.size() == 1){
results.clear();
}
log.debug("loopy checking the same");
break;
}
checker = binding.getOid();
}
response.clear();
for (int i = 0; i < results.size(); i++){
response.add((VariableBinding) results.get(i));
}

return response;
}
finally{
// always close the snmp connection
if (snmp != null){
snmp.close();
}
}
} 
 
 
 
 
 



      


More information about the SNMP4J mailing list