[Can you please *NOT* send messages to both mailing lists.
It just adds to the support load unnecessarily. I usually
delete such messages without responding. I'm making an
exception this time because of the subject matter.]
On Thu, 2006-02-02 at 21:31 +0200, Makavy, Erez (Erez) wrote:
> Questions 1
> ------------------
> Is there a multi-thread problem with using send_v2trap() in the main
> process, while the agent_check_and_process() thread is running?
> (I guess the answer is that there is a problem, because both threads
> require the same socket for sending agentX PDUs.)
There is certainly a problem with heavily loaded master/subagent
communication running into deadlock. As with many run-time problems,
the underlying causes are subtle and difficult to pin down.
> Proposed solution
> ---------------------------
> - Open a session over Unix Domain socket (so that the
> agent_check_and_process() will listen on it)
> - my main process will write the trap parameters to that socket.
> - In the callback funciton of that session, instead of parsing an
> agentX PDU,
> I'll read the parameters from the socket, and invoke send_v2Trap().
That sounds vaguely similar to an idea I've been toying with for
some time. Namely, registering *two* AgentX sessions, using
one for "agent-initiated" communication (traps and pings), and
the other for "master-initiated" communication (SNMP requests).
I'm appending a simple patch intended as a provisional implementation
of such an approach. It's by far from complete, but I'd be
interested in hearing how well it works for you?
Dave
--- snmp_agent.c.orig Fri Oct 15 11:08:55 2004
+++ snmp_agent.c Fri Oct 15 11:24:49 2004
@@ -404,9 +404,9 @@
{
int i, n = 0, r = 0;
int repeats = asp->pdu->errindex;
- int j;
+ int j, k;
int all_eoMib;
- netsnmp_variable_list *prev = NULL;
+ netsnmp_variable_list *prev = NULL, *curr;
if (asp->vbcount == 0) /* Nothing to do! */
return;
@@ -424,35 +424,48 @@
if (r == 0)
return;
- /*
- * For each of the original repeating varbinds (except the last),
- * go through the block of results for that varbind,
- * and link each instance to the corresponding instance
- * in the next block.
- */
- for (i = 0; i < r - 1; i++) {
+ /* Fix endOfMibView entries. */
+ for (i = 0; i < r; i++) {
prev = NULL;
for (j = 0; j < repeats; j++) {
+ curr = asp->bulkcache[i * repeats + j];
/*
* If we don't have a valid name for a given repetition
* (and probably for all the ones that follow as well),
- * extend the previous result to indicate 'endOfMibView'
+ * extend the previous result to indicate 'endOfMibView'.
+ * Or if the repetition already has type endOfMibView make
+ * sure it has the correct objid (i.e. that of the previous
+ * entry or that of the original request).
*/
- if (asp->bulkcache[i * repeats + j]->name_length == 0
- && prev) {
- snmp_set_var_objid(
- asp->bulkcache[i * repeats + j],
- prev->name, prev->name_length);
- snmp_set_var_typed_value(
- asp->bulkcache[i * repeats + j],
- SNMP_ENDOFMIBVIEW, NULL, 0);
+ if (curr->name_length == 0 || curr->type == SNMP_ENDOFMIBVIEW) {
+ if (prev == NULL) {
+ /* Use objid from original pdu. */
+ prev = asp->orig_pdu->variables;
+ for (k = i; prev && k > 0; k--)
+ prev = prev->next_variable;
+ }
+ if (prev) {
+ snmp_set_var_objid(curr, prev->name, prev->name_length);
+ snmp_set_var_typed_value(curr, SNMP_ENDOFMIBVIEW, NULL, 0);
+ }
}
- prev = asp->bulkcache[i * repeats + j];
+ prev = curr;
+ }
+ }
+ /*
+ * For each of the original repeating varbinds (except the last),
+ * go through the block of results for that varbind,
+ * and link each instance to the corresponding instance
+ * in the next block.
+ */
+ for (i = 0; i < r - 1; i++) {
+ for (j = 0; j < repeats; j++) {
asp->bulkcache[i * repeats + j]->next_variable =
asp->bulkcache[(i + 1) * repeats + j];
}
}
+
/*
* For the last of the original repeating varbinds,
* go through that block of results, and link each
@@ -461,37 +474,9 @@
* The very last instance of this block is left untouched
* since it (correctly) points to the end of the list.
*/
- if (r > 0) {
- prev = NULL;
- for (j = 0; j < repeats - 1; j++) {
- /*
- * Fill in missing names with 'endOfMibView' as above...
- */
- if (asp->bulkcache[(r - 1) * repeats + j]->name_length == 0
- && prev) {
- snmp_set_var_objid(
- asp->bulkcache[(r - 1) * repeats + j],
- prev->name, prev->name_length);
- snmp_set_var_typed_value(
- asp->bulkcache[(r - 1) * repeats + j],
- SNMP_ENDOFMIBVIEW, NULL, 0);
- }
- prev = asp->bulkcache[(r - 1) * repeats + j];
- asp->bulkcache[(r - 1) * repeats + j]->next_variable =
- asp->bulkcache[j + 1];
- }
- /*
- * ... Not forgetting the very last entry
- */
- if (asp->bulkcache[r * repeats - 1]->name_length == 0
- && prev) {
- snmp_set_var_objid(
- asp->bulkcache[r * repeats - 1],
- prev->name, prev->name_length);
- snmp_set_var_typed_value(
- asp->bulkcache[r * repeats - 1],
- SNMP_ENDOFMIBVIEW, NULL, 0);
- }
+ for (j = 0; j < repeats - 1; j++) {
+ asp->bulkcache[(r - 1) * repeats + j]->next_variable =
+ asp->bulkcache[j + 1];
}
/*
@@ -532,6 +517,27 @@
}
+/* EndOfMibView replies to a GETNEXT request should according to RFC3416
+ * have the object ID set to that of the request. Our tree search
+ * algorithm will sometimes break that requirement. This function will
+ * fix that.
+ */
+NETSNMP_STATIC_INLINE void
+_fix_endofmibview(netsnmp_agent_session *asp)
+{
+ netsnmp_variable_list *vb, *ovb;
+
+ if (asp->vbcount == 0) /* Nothing to do! */
+ return;
+
+ for (vb = asp->pdu->variables, ovb = asp->orig_pdu->variables;
+ vb && ovb; vb = vb->next_variable, ovb = ovb->next_variable) {
+ if (vb->type == SNMP_ENDOFMIBVIEW)
+ snmp_set_var_objid(vb, ovb->name, ovb->name_length);
+ }
+}
+
+
int
getNextSessID()
{
@@ -1499,6 +1505,10 @@
* some stuff needs to be saved in special subagent cases
*/
save_set_cache(asp);
+ break;
+
+ case SNMP_MSG_GETNEXT:
+ _fix_endofmibview(asp);
break;
case SNMP_MSG_GETBULK: