Wednesday, November 26, 2008

Extending Net-SNMP 5.4.2.1 Agent

This article describes how to extend Net-SNMP agent toolkit to instrument the EtherLike-MIB (RFC 3635) with hardcoded defaults. This article will describe the setup on windows (I used XP SP3) and Linux (I used openSUSE 11.0) required to develop this agent.

The following instructions were carried out for net-snmp source version 5.4.2.1. This article assumes the following default paths:

  1. Net-SNMP un-archived on windows in C:\net-snmp and ~/net-snmp on Linux.
  2. Net-SNMP installed in C:\usr on Windows and /usr/local on Linux.

1.1. Setup the development environment

  1. Download and install MSVC++ Express 2005 from http://www.microsoft.com/express/2005/download/default.aspx. There is some compilation issue of the net-snmp code with MSVC++ 2008 (Orcas) and i did not bother to fix it but used the 2005 instead.
  2. Download and setup platform sdk as described in http://www.microsoft.com/express/2005/platformsdk/default.aspx. Be sure to setup the development environment using the PSDK as described in the link step-wise.
  3. Download net-snmp source from http://www.net-snmp.org/download.html. The net-snmp version 5.4.2.1 can be downloaded from there.

1.2. Build and install net-snmp from source on windows

  1. Un-archive the net-snmp source to say c:\net-snmp.
  2. Follow the README.win32 to build the net-snmp code (Read the section Microsoft Visual C++ - Workspace – Building).
    1. We need to first load the winsdk.dsw in the MSVC++ 2005 express. Below is the screenshot of all projects that make up the win32sdk workspace in MSVC++.

clip_image002

Figure 1 - Projects in win32sdk.dsw

    1. Modify the win32\netsnmp\netsnmpconfig.h file to add:
               #define HAVE_WIN32_PLATFORM_SDK 1






    1. Build in order, the following project for (Release | Debug) configuration.





i. libagent



ii. libhelpers



iii. libnetsnmptrapd



iv. libsnmp



v. netsnmpmibsdk






    1. Go to Build > Batch Build… and select the (Debug | Release) configuration of all projects except for the ones you built in step c above.





  1. If everything is okay with setup, then build should go fine too.




  2. Using cmd line on windows, go to c:\net-snmp and run the command: win32\install_netsnmp.bat to install net-snmp you built above to location c:\usr.




  3. Set the c:\usr\bin to PATH environment variable for easy access to the command line snmp client and agent executables.




1.3. Build and install net-snmp from source on Linux





  1. Un-archive the net-snmp source to say ~/net-snmp.




  2. Follow the INSTALL to build the net-snmp code. Run the following commands on shell prompt:




    1. cd ~/net-snmp




    2. ./configure




    3. make




    4. make install (run as root)






The make install step will install the net-snmp binaries by default in /usr/local path.



1.4. Configuring the snmpd agent (snmpd.conf)





  1. Configure snmp agent by running snmpconf command (see man page) or copy the C:/net-snmp/Example.conf and modify.




    1. snmpconf –g basic_setup






  2. I used the following configuration. Copy-paste the text below into a file named snmpd.conf. The agent is configured for snmp v2c and with rwcommunity string of public.







com2sec local     localhost       public


 


group MyRWGroup    v1         local


group MyRWGroup    v2c        local


group MyRWGroup    usm        local


 


 


view all    included  .1                               80


 


 


#                context sec.model sec.level match  read   write  notif


access MyROGroup ""      any       noauth    exact  all    none   none


access MyRWGroup ""      any       noauth    exact  all    all    none


 


 


syslocation Right here, right now.


syscontact Me <me@somewhere.org>







  1. Save the file in path :




    1. C:\usr\etc\snmp\snmpd.conf (on Windows)




    2. /etc/snmp/snmpd.conf (on Linux)






