I use snmp4j to query data using snmpwalk, the version is 3.7.7. Sometime it is ok,but sometime it has a error:org.snmp4j.MessageException: Operation not permitted. How to fix it? According to this question, I have try to add the iptable rule, but it is still has the error in radom.
The total error is:org.snmp4j.MessageException: Operation not permitted
at org.snmp4j.MessageDispatcherImpl.sendPdu(MessageDispatcherImpl.java:642)
at org.snmp4j.Snmp.sendMessage(Snmp.java:1074)
at org.snmp4j.Snmp.send(Snmp.java:974)
at org.snmp4j.Snmp.send(Snmp.java:956)
at org.snmp4j.Snmp.send(Snmp.java:924)
com.iwhalecloud.uncc.util.SnmpUtil.lambda$getTableByWalkOid$0(SnmpUtil.java:581)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.io.IOException: Operation not permitted
at java.base/java.net.PlainDatagramSocketImpl.send(Native Method)
at java.base/java.net.DatagramSocket.send(DatagramSocket.java:695)
at org.snmp4j.transport.DefaultUdpTransportMapping.sendMessage(DefaultUdpTransportMapping.java:128)
at org.snmp4j.transport.DefaultUdpTransportMapping.sendMessage(DefaultUdpTransportMapping.java:46)
at org.snmp4j.MessageDispatcherImpl.sendMessage(MessageDispatcherImpl.java:261)
at org.snmp4j.MessageDispatcherImpl.sendPdu(MessageDispatcherImpl.java:619)
… 10 more
Are you using a single Snmp instance or do you create a new instance often?
using a single Snmp instance , and single pdu.The error happen in this code : responseEvent = snmp.send(pdu, target);.
Here is my total code:
log.info("start walk oid:{}", oid);
HashMap<String, VariableBinding> resultMap = new HashMap<>();
PDU pdu;
int version = customSnmpTarget != null ? customSnmpTarget.getSnmpVersion() : target.getVersion();
if (version == MessageProcessingModel.MPv3) {
pdu = new ScopedPDU();
}
else {
pdu = new PDU();
}
pdu.setType(PDU.GETBULK);
OID targetOId = new OID(oid);
pdu.add(new VariableBinding(targetOId));
//pdu.setMaxRepetitions(100);
pdu.setMaxRepetitions(maxRepetition);
pdu.setNonRepeaters(0);
boolean matched = true;
String nextOid = oid;
while (matched) {
ResponseEvent responseEvent = null;
responseEvent = snmp.send(pdu, target);
if ((responseEvent == null || responseEvent.getResponse() == null)) {
log.warn("result is null!responseEvent:{},pdu:{}", JsonUtil.obj2Json(responseEvent), JsonUtil.obj2Json(pdu.getVariableBindings()));
return resultMap;
}
PDU response = responseEvent.getResponse();
List<? extends VariableBinding> variableBindings = response.getVariableBindings();
for (int i = 0; i < variableBindings.size(); i++) {
VariableBinding variableBinding = variableBindings.get(i);
nextOid = variableBinding.getOid().toDottedString();
if (nextOid.length() > oid.length() && resultMap.containsKey(nextOid.substring(oid.length() + 1))) {
log.info("matched false! oid:{} have same subOid:{}", oid, nextOid);
matched = false;
break;
}
if (!nextOid.startsWith(oid)) {
log.info("matched false!nextOid:{},oid:{}", nextOid, oid);
matched = false;
break;
}
else {
if (oid.length() + 1 <= nextOid.length()) {
String subOid = nextOid.substring(oid.length() + 1);
if (log.isInfoEnabled()) {
Variable currentVariable = variableBinding.getVariable();
String varString = currentVariable.toString();
log.info("current oid:{},value:{}", subOid, varString);
}
resultMap.put(subOid, variableBinding);
}
else {
log.info("matched false!skip nextOid:{},oid:{}", nextOid, oid);
if (variableBindings.size() == 1) {
matched = false;
break;
}
}
}
}
if (log.isInfoEnabled())
log.info("next oid:{},response.oid:{}", nextOid, response.get(0).getOid().toDottedString());
}
if (!matched) {
break;
}
pdu.clear();
pdu.add(new VariableBinding(new OID(nextOid)));
}
if (log.isInfoEnabled()) {
log.info("ip:{},oid:{},size:{}", target.getAddress(), oid, resultMap.size());
}
return resultMap;
}
catch (Exception e) {
log.error("oid:" + oid + ",ip:" + (target == null ? customSnmpTarget.getNodeIp() : target.getAddress()) + "," + org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(e));
if (exceptionContainer.getException() == null) {
exceptionContainer.setException(e);
}
}
return null;
}
Then there is nothing you can do on Java level, you need to fix it on OS level (maybe by using a different JDK or finding the issue in your network setup). In any case the source of the problem is local not remote nor in-transit.
I am currently using synchronous requests like this: responseEvent = snmp.send(pdu, target);
. If I change to asynchronous, do you think the effect or query efficiency will be improved
In my code ,I .setMaxRepetitions 100.If I do not set the value,what is the default vlaue?
I thought you were already using TreeUtils or TableUtils.
You can use synchronous or asynchronous interfaces, that does not matter, but your logic for doing a “walk” does matter. Especially if the agent is not standard-conforming.
It’s because using TableUtils requires setting maxNumRowsPerPDU and MaxNumColumnsPerPDU, which have different values and require different strategies for device adjustment. Therefore, I had to switch to walk collection and then merge. Now, I have found that sometimes walk collection reports this error, while other times it doesn’t
I think the execution logic should be fine, because sometimes I can retrieve the correct values. What I am currently querying is using the same SNMP instance. Do you think if I create a new instance every time I query, it will reduce this type of error?
No, it can make things worse only (because of the overhead of creating the network ports and sync engine times)