AgentX

2012-03-23 24 views
7

का उपयोग कर एक एसएनएमपी तालिका को लागू करने के लिए उदाहरण कोड की तलाश में मैंने एक एजेंट एप (लिनक्स, जीसीसी, जी ++) लिखा है जो स्केलर्स को वापस भेजने में अच्छी तरह से काम करता है।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 
} 

कार्यों handle_foo1(...) कॉल snmp_set_var_typed_value(...) की तरह मान जो आवेदन के भीतर एक वैश्विक सी struct में कैश कर रहे हैं वापस जाने के लिए: यहाँ अब मैं क्या कर रहा है।

जो मैं अभी करने की कोशिश कर रहा हूं वह इस कोड को एसएनएमपी तालिका का समर्थन करने के लिए संशोधित कर रहा है। तालिका की सामग्री को एप्लिकेशन के भीतर एक एसटीएल कंटेनर के रूप में संग्रहीत/कैश किया जाता है। यह लगातार पंक्तियों के साथ अपेक्षाकृत सरल एसएनएमपी तालिका है, और सभी कॉलम इंटेगर 32, गेज 32, इनेट एड्रेस और ट्रुथवेल्यू जैसे प्रकारों से बना है। समस्या यह है कि मुझे net-snmp वेबसाइट पर बहुत अच्छे कोड उदाहरण नहीं दिखते हैं, बस बहुत सारे डॉक्सजिन पेज।

मेरा प्रश्न:

क्या एपीआई मैं पर विचार करना चाहिए? क्या ये सही कॉल हैं:

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

उत्तर

15

मुझे लगता है कि जब नेट-स्नैम्प की बात आती है तो सबसे बड़ा दर्द उन सभी डॉक्सिजन पेजों को Google अनुक्रमणिका करता है लेकिन जो शून्य-शून्य उपयोग योग्य सामग्री प्रदान करता है। .h फ़ाइलों को पढ़ना शायद अधिकांश डेवलपर्स के लिए पहले से ही स्पष्ट है, और सच्चाई यह है कि नेट-स्नैम्प बहुत उपयोगी दस्तावेज के साथ एपीआई की कई अलग-अलग परतें प्रदान करता है जो मुझे उपयोगी लगता है। हमें जो चाहिए वह डॉक्सिजन की मेजबानी करने वाली वेबसाइटों की कई दर्जन समान प्रतियां नहीं है, बल्कि इसके कुछ अच्छे उदाहरण हैं।

अंत में, mib2c उपकरण यह है कि पूरी चीज़ को काम करने के लिए मुझे पर्याप्त उदाहरण कोड कैसे मिला। मुझे लगता है कि मैंने प्रत्येक एकल नेट-स्नैम्प .conf फ़ाइल के साथ mib2c चलाने की कोशिश की, और बेहतर समझने के लिए उत्पन्न कोड को पढ़ने में काफी समय लगा। यहाँ लोगों को मैंने पाया मुझे सबसे अच्छा संकेत दे दिया जाता है:

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

.conf फ़ाइलें यहां हैं: /etc/snmp/mib2c.*

इसके अलावा उपयोगी थे अगले पन्नों:

से मैं क्या समझ, वहाँ कई सहायकों/परतों नेट SNMP एपीआई में उपलब्ध हैं। तो इस उदाहरण स्यूडोकोड सभी के लिए काम नहीं है, लेकिन यह कैसे मैं व्यक्तिगत रूप से नेट SNMP v5.4 का उपयोग कर काम करने के लिए मेरी टेबल मिल गया है:

चर कई कार्य (यह वैश्विक बनाने के लिए, या एक के एक सदस्य भर की जरूरत struct?)

netsnmp_tdata *table = NULL; 

संरचना तालिका में से एक पंक्ति का प्रतिनिधित्व करने के (एमआईबी परिभाषा से मेल खाना चाहिए)

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

यह एक साथ लाना

मेरे मामले में, पंक्तियों का निर्माण करने वाला अंतिम कार्य सिस्टम में कुछ अन्य घटनाओं द्वारा समय-समय पर ट्रिगर किया जाता है। तो प्रत्येक बार एक बार जब नए आंकड़े उपलब्ध होते हैं, तो तालिका का पुनर्निर्माण किया जाता है, सभी पुरानी पंक्तियां हटा दी जाती हैं, और नए डाले जाते हैं। मैंने मौजूदा पंक्तियों को संशोधित करने की कोशिश करने से परेशान नहीं किया। इसके बजाए, मैंने पाया कि तालिका को केवल खरोंच से पुनर्निर्माण करना आसान था।