1.5. Load the MIB module and generate the C code





  1. The EtherLike-MIB has 5 tables (columnar variables).




  2. For mib2c code generation I used linux host. Run the following commands on shell prompt:







mkdir ethmib_src


cd ethmib_src 


export MIBS=ALL 





EtherLike-MIB was part of the net-snmp distribution so all we need is to tell mib2c to use it by setting the environment variable MIBS.






mib2c –c mib2c.create-dataset.conf dot3StatsTable 





This will generate dot3StatsTable.c and dot3StatsTable.h files.



Similarly run the similar command for the other tables in the mib.






mib2c –c mib2c.create-dataset.conf dot3PauseTable 


mib2c –c mib2c.create-dataset.conf dot3HCStatsTable 


mib2c –c mib2c.create-dataset.conf dot3CollTable 


mib2c –c mib2c.create-dataset.conf dot3ControlTable 





Use the ethmib_src and use it for windows agent extension too.



1.6. Use the generated source files to instrument the mib on Windows





  • On Windows, the above generated source files can be copied to c:\net-snmp\agent\mibgroups. You may also create a folder names EtherLike-MIB and sub-folders for each table like dot3StatsTable etc, and keep the respective table *.c and *.h files in the folder with the table name.




  • Add the generated sources in the MSVC++ netsnmpmibssdk project as shown below:




clip_image004



Figure 2 - EtherLike-MIB files added to the netsnmpmibssdk project.





  • Add the dot3StatsTable.h and dot3StatsTable.c files to your 'netsnmpmibssdk' project in VC++.




  • Next edit the '<sourcedir>\win32\mib_module_includes.h' file to add an include to your .h file.







#include "mibgroup/EtherLike-MIB/dot3StatsTable/dot3StatsTable.h"


#include "mibgroup/EtherLike-MIB/dot3HCStatsTable/dot3HCStatsTable.h"


#include "mibgroup/EtherLike-MIB/dot3CollTable/dot3CollTable.h"


#include "mibgroup/EtherLike-MIB/dot3ControlTable/dot3ControlTable.h"


#include "mibgroup/EtherLike-MIB/dot3PauseTable/dot3PauseTable.h"





 





  • Next edit the '<sourcedir>\win32\mib_module_inits.h' file to add code to call your initialize function.







if (should_init("dot3StatsTable")) init_dot3StatsTable();


if (should_init("dot3HCStatsTable")) init_dot3HCStatsTable();


if (should_init("dot3CollTable")) init_dot3CollTable();


if (should_init("dot3ControlTable")) init_dot3ControlTable();


if (should_init("dot3PauseTable")) init_dot3PauseTable();





 



1.7. Instrument the EtherLike-MIB



This section only instruments the dot3StatsTable generated source to return some default data. Other table instrumentation can be done in the similar manner.





  1. Edit the dot3StatsTable.c file as shown below to return some hardcoded data. The changes to the generated code have been highlighted.







/*


 * Note: this file originally auto-generated by mib2c using


 *        : mib2c.create-dataset.conf 9375 2004-02-02 19:06:54Z rstory $


 */


 


#include <net-snmp/net-snmp-config.h>


#include <net-snmp/net-snmp-includes.h>


#include <net-snmp/agent/net-snmp-agent-includes.h>


#include "dot3StatsTable.h"


 


/** Initialize the dot3StatsTable table by defining its contents and how it's structured */


void


initialize_table_dot3StatsTable(void)


{


    static oid dot3StatsTable_oid[] = {1,3,6,1,2,1,10,7,2};


    size_t dot3StatsTable_oid_len = OID_LENGTH(dot3StatsTable_oid);


    netsnmp_table_data_set *table_set;


    


    // variables declared – wrajnees


    netsnmp_table_row *row;


    static int _max_cols = 21; // there are 18 columns in this table.


    int column = 0;


    int index = 1;


    int val = 20;


    static oid      objid_etherchipset[] = { 0 };     /* ethernetChipset vendor oid */


 


    // end variables declared.


 


    /* create the table structure itself */


    table_set = netsnmp_create_table_data_set("dot3StatsTable");


 


    /* comment this out or delete if you don't support creation of new rows */


    


    table_set->allow_creation = 1;


 


    /***************************************************


     * Adding indexes


     */


    DEBUGMSGTL(("initialize_table_dot3StatsTable",


                "adding indexes to table dot3StatsTable\n"));


 


    netsnmp_table_set_add_indexes(table_set,


                           ASN_INTEGER,  /* index: dot3StatsIndex */


                           0);


 


    


    DEBUGMSGTL(("initialize_table_dot3StatsTable",


                "adding column types to table dot3StatsTable\n"));         


    netsnmp_table_set_multi_add_default_row(table_set,


                                            /*COLUMN_DOT3STATSINDEX, ASN_INTEGER, 0,


                                            NULL, 0,*/


                                            COLUMN_DOT3STATSALIGNMENTERRORS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSFCSERRORS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSSINGLECOLLISIONFRAMES, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSMULTIPLECOLLISIONFRAMES, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSSQETESTERRORS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSDEFERREDTRANSMISSIONS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSLATECOLLISIONS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSEXCESSIVECOLLISIONS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSINTERNALMACTRANSMITERRORS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSCARRIERSENSEERRORS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSFRAMETOOLONGS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSINTERNALMACRECEIVEERRORS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSETHERCHIPSET, ASN_OBJECT_ID, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSSYMBOLERRORS, ASN_COUNTER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSDUPLEXSTATUS, ASN_INTEGER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSRATECONTROLABILITY, ASN_INTEGER, 0,


                                            NULL, 0,


                                            COLUMN_DOT3STATSRATECONTROLSTATUS, ASN_INTEGER, 0,


                                            NULL, 0,


                              0);


 


 


    


    /* registering the table with the master agent */


    /* note: if you don't need a subhandler to deal with any aspects


       of the request, change dot3StatsTable_handler to "NULL" */


    netsnmp_register_table_data_set(netsnmp_create_handler_registration("dot3StatsTable", NULL,


                                                        dot3StatsTable_oid,


                                                        dot3StatsTable_oid_len,


                                                        HANDLER_CAN_RONLY),


                            table_set, NULL);


    // Add code - wrajnees


 


    /*


     * create the a row for the table, and add the data 


     */


    row = netsnmp_create_table_data_row();


    /*


     * set the index to the IETF WG name "snmpv3" 


     */


    netsnmp_table_row_add_index(row, ASN_INTEGER, (u_char*)&index, sizeof(index));


    /*


     * set the column 2 and above


     */


    for (column = 2; column <= _max_cols; column++) {


        // Following columns are not valid.


        switch(column) {


            case 12: // INVALIDs


            case 14:


            case 15:


                break;


            case 17: // OID


                netsnmp_set_row_column(row, column, ASN_OBJECT_ID,


                               (u_char*)objid_etherchipset, 1*sizeof(oid));


                break;


            case 19: // INTEGER


            case 21:


                netsnmp_set_row_column(row, column, ASN_INTEGER,


                               (u_char*)&val, sizeof(val));    


                break;


            case 20: // TRUTH_VALUE


                netsnmp_set_row_column(row, column, ASN_INTEGER,


                               (u_char*)&val, sizeof(val));    


                break;


            default: // COUNTER


                netsnmp_set_row_column(row, column, ASN_COUNTER,


                               (u_char*)&val, sizeof(val));    


                break;


        }


 


 


    }


    /*


     * add the row to the table 


     */


    netsnmp_table_dataset_add_row(table_set, row);


 


    /*


     * Finally, this actually allows the "add_row" token it the


     * * snmpd.conf file to add rows to this table.


     * * Example snmpd.conf line:


     * *   add_row netSnmpIETFWGTable eos "Glenn Waters" "Dale Francisco"


     */


    netsnmp_register_auto_data_table(table_set, NULL);


 


    // End add code - wrajnees


}


 


