28、设计与实现 SNMP MIB 指南

设计与实现 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 的设计和实现,以确保网络设备的高效管理和监控。

根据原作 https://pan.quark.cn/s/459657bcfd45 的源码改编 Classic-ML-Methods-Algo 引言 建立这个项目,是为了梳理和总结传统机器学习(Machine Learning)方法(methods)或者算法(algo),和各位同仁相互学习交流. 现在的深度学习本质上来自于传统的神经网络模型,很大程度上是传统机器学习的延续,同时也在不少时候需要结合传统方法来实现. 任何机器学习方法基本的流程结构都是通用的;使用的评价方法也基本通用;使用的一些数学知识也是通用的. 本文在梳理传统机器学习方法算法的同时也会顺便补充这些流程,数学上的知识以供参考. 机器学习 机器学习是人工智能(Artificial Intelligence)的一个分支,也是实现人工智能最重要的手段.区别于传统的基于规则(rule-based)的算法,机器学习可以从数据中获取知识,从而实现规定的任务[Ian Goodfellow and Yoshua Bengio and Aaron Courville的Deep Learning].这些知识可以分为四种: 总结(summarization) 预测(prediction) 估计(estimation) 假想验证(hypothesis testing) 机器学习主要关心的是预测[Varian在Big Data : New Tricks for Econometrics],预测的可以是连续性的输出变量,分类,聚类或者物品之间的有趣关联. 机器学习分类 根据数据配置(setting,是否有标签,可以是连续的也可以是离散的)和任务目标,我们可以将机器学习方法分为四种: 无监督(unsupervised) 训练数据没有给定...
本系统采用微信小程序作为前端交互界面,结合Spring BootVue.js框架实现后端服务及管理后台的构建,形成一套完整的电子商务解决方案。该系统架构支持单一商户独立运营,亦兼容多商户入驻的平台模式,具备高度的灵活性扩展性。 在技术实现上,后端以Java语言为核心,依托Spring Boot框架提供稳定的业务逻辑处理数据接口服务;管理后台采用Vue.js进行开发,实现了直观高效的操作界面;前端微信小程序则为用户提供了便捷的移动端购物体验。整套系统各模块间紧密协作,功能链路完整闭环,已通过严格测试优化,符合商业应用的标准要求。 系统设计注重业务场景的全面覆盖,不仅包含商品展示、交易流程、订单处理等核心电商功能,还集成了会员管理、营销工具、数据统计等辅助模块,能够满足不同规模商户的日常运营需求。其多店铺支持机制允许平台方对入驻商户进行统一管理,同时保障各店铺在品牌展示、商品销售及客户服务方面的独立运作空间。 该解决方案强调代码结构的规范性可维护性,遵循企业级开发标准,确保了系统的长期稳定运行后续功能迭代的可行性。整体而言,这是一套技术选型成熟、架构清晰、功能完备且可直接投入商用的电商平台系统。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值