Search documentation of snmp

# snmp_generic (snmp v5.19.1)

View Source

Generic Functions for Implementing SNMP Objects in a Database

The module `snmp_generic` contains generic functions for implementing tables (and variables) using the SNMP built-in database or Mnesia. These default functions are used if no instrumentation function is provided for a managed object in a MIB. Sometimes, it might be necessary to customize the behaviour of the default functions. For example, in some situations a trap should be sent if a row is deleted or modified, or some hardware is to be informed, when information is changed.

The overall structure is shown in the following figure:

             +---------------+
             |   SNMP Agent  |
             +- - - - - - - -+
             |      MIB      |
             +---------------+
                     |
             Association file       (associates a MIB object with
                     |               snmp_generic:table_funct
                     |               snmp_generic:variable_func)
    +--------------------------------------+
    |           snmp_generic               |  Support for get-next,
    |                                      |  RowStatus operations
    +----------------------+---------------+
    |    snmpa_local_db    |    Mnesia     |  Database
    +--------------+-------+---------------+
    |     dets     |  ets  |
    | (persistent) |       |
    +--------------+-------+

Each function takes the argument `NameDb`, which is a tuple `{Name, Db}`, to identify which database the functions should use. `Name` is the symbolic name of the managed object as defined in the MIB, and `Db` is either `volatile`, `persistent`, or `mnesia`. If it is `mnesia`, all variables are stored in the Mnesia table `snmp_variables` which must be a table with two attributes (not a Mnesia SNMP table). The SNMP tables are stored in Mnesia tables with the same names as the SNMP tables. All functions assume that a Mnesia table exists with the correct name and attributes. It is the programmer's responsibility to ensure this. Specifically, if variables are stored in Mnesia, the table `snmp_variables` must be created by the programmer. The record definition for this table is defined in the file `snmp/include/snmp_types.hrl`.

