校园网络设备管理现状
上海财经大学现有网络设备1000多台, 需管理的设备型号复杂多样, 尤其是核心层设备上的管理数据量非常大,使用传统的SNMP管理协议来监控和管理效率比较低。对于学校的网络管理系统来说,如设备告警和性能等许多业务数据,是通过管理信息库MIB表来获取的。由于SNMP标准报文GET,GETNEXT报文的限制,如要获取相关的业务数据信息,必须将整个MIB表中告警和性能节点的数据全部获取下来,然后再进行过滤筛选。当整个MIB表非常庞大时,这种做法耗时较长且会消耗较多的带宽。
SNMP新成员构思方案
针对以上问题,我们在上海财经大学网络管理系统中设计了新的解决方案,提出两种新的SNMP服务,getAlm和getPm。
首先在新SNMP服务中需对过滤条件进行设置,封装在SNMP的GET报文中,有选择的获取M I B对象值。新服务沿袭了SNMP协议内容简单的特点,只需对P D U报文的get-request进行扩充(get-Alm-request和get-Pm-request),response报文结构维持不变,但需要在返回的P D U数据包中,增加对新服务的异常状态处理。
对于get-Alm-request,默认设置的过滤选项:cardtype板卡类型,severity严重级别,alarmtype告警类型,alarmtime告警产生时间。而对于get-Pm-request,默认选项包括:pfmtime性能产生时间 ,pfminterval性能监控间隔(包含15分钟或24小时), cardtype板卡类型,pfmparameters性能监控参数。上述这些选项可在S N M P管理端进行设置,SNMP的Agent端支持按上述选项过滤输出结果。
对SNMP协议数据单元做如下新的定义:
PDU ::= CHOICE {
get-requestGetRequest-PDU,
get-nextrequest GetNextRequest-PDU,
response Response-PDU,
set-requestSetRequest-PDU,
get-Alm-request GetAlmRequest-PDU,
get-Pm-request GetPmRequest-PDU
}
GetRequest-PDU ::= [0] IMPLICIT PDU
GetNextRequest-PDU ::= [1] IMPLICIT PDU
Response-PDU ::= [2] IMPLICIT PDU
SetRequest-PDU ::= [3] IMPLICIT PDU
GetAlmRequest-PDU ::=[20] IMPLICITAlm PDU
GetPmRequest-PDU ::= [21] IMPLICITPm PDU
从上表可以看出,在使用A S N .1描述SNMP的Protocol Data Unit(协议数据单元简称PDU)定义中,在choice可供选择的类型中新增了“20”和“21”两种新类型。
对于这两种新P D U的定义,在下面的ASN.1中给出了具体描述。
AlmPDU ::=
SEQUENCE{
request-id INTEGER
number-of-logic INTEGER(0..8)
max-return-records INTEGER
variable-bindings VarBindList
}
PmPDU ::=
SEQUENCE{
request-id INTEGER
number-of-logic INTEGER
(0..8) max-return-recordsINTEGER
variable-bindings VarBindList
}
上述PDU设计了最多八个逻辑表达式的条件,现在假设这个过滤条件数为n,这n个条件将出现在VarBindList变量表中。对于varbindlist的变量名和值,这里的变量名指的是上述cardtype, severity等过滤选项所对应的目标Object Identifiers(简称OID)值。而变量值罗列出了这些目标对象可能的取值范围。在逻辑条件表达式中,需要逻辑运算符来把变量名和值联系起来。因此设计了在目标对象名中用固定的整数值来表示相应的逻辑运算符:0表示“=”,1表示“<”, 2表示“>”, 3表示“< =”, 4表示“>=”, 5表示“!=”。
这样varbindlist变量表中的名和值键值就可以联系起来了。下面给出varbindlist的定义。
VarBindList ::=SEQUENCE OF VarBind VarBind ::=
SEQUENCE{
name myObjectName,
-- { myObjectName 0}: 对象名等于某值
-- { myObjectName 1}: 对象名小于某值
-- { myObjectName 2}: 对象名大于某值
-- { myObjectName 3}: 对象名小于等于于某值
-- { myObjectName 4}: 对象名大于等于某值
-- { myObjectName 5}: 对象名不等于某值。
CHOICE {
value objectSyntax,(出现在response报文或AlmPDU和PmPDU报文中)
NULL, (出现在一般的get报文中,为空值)
noSuchobject[0]
noSuchInstance [1]
endOfMibView [2]
endOfAlmTable [3]
endOfPmTable[4]
(出现在response报文中可能返回的异常结果。)
这里设置的endOfAlmTable和endOfPmTable标签,是因为考虑到设置的返回记录数大于实际数目时可以提前跳出。varbindlist变量表中的字段包括了两个条目:过滤条件和请求字段。其中的前x个varbind表示过滤条件,x的值就是number-of-logic字段值,其中每个varbind由变量名和值组成;而其余的varbind表示请求字段,其中的varbind只包含了所取的变量名。
另外两个PDU中的max-returnrecords字段表示了根据条件,AGENT端所返回的最大记录行数。如果该值设置成了n,则只会返回所有结果集中的前n条记录数据。如果max-return-records设置成了-1,那么AGENT就会返回所有的记录结果。
当AGENT在处理get-Alm-request和get-Pm-request请求报文的过程中,可能会出现各种异常情况,因此也需要对response报文作相应的修改。
下面给出它的定义。
PDU ::= SEQUENCE {
request-id INTEGER
error-status Integer{
noError(0),
tooBig(1),
nuSuchName(2),
badVaue(3),
readOnly(4),
⋯⋯
authorizationError(16),
notWritable(17),
numberOfLogicError(20),
maxReturnRecordsError(21),
myObjectNameWrong(22),
conditionWrong(23) },
error-index
Variable-bindings VarBindList
}
上述定义中,20-23是针对getAlm和getPm请求报文的响应。numberOfLogicError指的是逻辑条件数错误,由于目前设计的最大条件数为8,因此取值范围为1到8。maxReturnRecords应为最大返回的记录数,如取值异常,maxReturnRecordsError就会显示错误。myObjectNameWrong指的是由于myObjectName后的数值取值异常而引起的错误。正常情况下,myObjectName后的数值只能在0到5之间取整数值。最后的conditionWrong指的是在getAlm和getPm请求中使用了错误的过滤条件,所取数值超过了取值范围,将会返回conditionWrong状态的错误。
getAlm和getPm报文是用来提升现有SNMP管理性能的,在目前现有的SNMP管理端解决方案中,我们选用了SNMP4J, 在保持原有大框架不变的前提下,做简要的扩充,以支持这两种新报文,满足功能需求。
图2给出了相关类图的简要设计。主要思想是对SNMP4J中的PDU和VariableBinding类做了扩展,新增了WDMPDU类和WDMVariableBinding类,分别继承了SNMP4J框架中原有的PDU类和VariableBinding类。
在原有的PDU类中,包含了各种PDU数据包类型和各种异常情况状态等属性,根据新增的两种getPDU类型,在WDMPDU类中需增加相应的属性,即GetWDMAlm和GetWDMPm,同时也新增了4种异常情况状态属性。在PDU类中包含了一些方法,分别是addOID(),getVariable(),getBERPayloadLength(),decodeBER(),encodeBER(),getTypeString()等。其中addOID()给PDU报文增加mib号,getVariable()获取对应的mib节点数值。getBERPayloadLength()获取PDU报文的内容长度,是由requestID,errorstatus,errorIndex,还有variableBinding各字段长度值累加组成。其中errorstatus字段在response报文中表示报文错误状态码,在getAlm和getPm报文中表示的是逻辑操作符数目numberOfLogic;errorIndex字段在返回报文中表示错误索引值,在getAlm和getPm中表示的是返回记录数maxReturnRecords。另外requestID报文标识值长度计算方法也相同,variableBinding长度值是由VariableBinding类来计算。因此WDMPDU类中getBERPayloadLength()和原来的计算方式相同,再加上addOID()和getVariable(),不需要在子类中重写相关方法。PDU类中的encodeBER()和decodeBER()分别对即将进入网络传输的PDU数据包的输出流,和进入主机的PDU数据包的输入流进行编码和解码,也需要分别对上述requestID,errorStatus,errorIndex和variableBinding字段进行编码解码,还需要对报文的类型是否正确进行判断,这就需要在WDMPDU子类中对这两个方法进行重写,以支持新增加的GetAlm和GetPm报文。PDU类中的getTypeString()也需要重写,它根据PDU报文类型返回对应的报文描述,需要增加新增两种报文的支持。
在原有的VariableBinding类中,包含了oid和variable属性,分别表示mib节点标识和对应的值。WDMVariableBind类由于新增了比较运算符,因此新增了operator属性。VariableBinding类含有oid和variable的get和set方法,用来获取和设置对应的属性值。它们在子类WDMVariableBind类中同样存在,因此这里不需要被重写,直接继承父类中的方法即可。VariableBinding类中的decodeBER()和encodeBER()对进出网络的PDU数据包中的variable变量绑定域的输入输出流进行编码和解码,原先的方法中只是对oid和variable属性分别进行编码和解码,现在WDMVariableBind类新增了oparator属性,在编码和解码过程中需要增加对operator属性的编码解码操作,因此在WDMVariableBind类中重写了这两个方法。最后VariableBind类中的getBERPayloadLength()方法用于返回PDU报文中variable变量绑定域的内容长度,是由oid和variable这两个属性内容的长度值累加而成。现在新增了operator属性,同样需要在WDMVariableBind类中重写这一方法,需要将这三个属性内容的长度做累加。
WDMSNMPRequest类提供了常用的GET,GETNEXT,SET等标准SNMP相关操作,还增加了GETWDMAlm和GETWDMPm方法。该类继承了标准SNMP4J框架中的SnmpRequest类,SnmpRequest类提供了mib表示符oid号,SNMP版本号,PDU数据包类型,允许的超时时间,地址,团体字符串等属性信息,还包括了获取和设置oid相关数值的方法,创建snmp会话的方法等。例如getPDU()方法利用父类的createSnmpSession()方法创建snmp会话,然后进行监听。随后创建target对象,设置该对象的address,timeout,版本信息等属性。接着根据需要,创建PDU数据包对象或是新增的WDMPDU数据包对象,并设置PDU类型,增加VariableBinding对象或新增的WDMVariableBind对象到PDU数据包对象中,如果是GETWDMAlm和GETWDMPm操作,还需调用WDMPDU类中的setNumberOfLogic()和setMaxReturnRecords()对过滤条件数和最大返回记录数进行设置。最后等待AGENT端返回标准的SNMP的Response数据包,关闭snmp会话。WDMSNMPRequest在此基础上进行了扩展。
下面结合SNMP4J的框架,给出具体的实现的流程。
实现流程: 如图3所示,首先实例化一个SNMP对象,调用该对象的listen()方法监听消息。构造UserTarget对象设置对应属性。接着构造一个PDU或是WDMPDU对象,生成一个包含了MIB库中ID的OID对象,将此对象添加到PDU或是WDMPDU对象中去,且需设置该报文获取类型。上述过程完成后,就可以调用Snmp类中的send()函数来发送消息了。
消息被发送之后,便等待响应的到达,到达后返回一个ResponseEvent对象,该类提供了getResponse()方法,可以取到返回的PDU或WDMPDU对象。
示例代码:
Snmp snmp = createSnmpsession();
snmp.listen(); 然后创建并设置target对象的一些属性,如地址,超时,版本等,
CommunityTarget target = new CommunityTarget(); target.setAddress()。
接着创建wdmpdu对象:WDMPDU wdmpdu = new WDMPDU(); Variable var = new OctetString(value); 如整型则对应初始化相应的类型 new Integer32(value)。
再将wdmpdu对象赋予对应mib的oid值:wdmpdu.add(new WDMVariableBinding(new OID(oids), var) );
设置wdmpdu属性,如wdmpdu. setType(WDMPDU.GetWDMAlm)。
通过snmp.set(wdmpdu,target). getResponse; 就可得到对应的返回结果。最后关闭连接snmp.close()。
应用效果
经实际环境下的测试,发现通过增加过滤条件设置,扩充协议新成员的方案,能够提高性能表现。与标准的GET报文相比,在获取大量告警或性能信息的时候,采用getAlm或getPm,从request请求数,response响应数,发送和接收字节数以及延时各方面比较了GET与getAlm或是getPm的差异。
比较获取告警信息时的差异发现,需要获取告警级别是critical,且告警类型是设备告警的所有信息。在本实验中需要得到的是severity和alarmtype节点。构造过滤条件:(severity=“critical”) AND (alarmtype=“device”),而请求获取的字段则是告警时间和板卡类型。
比较获取性能参数信息时的差异,现在需要获取性能间隔参数是15分钟,且板卡类型是LWX2双通道任意速率通道转换板的所有信息。在本实验中需要得到的是pfminterval和cardtype节点。构造的过滤条件:(pfminterval=“15”) AND (cardtype=“LWX2”)。
通过以上实验发现,使用getAlm或getPm来获取告警和性能信息, 特别是在有大量数据需要获取的时候, 能够减少网络中传输的对象字节数,减少延时。
目前,上海财经大学网络中心通过与设备厂商合作,通过对设备进行固件的升级,大多数设备已经支持以上这种新的获取告警与性能数据的方式。网络管理系统获取管理数据非常高效。
(作者单位为上海财经大学教育技术中心)