W6300使用SNMP管理其他设备
更新于 2026年10月10日
本篇总结
在 W6300 上实现 SNMP Agent 功能,通过 MIB Browser 管理 W6300 的设备状态。
硬件平台:本例程基于 W6300-EVB-M4 开发板运行。
采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W6300-EVB-M4 开发板
本示例演示如何在 W6300 上实现 SNMP(简单网络管理协议)功能。通过实战例程,为大家讲解如何使用 MIB Browser 管理 W6300,实现远程读取设备管理等操作。该例程用到的其他网络协议,例如 DHCP,请参考相关章节。
前置工具准备
开始本例程前,请确认以下工具已安装:
SNMP 协议简介
SNMP(Simple Network Management Protocol)是应用层的网络管理协议,用于在网络设备之间交换管理信息。它工作在 UDP 之上,Agent 端口为 161,Trap 端口为 162。通过 SNMP,管理站可以远程监控和配置网络设备。
| 组成 | 角色 | 说明 |
|---|---|---|
| 管理站(Manager) | 发起请求 | 运行 MIB Browser 的 PC,向设备发送 GET/SET 请求 |
| 代理(Agent) | 响应请求 | W6300,监听 UDP 161,接收并处理管理站的请求 |
| MIB | 管理信息库 | 以 OID 树形结构组织的管理对象集合 |
W6300 的优势
W6300 SDK 内置了完整的 SNMP Agent 库,报文组包/解包、OID 匹配、Trap 发送全部由库函数处理。你只需要:注册定时器 → 添加 MIB 数据项 → 初始化 SNMP → 在主循环中调用 snmpd_run() 驱动状态机。
工程结构
工程核心文件如下:
Project/
├── main.c ← 系统入口:串口、GPIO、QSPI 初始化 + user_run()
├── USER/
│ ├── user_main.c ← 网络地址定义 + user_run() 主流程
│ ├── wiz_platform.c/h ← 平台适配:debug_usart_init、wizchip_gpio_init、hspi_init
│ └── wiz_interface.c/h ← W6300 驱动接口:wizchip_initialize、network_init、PHY 检测、软件定时器
└── Internet/
├── snmp.c ← SNMP Agent 初始化与主循环(snmpd_init / snmpd_run)
└── snmp_custom.c ← MIB 数据定义 + GET/SET 回调函数
本例程的核心:在 Internet/snmp_custom.c 中定义 MIB 数据项并注册 GET/SET 回调函数,通过 snmpd_run() 驱动 SNMP Agent 状态机处理请求。
硬件连接与拓扑
请注意:
PC(运行 MIB Browser)和 W6300 需处于同一网段。W6300 需先完成网络初始化(如通过 DHCP 获取 IP 地址)。
- Micro USB 线连接 DEBUG USB 口到 PC(供电 + 调试串口)
- 网线连接开发板 RJ45 网口 到路由器 LAN 口
- 确保 W6300 与 MH2457 之间的 QSPI 连线正确(CSn、SCK、DATA0~DATA3)
│ 路由器(DHCP Server) │
│ 192.168.1.1 │
└────┬───────────────────┬──────────┘
│ │
┌────┴──────┐ ┌────┴──────────────┐
│ W6300 │ │ PC │
│(SNMP Agent)│ │ (iReasoning MIB │
│ UDP :161 │ │ Browser) │
└────┬──────┘ └───────────────────┘
│ QSPI ↑
┌────┴──────┐ DEBUG USB
│ MH2457 │──────→ WIZ UartTool
│ MCU │
└───────────┘
步骤1:注册SNMP定时器
文件:USER/user_main.c — SNMP 协议的超时处理需要 10ms 级别的定时器。W6300 平台通过软件定时器链表注册回调,每 10ms 调用一次 SNMP_time_handler()。
/* Preserve the W6300 SNMP time base without putting protocol ticks in wiz_platform. */
wiz_add_timer(SNMP_time_handler, 10);
wiz_add_timer() 把回调注册到软件定时器链表,由 1ms 系统定时中断驱动 wiz_timer_handler(),累计到 10ms 后执行 SNMP_time_handler()。SNMP_time_handler() 将 snmp_tick_10ms 加 1,为 SNMP 的 SysUptime 提供时基。
步骤2:添加MIB功能函数
文件:Internet/snmp_custom.c — 在 snmpData 结构体变量中添加 MIB 数据项,包括系统信息、LED 的 GET/SET 功能以及长 OID 测试项。
dataEntryType snmpData[] = {
// System MIB
// SysDescr Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 1, 0},
SNMPDTYPE_OCTET_STRING, 30, {"WIZnet Embedded SNMP Agent"},
NULL, NULL
},
// SysObjectID Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 2, 0},
SNMPDTYPE_OBJ_ID, 8, {"\x2b\x06\x01\x02\x01\x01\x02\x00"},
NULL, NULL
},
// SysUptime Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 3, 0},
SNMPDTYPE_TIME_TICKS, 0, {""},
currentUptime, NULL
},
// sysContact Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 4, 0},
SNMPDTYPE_OCTET_STRING, 30, {"http://www.wizwiki.net/forum"},
NULL, NULL
},
// sysName Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 5, 0},
SNMPDTYPE_OCTET_STRING, 30, {"http://www.wiznet.co.kr"},
NULL, NULL
},
// Location Entry
{
8, {0x2b, 6, 1, 2, 1, 1, 6, 0},
SNMPDTYPE_OCTET_STRING, 30, {"4F Humax Village"},
NULL, NULL
},
// SysServices
{
8, {0x2b, 6, 1, 2, 1, 1, 7, 0},
SNMPDTYPE_INTEGER, 4, {""},
NULL, NULL
},
// OID Test #1 (long-length OID example, 19865)
{
0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
SNMPDTYPE_OCTET_STRING, 30, {"long-length OID Test #1"},
NULL, NULL
},
// OID Test #2 (long-length OID example, 22210)
{
0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0xad, 0x42, 0x01, 0x00},
SNMPDTYPE_OCTET_STRING, 35, {"long-length OID Test #2"},
NULL, NULL
},
// OID Test #2: SysObjectID Entry
{
0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0xad, 0x42, 0x02, 0x00},
SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\xad\x42\x02\x00"},
NULL, NULL
},
};
const int32_t maxData = (sizeof(snmpData) / sizeof(dataEntryType));
void initTable(void) {
// Example integer value for [OID 1.3.6.1.2.1.1.7.0]
snmpData[6].u.intval = 0xFFFFFFFBU; /* -5 in 32-bit two's-complement form */
}结构体变量 snmpData 的结构体 dataEntryType 定义如下所示:
typedef struct {
uint8_t oidlen;
uint8_t oid[MAX_OID];
uint8_t dataType;
uint8_t dataLen;
union {
uint8_t octetstring[MAX_STRING];
uint32_t intval;
} u;
void (*getfunction)(void *, uint8_t *);
void (*setfunction)(int32_t);
} dataEntryType;关键说明
MIB 数据项通过 getfunction 和 setfunction 两个回调函数与用户代码交互。读取时由 getfunction 返回当前值,设置时由 setfunction 应用新值。本例程中 SysUptime 使用 currentUptime 回调返回系统运行时间,其他数据项使用静态值。
步骤3:初始化SNMP协议
文件:Internet/snmp.c — 调用 snmpd_init() 初始化 SNMP Agent,注册管理站 IP、代理 IP、Agent Socket 号和 Trap Socket 号。
uint8_t manager[4] = {192, 168, 1, 127};
wizchip_getnetinfo(&net_info);
snmpd_init(manager, net_info.ip, SOCKET_ID, SOCKET_ID + 1);
snmpd_init() 函数内部记录 Socket 号、保存启动时间、调用 initTable() 初始化 MIB 数据、调用 initial_Trap() 向管理站发送 WarmStart Trap 通知。
void snmpd_init(uint8_t * managerIP, uint8_t * agentIP,
uint8_t sn_agent, uint8_t sn_trap)
{
SOCK_SNMP_AGENT = sn_agent;
SOCK_SNMP_TRAP = sn_trap;
if ((SOCK_SNMP_AGENT > _WIZCHIP_SOCK_NUM_) ||
(SOCK_SNMP_TRAP > _WIZCHIP_SOCK_NUM_)) return;
startTime = getSNMPTimeTick(); // Start time (unit: 10ms)
initTable(); // Settings for OID entry values
initial_Trap(managerIP, agentIP);
}步骤4:在主循环中运行snmpd_run()
文件:Internet/snmp.c — snmpd_run() 函数执行一个 UDP 状态机,当收到 SNMP 管理站的消息后执行解析以及回复操作。
int32_t snmpd_run(void) {
int32_t ret;
int32_t len = 0;
uint8_t svr_addr[6];
uint16_t svr_port;
uint8_t addr_len;
if (SOCK_SNMP_AGENT > _WIZCHIP_SOCK_NUM_) {
return -99;
}
switch (getSn_SR(SOCK_SNMP_AGENT)) {
case SOCK_UDP :
if ((len = getSn_RX_RSR(SOCK_SNMP_AGENT)) > 0) {
if (len > MAX_SNMPMSG_LEN) {
len = MAX_SNMPMSG_LEN;
}
request_msg.len = recvfrom(SOCK_SNMP_AGENT, request_msg.buffer, len,
svr_addr, &svr_port, &addr_len);
} else {
request_msg.len = 0;
}
if (request_msg.len > 0) {
// Initialize
request_msg.index = 0;
response_msg.index = 0;
errorStatus = errorIndex = 0;
memset(response_msg.buffer, 0x00, MAX_SNMPMSG_LEN);
// Received message parsing and send response process
if (parseSNMPMessage() != -1) {
sendto(SOCK_SNMP_AGENT, response_msg.buffer, response_msg.index,
svr_addr, svr_port, 4);
}
}
break;
case SOCK_CLOSED :
if ((ret = socket(SOCK_SNMP_AGENT, Sn_MR_UDP,
PORT_SNMP_AGENT, 0x00)) != SOCK_SNMP_AGENT) {
return ret;
}
printf(" - [%d] UDP Socket for SNMP Agent, port [%d]\r\n",
SOCK_SNMP_AGENT, PORT_SNMP_AGENT);
break;
default :
break;
}
return 1;
}
snmpd_run() 函数会执行一个 UDP 状态机,当收到 SNMP 管理的消息后会执行解析以及回复操作。在 SOCK_UDP 状态下接收数据,调用 parseSNMPMessage() 解析请求并生成响应,然后通过 sendto() 发送响应。W6300 平台的 recvfrom() / sendto() 需要额外传入地址长度参数(IPv4 为 4)。
运行验证
烧录例程运行后,首先可以看到打印了 PHY 链路检测和 DHCP 获取网络信息,然后运行 SNMP 程序。打开 iReasoning MIB Browser,输入 W6300 的 IP 地址进行以下操作:
MH2457 W6300 QSPI example start
W6300 SNMP example
PHY link
The current Mbtis speed : 100Mbps
The current Duplex Mode : Full-Duplex
DHCP running
DHCP success!
====================================================================================================
W6300 network configuration : DHCP
MAC : 00:08:DC:12:34:56
IP : 192.168.1.8
Subnet Mask : 255.255.255.0
Gateway : 192.168.1.1
DNS : 192.168.1.1
====================================================================================================
- SNMP : Start SNMP Agent Daemon
- [1] UDP Socket for SNMP Agent, port [161]
测试前提
测试实例需要 PC 端(运行 MIB Browser)和 W6300 处于同一网段。W6300 需先完成网络初始化(如通过 DHCP 获取 IP 地址)。
- 打开 MIB Browser,输入 W6300 的地址,然后依次点击 system 分支下的各个节点,获取到的结果与代码定义相同。
- 找到长 OID 测试分支下的节点,右键点击 get,即可读出对应的字符串值。


