RE: Query regarding ASYNC GET calls

"Rahul Ravikanth Anneboina" <[email protected]>
Newsgroups gmane.network.net-snmp.user
Message-ID <CCEE49B9CE065146BA4FE34B2748A53210E6FCF3@CEL-BANGT-M01.celstream-in.com>
I have stumbled on another problem.

I have created 4 threads, each thread will send out 256 requests for 4 different subnets. The responses are read in the same thread.

I get the following error: “lock in _callback_lock sleeps more than 100 milliseconds in snmp_call_callbacks  netsnmp_assert lock_holded < 100 failed ..\..\snmplib\callback.c:140”

 

Please let me know what this error implies and is there a way to overcome this.

Is there a limit on async operations i.e can I create 50 threads and send out 256 requests, querying 4 parameters in each request. Should I be aware of some limitation before doing so?

 

Your help is much appreciated. Thanks.

 

Here is the code:

*************************************************************************************************************************************

#include <windows.h>

#include <winsock.h>

#define _WINSOCKAPI_

#include <net-snmp/net-snmp-config.h>

#include <net-snmp/net-snmp-includes.h>

#include <net-snmp/library/large_fd_set.h>

#include <net-snmp/session_api.h>

#include <stdio.h>

#include <string.h>

#include <time.h>

 

#define COMMUNITY       "public"

#define SUBNET_STR            "10.255."

#define SUBNET_COUNT    256

#define MAX_OID_COUNT   4

 

oid OIDs[MAX_OID_COUNT][MAX_OID_LEN]      =     {

      {1,3,6,1,2,1,25,3,5,1,1,1},   /* Device Status */

      {1,3,6,1,2,1,25,3,2,1,3,1},   /* Device Description */

      {1,3,6,1,2,1,43,5,1,1,17,1},/* Device Serial # */

      {1,3,6,1,2,1,1,2,0}           /* sysObjectID */

};

unsigned char ucOIDLen[MAX_OID_COUNT] = {12,12,12,9};

                  

typedef struct range

{

      int lo;

      int hi;

      int subnet;

} STRUCT_Range;

 

void initialize (void)

{

      SOCK_STARTUP;

      init_snmp("asyncappdisc");

      printf("Initialize success ... \n\n");

}

 

void deinitialize (void)

{

      SOCK_CLEANUP;

      printf("DeInitialize success ... \n\n");

}

 

int print_result (int status, netsnmp_session *sp, netsnmp_pdu *pdu)

{

      char buf[1024];

      unsigned char result = 0;

      netsnmp_variable_list *vp = NULL;

      int ix;

 

      vp = pdu->variables;

 

      switch (status) 

      {

            case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:

                  if (pdu->errstat == SNMP_ERR_NOERROR) 

                  {

                        printf("Got response from '%s' with SNMP version '%ld'.... \n", sp->peername, pdu->version);

                  

                        while (vp) 

                        {

                              snprint_variable(buf, sizeof(buf), vp->name, vp->name_length, vp);

                              fprintf(stdout, "%s: %s\n", sp->peername, buf);

                              vp = vp->next_variable;

                        }

                  }

                  else 

                  {

                        for (ix = 1; vp && ix != pdu->errindex; vp = vp->next_variable, ix++);

                        

                        if (vp) 

                              snprint_objid(buf, sizeof(buf), vp->name, vp->name_length);

                        else 

                              strcpy(buf, "(none)");

                              

                        fprintf(stdout, "%s: %s: %s\n",     sp->peername, buf, snmp_errstring(pdu->errstat));

                  }

                  result = 1;

            break;

                  

            case NETSNMP_CALLBACK_OP_TIMED_OUT:

                  printf("\n");

                  fprintf(stdout, "No response from device @ '%s' operation timed out.\n", sp->peername);

            break;

                  

            case NETSNMP_CALLBACK_OP_SEND_FAILED:

                  printf("\n");

                  fprintf(stdout, "Send failed for device @ '%s'.\n", sp->peername);

            break;

                  

            case NETSNMP_CALLBACK_OP_CONNECT:

                  printf("\n");

                  fprintf(stdout, "Device @ '%s' is connected.\n", sp->peername);

            break;

                  

            case NETSNMP_CALLBACK_OP_DISCONNECT:

                  printf("\n");

                  fprintf(stdout, "Device @ '%s' is disconnected.\n", sp->peername);

            break;

      }

      

      if (vp)

            snmp_free_varbind(vp);

      

      return result;

}

 

