Java Dynamic Management Kit 4.0 Tutorial

The Proxy Roles

As we saw in "MIB Development Process", the MBeans that represent a MIB are generated from the MIB definition by the mibgen tool. This tool generates one main MBean representing the MIB and then one MBean for each group and each table entry. The main MBean extends the SnmpMib class whose implementation of the abstract SnmpMibAgent class processes all requests on a MIB.

For example, if an agent receives a get request for some variable, it will call the get method that the main MBean inherits from SnmpMibAgent. The implementation of this method relies on the MIB structure to find the MBean containing the corresponding attribute and then call its getter to read the value of the variable.

A proxy is another implementation of the SnmpMibAgent class which, instead of resolving variables in local MBeans, reformulates an SNMP request, sends it to a designated sub-agent and forwards the answer that it receives. Since only the main MBean of a MIB is bound to the SNMP adaptor, we bind the proxy instead, and the master agent transparently exposes the MIB which actually resides in the sub-agent.

The Master Agent

The master agent needs to instantiate one SNMP proxy object for each sub-agent containing MIBs that it wishes to serve. The remote MIBs can be on any number of sub-agents, and the master agent can have several proxy objects. Sub-agents themselves may contain proxies: it is up to the designer to define the complexity of the agent hierarchy.

The master agent may also contain a mix of proxies and MBeans for other MIBs. In the proxy example, the master agent exposes the DEMO MIB through local MBeans and a subset of the RFC1213 MIB through a proxy.


Example 9-1 The Master Agent of the Example

MBeanServerImpl server;
ObjectName snmpObjName;
ObjectName localMibObjName;
ObjectName remoteMibObjName;
int htmlPort = 8082;
int snmpPort = 8085;

// read sub-agent connection info from the command line
String host = argv[0];
String port = argv[1];

try {
    server = MBeanServerFactory.createMBeanServer();
    String domain = server.getDefaultDomain();

    // Create and start the HTML adaptor.
    [...]
      
    // Create and start the SNMP adaptor.
    [...]
  
    // Create, initialize, and bind the local MIB Demo.
    //
    localMibObjName = new ObjectName("snmp:class=DEMO_MIB");
    server.registerMBean(localMib, localMibObjName);
    localMib.setSnmpAdaptorName(snmpObjName);
  
    // Create and initialize the SNMP proxy.
    //
    remoteMibObjName = new ObjectName("snmp:class=proxy");
    SnmpMibAgentImpl remoteMib = new SnmpMibAgentImpl();
    server.registerMBean(remoteMib, remoteMibObjName);
    remoteMib.initializeProxy(host, Integer.parseInt(port), "1.3.6.1.2.1");

    // Bind the MIB proxy to the SNMP adaptor
    //
    ((SnmpMibAgent)remoteMib).setSnmpAdaptorName(snmpObjName);
  
} 
catch (Exception e) {
    e.printStackTrace();
    java.lang.System.exit(1);
}

We register the proxy object as any other MBean and then initialize it. We call the initialize method of the proxy, giving the host and port of the sub-agent it must communicate with and the root OID of the MIB or subset that it represents.

A single proxy object can serve several MIBs on a sub-agent, and in this case, the root OID is the common prefix of all objects. However, the OIDs of all proxies and MIBs in an agent must be distinct, none may be a substring of another (see "Binding the MIB MBeans"). Finally, we bind the proxy to the SNMP adaptor just as we would a MIB MBean.

The Sub-Agent

The sub-agent in our example is a stand-alone agent which serves a subset of the RFC1213 MIB. Since it implements no proxies of its own, it is just a plain agent which responds to SNMP management requests that happen to originate from a proxy object. Any SNMP manager could also send requests to this agent.

Stand-alone agents are covered in "Stand-Alone SNMP Agents". Since this stand-alone agent contains no code that is specific to its role as a sub-agent, we will not repeat its program listing here. The StandAloneAgent.java file only contains some extra code for reading its assigned port from the command line. We will use this to launch the agent on a known port to which the proxy can connect.

The Manager Application

The manager application is not affected by proxies in the agents to which it sends requests. It sends the requests to the master agent, in the same way that it would send a request for a MIB that is not served by a proxy. In fact, the SNMP manager cannot even distinguish between a MIB served by an agent and another MIB served through a proxy in the agent, except perhaps by analyzing the values returned.

There is one consideration for proxies, and that is the timeout interval. Since the proxy issues another request and only answers at the end of its timeout, the manager must have a longer timeout. The manager should be designed with some knowledge of all sub-agents in a hierarchy, so that the timeout can take into account all proxy delays and the multiple communication times.

As with any manager application written with the SNMP manager API, the manager in the proxy example must have access to the OID table objects that represent the MIBs that it will manage. Here is the code to initialize the manager:


Example 9-2 Initialization of the SNMP Proxy Manager

String host = argv[0];
String port = argv[1];

// Initialize the SNMP Manager API.
// Specify the OidTables containing all the MIB Demo and MIB II knowledge.
// Use the OidTables generated by mibgen when compiling MIB Demo and MIB II.
//
SnmpOidDatabaseSupport oidDB = new SnmpOidDatabaseSupport();
SnmpOid.setSnmpOidTable(oidDB);
oidDB.add(new RFC1213_MIBOidTable());
oidDB.add(new DEMO_MIBOidTable());
  
SnmpPeer agent = new SnmpPeer(host, Integer.parseInt(port));
SnmpParameters params = new SnmpParameters("public", "private");
SnmpSession session = new SnmpSession("Manager session");
  
// We update the time out to let the agent enough time 
// to do his job before retry.
//
agent.setTimeout(100000);
agent.setSnmpParam(params);
session.setDefaultPeer(agent);

The rest of the manager application is the code for synchronous get and set requests, similar to the one shown in "The Synchronous Manager Example".