林 刚 文全刚 傅晓阳 尹 贺
(吉林大学珠海学院计算机科学与技术系 广东 珠海 519041)
伴随着科技的发展,网络及其技术的应用在人们日常生活中的比重越来越大。足不出户,就可以通过互联网轻松完成购物、订餐、订房、订票、预约车等活动。支撑网络服务的硬件设备是否正常运行,在一定程度上影响着现代人的生活质量。由此,关注网络管理相关技术具有重大意义。概括来说,网络管理是管理进程(也称管理站)通过代理进程对被管设备运行状态的监测。TCP/IP网络管理协议标准框架由3个部分组成,管理信息库MIB,管理信息结构SMI和简单网络管理协议SNMP。其中,MIB包含代理进程可被查询和修改的参数,正在被使用的是MIB-II。互联网工程部(IETF)于1991年发布了MIB-II的定义文件RFC(Request For Comments) 1213,用于替代原先在RFC 1156文件中定义的MIB-I;SMI是MIB的公用结构和表示符号;SNMP是管理进程和代理进程之间的通信协议,版本有v1、v2和v3[1]。MIB文件的准确解析,是获取设备准确信息,有效网络管理的坚实基础。本文描述MIB定义文件,分析了几种有代表性的数据类型,设计了一套MIB文件解析API,并使用C#实现了MIB文件的解析。
为了获取到指定数据内容,代理进程需要知道对应的对象标识符OID以及数据结构的定义。在MIB定义文件中,这些信息使用抽象语法标记ASN.1(Abstract Syntax Notation One)进行定义。ASN.1是国际的标准化,与厂家无关,与平台无关,与语言无关,使用ASN.1定义的数据结构,抽象程度高[2]。
下面代码说明了MIB定义文件内容结构,节选自RFC 1213[4],其中“……”表示省略的部分内容。
RFC1213-MIB DEFINITIONS ::= BEGIN
IMPORTS
mgmt,NetworkAddress,IpAddress,Counter,Gauge,TimeTicks
FROM RFC1155-SMI
OBJECT-TYPE
FROM RFC-1212;
……
END
MIB定义文件内容结构特点如下:
1) 以“xxx DEFINITIONS ::= BEGIN”开头,以“END”结尾。
2) 可以引用其他MIB文件中已经定义的数据类型,语法格式为“IMPORTS ... FROM...”。
3) 数据格式的标准定义被包含在“IMPORTS”语句结束之后,“END”之前的中间部分。
MIB定义文件中的使用数据类型较多,除了ASN.1定义的原始基本类型INTEGER、OCTET STRING、OBJECT IDENTIFIER和NULL之外,还包含定义类型NetworkAddress、IpAddress、Counter、Gauge、TimeTicks、Opaque,以及构造类型SEQUENCE等,在RFC 1155中能找到相关说明[3]。
下面列出几种有代表性的数据类型,相关代码节选自RFC 1213[4]和RFC 1743[5]。
1) 简单的OBJECT-TYPE类型定义,用于描述被管理对象[6]。如ifIndex,依附于父对象ifEntry。
ifIndex OBJECT-TYPE
SYNTAX INTEGER
ACCESS read-only
STATUS mandatory
DESCRIPTION
″A unique value for ……
::= { ifEntry 1}
2) SEQUENCE类型定义,如IfEntry类型,ifEntry包含子元素ifIndex,ifDescr等。
ifEntry OBJECT-TYPE
SYNTAX IfEntry
ACCESS not-accessible
STATUS mandatory
DESCRIPTION
″An interface ……
INDEX { ifIndex }
::= { ifTable 1 }
IfEntry ::=
SEQUENCE {
ifIndex
INTEGER,
ifDescr
DisplayString,
……
}
3) 有序列表类型定义,如ifTable是IfEntry有序列表类型。
ifTable OBJECT-TYPE
SYNTAX SEQUENCE OF IfEntry
ACCESS not-accessible
STATUS mandatory
DESCRIPTION
″A list ……
::= { interfaces 2 }
4) MODULE-IDENTITY类型定义,用于描述信息模块[6],如dot5。
dot5 MODULE-IDENTITY
LAST-UPDATED ″9410231150Z″
ORGANIZATION ″IETF ……
::= { transmission 9 }
5) 使用“OBJECT IDENTIFIER”定义一种对象的标识符值[6],如mib-2。
mib-2 OBJECT IDENTIFIER ::= { mgmt 1 }
使用IMPORTS和EXPORTS语句之后,MIB定义文件不再是孤立的,而是彼此相互关联。在MIB定义文件中,使用EXPORTS语句,导出定义的数据类型或者是父OID值,在其他MIB定义文件中,使用IMPORTS语句,导入和使用这些数据类型和值。通过分析MIB定义文件中的IMPORTS和EXPORTS语句,可以明确MIB定义文件之间的相互依赖关系。部分公有RFC文件的定义依赖关系,如图1所示。
图1 MIB定义文件相互依赖图
图1中,实线表示导入或导出定义的数据类型,虚线表示导入或导出数据值;“CLNS-MIB”被定义在RFC 1238文件中。
MIB文件的加载和解析是实现基于SNMP的网管软件的核心过程[7]。MIB文件解析API的设计过程可分为三个阶段,即设计类、设计接口、实现接口。
根据MIB定义文件的特点,为数据类型设计类,一种数据类型对应一个类,如图 2所示。还可以使用其他的方法进行类设计,比如,设计一个通用类,对应MIB定义文件中的任何一种数据类型。一个类描述一种数据类型的设计,复杂度低、简单实用、代码可读性强。
图2 MIB定义中常见的数据结构类图
除了常见的数据类型之外,解析MIB定义文件和构建MIB树还需要设计IMibNode接口和MibNode类,用于存储MIB树的节点信息,以及两个核心接口和实现类,如图3和图4所示。
图3 IMibNode接口和MibNode类图
图4 MIB定义文件解析接口和实现类图
IMibNode的AddChild方法用于往当前节点中添加子节点。IMibDefinitionsDocument是MIB定义文件的接口,MibDefinitionsDocument是对应的实现类。IMibDefinitionsDocumentParser是MIB定义文件解析器的接口,MibDefinitionsDocumentParser是对应的实现类。整个API中,最核心的方法是解析器中的Parse,其主要算法如下:
步骤1遍历需要解析的所有MIB文件IMPORTS部分,构建依赖图。其数据结构可采用多路径树[8]、双亲树表示法[9]、孩子链表法等。本文采用C#实现了面向对象的双亲(Parent属性)、孩子(Children属性)一对多双向的树型结构,方便根、叶子和中间节点的遍历。
1) 解析文件定义名称,比如从“RFC1213-MIB DEFINITIONS ::= BEGIN”中解析出“RFC1213-MIB”。
2) 根据IMPORTS的内容,解析依赖关系,逐步形成依赖图。比如从“IMPORTS ... FROM RFC1155-SMI”解析出“RFC1155-SMI”,添加进当前文件对象的依赖列表中,即在依赖图中的“RFC1155-SMI”应该优先于当前文档被解析。
步骤2基于第1步生成的依赖图,按照顺序,深度优先或者广度优先遍历MIB文件的其他部分,解析每个文件的内容,构建MIB树。包括MODULE-IDENTITY,OBJECT-TYPE,Sequence类型等。比如从“application MODULE-IDENTITY ... ::= { mib-2 27 }”中解析出“application”父节点是对应为“mib-2”对应OID下的27,添加进父节点列表。
依赖图的引入,能够有助于准确定位缺失的MIB文件,为用户收集完整的MIB文件提供有效线索。对缺失的MIB文件默认不分析,提高MIB树的构建效率,此时的MIB树与RFC 1155定义的未标记根(unlabeled root)严格保持一致。使用两次遍历,第一次构建依赖图,第二次构建MIB树。其优点是分层清晰,便于理解。在构建MIB树时,按照已经生成的依赖图,从根节点出发,依次往叶子节点方向进行构建,避免了复杂的递归调用。构建MIB树中当前元素时,其父节点已经被解析,且被标识,所以能高效、准确地定位到父节点,即除数据类型自身解析外,几乎不需要花费更多额外代价去处理节点的关联关系。
IMibDefinitionsDocumentParser中的AddFile方法是往解析器中增加MIB定义文件;Serialize和Deserialize是序列化和反序列化操作,序列化将当前节点(包括所有子节点信息)输出到指定文件或者数据库中,反序列化则是相反过程;GetErrors方法获取解析器的错误信息;GetMibNodeRoot方法获取MIB树的根节点,通过循环访问MibNode的Children属性,可以从Root节点开始深度优先或广度优先遍历MIB树的所有节点,通过循环访问MibNode的Parent属性,可以直达Root节点,且只有一条路径。
MIB文件解析API接口设计数目并不多,其应用十分方便。连续调用AddFile方法往解析器中增加完全部相关MIB文件之后,调用Parse方法进行解析,调用GetMibNodeRoot方法获取解析得到的完整MIB树,调用Serialize方法将MIB树序列化到指定文件。相关代码片段如下:
var p = new MibDefinitionsDocumentParser();
p.AddFile(fileName1);
……
p.AddFile(xxx);
p.Parse();
mibNode = p.GetMibNodeRoot();
p.Serialize(outFileName);
MIB文件解析API接口的应用格式相对固定,功能灵活。如果将上述代码中的第一行稍加修改,就可以实现在解析得到的MIB树基础上,进一步解析其他MIB文件。修改代码如下:
var p = new MibDefinitionsDocumentParser(mibNode);
使用解析MIB文件的API的应用程序,在创建MIB树时,可以按照需要选择合适的方法,或者创建完整的MIB树;或者基于现有MIB树添加更多节点信息;或者通过反序列化文件或者持久化数据记录进行MIB树创建。
利用解析得到的MIB树,根据特定节点OID信息,并获取其值,可以实现对支持SNMP的网络设备进行故障跟踪和准确定位[10],包括调制解调器、路由器、交换机、服务器、工作站、打印机等[11]。
在前人研究成果的基础上,提出了基于MIB文件依赖图的解析MIB文件API的设计方法,过程中采用了面向对象的接口、类、实现三步设计方法,并在实际项目中得到了应用,为有效的网络管理奠定基础。今后,可以为API引入并行算法,提高性能;标准化持久化文件和数据记录格式,完善API应用的多点访问;考虑更多的常用场景,丰富接口等。
[1] Stevens W Richar.TCP/IP详解卷1:协议[M].范建华,胥光辉,张涛,等译.北京:机械工业出版社,2014.
[2] Larmouth John.ASN.1 Complete[M].Massachusetts:Morgan Kaufmann Publishers,1999.
[3] Rose M,McCloghrie K.RFC 1155-1990:Structure and Identification of Management Information for TCP/IP-based Internets[S].1990:1-13.
[4] McCloghrie K,Rose M.RFC 1213-1991:Management Information Base for Network Management of TCP/IP-based internets:MIB-II[S].1991:12-67.
[5] McCloghrie K,Decker E.RFC 1743-1994:IEEE 802.5 MIB using SMIv2[S].1994:4-5.
[6] McCloghrie K,Perkins D,Schoenwaelder J.RFC 2578-1999:Structure of Management Information Version 2 (SMIv2)[S].1999:2-19.
[7] 龚尚福,刘二恩,冯健.基于SNMP的MIB树结构研究与实现[J].计算机应用与软件,2013,30(12):163-166.
[8] 周剑,张晓彤,王沁.SNMP协议动态MIB结构与高效查找算法[J].计算机工程,2008,34(2):171-174.
[9] 张姣,李宥谋,何萌,等.SNMP网管技术在嵌入式仪器测控领域的研究与应用[J].计算机应用与软件,2014,31(10):329-333.
[10] 赵灿明,纪诗厚,石滚,等.面向以太网的网络故障自动实时发现与定位方法[J].计算机应用与软件,2016,33(9):101-105.
[11] SNMP wiki[EB/OL].[2017-4-7].https://en.wikipedia.org/wiki/Simple_Network_Management_Protocol.