[Erlang Systems]

2 Functional Description

The SNMP development toolkit contains the following parts:

The SNMP agent system consists of one Master Agent (MA) and optional Subagents.

This tool makes it easy to dynamically extend an SNMP agent in runtime. MIBs can be loaded and unloaded at any time. It is also easy to change the implementation of an MIB in runtime, without having to recompile the MIB. The MIB implementation is clearly separated from the agent.

To facilitate incremental MIB implementation, the tool can generate a prototype implementation for a whole MIB, or parts thereof. This allows different MIBs and management applications to be developed at the same time.

2.1 Definitions

The following definitions will help in understand the material presented in this user guide.

MIB.
The conceptual repository for management information is called the Management Information Base (MIB). It is conceptual because it does not hold any data, merely a definition of what data can be accessed. It can be compared to a header file in the C programming language. A definition of an MIB is a description of a collection of managed objects.
ASN.1.
The MIB is specified in a subset of the Abstract Syntax Notation One (ASN.1) language.
Managed object.
A resource to be managed is represented by a managed object which resides in the MIB. In an SNMP MIB, the managed objects are either:
  • scalar variables which have only one instance per agent. They have single values, not multiple values like vectors or structures.
  • tables which can grow dynamically.
  • a table element which is a special type of scalar variable.
Operations.
SNMP relies on the three basic operations: get (value), set (value) and get-next (value). The next item defines how operations are implemented.
Instrumentation function.
An instrumentation function is associated with each managed object. This is the function which actually implements the operations and will be called by the agent when it receives a request from the management station.

2.2 Features

To implement an agent, the programmer writes instrumentation functions for the variables and the tables in the MIBs that the agent is going to support. A running prototype which handles set, get, and get-next can be created without any programming.

The toolkit provides the following:

2.3 SNMPv1, SNMPv2 and SNMPv3

Currently (spring 1998), SNMPv1 is the full internet standard to use for network management. However, the "new" set of SNMPv2 specifications (RFC1902-1907) are now draft internet standards. Many managers choose to support both of these protocols. The main features of SNMPv2 compared to SNMPv1 are:

The standard documents that define SNMPv2 are incomplete, in the sense that they do not specify what a SNMPv2 message looks like. The message format and security issues are left to a special Administrative Framework. One such framework is the Community-based SNMPv2 Framework (SNMPv2c), which uses the same message format and framework as SNMPv1. There are other experimental frameworks as well, e.g. SNMPv2u and SNMPv2*.

The SNMPv3 specifications (RFC2271-2275) are now draft internet standrads as well. These specifications take a modular approach to SNMP. All modules are separated from each other, and can be extended or replaced individually. Examples of modules are Message definition, Security and Access Control. The main features of SNMPv3 are:

All these specifications are commonly refered to as "SNMPv3", but it is actually only the Message module, which defines a new message format, and Security module, which takes care of encryption and authentication, that can't be used with SNMPv1 or SNMPv2. In this version of the agent toolkit, some of the MIBs for agent configuration are used, specifically the MIBs for definition of management targets for notifications.

The extensible agent in this toolkit understands both SNMPv1 and SNMPv2c. Recall that SNMP consists of two separate parts, the MIB definition language (SMI), and the protocol. On the protocol level, the agent can be configured to speak v1, v2c or both of them at the same time, i.e. a v1 request gets an v1 reply, and a v2c request gets a v2c reply. On MIB level, the MIB compiler can compile both SMIv1 and SMIv2 MIBs. Once compiled, any of the formats can be loaded into the agent, regardless of which protocol version the agent is configured to use. This means that the agent translates from v2 notifictaions to v1 traps, and vice versa. For example, v2 MIBs can be loaded into an agent that speaks v1 only. The procedures for the translation between the two protocols are described in RFC1908 and RFC2089.

In order for an implementation to make full use of the new SNMPv2 error codes, it is essential that the instrumentation functions always return v2 error codes, in case of error. These are translated into the corresponding v1 error codes by the agent, if necessary.