If an instrumentation function in the association file for a variable `myVar` does not have a name when compiling an MIB, the compiler generates an entry.

    {myVar, {snmp_generic, variable_func, [{myVar, Db]}}.

And for a table:

    {myTable, {snmp_generic, table_func, [{myTable, Db]}}.

## Example

The following example shows an implementation of a table which is stored in Mnesia, but with some checks performed at set-request operations.

    myTable_func(new, NameDb) ->   % pass unchanged
      snmp_generic:table_func(new, NameDb).

    myTable_func(delete, NameDb) ->   % pass unchanged
      snmp_generic:table_func(delete, NameDb).

    %% change row
    myTable_func(is_set_ok, RowIndex, Cols, NameDb) ->
      case snmp_generic:table_func(is_set_ok, RowIndex,
                                   Cols, NameDb) of
        {noError, 0} ->
          myApplication:is_set_ok(RowIndex, Cols);
        Err ->
          Err
      end;

    myTable_func(set, RowIndex, Cols, NameDb) ->
      case snmp_generic:table_func(set, RowIndex, Cols,
                                   NameDb),
        {noError, 0} ->
          % Now the row is updated, tell the application
          myApplication:update(RowIndex, Cols);
        Err ->
          Err
      end;

    myTable_func(Op, RowIndex, Cols, NameDb) ->   % pass unchanged
      snmp_generic:table_func(Op, RowIndex, Cols, NameDb).

The `.funcs` file would look like:

    {myTable, {myModule, myTable_func, [{myTable, mnesia}]}}.

# Summary

## Types

column()
columns()

Is a list of column numbers in the case of a get operation, and a list of column numbers and values in the case of a set operation.

table_info_item()

For an ordinary table, the types will be the following

## Functions

get_index_types(Name)

Gets the index types of `Name`

get_status_col(Name, Cols)

Gets the value of the status column from `Cols`.

get_table_info/2

Get a specific table info item or, if `Item` has the value 'all', a two tuple list (property list) is instead returned with all the items and their respctive values of the given table.

table_func(Op, NameDb)

This is the default instrumentation function for tables.

table_func(Op, RowIndex, Cols, NameDb)

This is the default instrumentation function for tables.

table_get_elements(NameDb, RowIndex, Cols)

Returns a list with values for all columns in `Cols`. If a column is undefined, its value is `noinit`.

table_next(NameDb, RestOid)

Finds the indices of the next row in the table. `RestOid` does not have to specify an existing row.

table_row_exists(NameDb, RowIndex)

Checks if a row in a table exists.

table_set_elements(NameDb, RowIndex, Cols)

Sets the elements in `Cols` to the row specified by `RowIndex`. No checks are performed on the new values.

variable_func/2

This is the default instrumentation function for variables.

variable_func/3

This is the default instrumentation function for variables with operations; `is_set_ok | set | undo`.

variable_get(Name)

Gets the value of a variable.

variable_set(Name, Value)

Sets a new value to a variable. The variable is created if it does not exist. No checks are made on the type of the new value.

# Types

# column()

    -type column() :: pos_integer().

# columns()

    -type columns() :: [column()] | [{column(), Value :: term()}].

Is a list of column numbers in the case of a get operation, and a list of column numbers and values in the case of a set operation.

# table_info_item()

(not exported)

    -type table_info_item() ::
              nbr_of_cols | defvals | status_col | not_accessible | index_types | first_accessible |
              first_own_index.

For an ordinary table, the types will be the following:

- `nbr_of_cols` - Number of columns.

  Value type: pos_integer()

- `defvals` - A list of default values, ordered by column.

  Value type: [{Col :: pos_integer(), DefVal :: term()}]

- `status_col` - Column number of the status column.

  Value type: pos_integer()

- `not_accessible` - A sorted list of columns (> first_accessible) that are 'not-accessible'.

  Value type: [pos_integer()]

- `index_types` - A list of asn1_type() for the index columns, ordered by column number or an "augment"-tuple (see below).

  Value type: [asn1_type()]

- `first_accessible` - The first accessible column.

  Value type: pos_integer()

- `first_own_index` - Column number of the first own index. Will be `0` if there is no such index for this table.

  Value type: non_neg_integer()

For a augmented table, it will instead look like this:

- `index_types` - Value type: {augments, {atom(), asn1_type()}}

- `nbr_of_cols` - Value type: pos_integer()

- `not_accessible` - Value type: [pos_integer()]

- `first_accessible` - Value type: pos_integer()

# Functions

# get_index_types(Name)

    -spec get_index_types(Name) -> IndexTypes
                             when Name :: snmpa:name() | snmpa:name_db(), IndexTypes :: [snmp:asn1_type()].

Gets the index types of `Name`

This function can be used in instrumentation functions to retrieve the index types part of the table info.

# get_status_col(Name, Cols)

    -spec get_status_col(Name, Cols) -> false | {value, StatusCol}
                            when
                                Name :: snmpa:name() | snmpa:name_db(),
                                Cols :: columns(),
                                StatusCol :: term().

Gets the value of the status column from `Cols`.

This function can be used in instrumentation functions for `is_set_ok`, `undo` or `set` to check if the status column of a table is modified.

# get_table_info/2

(since OTP R15B01)

    -spec get_table_info(Name, Item :: nbr_of_cols) -> Result
                            when Name :: snmpa:name() | snmpa:name_db(), Result :: pos_integer();
                        (Name, Item :: defvals) -> Result
                            when
                                Name :: snmpa:name() | snmpa:name_db(),
                                Result :: [{Col, DefVal}],
                                Col :: pos_integer(),
                                DefVal :: term();
                        (Name, Item :: status_col) -> Result
                            when Name :: snmpa:name() | snmpa:name_db(), Result :: pos_integer();
                        (Name, Item :: not_accessible) -> Result
                            when Name :: snmpa:name() | snmpa:name_db(), Result :: [pos_integer()];
                        (Name, Item :: index_types) -> Result
                            when Name :: snmpa:name() | snmpa:name_db(), Result :: [snmp:asn1_type()];
                        (Name, Item :: first_accessible) -> Result
                            when Name :: snmpa:name() | snmpa:name_db(), Result :: pos_integer();
                        (Name, Item :: first_own_index) -> Result
                            when Name :: snmpa:name() | snmpa:name_db(), Result :: non_neg_integer();
                        (Name, Item :: all) -> Result
                            when
                                Name :: snmpa:name() | snmpa:name_db(),
                                Result :: [{table_info_item(), term()}].

Get a specific table info item or, if `Item` has the value 'all', a two tuple list (property list) is instead returned with all the items and their respctive values of the given table.

This function can be used in instrumentation functions to retrieve a given part of the table info.

# table_func(Op, NameDb)

    -spec table_func(Op, NameDb) -> Return
                        when Op :: new | delete, NameDb :: snmpa:name_db(), Return :: term().

This is the default instrumentation function for tables.

- The `new` operation creates the table if it does not exist, but only if the database is the SNMP internal db.
- The `delete` operation does not delete the table from the database since unloading an MIB does not necessarily mean that the table should be destroyed.

If it is possible for a manager to create or delete rows in the table, there must be a `RowStatus` column for `is_set_ok`, `set` and `undo` to work properly.

The function returns according to the specification of an instrumentation function.

# table_func(Op, RowIndex, Cols, NameDb)

    -spec table_func(Op, RowIndex, Cols, NameDb) -> Return
                        when
                            Op :: get | get_next | is_set_ok | set | undo,
                            RowIndex :: snmp:row_index(),
                            Cols :: columns(),
                            NameDb :: snmpa:name_db(),
                            Return :: term().

This is the default instrumentation function for tables.

- The `is_set_ok` operation checks that a row which is to be modified or deleted exists, and that a row which is to be created does not exist.
- The `undo` operation does nothing.
- The `set` operation checks if it has enough information to make the row change its status from `notReady` to `notInService` (when a row has been been set to `createAndWait`). If a row is set to `createAndWait`, columns without a value are set to `noinit`. If Mnesia is used, the set functionality is handled within a transaction.

If it is possible for a manager to create or delete rows in the table, there must be a `RowStatus` column for `is_set_ok`, `set` and `undo` to work properly.

The function returns according to the specification of an instrumentation function.

# table_get_elements(NameDb, RowIndex, Cols)

    -spec table_get_elements(NameDb, RowIndex, Cols) -> Values
                                when
                                    NameDb :: snmpa:name_db(),
                                    RowIndex :: snmp:row_index(),
                                    Cols :: columns(),
                                    Values :: [noinit | Value],
                                    Value :: term().

Returns a list with values for all columns in `Cols`. If a column is undefined, its value is `noinit`.

# table_next(NameDb, RestOid)

    -spec table_next(NameDb, RestOid) -> Result
                        when
                            NameDb :: snmpa:name_db(),
                            RestOid :: [integer()],
                            Result :: RowIndex | endOfTable,
                            RowIndex :: snmp:row_index().

Finds the indices of the next row in the table. `RestOid` does not have to specify an existing row.

# table_row_exists(NameDb, RowIndex)

    -spec table_row_exists(NameDb, RowIndex) -> Result
                              when
                                  NameDb :: snmpa:name_db(),
                                  RowIndex :: snmp:row_index(),
                                  Result :: boolean().

Checks if a row in a table exists.

# table_set_elements(NameDb, RowIndex, Cols)

    -spec table_set_elements(NameDb, RowIndex, Columns) -> Result
                                when
                                    NameDb :: snmpa:name_db(),
                                    RowIndex :: snmp:row_index(),
                                    Columns :: [{Column, Value}],
                                    Column :: column(),
                                    Value :: term(),
                                    Result :: boolean().

Sets the elements in `Cols` to the row specified by `RowIndex`. No checks are performed on the new values.

If the Mnesia database is used, this function calls `mnesia:write` to store the values. This means that this function must be called from within a transaction (`mnesia:transaction/1`).

# variable_func/2

    -spec variable_func(Op :: new, Name) -> Result
                           when Name :: snmpa:name() | snmpa:name_db(), Result :: ok | boolean();
                       (Op :: delete, Name) -> Result
                           when Name :: snmpa:name() | snmpa:name_db(), Result :: ok;
                       (Op :: get, Name) -> Result
                           when
                               Name :: snmpa:name() | snmpa:name_db(),
                               Result :: {value, Value} | genErr,
                               Value :: term().

This is the default instrumentation function for variables.

- The `new` opeation creates a new variable in the database with a default value as defined in the MIB, or a zero value (depending on the type).
- The `delete` function does not delete the variable from the database.

The function returns according to the specification of an instrumentation function.

# variable_func/3

    -spec variable_func(Op :: is_set_ok, Value, Name) -> Result
                           when Value :: term(), Name :: snmpa:name() | snmpa:name_db(), Result :: noError;
                       (Op :: set, Value, Name) -> Result
                           when
                               Value :: term(),
                               Name :: snmpa:name() | snmpa:name_db(),
                               Result :: noError | commitFailed;
                       (Op :: undo, Value, Name) -> Result
                           when Value :: term(), Name :: snmpa:name() | snmpa:name_db(), Result :: noError.

This is the default instrumentation function for variables with operations; `is_set_ok | set | undo`.

- The `is_set_ok` operation does nothing.
- The `set` operation return `noError` if successful or `commitFailed` otherwise.
- The `undo` operation does nothing.

The function returns according to the specification of an instrumentation function.

# variable_get(Name)

    -spec variable_get(Name) -> {value, Value} | undefined
                          when Name :: snmpa:name() | snmpa:name_db(), Value :: term().

Gets the value of a variable.

# variable_set(Name, Value)

    -spec variable_set(Name, Value) -> boolean()
                          when Name :: snmpa:name() | snmpa:name_db(), Value :: term().

Sets a new value to a variable. The variable is created if it does not exist. No checks are made on the type of the new value.

Returns `false` if the `NameDb` argument is incorrectly specified, otherwise `true`.