I am having a strange problem with SNMP4J (we have the snmp4j 2.7.0). For the most part it has been working great, but we hit a snag over the holiday weekend. We are trying to status devices using SNMP Get (which work great) on SNMP3 devices. The issue is when we try and status 2 of the same types of devices on separate IPs and ports at the same time we get one status as coming back and the other as timing out. If I remove either one of the devices the SNMP GET will work, just not both together. I pulled up Wireshark and can see responses coming back from both devices, its just that my listener gets a NULL event back (on one of the devices). The only thing odd I see in the packets coming back is that both devices use the same engineID. Would this cause an issue? I know its not proper, but right now we would need to go back to our hardware vendor to have them update firmware.
Here is what our code (minus the processing) looks like:
class SNMPHardwareLayer extends HardwareLayer
{
private static final int ALLOWED_ATTEMPTS = 3;
private static final int TIMEOUT = 3000;
private Map<Equipment, Target> m_equipTargets = new HashMap<>();
private Snmp m_snmp = null;
public SNMPHardwareLayer()
{
startConnection();
}
public void startConnection()
{
OctetString localEngineId = new OctetString(MPv3.createLocalEngineID());
USM usm = new USM(SecurityProtocols.getInstance(),localEngineId,0);
SecurityModels.getInstance().addSecurityModel(usm);
try
{
TransmportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
m_snmp = new SNMP(transport);
USM userSecModel = new USM();
SecurityModels.getInstance().addSecurityModel(userSecModel);
transport.listen();
}
catch(exception e)
{
}
}
public connectToEquipment(Equipment equipment)
{
UserTarget target = new UserTarget();
OctetString username = new OctetString(equipment.getUsername());
OctetString password = new OctetString(equipment.getPassword());
UdpAddress address = new UdpAddress(InetAddress.getByName(equipment.getIp()), equipment.getPort());
target.setAddress(target);
target.setRetries(ALLOWED_ATTEMPTS);
target.setTimeout(TIMEOUT);
target.setVersion(SnmpConstants.version3);
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
target.setSecurityName(username);
OID authProtocol = AuthSHA.ID;
OID privProtocol = org.snmp4j.security.Priv3DES.ID;
UsmUser usmUser = new UsmUser(username,authProtocol,password,privProtocol,new OctetString(equipment.getPrivPwd()));
m_snmp.getUSM().addUser(usmUser);
m_equipTargets.put(equipment,target);
}
public void runStatus(Equipment equipment, oid)
{
Target target = m_equipTargets.get(equipment);
try
{
PDU pdu = new ScopedPDU();
pdu.add(new VariableBinding(oid);
pdu.setType(PDU.GET);
m_snmp.send(pdu,target,null, new ResponseListener() {
public void onResponse(ResponseEvent event)
{
PDU response = event.getResponse();
if(response != null)
{
((Snmp)event.getSource()).cancel(event.getRequest(),this);
// Do some processing
}
else
{
System.out.println(“TIMEOUT”);
}
}
}
}
catch(Exception e)
{
}
}
public static void main(String args[])
{
SNMPHardwareLayer layer = new SNMPHardwareLayer();
// Fill out equipment 1 and 2 of the same device type just different IPs
Equipment equip1 = new Equipment();
Equipment equip2 = new Equipment();
layer.connectToEquipment(equip1);
layer.connectToEquipment(equip2);
OID statusOID = new OID();
/// Fill out same oid on both devices for status
while(true)
{
try
{
layer.runStatus(equip1,statusOID);
layer.runStatus(equip2,statusOID);
Thread.sleep(1000);
}
catch(exception e)
{
}
}
}
}
If this is a problem with my code please let me know. If not, is there a way to have my code not worry about the SNMP engineID being unique and simply map responses via UDP IP and PORT? BTW I only am thinking the engine ID because of this post:
Again if this is a red herring, then please let me know.
Thanks.