8

スケーラーを送り返すのに適した AgentX アプリ (Linux、gcc、g++) を作成しました。これが私が今していることです:

init_agent( "blah" );
netsnmp_register_read_only_scalar( netsnmp_create_handler_registration( "foo1", handle_foo1, oid, oid.size(), HANDLER_CAN_RONLY ) );
init_snmp( "blah" );
while ( true )
{
    // internal stuff
    agent_check_and_process(1); // where 1==block
}

などの関数は、アプリケーション内のグローバル C 構造体にキャッシュされた値を返すhandle_foo1(...)呼び出しを行います。snmp_set_var_typed_value(...)

私が今やろうとしているのは、SNMP テーブルもサポートするようにこのコードを変更することです。テーブルのコンテンツは、アプリケーション内で STL コンテナーとして保存/キャッシュされます。これは比較的単純な SNMP テーブルで、行が連続しており、すべての列が Integer32、Gauge32、InetAddress、TruthValue などのタイプで構成されています。問題は、net-snmp の Web サイトに優れたコード例が見当たらないことです。doxygen のページがたくさんあるだけです。

私の質問:

どの API を調べる必要がありますか? これらは正しい呼び出しですか:

netsnmp_register_read_only_table_data();
netsnmp_create_table_data();
netsnmp_create_table_data_row();
netsnmp_table_data_add_row();

...または、私が使用すべきより簡単なものはありますか?

4

1 に答える 1

18

net-snmp に関する最大の問題は、Google がインデックスに登録しているにもかかわらず、使用可能なコンテンツがほとんどない Doxygen ページがすべてあることだと思います。ファイルを読むこと.hは、ほとんどの開発者にとっておそらくすでに明らかであり、実際のところ、net-snmp は多くの異なる API レイヤーを提供し、私が役立つと思ったドキュメントはほとんどありません。私たちが必要としているのは、Doxygen をホストしている Web サイトの数十の同一のコピーではなく、いくつかの良い例です。

最後に、mib2c ツールは、すべてを機能させるのに十分なサンプル コードを取得する方法です。私は、すべての net-snmp ファイルで mib2c を実行してみて.conf、生成されたコードをよりよく理解するために多くの時間を費やしたと思います。これが私が見つけたもので、最高のヒントを与えてくれました:

  • mib2c -c mib2c.create-dataset.conf MyMib
  • mib2c -c mib2c.table_data.conf MyMib

ファイルは次の.confとおりです。 /etc/snmp/mib2c.*

次のページも役に立ちました。

私が理解していることから、net-snmp API には多くのヘルパー/レイヤーが用意されています。したがって、この疑似コードの例は誰にとってもうまくいくとは限りませんが、net-snmp v5.4 を使用して個人的にテーブルを動作させる方法を以下に示します。

複数の関数で必要な変数 (グローバルにするか、構造体のメンバーにするか?)

netsnmp_tdata *table = NULL;

テーブルの 1 行を表す構造 (MIB 定義と一致する必要があります)

struct MyTable_entry
{
    long myTableIndex;
    ...insert one line here for each column of the table...
    int valid; // add this one to the end
}

snmpd でテーブルを初期化する

std::string name( "name_of_the_table_from_mib" );
table = netsnmp_tdata_create_table( name.c_str(), 0 );
netsnmp_table_registration_info *table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info );
netsnmp_table_helper_add_indexes( table_info, ASN_INTEGER, 0 ); // index: myTableIndex
// specify the number of columns in the table (exclude the index which was already added)
table_info->min_column = COLUMN_BLAH;
table_info->max_column = MAX_COLUMN_INDEX;
netsnmp_handler_registration *reg = netsnmp_create_handler_registration( name.c_str(), MyTable_handler, oid, oid.size(), HANDLER_CAN_RONLY );
netsnmp_tdata_register( reg, table, table_info );

リクエストを処理するハンドラ

int myTable_handler( netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests )
{
    if ( reqInfo->mode != MODE_GET ) return SNMP_ERR_NOERROR;
    for ( netsnmp_request_info *request = requests; request; request = request->next )
    {
        MyTable_entry *table_entry  = (MyTable_entry*)netsnmp_tdata_extract_entry( request );
        netsnmp_table_request_info *table_info = netsnmp_extract_table_info( request );

        if ( table_entry == NULL ) { netsnmp_set_request_error( reqinfo, request, SNMP_NOSUCHINSTANCE); continue; }

        switch ( table_info->colnum )
        {
            // ...this is similar to non-table situations, eg:
            case COLUMN_BLAH:
                snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER, table_entry->blah ); break;
            // ...
            default: netsnmp_set_request_error( reqinfo, request, SNMP_NOSUCHOBJECT );
        }
    }
    return SNMP_ERR_NOERROR;
}

テーブルへの行の作成/追加

if ( table == NULL ) return;   // remember our "global" variable named "table"?

// start by deleting all of the existing rows
while ( netsnmp_tdata_row_count(table) > 0 )
{
    netsnmp_tdata_row *row = netsnmp_tdata_row_first( table );
    netsnmp_tdata_remove_and_delete_row( table, row );
}

for ( ...loop through all the data you want to add as rows into the table... )
{
    MyTable_entry *entry = SNMP_MALLOC_TYPEDEF( MyTable_entry );
    if ( entry == NULL ) ... return;
    netsnmp_tdata_row *row = netsnmp_tdata_create_row();
    if ( row == NULL ) SNMP_FREE( entry ); .... return;

    entry->myTableIndex = 123; // the row index number
    // populate the table the way you need
    entry->blah = 456;
    // ...

    // add the data into the row, then add the row to the table
    entry->valid = 1;
    row->data = entry;
    netsnmp_tdata_row_add_index( row, ASN_INTEGER, &(entry->myTableIndex), sizeof(entry->myTableIndex) );
    netsnmp_tdata_add_row( table, row );
}

それを一緒に入れて

私の場合、行を構築する最後の関数は、システム内の他のイベントによって定期的にトリガーされます。そのため、新しい統計が利用可能になると、テーブルが再構築され、古い行がすべて削除され、新しい行が挿入されます。既存の行を変更しようとはしませんでした。代わりに、テーブルを最初から再構築する方が簡単であることがわかりました。

于 2012-04-06T02:44:53.437 に答える