SNMP自定義MIB中RowStatus的應用

應用場景:
在管理Agent設備的配置文件的時候,難免會遇到增刪查改的操作。一般的snmpget對應查,snmpset對應改,但是增刪就不是簡單的直接操作了,就需要用到今天的主角——RowStatus這個屬性。


小坑一個:RowStatus一定是和Table一起用的。

傳送門:官方文檔,喜歡閱讀官方文檔的朋友不容錯過,不過是全英文的。

環境:

系統:Ubuntu14.04LTS
snmp版本:net-snmp-5.7.3

step1.編寫MIB文件

在上一篇文章中,已經註釋解釋了教爲通用的部分,今天這個MIB加入了Table,稍有不同:

QQMIB DEFINITIONS ::= BEGIN 

IMPORTS 
    OBJECT-GROUP, MODULE-COMPLIANCE, NOTIFICATION-GROUP
        FROM SNMPv2-CONF
    enterprises, Integer32, Unsigned32, OBJECT-TYPE, MODULE-IDENTITY,NOTIFICATION-TYPE
        FROM SNMPv2-SMI
    DisplayString, RowStatus
        FROM SNMPv2-TC;

--.1.3.6.1.4.1.73691
QQMIB OBJECT IDENTIFIER ::= { enterprises 73691 }

--.1.3.6.1.4.1.73691.1
qosTableRoot OBJECT IDENTIFIER ::= { QQMIB 1 }

    --創建一個table,必須以xxxTable這樣的格式命名
    --注意MAX-ACCESS的設置
    --.1.3.6.1.4.1.73691.1.1
    qosTable OBJECT-TYPE
        SYNTAX SEQUENCE OF QosEntry 
        MAX-ACCESS read-create
        STATUS current
        DESCRIPTION
            "專用承載列表"
        ::= { qosTableRoot 1 }

    --創建Entry對象,理解爲Row,格式爲xxxEntry,注意和定義的Entry對象名區別開
    --注意INDEX一定要的
    --.1.3.6.1.4.1.73691.1.1.1
    qosEntry OBJECT-TYPE
        SYNTAX QosEntry 
        MAX-ACCESS read-create
        STATUS current
        DESCRIPTION
            ""
        INDEX { qosIndex }
        ::= { qosTable 1 }

    --定義Entry對象,格式爲xxxEntry,注意和創建Entry對象名區別開
    --這裏定義Index,RowStatus是必須的,其他的就按照需求自定義了
    QosEntry::= SEQUENCE {
            qosIndex Integer32,
            WANDevice Integer32,
            DLMaxRate Unsigned32,
            qosRowStatus RowStatus
            }

    --.1.3.6.1.4.1.73691.1.1.1.1
    qosIndex OBJECT-TYPE
        SYNTAX Integer32 
        MAX-ACCESS read-create
        STATUS current
        DESCRIPTION
            "index"
        ::= { qosEntry 1 }

    --.1.3.6.1.4.1.73691.1.1.1.2
    WANDevice OBJECT-TYPE
        SYNTAX Integer32 
        MAX-ACCESS read-create
        STATUS current
        DESCRIPTION
            "參數解釋:廣域網側設備。取值範圍:4 - 4 ,默認值:4"
        ::= { qosEntry 2 }

    --.1.3.6.1.4.1.73691.1.1.1.3
    DLMaxRate OBJECT-TYPE
        SYNTAX Unsigned32
        MAX-ACCESS read-create
        STATUS current
        DESCRIPTION
            "參數解釋:下行最大速率。取值範圍:0 - 262144,默認值:262144"
        ::= { qosEntry 3 }

    --注意SYNTAX類型
    --.1.3.6.1.4.1.73691.1.1.1.4
    qosRowStatus OBJECT-TYPE
        SYNTAX RowStatus
        MAX-ACCESS read-create
        STATUS current
        DESCRIPTION
            "rowStatus"
        ::= { qosEntry 4 }
