2012-03-23 101 views
7

我已经编写了一个AgentX应用程序(Linux,gcc,g ++),它可以很好地发送回缩放器。这是我现在在做什么:查找使用AgentX实现SNMP表的示例代码

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 
} 

的功能,如呼叫handle_foo1(...)snmp_set_var_typed_value(...)返回其在应用程序中的全局C结构缓存值。

我现在要做的是修改此代码以支持SNMP表。表格的内容作为应用程序中的STL容器存储/缓存。这是一个相对简单的SNMP表,它具有连续的行,并且所有列都由类似Integer32,Gauge32,InetAddress和TruthValue组成。问题是我在net-snmp网站上看不到很好的代码示例,只是很多doxygen页面。

我的问题:

我应该看什么API?这些是正确的电话:

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

...或者是否有更简单的我应该使用?

+0

您是从头开始编写代理还是使用'mib2c'? 'mib2c'可以为你生成整个骨架。之后,将其转换为子代理很容易。你有没有看过“http://net-snmp.sourceforge.net/wiki/index.php/TUT:Writing_a_Subagent”? – j4x 2012-04-03 16:24:35

回答

15

我认为net-snmp最大的问题就是所有那些Doxygen的Google索引页面,但它提供了几乎为零的可用内容。读取.h文件对于大多数开发人员来说可能已经很明显了,事实是net-snmp提供了许多不同的API层,而且我发现很少有文档对我有用。我们需要的不是几十个相同的托管Doxygen网站的副本,而是一些很好的例子。

最后,mib2c工具是我如何获得足够的示例代码来完成整个工作。我想我试过每一个net-snmp .conf文件都运行mib2c,并且花了很多时间阅读它生成的代码以获得更好的理解。下面是我发现的那些给了我最好的提示:

  • 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; 

结构来表示表中的一行(必须的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); 

Handler来进程请求

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); 
} 

将其组合在一起

在我的情况下,构建行的最后一个函数是由系统中的其他事件定期触发的。所以每隔一段时间当新的统计数据可用时,表格会被重建,所有旧的行被删除,并且新的数据被插入。我没有试图修改现有的行。相反,我发现从头开始重建表更容易。