MFD:ifTable:Data Structures

From Net-SNMP Wiki
Jump to: navigation, search

MFD Data Structures

There are a few basic data structures that the MFD template code uses extensively.


Registration Pointer

The first structure is the registration pointer. This pointer is supplied by the implementor in the module's initialization routine. It is never used by the MFD code, but is passed as a parameter to virtually every generated function. It is for the convenience of the implementor. By default it will be a netsnmp_data_list pointer.


Data Context

The next structure is the data context. This structure should contain all the data for a particular row. By default, mib2c will generate this data structure, and it will contain storage for each column in the table. Running mib2c on the ifTable table results in this data context structure:

   /*
    * data context
    */
   /*
    * This structure contains storage for all the columns defined in the
    * ifTable.
    */
   typedef struct ifTable_data_s {

       /*
        * ifDescr(2)/DisplayString/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/H
        */
       char            ifDescr[255];
       size_t          ifDescr_len;    /* # of char elements, not bytes */

       /*
        * ifType(3)/IANAifType/ASN_INTEGER/long(u_long)//l/A/w/E/r/d/h
        */
       u_long          ifType;

       /*
        * ifMtu(4)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h
        */
       long            ifMtu;

       /*
        * ifSpeed(5)/GAUGE/ASN_GAUGE/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifSpeed;

       /*
        * ifPhysAddress(6)/PhysAddress/ASN_OCTET_STR/char(char)//L/A/w/e/r/d/H
        */
       char            ifPhysAddress[65535];
       size_t          ifPhysAddress_len;      /* # of char elements, not bytes */

       /*
        * ifAdminStatus(7)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h
        */
       u_long          ifAdminStatus;

       /*
        * ifOperStatus(8)/INTEGER/ASN_INTEGER/long(u_long)//l/A/w/E/r/d/h
        */
       u_long          ifOperStatus;

       /*
        * ifLastChange(9)/TICKS/ASN_TIMETICKS/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifLastChange;

       /*
        * ifInOctets(10)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifInOctets;

       /*
        * ifInUcastPkts(11)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifInUcastPkts;

       /*
        * ifInNUcastPkts(12)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifInNUcastPkts;

       /*
        * ifInDiscards(13)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifInDiscards;

       /*
        * ifInErrors(14)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifInErrors;

       /*
        * ifInUnknownProtos(15)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifInUnknownProtos;

       /*
        * ifOutOctets(16)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifOutOctets;

       /*
        * ifOutUcastPkts(17)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifOutUcastPkts;

       /*
        * ifOutNUcastPkts(18)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifOutNUcastPkts;

       /*
        * ifOutDiscards(19)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifOutDiscards;

       /*
        * ifOutErrors(20)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifOutErrors;

       /*
        * ifOutQLen(21)/GAUGE/ASN_GAUGE/u_long(u_long)//l/A/w/e/r/d/h
        */
       u_long          ifOutQLen;

       /*
        * ifSpecific(22)/OBJECTID/ASN_OBJECT_ID/oid(oid)//L/A/w/e/r/d/h
        */
       oid             ifSpecific[128];
       size_t          ifSpecific_len; /* # of oid elements, not bytes */

   } ifTable_data;

If you have an existing data structure that contains all the data for your table, you can use that instead (we'll cover that in a later tutorial).


MIB Index

When a MIB table is defined, it has an INDEX clause that defines how the data in the table is ordered when queried. mib2c generates a MIB index structure with sufficent storage to represent the index for a table row. Running mib2c on the ifTable table results in this MIB index structure:

   /*
    * This structure is used to represent the index for a table.
    */
   typedef struct ifTable_mib_index_s {

       /*
        * ifIndex(1)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/w/e/R/d/H
        */
       long            ifIndex;


   } ifTable_mib_index;

Row Request Context

The next structure is the row context. This structure is used during the processing of a SNMP request. It is contains all the previous structures, and a few additional items. Running mib2c on the ifTable table results in this row request context structure:

   /*
    *********************************************************************
    * Row request context
    * When your functions are called, you will be passed a
    * ifTable_rowreq_ctx pointer.
    */
   typedef struct ifTable_rowreq_ctx_s {

   /** this must be first for container compare to work */
       netsnmp_index   oid_idx;
       oid             oid_tmp[MAX_OID_LEN];   /* xxx-rks: shrink this */

       ifTable_mib_index tbl_idx;

       ifTable_data    data;
       ifTable_undo_data *undo;
       unsigned int    set_flags;

   /** implementor's context pointer provided during registration */
       ifTable_registration_ptr ifTable_reg;

       /*
        * TODO:
        * add any other useful data
        *       (e.g. flags for when a column has been set)
        */

       /*
        * storage for future expansion
        */
       netsnmp_data_list *ifTable_data_list;

   } ifTable_rowreq_ctx;

The registration pointer (ifTable_reg in this example), mib index (tbl_idx) and data context (data) were discussed above. The oid varaibles oid_idx and oid_tmp are used internally, and will likely go away in the future. The data_list is a generic way of dynamically storing one or more pointers, using a string as the storage and retrieval key. It is not currently used internally, but may be in the future. For the implementor, it is a convienent way of storing additional data for a row request, without having to modify the row request structure itself.