int asynch_response(int operation, netsnmp_session *sp, int reqid, netsnmp_pdu *pdu, void *magic)

{

      netsnmp_session *host = (netsnmp_session *)magic;

 

      printf("Processing ... %s, Op: %d, ", host->peername, operation);

      print_result(operation, sp, pdu);

      printf("\n");

 

      return 1;

}

 

int init_snmp_sess(char * ip, void ** session)

{

      int i;

      netsnmp_session *sessp = NULL;

      void * nss = NULL;

      netsnmp_pdu *req = NULL;

      netsnmp_session sess;

 

      snmp_sess_init(&sess);

 

      sess.version = SNMP_VERSION_2c;

      sess.peername = (char *)strdup(ip);

      sess.community = (char *)strdup(COMMUNITY);

      sess.community_len = strlen(COMMUNITY);

 

      nss = snmp_sess_open(&sess);

      if (nss)

            sessp = snmp_sess_session(nss);

 

      if (!sessp)

      {

            printf("%s - snmp_open error.\n", ip);

            return 0;

      }

 

      *session = nss;

      req = snmp_pdu_create(SNMP_MSG_GET);

 

      if (req)

      {

            for (i = 0; i < MAX_OID_COUNT; i++)

                  snmp_add_null_var(req, OIDs[i], ucOIDLen[i]);

 

            if (!snmp_sess_async_send(nss, req, asynch_response, sessp))

            {

                  int liberr, syserr;

                  char *errstr;

 

                  snmp_sess_error(nss, &liberr, &syserr, &errstr);

                  printf("%s - snmp_sess_async_send error. Error '%s'.\n", ip, errstr);

                  snmp_free_pdu(req);

                  free(errstr);

                  return 0;

            }

      }

      else

      {

            printf("%s - snmp_pdu_create error.\n", ip);

            return 0;

      }

 

      return 1;

}

 

void AsyncReqsRespThread(void *p)

{

      STRUCT_Range * r = (STRUCT_Range *)p;

      int i = 0;

      netsnmp_large_fd_set fdset;

      short int count = 0;

      void * hs[SUBNET_COUNT] = {0};

      char cIp[20];

      struct tm *tm;

      time_t rawtime;

 

      printf("\nStarted Request-Response '%d' ....\n\n", GetCurrentThreadId());

 

      while (1)

      {

            if (r && !count)

            {

                  if (r->hi > 0)

                  {

                        time ( &rawtime );

                        tm = localtime ( &rawtime );

 

                        printf("Start '%d' %s", GetCurrentThreadId(), asctime(tm));

 

                        for (i = r->lo; i < r->hi; i++)

                        {

                              memset(cIp, 0, 20);

                              snprintf(cIp, 20, "%s%d.%d", SUBNET_STR, r->subnet, i);

 

                              if (init_snmp_sess(cIp, &hs[i]))

                                    count++;

                        }

 

                        printf("Completed sending %d requests. Waiting for responses .... \n\n", count);

                  }

 

                  if (count)

                  {

                        netsnmp_large_fd_set_init(&fdset, r->hi-r->lo);

 

                        for (i = r->lo; i < r->hi; i++)

                        {

                              int fds = -1, block = 1, result = -1;

                              struct timeval timeout;

 

                              if (hs[i])

                              {

                                    result = snmp_sess_select_info(hs[i], &fds, fdset.lfs_setptr, &timeout, &block);

                                    fds = select(fds, fdset.lfs_setptr, NULL, NULL, block ? NULL : &timeout);

 

                                    if (fds > 0)

                                          snmp_sess_read(hs[i], fdset.lfs_setptr);

                                    else

                                          snmp_sess_timeout(hs[i]);

 

                                    if (count > 0)

                                          count--;

 

                                    Sleep(0);

                              }

                        }

 

                        /*netsnmp_large_fd_set_cleanup(&fdset);

 

                        Sleep(1);

 

                        for (i = r->lo; i < r->hi; i++)

                        {

                              if (hs[i])

                              {

                                    snmp_sess_close(hs[i]);

                                    hs[i] = NULL;

                              }

                        }

 

                        r->hi = 0;

 

                        time ( &rawtime );

                        tm = localtime ( &rawtime );

                        printf("End '%d' %s", GetCurrentThreadId(), asctime(tm));*/

                  }

                  else

                        r->hi = 0;

            }

 

            printf("Remaining hosts '%d' ...'%d\n", count, GetCurrentThreadId());

            Sleep(1000);

      }

 

      printf("\nEnded Request-Response '%d' ....\n\n", GetCurrentThreadId());

      _endthread();

}

 

