Hello
I’m using SNMP4j 2.8.18 to perform multi-threaded OID queries on different SNMPv3 devices, with different security name, authentication and privacy settings.
I use ScheduledExecutorService to execute the SNMPv3 OID query method as follows:
SubTreeRunnerV3 sub1 = new SubTreeRunnerV3("192.168.1.1", SecurityLevel.AUTH_PRIV, "account1", "passwd1", AuthMD5.ID, "passwd1", PrivAES128.ID, oids);
//sub2 ~ sub7 omitted
executor.scheduleAtFixedRate(sub1, 1, 10, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(sub2, 2, 10, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(sub3, 3, 10, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(sub4, 4, 10, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(sub5, 5, 10, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(sub6, 6, 10, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(sub7, 7, 10, TimeUnit.SECONDS);
This works fine with a 10-second execution interval. However, when I change the interval to 1 second, the OID responses fail to return successfully from all devices. Only 1 or 2 threads continue working, while the others display timeout error messages.
Here is my code for the SNMPv3 OID query:
public SubTreeRunnerV3(String host, int securityLevel, String userName, String authPwd, OID authProtocol, String privPwd, OID privProtocol, List<String> oidList) {
this.host = host;
this.securityLevel = securityLevel;
this.userName = userName;
this.authPwd = authPwd;
this.authProtocol = authProtocol;
this.privPwd = privPwd;
this.privProtocol = privProtocol;
this.oidList = oidList;
}
public void run() {
logKey = "[" + host + "]: ";
Thread.currentThread().setName("SNMPv3-" + host);
try {
TransportMapping transport = new DefaultUdpTransportMapping();
transport.listen();
Snmp snmp = new Snmp(transport);
OctetString engineId = new OctetString(MPv3.createLocalEngineID());
USM usm = new USM(SecurityProtocols.getInstance(), engineId, 0);
SecurityModels.getInstance().addSecurityModel(usm);
System.out.println(logKey + "EngineId: " + engineId.toString());
UsmUser user = null;
switch (securityLevel) {
case SecurityLevel.NOAUTH_NOPRIV:
user = new UsmUser(new OctetString(userName),
null,
null,
null,
null);
break;
case SecurityLevel.AUTH_NOPRIV:
user = new UsmUser(new OctetString(userName),
authProtocol,
new OctetString(authPwd),
null,
null);
break;
case SecurityLevel.AUTH_PRIV:
user = new UsmUser(new OctetString(userName),
authProtocol,
new OctetString(authPwd),
privProtocol,
new OctetString(privPwd));
break;
default :
System.out.println("Unkown Security level");
}//end switch securityLevel
// add user to the USM
snmp.getUSM().addUser(new OctetString(userName), user);
// create the target
UserTarget target = new UserTarget();
target.setAddress(GenericAddress.parse("udp:" + host + "/" + port));
target.setRetries(retry);
target.setTimeout(timeout);
target.setVersion(SnmpConstants.version3);
target.setSecurityLevel(securityLevel);
target.setSecurityName(new OctetString(userName));
int responseCount = 0;
TreeUtils treeUtils = new TreeUtils(snmp, new DefaultPDUFactory(PDU.GETBULK));
for (String oid : oidList) {
List<TreeEvent> events = treeUtils.getSubtree(target, new OID(oid));
if (events == null || events.size() == 0) {
System.out.println(logKey + "Error: oid " + oid + " no response ");
continue;
}
for (TreeEvent event : events) {
if (event == null || event.isError()) {
System.out.println(logKey + "Error: " + event.getErrorMessage());
continue;
}
VariableBinding[] varBindings = event.getVariableBindings();
if (varBindings != null) {
responseCount += varBindings.length;
}
}
}
System.out.println(logKey + "Response: " + responseCount);
snmp.close();
transport.close();
} catch (Exception e) {
System.out.println(logKey + "Exception occour");
}
}
How can I ensure consistent responses from all devices when the execution interval is set to 1 second or even shorter?