1

为单个设备运行 get/ getNextMessage processing model 3 returned error: Unknown security name命令时出现错误。我每 2 秒敲击一次设备。为了有更好的性能,如果我想得到不同的表。我创建线程并从我的应用程序并行访问每个线程。当我以单线程模式访问设备时,所有请求都可以正常工作。但是,当我在多线程模式下运行它时,我会间歇性地遇到上述错误(10 个请求中 2 个失败)。这是堆栈跟踪。

2014-06-11 11:26:10,371 [http-8080-6] INFO  com.kp.SnmpV3Connection - User Target: Security level is: 3Security Name is: user7
2014-06-11 11:26:10,371 [http-8080-3] INFO  com.kp.SnmpV3Connection - User Target: Security level is: 3Security Name is: user7
2014-06-11 11:26:10,373 [http-8080-6] DEBUG org.snmp4j.security.UsmUserTable - Adding user user7 = UsmUser[secName=user7,authProtocol=1.3.6.1.6.3.10.1.1.3,authPassphrase=kp-pass,privProtocol=1.3.6.1.6.3.10.1.2.4,privPassphrase=kp-pass,localizationEngineID=null]
2014-06-11 11:26:10,373 [http-8080-6] DEBUG org.snmp4j.security.UsmUserTable - Adding user user7 = UsmUser[secName=user7,authProtocol=1.3.6.1.6.3.10.1.1.3,authPassphrase=kp-pass,privProtocol=1.3.6.1.6.3.10.1.2.4,privPassphrase=kp-pass,localizationEngineID=null]
2014-06-11 11:26:10,374 [http-8080-6] DEBUG org.snmp4j.security.USM - Security name not found for engineID=, securityName=75:73:65:72:37
2014-06-11 11:26:10,374 [http-8080-6] DEBUG org.snmp4j.security.USM - Security name not found for engineID=, securityName=75:73:65:72:37
2014-06-11 11:26:10,376 [http-8080-6] ERROR org.snmp4j.util.TableUtils - org.snmp4j.MessageException: Message processing model 3 returned error: Unknown security name
2014-06-11 11:26:10,376 [http-8080-6] ERROR org.snmp4j.util.TableUtils - org.snmp4j.MessageException: Message processing model 3 returned error: Unknown security name

根据此处给出的链接,我使用以下安全模型:

USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(
                    MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);

另一个选项 noAuthNopriv 对我来说不是一个选项,我需要在 authpriv 中运行它。有人可以指出我正确的方向。

我相信这是一些 snmp 会话或 engineId 的问题。

************************编辑**********************

经过数周的调查,我终于发现我创建 USM 对象的方式

USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);

我为每个请求创建这个对象并添加到 securitymodel 中,从而重新创建 UserTable 和 usertime 表。我通过使 USM 成为单例并阻止重新创建 USM 表来解决此问题。但是我最终遇到了新问题,现在我遇到了错误

2014-06-24 07:11:19,671 [DefaultUDPTransportMapping_10.110.113.75/0] DEBUG org.snmp4j.mp.MPv3 - SNMPv3 header decoded: msgId=1263968764, msgMaxSize=65535, msgFlags=03, secModel=3
2014-06-24 07:11:19,671 [DefaultUDPTransportMapping_10.110.113.75/0] DEBUG org.snmp4j.security.USM - getUser(engineID=80:00:05:49:04:4d:49:4d:49:43, securityName=user10)
2014-06-24 07:11:19,671 [DefaultUDPTransportMapping_10.110.113.75/0] DEBUG org.snmp4j.security.UsmTimeTable - CheckTime: received message outside time window (non authoritative)
2014-06-24 07:11:19,671 [DefaultUDPTransportMapping_10.110.113.75/0] DEBUG org.snmp4j.security.USM - RFC3414 ?3.2.7.a Not in time window; engineID='80:00:05:49:04:4d:49:4d:49:43', engineBoots=5, engineTime=58766
2014-06-24 07:11:19,671 [DefaultUDPTransportMapping_10.110.113.75/0] WARN  org.snmp4j.MessageDispatcherImpl - statusInfo=1.3.6.1.6.3.15.1.1.2.0 = 0, status=1411

经过一番调查,我发现 snmp4j 没有在 UserTimeTable 中更新它自己的引擎时间和设备引擎时间。


除了这个问题,我还有几个查询。

  1. 如果我让 USM 成为一个单独的 USM 表,那么我的应用程序将拥有它的生命。如何清除此表(我可能有数万台设备,最终可能导致内存不足)。在什么基础上我可以清除这些用户?

  2. 如何让 SNMP4J 明确要求引擎启动和引擎时间

  3. 如果设备具有相同的用户名和安全名称但不同的 Authphrase 和隐私短语以及(可能相同的 engineId),SNMP4J 如何区分设备提前致谢。

4

2 回答 2

2

当我将 USM 设置为单例并且有单个 UsmUserTable 时,安全模型问题就解决了。

USM usm = USMFactory.getInstance();

并且received message outside time window是我配置的设备的问题。所有设备都有相同的engineId。当我使 engineId 唯一时,问题就解决了。

于 2014-06-27T08:26:05.317 回答
0

为了增加@Karthik Prasad 的答案,我想指出从snmp4j v2.8.6 开始没有USMFactory课程。因此解决方案可能如下所示:

public class SnmpDeviceProxy {    // one of your application classes
 
  public static final USM USM;
  static {
    // extract USM into a singleton to avoid multiple userTable instances creation that causes 'UnknownSecurityName'
    USM = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
    SecurityModels.getInstance().addSecurityModel(USM);
  }

问题详情

在使 USM 成为单例之前,每次调用时,SecurityModels.getInstance().addSecurityModel(USM)我们实际上并没有添加新模型,而是一遍又一遍地重写addSecurityModel同一个模型,因为它就是这样做的:

  public SecurityModels addSecurityModel(SecurityModel model) {
    securityModels.put(new Integer32(model.getID()), model);
    return this;
  }

,即将模型放入一个映射中,其中的键取自model.getId()方法,而方法的值又取自常量:

  public int getID() {
    return SECURITY_MODEL_USM;
  }

令人沮丧地宣布为:

  public static final int SECURITY_MODEL_USM = 3;

换句话说,无论我们尝试添加什么 USM 实例,它都将始终securityModels使用 key 存储到地图中3。并且每次存储时,我们都会丢失之前的状态,userTable因为它是每个 USM 实例的子对象(字段)。因此,如果我们在创建 USM 实例后立即调用,我们会打开一个空或不完整addSecurityModel的时间段。userTable如果一个线程在此期间查询表,它会得到Unknown security name. 但是如果我们让 USM 成为一个单例并且只存储一次,我们可以在不丢失之前的值的情况下更新模型映射。

于 2022-02-16T05:34:15.400 回答