常见问题
Q: SNMP有哪些版本,本例程使用哪个版本
SNMP主要有三个版本:SNMPv1、SNMPv2c和SNMPv3。本例程使用的是SNMPv1版本(Version字段值为0)。SNMPv1和SNMPv2c使用社区字符串进行简单身份验证,SNMPv3提供了更强的安全机制(认证和加密)。不同版本的报文格式存在差异。
Q: 什么是社区字符串,public和private有什么区别
社区字符串是SNMPv1和SNMPv2c的一种简单身份验证机制,用于限制对管理对象的访问权限。public通常表示只读访问权限,private通常表示读写访问权限。它相当于一个简单的"密码",安全性较低,SNMPv3中已被更完善的USM安全模型取代。
Q: OID是什么,如何查询和设置设备信息
OID(对象标识符)是唯一标识MIB中管理对象的分层命名方案,由点号分隔的整数组成(如1.3.6.1.2.1.1.1.0)。使用SNMP GET请求可查询特定OID的值,使用SET请求可修改OID的值(需设备支持),使用WALK请求可遍历一个OID下的所有子节点。使用前最好查阅设备的MIB文档了解支持的OID。
Q: 如何让设备主动上报事件
设备可以通过SNMP Trap机制主动向管理站上报事件。在snmpd_init()初始化时配置管理站IP和代理IP,然后调用snmp_sendTrap()函数发送Trap报文。支持通用Trap(如warmStart)和企业自定义Trap。Trap使用UDP端口发送,无需管理站主动请求。
Q: 测试SNMP功能有什么前提条件
测试实例需要PC端(运行MIB Browser)和W6300处于同一网段。W6300需要先完成网络初始化(如通过DHCP获取IP地址),并确保SNMP Agent的UDP Socket(端口161)正常打开。snmpd_run()需要在主循环中持续调用以处理来自管理站的请求。
总结
- 协议概念:SNMP是应用层网络管理协议,具有简单性、互操作性、跨平台支持等特点
- 架构组成:包括管理站(Manager)、代理(Agent)、管理信息库(MIB)和协议本身四部分
- OID详解:分层命名方案(如1.3.6.1.2.1.1.1.0),通过GET/SET/WALK操作管理设备
- 报文格式:基于ASN.1/BER编码,包含Version、Community、PDU、变量绑定等字段
- 实现步骤:注册10ms定时器 → 添加MIB功能函数 → 初始化SNMP → 主循环运行snmpd_run()
- 应用场景:故障报警、工业自动化环境监控、数据中心机房管理