END 

需要注意的地方已經在上面的MIB文件中註釋了,可別看漏了哦。畢竟漏一些東西,也可以正常生成c文件,最後運行時候命令效果不對,根本不知道哪裏出了問題。

step2.使用mib2c工具生成c文件

和上篇文章一樣,不多贅述。輸入指令,依據需求選擇:

zzj@sed:~/net-snmp/net-snmp-5.7.3/local$ env MIBS="+/home/zzj/.snmp/mibs/QQ-MIB.txt" mib2c qosTableRoot
writing to -
mib2c has multiple configuration files depending on the type of
code you need to write.  You must pick one depending on your need.

You requested mib2c to be run on the following part of the MIB tree:
  OID:                              qosTableRoot
  numeric translation:              .1.3.6.1.4.1.73691.1
  number of scalars within:         0
  number of tables within:          1
  number of notifications within:   0

First, do you want to generate code that is compatible with the
ucd-snmp 4.X line of code, or code for the newer Net-SNMP 5.X code
base (which provides a much greater choice of APIs to pick from):

  1) ucd-snmp style code
  2) Net-SNMP style code

Select your choice : 2

**********************************************************************
             GENERATING CODE FOR TABLES:
**********************************************************************

  The Net-SNMP agent API is extremely extensive and, in fact, lets
  each programmer write agent code according to the style that works
  best for them based on their experience and their preference.  We're
  going to ask you a serious of questions that will help mib2c
  generate code that best suits *your* needs, as the programmer that
  will be responsible for taking the code and further refining it.  If
  you don't like how the results look, you are always welcome to
  re-run mib2c and select a different set of options.

    There are essentially two tasks involved in processing requests
  for OIDs within a MIB table - firstly identifying the relevant row
  of the table for a given request, and then returning (or updating)
  the appropriate column value within that row.  Many MIB tables model
  the state of some external system (the kernel, a device, processes,
  etc), and the MIB implementation module (the code we're about to
  produce a template for) acts as an interface between this underlying
  system and the SNMP side.  Other tables hold data internally that is
  only available within the agent itself, or at least the master copy
  of the data is held within the agent.

    There are a number of different code templates that can be used to
  implement MIB tables, using various approaches to these two tasks.

  There are three basic approaches to identifying the relevant row:

    1) Pass the request through to the table-specific code, and
       identify the requested row there (for both GET and GETNEXT
       requests).  This is typically the most efficient way to get
       up-to-date information, but relies on suitable
       (programmer-provided) code within the MIB handler.
       Most importantly, you should be an expert to use this choice.

       This will produce code based on the table_dataset handler.

    2) Have table-specific code to provide information about which
       rows exist in the table (by iterating through them in turn),
       but utilise standard helper code to select the appropriate
       row for a given request.  This is particularly suitable for
       tables where the data is naturally stored in a "random" order
       (or differently to the MIB table index), or where rows are
       frequently added to or removed from the table.

         However searching for the requested row is not very efficient,
       and performance can be slow - particularly for large tables with
       many rows.

    3) Hold a locally cached copy of the contents of the table (or at
       least a cache of which rows are valid), and utilise standard
       helper code to select the appropriate row.  This is
       significantly faster than the iterator-based approach, but
       cached data is inevitably slightly "stale" with respect to the
       data from the underlying system being managed.  This approach,
       since it relies on caching of data, is also results in a larger
       memory footprint.  It is less appropriate for tables where rows
       are frequently added or removed externally to the agent (i.e.,
       not via SNMP requests).

       This approach can also be used where _all_ use of the table is
       via SNMP, and there is no external "underlying system".  In
       this case, the local cache is the canonical version of the
       table.

    4) Do not generate code for the tables.