The translation from a v1 MIB to a v2 reply is always very straightforward, but the translation from a v2 MIB to a v1 reply is somewhat more complicated. There is one data type in v2, called Counter64, that a v1 manager can't decode correctly. Therefore, an agent may never send a Counter64 object to a v1 manager. The common practise in these situations is to simple ignore the any Counter64 objects, when sending a reply or a trap to a v1 manager. For example, if a v1 manager tries to GET an object of type Counter64, he will get a noSuchName error, while a v2 manager would get a correct value.

2.4 Operation

The following steps are needed to get a running agent:

  1. Write your MIB in ASN.1 in a text file.
  2. Write the instrumentation functions in Erlang and compile them.
  3. Put their names in the association file.
  4. Run the MIB together with the association file through the MIB compiler.
  5. Configure the agent.
  6. Start the agent.
  7. Load the compiled MIB into the agent.

The figures in this section illustrate the steps involved in the development of an SNMP agent.

snmp-um-1-image-1
MIB Compiler Principles

The compiler parses the ASN.1 file and associates each table or variable with an instrumentation function (see MIB Compiler Principles). The actual instrumentation functions are not needed at MIB compile time, only their names.

The binary output file produced by the compiler is read by the agent at MIB load time (see Starting the Agent). The instrumentation is ordinary Erlang code which is loaded explicitly or automatically the first time it is called.

snmp-um-1-image-2
Starting the Agent

The SNMP agent system consists of one Master Agent and optional subagents. The Master Agent can be thought of as a special kind of subagent. It implements the core agent functionality, UDP packet processing, type checking, access control, trap distribution, and so on. From a user perspective, it is used as an ordinary subagent.

Subagents are only needed if your application requires special support for distribution from the SNMP toolkit. A subagent can also be used if the application requires a more complex set transaction scheme than is found in the master agent.

The following illustration shows how the system can look at runtime.

snmp-um-1-image-3
Architecture

A typical operation could include the following steps:

  1. The Manager sends a request to the Agent.
  2. The Master Agent decodes the incoming UDP packet.
  3. The Master Agent determines which items in the request that should be processed here and which items should be forwarded to its subagent.
  4. Step 3 is repeated by all subagents.
  5. Every subagent calls the instrumentation for its loaded MIBs.
  6. The results of calling the instrumentation are propagated back to the Master Agent.
  7. The answer to the request is encoded to a UDP Protocol Data Unit (PDU).

The sequence of steps shown is probably more complex than normal, but it illustrates the amount of functionality which is available. The following points should be noted:

Most applications only need the Master Agent because an agent can have multiple MIBs loaded at the same time.

2.5 Subagents and MIB Loading

Since applications tend to be transient (they are dynamically loaded and unloaded), the management of these applications must be dynamic as well. For example, if we have an equipment MIB for a rack and different MIBs for cards which can be installed in the rack, the MIB for a card should be loaded when the card is inserted, and unloaded when the card is removed.

In this agent system, there are two ways to dynamically install management information. The most common way is to load an MIB into an agent. The other way is to use a subagent which is controlled by the application and registers and de-registers itself. A subagent can register itself below a subtree (not to be mixed up with erlang:register). The subtree is identified by an Object Identifier. When a subagent is registered, it receives all requests for this particular subtree and it is responsible for answering them. It should also be noted that a subagent can be started and stopped at any time.

Compared to other SNMP agent packages, there is a significant difference in this way of using subagents. Other packages normally use subagents to load and unload MIBs in runtime. In Erlang, it is easy to load code in runtime and it is possible to load an MIB into an existing subagent. We do not need to create a new process for handling a new MIB.

Subagents are used for the following reasons:

Refer to the chapter Advanced Topics in this User's Guide for more information about these topics.

The communication protocol between subagents is the normal message passing which is used in distributed Erlang systems. This implies that subagent communication is very efficient compared to SMUX, DPI, and similar protocols.

2.6 Management of the Agent

Any SNMP agent must implement the system group and the snmp group, defined in MIB-II. The definitions of these groups have changed from SNMPv1 to SNMPv2. Provided in the distribution are MIBs and implementations for both of these versions. The MIB file for SNMPv1 is called STANDARD-MIB, and the corresponding for SNMPv2 is called SNMPv2-MIB. If the agent is configured to speak SNMPv1, the STANDARD-MIB is loaded by default. If it is configured to speak SNMPv2 or both protocols, the SNMPv2-MIB is loaded by defualt. It is possible to override this default behaviour, by explicitly load another MIB, for example, you could choose to implement the union of all objects in these two MIBs.

