MFD:ifTable:Data Structures
MFD Tutorial | |
|
Contents
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.