查看源代码 MIB 编译器

MIB 编译器 章节描述了 MIB 编译器,包含以下主题

  • 操作
  • 导入
  • MIB 之间的一致性检查
  • .hrl 文件生成
  • Emacs 集成
  • 与标准的偏差

注意

导入 MIB 时,请确保导入的 MIB 以及正在导入的 MIB 使用相同版本的 SNMP 编译器进行编译。

操作

在编译之前,必须使用 ASN.1 表示法将 MIB 编写为 SMIv1 或 SMIv2 文本文件。此文本文件必须与 MIB 同名,但后缀为 .mib。这对于处理 IMPORT 语句是必要的。

关联文件包含 MIB 的检测功能的名称,应具有后缀 .funcs。如果编译器找不到关联文件,则会给出警告消息并使用默认的检测功能。(有关更多详细信息,请参阅 默认检测)。

MIB 编译器通过调用 snmpc:compile(<mibname>). 启动。例如

snmpc:compile("RFC1213-MIB").

输出是一个名为 <mibname>.bin 的新文件。

MIB 编译器可以理解 SMIv1 和 SMIv2 MIB。它使用 MODULE-IDENTITY 语句来确定 MIB 是使用 SMI 版本 1 还是 2 编写的。

导入 MIB

编译器处理 IMPORT 语句。重要的是导入已编译的文件,而不是 ASN.1(源)文件。必须重新编译 MIB,才能使更改对导入它的其他 MIB 可见。

导入的 MIB 的编译文件必须存在于当前目录或当前路径中的目录中。路径使用 {i, Path} 选项提供,例如

snmpc:compile("MY-MIB",
       [{i, ["friend_mibs/", "../standard_mibs/"]}]).

也可以使用 il 选项以类似于 "include_lib" 的方式从 OTP 应用程序导入 MIB。例如

snmpc:compile("MY-MIB",
       [{il, ["snmp/priv/mibs/", "myapp/priv/mibs/"]}]).

在 OTP 系统中查找 snmpmyapp 应用程序的最新版本,并将扩展后的路径用作包含路径。

请注意,SMIv2 MIB 可以导入 SMIv1 MIB,反之亦然。

以下 MIB 是 Erlang SNMP 编译器的内置 MIB:SNMPv2-SMI、RFC-1215、RFC-1212、SNMPv2-TC、SNMPv2-CONF 和 RFC1155-SMI。因此,它们不能单独编译。

MIB 一致性检查

编译 MIB 时,编译器会检测是否有多个被管理对象使用相同的 OBJECT IDENTIFIER。如果是这种情况,它会发出错误消息。但是,编译器无法检测不同 MIB 之间的 Oid 冲突。这些类型的冲突会在加载时生成错误。为了避免这种情况,可以使用以下函数在 MIB 之间进行一致性检查


erl>snmpc:is_consistent(ListOfMibNames).

ListOfMibNames 是已编译的 MIB 的列表,例如 ["RFC1213-MIB", "MY-MIB"]。该函数还执行陷阱定义的一致性检查。

.hrl 文件生成

可以从已编译的 MIB 文件生成包含 Erlang 常量定义的 .hrl 文件。然后可以将此文件包含在 Erlang 源代码中。该文件将包含以下常量:

  • 表、表项和变量的对象标识符
  • 列号
  • 枚举值
  • 变量和表列的默认值。

使用以下命令从 MIB 生成 .hrl 文件

erl>snmpc:mib_to_hrl(MibName).

Emacs 集成

使用 Emacs 编辑器,next-error (C-X `) 函数可用于指示发生编译错误的位置,前提是错误消息由行号描述。

使用 M-x compile 从 Emacs 内部编译 MIB,然后输入

 erl -s snmpc compile <MibName> -noshell

<MibName> 的示例是 RFC1213-MIB

从 Shell 或 Makefile 编译

可以使用 erlc 命令来编译 SNMP MIB。例如

 erlc MY-MIB.mib

支持所有标准的 erlc 标志,例如

 erlc -I mymibs -o mymibs -W MY-MIB.mib

可以使用 + 语法指定 MIB 编译器特有的标志

 erlc +'{group_check,false}' MY-MIB.mib

与标准的偏差

在某些方面,Erlang MIB 编译器并未完全遵循或实现 SMI。以下是差异

  • 必须按以下顺序编写表:tableObjectentryObjectcolumn1、...、columnN(按顺序)。
  • 整数值,例如在 SIZE 表达式中,必须以十进制语法输入,而不是以十六进制或位语法输入。
  • 符号名称在 MIB 内和系统内必须是唯一的。
  • SMIv2 中允许使用连字符(一种务实的方法)。这样做的原因是,根据 SMIv2,连字符允许用于从 SMIv1 转换的对象,但不允许用于其他对象。这对于编译器来说是无法检查的。
  • 如果一个单词是 SMIv1 或 SMIv2 中的任何一个关键字,则它也是编译器中的关键字(仅与 SMIv1 不同)。
  • 表中的索引必须是对象,而不是类型(仅与 SMIv1 不同)。
  • 实现了对类型的语义检查的一个子集。例如,严格来说,TimeTicks 不能被子类化,但编译器允许这样做(标准 MIB 必须通过编译器)(仅与 SMIv2 不同)。
  • 未实现 MIB.Object 语法(因为所有对象都必须是唯一的)。
  • 两个不同的名称不能定义相同的 OBJECT IDENTIFIER。
  • SEQUENCE 构造中的类型检查是非严格的(即,可以指定子类型)。这样做的原因是,一些标准 MIB 使用了这种方法。
  • 定义通常具有状态字段。当状态字段的值为 deprecated 时,MIB 编译器将忽略此定义。使用 MIB 编译器选项 {deprecated,true},MIB 编译器不会忽略已弃用的定义。
  • 对象具有 DESCRIPTIONS 字段。默认情况下,描述字段不会包含在已编译的 mib 中。为了获取描述,必须使用选项 description 编译 mib。