There is another MIB that may be loaded into the agent. It is called OTP-SNMPEA-MIB (in previous versions of the toolkit it was called INTERNAL-MIB). This MIB defines managed objects for the configuration of the agent itself.

There are two standard MIBs, defined in RFC2273, that also may be loaded into the agent. The MIBs are SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB, and defines managed objects for configuration of management targets, i.e. receivers of notifications (traps and informs).

All of these MIBs should be loaded into the Master Agent. The ASN.1 code, the Erlang source code, and the generated .hrl files for them are provided in the distribution.

The .hrl files are generated with snmp:mib_to_hrl/1 and they are located in the include directory of the snmp application. Include these files in your code as follows:

-include_lib("snmp/include/STANDARD-MIB.hrl").
    

2.6.1 STANDARD-MIB and SNMPv2-MIB

These MIBs contain the snmp- and system groups from MIB-II which is defined in RFC1213 (STANDARD-MIB) or RFC1907 (SNMPv2-MIB). They are implemented in the snmp_standard_mib module. The snmp counters all reside in volatile memory and the system and snmpEnableAuthenTraps variables in persistent memory, using the SNMP built-in database (refer to the Reference Manual, section snmp, module snmp_local_db for more details).

If you need another implementation of any of these objects, e.g. you may want to store the persistent variables in the Mnesia database instead, you will have to make your own implementation of these variables (you can of course use the standard implementation for the other variables), compile and load the MIB instead of the default MIB. The new compiled MIB must have the same name as the original MIB (i.e. STANDARD-MIb or SNMPv2-MIB), and be located in the SNMP configuration directory (see Configuration Files.)

2.6.1.1 Data Types

There are some new data types in SNMPv2 that are useful in SNMPv1 as well. In the STANDARD-MIB, three data types are defined, RowStatus, TruthValue and DateAndTime. These data types are originally defined as textual conventions in SNMPv2-TC (RFC1903).

2.6.2 OTP-SNMPEA-MIB

There are a few unspecified issues in SNMPv1 as well as in SNMPv2c. These include:

These problems have been solved in other versions of SNMPv2, and in SNMPv3. We use some of the SNMPv2p approaches to solve the problems in this agent. In this version of the agent, standard (RFC2273) MIBs are used for configuration of which managers should receive traps. In future versions of the agent, all standard mechanisms will be used, and the OTP-SNMPEA-MIB will no longer be used for this purpose.

The OTP-SNMPEA-MIB defines managed objects for configuration which is used internally by the agent (see Configuration Files for further details). All data in this MIB is stored in volatile memory. This means that the data in the configuration files is read at start-up and inserted into the database. If another behaviour is needed, change the implementation of the functions in the module snmp_internal_mib.

This MIB does not have to be loaded in the Master Agent. If it was, managers would have access to configuration data such as MIB views, communities, and trap destinations. Unless security is provided, it is generally not a good idea to make this MIB visible for managers. However, it is possible to load this MIB, or parts of it, and use the MIB view mechanism to restrict the visibility to certain managers.

If only parts of the MIB are wanted, delete the unwanted objects from the MIB file and recompile.

All tables use the RowStatus textual convention from SNMPv2, which is defined in STANDARD-MIB, to provide a uniform row handling mechanism.

2.6.2.1 intCommunityTable

This table contains access information for different communities known to the agent. The ASN.1 definition looks as follows:

IntCommunityEntry ::=
 SEQUENCE {
  intCommunityDestination      IpAddress,
  intCommunityString           DisplayString,
  intCommunityViewIndex        INTEGER,
  intCommunityAccess           INTEGER,
  intCommunityStatus           RowStatus
}
INDEX {    intCommunityDestination, 
           intCommunityString }
        

A MIB view, and a corresponding access to that MIB view, is defined for each pair of intCommunityDestination and intCommunityString. The view is defined in intViewTable. The access can be read or readWrite.

