Simple tables

Having considered the simplest style of module implementation, we now turn our attention to the next style - a simple table. The tabular nature of these is immediately apparent from the MIB definition file, but the qualifier simple deserves a word of explanation.
A simple table, in this context, has four characteristics:
  1. It is indexed by a single integer value;
  2. Such indices run from 1 to a determinable maximum;
  3. All indices within this range are valid;
  4. The data for a particular index can be retrieved directly
    (e.g. by indexing into an underlying data structure).
If any of the conditions are not met, then the table is not a pure simple one, and the techniques described here are not applicable. The next section of this guide will cover the more general case. (In fact, it may be possible to use the bulk of the techniques covered here, though special handling will be needed to cope with the invalid assumption or assumptions). Note that mib2c assumes that all tables are simple.

As with the scalar case, the variable routine needs to provide two basic functions - request validation and data retrieval.

Validation

This is provided by the shared utility routine header_simple_table As with the scalar header routine, this takes the same parameters as the main variable routine, with one addition - the maximum valid index. Mib2c generates a dummy token for this, which must be replaced by the appropriate value.
As with the header routine, it also returns an indication of whether the request was valid, as well as setting up the return parameters with the matching OID information, and defaults for var_len and write_method.
Note that in releases prior to 3.6, this job was performed by the routine checkmib. However, the return values of this were the reverse of those for generic_header and header_simple_table. A version of checkmib is still available for compatability purposes, but you are encouraged to use header_simple_table instead.

The basic code fragment (see ucd-snmp/disk.c) is therefore of the form:

	unsigned char *
	var_extensible_disk(vp, name, length, exact, var_len, write_method)
	{
	    if (header_simple_table(vp,name,length,exact,var_len,write_method,numdisks)
					== MATCH_FAILED)
		return(NULL);

	    [ etc, etc, etc ]

	}
Note that the maximum index value parameter does not have to be a permanently fixed constant. It specifies the maximum valid index at the time the request is processed, and a subsequent request may have a different maximum.
An example of this can be seen in mibII/sysORTable.c where the table is held purely internally to the agent code, including its size (and hence the maximum valid index). This maximum could also be retrieved via a system call, or via a kernel data variable.

Data Retrieval

As with the scalar case, the other required function is to retrieve the data requested. However, given the definition of a simple table this is simply a matter of using the single, integer index sub-identifier to index into an existing data structure. This index will always be the last index of the OID returned by header_simple_table, so can be obtained as name[*length-1].
A good example of this type of table can be seen in ucd-snmp/disk.c

With some modules, this underlying table may be relatively large, or only accessible via a slow or cumbersome interface. The implementation described so far may prove unacceptably slow, particularly when walking a MIB tree requires the table to be loaded afresh for each variable requested.

In these circumstances, a useful technique is to cache the table when it is first read in, and use that cache for subsequent requests. This can be done by having a separate routine to read in the table. This uses two static variables, one a structure or array for the data itself, and the other an additional timestamp to indicate when the table was last loaded. When a call is made to this routine to "read" the table, it can first check whether the cached table is "new enough". If so, it can return immediately, and the system will use the cached data.
Only if the cached version is sufficiently old that it's probably out of date, is it necessary to retrieve the current data, updating the cached version and the timestamp value.
This is particularly useful if the data itself is relatively static, such as a list of mounted filesystems. There is an example of this technique in the Host Resources implementation.

As with the scalar case, mib2c simply provides placeholder dummy return values. It's up to the programmer to fill in the details.

The next part concludes the examination of the detailed implementation by looking at more general tables.


Copyright 1999 - D.T.Shield. Not to be distributed without the explicit permission of the author.