2012-03-23 16 views
7

Escribí una aplicación AgentX (Linux, gcc, g ++) que funciona bien para enviar escaladores. Esto es lo que estoy haciendo ahora:Buscando un código de ejemplo para implementar una tabla SNMP usando AgentX

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 
} 

Las funciones como handle_foo1(...) llamada snmp_set_var_typed_value(...) para devolver los valores que se almacenan en una estructura global de C dentro de la aplicación.

Lo que trato de hacer ahora es modificar este código para que también admita una tabla SNMP. El contenido de la tabla se almacena/almacena en caché como un contenedor STL dentro de la aplicación. Esta es una tabla SNMP relativamente simple, con filas consecutivas, y todas las columnas se componen de tipos como Integer32, Gauge32, InetAddress y TruthValue. El problema es que no veo buenos ejemplos de código en el sitio web de net-snmp, solo un montón de páginas doxygen.

Mi pregunta:

Qué API debería estar mirando? ¿Son estas las llamadas correctas:

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

... o hay algo más simple que debería estar usando?

+0

¿Está escribiendo su agente desde cero o utilizando 'mib2c'? 'mib2c' puede generar todo el esqueleto para usted. Después de eso, convertirlo en un subagente es fácil. ¿Ya ha mirado "http://net-snmp.sourceforge.net/wiki/index.php/TUT:Writing_a_Subagent"? – j4x

Respuesta

15

Creo que el mayor dolor cuando se trata de net-snmp es todas aquellas páginas de Doxygen en los índices de Google, pero que proporcionan contenido útil cercano a cero. La lectura de los archivos .h probablemente ya sea obvia para la mayoría de los desarrolladores, y la verdad es que net-snmp proporciona muchas capas diferentes de API con muy poca documentación que encontré útil. Lo que necesitamos no son varias docenas de copias idénticas de sitios web que alojan Doxygen, sino algunos buenos ejemplos.

Al final, la herramienta mib2c es cómo obtuve suficiente código de ejemplo para que todo funcione. Creo que traté de ejecutar mib2c con cada archivo net-snmp .conf, y dediqué mucho tiempo a leer el código que generaba para comprenderlo mejor. Aquí están los que encontré me dieron los mejores consejos:

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

Los archivos .conf Estás aquí: /etc/snmp/mib2c.*

también Han sido útiles las siguientes páginas:

Por lo que entiendo, hay muchos ayudantes/capas disponibles en la API de red SNMP. Así que este ejemplo pseudocódigo puede no funcionar para todos, pero así es como yo personalmente tengo mis tablas para trabajar de uso de red SNMP v5.4:

variable necesaria la mayoría de las funciones (que sea global o un miembro de una struct?)

netsnmp_tdata *table = NULL; 

estructura para representar una fila de la tabla (debe coincidir con la definición MIB)

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

inicializar la tabla con 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 para procesar las solicitudes

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

Construcción/añadir filas a la tabla

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

Juntando todo

En mi caso, esa última función que crea las filas se activa periódicamente por algunos otros eventos en el sistema. Entonces, de vez en cuando, cuando hay nuevas estadísticas disponibles, la tabla se reconstruye, todas las filas antiguas se eliminan y las nuevas se insertan. No me molesté en tratar de modificar las filas existentes. En cambio, descubrí que era más fácil reconstruir la tabla desde cero.

Cuestiones relacionadas