文/陶晉
?
SNMP協議家族的新成員
文/陶晉
在當前國內高校的網絡管理中, SNMP一直是被普遍接受的通用網絡管理協議標準和工業標準。但是隨著各高校網絡設備數量越來越多和復雜,需管理監控的數據日益增多,使SNMP網絡管理協議更高效地工作,成為了保障高校網絡安全運維的重要條件。上海財經大學網絡中心對此問題做了專門研究,設計出兩種新的SNMP服務,并利用現有的SNMP4J開源庫,在其總體框架上進行擴展,有效地提高了網絡設備的管理效率。
上海財經大學現有網絡設備1000多臺,需管理的設備型號復雜多樣, 尤其是核心層設備上的管理數據量非常大,使用傳統的SNMP管理協議來監控和管理效率比較低。對于學校的網絡管理系統來說,如設備告警和性能等許多業務數據,是通過管理信息庫MIB表來獲取的。由于SNMP標準報文GET,GETNEXT報文的限制,如要獲取相關的業務數據信息,必須將整個MIB表中告警和性能節點的數據全部獲取下來,然后再進行過濾篩選。當整個MIB表非常龐大時,這種做法耗時較長且會消耗較多的帶寬。

圖1
針對以上問題,我們在上海財經大學網絡管理系統中設計了新的解決方案,提出兩種新的SNMP服務,getAlm和getPm。
首先在新SNMP服務中需對過濾條件進行設置,封裝在SNMP的GET報文中,有選擇的獲取MIB對象值。新服務沿襲了SNMP協議內容簡單的特點,只需對PDU報文的get-request進行擴充(get-Alm-request和get-Pm-request),response報文結構維持不變,但需要在返回的PDU數據包中,增加對新服務的異常狀態處理。
對于get-Alm-request,默認設置的過濾選項:cardtype板卡類型,severity嚴重級別,alarmtype告警類型,alarmtime告警產生時間。而對于get-Pm-request,默認選項包括:pfmtime性能產生時間 ,pfminterval性能監控間隔(包含15分鐘或24小時), cardtype板卡類型,pfmparameters性能監控參數。上述這些選項可在SNMP管理端進行設置,SNMP的Agent端支持按上述選項過濾輸出結果。
對SNMP協議數據單元做如下新的定義:

從上表可以看出,在使用ASN.1描述SNMP的Protocol Data Unit(協議數據單元簡稱PDU)定義中,在choice可供選擇的類型中新增了“20”和“21”兩種新類型。
對于這兩種新PDU的定義,在下面的ASN.1中給出了具體描述。

上述PDU設計了最多八個邏輯表達式的條件,現在假設這個過濾條件數為n,這n個條件將出現在VarBindList變量表中。對于varbindlist的變量名和值,這里的變量名指的是上述cardtype, severity等過濾選項所對應的目標Object Identifiers(簡稱OID)值。而變量值羅列出了這些目標對象可能的取值范圍。在邏輯條件表達式中,需要邏輯運算符來把變量名和值聯系起來。因此設計了在目標對象名中用固定的整數值來表示相應的邏輯運算符:0表示“=”,1表示“<”, 2表示“>”, 3表示“<=”,4表示“>=”, 5表示“!=”。
這樣varbindlist變量表中的名和值鍵值就可以聯系起來了。下面給出varbindlist的定義。


(出現在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報文作相應的修改。
下面給出它的定義。


上述定義中,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類。

圖2
在原有的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()函數來發送消息了。

圖3
消息被發送之后,便等待響應的到達,到達后返回一個ResponseEvent對象,該類提供了getResponse()方法,可以取到返回的PDU或WDMPDU對象。
示例代碼:

接著創建wdmpdu對象:

如整型則對應初始化相應的類型 new Integer32(value)。
再將wdmpdu對象賦予對應mib的oid值:wdmpdu.add(new WDMVariableBinding(new OID(oids), var));
設置w d m p d u屬性,如w d m p d u . 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來獲取告警和性能信息, 特別是在有大量數據需要獲取的時候, 能夠減少網絡中傳輸的對象字節數,減少延時。
目前,上海財經大學網絡中心通過與設備廠商合作,通過對設備進行固件的升級,大多數設備已經支持以上這種新的獲取告警與性能數據的方式。網絡管理系統獲取管理數據非常高效。
(作者單位為上海財經大學教育技術中心)