/** Initializes the dot3StatsTable module */


void


init_dot3StatsTable(void)


{


 


  /* here we initialize all the tables we're planning on supporting */


    initialize_table_dot3StatsTable();


}







  1. Now rebuild the netsnmpmibssdk project and then snmpdsdk project, in order.




  2. Run the following command to re-install the modified agent with the dot3StatsTable changes.







cd c:\net-snmp 


win32\install_netsnmp.bat 







  1. Start the new agent as follows:







cd c:\usr\bin 


snmpd.exe –f –Lo –V 







  1. Open a MIB Browser to walk the dot3StatsTable instrumentation:




clip_image006



1.8. Instrumentation on Linux





  1. Copy the generated source to the path ~/net-snmp/agent/mibgroups and run the following commands:







./configure –with-mib-modules=”dot3StatsTable dot3PauseTable dot3HCStatsTable dot3CollTable dot3ControlTable” 


make 


make install (run as root)







  1. Start the snmpd as:







/usr/local/sbin/snmpd –f –Lo –V 







  1. Run a command line snmpwalk to test it.







$ snmpwalk -v 2c -mAll -c public localhost dot3StatsTable 


 


EtherLike-MIB::dot3StatsAlignmentErrors.1 = Counter32: 20 


EtherLike-MIB::dot3StatsFCSErrors.1 = Counter32: 20 


EtherLike-MIB::dot3StatsSingleCollisionFrames.1 = Counter32: 20 


EtherLike-MIB::dot3StatsMultipleCollisionFrames.1 = Counter32: 20 


EtherLike-MIB::dot3StatsSQETestErrors.1 = Counter32: 20 


EtherLike-MIB::dot3StatsDeferredTransmissions.1 = Counter32: 20 


EtherLike-MIB::dot3StatsLateCollisions.1 = Counter32: 20 


EtherLike-MIB::dot3StatsExcessiveCollisions.1 = Counter32: 20 


EtherLike-MIB::dot3StatsInternalMacTransmitErrors.1 = Counter32: 20 


EtherLike-MIB::dot3StatsCarrierSenseErrors.1 = Counter32: 20





2. Co-existance with MS Windows SNMP Agent



We have 2 approaches to getting the net-snmp agent to co-exist with the Microsoft provided SNMP agent:





  • As of Net-SNMP 5.4, the Net-SNMP agent is able to load the Windows SNMP service extension DLLs by using the Net-SNMP winExtDLL extension. In this scenario, MS SNMP agent is installed but disabled. This is required because winExtDLL extension and existing windows extensions use Windows SNMP API from snmpapi.dll. The limitations of this approach are:





    • linkUp/Down generic traps are not received for some unknown reason.




    • sysUpTime.0 does not report the correct uptime for the agent. This is because the Windows extension checks for the uptime of the SNMP service, which is not running when Net-SNMP is running.





  • Alternatively, Net-SNMP agent can run as a proxy SNMP agent and will proxy for the MS SNMP agent (running at a non-default port) for those MIBs that MS SNMP agent instruments. For all other MIBs, Net-SNMP agent can service the SNMP requests. This approach does not suffer from the winExtDLL approach’s limitation, but then we need to run two snmp agents (net-snmp and MS snmp agents).




This sums up in short, the development setup required to get started with extending the net-snmp agent.

1 comment:

Anonymous said...

There is so much information about using net-snmp out there... but no one connected the dots together like this! Regarding SNMP, the basic stuff is pretty easy, and obvious... but to make it any useful, there is such a big learning curve associated to defining custom MIBs and customizing the SNMP agents. Again, thanks for putting it all together!!

Popular micro services patterns

Here are some popular Microservice design patterns that a programmer should know: Service Registry  pattern provides a  central location  fo...