[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