1.Architecture
1.1 Agent Architecture
Upon starting, the agent goes through the following steps (in SnmpDaemonMain()):
- reads command line options
- decides whether it’s a master or subagent
- calls init_agent()
- initializes the mib-module registration tree
- registers its own configuration file tokens and callbacks
- initializes the Agent Helpers
- initializes all the compiled-in mib modules
- initializes the base libnetsnmp library
- opens all the required ports to listen on
- forks
- saves persistent data (it’s likely at least something has changed already)
- sends a coldStart trap
- invokes receive() to perform the main packet handling
Reference: Agent_Architecture
1.2 snmpget snmpset snmpwalk snmptrap
Reference: mib2c_General_Overview
* snmptranslate: learning about the MIB tree.
* snmpget: retrieving data from a host.
* snmpgetnext: retrieving unknown indexed data.
* snmpwalk: retrieving lots of data at once!
* snmptable: displaying a table.
* snmpset: peforming write operations.
* snmpbulkget: communicates with a network entity using SNMP GETBULK request
* snmpbulkwalk: retrieve a sub-tree of management values using SNMP GETBULK requests.
* snmptrap: sending traps messages, and acting upon them.
* snmptrapd: receive and logs SNMP TRAP and INFORM messages.
for more, use 'man' command to see usage.
example:
#### snmpwalk
[dennis@localhost ~]$ snmpwalk -v2c -c public 192.168.110.98 .1.3.6.1.4.1.50369
...
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.3.1 = INTEGER: 856398
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.4.1 = INTEGER: 432164
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.5.1 = INTEGER: 424234
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.6.1 = INTEGER: 1
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.7.1 = INTEGER: 3
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.8.1 = STRING: "0:1 0:2 0:3 "
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.9.1 = INTEGER: 3
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.10.1 = INTEGER: 0
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.11.1 = INTEGER: 4
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.12.1 = INTEGER: 0
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.13.1 = INTEGER: 5
#### snmpget
[dennis@localhost ~]$ snmpget -v2c -c public 192.168.110.98 .1.3.6.1.4.1.50369.1.1.2.5.1.3.1
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.3.1 = INTEGER: 856398
[dennis@localhost ~]$ snmpget -v2c -c public 192.168.110.98 .1.3.6.1.4.1.50369.1.1.2.5.1.8.1
SNMPv2-SMI::enterprises.50369.1.1.2.5.1.8.1 = STRING: "0:1 0:2 0:3 "
#### snmpset
[dennis@localhost ~]$ snmpset -v2c -c private 192.168.110.98 .1.3.6.1.4.1.50369.1.1.1.3.1.0 i 2
SNMPv2-SMI::enterprises.50369.1.1.1.3.1.0 = INTEGER: 2
[dennis@localhost ~]$ snmpset -v2c -c private 192.168.110.98 .1.3.6.1.4.1.50369.1.1.1.3.2.0 s "2013-08-16 15:32:40"
SNMPv2-SMI::enterprises.50369.1.1.1.3.2.0 = STRING: "2013-08-16 15:32:40"
#### snmptrap
# use snmptrapd to receive trap message.
# 1.first create file "touch /usr/local/share/snmp/snmptrapd.conf"
# 2.then add "authcommunity execute,log,net public" to the file to access
# receive trap message.
# (use command 'snmpconf' to create and config is another choise)
# use root to start snmptrapd
[root@localhost ~]# snmptrapd -f -Le -F "%02.2h:%02.2j TRAP%w.%q from %b\n %v\n"
NET-SNMP version 5.7.2
14:30 TRAP0.0 from UDP: [192.168.110.39]:52222->[192.168.50.63]:162
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (1) 0:00:00.01 SNMPv2-MIB::snmpTrapOID.0 = OID: SNMPv2-SMI::enterprises.50369.1.3.0.1 SNMPv2-SMI::enterprises.50369.1.1.2 = INTEGER: 1
15:38 TRAP0.0 from UDP: [172.16.110.39]:35505->[172.16.50.63]:162
SNMPv2-MIB::snmpTrapOID.0 = OID: SNMPv2-SMI::enterprises.50369 SNMPv2-SMI::enterprises.50369.1.1.2 = STRING: "string value test"
root:~# snmptrap -v 2c -c public 192.168.50.63 1 .1.3.6.1.4.1.50369.1.3.0.1 .1.3.6.1.4.1.50369.1.1.2 i 1
root:~# snmptrap -v 2c -c public 192.168.50.63 "abc" .1.3.6.1.4.1.50369 .1.3.6.1.4.1.50369.1.1.2 s "string value test"
2. Install
2.1 Yum
install snmp
su -c 'yum install net-snmp'
install mib2c
su -c 'yum install net-snmp-perl'
install utils tools:snmpwalk, snmpget,…
su -c 'yum install net-snmp-utils'
3. Steps
- Write your self-defined mibs
- Copy to /usr/local/share/snmp/mibs
- 用snmptranslate -Ts -m ALL 就可以看到所以OID的输出了,当然也包括你新加的。
如果写的mib文件不正确,应该不能输出,你可以找第三方工具来验证你的文件格式是否正确。
- 编写相关的函数。
- 为你的mib新建一个c文件,可以使用mib2c这样的工具来完成。
- 如果该OID是只读的,那就在该文件里编写一个只读的函数(mib2c应该会生成的);如果可写,也应该有一个写的函数(相样是生成的)
3.2 Self-defined Mib
I don’t find any good tools for generate mibs, what I do is hacking by hand; if
you know some good tool, don’t forget to tell me.
--============================================================
-- Dennis Sample Management Information Base (MIB)
--============================================================
DENNIS-MIB DEFINITIONS ::= BEGIN
IMPORTS
DisplayString,
PhysAddress,
MacAddress,
DateAndTime,
RowStatus,
TEXTUAL-CONVENTION
FROM SNMPv2-TC
MODULE-IDENTITY,
OBJECT-TYPE,
NOTIFICATION-TYPE,
Integer32,
IpAddress,
TimeTicks,
Unsigned32
FROM SNMPv2-SMI;
--============================================================
-- MODULE IDENTITY : dennis
--============================================================
dennis MODULE-IDENTITY
LAST-UPDATED "201308160000Z"
ORGANIZATION "MIB"
CONTACT-INFO
"Shenzhen, China, Earth village, Solar system
http://matrix207.github.com
E-mail: dennis.cpp@gmail.com"
DESCRIPTION
"Sample MIB Definition for
iso(1).org(3).dod(6).internet(1).private(4).enterprises(1).dennis(9913)"
::= { 1 3 6 1 4 1 9913 }
--============================================================
-- Definition of the Sample MIB Common Objects
--============================================================
dennisSampleMib OBJECT IDENTIFIER ::= { dennis 1 }
--============================================================
-- Definition of the Information Group
--============================================================
dennisSystemInformation OBJECT IDENTIFIER ::= { dennisSampleMib 1 }
--============================================================
-- Definition of the Information Group (Object type: scalar)
--============================================================
dennisSysInfoEntry OBJECT IDENTIFIER ::= { dennisSystemInformation 1 }
dennisSystemOSVersion OBJECT-TYPE
SYNTAX DisplayString (SIZE (64))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"This object show the operator system version."
::= { dennisSysInfoEntry 1 }
dennisSystemOSBit OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"This object show the operator system bit"
::= { dennisSysInfoEntry 2 }
dennisSystemCPU OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The speed of processor, unit: MHZ"
::= { dennisSysInfoEntry 3 }
dennisSystemMemory OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The total number of memory, unit: MB"
::= { dennisSysInfoEntry 4 }
dennisSystemDiskSizy OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The total size of disks"
::= { dennisSysInfoEntry 5 }
--============================================================
-- Definition of the Directory Group Mount on Root (Object type: table)
--============================================================
dennisSubDirOfRootInformationTable OBJECT-TYPE
SYNTAX SEQUENCE OF DennisSubDirOfRootInformationEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A list of expander chassis information."
::= { dennisSampleMib 2 }
dennisSubDirOfRootInformationEntry OBJECT-TYPE
SYNTAX DennisSubDirOfRootInformationEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A expander chassis information entry"
INDEX { dennisSubDirOfRootIndex }
::= { dennisSubDirOfRootInformationTable 1 }
DennisSubDirOfRootInformationEntry ::=
SEQUENCE {
dennisSubDirOfRootIndex Integer32,
dennisSubDirOfRootName DisplayString,
dennisSubDirOfRootSize Integer32,
dennisSubDirOfRootDate DisplayString }
dennisSubDirOfRootIndex OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The index."
::= { dennisSubDirOfRootInformationEntry 1 }
dennisSubDirOfRootName OBJECT-TYPE
SYNTAX DisplayString (SIZE (64))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The type of expander chassis."
::= { dennisSubDirOfRootInformationEntry 2 }
dennisSubDirOfRootSize OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The expander chassis manufacturer's id."
::= { dennisSubDirOfRootInformationEntry 3 }
dennisSubDirOfRootDate OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The total number of physical slots for physical
disk on the chassis."
::= { dennisSubDirOfRootInformationEntry 4 }
--============================================================
-- Definition of access object (Object type: scalar)
--============================================================
dennisAccessObject OBJECT IDENTIFIER ::= { dennisSampleMib 3 }
dennisShutdownType OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Use for shudown operator system, 1:shutdown 2:reboot"
::= { dennisAccessObject 1 }
--============================================================
-- End Definition
--============================================================
END
3.3 Check mib
[root@localhost mib]# snmptranslate -Tp -m DENNIS-MIB
+--iso(1)
|
+--anonymous#0(3)
|
+--anonymous#1(6)
|
+--anonymous#2(1)
|
+--anonymous#3(4)
|
+--anonymous#4(1)
|
+--dennis(9913)
|
+--dennisSampleMib(1)
|
+--dennisSystemInformation(1)
| |
| +--dennisSysInfoEntry(1)
| |
| +-- -R-- String dennisSystemOSVersion(1)
| | Textual Convention: DisplayString
| | Size: 64
| +-- -R-- Integer32 dennisSystemOSBit(2)
| +-- -R-- Integer32 dennisSystemCPU(3)
| +-- -R-- Integer32 dennisSystemMemory(4)
| +-- -R-- Integer32 dennisSystemDiskSizy(5)
|
+--dennisSubDirOfRootInformationTable(2)
| |
| +--dennisSubDirOfRootInformationEntry(1)
| | Index: dennisSubDirOfRootIndex
| |
| +-- -R-- Integer32 dennisSubDirOfRootIndex(1)
| +-- -R-- String dennisSubDirOfRootName(2)
| | Textual Convention: DisplayString
| | Size: 64
| +-- -R-- Integer32 dennisSubDirOfRootSize(3)
| +-- -R-- String dennisSubDirOfRootDate(4)
| Textual Convention: DisplayString
| Size: 0..255
|
+--dennisAccessObject(3)
|
+-- -RW- Integer32 dennisShutdownType(1)
4. Use mib2c
4.1 mib object
scalar: int, string, time and so on.
table : table has row and column, like table in database.
4.2 use mib2c to create source file
append string “DENNIS-MIB” to config file: snmpd.conf
su -c 'vim /etc/snmp/snmpd.conf'
copy mib file to mibs directory(depend on which directory mib2c installed)
su -c 'cp DENNIS-MIB.txt /usr/local/share/snmp/mibs/'
generate c source file by mib2c
mib2c -c mib2c.scalar.conf DENNIS-MIB::dennis
for scalar object
mib2c -c mib2c.old-api.conf DENNIS-MIB::dennis
for scalar object
mib2c -c mib2c.iterate.conf DENNIS-MIB::dennis
for table object (choise 2)
mib2c -c mib2c.notify.conf DENNIS-MIB::dennis
for trapping message
if failed to translate, check the mibs directory again, or look the output message.
more configure files, look as below:
[dennis@localhost net-snmp-5.4.2]$ ls /usr/local/share/snmp/*.conf
/usr/local/share/snmp/mib2c.access_functions.conf
/usr/local/share/snmp/mib2c.int_watch.conf
/usr/local/share/snmp/mib2c.array-user.conf
/usr/local/share/snmp/mib2c.iterate_access.conf
/usr/local/share/snmp/mib2c.check_values.conf
/usr/local/share/snmp/mib2c.iterate.conf
/usr/local/share/snmp/mib2c.check_values_local.conf
/usr/local/share/snmp/mib2c.mfd.conf
/usr/local/share/snmp/mib2c.column_defines.conf
/usr/local/share/snmp/mib2c.notify.conf
/usr/local/share/snmp/mib2c.column_enums.conf
/usr/local/share/snmp/mib2c.old-api.conf
/usr/local/share/snmp/mib2c.column_storage.conf
/usr/local/share/snmp/mib2c.perl.conf
/usr/local/share/snmp/mib2c.conf
/usr/local/share/snmp/mib2c.raw-table.conf
/usr/local/share/snmp/mib2c.container.conf
/usr/local/share/snmp/mib2c.scalar.conf
/usr/local/share/snmp/mib2c.create-dataset.conf
/usr/local/share/snmp/mib2c.table_data.conf
/usr/local/share/snmp/mib2c.genhtml.conf
/usr/local/share/snmp/snmptrapd.conf
5. Add self-defined mib library
5.1 steps:
使用net-snmp扩展私有MIB的大致方法
参考: net-snmp tutorial
step 1. 首先需要使用net-snmp的相关API编写MIB相关C代码,
1. MFD/mib2c:这是一种通过net-snmp提供的mib2c程序自动生成相关代码的方式
2. A simple scalar attached to a variable:适合于简单变量类型的object
3. A simple scalar with the value returned from code:适用于任何变量类型的object
step 2. 然后将刚写的MIB C code编译进net-snmp,有几种方法:
1. compile it into master agent:
1)将刚编写的码加入net-snmp的src目录,
2)通过configure的option指示make编译该mib,
如./configure --with-mib-modules="myobject"
3)make
4)make install
这样,你的MIB就已经被内置如snmp服务程序中了,MIB的生效也就理所当然
2. compile your code into a “subagent”:
这种方式可以将subagent通过agentx协议与master agent通信,
参考: http://net-snmp.sourceforge.net/tutorial/tutorial-5/toolkit/demon/index.html
这种情况subagent最终是一个独立的application,包含两种生成方式,
1).是通过net-snmp-config工具生成;
2).是自己编写程序控制调用;
后者更为灵活,subagent功能可以被集成在其它application中。
3. compile your code into pluggable shared object and tell the snmpd agent to load it
这种方式最后生成一个.so的共享库,用户启动snmpd服务时可以通过指定参数的方式
加载该共享库以扩展MIB,
参考: http://net-snmp.sourceforge.net/tutorial/tutorial-5/toolkit/dlmod/index.html
5.2 compile net-snmp by shell script
cd /home/dennis/net-snmp-5.4.2/
cp -f /home/dennis/dennis.{h,c} ./agent/mibgroup
./configure --prefix=/usr --with-mib-modules="dennis"
make clean
make
make install
5.3 update mib
copy "net-snmp-5.4.2/agent/.libs/libnetsnmpmibs.so" to "/usr/lib/",
64bit system is to "/usr/lib64/"
5.4 check the so had have the interfaces which you implement
[root@ ~]# which snmpd
/usr/sbin/snmpd
[root@ ~]# ldd /usr/sbin/snmpd | grep libnetsnmpmib
libnetsnmpmibs.so.15 => /usr/lib64/libnetsnmpmibs.so.15 (0x0000003655600000)
[root@ ~]# nm /usr/lib64/libnetsnmpmibs.so.15 | grep "YOUR_INTERFACE_KEY"
5.5 check config file
check the file /etc/snmp/snmpd.conf, append `rwcommunity private` to it to
make access authority for `snmpset`.
5.6 restart snmp
/usr/sbin/snmpd -c /etc/snmp/snmpd.conf -Le
6. Improve speed
When snmp agent receive lots of request, and if do some I/O operation of each
request, that will show a low performance.
One not-bad solution is use a thread do the I/O job, and store the information
to memory (using global variable, array, structure …), then fill info and
return to client when get the request.
6.1 add thread function to mib file
Add include #include <pthread.h>
to the mib file
Write thread function like this: void *update_all_info (void *parm);
6.2 modify Makefile
Add link library(-lpthread
) to agent/Makefile (line:199):
LOCAL_LIBS = -L../snmplib/.libs -L../snmplib -L./.libs -L./helpers/.libs -L./helpers -lpthread
7. Reference
7.1 network link