The special IP address {0.0.0.0} is used as a wildcard. This wildcard matches all IP addresses which makes it possible to give certain access to all IP addresses.

This table is used by the agent as follows:

  1. A request which includes a reference to a community string comes in from a certain IP address.
  2. The agent looks in the table for the MIB view and the access which corresponds to the IP address and the community string.
  3. The operation is validated against the access and all requested objects are validated against the MIB view.

If the standard variable snmpEnableAuthenTraps is set to enabled, an authenticationFailure notification is sent when the validation fails. This notification is sent to all management targets.

2.6.2.2 intAgentIpAddress

This variable holds the IP address of the agent. It is used when sending traps and is included in the trap PDU sent to the management stations.

2.6.2.3 intAgentUDPPort

This variable holds the UDP port which the agent listens to.

2.6.2.4 intAgentMaxPacketSize

This variable describes the maximum packet size that this agent will send to a management station. The size is specified in bytes.

2.6.2.5 intAddressTable

This table contains UDP related information for each management station that is known to the agent. The ASN.1 definition looks as follows:

IntAddressEntry ::=
 SEQUENCE {
  intAddressDestination          IpAddress,
  intAddressUDPPort              INTEGER,
  intAddressMaxPacketSize        INTEGER   (484..65535),
  intAddressStatus               RowStatus
 }
INDEX      { intAddressDestination }
        

The following criteria is defined for each management station IP address:

This table is used when the agent sends a message to a management station. When sending a response, the agent checks that the packet size is less than specified in the intAgentMaxPacketSize variable and the intAddressMaxPacketSize for the management station. Otherwise, a tooBig error is returned.

When sending a trap, a check is performed to ensure that the trap is not too big. If it is, the trap will not be sent to the management station destination.

2.6.2.6 intTrapDestTable

This table is obsolete, and is no longer used. The tables in SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB are used for this purpose.

2.6.2.7 intViewTable

This table contains definitions for the MIB views. It is the same table as viewTable in SNMPv2. The ASN.1 definition looks as follows:

IntViewEntry ::=
 SEQUENCE {
  intViewIndex        INTEGER,
  intViewSubtree      OBJECT IDENTIFIER,
  intViewMask         OCTET STRING,
  intViewType         INTEGER,
  intViewStorageType  StorageType,
  intViewStatus       RowStatus
 }
INDEX { intViewIndex, intViewSubtree }
        

The intViewStorageType column is not used.

Each intViewIndex refers to a collection of sub-trees. Refer to the file OTP-SNMPEA-MIB.mib, or to RFC1447, for a complete description on this table

2.6.2.7.1 MIB View Semantics

The formal definition of MIB views can be found in RFC1445 (from SNMPv2) . The following paragraphs are an extract from this RFC.

An MIB view is a collection of included and excluded subtrees. A subtree is identified by an OBJECT IDENTIFIER. A mask is associated with each subtree.

For each possible MIB object instance, the instance belongs to a subtree if:

Membership of an object instance in an MIB view is determined by the following algorithm:

Note!

If the OBJECT IDENTIFIER is longer than an OBJECT IDENTIFIER of an object type in the MIB, it refers to object instances. Because of this, it is possible to control whether or not particular rows in a table shall be visible.

2.6.3 SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB

These MIBs define managed objects for configuration of notification receivers. They are described in detail in RFC2273. Here is only a brief description given.

2.6.3.1 snmpNotifyTable

An entry in this table selects a set of management targets which should receive notifications, as well as the type (trap or inform) of notification which should be sent to each selected management target.

The key in this table, snmpNotifyName is used in a special way in this version of the agent. It is used as the CommunityString which is included in each SNMPv1 or SNMPv2c notification. When an application sends a notification using the function send_notification/5 or the old function send_trap the parameter NotifyName specified in the call is used as an index in this table. The notification is sent to the management targets selected by that entry.

2.6.3.2 snmpTargetAddrTable

An entry in this table defines transport parameters (such as IP address and UDP port) for each management target. Each row in the snmpNotifyTable refers to potentially many rows in this table. Each row in the snmpTargetAddrTable refers to an entry in the snmpTargetParamsTable.

