[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