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