2.6.3.3 snmpTargetParamsTable

An entry in this table defines which SNMP version to use, and which security parameters to use.

Which SNMP version to use is implicitly defined by specifying the Message Processing Model. This version of the agent handles the models v1 and v2c.

Each row specifies which security model to use, along with security level and security parameters. This version of the agent handles the security model otp_sec, which provides simple security by validating the IP address from which a request is sent. The SnmpSecurityModel value for this security model is 49427 (which is calculated as ericsson * 256 + otp.)

2.7 Notifications

Notifications are defined in SNMPv1 with the TRAP-TYPE macro in the ASN.1 definition of an MIB (see RFC1215). The corresponding macro in SNMPv2 is NOTIFICATION-TYPE. When an application decides to send a notification, it calls one of the following function:

snmp:send_notification(Agent,Notification,Receiver[,NotifyName,Varbinds])
snmp:send_trap(Agent,Notification,Community[,Receiver,Varbinds])
    

providing the registered name or process identifier of the agent where the MIB which defines the notification is loaded and the symbolic name of the notification.

If the send_notification/3,4 function is used, all management targets are selected, as defined in RFC2273. The Receiver parameter defines where the agent should send information about the delivery of inform requests.

If the send_notification/5 function is used, an NotifyName must be provided. This parameter is used as an index in the snmpNotifyTable, and the management targets defined by that single entry is used.

The function send_trap is kept for backwards compatibility. The Community is used as a NotifyName described above.

Applications that use the old function send_trap will continue to work. The snmpNotifyName is used as the community string by the agent when a notification is sent.

2.7.1 Notification Sending

The simplest way is to call the function as snmp:send_notification(Agent, Notification, no_receiver). In this case, the agent performs a get-operation to retrieve the object values which are defined in the notification specification (with the TRAP-TYPE or NOTIFICATION-TYPE macros). The notification is sent to all managers defined in the target and notify tables, either unacknowledged as traps, or acknowledged as inform requests.

If the caller of the function wants to know whether or not acknowledgements are received for a certain notification (provided it is sent as an inform), the Receiver parameter can be specified as {Tag, ProcessName} (refer to the Reference Manual, section snmp, module snmp for more details). In this case, the agent send a message {snmp_notification, Tag, {got_response, ManagerAddr}} or {snmp_notification, Tag, {no_response, ManagerAddr}} for each management target.

Sometimes it is not possible to retrieve the values for some of the objects in the notification specification with a get-operation. However, they are known when the send_notification function is called. This is the case if an object is an element in a table. It is possible to give the values of some objects to the send_notification function snmp:send_notification(Agent, Notification, Receiver, Varbinds). In this function, Varbinds is a list of Varbind, where each Varbind is one of:

For example, to specify that sysLocation should have the value "upstairs" in the notification, we could use one of:

It is also possible to specify names and values for extra variables that should be sent in the notification, but were not defined in the notification specification.

The notification is sent to all management targets found in the tables. However, make sure that each manager has access to the variables in the notification. If a variable is outside a manager's MIB view, this manager will not receive the notification.

Note!

By definition, it is not possible to send objects with ACCESS not-accessible in notifications. However, historically this is often done and for this reason we allow it in notification sending. If a variable has ACCESS not-accessible, the user must provide a value for the variable in the Varbinds list. It is not possible for the agent to perform a get-operation to retrieve this value.

2.7.2 Subagent Path

If a value for an object is not given to the send_notification function, the subagent will perform a get-operation to retrieve it. If the object is not implemented in this subagent, its parent agent tries to perform a get-operation to retrieve it. If the object is not implemented in this agent either, it forwards the object to its parent, and so on. Eventually the Master Agent is reached and at this point all unknown object values must be resolved. If some object is unknown even to the Master Agent, this is regarded as an error and is reported with a call to snmp_error:user_err/2. No notifications are sent in this case.

For a given notification, the variables which are referred to in the notification specification must be implemented by the agent which has the MIB loaded, or by some parent to this agent. If not, the application must provide values for the unknown variables. The application must also provide values for all elements in tables.


Copyright © 1991-98 Ericsson Telecom AB