查看源码 snmp_generic (snmp v5.18)

在数据库中实现 SNMP 对象的通用函数

模块 snmp_generic 包含用于使用 SNMP 内置数据库或 Mnesia 实现表(和变量)的通用函数。如果 MIB 中的托管对象未提供检测函数,则会使用这些默认函数。有时,可能需要自定义默认函数的行为。例如,在某些情况下,如果删除或修改行,则应发送陷阱,或者在信息更改时应通知某些硬件。

整体结构如下图所示

         +---------------+
         |   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) |       |
+--------------+-------+

每个函数都使用参数 NameDb,它是一个元组 {Name, Db},用于标识函数应使用的数据库。Name 是 MIB 中定义的托管对象的符号名称,Dbvolatilepersistentmnesia。如果它是 mnesia,则所有变量都存储在 Mnesia 表 snmp_variables 中,该表必须是具有两个属性的表(而不是 Mnesia SNMP 表)。SNMP 表存储在与 SNMP 表同名的 Mnesia 表中。所有函数都假定存在具有正确名称和属性的 Mnesia 表。程序员有责任确保这一点。具体而言,如果变量存储在 Mnesia 中,则必须由程序员创建表 snmp_variables。此表的记录定义在文件 snmp/include/snmp_types.hrl 中定义。

如果在编译 MIB 时,变量 myVar 的关联文件中的检测函数没有名称,则编译器会生成一个条目。

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

对于表

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

示例

以下示例显示了在 Mnesia 中存储的表的实现,但在设置请求操作时执行了一些检查。

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).

.funcs 文件如下所示

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

总结

类型

在 get 操作的情况下,它是列号列表;在 set 操作的情况下,它是列号和值的列表。

对于普通表,类型将如下所示

函数

获取 Name 的索引类型

Cols 获取状态列的值。

获取特定的表信息项,或者,如果 Item 的值为“all”,则返回一个包含给定表的所有项及其各自值的二元组列表(属性列表)。

这是表的默认检测函数。

这是表的默认检测函数。

返回一个列表,其中包含 Cols 中所有列的值。如果某列未定义,则其值为 noinit

查找表中下一行的索引。RestOid 不必指定现有行。

检查表中的行是否存在。

Cols 中的元素设置为由 RowIndex 指定的行。不对新值执行任何检查。

这是变量的默认检测函数。

这是带有操作的变量的默认检测函数:is_set_ok | set | undo

获取变量的值。

为变量设置新值。如果变量不存在,则会创建该变量。不对新值的类型进行任何检查。

类型

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

在 get 操作的情况下,它是列号列表;在 set 操作的情况下,它是列号和值的列表。

链接到此类型

table_info_item()

查看源码 (未导出)
-type table_info_item() ::
          nbr_of_cols | defvals | status_col | not_accessible | index_types | first_accessible |
          first_own_index.

对于普通表,类型将如下所示

  • nbr_of_cols - 列数。

    值类型: pos_integer()

  • defvals - 默认值列表,按列排序。

    值类型: [{Col :: pos_integer(), DefVal :: term()}]

  • status_col - 状态列的列号。

    值类型: pos_integer()

  • not_accessible - 一个排序列表,包含“不可访问”的列(> first_accessible)。

    值类型: [pos_integer()]

  • index_types - 索引列的 asn1_type() 列表,按列号或“augment”元组(见下文)排序。

    值类型: [asn1_type()]

  • first_accessible - 第一个可访问的列。

    值类型: pos_integer()

  • first_own_index - 第一个自有索引的列号。如果此表没有此类索引,则为 0

    值类型: non_neg_integer()

对于增强表,它将如下所示

函数

链接到此函数

get_index_types(Name)

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

获取 Name 的索引类型

此函数可以在检测函数中使用,以检索表信息的索引类型部分。

链接到此函数

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().

Cols 获取状态列的值。

此函数可以在 is_set_okundoset 的检测函数中使用,以检查是否修改了表的状态列。

链接到此函数

get_table_info/2

查看源码 (自 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()}].

获取特定的表信息项,或者,如果 Item 的值为“all”,则返回一个包含给定表的所有项及其各自值的二元组列表(属性列表)。

此函数可以在检测函数中使用,以检索表信息的给定部分。

链接到此函数

table_func(Op, NameDb)

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

这是表的默认检测函数。

  • 如果表不存在,则 new 操作会创建该表,但前提是数据库是 SNMP 内部数据库。
  • delete 操作不会从数据库中删除该表,因为卸载 MIB 并不一定意味着应该销毁该表。

如果管理器可以创建或删除表中的行,则必须有一个 RowStatus 列,以便 is_set_oksetundo 正常工作。

该函数根据检测函数的规范返回。

链接到此函数

table_func(Op, RowIndex, Cols, NameDb)

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

这是表的默认检测函数。

  • is_set_ok 操作检查要修改或删除的行是否存在,以及要创建的行是否不存在。
  • undo 操作不执行任何操作。
  • set 操作检查它是否有足够的信息将行的状态从 notReady 更改为 notInService(当行已设置为 createAndWait 时)。如果将行设置为 createAndWait,则没有值的列将设置为 noinit。如果使用 Mnesia,则 set 功能在事务中处理。

如果管理器可以创建或删除表中的行,则必须有一个 RowStatus 列,以便 is_set_oksetundo 正常工作。

该函数根据检测函数的规范返回。

链接到此函数

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().

返回一个列表,其中包含 Cols 中所有列的值。如果某列未定义,则其值为 noinit

链接到此函数

table_next(NameDb, RestOid)

查看源码

查找表中下一行的索引。RestOid 不必指定现有行。

链接到此函数

table_row_exists(NameDb, RowIndex)

查看源码

检查表中的行是否存在。

链接到此函数

table_set_elements(NameDb, RowIndex, Cols)

查看源码

Cols 中的元素设置为由 RowIndex 指定的行。不对新值执行任何检查。

如果使用 Mnesia 数据库,则此函数会调用 mnesia:write 来存储值。这意味着必须从事务 (mnesia:transaction/1) 中调用此函数。

-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().

这是变量的默认检测函数。

  • new 操作会在数据库中创建一个新变量,其默认值在 MIB 中定义,或者为零值(取决于类型)。
  • delete 函数不会从数据库中删除变量。

该函数根据检测函数的规范返回。

-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.

这是带有操作的变量的默认检测函数:is_set_ok | set | undo

  • is_set_ok 操作不执行任何操作。
  • 如果成功,则 set 操作返回 noError,否则返回 commitFailed
  • undo 操作不执行任何操作。

该函数根据检测函数的规范返回。

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

获取变量的值。

链接到此函数

variable_set(Name, Value)

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

为变量设置新值。如果变量不存在,则会创建该变量。不对新值的类型进行任何检查。

如果 NameDb 参数指定不正确,则返回 false,否则返回 true