Chapter 17. The SNMP Agent

Table of Contents

17.1. Introduction to the ConfD SNMP Agent
17.2. Agent Functional Description
17.3. Generating MIBs from YANG
17.4. Configuring the SNMP Agent
17.5. How the SNMP Agent Interacts with ConfD
17.6. Running the SNMP Agent as a NET-SNMP subagent

17.1. Introduction to the ConfD SNMP Agent

The ConfD integrated SNMP agent provides an environment where SNMP and other agents such as NETCONF, Web UI, and CLI, coexist and use the same built-in database (CDB) for configuration storage and the same set of instrumentation functions for controlling managed objects (MOs). Simple bindings from SNMP MIB objects to YANG nodes is all that is needed to open up a configuration database to be accessed by an SNMP manager.

The advantage of having an integrated SNMP agent in ConfD is that configuration data can be accessed directly from the built-in database (CDB) or from user written managed objects without having to do the tedious work of writing a separate set of instrumentation functions just for SNMP. One set of common instrumentation functions is used for serving the NETCONF, CLI, Web UI, and SNMP agents.

confdc --mib2yang is used to make YANG models from MIBs. It also provides the necessary bindings from MIB objects to nodes in the YANG model.

To go the opposite way, from YANG to MIBs, see Section 17.3, “Generating MIBs from YANG”.

