[SNMP4J] SNMP4J Correct Multi-thread Design for use it (under Linux) ?
TESSALONIKOS, THIERRY
thierry.tessalonikos at atos.net
Mon Sep 26 10:42:05 CEST 2016
Hi Franck,
Think you for your help.
Yes my factory method is not thread safe, but in my implementation, only the main create one instance of the singleton, and the threads call the static method getSnmp() that return the only one instance of snmp class.
But, yes, I can add synchronized for the factory method getInstance(), it is better ☺
But, for the getSnmp() method, that is not synchronized, is the design of SNMP4J allow many threads to call the method snmp.send(pdu, target) in parallel ?
In my design that works well expect when I make two call in parallel send(pdu,target), where targets are two different instances, but they are initialized with the same IP address. Is it a problem for SNMP4J or is it usual ?
· Because I receive org.snmp4j.MessageException : Operation not permitted for the first request only (at each time). Do you know the cause/raison of this exception ?
Thank you very much for your opinion.
Best Regards,
Thierry TESSALONIKOS
From: Frank Fock [mailto:fock at agentpp.com]
Sent: Saturday, September 24, 2016 11:42 AM
To: TESSALONIKOS, THIERRY
Cc: snmp4j at agentpp.org
Subject: Re: SNMP4J Correct Multi-thread Design for use it (under Linux) ?
Hi Thierry,
Your singleton factory method is NOT thread safe. This could create issues and
need to be fixed.
Anything else does not seem to be a real issue with SNMP.
The notInTimeWindow report is normal when two SNMPv3 entities
exchange messages for the first time (the time needs to be synchronised).
Best regards,
Frank
On 23 Sep 2016, at 15:57, TESSALONIKOS, THIERRY <thierry.tessalonikos at atos.net<mailto:thierry.tessalonikos at atos.net>> wrote:
Hi,
I need to use SNMP4J API in multi-threading design, because I must send 2 snmp set in parallel toward 2 Network Elements for sending them a parameters…
So, I have a main thread that initialize the SNMP4J API, with a singleton like this :
public class SNMP4JInitialize implements SNMPEngineInitInterface{
// properties SNMP4J
private static SNMP4JInitialize snmp4JInitializeInstance;
private static TransportMapping transport;
private static Snmp snmp;
private static USM usm;
private static OctetString localEngineID;
private SNMP4JInitialize() throws IOException {
// Intialisation SNMP4J
transport = new DefaultUdpTransportMapping(); //@TODO utiliser un autre constructeur pour positionner adresse IP d'écoute
snmp = new Snmp(transport);
localEngineID = new OctetString(MPv3.createLocalEngineID());
usm = new USM(SecurityProtocols.getInstance(), localEngineID, 0);
SecurityModels.getInstance().addSecurityModel(usm);
SecurityProtocols.getInstance().addPrivacyProtocol(new PrivAES256With3DESKeyExtension());
transport.listen();
// Instanaciation de la classe qui gere les UsmUer automatiquement à partir des MAJ JMS envoyées par l'appli JEE
OctetString securityName1 = new OctetString("toto");
UsmUser usmUser1 = new UsmUser(securityName1, // securityName
AuthMD5.ID, // authenticationProtocol
new OctetString("toto123456"), // authenticationPassphrase
PrivAES128.ID, // privacyProtocol
new OctetString("toto123456")); // privacyPassphrase
snmp.getUSM().addUser(usmUser1);
OctetString securityName2 = new OctetString("titi");
UsmUser usmUser2 = new UsmUser(securityName2, // securityName
AuthSHA.ID, // authenticationProtocol
new OctetString("toto123456"), // authenticationPassphrase
PrivAES256With3DESKeyExtension.ID, // privacyProtocol
//PrivAES256.ID, // privacyProtocol
new OctetString("toto123456")); // privacyPassphrase
snmp.getUSM().addUser(usmUser2);
}
public static Snmp getSnmp() {
return snmp;
}
public static SNMP4JInitialize getInstance() throws IOException, Exception {
if (snmp4JInitializeInstance == null) {
snmp4JInitializeInstance = new SNMP4JInitialize();
}
return (snmp4JInitializeInstance);
}
}
And after I launch 2 thread in parallel (from a thread pool, managed by ExecutorService class…)
Each thread create a new UserTarget and getSNMP instance from the Initialization Singleton, and send the PDU with snmp.send(pdu, target) like this :
public class SNMP4JRequestSender implements SNMPModuleSenderInterface {
public RequestTaskStatus sendsnmpv3Request(RequestTaskStatus requestTaskStatus, RequestTaskSNMP requestTaskSNMP) throws IOException {
final Address targetAddress = GenericAddress.parse(requestTaskSNMP.getSnmpTargetURL());
// create the target
UserTarget target = new UserTarget();
target.setAddress(targetAddress);
target.setRetries(requestTaskSNMP.getRetry());
target.setTimeout(requestTaskSNMP.getTimout());
target.setVersion(SnmpConstants.version3);
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
target.setSecurityName(requestTaskSNMP.getSecurityName()); // The same name used for usmUser
//create the PDU
ScopedPDU pdu = new ScopedPDU();
List<VariableBinding> variableBindings = requestTaskSNMP.getOids();
if ((variableBindings == null) || (variableBindings.isEmpty())) {
requestTaskStatus.setResultStatus(GeneralResultStatusEnum.Failed);
requestTaskStatus.setReasonStatus(ReasonStatusEnum.NoOIDinSNMPRequest);
return (requestTaskStatus);
}
for (VariableBinding variableBinding : variableBindings) {
pdu.add(variableBinding);
}
pdu.setType(requestTaskSNMP.getPDUType());
// send the PDU
final ResponseEvent response = SNMP4JInitialize.getSnmp().send(pdu, target);
// extract the response PDU (could be null if timed out)
final PDU responsePDU = response.getResponse();
if (responsePDU == null) {
requestTaskStatus.setResultStatus(GeneralResultStatusEnum.Failed);
requestTaskStatus.setReasonStatus(ReasonStatusEnum.NoResponseFromNetworkElement);
}
return (requestTaskStatus);
}
}
Is this design is correct or supported with SNMP4J API ? (thread safe, …).
It seems work well when I launch in parallel the 2 thread for sending 2 snmp request toward to different IP address target.
But when I launch the 2 thread toward the same IP address (but each thread use its own instance of UserTarget, but with the same IP) a have the following error only for the second request :
· org.snmp4j.MessageException : Operation not permitted
In this context, I observe with wireshark that the targets responds with SNMP Report : usmStatsNotInTimeWindows.0 but at my class SNMP4JInitalize is a Singleton, I do not recreate new instances of snmp() class or I do not reinit the EngineID…
I have this problem only one time, at the first run, I a second run I do not have any error. Is usmStatsNotInTimeWindows.0 is normal the first time for initializing the global instance of EngineID ?
Wireshark trace with iptable permit all (iptables –F) :
No. Time Source Destination Protocol Length Info
1 2016-09-23 13:26:35.033849965 192.168.1.3 192.168.1.4 SNMP 103 get-request
2 2016-09-23 13:26:35.034764515 192.168.1.4 192.168.1.3 SNMP 141 report SNMP-USER-BASED-SM-MIB::usmStatsUnknownEngineIDs.0
3 2016-09-23 13:26:35.214557739 192.168.1.3 192.168.1.4 SNMP 180 get-request SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16975104
4 2016-09-23 13:26:35.215829657 192.168.1.4 192.168.1.3 SNMP 157 report SNMP-USER-BASED-SM-MIB::usmStatsNotInTimeWindows.0
5 2016-09-23 13:26:35.216503803 192.168.1.3 192.168.1.4 SNMP 181 get-request SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16975104
6 2016-09-23 13:26:35.218085613 192.168.1.4 192.168.1.3 SNMP 185 get-response SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16975104
7 2016-09-23 13:26:40.037023750 192.168.1.3 192.168.1.4 SNMP 181 get-request SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16974080
8 2016-09-23 13:26:40.043708644 192.168.1.4 192.168.1.3 SNMP 185 get-response SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16974080
SNMP4J do not receive : get-response SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16974080 and instead : org.snmp4j.MessageException : Operation not permitted.
I also observe that the response from the second target is OK, but seems to be blocked by iptable. But my iptable permit all. So, when I completely stop the firewalld, this works with no error, but in observe SNMP Report : usmStatsNotInTimeWindows.0 only for the 2 first request :
Wirewhark trace without firewalld : no error SNMP4J but Report : usmStatsNotInTimeWindows.0
No. Time Source Destination Protocol Length Info
1 2016-09-23 13:41:22.582650149 192.168.1.3 192.168.1.4 SNMP 103 get-request
2 2016-09-23 13:41:22.582658266 192.168.1.3 192.168.1.4 SNMP 103 get-request
3 2016-09-23 13:41:22.583463629 192.168.1.4 192.168.1.3 SNMP 141 report SNMP-USER-BASED-SM-MIB::usmStatsUnknownEngineIDs.0
4 2016-09-23 13:41:22.583987192 192.168.1.4 192.168.1.3 SNMP 141 report SNMP-USER-BASED-SM-MIB::usmStatsUnknownEngineIDs.0
5 2016-09-23 13:41:22.745228783 192.168.1.3 192.168.1.4 SNMP 180 get-request SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16974080
6 2016-09-23 13:41:22.745775804 192.168.1.3 192.168.1.4 SNMP 180 get-request SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16975104
7 2016-09-23 13:41:22.746921812 192.168.1.4 192.168.1.3 SNMP 157 report SNMP-USER-BASED-SM-MIB::usmStatsNotInTimeWindows.0
8 2016-09-23 13:41:22.747486766 192.168.1.3 192.168.1.4 SNMP 181 get-request SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16974080
9 2016-09-23 13:41:22.747921357 192.168.1.4 192.168.1.3 SNMP 157 report SNMP-USER-BASED-SM-MIB::usmStatsNotInTimeWindows.0
10 2016-09-23 13:41:22.748393948 192.168.1.3 192.168.1.4 SNMP 181 get-request SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16975104
11 2016-09-23 13:41:22.749550684 192.168.1.4 192.168.1.3 SNMP 185 get-response SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16974080
12 2016-09-23 13:41:22.750722158 192.168.1.4 192.168.1.3 SNMP 185 get-response SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16975104
Is the error org.snmp4j.MessageException : Operation not permitted is because of my multi-thread design or because of Linux environment firewall ?
Is it normal to have report SNMP-USER-BASED-SM-MIB::usmStatsNotInTimeWindows.0 at the first time or is because of my multi-thread design ?
So we I launch a lot of request like in the same execution program, I have at each time, the first time report SNMP-USER-BASED-SM-MIB::usmStatsNotInTimeWindows.0, and the other request/response are normal like this :
No. Time Source Destination Protocol Length Info
1 2016-09-23 13:32:50.405161233 192.168.1.3 192.168.1.4 SNMP 181 get-request SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16975104
2 2016-09-23 13:32:50.405629005 192.168.1.3 192.168.1.4 SNMP 181 get-request SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16974080
3 2016-09-23 13:32:50.406982591 192.168.1.4 192.168.1.3 SNMP 185 get-response SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16975104
4 2016-09-23 13:32:50.408058738 192.168.1.4 192.168.1.3 SNMP 185 get-response SNMPv2-SMI::enterprises.7483.2.2.4.3.4.190.1.3.16974080
Thank you for your help/opinion (multi-thread design problem or linux firewalling problem or else ) ?
Best Regards,
Thierry TESSALONIKOS
More information about the SNMP4J
mailing list