int main (int argc, char **argv)

{

      STRUCT_Range r, p, q, s;

 

      initialize();

 

      r.lo = 0;

      r.hi = 256;

      r.subnet = 110;

      _beginthread(AsyncReqsRespThread, 0, &r);

 

      p.lo = 0;

      p.hi = 256;

      p.subnet = 109;

      _beginthread(AsyncReqsRespThread, 0, &p);

 

      q.lo = 0;

      q.hi = 256;

      q.subnet = 111;

      _beginthread(AsyncReqsRespThread, 0, &q);

 

      s.lo = 0;

      s.hi = 256;

      s.subnet = 108;

      _beginthread(AsyncReqsRespThread, 0, &s);

 

      while (1)

      {

            Sleep(3000);

            printf("Main sleeping for 3 seconds... \n\n");

      }

 

      deinitialize();

 

      return 0;

}

*************************************************************************************************************************************

 

From: Xiang Li [mailto:[email protected]] 
Sent: Monday, May 16, 2011 1:40 AM
To: Rahul Ravikanth Anneboina
Cc: [email protected]
Subject: Re: Query regarding ASYNC GET calls

 

Hi

On 5/11/2011 6:34 AM, Rahul Ravikanth Anneboina wrote: 

Hi …

 

Need help from you’ll …..

 

I have a piece of code (attached below) that sends out SNMP_MSG_GET requests to an entire subnet.

I am using snmp_async_send() to send out the requests and the responses are read in the callback function asynch_response().

The OID’s correspond to printer details and there are about 10 printers within that subnet.

Every time the callback is triggered with NETSNMP_CALLBACK_OP_TIMED_OUT and all the 255 IP’s time out. Ideally it should get values for those 10 printers and time out the rest of the IPs.

Wireshark packets show that all 256 requests have been sent and responses from the 10 printers have been received.

 

If I break down the IP list to a bunch of 50 at a time, then I’m able to get accurate results. But when I query all 256 at one go, I have this problem.

 

Please point me to where I am going wrong.

 

Assuming there are no problems in your piece of code then I am guessing this behavior might have something 
to do with select() call and FD_SETSIZE (64)  limit  on Windows systems. 

http://net-snmp.sourceforge.net/dev/agent/structnetsnmp__large__fd__set__s.html

You may want to try using    netsnmp_large_fd_set,  snmp_select_info2  etc. and see if that makes any difference.

-- 
Xiang Li
http://www.champnms.com

______________________________________________________________________________
 DISCLAIMER: This electronic message and any attachments to this electronic
 message is intended for the exclusive use of the addressee(s) named herein
 and may contain legally privileged and confidential information. It is the 
 property of Celstream Technologies Pvt Limited. If you are not the intended
 recipient, you are hereby strictly notified not to copy, forward, distribute
 or use this message or any attachments thereto. If you have received this
 message in error, please delete it and all copies thereof, from your system
 and notify the sender at Celstream Technologies or 
 [email protected] immediately.
______________________________________________________________________________

------------------------------------------------------------------------------
Simplify data backup and recovery for your virtual environment with vRanger. 
Installation's a snap, and flexible recovery options mean your data is safe,
secure and there when you need it. Data protection magic?
Nope - It's vRanger. Get your free trial download today. 
http://p.sf.net/sfu/quest-sfdev2dev

_______________________________________________
Net-snmp-users mailing list
[email protected]
Please see the following page to unsubscribe or change other options:
https://lists.sourceforge.net/lists/listinfo/net-snmp-users
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.