1. 程式人生 > >net-snmp移植專案總結

net-snmp移植專案總結

1、       專案移植總結

1.1  交叉編譯的configure引數的配置

交叉編譯引數的設定,這個部分是最基本的,如果引數設定的有問題,snmpd執行起來就會有問題。

在x86環境下進行測試的時候,選用一個簡單的編譯引數,可以工作:

LDFLAGS="-L/home/zmj/work/LNOS/mc218/lib/x86"LIBS="-lsqlite3 -lmc218 -lpthread"CPPFLAGS="-I/home/zmj/work/LNOS/mc218/include" ./configure  --enable-shared --with-perl-modules--with-mib-modules="XXX-MIB mibII/system_mib"--prefix=/home/zmj/work/snmp

對編譯引數進行一下說明,

LDFLAGS:是要引用到的私有庫的路徑,

LIBS:是要引用的庫,

CPPFLAGS:要引用的標頭檔案的路徑

--with-mib-modules:要編譯進來的庫,net-snmp有一些自帶的庫,其中mibII/system_mib就是net-snmp自帶的庫,還可以加一些自定義的庫,如XXX_MIB

交叉編譯的時候,引數如下:

LDFLAGS="-L`pwd`/../mc218/lib/arm"LIBS="-lsqlite3 -lmc218 -lpthread" CPPFLAGS="-I`pwd`/../mc218/include" ./configure --build=i386-linux--host=arm-linux --disable-ipv6 --with-endianness=little --disable-manuals--disable-ucd-snmp-compatibility --disable-embedded-perl --without-perl-modules--disable-snmptrapd-subagent --disable-applications --disable-scripts--with-enterprise-oid=n --with-enterprise-sysoid=.1.3.6.1.4.1.x.x--enable-mini-agent --with-mib-modules="mibII/system_mib XXX-MIB"--with-sys-location="Beijing"--with-sys-contact="

[email protected]"-with-default-snmp-version="2"--with-logfile="/var/log/snmpd.log" --with-persistent-directory="/var/net-snmp"--sysconfdir="/etc/" --disable-mib-loading  --prefix=$PREFIX

為了在嵌入式環境當中編譯出來的檔案最小,對snmp進行了一定的簡化,沒有編譯help、snmptrapd等資訊,最小化snmpd,配置為小端模式,其中--with-enterprise-oid配置的是企業號是一個整數,--with-enterprise-sysoid配置的是企業系統ID,這樣在snmp管理軟體讀取的時候才能正確顯示相關資訊

1.2  編譯自定義的mib檔案

具體詳情可以參見《snmp學習筆記-自定義節點的實現.docx》文件

1.3  增加自定義的trap,inotify的使用

具體詳情可行參見《RD030-snmptrap設計文件.docx》文件

1.4  修改啟動daemon程序程式碼的位置

在net-snmp執行的過程中發現,snmpd啟動的過程當中,如果開啟除錯開關,使用命令snmpd –f –Le執行snmpd,那麼snmpd傳送trap是正常的,指定的伺服器可以接收到trap資訊。但是,如果直接開啟snmpd,使用命令snmpd,則snmpd在後臺執行,這個時候發現伺服器接收不到snmpd傳送trap資訊。

檢視程式碼發現,啟動daemon程序是在net-snmp-5.7.2/agent/snmpd.c檔案當中入口函式main中,並且開啟daemon程序的函式netsnmp_daemonize函式是在初始化mib(init_mib_modules)之後。應該是trap的某些工作在fork之前操作,但是子程序又沒有繼承過來。導致了trap的初始化工作做的不到位。

因此修改程式碼,把daemon的操作移到int_mib_modules之前去執行,這樣後面的程式碼子程序就會執行一遍了。

1.5  解決傳送冷啟動、熱啟動trap的問題

在net-snmp的程式碼當中,預設傳送coldstart告警,並且不論是冷啟動還是熱啟動,都發送coldstart告警,在net-snmp官網上檢視FAQ,發現這是一個一致存在的問題,官方沒有找到解決方案。

在這個專案中,我們結合電源管理部分的特徵,在啟動的時候動一下手腳,建立一個只讀檔案/proc/tsc,如果是冷重啟,那麼建立檔案的時候,寫入0;否則就寫入一個不等於0的數字。這樣,我們就可以在snmpd啟動的時候(net-snmp-5.7.2/agent/snmpd.c檔案main函式當中),增加一個判斷,讀取檔案/proc/tsc的值,如果是0,就傳送coldstart告警(send_easy_trap(0,0);)否則,傳送warmstart告警(send_easy_trap(1,0);)

1.6  sysName的問題

在net-snmp當中有三個節點sysName、sysLocation、sysContact,這三個節點比較特殊,在mib檔案當中可以發現這三個節點是可讀可寫的,可是在實際的應用當中發現,在snmpd啟動之後沒有/etc/snmp/snmpd.conf配置檔案的時候,sysName、sysLocation、sysContact三個節點都是可讀可寫的;如果已經存在了/etc/snmp/snmpd.conf配置檔案,這時候sysLocation、sysContact兩個節點是不可以寫的,sysName可以寫,但是修改的值並不對hostname造成影響,而是修改了配置檔案/var/net-snmp/snmpd.conf,增加了psysName欄位。

在官網的FAQ中解釋說,出於安全考慮,sysName、sysLocation、sysContact只有在配置檔案不存在的情況下才可以修改。

實際的情況跟官網有出入,就是sysName的特殊性,並且在網上也找到一些網友發出這樣的疑問,但是目前沒有得到解答。

追蹤程式碼可以發現,在檔案system_mib.c當中,這三個節點的更新是通過system_store函式實現,並且使用了三個特殊的變數sysLocationSet、sysContactSet、sysNameSet。就是這三個變數成為三個節點是否可寫的開關。
目前,還沒有找到為什麼sysName跟sysLocation和sysContact兩個節點表現不一樣,後期還需要修改。

1.7  未解決的問題

在移植net-snmp的過程當中,需要引用外部自己寫的庫,包含外部標頭檔案的時候發現使用相對路徑包含不成功,最終使用了絕對路徑進行引用,程式碼才編譯通過,這個問題至今還沒有找到原因。

2、       總結的經驗教訓

總體來說,net-snmp的移植只要掌握了技巧,移植的過程並不是特別難,因為net-snmp本來程式碼完整,還有編譯自定義mib的軟體mib2c,所以移植的過程當中注意以下幾點:

1、   首先是自定義mib檔案的形成,這個檔案很重要,如果後期反覆修改的話,每次都要編譯一遍,增加了很多工作量。編寫mib檔案的時候要規範,結構要清楚,否則,後期snmp伺服器就無法識別,而且也不好擴充套件,在snmp伺服器上畫面板圖等工作就不好執行。

2、   其次,根據需要設定configure引數,這個引數直接影響了移植出來的snmpd是否可以工作,需要反覆實驗。

3、   不要蠻目的相信mib2c軟體,在實際應用的過程當中,我就發現mib2c生成的程式碼有出錯的情況,例如生成的XXX_interface.c檔案裡面把配置只讀,還是可讀可寫的地方寫反了。當然,這樣的情況就發現一處,大部分的程式碼還是正確的。實際的應用當中,自己要稍微檢查一下生成的程式碼,看看是否有問題。

4、   在使用mib2c編譯自定義程式碼的時候,會生成一個配置檔案,當第二次編譯的時候就可以直接修改生成的配置檔案,而不用一步一步的選擇配置項了。例如使用mib2c –c mib2c.mfd.conf 命令的時候,就會在snmp\share\snmp\mibs\defaults資料夾下生成配置檔案table-XXX.m2d