The ConfD SNMP agent application provides the following features:

  • An extensible SNMP agent that understands SNMPv1, SNMPv2c and SNMPv3.

  • A MIB compiler that understands SMIv1 and SMIv2.

  • Configuration data is specified in YANG models.

  • Common instrumentation functions for controlling managed objects (MO's) via NETCONF, CLI, Web UI, and SNMP agent.

  • The SNMP agent uses ConfD AAA datarules to determine access to data, as well as using the standard SNMP view based and user based access control mechanisms.

  • The following MIBs are builtin in the ConfD SNMP agent:

  • The following MIBs define the SMI language:

17.1.1. Implementing MIBs

To set up an SNMP agent to manage objects in the MIB the following information must be provided:

  • MIB

  • YANG (.yang or .yin) file.

  • Associations between objects in the MIB and nodes in the YANG module.

  • Instrumentation functions (not needed for config data if CDB is used)

The MIBs are typically already existing standard or proprietary enterprise MIBs, but they can also be generated from the YANG models.

The MIB compiler needs a mapping between the MIB object to nodes in the YANG module. This is done by adding YANG statements to the data model, that associate YANG nodes with objects in the MIB. The association statements can be written directly in the YANG module file, or in a separate YANG annotation file (see tailf_yang_extensions(5)).

The confdc compiler verifies that the types of the SNMP objects and the types in the YANG module are compatible.

There are three main use cases to consider when implementing a MIB with ConfD:

  1. The MIB is given, and a YANG module is generated from the MIB.

    The YANG modules and associations are generated with the confdc --mib2yang translator program. The generated YANG modules will in this case resemble the structure of the MIBs.

  2. The MIB and YANG module are both given (or written manually).

    In this case, MIB associations should be written to bind MIB objects to the nodes in the YANG data model. Statements tailf:snmp-name, tailf:snmp-oid, etc. are added either directly in the YANG module or in a separate annotation file (see tailf_yang_extensions(5)).

  3. The YANG module is given (or written manually), and the MIB is generated from it.

    The MIBs are generated using the confdc --emit-mib command.

17.2. Agent Functional Description

The ConfD SNMP agent provides SNMP access to the data available through the ConfD management backplane. The same data can also be accessed via other protocols/applications such as NETCONF, Web UI, and CLI. This data can be stored in CDB, or made available by a data provider.

SNMP has certain features that are not meaningful to model in YANG. There are also some requirements on how the data is to be sorted in tables since SNMP operations require a strict lexicographical order of the elements in a table. Below is a listing of some of the SNMP specific behaviors and what needs to be done:

  • The RowStatus column in tables are handled by the SNMP agent and must not be part of the YANG model. Rows with a RowStatus column set to 'notReady' or 'notInService' are temporarily stored in the SNMP agent and will not show up in the database. Once activated they will be inserted into the database.

  • SNMP requires objects that are stored in tables to be ordered in a strict lexicographical order. If we have a list in a YANG module which is handled by an instrumentation function, the get_next() callback function (which must be provided by the user), must return the elements in the same lexicographical order as SNMP expects. If the order of the elements is not correct, then an SNMP manager will not be able to correctly traverse the elements in a table. If the list statement has a tailf:secondary-index with the name snmp, the agent will iterate over the table using this index. Thus, the instrumentation code can reply with instances in SNMP lexicographical order when the objects are retrieved over SNMP, and a more natural sort order when the objects are retrieved in the CLI and other northbound interfaces.

  • Tables with INDEX with dynamic length must have a length byte as part of the index. If the table index is specified as IMPLIED, then the length byte is excluded from the index. The statement tailf:sort-order can be specified in lists and secondary indexes in the YANG module, to control whether index elements should be ordered with the length byte included or not.

  • Enumerations must have the same enumerated values in YANG and in the MIB. Note that the symbolic string associated with the enum may be different in the YANG module and MIB.

  • SNMP v3 has support for contexts. The ConfD SNMP agent uses "" as the default context where all operations for this context are made towards the running database.

  • Scalar variables of TestAndIncr are automatically handled by the agent.

17.2.1. Operation Overview

The following steps are needed to get a ConfD SNMP agent up and running:

  1. Write a MIB module, generate one from a YANG module, or use an existing one.

  2. Write a YANG module, generate one from a MIB module, or use an existing one.

  3. Write associations that provide the mapping of MIB objects into YANG nodes.

  4. Write instrumentation functions for nodes in the YANG module, or store data in CDB.

  5. Compile the YANG module into an .fxs file.

  6. Run the MIB together with the YANG .fxs file, and an optional mib annotations file (.miba, see mib_annotations(5)), through the MIB compiler to produce a .bin file.

  7. Configure the agent (confd.conf and initial MIB data). Specify which compiled MIBs are to be loaded by the agent (.bin files) in confd.conf .

  8. The produced .fxs file as well as the .fxs files for the built-in MIBs must be found in the loadPath specified in confd.conf .

  9. Start ConfD.

17.2.2. MIBs and YANG

The basic objects in a MIB are scalar objects and table objects. Each MIB object must be mapped to a node in a YANG module. Scalar MIB objects must be mapped to YANG leafs with matching types, so that the agent can translate the value between the SNMP value and the internal value defined by the YANG type. Tables in the MIB must be mapped to lists in YANG. The mapping between the MIB objects and the YANG nodes is specified in the YANG module (or annotation file for the module) using tailf:snmp-name and tail:snmp-oid statements. tailf:snmp-name specifies the symbolic name of a MIB object, and tailf:snmp-oid specifies the corresponding OID.

Let us assume that we have the following MIB named SIMPLE-MIB containing a scalar and table:

-- a scalar
numberOfHosts OBJECT-TYPE
    SYNTAX      INTEGER (0..65535)
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
            "Return the current number of hosts"
    ::= { simpleVariables 1 }

-- a table
hostTable OBJECT-TYPE
    SYNTAX       SEQUENCE OF HostEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION
        "The table of hosts."
    ::= { simpleTables 1 }

hostEntry OBJECT-TYPE
    SYNTAX       HostEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION
        "Information about a host."
    INDEX       { hostName }
    ::= { hostTable 1 }

HostEntry ::= SEQUENCE {
    hostName              DisplayString,
    hostEnabled           TruthValue,
    hostNumberOfServers   Integer32,
    hostRowStatus         RowStatus
}

hostName OBJECT-TYPE
    SYNTAX      DisplayString
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "The unique index value of a row in this table."
    ::= { hostEntry 1 }

hostEnabled OBJECT-TYPE
    SYNTAX       TruthValue
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
        "A bool value saying if host is enabled or not."
    ::= { hostEntry 2 }

hostNumberOfServers OBJECT-TYPE
    SYNTAX       Integer32
    MAX-ACCESS   read-only
    STATUS       current
    DESCRIPTION
        "A read-only integer saying how many servers there currently are."
    ::= { hostEntry 3 }

hostRowStatus OBJECT-TYPE
    SYNTAX       RowStatus
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
        "The status of this conceptual row in the hostTable."
    ::= { hostEntry 4 }

An association must be written to bind the two SNMP objects (the scalar and the table) into YANG. Below is an example of a simple YANG module with SNMP statements that maps to SNMP objects in the MIB.

Example 17.1. Simple YANG module

module simple {
  namespace "http://tail-f.com/ns/simple";
  prefix simple;

  import ietf-inet-types {
    prefix inet;
  }
  import tailf-common {
    prefix tailf;
  }

  typedef nameType {
    type string {
      length "min .. 255";
    }
  }

  tailf:snmp-mib-module-name TAIL-F-TEST-MIB;

  container simpleObjects {

    leaf numberOfHosts {
      type uint16;
      mandatory true;
      tailf:snmp-name numberOfHosts;
    }

    container hosts {
      list host {
        key name;
        max-elements 64;
        tailf:sort-order snmp;
        tailf:snmp-name hostTable;
        tailf:snmp-row-status-column 4;

        leaf name {
          type nameType;
        }

        leaf enabled {
          type boolean;
          mandatory true;
          tailf:snmp-name hostEnabled;
        }

        leaf numberOfServers {
          type uint16;
          mandatory true;
          tailf:snmp-oid .3;
        }
      }
    }
  }
}

In the code listing above there is one variable numberOfHosts mapped to the SNMP scalar variable numberOfHosts using the tailf:snmp-name statement. The numberOfServers object uses the alternative notation with a tailf:snmp-oid statement. Which one to use is a matter of taste.

The list host is mapped to the SNMP table hostTable using tailf:snmp-name hostTable. It would also be possible to specify the tailf:snmp-oid if preferred. Notice also that for tables which support creation and deletion of rows through a RowStatus column, the statement tailf:snmp-row-status-column can be given. (This is not necessary if the model will be used with an existing MIB, but it is necessary for confdc --emit-mib to generate a writable table if the model is used for generating a new MIB.) See Section 17.2.9, “The RowStatus column” for more details.

It is possible to map one YANG node to multiple SNMP objects. For example, if an SNMP table augments another table, both these tables can be implemented in a single YANG list, where some leafs are mapped to the base table, and some are mapped to the augmented table.

The following example illustrates the idea. The single YANG list 'interface' is mapped to the MIB tables ifTable, ifXTable, and ipv4InterfaceTable:

list interface {
  key index;
  tailf:snmp-name 'ifTable'; // primary table
  tailf:snmp-name 'ifXTable';
  tailf:snmp-name 'IP-MIB:ipv4InterfaceTable';

  leaf index {
    type int32;
  }
  leaf description {
    type string;
    tailf:snmp-name 'ifDescr';  // mapped to primary table
  }
  leaf name {
    type string;
    tailf:snmp-name 'ifXTable:ifName';
  }
  leaf ipv4-enable {
    type boolean;
    tailf:snmp-name
      'IP-MIB:ipv4InterfaceTable:ipv4InterfaceEnableStatus';
  }
  ...
}

17.2.3. Types

When the SNMP agent receives a request to GET an object, it will lookup the object in the compiled MIB, and through the association information find the corresponding YANG node. Next, it will retrieve the correct instances value from a data provider. This value will be encoded according to the type in the YANG module. The SNMP agent translates this value to the corresponding SNMP value, and sends the reply to the manager. For this translation to work, the types in the YANG module and MIB must match.

The following table shows how SMI data types are mapped to YANG datatypes. This mapping is used internally in the agent in runtime, and also by the confdc --mib2yang program when a YANG module is generated from a MIB. See the confd_types(3) man page for details about the XSD and confd types.

Table 17.1. SMI mapping to YANG types

SMI YANG C value type XML example
OBJECT IDENTIFIER yang:object-identifier C_OID 1.3.6.1.2.1
IpAddress inet:ipv4-address C_IPV4 192.168.2.3
Unsigned32 uint32 C_UINT32
Gauge32 yang:gauge32 C_UINT32
Counter32 yang:counter32 C_UINT32
TimeTicks yang:time-ticks C_UINT32
Integer32 int32 C_INT32
Counter64 yang:counter64 C_UINT64
INTEGER { enums... } enumeration C_ENUMHASH udp
INTEGER int32 C_INT32 42
DisplayString string C_BUF/C_STR Hello world!
OCTET STRING (with DISPLAY-HINT on the form "Na" or "Nt") string C_BUF/C_STR Hello world!
OCTET STRING (binary), Opaque tailf:hex-list C_BINARY 4f:12:ff
IPV6-TC::Ipv6Address inet:ipv6-address C_IPV6 ::213.180.94.158
SNMPv2-TC::DateAndTime yang:date-and-time C_DATETIME 2006-08-17T16:30:53+02:00
SNMPv2-TC::TruthValue boolean, enumeration (1), empty C_BOOL, C_ENUMHASH true
SNMPv2-TC::PhysAddress yang:phys-addressC_BINARY
SNMPv2-TC::MacAddress yang:mac-addressC_BINARY
SNMPv2-TC::TimeStamp yang:timestampC_UINT32
SNMPv2-TC::TimeInterval int32C_INT32
SNMPv2-TC::TAddress tailf:octet-listC_BINARY

(1) SNMPv2-TC::TruthValue is a bit special. At runtime, the agent can map it either to a normal enumeration (which is how it is defined in SNMPv2-TC), to a boolean, to an empty leaf, or to a presence-container. When confd --mib2yang is used to create the YANG module from a MIB, it uses the enumeration mapping. This is also the recommended mapping. If a boolean is used, it cannot be part of the INDEX in a table.

The following table shows how YANG data types are mapped to SMI datatypes. This mapping is used internally in the agent in runtime, and also by the confdc --emit-mib program when a MIB is generated from a YANG module.

If the association between the MIB and YANG module is written manually, the type mappings in this table must be used.

Some of the more complex YANG types that cannot be easily translated to native SMI types are translated into strings of the type "ConfdString" In this case, the human-readable string value is passed over SNMP. These types cannot be used as INDEX in SNMP tables.

See the confd_types(3) man page for details about the XSD and confd types.

Table 17.2. YANG mapping to SMI types

YANG SMI C value type Use as INDEX
int32 Integer32 C_INT32 yes
int16 Integer32 (-32768..32767) C_INT16 yes
int8 Integer32 (-128..127) C_INT8 yes
uint64 ConfdString C_UINT64 yes
uint32 Unsigned32 C_UINT32 yes
uint16 Unsigned32 (0..65535) C_UINT16 yes
uint8 Unsigned32 (0..255) C_UINT8 yes
boolean SNMPv2-TC::TruthValue C_BOOL no
enumeration INTEGER { enums... } C_ENUMHASH yes
string OCTET STRING C_BUF / C_STR yes
decimal64 ConfdString C_DECIMAL64 no
int64 ConfdString C_INT64 no
union ConfdString depending on type no
binary OCTET STRING C_BINARY no
empty SNMPV2-TC::TruthValue C_BOOL no
identity not supported n/a n/a
yang:date-and-time SNMPv2-TC::DateAndTime C_DATETIME yes
yang:counter32 Counter32 C_UINT32 yes
yang:counter64 Counter64 C_UINT64 yes
yang:gauge32 Gauge32 C_UINT32 yes
yang:object-identifier OBJECT IDENTIFIER C_OID yes
xs:float, xs:double, xs:decimal ConfdString C_DOUBLE no
inet:ipv4-address IpAddress C_IPV4 yes
inet:ipv6-address IPV6-TC::Ipv6Address C_IPV6 yes
inet:ip-address OCTET STRING (SIZE (4|16)) C_IPV4 | C_IPV6 yes
inet:host ConfdString C_BUF / C_STR no
inet:domain-name ConfdString C_BUF / C_STR no
inet:port-number Unsigned32 (0..65535) C_UINT16 yes
inet:ipv4-prefix OCTET STRING (SIZE (5)) C_IPV4PREFIX yes
inet:ipv6-prefix OCTET STRING (SIZE (17)) C_IPV6PREFIX yes
inet:ip-prefix OCTET STRING (SIZE (5|17)) C_IPV4PREFIX | C_IPV6PREFIX yes
tailf:size OCTET STRING C_BUF / C_STR no
tailf:octet-list, tailf:hex-list OCTET STRING C_BINARY yes
xs:date ConfdString C_DATE no
xs:time ConfdString C_TIME no
xs:duration ConfdString C_DURATION no
xs:hexBinary OCTET STRING C_BINARY no
xs:QName not supported n/a n/a

A YANG presence container and a leaf of type empty can be mapped to a SMI scalar or columnar object of type SNMPv2-TC::TruthValue. If the empty leaf or presence container exists, the SMI object is 'true', and if it does not exist, but its parent exists, it has the value 'false'. Setting the SMI object to 'true' creates the leaf or presence container, and setting it to 'false' deletes it.

17.2.4. Generating the YANG module

The confdc --mib2yang is used to generate a YANG (.yang) files from MIBs. The element structure in the resulting YANG module will resemble the structure of the objects in the MIB.

If the MIB IMPORTs other MIBs, these MIBs must be available (as .mib files) to the compiler when a YANG module is generated. By default, all MIBs in the current directory and all builtin MIBs (see Section 17.1, “Introduction to the ConfD SNMP Agent”) are available. Since the compiler uses the tool smidump to perform the conversion to YANG, the environment variable SMIPATH can be set to a colon-separated list of directories to search for MIB files.

Example 17.2. Generating and compiling YANG from MIB

$ confdc --mib2yang -o SIMPLE-MIB.yang SIMPLE-MIB.mib
$ confdc -c -o SIMPLE-MIB.fxs SIMPLE-MIB.yang

Below is the generated YANG module. The structure of the YANG module resembles the structure of the SIMPLE-MIB it was generated from.

Example 17.3. The YANG file generated by confdc --mib2yang

module SIMPLE-MIB {
  namespace "http://tail-f.com/ns/mibs/SIMPLE-MIB/200702080000Z";
  prefix SIMPLE-MIB;
  tailf:id "";
  tailf:snmp-mib-module-name SIMPLE-MIB;

  import ietf-yang-types {
    prefix yang;
  }
  import ietf-inet-types {
    prefix inet;
  }
  import tailf-common {
    prefix tailf;
  }
  import tailf-xsd-types {
    prefix xs;
  }

  import SNMPv2-TC {
    prefix SNMPv2-TC;
  }

  revision 2007-02-08 {
    description "";
  }
  container SIMPLE-MIB {
    container variables {
      tailf:snmp-oid 1.3.6.1.4.1.24961.3.1.1;
      leaf numberOfHosts {
        type int32;
        tailf:snmp-oid 1.3.6.1.4.1.24961.3.1.1.1;
      }
    }
    container hostTable {
      list hostEntry {
        key hostName;
        tailf:sort-order snmp;
        tailf:snmp-oid 1.3.6.1.4.1.24961.3.1.2.1;
        leaf hostName {
          type hostNameType;
          tailf:snmp-oid 1.3.6.1.4.1.24961.3.1.2.1.1.1;
        }
        leaf hostEnabled {
          type SNMPv2-TC:TruthValue;
          tailf:snmp-oid 1.3.6.1.4.1.24961.3.1.2.1.1.2;
        }
        leaf hostNumberOfServers {
          type int32;
          tailf:snmp-oid 1.3.6.1.4.1.24961.3.1.2.1.1.3;
        }
      }
    }
  }
  typedef hostNameType {
    type string {
      length "min .. 64";
    }
  }
}

17.2.5. Compiling the YANG modules

Compile the YANG modules representing MIBs the same way that any other YANG module is compiled, using confdc .

Note that all YANG modules representing the builtin MIBs are available in $CONFD_DIR/src/confd/snmp/yang directory. The parameter --yangpath can be given to the compiler to search this directory.

17.2.6. Compiling the MIBs

MIB compilation

The confdc compiler is used for compiling the MIB into a binary format that can be loaded by the ConfD SNMP agent. The MIB is compiled with the YANG .fxs file with associations that map the YANG nodes into objects in the MIB. The resulting file is a binary (.bin) file that is loaded into the ConfD SNMP agent.

$ confdc -c SIMPLE-MIB.mib simple.fxs

If the MIB IMPORTs other MIBs, these MIBs must be available (as compiled .bin files) to the compiler. By default, all compiled MIBs in the current directory and all builtin MIBs are available. Use the parameters --include-dir or --include-file to specify where the compiler can find the compiled MIBs.

Note that not every object in the MIB must have a mapping to a node in the YANG module. By using a separate MIB annotation file, ConfD can be instructed how these missing objects should be treated by the SNMP agent. The agent can treat the objects either as not implemented, or as implemented but non-existent.

The format of an annotation line is object-name annotation, where object-name is the name of an object type (column or scalar), and annotation has the form behavior=noSuchObject, behavior=noSuchInstance, max_access=not_accessible, max_access=read_only.

If a line is blank or starts with a # character, it is ignored. An object name may occur on several lines.

Example:

$ cat HOST-RESOURCES-MIB.miba
# tell the agent to not implement these objects
hrPartitionID           behavior=noSuchInstance
hrSWInstalledDate       behavior=noSuchObject
$ confdc -c HOST_RESOURCES-MIB.mib \
         --mib-annotation HOST_RESOURCES.miba host-resources.fxs
          

17.2.7. Loading MIBs

The ConfD SNMP agent have the following built-in MIBs:

  • SNMPv2-MIB, a mandatory MIB for an agent. This MIB is always loaded at start-up.

  • SNMP-MPD-MIB, a mandatory MIB for an agent. This MIB is always loaded at start-up if the agent is configured for SNMPv3.

  • SNMP-FRAMEWORK-MIB, a mandatory MIB for an agent. This MIB is always loaded at start-up if the agent is configured for SNMPv3.

  • SNMP-COMMUNITY-MIB, handles SNMP v1 and v2c communities.

  • SNMP-VIEW-BASED-ACM-MIB, handles the view based access control.

  • SNMP-USER-BASED-SM-MIB, handles the user based access control.

  • SNMP-TARGET-MIB, to be able to configure targets for SNMP traps.

  • SNMP-NOTIFICATION-MIB, defines SNMP traps.

  • IPV6-TC, defines some IPv6 specific TEXTUAL-CONVENTIONs.

  • TRANSPORT-ADDRESS-MIB, defines some OBJECT-IDENTITYs for transport protocols. This MIB module cannot be loaded as a built-in module in the agent. If some other MIB IMPORTs this MIB, then it needs to be compiled and loaded as other non-built-in MIBs.

  • SNMP-USM-AES-MIB, defines an OBJECT-IDENTITY for the AES privacy protocol. This MIB module must not be loaded into the agent.

These MIBs of course must have their corresponding YANG .fxs files loaded in order for the SNMP agent to work (see the next section). The MIBs themselves are not required to be loaded. The user decides which MIBs should be loaded, and there may be reasons to not provide SNMP access to certain MIBs.

The MIBs SNMPv2-MIB, SNMP-MPD-MIB, and SNMP-FRAMEWORK-MIB, are always loaded into the ConfD SNMP agent at start-up. These MIBs are required for an SNMP agent.

The other built-in MIBs are not loaded per default, which means that they cannot be accessed/configured via SNMP but of course via for example CDB init files (see Section 5.8, “Loading initial data into CDB”) NETCONF, or even CLI directly. If the intention is to have these MIBs loaded, they must be listed in confd.conf without any explicit paths to where they are stored as shown in the example below.

Other MIBs (that are not built-in) are loaded by specifying their absolute or relative paths, or alternatively the MIBs can be loaded from ConfDs loadPath. We recommend that these MIBs are loaded from the load path. This is how other data model files (.fxs etc) are handled.

The main reason for this recommendation is how MIBs can be dynamically reloaded. MIBs that are explicitly listed are reloaded by giving the command confd --reload. If any MIB cannot be loaded for whatever reason, ConfD halts. MIBs in the load path are reloaded using the data model upgrade functions, see Chapter 13, In-service Data Model Upgrade.

Example 17.4. Specifying built-in MIBs to be loaded into the agent

<snmpAgent>
  <enabled>true</enabled>
  <mibs>
    <!-- Load built-in MIBS -->
    <file>SNMP-COMMUNITY-MIB.bin</file>
    <file>SNMP-VIEW-BASED-ACM-MIB.bin</file>
    <file>SNMP-USER-BASED-SM-MIB.bin</file>
    <file>SNMP-TARGET-MIB.bin</file>
    <file>SNMP-NOTIFICATION-MIB.bin</file>

    <!-- Load specific user MIBs -->
    <file>/etc/confd/mibs/SIMPLE-MIB.bin</file>

    <!-- Load all MIBs present in the loadPath -->
    <fromLoadPath>true</fromLoadPath>
  </mibs>
</snmpAgent>

17.2.8. Loading YANG modules for built-in MIBs

The SNMP agent has a few built-in MIBs that store its configuration data in CDB. The following .fxs files defines namespaces for the built-in MIBs and must be loaded at start-up if the SNMP agent is enabled:

  • SNMPv2-MIB.fxs, SNMPv2-SMI.fxs, SNMPv2-TC.fxs - contains base SNMPv2 types

  • SNMP-FRAMEWORK-MIB.fxs

  • SNMP-MPD-MIB.fxs

  • SNMP-COMMUNITY-MIB.fxs

  • SNMP-VIEW-BASED-ACM-MIB.fxs

  • SNMP-USER-BASED-SM-MIB.fxs

  • SNMP-TARGET-MIB.fxs

  • SNMP-NOTIFICATION-MIB.fxs

Preferably a loadPath in the confd.conf file can be set to the directory where these files are installed. If ConfD fails to load these files it will terminate with a fatal error.

The built-in .fxs files are delivered as pre-built, but the YANG source code is provided as well. Tampering with these files is not advised and may result in a serious internal error. However we may wish to recompile these YANG modules using the confdc compiler flag --export, to not expose the built-in MIB data to other ConfD internal protocols/applications such as NETCONF, CLI, and Web UI. The YANG source code is provided for this reason. Also it is possible to provide external callpoints for the built-in MIB data to store the data in an external database instead of CDB.

17.2.9. The RowStatus column

The rowstatus column for tables is always handled by the SNMP agent and should not be modeled in the YANG modules. The tailf:snmp-row-status-column statement can be left out and the row status column will be looked up by the compiler.

The RowStatus column in an SNMP table is used for reading the status of a conceptual row in a table and for creating and deleting new conceptual rows in the table. The following values are always defined for the row status:

  • active (1) - indicates that the conceptual row is available.

  • notInService (2) - indicates that the conceptual row is unavailable. This is a temporary state where the row is stored in the SNMP agent and not in the database. A row with a RowStatus of 'notInService' can be made 'active' which means that the row will be inserted into the database.

  • notReady (3) - indicates that the conceptual row is missing information. This is a temporary state where the row is stored in the SNMP agent and not in the database. A RowStatus of 'notReady' is returned to indicate that the row is missing a value for one or more mandatory column(s). When the row have all the mandatory values set, a RowStatus of 'notInService' will be returned instead of 'notReady'.

  • createAndGo (4) - set by manager to create new row instance.

  • createAndWait (5) - set by manager to create new row instance but not make it available. A RowStatus of 'notInService' or 'notReady' is returned depending on if all values for the mandatory columns are set or not.

  • destroy (6) - set by manager to delete all instances in the conceptual row.

The createAndWait creates a new instance of a conceptual row in a temporary state where the row will have a RowStatus set to 'notReady' or 'notInService' depending on if all the mandatory columns are set for the column or not. It can be made 'active' and will then be inserted into the database. Note that there are no guarantees that the row will exist more than 5 minutes (by default) in the temporary storage in the SNMP Agent. The temporary cache used by the SNMP agent for this storage is volatile. The temporary storage time can be configured in by setting temporaryStorageTime in confd.conf .

To delete a conceptual row the destroy value is used.

17.2.10. TestAndIncr

When a YANG module is generated from a MIB, and the MIB contains any scalar object of type TestAndIncr, these objects are not translated into the YANG module, since they don't make sense outside SNMP. Then, when the MIB is compiled, the compiler generates code so ConfD automatically handles these objects. No coding is required.

17.2.11. MIB access and YANG config

Objects in MIBs can be read-only or writable. In YANG, nodes are marked as representing configuration or non-configuration data.

Read-only MIB objects

If a MIB object is read-only, it can be mapped to a configuration or non-configuration YANG node.

When a YANG module is generated from a MIB, all read-only MIB objects are translated into non-configuration YANG nodes.

Writable MIB objects

If a MIB object is writable, it is usually mapped to a configuration YANG node. However, in some cases, the MIB object doesn't really represent configuration, but is rather writable operational data. An example could be a scalar variable rebootRouter. When written to, the router will reboot. In order to support this, non-configuration YANG nodes can be marked with tailf:writable true. Writable MIB objects can be mapped into non-configuration YANG nodes that are marked with tailf:writable true.

When a YANG module is generated from a MIB, writable MIB objects are translated into configuration YANG nodes, unless the MIB object is marked as representing writable operational data in a MIB annotation file (see mib_annotations(5)).

If the SNMP agent receives a SET PDU with one or more writable operational objects, it will start a read-write transaction towards CONFD_OPERATIONAL. In this transaction, the agent will write all variables from the PDU, and then it will commit the transaction. Instrumentation code needs to be written to handle these writes.

See Section 7.8, “Writable operational data” for how these objects are implemented, and examples.confd/snmpa/9-writable-operational in the ConfD examples collection for an example of how this can be implemented.

17.2.12. Optional YANG nodes

There is no protocol support in SNMP to delete optional nodes. Conceptual table rows are typically created and deleted by using a RowStatus column, but there is no standardized way to delete optional nodes. One technique to handle this is to introduce a special value for the object, so that the object is deleted when it is set to this special value. ConfD supports this technique with the YANG extension tailf:snmp-delete-value.

In order to use this technique, an optional leaf in the YANG model is mapped to a scalar or columnar object in the MIB module. The data type definition of the MIB object allows the same values as the corresponding YANG leaf, and in addition it also allows one extra value, not allowed by the YANG leaf. This special value is also defined in the YANG model in the tailf:snmp-delete-value statement.

In the following example, we define a MIB object fooOptionalLeaf, and corresponding YANG leaf foo-optional-leaf.

Example 17.5. SMI definition of an optional object

fooOptionalLeaf OBJECT-TYPE
    SYNTAX       Integer32 (0..255)
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
        "The special value zero means not used."
    ::= { fooEntry 3 }

Example 17.6. YANG definition of an optional leaf

leaf foo-optional-leaf {
  type int32 {
    range "1..255";
  }
  tailf:snmp-delete-value 0;
  tailf:snmp-name fooOptionalLeaf;
}

When the SNMP agent receives a SET request to set this object to '0', the leaf will be deleted.

If the tailf:snmp-delete-value statement has the substatement tailf:snmp-send-delete-value, the same special value will be returned on a GET request, instead of the default noSuchInstance.

17.2.13. tailf:sort-order on tables

Tables in SNMP are strictly lexicographically ordered. An SNMP table is typically traversed with GET-NEXT requests, where given a previous index of a row the next greater index is returned. Since the table is specified in a YANG module and may be stored in an external database or perhaps as a managed object (MO) written in C, it is important that the get_next() function returns the elements in correct order. If the get-next function doesn't return the elements properly in order, SNMP will not work. If CDB is used to store the data the ordering of the elements will be correct. Note that the tailf:sort-order statement may have to be specified for indexes with dynamic length (see Section 17.2.8, “Loading YANG modules for built-in MIBs”).

Types with dynamic length in SNMP like OCTET STRING will have a length indicator when they are part of the INDEX, so the ordering for strings stored in such a table will be on length first, unless they are declared as IMPLIED as in IMPLIED OCTET STRING. In this case the index will not have any length indicator included, and the table should be sorted as normal.

The following values can be given to the tailf:sort-order statement:

normal

This is the default and means that the table is sorted using the key values. This value should be used when the corresponding SNMP table does not have any INDEX object with dynamic length.

snmp

This value means that when sorting, any key element of dynamic length will have the length prepended to the value before sorting. It should be used if the corresponding SNMP table has any INDEX object with dynamic length, and no IMPLIED object.

snmp-implied

This value is the same as snmp, except that the last key element will not prepend the length indicator to the key value. It should be used if the corresponding SNMP table has any IMPLIED INDEX.

Here's an example of a MIB table with a DisplayString with dynamic length as index.

Example 17.7. simple.mib

hostTable OBJECT-TYPE
    SYNTAX       SEQUENCE OF HostEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION
        "The table of hosts."
    ::= { simpleTables 1 }

hostEntry OBJECT-TYPE
    SYNTAX       HostEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION
        "Information about a host."
    INDEX       { hostName }
    ::= { hostTable 1 }

HostEntry ::= SEQUENCE {
    hostName             DisplayString,
    hostEnabled          TruthValue,
    hostNumberOfServers  INTEGER,
    hostRowStatus        RowStatus
}

If the list corresponding to this SNMP table is stored in CDB, the definition in the YANG module must specify tailf:sort-order snmp so that the table is sorted correctly (with length indicator included).

Example 17.8. simple.yang


list host {
  key name;

  tailf:sort-order snmp;

  leaf name {
    type nameType;
  }

  leaf enabled {
    type boolean;
    mandatory true;
  }

  leaf numberOfServers {
    type uint16;
    mandatory true;
  }
}

When the sort order is set to "snmp" or "snmp-implied" on a list, it affects the displayed sort order in all northbound interfaces. Thus the list of hosts above will be sorted according to SNMP lexicographical ordering, even in e.g. the CLI. Sometimes this may be confusing to users. This problem can be solved by adding a tailf:secondary-index to the list:

Example 17.9. simple.yang with secondary index

list host {
  key name;

  tailf:secondary-index snmp {
    tailf:index-leafs "name";
    tailf:sort-order snmp;
  }

  leaf name {
    type nameType;
  }

  leaf enabled {
    type boolean;
    mandatory true;
  }

  leaf numberOfServers {
    type uint16;
    mandatory true;
  }
}

When the SNMP agent traverses a table, it checks if there is a secondary-index with the reserved name "snmp" defined for the table. If there is such an index, the agent traverses the table using this index.

In the example above, the host table is sorted in normal order, which means that "arthur" appears before "ford". But since there is a secondary-index called snmp, the SNMP agent will use this index when traversing the table, so that 4."ford" appears before 5."arthur" over SNMP.

Note that the presence of a secondary-index in the YANG module is not enough; the instrumentation code must be prepared to perform the actual sorting. See confd_lib_dp(3) for details.

17.2.14. Enumerations

Enumerations in SNMP have textual representation mapped to an integer. A simple example would be the definition for TruthValue:

Example 17.10. TruthValue from the SNMPv2-TC

TruthValue ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Represents a boolean value."
    SYNTAX       INTEGER { true(1), false(2) }


The confdc --mib2yang tool produces the following type definition for TruthValue:

Example 17.11. A typedef for TruthValue

typedef TruthValue {
  type enumeration {
    enum true {
      value 1;
    }
    enum false {
      value 2;
    }
  }
}

17.2.15. Notifications

Notifications are defined by the NOTIFICATION-TYPE macro in SMIv2. There are two types of notifications in SNMP: trap and inform. When the managed object needs to send trap notifications the following functions should be called (from MO's written in C).

Example 17.12. Functions for sending notification from C

int confd_register_snmp_notification(
    struct confd_daemon_ctx *dx, int fd,
    const char *notify_name, const char *ctx_name,
    struct confd_notification_ctx **nctx);

int confd_notification_send_snmp(
    struct confd_notification_ctx *nctx, const char *notification,
    struct confd_snmp_varbind *varbinds, int num_vars);
            

The confd_register_snmp_notification() function is typically called once to register the parameters common to a set of notifications, and then the individual notifications are sent by calling confd_notification_send_snmp(). The daemon context pointer dx is obtained by calling confd_init_daemon(), and the socket file descriptor fd is a worker socket connected to the ConfD daemon via a call to confd_connect(). See confd_lib_dp(3) man page for details about these functions. Note also that a control socket must be connected to the ConfD daemon before calling confd_register_snmp_notification().

The notify_name parameter matches the NotifyName in the snmpNotifyTable in the SNMP-NOTIFICATION-MIB. Trap will be sent to targets pointed out by NotifyName. If NotifyName is ""; the normal procedure defined in SNMP-NOTIFICATION-MIB is used, i.e. the trap is sent to all managers. Otherwise, the NotifyName is used to find an entry in the SnmpNotifyTable which defines how to send the notification (as an Inform or a Trap), and to select targets from SnmpTargetAddrTable (using the Tag).

The ctx_name is the name of the context. The default context is "".

The notification string is the notification name. For example "coldStart" or "warmStart". This symbolic name of a notification must be defined in a MIB that is loaded into the agent.

If the empty string is used as notification name, the notification to send is constructed from the varbinds array alone, which must then contain a value for the snmpTrapOID variable.

The varbinds array contains variable bindings for parameters that should be sent along in the notification. The include file confd_lib.h defines data structures for these:

Example 17.13. SNMP varbind structures from confd_maapi.h

enum confd_snmp_var_type {
    CONFD_SNMP_VARIABLE = 1,
    CONFD_SNMP_OID      = 2,
    CONFD_SNMP_COL_ROW  = 3
};

struct confd_snmp_oid {
    int oid[128];
    int len;
};

struct confd_snmp_col_row {
    char column[256];
    struct confd_snmp_oid rowindex;
};

struct confd_snmp_varbind {
    enum confd_snmp_var_type type;
    union {
        char name[256];
        struct confd_snmp_oid oid;
        struct confd_snmp_col_row cr;
    } var;
    confd_value_t val;
};
            

Each varbind is either:

a variable

a symbolic name of a scalar variable referred to in the notification specification.

a column

a symbolic name of a column variable. Rowindex is the index of the specified column.

an OBJECT IDENTIFIER

for the instance of an object, scalar variable or column variable.

If a value is given it will be used. If it is not given (i.e. set to C_NOEXISTS) then the agent will look up the value with a GET operation.

Example 17.14. Notification registration

int setup(struct confd_daemon_ctx *dctx, int workersock,
          struct confd_notification_ctx **nctx)
{
    if (confd_register_snmp_notification(dctx, workersock,
                                         "std_v1_trap", "", nctx)) != CONFD_OK)
        return CONFD_ERR;
    return confd_register_done(dctx);
}
             

Example 17.15. Sending a coldStart notification

int test1(struct confd_notification_ctx *nctx)
{
    return confd_notification_send_snmp(nctx, "coldStart", NULL, 0);
}
             

Example 17.16. Sending a notification with a varbind

int test2(struct confd_notification_ctx *nctx)
{
    struct confd_snmp_varbind vb;
    vb.type = CONFD_SNMP_VARIABLE;
    strcpy(vb.var.name, "myVariable");
    CONFD_SET_INT32(&vb.val, 32);
    return confd_notification_send_snmp(nctx, "notif1", &vb, 1);
}
             

The inform type notifications are similar to the trap type except there is an acknowledgment sent back from the manager that received the inform. Two callbacks needs to be registered to receive the result of the inform, and there's a separate function for sending an inform.

int confd_register_notification_snmp_inform_cb(
    struct confd_daemon_ctx *dx,
    const struct confd_notification_snmp_inform_cbs *cb);
int confd_notification_send_snmp_inform(
    struct confd_notification_ctx *nctx, const char *notification,
    struct confd_snmp_varbind *varbinds, int num_vars,
    const char *cb_id, int ref);

The struct confd_notification_snmp_inform_cbs is defined as:

struct confd_notification_snmp_inform_cbs {
    char cb_id[MAX_CALLPOINT_LEN];
    void (*targets)(struct confd_notification_ctx *nctx,
                    int ref, struct confd_snmp_target *targets,
                    int num_targets);
    void (*result)(struct confd_notification_ctx *nctx,
                   int ref, struct confd_snmp_target *target,
                   int got_response);
    void *cb_opaque;        /* private user data */
};

In order to debug the notification sending process in ConfD, the /confdConfig/logs/developerLogLevel in confd.conf(5) can be set to "trace".

17.3. Generating MIBs from YANG

The previous sections have discussed the scenario where there is an existing set of MIB files, and then confdc --mib2yang is used to convert these to YANG with the associations that the agent needs.

If instead no MIBs exist, but a number of YANG files (complied to .fxs files), these can be translated to MIB files (in SMIv2 syntax), using the --emit-mib option of confdc.

The normal operation of the translator is to select those nodes that have an tailf:snmp-oid statement, and ignore the others. If the option --generate-oids is given (described later in this section), all elements are selected, unless explicitly marked with tailf:snmp-exclude-object.

The value of the tailf:snmp-oid statement can be either a one-component suffix, for example ".4", or a full OID, such as "1.3.6.1.4.1.12345" or "private.1.12345". If it's a suffix, a full OID should be specified for some ancestor element, in the YANG module header, or using the --oid option.

In order to be selected for translation to the MIB file, an element must also match the module name. The module name can be given as an tailf:snmp-mib-module-name statement in the YANG module header, which is then inherited by all nodes, or using the --module option. It can also be specified on a node, which then overrides the value from the header or ancestor nodes.

Since tables can not reside inside tables in SMI, lists containing lists are handled by moving the inner lists up to top level.

Nodes inside containers in lists are given OIDs directly below the table entry, and names which are the concatenation of the path down from the table level. The containers should not have an OID.

If a RowStatus column is desired for a table, use the statement tailf:snmp-row-status-column on the corresponding list. The statement's value should be the column number (i.e., the last OID component, with no leading period). The object will be called rowstatus.

17.3.1. Translating a .fxs file to a MIB

The form of the translation command is shown below (using fictitious parameters):

confdc --emit-mib FOO-MIB.mib --oid enterprises.24961 -- foo.fxs

The basename of the output file (here, FOO-MIB) by default becomes the name of the module (with all letters made upper case). The option --module can be used to specify the module name.

Any other .fxs files we depend on have to be given with -f, as usual.

confdc --emit-mib FOO-MIB.mib --oid enterprises.24961 -f types.fxs -- foo.fxs

To build the .bin file to be loaded by the ConfD SNMP agent, do

confdc -c FOO-MIB.mib foo.fxs -f types.fxs

During translation, problems are reported as warnings or errors. When an error occurs, translation continues so that a complete MIB file is still produced, but the exit status from confdc is 1, rather than 0.

17.3.2. --generate-oids

With the option --generate-oids, the translator selects all nodes, inventing OIDs for the nodes which don't already have an tailf:snmp-oid statement. If a node has a tailf:snmp-exclude-object statement, it is ignored. The --generate-oids is useful when the original YANG module cannot be modified.

By default, the OID suffixes of child elements are numbered consecutively, starting with 1. This can be overridden with a suffix tailf:snmp-oid on a node. The suffixes of the following elements will continue from that point.

A RowStatus element is always generated.

Since the MIB compiler (i.e., confdc -c when given a MIB file) needs to know the association between MIB objects and YANG nodes, and this association is not present in the YANG module (if it was, there would be no need for generating OIDs), we use YANG annotation files.

A YANG annotation file is used to define the mapping between YANG nodes and MIB objects. The YANG annotation file can be written by hand, or generated from the YANG module. Since it is important in SNMP that OIDs once assigned do not change, it is recommended to generate an initial version of a YANG annotation file, and then update it manually as the YANG module evolves. The process to do this is:

  • Compile the YANG module: confdc -c foo.yang

  • Generate an initial YANG annotation file: confdc --emit-mib FOO-MIB.mib --oid experimental.1 --generate-oids --generate-yang-annotation foo.fxs

    The YANG annotation file will be called foo-ann.yang.

Once the initial YANG annotation file is generated, it should be kept and updated as the original YANG module is updated. The MIB can then be generated as needed:

  • Compile the YANG module and annotation file: confdc -c -a foo-ann.yang foo.yang

  • Generate the MIB: confdc --emit-mib FOO-MIB.mib foo.fxs

  • Compile the MIB: confdc -c FOO-MIB.mib foo.fxs

17.3.3. Lexical structure

At the start of the generated MIB file, a header of comments gives some information on how the file was produced, including the confdc invocation, the namespace of the .fxs file, and the current date and time. (Any -- strings are converted to ++ because the former cannot occur in SMI comments.)

The only field in the module header which can be filled in with information from the .fxs file is the first DESCRIPTION field, which is taken from the YANG module's description statement, if one exists.

The remaining fields have the following format, in order to facilitate automatic editing of the values:

    LAST-UPDATED "@LAST-UPDATED"
    ORGANIZATION "@ORGANIZATION"
    CONTACT-INFO "@CONTACT-INFO"
    REVISION "@REVISION"
    DESCRIPTION "@REVISION-DESCRIPTION"
              

17.3.4. Names

The names of the objects are constructed by joining all the parts of the full tag path of the nodes, capitalizing each part. An alternative is to not capitalize, and join the parts with "-" (with the option --join-names hyphen see the section called “Emit SMIv2 MIB options”).

If the statement tailf:snmp-name is used on a node, its value is taken as the full name of the object. For containers and tables, it also becomes the first part of its children's names.

The characters '.' and '_' can occur in YANG identifiers but not in SNMP identifiers; they are converted to '-', unless the option --join-names force-capitalize is given. In this case, such identifiers are capitalized (to lowerCamelCase).

If generated names clash with each other (for example both /x/a/b-c and /x/a-b/c yielding the name x-a-b-c), an error is reported.

17.3.5. Types

YANG types are mapped according to the table in Table 17.2, “YANG mapping to SMI types”. .

The type restrictions that deal with lengths ranges are translated. The remaining restrictions (pattern, fraction-digits) are silently ignored.

If inet:ipv6-address is used, Ipv6Address is imported from IPV6-TC. Otherwise, imports are only made from SNMPv2-SMI, SNMPv2-CONF and SNMPv2-TC.

Leafs with types which are not handled are skipped in the translation, with a warning.

Identifiers which have an invalid syntax (for example, start with a digit) are kept in the translation, but a warning is given.

If a leaf with type yang:counter64 is used as an index or as writable, a warning is given.

17.3.6. Miscellaneous

STATUS is current by default for all objects. To cause STATUS to be deprecated or obsolete, use the YANG statement status with the corresponding value on the YANG node.

MAX-ACCESS is read-only for operational nodes (having config false;).

Actions are silently ignored.

Before each generated OBJECT-TYPE and OBJECT IDENTIFIER, a comment containing the word "tagpath" indicates which YANG node the object corresponds to.

DESCRIPTION is copied from the .fxs file, when available (if the description statement is present). For containers, they are emitted as comments instead (the string "--" is replaced with "- -"). description for nodes that are not translated into any OID are lost. Double quote characters, which can't occur in DESCRIPTION, are replaced with single quotes.

For a string with a min length, but no max length, the max length is assumed to be 65535.

tailf:sort-order snmp-implied; results in the IMPLIED keyword, if appropriate for the type.

If a type containing negative values is used as an index, or if a string with unlimited length is used as an index, a warning is given.

If a list uses tailf:sort-order normal, the child nodes may not appear in SNMP order when listed, and so some elements may get lost, or confuse the manager. A warning is given for such cases.

If tailf:sort-order snmp-implied is used for one list list, which contains another list, the last index of the outer list (with implied length) can no longer have implied length in SNMP, so agent communication will most likely fail.

DEFVAL clauses are emitted for string and integer types (including bit types), but not for others.

17.4. Configuring the SNMP Agent

Configuration data for the ConfD SNMP agent consists of:

  • data in confd.conf

  • data for built-in MIBs

The configuration data in confd.conf is typically only configured once and then never changed. (It is possible to change however).

To store initial data for the built-in MIBs, CDB init files can be used. CDB init files are loaded the first time the system is started and the database is initialized with this data. See Section 5.8, “Loading initial data into CDB”. Typically these files will define access rules and users of the agent. Updating the MIB data is done directly from the northbound agents such as NETCONF or CLI. The confdc compiler flag --export can be used to grant access for applications / protocols such as NETCONF and CLI to modify the built-in SNMP data. For this reason the YANG source for the built-in MIBs are provided so that they can be recompiled with the --export flag.

The data for the SNMP agent built-in MIBs are by default stored in CDB, but it is also possible have this data in an external database. In this case the user needs to add external callpoints to the YANG modules and recompile them.

17.4.1. Configuration data in confd.conf

There are a few elements that must be configured in confd.conf in order for the SNMP agent to start. First of all the ConfD SNMP agent must be enabled, and it must have an address and a port that it will try to bind to at start-up. If if fails to bind to the port, ConfD will fail to start. It should also have a list of MIBs that should be loaded into the agent. If it fails to load any of the MIBs, ConfD will fail to start.

Several options can be given to control the behavior of the SNMP agent:

enabled

Whether or not the agent should be started.

ip, port

The IP address and port that the agent will bind and listen for incoming requests to.

mibs

The MIBs that the agent should load at start-up.

snmpVersions

The version of the SNMP protocol that the agent will understand (the supported versions are v1, v2c, and v3).

snmpEngineID, snmpEngineMaxMessageSize

The engine identifier and max message size that this agent can handle.

sysDescr

Description of the entity. The description should include the full name and version identification of the system. See SNMPv2-MIB for more information.

sysObjectID

The vendor's authoritative identification of the network management subsystem contained in the entity. See SNMPv2-MIB for more information.

sysServices

A value which identifies the set of services that this entity primarily offers. See SNMPv2-MIB for more information.

sysORTable

An optional table with SNMP agent capabilities. These entries will populate the real sysORTable in the SNMPv2-MIB.

Below is an example of a confd.conf file:

Example 17.17. Example of a confd.conf

<snmpAgent>
   <enabled>true</enabled>
   <ip>0.0.0.0</ip>
   <port>161</port>
   <mibs>
      <file>SIMPLE-MIB.bin</file>
   </mibs>
   <snmpVersions>
      <v1>true</v1>
      <v2c>true</v2c>
      <v3>false</v3>
   </snmpVersions>
    <snmpEngine>
      <snmpEngineID>80:00:61:81:05:01</snmpEngineID>
    </snmpEngine>
   <system>
      <sysDescr>Tail-f ConfD agent</sysDescr>
      <sysObjectID>1.3.6.1.4.1.24961</sysObjectID>
   </system>
</snmpAgent>

This will enable the SNMP agent, which will listen to requests incoming to locally at port 161. The MIB file SIMPLE-MIB.bin is loaded in the agent, and the agent will understand SNMP versions v1 and v2c, but not v3.

17.4.2. Changing configuration data in confd.conf in run-time

The data stored in confd.conf can be changed by modifying the file and then issuing a confd --reload command. This will trigger an already running ConfD daemon to check its configuration data and make the necessary changes. Certain changes like the SNMP agents IP address will trigger an internal restart of the SNMP agent (ConfD will still remain up), other changes like the MIBs that are loaded can be done without restarting the SNMP agent. It's thus possible to update the MIBs in a running ConfD SNMP agent without restarting the SNMP agent.

Example 17.18. Old confd.conf content

<snmpAgent>
  <enabled>true</enabled>
  <ip>0.0.0.0</ip>
  <port>161</port>
  <mibs>
    <file>SIMPLE-MIB.bin</file>
  </mibs>
</snmpAgent>

Example 17.19. Updated confd.conf content

<snmpAgent>
  <enabled>true</enabled>
  <ip>0.0.0.0</ip>
  <port>161</port>
  <mibs>
    <file>SIMPLE-MIB.bin</file>
    <file>SIMPLE-MIB2.bin</file>
  </mibs>
</snmpAgent>

The example above will on a confd --reload command unload all the loaded MIBs that were specified on the old configuration, and load the MIBs specified in the updated configuration. The MIB SIMPLE-MIB.bin is unloaded and then loaded again, which can be useful during development to update to a newer version of the MIB.

17.4.3. Built-in MIB data

There is a set of standard MIBs which are used to control and configure an SNMP agent. These MIBs are implemented in this agent. The user can control which of these MIBs are actually loaded into the agent, and thus made visible to SNMP managers. For example, in a non-secure environment, it might be a good idea to not make MIBs that define access control visible. Note, the data that the MIBs define is used internally in the agent, even if the MIBs are not loaded.

Any SNMP agent must implement the system group and the snmp group, defined in SNMPv2-MIB. This MIB will be loaded by default.

An SNMPv3 agent must implement the SNMP-FRAMEWORK-MIB and SNMP-MPD-MIB. These MIBs are also loaded by default, if the agent is configured for SNMPv3.

There are five other standard MIBs, which also may be loaded into the agent. These MIBs are:

  • SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB which defines managed objects for configuration of management targets, i.e. receivers of notifications (traps and informs). These MIBs can be used with any SNMP version.

  • SNMP-VIEW-BASED-ACM-MIB, which defines managed objects for access control. This MIB can be used with any SNMP version.

  • SNMP-COMMUNITY-MIB, which defines managed objects for coexistence of SNMPv1 and SNMPv2c with SNMPv3. This MIB is only useful if SNMPv1 or SNMPv2c is used, possibly in combination with SNMPv3.

  • SNMP-USER-BASED-SM-MIB, which defines managed objects for authentication and privacy. This MIB is only useful with SNMPv3.

Initial config data for communities, access rules, users etc. is preferably stored in CDB init files. They are read once when the system is started for the first time and put in the database. The files must be located in the dbDir. Typically a system have the following CDB init files for the built-in MIBs (the file name can be anything but must end with the suffix _init.xml):

community_init.xml

Data for SNMP-COMMUNITY-MIB. Defines the communities that have access to the system.

vacm_init.xml

Data for SNMP-VIEW-BASED-ACM-MIB. Defines view based access.

usm_init.xml

Data for SNMP-USER-BASED-SM-MIB. Defines user based access used with authentication and privacy. This is only used with SNMP v3.

target_init.xml

Data for SNMP-TARGET-MIB. Defines trap targets.

notify_init.xml

Data for SNMP-NOTIFICATION-MIB. Defines notifications.

Below is an example of an init file to define a community within the agent.

Example 17.20. Example community_init.xml

<SNMP-COMMUNITY-MIB
        xmlns="http://tail-f.com/ns/mibs/SNMP-COMMUNITY-MIB/200308060000Z">
  <snmpCommunityTable>
    <snmpCommunityEntry>
      <snmpCommunityIndex>public</snmpCommunityIndex>
      <snmpCommunityName>public</snmpCommunityName>
      <snmpCommunitySecurityName>public</snmpCommunitySecurityName>
      <snmpCommunityContextEngineID>80:00:61:81:05:01</snmpCommunityContextEngineID>
      <snmpCommunityContextName/>
      <snmpCommunityTransportTag/>
      <snmpCommunityStorageType>permanent</snmpCommunityStorageType>
    </snmpCommunityEntry
  </snmpCommunityTable>
</SNMP-COMMUNITY-MIB>

SNMP-TARGET-MIB

The following values are supported for the object snmpTargetAddrTDomain:

  • SNMPv2-TM::snmpUDPDomain UDP over IPv4

  • TRANSPORT-ADDRESS-MIB::transportDomainUdpIpv4 UDP over IPv4 (same as snmpUDPDomain above)

  • TRANSPORT-ADDRESS-MIB::transportDomainUdpIpv6 UDP over IPv6

SNMP-USER-BASED-SM-MIB

The following authentication algorithms are supported:

  • SNMP-USER-BASED-SM-MIB::usmNoAuthProtocol No Authentication Protocol.

  • SNMP-USER-BASED-SM-MIB::usmHMACMD5AuthProtocol The HMAC-MD5-96 Digest Authentication Protocol.

  • SNMP-USER-BASED-SM-MIB::usmHMACSHAAuthProtocol The HMAC-SHA-96 Digest Authentication Protocol.

The following privacy algorithms are supported:

  • SNMP-USER-BASED-SM-MIB::usmNoPrivProtocol No Privacy Protocol.

  • SNMP-USER-BASED-SM-MIB::usmDESPrivProtocol The CBC-DES Symmetric Encryption Protocol.

  • SNMP-USM-AES-MIB::usmAesCfb128Protocol The CFB128-AES-128 Privacy Protocol.

17.5. How the SNMP Agent Interacts with ConfD

17.5.1. ConfD Sessions and Transactions

All data access to ConfD is done through user sessions. Once a user session is established, it can open read-only or read-write transactions towards a data store or towards operational data.

All requests start transactions towards the running data store.

SNMP over UDP does not have a concept of a user session. Each packet is (in theory) handled independently. However, for performance reasons, the SNMP agent creates a user session and a transaction when it receives the first packet. It then caches the session and transaction, and if it gets a new packet with the same source IP address, same UDP port, and same securityName, it reuses the session and transaction.

If no packet has been received during a 10 second period, the session and transaction are closed.

The cache has a limit of 32 sessions. If the cache is full when the agent needs to create a new session, an old session can be closed for this purpose, even though it was in use less than 10 seconds ago.

The confd.conf parameters for session limits can be used to limit the number of concurrent SNMP user sessions or configuration transactions, but note that higher values than 32 (the session cache limit described above) will not have any effect.

17.5.2. USM and VACM and ConfD AAA

When the SNMP agent receives a SNMP request, it determines the securityName and SNMP context for the request. If SNMPv1 or SNMPv2c is used, the snmpCommunityTable is consulted to determine the securityName and SNMP context. If SNMPv3 is used, the SNMP context is explicitly given in the request, and the securityName is determined from the usmUserTable.

When the SNMP agent starts a user session in ConfD, it uses the securityName as the username, the string "snmp" as ConfD AAA context, and no groups. If the username is a member of any of ConfD's AAA groups, it will be placed in these groups. Otherwise, if there is a defaultGroup configured in confd.conf , the user will be placed in this group. Otherwise, the user does not belong to any group.

Note that the user is authenticated by the SNMP agent, and not by ConfD's AAA.

For each SNMP object the user tries to access, VACM is consulted to see if the user's securityName has access, in the given context. If it has, the SNMP agent will try to access the corresponding YANG object. ConfD's normal AAA authorization is consulted to see if the groups the user belongs to have access to the YANG object.

Since both VACM and ConfD's AAA are consulted, a ConfD user can choose to use one of them, or both. One usage strategy can be to add VACM rules which gives full access to everyone, and then rely on ConfD's AAA datarules. Another strategy could be to have detailed rules in VACM, and then give full access to the "snmp" context in ConfD's AAA.

17.5.3. ConfD High Availability

If ConfD is run in HA mode, the SNMP variables sysUpTime, snmpEngineTime, and snmpEngineBoots are automatically replicated. This means that if a slave ConfD takes over as master, these variables will keep their values.

It is essential that each ConfD instance in the cluster has the same snmpEngineID configured. This value is defined in confd.conf , and it is the responsibility of the user to make sure it has the same value on all nodes in the cluster. However, if ConfD's configuration is stored in CDB (see Section 28.4.2, “Storing ConfD configuration parameters in CDB”), then since CDB is replicated, the snmpEngineID will always be the same in the cluster.

17.6. Running the SNMP Agent as a NET-SNMP subagent

The ConfD integrated SNMP agent can run as subagent to the NET-SNMP master agent. This is useful in scenarios where you want to use NET-SNMP agents for monitoring the host, or reuse other NET-SNMP subagents in your solution.

The easiest way to run the agent as sub-agent is to configure the proxy alternative in NET-SNMP snmpd.conf. (See the snmpd.conf man page) Make sure that you have created an access view with the correct OID root. You need to add a proxy command entry to the snmpd.conf file.

      proxy [-Cn CONTEXTNAME] [SNMPCMD_ARGS] HOST OID [REMOTEOID]
      

Values for the proxy configuration:

  • SNMPCMD_ARGS : these are the authentication parameters you want to pass to the ConfD SNMP agent. Note that the original auth parameters will not be used. (See snmpcmd man page). In the simplest configuration you specify a community string, for example -c secret where secret will be used as community string for all requests forwarded to ConfD.

  • HOST : IPv4-address[:port] : the IP address and the port of the ConfD SNMP agent. Make sure that ConfD uses a different port than the standard ports which you probably have configured for the NET-SNMP master agent.

  • OID : the SNMP OBJECT-IDENTIFIER of the root of the tree managed by ConfD SNMP agent.

After adding the values in the snmpd.conf file, restart the snmpd service.

The example below will forward all requests for Tail-f specific objects to the ConfD agent running on localhost on port 5000 using the communit string secret.

    proxy -c secret localhost:5000 1.3.1.6.4.24961