masterIoInit( ) - create the IPC mechanism at the SNMP master agent
snmpMonitorSpawn( ) - spawn tMonQue to run snmpQueMonitor( )
masterIpcComp( ) - transmit a completion of transmission message
masterIoWrite( ) - send the encoded buffer to the subagent
masterIpcSend( ) - send a message to a subagent
masterIpcRcv( ) - wait for a reply from the subagent
masterIpcAyt( ) - check the status of the IPC link
masterIpcFree( ) - free the IPC resources allocated by the SNMP master agent
masterQueCleanup( ) - free resources allocated for SNMP master agent
STATUS masterIoInit (void)
This module implements the I/O routines used by the SNMP master agent. As shipped, the WindNet SNMP code uses message queues to communicate between the master agent and its subagents. The SNMP master agent also uses a message queue to handle communication between its two component tasks, tSnmpd and tMonQue. The tSnmpd task handles communication with the SNMP manager. The tMonQue task is a secondary task spawned from tSnmpd to receive messages from subagents.
When tSnmpd spawns tMonQue, it assigns snmpQueMonitor( ) to manage the process. This function waits on the message queue that subagents use to send messages to the master agent. The snmpQueMonitor( ) function interprets messages on its queue using an SA_MESSAGE_T structure, which is defined in ipcLib.h as:
typedef struct SA_MESSAGE_S
A switch internal to snmpQueMonitor( ) handles the message according to the value of the msgType member.
If the message type is CALL_QUERY_HANDLER, the message is a response to a query from the master agent. The buffer referenced in the mesg is then transferred to the local message queue monitored by tSnmpd, which is waiting for a query response from a subagent.
If the message type is CALL_REG_HANDLER, the message is either a registration request, a deregistration request, or some other control message (such as a trap). To respond to such requests, snmpQueMonitor( ) passes the buffer in mesg to snmpMasterHandlerWR( ).
If the message submitted to snmpMasterHandlerWR( ) is a registration request, it includes information on a set of leaves representing the objects that the subagent wants to add to the master agent's MIB tree. If the message passes all checks, the objects are added to the master agent's MIB tree and snmpMasterHandlerWR( ) returns success. All objects registered in one message become part of a group. They share the same IPC information, and, if the IPC link to their subagent is broken, they are deactivated as a group.
If snmpMasterHandlerWR( ) returns a function value indicating success, it also returns a message for the subagent containing the group ID for the variables just added. The snmpQueMonitor( ) takes responsibility for forwarding this message to the subagent. The subagent uses the group ID contained in this message when it comes time to deregister, as well as when it must register instances of an already registered object.
The returned function value of snmpMasterHandlerWR( ) can indicate failure or an opcode. You might want to rewrite this code to do something different. For example, if the subagent has sent a trap up to the master agent, the returned value of snmpMasterHandlerWR( ) is SA_TRAP_REQUEST, and the vblist parameter contains a varbind list from the subagent. In this case, you would want to modify snmpQueMonitor( ) to pass the trap on to the SNMP manager.
These MIB variables that the subagent adds to the master agent's MIB tree look transparent to the SNMP manager that is in communication with the master agent. However, the method routines associated with these MIB variables in the master agent are not standard MIB routines. Instead, they are special routines that know how to queue test, get, and set work on the subagent that registered the MIB variables with the master agent. From the point of view of the PDU processing code, these special method routines look like any other method routines. However, when tSnmpd executes one of these routines, the special method routine actually passes the work on to a subagent while tSnmpd waits on a local message queue.
Because the subagent does not know about this local message queue, its response to the master agent is somewhat indirect. The only master agent message queue known to the subagent is the message queue managed by tMonQue, so the subagent puts its response on that queue. When the snmpQueMonitor( ) function that tMonQue runs to monitor the message queue sees that the message is a query response, it then transfers the message to the local queue upon which tSnmpd is awaiting a response. When tSnmpd sees the response, it parses it and merges the message into the PDU processing system.
In the shipped implementation, communication between the master agent and its subagents is handled serially. For example, if the SNMP manager made a request concerning three MIB variables managed by three different subagents, the master agent would query each subagent in turn. After gathering all three responses, the master agent would then pack them up and ship the information back to the SNMP manager.
With some modifications to the code, you could rewrite the SNMP master agent to query all three subagents simultaneously (see the description of the snmpMasterHandlerAsync( ) function defined in subagentLib.c). That is, the master agent would query all three subagent one after the other without waiting for a response after making each request. If the subagents reside on different targets (each with its own processor), this asynchronous query method of multiple subagents lets you take advantage of the capacity for parallel processing.
However, if the subagents reside on different targets, you will also need to replace the code that implements the IPC mechanism used between the master agent and its subagents. In the shipped code, message queues serve as the IPC mechanism. To support agents that reside on different machines, you must replace this IPC mechanism with something such as sockets. To make this possible, the functions that implement the IPC mechanism are isolated to masterIoLib.c and saIoLib.c. These files ship as source code that you should feel free to edit as needed.