Select the option that best fits your requirements: 2


  Having identified the appropriate row for a given request, there are
  three basic styles of code for returning (or updating) the requested
  column value from within this row:

    1) A single handler routine, which contains all the code needed to
       handle GET and SET requests for each of the column objects.

       The code typically looks like a single function with a large 'case'
       statement covering each of the columns.

       This will produce code based on the 'iterator' hepler.

    2) A set of individual routines, each of which is concerned
       with a particular aspect of processing the request.
       Each column object within the table has one routine for
       retrieving the current value, and another for setting a new one.

       This will produce code based on the 'iterate_access' hepler.

    3) A (different) set of individual routines, each of which is
       smaller and more tightly focused than the code generated by
       style 2.  The aim here is to reduce the amount of SNMP specific
       knowledge required to implement a module, and hide much of the
       SNMP terminology and processing within standard generated code
       (which can simply be used sight unseen).
         However this style of code can only be generated when mib2c
       is run on an individual MIB table.  To use this approach, you
       will need to re-invoke mib2c with the name of a single MIB table.

       This will produce code based on the 'mfd' hepler ('MIB for Dummies').

    4) Do not generate code for the tables.

   (In all cases, GETNEXT requests are automatically converted
    into the equivalent GET request, so the MIB specific code
    need only be concerned with GET and SET requests.).

Select the code style you wish to use: 1



     The same template code can be generated using
                 mib2c -c mib2c.iterate.conf qosTableRoot
This framework can work in one of two ways:

  1)  Hold a local cached copy of some external data
      which is then used to service incoming requests.

  2)  Query the external data directly for each request.

The first is typically more efficient, but results in
slightly "stale" data (depending on the expiration timeout
for the cache) and greater memory usage.  The second can
provide more up-to-date information, but at the cost of
higher processing overheads.

Which is more appropriate for your needs?
Select your choice : 1

writing to qosTableRoot.h
writing to qosTableRoot.c


**********************************************************************
* NOTE WELL: The code generated by mib2c is only a template.  *YOU*  *
* must fill in the code before it'll work most of the time.  In many *
* cases, spots that MUST be edited within the files are marked with  *
* /* XXX */ or /* TODO */ comments.                                  *
**********************************************************************
running indent on qosTableRoot.h
running indent on qosTableRoot.c

我的選項如上,供大夥在“感覺不太對”時,找回自信。生成的c代碼如下,我在代碼中做好了註釋:

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

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

/** Initializes the qosTableRoot module */
void
init_qosTableRoot(void)
{
  /* here we initialize all the tables we're planning on supporting */
    initialize_table_qosTable();
}
  /*XXX 註釋掉*/
  # Determine the first/last column names

/** Initialize the qosTable table by defining its contents and how it's structured */
void
initialize_table_qosTable(void)
{
    const oid qosTable_oid[] = {1,3,6,1,4,1,73691,1,1};
    const size_t qosTable_oid_len   = OID_LENGTH(qosTable_oid);
    netsnmp_handler_registration    *reg;
    netsnmp_iterator_info           *iinfo;
    netsnmp_table_registration_info *table_info;

    DEBUGMSGTL(("qosTableRoot:init", "initializing table qosTable\n"));

    reg = netsnmp_create_handler_registration(
              "qosTable",     qosTable_handler,
              qosTable_oid, qosTable_oid_len,
              HANDLER_CAN_RWRITE
              );

    table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info );
    netsnmp_table_helper_add_indexes(table_info,
                           ASN_INTEGER,  /* index: qosIndex */
                           0);
    table_info->min_column = COLUMN_QOSINDEX;
    table_info->max_column = COLUMN_QOSROWSTATUS;

    iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info );
    iinfo->get_first_data_point = qosTable_get_first_data_point;
    iinfo->get_next_data_point  = qosTable_get_next_data_point;
    iinfo->table_reginfo        = table_info;

    netsnmp_register_table_iterator( reg, iinfo );
    netsnmp_inject_handler_before( reg, 
        netsnmp_get_cache_handler(QOSTABLE_TIMEOUT,
                                  qosTable_load, qosTable_free,
                                  qosTable_oid, qosTable_oid_len),
            TABLE_ITERATOR_NAME);

    /* Initialise the contents of the table here */
    /* XXX 便於測試,你可以在這裏初始化幾行數據*/
}

    /* Typical data structure for a row entry */
