设计与实现 SNMP MIB 指南
1. SNMP MIB 对象访问权限设计
在设计 SNMP MIB 时,每个对象的 MAX - ACCESS 子句定义了其使用方式。以下是一些对象的访问权限设置:
| 对象名称 | 访问权限 | 说明 |
| ---- | ---- | ---- |
| ladAlarmZoneId | 不可访问 | 仅用于索引表以读写其他值 |
| ladAlarmEnable | 读写 | 可使用 SNMP 命令启用或禁用警报 |
| ladAlarmLatching | 读写 | 可使用 SNMP 命令更改警报是否锁定 |
| ladAlarmState | 读写 | 可通过将状态设置为 false 清除警报 |
| ladAlarmZoneName | 只读 | 区域名称被视为静态配置,应通过其他接口(如 Web 接口或 CLI)更改 |
| ladAlarmCount | 只读 | 记录警报触发次数的历史记录 |
这些访问权限的选择并非强制,设计者可根据需求进行不同的设计。例如,若将 ladAlarmZoneId 定义为可读,在 SNMP 显示区域结构时,每行开头将显示行号;也可将计数字段定义为可写,以便定期将其重置为零,方便查看一段时间内警报的触发次数。
2. SNMP 陷阱设计
SNMP 陷阱用于在特定事件发生时发出通知。这里设计了两个陷阱:
-- -----------------------------------------
-- LAD traps
-- -----------------------------------------
ladAlarm NOTIFICATION - TYPE
OBJECTS { ladTrapZoneId, ladTrapZoneName }
STATUS current
DESCRIPTION
" Trap issued when an alarm is triggered. "
::= { ladTraps 1 }
ladAlarmClear NOTIFICATION - TYPE
STATUS current
DESCRIPTION
" Trap issued when last raised alarm returns to normal state. "
::= { ladTraps 2 }
ladAlarm 陷阱在检测到入侵时发出警报, ladAlarmClear 陷阱在最后一次触发的警报恢复正常状态时发出通知。
陷阱定义中的 OBJECTS 子句指定了伴随陷阱发送的其他信息,即变量绑定列表(varbind list)。以下是这些变量的定义:
-- -----------------------------------------
-- LAD Trap Info: varbinds sent with traps
-- -----------------------------------------
ladTrapZoneId OBJECT - TYPE
SYNTAX Integer32
MAX - ACCESS accessible - for - notify
STATUS current
DESCRIPTION
"This is the ID (row number in the ladAlarmTable) of the
zone generating the alarm."
::= { ladTrapInfo 1 }
ladTrapZoneName OBJECT - TYPE
SYNTAX DisplayString
MAX - ACCESS accessible - for - notify
STATUS current
DESCRIPTION
"This is the name of the zone generating the alarm."
::= { ladTrapInfo 2 }
这些对象的 MAX - ACCESS 设置为 accessible - for - notify ,意味着它们不能被轮询,仅为陷阱接收者定义对象,只有在附加到陷阱时才有意义。
早期的 SNMP 文档关注减少 SNMP 流量,陷阱仅用于引起对可能问题的关注,具体问题需轮询设备获取。如今,一些网络管理员将陷阱日志作为设备历史记录,希望陷阱携带所有相关信息并由接收软件记录。
同时,要注意设备陷阱不要过于频繁。若设备每分钟检查错误条件并在指标超过阈值时生成陷阱,可能会发送大量重复警报,掩盖其他设备的问题。可选择在首次发现问题时报告一次,问题解决时再发送一次通知。
发送大量陷阱的观点认为 SNMP 设计上不可靠,使用 UDP 数据包报告问题,重要问题会多次被发现,单个陷阱丢失不影响。另一种方法是使用 SNMPv2 中的 informs ,它具有一定的可靠性,期望接收者返回确认消息,未收到确认会重试。若仍不满意,可考虑在设备未得到关注时降低陷阱重发频率。
3. MIB 验证
MIB 编写完成后,需进行有效性测试。MIB 不仅要人类可读,还要能被机器解析,其语法必须正确,否则使用该 MIB 的应用程序将无法解释。可使用多个在线免费 MIB 验证器,如:
- SimpleWeb 网站的验证器: http://wwwsnmp.cs.utwente.nl/ietf/mibs/validate
- Muonics 提供的验证器: http://www.muonics.com/Tools/smicheck.php
验证步骤:
1. 打开浏览器,进入验证器网站。
2. 上传 MIB 文件进行验证。
务必进行验证步骤,语法错误将导致后续操作无法正常进行。
4. MIB 结构设计建议
设计 MIB 结构时,要考虑未来产品的变化。可考虑以下基本类型的信息:
- 配置信息
- 统计信息
- 历史信息
- 各种运行时状态
- 性能指标
- 使用级别
- 服务或资源饱和级别
这些信息类型可指导 MIB 结构设计,使未来应对需求变化时更加轻松。
5. 实现 SNMP MIB
要实现支持自定义 MIB 的 SNMP 代理,可按以下步骤进行:
5.1 下载 Net - SNMP 代理源码
从 http://net - snmp.sourceforge.net 下载最新版本的 Net - SNMP 源码 tarball,当前版本为 5.2.1,下载 net - snmp - 5.2.1.tar.gz 。
5.2 编写 Makefile
以下是简化的 Makefile 示例:
NETSNMP_VERSION = 5.2.1
BUILD_DIR = ./net - snmp - $(NETSNMP_VERSION)
#
# Targets
#
all: clean setup config build
clean:
rm -rf $(BUILD_DIR)
rm -rf /opt/snmp/*
setup:
tar zxf net - snmp - $(NETSNMP_VERSION).tar.gz
config:
cd $(BUILD_DIR); \
./configure --prefix=/opt/snmp <../configure.input; \
cd ..
build:
cd $(BUILD_DIR); \
make
install:
cd $(BUILD_DIR); \
install
若使用新版本的 Net - SNMP,只需将 tarball 放入与 Makefile 相同的目录,修改 NETSNMP_VERSION 行以匹配版本,然后继续后续操作。
5.3 编写 configure.input 文件
<blank line>
2
Not Set
Not Set
/var/log/snmpd.log
/var/net - snmp
第一行必须为空,因为 configure 脚本要求在准备输入时按 ENTER 。 2 选择 SNMPv2 作为默认 SNMP 版本,两个 Not Set 行用于系统联系人和系统位置,后续将在代理配置文件中覆盖这些值。最后两行是默认日志文件和持久存储位置。
5.4 构建和安装 Net - SNMP
执行 make 命令构建 Net - SNMP 应用程序、库和代理。若失败,可手动执行步骤:
1. 解压 tarball 并进入生成的目录。
2. 运行 ./configure 并按 configure.input 中的内容回答问题。
3. 检查 configure 输出,确保没有缺少必要的库。
4. 若无误,在 net - snmp.5.2.1 目录中执行 make 并观察错误。
构建成功后,以 root 身份执行 make install 安装 Net - SNMP 到开发系统,安装文件将位于 /opt/snmp 下的多个目录:
$ ls /opt/snmp
bin/ include/ lib/ man/ sbin/ share/
在设备上,不需要 include 或 man 目录,可考虑从 bin 目录中移除 snmpget 和 snmpset 等客户端应用程序,但不要移除 snmptrap ,因为将使用它从设备发送陷阱。
若要在 logmuxd 过滤器中使用数字对象标识符(OIDs)的可读名称,需告诉 snmptrap 命令 MIB 文件的位置,可通过以下两种方式:
- 在命令行添加选项: -m ALL -M /opt/snmp/share/snmp/mibs
- 设置环境变量:
export MIBS=ALL
export MIBDIRS=/opt/snmp/share/snmp/mibs
5.5 生成 MIB 骨架代码
Net - SNMP 提供了 mib2c 实用程序,可读取 MIB 文件并生成代理扩展的骨架代码。使用前需安装 SNMP Perl 模块,可从 Net - SNMP tarball 中安装,也可安装 Linux 发行版提供的 libsnmp - perl 包。
将 MIB 文件(如 LADDIE - GROUP - SMI.txt 和 LAD - MIB.txt )复制到 /opt/snmp/share/snmp/mibs 目录,或添加 . 到 MIBDIRS 列表:
export MIBDIRS=.:/opt/snmp/share/snmp/mibs
运行 mib2c 生成骨架代码:
$ mib2c LAD - MIB:ladProject
运行过程中,需选择代码风格,这里选择 ucd - snmp 风格:
First, do you want to generate code that is compatible with the
ucd - snmp 4.X line of code, or code for the newer Net - SNMP 5.X code
base (which provides a much greater choice of APIs to pick from):
1) ucd - snmp style code
2) Net - SNMP style code
Select your choice : 1
生成的代码将写入 ladProject.h 和 ladProject.c 文件,注意生成的代码只是模板,大部分情况下需要手动填充,文件中标记为 /* XXX */ 或 /* TODO */ 的地方必须编辑。
6. 总结
通过以上步骤,我们完成了 SNMP MIB 的设计、验证和实现。设计 MIB 时要考虑访问权限、陷阱设置和未来扩展性,实现过程中借助 Net - SNMP 工具生成骨架代码并进行必要的修改。在实际应用中,可根据具体需求调整配置,确保 SNMP 代理正常工作。
以下是整个实现流程的 mermaid 流程图:
graph LR
A[下载 Net - SNMP 源码] --> B[编写 Makefile]
B --> C[编写 configure.input 文件]
C --> D[构建 Net - SNMP]
D --> E{构建是否成功}
E -- 是 --> F[安装 Net - SNMP]
E -- 否 --> G[手动执行步骤排查问题]
G --> D
F --> H[准备 MIB 文件]
H --> I[安装 SNMP Perl 模块]
I --> J[运行 mib2c 生成骨架代码]
这样,我们就完成了从 SNMP MIB 设计到实现的全过程,为网络设备的管理和监控提供了有力支持。
设计与实现 SNMP MIB 指南
7. 深入理解 MIB 骨架代码
mib2c 生成的 ladProject.h 和 ladProject.c 文件是实现 MIB 的基础骨架。下面我们来深入了解这两个文件。
7.1 ladProject.h 文件
这个文件主要包含了一些常量、结构体和函数的声明,为 ladProject.c 文件提供必要的定义。以下是一个简化的示例结构:
// ladProject.h
#ifndef LADPROJECT_H
#define LADPROJECT_H
// 定义一些常量
#define LAD_ALARM_TABLE_SIZE 10
// 定义结构体
typedef struct ladAlarmTableEntry_s {
int ladAlarmZoneId;
int ladAlarmEnable;
int ladAlarmLatching;
int ladAlarmState;
int ladAlarmCount;
char ladAlarmZoneName[50];
} ladAlarmTableEntry;
// 声明函数
void init_ladProject(void);
int handle_ladAlarmTable(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests);
#endif /* LADPROJECT_H */
在上述示例中,我们定义了一个常量 LAD_ALARM_TABLE_SIZE 表示警报表的大小,还定义了一个结构体 ladAlarmTableEntry 来表示警报表中的每一项。同时声明了一些函数,如 init_ladProject 用于初始化项目, handle_ladAlarmTable 用于处理警报表的请求。
7.2 ladProject.c 文件
这个文件是实现 MIB 功能的核心,需要填充 mib2c 生成的模板代码。以下是一个简化的示例:
// ladProject.c
#include "ladProject.h"
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
// 定义警报表
ladAlarmTableEntry ladAlarmTable[LAD_ALARM_TABLE_SIZE];
// 初始化函数
void init_ladProject(void) {
// 初始化警报表
for (int i = 0; i < LAD_ALARM_TABLE_SIZE; i++) {
ladAlarmTable[i].ladAlarmZoneId = i + 1;
ladAlarmTable[i].ladAlarmEnable = 0;
ladAlarmTable[i].ladAlarmLatching = 0;
ladAlarmTable[i].ladAlarmState = 0;
ladAlarmTable[i].ladAlarmCount = 0;
snprintf(ladAlarmTable[i].ladAlarmZoneName, sizeof(ladAlarmTable[i].ladAlarmZoneName), "Zone %d", i + 1);
}
// 注册警报表处理函数
netsnmp_register_table("ladAlarmTable", handle_ladAlarmTable, NULL);
}
// 处理警报表请求的函数
int handle_ladAlarmTable(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests) {
netsnmp_request_info *request;
for (request = requests; request; request = request->next) {
// 根据请求类型进行处理
switch (reqinfo->mode) {
case MODE_GET:
// 处理 GET 请求
// 这里需要根据 OID 找到对应的表项并返回值
break;
case MODE_SET_RESERVE1:
// 处理 SET 请求的预检查
break;
case MODE_SET_RESERVE2:
// 处理 SET 请求的资源分配
break;
case MODE_SET_ACTION:
// 处理 SET 请求的实际操作
break;
case MODE_SET_COMMIT:
// 处理 SET 请求的提交
break;
case MODE_SET_FREE:
// 处理 SET 请求的资源释放
break;
case MODE_SET_UNDO:
// 处理 SET 请求的撤销操作
break;
}
}
return SNMP_ERR_NOERROR;
}
在 ladProject.c 文件中,我们首先包含了必要的头文件,然后定义了警报表 ladAlarmTable 。 init_ladProject 函数用于初始化警报表并注册处理函数。 handle_ladAlarmTable 函数根据请求的模式(如 MODE_GET 或 MODE_SET )来处理对警报表的请求。
8. 调试 SNMP MIB 实现
在实现 MIB 过程中,调试是必不可少的步骤。以下是一些调试的方法和建议:
8.1 使用日志文件
Net - SNMP 代理可以将调试信息记录到日志文件中。在 configure.input 文件中,我们已经指定了日志文件的位置 /var/log/snmpd.log 。可以通过查看这个日志文件来了解代理的运行情况,例如:
tail -f /var/log/snmpd.log
通过实时查看日志文件,可以及时发现错误信息和警告信息。
8.2 启用调试模式
可以通过设置环境变量来启用 Net - SNMP 的调试模式。例如:
export MIBS=ALL
export MIBDIRS=/opt/snmp/share/snmp/mibs
export SNMPDEBUG=1
启用调试模式后,Net - SNMP 会输出更详细的调试信息,帮助我们定位问题。
8.3 使用 SNMP 命令进行测试
可以使用 snmpget 、 snmpset 等命令来测试 MIB 的实现。例如,使用 snmpget 命令获取警报表的信息:
snmpget -c public -v2c myappliance LAD-MIB::ladAlarmTable
通过观察命令的输出结果,检查 MIB 是否正确返回了预期的值。
9. 陷阱的实现与测试
在前面我们已经设计了陷阱,现在来实现和测试它们。
9.1 实现陷阱发送
在 ladProject.c 文件中添加陷阱发送的代码。例如,当警报触发时发送 ladAlarm 陷阱:
// ladProject.c
#include "ladProject.h"
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
// ... 前面的代码 ...
void send_ladAlarm_trap(int zoneId, const char *zoneName) {
netsnmp_variable_list *varlist = NULL;
// 添加陷阱相关的变量
snmp_varlist_add_variable(&varlist,
netsnmp_create_variable("LAD-MIB::ladTrapZoneId",
ASN_INTEGER,
&zoneId,
sizeof(zoneId)));
snmp_varlist_add_variable(&varlist,
netsnmp_create_variable("LAD-MIB::ladTrapZoneName",
ASN_OCTET_STR,
zoneName,
strlen(zoneName)));
// 发送陷阱
snmp_send_trap("LAD-MIB::ladAlarm", varlist);
// 释放变量列表
snmp_free_varbind(varlist);
}
// ... 后面的代码 ...
在上述代码中,我们定义了一个 send_ladAlarm_trap 函数,用于发送 ladAlarm 陷阱。在函数中,我们创建了陷阱相关的变量并添加到变量列表中,然后使用 snmp_send_trap 函数发送陷阱,最后释放变量列表。
9.2 测试陷阱接收
在开发系统上保留 snmptrapd 服务,用于测试陷阱的接收。启动 snmptrapd 服务:
snmptrapd -Lf /var/log/snmptrapd.log -Le
这个命令将 snmptrapd 服务的日志记录到 /var/log/snmptrapd.log 文件中。当设备发送陷阱时,可以通过查看这个日志文件来确认是否接收到陷阱:
tail -f /var/log/snmptrapd.log
10. 最终部署与优化
完成 MIB 的设计、实现、调试和测试后,就可以进行最终的部署和优化了。
10.1 部署到设备
将 /opt/snmp 目录下的必要文件复制到设备上。在设备上,不需要 include 或 man 目录,可考虑从 bin 目录中移除 snmpget 和 snmpset 等客户端应用程序,但不要移除 snmptrap 。
10.2 优化陷阱发送策略
根据实际情况优化陷阱发送策略,避免发送过多的重复陷阱。可以设置一个阈值,当某个问题持续出现一定次数后才发送陷阱,或者在问题解决后发送确认陷阱。
10.3 定期维护和更新
定期维护和更新 MIB,根据设备的功能变化和网络管理的需求,对 MIB 进行相应的修改和扩展。
以下是陷阱实现和部署的 mermaid 流程图:
graph LR
A[实现陷阱发送代码] --> B[启动 snmptrapd 服务]
B --> C[设备发送陷阱]
C --> D{是否接收到陷阱}
D -- 是 --> E[记录到日志文件]
D -- 否 --> F[排查问题]
F --> C
E --> G[部署到设备]
G --> H[优化陷阱发送策略]
H --> I[定期维护和更新 MIB]
通过以上步骤,我们完成了从 SNMP MIB 的详细设计到最终部署和优化的全过程。在实际应用中,要根据具体的网络环境和设备需求,灵活调整和优化 MIB 的设计和实现,以确保网络设备的高效管理和监控。
超级会员免费看
118

被折叠的 条评论
为什么被折叠?