struct qosTable_entry {
    /* Index values */
    long qosIndex;

    /* Column values */
    long qosIndex;
    long old_qosIndex;
    long WANDevice;
    long old_WANDevice;
    u_long DLMaxRate;
    u_long old_DLMaxRate;
    long qosRowStatus;

    /* Illustrate using a simple linked list */
    int   valid;
    struct qosTable_entry *next;
};

struct qosTable_entry  *qosTable_head;

/* create a new row in the (unsorted) table */
struct qosTable_entry *
qosTable_createEntry(
                 long  qosIndex,
        /*XXX 把參數補齊 */
                ) {
    struct qosTable_entry *entry;

    entry = SNMP_MALLOC_TYPEDEF(struct qosTable_entry);
    if (!entry)
        return NULL;

    entry->qosIndex = qosIndex;
    /*XXX 賦值 */
    entry->next = qosTable_head;
    qosTable_head = entry;
    return entry;
}

/* XXX 這裏和下面調用參數匹配不上,修改使其一致即可*/
/* remove a row from the table */
void
qosTable_removeEntry( struct qosTable_entry *entry ) {
    struct qosTable_entry *ptr, *prev;

    if (!entry)
        return;    /* Nothing to remove */

    for ( ptr  = qosTable_head, prev = NULL;
          ptr != NULL;
          prev = ptr, ptr = ptr->next ) {
        if ( ptr == entry )
            break;
    }
    if ( !ptr )
        return;    /* Can't find it */

    if ( prev == NULL )
        qosTable_head = ptr->next;
    else
        prev->next = ptr->next;

    SNMP_FREE( entry );   /* XXX - release any other internal resources */
}

/* Example cache handling - set up linked list from a suitable file */
int
qosTable_load( netsnmp_cache *cache, void *vmagic ) {
    FILE *fp;
    struct qosTable_entry *this;
    char buf[STRMAX];

    /* The basic load routine template assumes that the data to
       be reported is held in a file - with one row of the file
       for each row of the table.
          If your data is available via a different API, you
       should amend this initial block (and the control of the
       'while' loop) accordingly.
          'XXX' marks where the template is incomplete and
       code will definitely need to be added. */

    //初始化操作,在這裏讀取文件,加載到table中
    fp = fopen( "/data/for/qosTable", "r" );
    if ( !fp ) {
        return -1;
    }
    while ( fgets( buf, STRMAX, fp )) {
        this = SNMP_MALLOC_TYPEDEF( struct qosTable_entry );
        /* XXX - Unpick 'buf' to extract the individual field values
                 and then populate the 'this' data structure with them */

        this->next = qosTable_head;
        qosTable_head = this;    /* Iterate helper is fine with unordered lists! */
    }
    fclose(fp);
    return 0;  /* OK */
}

void
qosTable_free( netsnmp_cache *cache, void *vmagic ) {
    struct qosTable_entry *this, *that;

    for ( this = qosTable_head; this; this=that ) {
        that = this->next;
        SNMP_FREE( this );   /* XXX - release any other internal resources */
    }
    qosTable_head = NULL;
}

/* Example iterator hook routines - using 'get_next' to do most of the work */
netsnmp_variable_list *
qosTable_get_first_data_point(void **my_loop_context,
                          void **my_data_context,
                          netsnmp_variable_list *put_index_data,
                          netsnmp_iterator_info *mydata)
{
    *my_loop_context = qosTable_head;
    return qosTable_get_next_data_point(my_loop_context, my_data_context,
                                    put_index_data,  mydata );
}

netsnmp_variable_list *
qosTable_get_next_data_point(void **my_loop_context,
                          void **my_data_context,
                          netsnmp_variable_list *put_index_data,
                          netsnmp_iterator_info *mydata)
{
    struct qosTable_entry *entry = (struct qosTable_entry *)*my_loop_context;
    netsnmp_variable_list *idx = put_index_data;

    if ( entry ) {
        snmp_set_var_typed_integer( idx, ASN_INTEGER, entry->qosIndex );
        idx = idx->next_variable;
        *my_data_context = (void *)entry;
        *my_loop_context = (void *)entry->next;
        return put_index_data;
    } else {
        return NULL;
    }
}

//table_row和ret沒有定義,自己定義一下吧
/** handles requests for the qosTable table */
int
qosTable_handler(
    netsnmp_mib_handler               *handler,
    netsnmp_handler_registration      *reginfo,
    netsnmp_agent_request_info        *reqinfo,
    netsnmp_request_info              *requests) {

    netsnmp_request_info       *request;
    netsnmp_table_request_info *table_info;
    struct qosTable_entry          *table_entry;

    DEBUGMSGTL(("qosTableRoot:handler", "Processing request (%d)\n", reqinfo->mode));

    switch (reqinfo->mode) {
        /*
         * Read-support (also covers GetNext requests)
         */
    case MODE_GET:
        for (request=requests; request; request=request->next) {
            table_entry = (struct qosTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);

            switch (table_info->colnum) {
            case COLUMN_QOSINDEX:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->qosIndex);
                break;
            case COLUMN_WANDEVICE:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->WANDevice);
                break;
            case COLUMN_DLMAXRATE:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_UNSIGNED,
                                            table_entry->DLMaxRate);
                break;
            case COLUMN_QOSROWSTATUS:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
                                            table_entry->qosRowStatus);
                break;
            default:
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_NOSUCHOBJECT);
                break;
            }
        }
        break;

        /*
         * Write-support
         */
    case MODE_SET_RESERVE1:
        for (request=requests; request; request=request->next) {
            table_entry = (struct qosTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);

            switch (table_info->colnum) {
            case COLUMN_QOSINDEX:
                /* or possibly 'netsnmp_check_vb_int_range' */
                ret = netsnmp_check_vb_int( request->requestvb );
                if ( ret != SNMP_ERR_NOERROR ) {
                    netsnmp_set_request_error( reqinfo, request, ret );
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_WANDEVICE:
                /* or possibly 'netsnmp_check_vb_int_range' */
                ret = netsnmp_check_vb_int( request->requestvb );
                if ( ret != SNMP_ERR_NOERROR ) {
                    netsnmp_set_request_error( reqinfo, request, ret );
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_DLMAXRATE:
                /* or possibly 'netsnmp_check_vb_int_range' */
                ret = netsnmp_check_vb_int( request->requestvb );
                if ( ret != SNMP_ERR_NOERROR ) {
                    netsnmp_set_request_error( reqinfo, request, ret );
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_QOSROWSTATUS:
                ret = netsnmp_check_vb_rowstatus(request->requestvb,
                         (table_entry ? RS_ACTIVE : RS_NONEXISTENT ));
                if ( ret != SNMP_ERR_NOERROR ) {
                    netsnmp_set_request_error( reqinfo, request, ret );
                    return SNMP_ERR_NOERROR;
                }
                break;
            default:
                netsnmp_set_request_error( reqinfo, request,
                                           SNMP_ERR_NOTWRITABLE );
                return SNMP_ERR_NOERROR;
            }
        }
        break;

    case MODE_SET_RESERVE2:
        for (request=requests; request; request=request->next) {
            table_entry = (struct qosTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);

            switch (table_info->colnum) {
            case COLUMN_QOSROWSTATUS:
                switch (*request->requestvb->val.integer) {
        //按規範,一般是在RESERVE2這裏做內存申請等操作,因此在這裏創建了新的table_row
                case RS_CREATEANDGO:
                case RS_CREATEANDWAIT:
                    table_row = qosTable_createEntry(
                        , *table_info->indexes->val.integer
                        );
                    if (table_row) {
                        netsnmp_insert_iterator_context( request, table_row );
                    } else {
                        netsnmp_set_request_error( reqinfo, request,
                                                   SNMP_ERR_RESOURCEUNAVAILABLE );
                        return SNMP_ERR_NOERROR;
                    }
                }
            }
        }
        break;

    case MODE_SET_FREE:
        for (request=requests; request; request=request->next) {
            table_entry = (struct qosTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);

            switch (table_info->colnum) {
            case COLUMN_QOSROWSTATUS:
                switch (*request->requestvb->val.integer) {
        //valid屬性是0,表示移除該行,這裏怪怪的?可能因爲是和SET_FREE有關吧
                case RS_CREATEANDGO:
                case RS_CREATEANDWAIT:
                    if (table_entry && !table_entry->valid) {
                        qosTable_removeEntry(table_data, table_row );
                    }
                }
            }
        }
        break;

    case MODE_SET_ACTION:
        for (request=requests; request; request=request->next) {
            table_entry = (struct qosTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);

            switch (table_info->colnum) {
            case COLUMN_QOSINDEX:
                table_entry->old_qosIndex = table_entry->qosIndex;
                table_entry->qosIndex     = *request->requestvb->val.integer;
                break;
            case COLUMN_WANDEVICE:
                table_entry->old_WANDevice = table_entry->WANDevice;
                table_entry->WANDevice     = *request->requestvb->val.integer;
                break;
            case COLUMN_DLMAXRATE:
                table_entry->old_DLMaxRate = table_entry->DLMaxRate;
                table_entry->DLMaxRate     = *request->requestvb->val.integer;
                break;
            }
        }
        /* Check the internal consistency of an active row */
        for (request=requests; request; request=request->next) {
            table_entry = (struct qosTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);

            switch (table_info->colnum) {
            case COLUMN_QOSROWSTATUS:
                switch (*request->requestvb->val.integer) {
                case RS_ACTIVE:
                case RS_CREATEANDGO:
            /* XXX 這兩種狀態對應使 指定的Row生效*/
                    if (/* XXX 異常判斷*/) {
                        netsnmp_set_request_error( reqinfo, request,
                                                   SNMP_ERR_INCONSISTENTVALUE );
                        return SNMP_ERR_NOERROR;
                    }
                }
            }
        }
        break;

    case MODE_SET_UNDO:
        for (request=requests; request; request=request->next) {
            table_entry = (struct qosTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);

            switch (table_info->colnum) {
            case COLUMN_QOSINDEX:
                table_entry->qosIndex     = table_entry->old_qosIndex;
                table_entry->old_qosIndex = 0;
                break;
            case COLUMN_WANDEVICE:
                table_entry->WANDevice     = table_entry->old_WANDevice;
                table_entry->old_WANDevice = 0;
                break;
            case COLUMN_DLMAXRATE:
                table_entry->DLMaxRate     = table_entry->old_DLMaxRate;
                table_entry->old_DLMaxRate = 0;
                break;
            case COLUMN_QOSROWSTATUS:
                switch (*request->requestvb->val.integer) {
                case RS_CREATEANDGO:
                case RS_CREATEANDWAIT:
                    if (table_entry && !table_entry->valid) {
                        qosTable_removeEntry(table_data, table_row );
                    }
                }
                break;
            }
        }
        break;

    case MODE_SET_COMMIT:
        for (request=requests; request; request=request->next) {
            table_entry = (struct qosTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);

            switch (table_info->colnum) {
            case COLUMN_QOSROWSTATUS:
                switch (*request->requestvb->val.integer) {
        //這裏mib2c生成的已幫我們處理好,CREATEANDGO,valid直接是1,同時還把qosRowStatus設置爲ACTIVE
                case RS_CREATEANDGO:
                    table_entry->valid = 1;
                    /* Fall-through */
                case RS_ACTIVE:
                    table_entry->qosRowStatus = RS_ACTIVE;
                    break;

        //創建但是不ACTIVE
                case RS_CREATEANDWAIT:
                    table_entry->valid = 1;
                    /* Fall-through */
                case RS_NOTINSERVICE:
                    table_entry->qosRowStatus = RS_NOTINSERVICE;
                    break;

                case RS_DESTROY:
                    qosTable_removeEntry(table_data, table_row );
                }
            }
        }
        break;
    }
    return SNMP_ERR_NOERROR;
}

對於RowStatus的幾種狀態的解釋:
-active(1):表明狀態行是可用的
-notInService(2):表明行存在但不可用
-notReady (3):表明存在,但因爲缺少必要的信息而不能用
-createAndGo (4):由管理者設置,表明希望創建一個行並設置該行的狀態列對象爲active
-createAndWait(5):由管理者設置,表明希望創建一個行,但不可用,從上面的代碼看到,是被設置爲了notInService
-destroy(6):刪除行

step3.編譯、加載動態庫

step4.調試

先snmpwalk看看情況:

zzj@sed:~/net-snmp/net-snmp-5.7.3/local$ snmpwalk -v2c -c sedwt localhost  .1.3.6.1.4.1
SNMPv2-SMI::enterprises.73691.1.1.1.1.1 = INTEGER: 1
SNMPv2-SMI::enterprises.73691.1.1.1.1.2 = INTEGER: 2
SNMPv2-SMI::enterprises.73691.1.1.1.2.1 = INTEGER: 4
SNMPv2-SMI::enterprises.73691.1.1.1.2.2 = INTEGER: 4
SNMPv2-SMI::enterprises.73691.1.1.1.3.1 = Gauge32: 276432
SNMPv2-SMI::enterprises.73691.1.1.1.3.2 = Gauge32: 276433
SNMPv2-SMI::enterprises.73691.1.1.1.4.1 = INTEGER: 0
SNMPv2-SMI::enterprises.73691.1.1.1.4.2 = INTEGER: 0

看來比較正常(本文在初始化中添加了2行數據),下面我們來添加一行數據:添加一行index爲5的數據:

zzj@sed:~/net-snmp/net-snmp-5.7.3/local$ snmpset -v2c -c sedwt localhost  .1.3.6.1.4.1.73691.1.1.1.4.5 i 5
SNMPv2-SMI::enterprises.73691.1.1.1.4.5 = INTEGER: 5
zzj@sed:~/net-snmp/net-snmp-5.7.3/local$ snmpwalk -v2c -c sedwt localhost  .1.3.6.1.4.1
SNMPv2-SMI::enterprises.73691.1.1.1.1.1 = INTEGER: 1
SNMPv2-SMI::enterprises.73691.1.1.1.1.2 = INTEGER: 2
SNMPv2-SMI::enterprises.73691.1.1.1.1.5 = INTEGER: 5
SNMPv2-SMI::enterprises.73691.1.1.1.2.1 = INTEGER: 4
SNMPv2-SMI::enterprises.73691.1.1.1.2.2 = INTEGER: 4
SNMPv2-SMI::enterprises.73691.1.1.1.2.5 = INTEGER: 0
SNMPv2-SMI::enterprises.73691.1.1.1.3.1 = Gauge32: 276432
SNMPv2-SMI::enterprises.73691.1.1.1.3.2 = Gauge32: 276433
SNMPv2-SMI::enterprises.73691.1.1.1.3.5 = Gauge32: 0
SNMPv2-SMI::enterprises.73691.1.1.1.4.1 = INTEGER: 0
SNMPv2-SMI::enterprises.73691.1.1.1.4.2 = INTEGER: 0
SNMPv2-SMI::enterprises.73691.1.1.1.4.5 = INTEGER: 2

看到已經添加了一行數據,剩下分別set各屬性值,最後設置RowStatus爲active(1)就好了。
刪除和修改都比較簡單,就不貼過程了。

全文完

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章